Thread: [cedet-semantic] bug fixes and inline completion 'improvements'
Brought to you by:
zappo
From: Pete B. <elb...@ms...> - 2011-06-26 21:01:24
|
hi. here is a set of patches for several bugs and some improvements to the inline completion mechanism. i worked almost exclusively around the base elisp code of '(setq po (poin', and note that below, the character # is supposed to represent the current point position. each bug's diff is incremental, allowing for individual commits (top one first!) which is probably what you want. alternatively, beyond the last commentary is a complete recursive diff set, but note that this includes all other improvements too. ### #1. bug #1: Bug Showing Completions: (wrong-type-argument consp nil) #recipe $ (setq po (point-m# wait for idle completion BUG! #location semantic-displayor-show-request semantic-complete.el:1634 (bzr8071) #commentary an off-by-one error only hit when there are the same number of matches as max-tags (set at 5). a corner case really as the code isn't hit for <5 due to line 1605 '(< ll (oref obj max-tags))' ..and with >6 matches the problem is masked (though the user sees 6 completions as opposed to the max 5!) #patch --- cedet/semantic/semantic-complete.el.orig 2011-06-25 17:40:27.000000000 +0100 +++ cedet/semantic/semantic-complete.el 2011-06-25 17:44:34.000000000 +0100 @@ -1631,7 +1631,7 @@ (oset obj typing-count (1+ typing-count))) ;; At this point, we know we have too many items. ;; Lets be brave, and truncate l - (setcdr (nthcdr (oref obj max-tags) l) nil) + (setcdr (nthcdr (1- (oref obj max-tags)) l) nil) (setq msg (mapconcat 'identity l "\n")) (cond ((= force-show -1) ### ### #2. bug #2: Bug Showing Completions: (wrong-type-argument number-or-marker-p (+ -90)) #recipe move the frame to the left so that it is partially off the screen $ (setq po (poin# wait for idle completion BUG! #location semantic-displayor-point-position semantic-complete.el:1659 (bzr8071) #commentary frame position parameters can also be specified as a cons cell with a car of + or - and a cdr giving the position relative to the left/top (+) or right/bottom (-) position of the screen. emacs returns such a construct when part of the frame lies off the edge of the screen. the diff below fixes it, but will no doubt be incorrect for cases where someone has bizarrely decided to setup their left frame parameter with respect to right hand side of the screen. there's a better implementation of this fix in the re-write / improvements section, but i still choose not to implement correctly for such occurrences. #patch --- cedet/semantic/semantic-complete1.el 2011-06-25 18:11:01.000000000 +0100 +++ cedet/semantic/semantic-complete.el 2011-06-25 18:11:24.000000000 +0100 @@ -1656,8 +1656,8 @@ "Return the location of POINT as positioned on the selected frame. Return a cons cell (X . Y)" (let* ((frame (selected-frame)) - (left (frame-parameter frame 'left)) - (top (frame-parameter frame 'top)) + (left (or (car-safe (cdr-safe (frame-parameter frame 'left))) (frame- parameter frame 'left))) + (top (or (car-safe (cdr-safe (frame-parameter frame 'top))) (frame- parameter frame 'top))) (point-pix-pos (posn-x-y (posn-at-point))) (edges (window-inside-pixel-edges (selected-window)))) (cons (+ (car point-pix-pos) (car edges) left) ### ### #3. bug #3: tooltip disappears immediately #recipe place the mouse cursor in the region that the tooltip will be displayed in #location semantic-displayor-tooltip-show semantic-complete.el:1659 (bzr8071) #commentary this is a 'bug' / 'feature' in the low-level C 'x-show-tip' function ..i won't be looking in there any time soon. the patch below is a work around which simply warps the mouse pointer out of the way. i pushed the obtaining of the actual mouse point to 'semantic-displayor-point-position' as the frame parameter parsing was already done there. rather annoyingly, 'mouse-pixel-position' and 'set-mouse-pixel-position' are only compatible by a frame X Y shift, making the code below look messier than it ought to have been. #patch diff -u cedet/semantic/semantic-complete2.el cedet/semantic/semantic-complete.el --- cedet/semantic/semantic-complete2.el 2011-06-26 11:38:06.000000000 +0100 +++ cedet/semantic/semantic-complete.el 2011-06-26 11:47:34.000000000 +0100 @@ -1652,29 +1652,61 @@ 'window-edges) )) -(defun semantic-displayor-point-position () - "Return the location of POINT as positioned on the selected frame. -Return a cons cell (X . Y)" - (let* ((frame (selected-frame)) - (left (or (car-safe (cdr-safe (frame-parameter frame 'left))) (frame- parameter frame 'left))) - (top (or (car-safe (cdr-safe (frame-parameter frame 'top))) (frame- parameter frame 'top))) - (point-pix-pos (posn-x-y (posn-at-point))) - (edges (window-inside-pixel-edges (selected-window)))) - (cons (+ (car point-pix-pos) (car edges) left) - (+ (cdr point-pix-pos) (cadr edges) top)))) - - +(defun semantic-displayor-point-position (&optional mouse frame-rel) + "Return the location of the POINT or optionally the MOUSE-cursor as positioned on +the selected frame (or nil otherwise). Setting FRAME-REL non-nil produces results +relative to the top-left (X Y) of the selected frame, Return a cons cell (X . Y)" + (let ((fleft 0) (ftop 0)) + (if (not frame-rel) ;;add frame offsets + (let* ((frame (selected-frame)) + (lpos (frame-parameter frame 'left)) + (tpos (frame-parameter frame 'top))) +; (setq fleft (or (car-safe (cdr-safe (frame-parameter frame 'left))) (frame-parameter frame 'left))) + (setq fleft (cond ((eq (type-of lpos) 'integer) lpos) + ((eq (car lpos) '+) (cadr lpos)) + (t (error "unexpected position in frame- parameter 'left: %s" lpos)))) +; (setq ftop (or (car-safe (cdr-safe (frame-parameter frame 'top))) (frame-parameter frame 'top))) + (setq ftop (cond ((eq (type-of tpos) 'integer) tpos) + ((eq (car tpos) '+) (cadr tpos)) + (t (error "unexpected position in frame- parameter 'top: %s" tpos)))))) + (cond (mouse (if (cddr (mouse-pixel-position)) + (cons (+ (nth 1 (mouse-pixel-position)) fleft) + (+ (nthcdr 2 (mouse-pixel-position)) ftop)))) + (t (let* ((point-pix-pos (posn-x-y (posn-at-point))) + (edges (window-inside-pixel-edges (selected-window)))) + (cons (+ (car point-pix-pos) (car edges) fleft) + (+ (cdr point-pix-pos) (cadr edges) ftop))))))) + (defun semantic-displayor-tooltip-show (text) "Display a tooltip with TEXT near cursor." - (let ((point-pix-pos (semantic-displayor-point-position)) - (tooltip-frame-parameters - (append tooltip-frame-parameters nil))) - (push - (cons 'left (+ (car point-pix-pos) (frame-char-width))) - tooltip-frame-parameters) - (push - (cons 'top (+ (cdr point-pix-pos) (frame-char-height))) - tooltip-frame-parameters) + (let* ((point-pix-pos (semantic-displayor-point-position)) + (point-pix-pos-mouse (semantic-displayor-point-position t)) + (point-pix-pos-mouse-frame-rel (semantic-displayor-point-position t t)) + (tooltip-frame-parameters (append tooltip-frame-parameters nil)) + (tooltip-left (+ (car point-pix-pos) (frame-char-width))) + (tooltip-top (+ (cdr point-pix-pos) (frame-char-height))) + (mouse-left (car-safe point-pix-pos-mouse)) + (mouse-top (cdr-safe point-pix-pos-mouse)) + lines (width 0) (height 0)) + ;;setup tooltip + (push (cons 'left tooltip-left) tooltip-frame-parameters) + (push (cons 'top tooltip-top) tooltip-frame-parameters) + ;;if possible ensure mouse pointer is out of the way or the tooltip will immediately disappear + (setq lines (split-string text "\n")) + (mapc '(lambda (line) (setq width (max width (length line)))) lines) + (setq width (* (frame-char-width) width)) + (setq height (* (frame-char-height) (length lines))) + (if (and point-pix-pos-mouse + (>= mouse-left (- tooltip-left (frame-char-width))) + (<= mouse-left (+ tooltip-left width (frame-char-width))) + (>= mouse-top (- tooltip-top (* 6 (frame-char-height)))) + (<= mouse-top (+ (- tooltip-top (* 6 (frame-char-height))) height))) + ;;mouse cursor is in the frame, in the tooltip space (allowing + ;;for the five entries above and a character sized border) + (set-mouse-pixel-position (car (mouse-pixel-position)) + (- (car point-pix-pos-mouse-frame-rel) (- mouse-left (car point-pix-pos)) (frame-char-width)) + (cdr point-pix-pos-mouse-frame-rel))) + ;;show text (tooltip-show text))) (defmethod semantic-displayor-scroll-request ((obj semantic-displayor-tooltip)) ### ### #4. bug #4 use last completions when new prefix is subset of old prefix #recipe no test cases #location semantic-collector-calculate-completions semantic-complete.el:989 (bzr8071) #commentary the term subset is ambiguous in this code, but there is a comment 'New prefix is subset of old prefix' which means the implementation was wrong and the subset cases would never be hit. regardless, this appears to have little effect, as the choice is between use of the last completions '(oref obj last-all-completions)' ..or the cache '(semantic-collector-get-cache obj)' so there's only a little processing difference in it. #patch --- cedet/semantic/semantic-complete3.el 2011-06-26 00:48:25.000000000 +0100 +++ cedet/semantic/semantic-complete.el 2011-06-26 00:50:34.000000000 +0100 @@ -986,7 +986,7 @@ (if (or same-prefix-p (and (slot-boundp obj 'last-prefix) (eq (compare-strings (oref obj last-prefix) 0 nil - prefix 0 (length prefix)) + prefix 0 (length (oref obj last- prefix))) t))) ;; New prefix is subset of old prefix (oref obj last-all-completions) ### ### #5. 'bug' #5 don't complete if there's no context #recipe apply idle patch set verbose mode -> (setq semantic-idle-scheduler-verbose-flag t) *@#k ..cannot reproduce #location semantic-complete-analyze-inline-idle semantic-complete.el:2145 (bzr8071) #commentary a (in)valid overlay ..and no context?! how did i get here? probably just ignore this as it 'should' be impossible, although i suppose it can't hurt to add it given that i don't think i was far enough into my hacking session to have tampered with anything that would obviously leave the engine in an unrecoverable state (i.e. quiting the debugger so the clean-up hooks don't run). i patched 'semantic-complete-analyze-idle' assuming a similar issue could arise from the mini-buffer. also note that this error was only evident having patched semantic-idle.el to not simply ignore problems (which i think should stand going forward!) #patch diff -u cedet/semantic/semantic-idle.el cedet/semantic/semantic-idle.el --- cedet/semantic/semantic-idle.el.orig 2011-06-25 18:28:32.000000000 +0100 +++ cedet/semantic/semantic-idle.el 2011-06-25 23:43:11.000000000 +0100 @@ -965,13 +965,13 @@ ;; This mode can be fragile. Ignore problems. ;; If something doesn't do what you expect, run ;; the below command by hand instead. - (condition-case nil + (condition-case err (semanticdb-without-unloaded-file-searches ;; Use idle version. - (semantic-complete-analyze-inline-idle) - ) - (error nil)) - )) + (semantic-complete-analyze-inline-idle)) + (error + (if semantic-idle-scheduler-verbose-flag + (message " %s" (error-message-string err))))))) ### diff -u cedet/semantic/semantic-complete4.el cedet/semantic/semantic-complete.el --- cedet/semantic/semantic-complete4.el 2011-06-26 11:53:23.000000000 +0100 +++ cedet/semantic/semantic-complete.el 2011-06-26 11:53:36.000000000 +0100 @@ -2007,7 +2007,8 @@ See `semantic-complete-inline-tag-engine' for details on how completion works." (if (not context) (setq context (semantic-analyze-current-context (point)))) - (if (not context) (error "Nothing to complete on here")) + (if (not context) + (if semantic-idle-scheduler-verbose-flag (message " Nothing to complete on here"))) (let* ((collector (semantic-collector-analyze-completions "inline" :buffer (oref context buffer) @@ -2152,7 +2153,8 @@ how completion options are displayed." (interactive) ;; Only do this if we are not already completing something. - (if (not (semantic-completion-inline-active-p)) + (if (and (not (semantic-completion-inline-active-p)) + (semantic-analyze-current-context (point))) (semantic-complete-inline-analyzer (semantic-analyze-current-context (point)))) ;; Report a message if things didn't startup. @@ -2174,7 +2176,8 @@ to change how completion options are displayed." (interactive) ;; Only do this if we are not already completing something. - (if (not (semantic-completion-inline-active-p)) + (if (and (not (semantic-completion-inline-active-p)) + (semantic-analyze-current-context (point))) (semantic-complete-inline-analyzer-idle (semantic-analyze-current-context (point)))) ;; Report a message if things didn't startup. ### #### #6. misc typo patches.. diff -u cedet/semantic/semantic-idle1.el cedet/semantic/semantic-idle.el --- cedet/semantic/semantic-idle1.el 2011-06-26 01:21:44.000000000 +0100 +++ cedet/semantic/semantic-idle.el 2011-06-26 01:26:02.000000000 +0100 @@ -275,7 +275,7 @@ ;; services. Stop on keypress. ;; NOTE ON COMMENTED SAFE HERE - ;; We used to not execute the services if the buffer wsa + ;; We used to not execute the services if the buffer was ;; unparseable. We now assume that they are lexically ;; safe to do, because we have marked the buffer unparseable ;; if there was a problem. @@ -284,11 +284,11 @@ (save-excursion (semantic-throw-on-input 'idle-queue) (when semantic-idle-scheduler-verbose-flag - (working-temp-message "IDLE: execture service %s..." service)) + (working-temp-message "IDLE: execute service %s..." service)) (semantic-safe (format "Idle Service Error %s: %%S" service) (funcall service)) (when semantic-idle-scheduler-verbose-flag - (working-temp-message "IDLE: execture service %s...done" service)) + (working-temp-message "IDLE: executre service %s...done" service)) ))) ;;) ;; Finally loop over remaining buffers, trying to update them as ### ### --- cedet/semantic/semantic-complete5.el 2011-06-26 00:51:33.000000000 +0100 +++ cedet/semantic/semantic-complete.el 2011-06-26 01:36:56.000000000 +0100 @@ -705,8 +705,7 @@ ;;(message "Exit: %S %S %S" s e (point)) (semantic-complete-inline-exit) ) - ;; Exit if the user typed in a character that is not part - ;; of the symbol being completed. + ;; Exit if the user typed an invalid symbol character. ((and (setq txt (semantic-completion-text)) (not (string= txt "")) (and (/= (point) s) @@ -926,7 +925,7 @@ (defmethod semantic-collector-next-action ((obj semantic-collector-abstract) partial) - "What should we do next? OBJ can predict a next good action. + "What should we do next? OBJ can be used to determine the next action. PARTIAL indicates if we are doing a partial completion." (if (and (slot-boundp obj 'last-completion) (string= (semantic-completion-text) (oref obj last-completion))) @@ -1039,7 +1038,7 @@ (defmethod semantic-collector-try-completion-whitespace ((obj semantic-collector-abstract) prefix) - "For OBJ, do whatepsace completion based on PREFIX. + "For OBJ, do whitepsace completion based on PREFIX. This implies that if there are two completions, one matching the test \"preifx\\>\", and one not, the one matching the full word version of PREFIX will be chosen, and that text returned. @@ -1169,7 +1168,7 @@ (semantic-collector-buffer-abstract) () "Completion engine for tags in the current buffer. -When searching for a tag, uses semantic deep searche functions. +When searching for a tag, uses semantic deep search functions. Basics search only in the current buffer.") (defmethod semantic-collector-calculate-cache ### ### #7. improvement #1 collect additional matches when the context/prefix decreases in size #recipe $ (setq po (point-m# wait for idle completion ((point-marker) (point-max) (point-max-marker)) BACKSPACE x5 $ (setq po (po# wait for idle completion ((point-marker) (point-max) (point-max-marker)) :( ..after patches.. ((po-find-charset filename) (po-find-file-coding-system arg-list) (po-find-file-coding-system-guts operation filename) (point .. :) #commentary whereever in a symbol one lets idle completion kick in, the initial search performed is also the last full search performed for the rest of the completion. yes use cache when closing in on a match, but if we change our minds, lets avoid the annoyance of having to cancel the completion and then wait again (RIGHT-ARROW LEFT-ARROW wait!!). i think i found a suitable place to do this - 'semantic-collector-calculate-completions'. it IS the right place in my mind if you consider the function more along the lines of 'look at completion operation state, make cache changes if necessary, then calculate completions on a possibly revised cache'. to force the new cache into the displayor immediately 'semantic-complete-inline-force-display' also had to be modified to except the possibility of a dynamic collector. #patch diff -u cedet/semantic/semantic-complete6.el cedet/semantic/semantic-complete.el --- cedet/semantic/semantic-complete6.el 2011-06-26 12:53:57.000000000 +0100 +++ cedet/semantic/semantic-complete.el 2011-06-26 16:52:12.000000000 +0100 @@ -734,18 +734,23 @@ DO NOT CALL THIS IF THE INLINE COMPLETION ENGINE IS NOT ACTIVE." (condition-case e (save-excursion - (let ((collector semantic-completion-collector-engine) - (displayor semantic-completion-display-engine) - (contents (semantic-completion-text))) - (when collector + (let ((contents (semantic-completion-text))) + (when semantic-completion-collector-engine + ;;update current completions (semantic-collector-calculate-completions - collector contents nil) + semantic-completion-collector-engine contents nil) + ;;update displayor with new completions (semantic-displayor-set-completions - displayor - (semantic-collector-all-completions collector contents) - contents) + semantic-completion-display-engine + (semantic-collector-all-completions + ;;the call to update the current completions may have + ;;updated the collector! + semantic-completion-collector-engine + contents) + contents) ;; Ask the displayor to display them. - (semantic-displayor-show-request displayor)) + (semantic-displayor-show-request + semantic-completion-display-engine)) )) (error (message "Bug Showing Completions: %S" e)))) @@ -981,24 +986,36 @@ "Calculate completions for prefix as setup for other queries." (let* ((case-fold-search semantic-case-fold) (same-prefix-p (semantic-collector-last-prefix= obj prefix)) + (last-prefix (if (slot-boundp obj 'last-prefix) (oref obj last-prefix) nil)) (completionlist - (if (or same-prefix-p - (and (slot-boundp obj 'last-prefix) - (eq (compare-strings (oref obj last-prefix) 0 nil - prefix 0 (length (oref obj last- prefix))) - t))) - ;; New prefix is subset of old prefix - (oref obj last-all-completions) - (semantic-collector-get-cache obj))) + (cond ((or same-prefix-p + (and last-prefix (eq (compare-strings + last-prefix 0 nil + prefix 0 (length last-prefix)) t))) + ;;same prefix. or last-prefix is a substring of the of new prefix in + ;;which case we are refining our symbol so just re-use cache! + (oref obj last-all-completions)) + (t + (if (and last-prefix (> (length prefix) 1) (eq (compare- strings + prefix 0 nil + last-prefix 0 (length prefix)) t)) + ;;new prefix is substring of old prefix. perform a full search to pull + ;;in additional matches. + ;;NOTE: this behaviour is avoided when we have deleted our prefix down + ;;to a single character as the overhead of such a large search is almost + ;;certainly unwanted. + (progn (let ((context (semantic-analyze-current-context (point)))) + (setq semantic-completion-collector-engine + (semantic-collector-analyze-completions + "inline" :buffer (oref context buffer) :context context))) + (setq obj semantic-completion-collector-engine))) + (semantic-collector-get-cache obj)))) ;; Get the result (answer (if same-prefix-p completionlist - (semantic-collector-calculate-completions-raw - obj prefix completionlist)) - ) + (semantic-collector-calculate-completions-raw obj prefix completionlist))) (completion nil) - (complete-not-uniq nil) - ) + (complete-not-uniq nil)) ;;(semanticdb-find-result-test answer) (when (not same-prefix-p) ;; Save results if it is interesting and beneficial ### ### #8. improvement #2 short-circuit 'display action on TAB #recipe $ (setq po (poin# wait for idle completion press TAB 'for more' the same 5 completions return :( #commentary tab is advertised as on any completion where there are additional matches available, yet hitting tab doesn't immediately expand the tooltip to show more matches as expected #patch --- cedet/semantic/semantic-complete7.el 2011-06-26 02:36:10.000000000 +0100 +++ cedet/semantic/semantic-complete.el 2011-06-26 02:43:30.000000000 +0100 @@ -1328,8 +1328,9 @@ (defmethod semantic-displayor-next-action ((obj semantic-displayor-abstract)) "The next action to take on the minibuffer related to display." (if (and (slot-boundp obj 'last-prefix) - (string= (oref obj last-prefix) (semantic-completion-text)) - (eq last-command this-command)) + (or (eq this-command 'semantic-complete-inline-TAB) + (and (string= (oref obj last-prefix) (semantic-completion-text)) + (eq last-command this-command)))) 'scroll 'display)) ### #9. improvement #3 refine displayor modes of operation, make some properties customisable, add 'remaining match' counts to tooltips, reset max-tags count when searching on a shortened prefix #recipe there are too few/many completions displayed initially/after expansion 'M-x customize-apropos <RET> idle <RET>' there are no inline completion 'mode' options :( #commentary i've tried to clean up the current implementation of the 'semantic-displayor-tooltip' class and 'semantic-displayor-show-request' function, exposing some of the parameters available in the tooltip class along the way for additional control over the displaying of completions (namely 'max-tags' and 'mode' (originally 'force-show')). it took some time to understand how the original mechanism was supposed to work (documentation is a little flakey) and i'm sure i was probably biased by my pre-conceptions of 'the way it should work', however, my initial thoughts were: -there are three modes of operation through 'force-show' (-1, 0, or -1) yet not one of these actually suppresses completions! -'force-show' is a pretty misleading variable name, completions are alway s 'shown', it's just a matter of how many. 5, or after several TABs 30. -there seems to be some redundancy between modes 1 and -1, the difference ultimately just '....' (for -1 mode) vs 'TAB for more' (in 1 mode) appended to the end of the completions -there's no way to change the size of the tooltips as such i've made a few refinements.. as far as maximum tag counts go, i added a couple of defcustom variables for an 'initial' max-tags count, and an 'extended' max-tags count. they work well through the 'M-x customize-apropos <RET> idle <RET>' mechanism, however, the custom 'set' functionality which has been used to override the 'x-max-tooltip-size' variable to curtail any clipping by 'x-show-tip' is easily by-passed using a direct 'setq'. i can't imagine this biting too many people however. my 'new' specification for 'modes' is: 'quiet-mode' - suppress all matches until the total number of matches available is less than 'semantic-completion max-tags' number. several tab presses will show an extended completion list, but only until the next non-completion key/command is sent, hence truly staying 'quiet'. 'standard-mode' - always provide up to 'semantic-completion max-tags' number of completions when available by default. single TAB will reveal the extended list of completions up to 'semantic-completion max-tags-extended' number, and this extended list will be shown for the remainder of the completion, unless backspace is keyed which resets the max-tags count back down to 'semantic-completion-max-tags'. 'verbose-mode' - always show the extended completions list. horrible. note the 'setup' area in the 'semantic-displayor-show-request' code is now a good place to influence any of the relevant local and object instance variables should you want to tweak usage, for example, i've set up 'quiet-mode' to default back to the 'standard-mode' here for excessive (> 5 consecutive completion commands. cheers, Pete. #patch diff -u cedet/semantic/semantic-complete8.el cedet/semantic/semantic-complete.el --- cedet/semantic/semantic-complete8.el 2011-06-26 16:56:11.000000000 +0100 +++ cedet/semantic/semantic-complete.el 2011-06-26 18:50:39.000000000 +0100 @@ -130,6 +130,64 @@ ;;; Code: +(defvar semantic-complete-inline-mode 0) + +;;;###autoload +(defcustom semantic-complete-inline-mode-quiet nil + "When enabled, only show completions when we have narrowed all +posibilities down to a maximum of 'semantic-complete-inline-max-tags' +tags. Pressing TAB multiple times will also show completions." + :group 'semantic + :type 'boolean + :set '(lambda (sym var) + (set-default sym var) + (setq semantic-complete-inline-mode-standard nil) + (setq semantic-complete-inline-mode-verbose nil) + (if var (setq semantic-complete-inline-mode -1)))) + +(defcustom semantic-complete-inline-mode-standard t + "When enabled, show only 'semantic-complete-inline-max-tags' number +of completions initially. Pressing TAB will show the extended set." + :group 'semantic + :type 'boolean + :set '(lambda (sym var) + (set-default sym var) + (setq semantic-complete-inline-mode-quiet nil) + (setq semantic-complete-inline-mode-verbose nil) + (if var (setq semantic-complete-inline-mode 0)))) + +(defcustom semantic-complete-inline-mode-verbose nil + "When enabled, always show all completions available for the context." + :group 'semantic + :type 'boolean + :set '(lambda (sym var) + (set-default sym var) + (setq semantic-complete-inline-mode-standard nil) + (setq semantic-complete-inline-mode-quiet nil) + (if var (setq semantic-complete-inline-mode 1)))) + +;;;###autoload +(defcustom semantic-complete-inline-max-tags 5 + "The maximum number of tags to be displayed for an initial inline +completion, or at all in the case of 'semantic-complete-inline-show-always' +being in its conservative mode (i.e. nil)" + :group 'semantic + :type 'integer) + +;;;###autoload +(defcustom semantic-complete-inline-max-tags-extended 25 + "The maximum number of tags to be displayed for an inline +completion where we have activated the extended completion list through +typing TAB or SPACE multiple times. This limit needs to fit on your +screen! +NOTE: this variable in turn increases 'x-max-tooltip-size' to force +over-sized tooltips if necessary, these changes are one way only." + :group 'semantic + :type 'integer + :set '(lambda (sym var) + (set-default sym var) + (setcdr x-max-tooltip-size (max (1+ var) (cdr x-max-tooltip- size))))) + ;;; Compatibility ;; (if (fboundp 'minibuffer-contents) @@ -713,17 +771,19 @@ (forward-char -1) (not (looking-at "\\(\\w\\|\\s_\\)"))))) ;;(message "Non symbol character.") - (semantic-complete-inline-exit)) + (semantic-complete-inline-exit)) + ;; If the last command was one of our completion commands, + ;; then do nothing. ((lookup-key semantic-complete-inline-map - (this-command-keys) nil) - ;; If the last command was one of our completion commands, - ;; then do nothing. - nil - ) + (this-command-keys) nil) + nil) (t - ;; Else, show completions now - (semantic-complete-inline-force-display) - + (if (eq this-command 'backward-delete-char-untabify) + ;; reset max tags + (when semantic-completion-display-engine + (oset semantic-completion-display-engine max-tags + semantic-complete-inline-max-tags))) + (semantic-complete-inline-force-display) )))) ;; If something goes terribly wrong, clean up after ourselves. (error (semantic-complete-inline-exit)))) @@ -1560,31 +1620,35 @@ ;; * Don't use 'avoid package for tooltip positioning. (defclass semantic-displayor-tooltip (semantic-displayor-traditional) - ((max-tags :type integer + ((mode :type integer + :initarg :mode + :initform (symbol-value 'semantic-complete-inline-mode) + :custom (choice (const + :tag "Quiet mode. Show matches only if the total +number of matches available is less than `max-tags'." + -1) + (const + :tag "Standard mode. Show only a few matches initially, +pressing TAB to see the extended set (if applicable) when required." + 0) + (const + :tag "Verbose mode. Show the extended set of matches, +always!" + 1)) + :documentation + "Control the behavior of the number of matches displayed in the +tooltip. +-1 is 'quiet-mode', showing matches only if the total number of matches available +is less than `max-tags'. +0 is 'standard-mode', showing only a few matches initially, the user hitting TAB to +see the extended set (if applicable) when required. +1 is 'verbose-mode', showing the extended set of matches, always") + (max-tags :type integer :initarg :max-tags - :initform 5 + :initform (symbol-value 'semantic-complete-inline-max-tags) :custom integer :documentation - "Max number of tags displayed on tooltip at once. -If `force-show' is 1, this value is ignored with typing tab or space twice continuously. -if `force-show' is 0, this value is always ignored.") - (force-show :type integer - :initarg :force-show - :initform 1 - :custom (choice (const - :tag "Show when double typing" - 1) - (const - :tag "Show always" - 0) - (const - :tag "Show if the number of tags is less than `max-tags'." - -1)) - :documentation - "Control the behavior of the number of tags is greater than `max-tags'. --1 means tags are never shown. -0 means the tags are always shown. -1 means tags are shown if space or tab is typed twice continuously.") + "Upper bound to number of matches displayed in the tooltip at once.") (typing-count :type integer :initform 0 :documentation @@ -1592,7 +1656,7 @@ (shown :type boolean :initform nil :documentation - "Flag representing whether tags is shown once or not.") + "Flag representing whether tooltip has been shown yet.") ) "Display completions options in a tooltip. Display mechanism using tooltip for a list of possible completions.") @@ -1611,51 +1675,62 @@ ;; a traditional completion buffer. (call-next-method) (let* ((tablelong (semanticdb-strip-find-results (oref obj table))) - (table (semantic-unique-tag-table-by-name tablelong)) - (l (mapcar semantic-completion-displayor-format-tag-function table)) - (ll (length l)) - (typing-count (oref obj typing-count)) - (force-show (oref obj force-show)) - (matchtxt (semantic-completion-text)) - msg) - (if (or (oref obj shown) - (< ll (oref obj max-tags)) - (and (<= 0 force-show) - (< (1- force-show) typing-count))) + (table (semantic-unique-tag-table-by-name tablelong)) + (completions (mapcar semantic-completion-displayor-format-tag- function table)) + (l (length completions)) + (mode (oref obj mode)) + (max-tags (oref obj max-tags)) + (matchtxt (semantic-completion-text)) + msg msg-tail) + ;; keep a count of the consecutive completion commands entered by the user + (if (and (stringp (this-command-keys)) (string= (this-command-keys) "\C- i")) + (oset obj typing-count (1+ (oref obj typing-count))) + (oset obj typing-count 0)) + ;; setup + (cond ((eq mode 0) ;; 'standard-mode' + ;; no special setup + ) + ((eq mode -1) ;; 'quiet-mode' + ;; the typing count determines whether the user wants to override the quiet + ;; mode and show completions and is dealt with below. very angry people get + ;; switched back to standard mode. + (if (>= (oref obj typing-count) 5) + (progn (oset obj mode 0) (setq mode 0) + (message "resetting inline-mode to 'standard-mode'")))) + ((eq mode 1) ;; 'verbose-mode' + ;; always show extended match set + (oset obj max-tags semantic-complete-inline-max-tags-extended) + (setq max-tags semantic-complete-inline-max-tags-extended))) + ;; completion string + (if (and (= mode -1) (> l semantic-complete-inline-max-tags) (< (oref obj typing-count) 2)) + (setq msg "....") ;; just discretely hint at completion availability (progn - (oset obj typing-count 0) - (oset obj shown t) - (if (eq 1 ll) - ;; We Have only one possible match. There could be two cases. - ;; 1) input text != single match. - ;; --> Show it! - ;; 2) input text == single match. - ;; --> Complain about it, but still show the match. - (if (string= matchtxt (semantic-tag-name (car table))) - (setq msg (concat "[COMPLETE]\n" (car l))) - (setq msg (car l))) - ;; Create the long message. - (setq msg (mapconcat 'identity l "\n")) - ;; If there is nothing, say so! - (if (eq 0 (length msg)) - (setq msg "[NO MATCH]"))) - (semantic-displayor-tooltip-show msg)) - ;; The typing count determines if the user REALLY REALLY - ;; wanted to show that much stuff. Only increment - ;; if the current command is a completion command. - (if (and (stringp (this-command-keys)) - (string= (this-command-keys) "\C-i")) - (oset obj typing-count (1+ typing-count))) - ;; At this point, we know we have too many items. - ;; Lets be brave, and truncate l - (setcdr (nthcdr (1- (oref obj max-tags)) l) nil) - (setq msg (mapconcat 'identity l "\n")) - (cond - ((= force-show -1) - (semantic-displayor-tooltip-show (concat msg "\n..."))) - ((= force-show 1) - (semantic-displayor-tooltip-show (concat msg "\n(TAB for more)"))) - ))))) + (oset obj shown t) + (cond ((> l max-tags) + ;; we have too many items, be brave and truncate 'completions' + (setcdr (nthcdr (1- max-tags) completions) nil) + (cond ((= max-tags semantic-complete-inline-max-tags) + (setq msg-tail (concat "\n[<TAB> " (number-to- string (- l max-tags)) " more]"))) + (t (setq msg-tail (concat "\n[<n/a> " (number-to- string (- l max-tags)) " more]")) + (if (>= (oref obj typing-count) 2) + (message "refine search to display results beyond the '%s' limit" + (symbol-name 'semantic-complete- inline-max-tags-extended)))))) + ((= l 1) + ;; two possible cases + ;; 1. input text != single match - we found a unique completion! + ;; 2. input text == single match - we found no additional matches, it's just the input text! + (if (string= matchtxt (semantic-tag-name (car table))) + (setq msg "[COMPLETE]\n"))) + ((eq l 0) + (oset obj shown nil) + ;; no matches, say so if in verbose mode! + (if semantic-idle-scheduler-verbose-flag (setq msg "[NO MATCH]")))) + ;; create the tooltip text + (setq msg (concat msg (mapconcat 'identity completions "\n"))))) + ;; add any tail info + (setq msg (concat msg msg-tail)) + ;; display tooltip + (if (not (eq msg "")) (semantic-displayor-tooltip-show msg))))) ;;; Compatibility ;; @@ -1729,7 +1804,7 @@ (defmethod semantic-displayor-scroll-request ((obj semantic-displayor-tooltip)) "A request to for the displayor to scroll the completion list (if needed)." ;; Do scrolling in the tooltip. - (oset obj max-tags 30) + (oset obj max-tags semantic-complete-inline-max-tags-extended) (semantic-displayor-show-request obj) ) ### ############################################################################### ### #10. full recursive diff patch set diff -ur cdt2/semantic/semantic-complete.el cdt/semantic/semantic-complete.el --- cedet.orig/semantic/semantic-complete.el 2011-06-26 13:17:26.000000000 +0100 +++ cedet/semantic/semantic-complete.el 2011-06-26 16:59:55.000000000 +0100 @@ -130,6 +130,64 @@ ;;; Code: +(defvar semantic-complete-inline-mode 0) + +;;;###autoload +(defcustom semantic-complete-inline-mode-quiet nil + "When enabled, only show completions when we have narrowed all +posibilities down to a maximum of 'semantic-complete-inline-max-tags' +tags. Pressing TAB multiple times will also show completions." + :group 'semantic + :type 'boolean + :set '(lambda (sym var) + (set-default sym var) + (setq semantic-complete-inline-mode-standard nil) + (setq semantic-complete-inline-mode-verbose nil) + (if var (setq semantic-complete-inline-mode -1)))) + +(defcustom semantic-complete-inline-mode-standard t + "When enabled, show only 'semantic-complete-inline-max-tags' number +of completions initially. Pressing TAB will show the extended set." + :group 'semantic + :type 'boolean + :set '(lambda (sym var) + (set-default sym var) + (setq semantic-complete-inline-mode-quiet nil) + (setq semantic-complete-inline-mode-verbose nil) + (if var (setq semantic-complete-inline-mode 0)))) + +(defcustom semantic-complete-inline-mode-verbose nil + "When enabled, always show all completions available for the context." + :group 'semantic + :type 'boolean + :set '(lambda (sym var) + (set-default sym var) + (setq semantic-complete-inline-mode-standard nil) + (setq semantic-complete-inline-mode-quiet nil) + (if var (setq semantic-complete-inline-mode 1)))) + +;;;###autoload +(defcustom semantic-complete-inline-max-tags 5 + "The maximum number of tags to be displayed for an initial inline +completion, or at all in the case of 'semantic-complete-inline-show-always' +being in its conservative mode (i.e. nil)" + :group 'semantic + :type 'integer) + +;;;###autoload +(defcustom semantic-complete-inline-max-tags-extended 25 + "The maximum number of tags to be displayed for an inline +completion where we have activated the extended completion list through +typing TAB or SPACE multiple times. This limit needs to fit on your +screen! +NOTE: this variable in turn increases 'x-max-tooltip-size' to force +over-sized tooltips if necessary, these changes are one way only." + :group 'semantic + :type 'integer + :set '(lambda (sym var) + (set-default sym var) + (setcdr x-max-tooltip-size (max (1+ var) (cdr x-max-tooltip- size))))) + ;;; Compatibility ;; (if (fboundp 'minibuffer-contents) @@ -705,8 +763,7 @@ ;;(message "Exit: %S %S %S" s e (point)) (semantic-complete-inline-exit) ) - ;; Exit if the user typed in a character that is not part - ;; of the symbol being completed. + ;; Exit if the user typed an invalid symbol character. ((and (setq txt (semantic-completion-text)) (not (string= txt "")) (and (/= (point) s) @@ -714,17 +771,19 @@ (forward-char -1) (not (looking-at "\\(\\w\\|\\s_\\)"))))) ;;(message "Non symbol character.") - (semantic-complete-inline-exit)) + (semantic-complete-inline-exit)) + ;; If the last command was one of our completion commands, + ;; then do nothing. ((lookup-key semantic-complete-inline-map - (this-command-keys) nil) - ;; If the last command was one of our completion commands, - ;; then do nothing. - nil - ) + (this-command-keys) nil) + nil) (t - ;; Else, show completions now - (semantic-complete-inline-force-display) - + (if (eq this-command 'backward-delete-char-untabify) + ;; reset max tags + (when semantic-completion-display-engine + (oset semantic-completion-display-engine max-tags + semantic-complete-inline-max-tags))) + (semantic-complete-inline-force-display) )))) ;; If something goes terribly wrong, clean up after ourselves. (error (semantic-complete-inline-exit)))) @@ -735,18 +794,23 @@ DO NOT CALL THIS IF THE INLINE COMPLETION ENGINE IS NOT ACTIVE." (condition-case e (save-excursion - (let ((collector semantic-completion-collector-engine) - (displayor semantic-completion-display-engine) - (contents (semantic-completion-text))) - (when collector + (let ((contents (semantic-completion-text))) + (when semantic-completion-collector-engine + ;;update current completions (semantic-collector-calculate-completions - collector contents nil) + semantic-completion-collector-engine contents nil) + ;;update displayor with new completions (semantic-displayor-set-completions - displayor - (semantic-collector-all-completions collector contents) - contents) + semantic-completion-display-engine + (semantic-collector-all-completions + ;;the call to update the current completions may have + ;;updated the collector! + semantic-completion-collector-engine + contents) + contents) ;; Ask the displayor to display them. - (semantic-displayor-show-request displayor)) + (semantic-displayor-show-request + semantic-completion-display-engine)) )) (error (message "Bug Showing Completions: %S" e)))) @@ -926,7 +990,7 @@ (defmethod semantic-collector-next-action ((obj semantic-collector-abstract) partial) - "What should we do next? OBJ can predict a next good action. + "What should we do next? OBJ can be used to determine the next action. PARTIAL indicates if we are doing a partial completion." (if (and (slot-boundp obj 'last-completion) (string= (semantic-completion-text) (oref obj last-completion))) @@ -982,24 +1046,36 @@ "Calculate completions for prefix as setup for other queries." (let* ((case-fold-search semantic-case-fold) (same-prefix-p (semantic-collector-last-prefix= obj prefix)) + (last-prefix (if (slot-boundp obj 'last-prefix) (oref obj last-prefix) nil)) (completionlist - (if (or same-prefix-p - (and (slot-boundp obj 'last-prefix) - (eq (compare-strings (oref obj last-prefix) 0 nil - prefix 0 (length prefix)) - t))) - ;; New prefix is subset of old prefix - (oref obj last-all-completions) - (semantic-collector-get-cache obj))) + (cond ((or same-prefix-p + (and last-prefix (eq (compare-strings + last-prefix 0 nil + prefix 0 (length last-prefix)) t))) + ;;same prefix. or last-prefix is a substring of the of new prefix in + ;;which case we are refining our symbol so just re-use cache! + (oref obj last-all-completions)) + (t + (if (and last-prefix (> (length prefix) 1) (eq (compare- strings + prefix 0 nil + last-prefix 0 (length prefix)) t)) + ;;new prefix is substring of old prefix. perform a full search to pull + ;;in additional matches. + ;;NOTE: this behaviour is avoided when we have deleted our prefix down + ;;to a single character as the overhead of such a large search is almost + ;;certainly unwanted. + (progn (let ((context (semantic-analyze-current-context (point)))) + (setq semantic-completion-collector-engine + (semantic-collector-analyze-completions + "inline" :buffer (oref context buffer) :context context))) + (setq obj semantic-completion-collector-engine))) + (semantic-collector-get-cache obj)))) ;; Get the result (answer (if same-prefix-p completionlist - (semantic-collector-calculate-completions-raw - obj prefix completionlist)) - ) + (semantic-collector-calculate-completions-raw obj prefix completionlist))) (completion nil) - (complete-not-uniq nil) - ) + (complete-not-uniq nil)) ;;(semanticdb-find-result-test answer) (when (not same-prefix-p) ;; Save results if it is interesting and beneficial @@ -1039,7 +1115,7 @@ (defmethod semantic-collector-try-completion-whitespace ((obj semantic-collector-abstract) prefix) - "For OBJ, do whatepsace completion based on PREFIX. + "For OBJ, do whitepsace completion based on PREFIX. This implies that if there are two completions, one matching the test \"preifx\\>\", and one not, the one matching the full word version of PREFIX will be chosen, and that text returned. @@ -1169,7 +1245,7 @@ (semantic-collector-buffer-abstract) () "Completion engine for tags in the current buffer. -When searching for a tag, uses semantic deep searche functions. +When searching for a tag, uses semantic deep search functions. Basics search only in the current buffer.") (defmethod semantic-collector-calculate-cache @@ -1312,8 +1388,9 @@ (defmethod semantic-displayor-next-action ((obj semantic-displayor-abstract)) "The next action to take on the minibuffer related to display." (if (and (slot-boundp obj 'last-prefix) - (string= (oref obj last-prefix) (semantic-completion-text)) - (eq last-command this-command)) + (or (eq this-command 'semantic-complete-inline-TAB) + (and (string= (oref obj last-prefix) (semantic-completion-text)) + (eq last-command this-command)))) 'scroll 'display)) @@ -1543,31 +1620,35 @@ ;; * Don't use 'avoid package for tooltip positioning. (defclass semantic-displayor-tooltip (semantic-displayor-traditional) - ((max-tags :type integer + ((mode :type integer + :initarg :mode + :initform (symbol-value 'semantic-complete-inline-mode) + :custom (choice (const + :tag "Quiet mode. Show matches only if the total +number of matches available is less than `max-tags'." + -1) + (const + :tag "Standard mode. Show only a few matches initially, +pressing TAB to see the extended set (if applicable) when required." + 0) + (const + :tag "Verbose mode. Show the extended set of matches, +always!" + 1)) + :documentation + "Control the behavior of the number of matches displayed in the +tooltip. +-1 is 'quiet-mode', showing matches only if the total number of matches available +is less than `max-tags'. +0 is 'standard-mode', showing only a few matches initially, the user hitting TAB to +see the extended set (if applicable) when required. +1 is 'verbose-mode', showing the extended set of matches, always") + (max-tags :type integer :initarg :max-tags - :initform 5 + :initform (symbol-value 'semantic-complete-inline-max-tags) :custom integer :documentation - "Max number of tags displayed on tooltip at once. -If `force-show' is 1, this value is ignored with typing tab or space twice continuously. -if `force-show' is 0, this value is always ignored.") - (force-show :type integer - :initarg :force-show - :initform 1 - :custom (choice (const - :tag "Show when double typing" - 1) - (const - :tag "Show always" - 0) - (const - :tag "Show if the number of tags is less than `max-tags'." - -1)) - :documentation - "Control the behavior of the number of tags is greater than `max-tags'. --1 means tags are never shown. -0 means the tags are always shown. -1 means tags are shown if space or tab is typed twice continuously.") + "Upper bound to number of matches displayed in the tooltip at once.") (typing-count :type integer :initform 0 :documentation @@ -1575,7 +1656,7 @@ (shown :type boolean :initform nil :documentation - "Flag representing whether tags is shown once or not.") + "Flag representing whether tooltip has been shown yet.") ) "Display completions options in a tooltip. Display mechanism using tooltip for a list of possible completions.") @@ -1594,51 +1675,61 @@ ;; a traditional completion buffer. (call-next-method) (let* ((tablelong (semanticdb-strip-find-results (oref obj table))) - (table (semantic-unique-tag-table-by-name tablelong)) - (l (mapcar semantic-completion-displayor-format-tag-function table)) - (ll (length l)) - (typing-count (oref obj typing-count)) - (force-show (oref obj force-show)) - (matchtxt (semantic-completion-text)) - msg) - (if (or (oref obj shown) - (< ll (oref obj max-tags)) - (and (<= 0 force-show) - (< (1- force-show) typing-count))) - (progn - (oset obj typing-count 0) - (oset obj shown t) - (if (eq 1 ll) - ;; We Have only one possible match. There could be two cases. - ;; 1) input text != single match. - ;; --> Show it! - ;; 2) input text == single match. - ;; --> Complain about it, but still show the match. - (if (string= matchtxt (semantic-tag-name (car table))) - (setq msg (concat "[COMPLETE]\n" (car l))) - (setq msg (car l))) - ;; Create the long message. - (setq msg (mapconcat 'identity l "\n")) - ;; If there is nothing, say so! - (if (eq 0 (length msg)) - (setq msg "[NO MATCH]"))) - (semantic-displayor-tooltip-show msg)) - ;; The typing count determines if the user REALLY REALLY - ;; wanted to show that much stuff. Only increment - ;; if the current command is a completion command. - (if (and (stringp (this-command-keys)) - (string= (this-command-keys) "\C-i")) - (oset obj typing-count (1+ typing-count))) - ;; At this point, we know we have too many items. - ;; Lets be brave, and truncate l - (setcdr (nthcdr (oref obj max-tags) l) nil) - (setq msg (mapconcat 'identity l "\n")) - (cond - ((= force-show -1) - (semantic-displayor-tooltip-show (concat msg "\n..."))) - ((= force-show 1) - (semantic-displayor-tooltip-show (concat msg "\n(TAB for more)"))) - ))))) + (table (semantic-unique-tag-table-by-name tablelong)) + (completions (mapcar semantic-completion-displayor-format-tag- function table)) + (l (length completions)) + (mode (oref obj mode)) + (max-tags (oref obj max-tags)) + (matchtxt (semantic-completion-text)) + msg msg-tail) + ;; keep a count of the consecutive completion commands entered by the user + (if (and (stringp (this-command-keys)) (string= (this-command-keys) "\C- i")) + (oset obj typing-count (1+ (oref obj typing-count))) + (oset obj typing-count 0)) + ;; setup + (cond ((eq mode 0) ;; 'standard-mode' + ;; no special setup + ) + ((eq mode -1) ;; 'quiet-mode' + ;; the typing count determines whether the user wants to override the quiet mode and show + ;; lots of completions. if this tooltip has already been shown, simply use standard mode + ;; for the remainder of this completion 'session' instead. note: we only override the + ;; local 'mode' symbol. + (if (oref obj shown) (setq mode 0))) + ((eq mode 1) ;; 'verbose-mode' + ;; always show extended match set + (oset obj max-tags semantic-complete-inline-max-tags-extended) + (setq max-tags semantic-complete-inline-max-tags-extended))) + ;; completion string + (if (and (= mode -1) (> l max-tags) (< (oref obj typing-count) 2)) + (setq msg "....") ;; just discretely hint at completion availability + (progn + (cond ((> l max-tags) + (oset obj shown t) + ;; we have too many items, be brave and truncate 'completions' + (setcdr (nthcdr (1- max-tags) completions) nil) + (cond ((= max-tags semantic-complete-inline-max-tags) + (setq msg-tail (concat "\n[<TAB> " (number-to- string (- l max-tags)) " more]"))) + (t (setq msg-tail (concat "\n[<n/a> " (number-to- string (- l max-tags)) " more]")) + (if (>= (oref obj typing-count) 2) + (message "refine search to display results beyond the '%s' limit" + (symbol-name 'semantic-complete- inline-max-tags-extended)))))) + ((= l 1) + (oset obj shown t) + ;; two possible cases + ;; 1. input text != single match - we found a unique completion! + ;; 2. input text == single match - we found no additional matches, it's just the input text! + (if (string= matchtxt (semantic-tag-name (car table))) + (setq msg "[COMPLETE]\n"))) + ((eq l 0) + ;; no matches, say so if in verbose mode! + (if semantic-idle-scheduler-verbose-flag (setq msg "[NO MATCH]")))) + ;; create the tooltip text + (setq msg (concat msg (mapconcat 'identity completions "\n"))))) + ;; add any tail info + (setq msg (concat msg msg-tail)) + ;; display tooltip + (if (not (eq msg "")) (semantic-displayor-tooltip-show msg))))) ;;; Compatibility ;; @@ -1652,35 +1743,67 @@ 'window-edges) )) -(defun semantic-displayor-point-position () - "Return the location of POINT as positioned on the selected frame. -Return a cons cell (X . Y)" - (let* ((frame (selected-frame)) - (left (frame-parameter frame 'left)) - (top (frame-parameter frame 'top)) - (point-pix-pos (posn-x-y (posn-at-point))) - (edges (window-inside-pixel-edges (selected-window)))) - (cons (+ (car point-pix-pos) (car edges) left) - (+ (cdr point-pix-pos) (cadr edges) top)))) - - +(defun semantic-displayor-point-position (&optional mouse frame-rel) + "Return the location of the POINT or optionally the MOUSE-cursor as positioned on +the selected frame (or nil otherwise). Setting FRAME-REL non-nil produces results +relative to the top-left (X Y) of the selected frame, Return a cons cell (X . Y)" + (let ((fleft 0) (ftop 0)) + (if (not frame-rel) ;;add frame offsets + (let* ((frame (selected-frame)) + (lpos (frame-parameter frame 'left)) + (tpos (frame-parameter frame 'top))) +; (setq fleft (or (car-safe (cdr-safe (frame-parameter frame 'left))) (frame-parameter frame 'left))) + (setq fleft (cond ((eq (type-of lpos) 'integer) lpos) + ((eq (car lpos) '+) (cadr lpos)) + (t (error "unexpected position in frame- parameter 'left: %s" lpos)))) +; (setq ftop (or (car-safe (cdr-safe (frame-parameter frame 'top))) (frame-parameter frame 'top))) + (setq ftop (cond ((eq (type-of tpos) 'integer) tpos) + ((eq (car tpos) '+) (cadr tpos)) + (t (error "unexpected position in frame- parameter 'top: %s" tpos)))))) + (cond (mouse (if (cddr (mouse-pixel-position)) + (cons (+ (nth 1 (mouse-pixel-position)) fleft) + (+ (nthcdr 2 (mouse-pixel-position)) ftop)))) + (t (let* ((point-pix-pos (posn-x-y (posn-at-point))) + (edges (window-inside-pixel-edges (selected-window)))) + (cons (+ (car point-pix-pos) (car edges) fleft) + (+ (cdr point-pix-pos) (cadr edges) ftop))))))) + (defun semantic-displayor-tooltip-show (text) "Display a tooltip with TEXT near cursor." - (let ((point-pix-pos (semantic-displayor-point-position)) - (tooltip-frame-parameters - (append tooltip-frame-parameters nil))) - (push - (cons 'left (+ (car point-pix-pos) (frame-char-width))) - tooltip-frame-parameters) - (push - (cons 'top (+ (cdr point-pix-pos) (frame-char-height))) - tooltip-frame-parameters) + (let* ((point-pix-pos (semantic-displayor-point-position)) + (point-pix-pos-mouse (semantic-displayor-point-position t)) + (point-pix-pos-mouse-frame-rel (semantic-displayor-point-position t t)) + (tooltip-frame-parameters (append tooltip-frame-parameters nil)) + (tooltip-left (+ (car point-pix-pos) (frame-char-width))) + (tooltip-top (+ (cdr point-pix-pos) (frame-char-height))) + (mouse-left (car-safe point-pix-pos-mouse)) + (mouse-top (cdr-safe point-pix-pos-mouse)) + lines (width 0) (height 0)) + ;;setup tooltip + (push (cons 'left tooltip-left) tooltip-frame-parameters) + (push (cons 'top tooltip-top) tooltip-frame-parameters) + ;;if possible ensure mouse pointer is out of the way or the tooltip will immediately disappear + (setq lines (split-string text "\n")) + (mapc '(lambda (line) (setq width (max width (length line)))) lines) + (setq width (* (frame-char-width) width)) + (setq height (* (frame-char-height) (length lines))) + (if (and point-pix-pos-mouse + (>= mouse-left (- tooltip-left (frame-char-width))) + (<= mouse-left (+ tooltip-left width (frame-char-width))) + (>= mouse-top (- tooltip-top (* 6 (frame-char-height)))) + (<= mouse-top (+ (- tooltip-top (* 6 (frame-char-height))) height))) + ;;mouse cursor is in the frame, in the tooltip space (allowing + ;;for the five entries above and a character sized border) + (set-mouse-pixel-position (car (mouse-pixel-position)) + (- (car point-pix-pos-mouse-frame-rel) (- mouse-left (car point-pix-pos)) (frame-char-width)) + (cdr point-pix-pos-mouse-frame-rel))) + ;;show text (tooltip-show text))) (defmethod semantic-displayor-scroll-request ((obj semantic-displayor-tooltip)) "A request to for the displayor to scroll the completion list (if needed)." ;; Do scrolling in the tooltip. - (oset obj max-tags 30) + (oset obj max-tags semantic-complete-inline-max-tags-extended) (semantic-displayor-show-request obj) ) @@ -1975,7 +2098,8 @@ See `semantic-complete-inline-tag-engine' for details on how completion works." (if (not context) (setq context (semantic-analyze-current-context (point)))) - (if (not context) (error "Nothing to complete on here")) + (if (not context) + (if semantic-idle-scheduler-verbose-flag (message " Nothing to complete on here"))) (let* ((collector (semantic-collector-analyze-completions "inline" :buffer (oref context buffer) @@ -2120,7 +2244,8 @@ how completion options are displayed." (interactive) ;; Only do this if we are not already completing something. - (if (not (semantic-completion-inline-active-p)) + (if (and (not (semantic-completion-inline-active-p)) + (semantic-analyze-current-context (point))) (semantic-complete-inline-analyzer (semantic-analyze-current-context (point)))) ;; Report a message if things didn't startup. @@ -2142,7 +2267,8 @@ to change how completion options are displayed." (interactive) ;; Only do this if we are not already completing something. - (if (not (semantic-completion-inline-active-p)) + (if (and (not (semantic-completion-inline-active-p)) + (semantic-analyze-current-context (point))) (semantic-complete-inline-analyzer-idle (semantic-analyze-current-context (point)))) ;; Report a message if things didn't startup. diff -ur cedet.orig/semantic/semantic-idle.el cedet/semantic/semantic-idle.el --- cedet.orig/semantic/semantic-idle.el 2011-06-26 13:17:05.000000000 +0100 +++ cedet/semantic/semantic-idle.el 2011-06-26 01:26:02.000000000 +0100 @@ -275,7 +275,7 @@ ;; services. Stop on keypress. ;; NOTE ON COMMENTED SAFE HERE - ;; We used to not execute the services if the buffer wsa + ;; We used to not execute the services if the buffer was ;; unparseable. We now assume that they are lexically ;; safe to do, because we have marked the buffer unparseable ;; if there was a problem. @@ -284,11 +284,11 @@ (save-excursion (semantic-throw-on-input 'idle-queue) (when semantic-idle-scheduler-verbose-flag - (working-temp-message "IDLE: execture service %s..." service)) + (working-temp-message "IDLE: execute service %s..." service)) (semantic-safe (format "Idle Service Error %s: %%S" service) (funcall service)) (when semantic-idle-scheduler-verbose-flag - (working-temp-message "IDLE: execture service %s...done" service)) + (working-temp-message "IDLE: executre service %s...done" service)) ))) ;;) ;; Finally loop ... [truncated message content] |
From: David E. <de...@ra...> - 2011-06-27 19:56:45
|
Pete Beardmore writes: > here is a set of patches for several bugs and some improvements to the > inline completion mechanism. Thank you for the patches; they're much appreciated. Do you have papers signed with the FSF? This will be necessary since CEDET is merged with Emacs and your patches by far exceed the "tiny patch" limit. Cheers, David |
From: Pete B. <elb...@ms...> - 2011-07-11 20:22:30
|
David Engster <deng <at> randomsample.de> writes: > Thank you for the patches; they're much appreciated. Do you have papers > signed with the FSF? This will be necessary since CEDET is merged with > Emacs and your patches by far exceed the "tiny patch" limit. > > Cheers, > David > hi, no i don't sorry. from what i've just read, is it possible for you to send me the assignment paper template(s) for this project? and does it really require snail mail all the way across the big pond? cheers. |
From: David E. <de...@ra...> - 2011-07-12 19:19:47
Attachments:
request-assign.future
|
Pete Beardmore writes: > David Engster <deng <at> randomsample.de> writes: >> Thank you for the patches; they're much appreciated. Do you have papers >> signed with the FSF? This will be necessary since CEDET is merged with >> Emacs and your patches by far exceed the "tiny patch" limit. > no i don't sorry. from what i've just read, is it possible for you to send > me the assignment paper template(s) for this project? I attached the form to this mail. As for the project, just use 'GNU Emacs', since this will also cover every project that is merged with it. > and does it really require snail mail all the way across the big pond? Unfortunately, yes. But I will need some time digging through your patches anyway. :-) BTW, are you using CEDET from bzr, and which Emacs version are you using? -David |
From: Pete B. <elb...@ms...> - 2011-08-04 23:39:55
|
David Engster <deng <at> randomsample.de> writes: > ..but I will need some time digging through your patches anyway. > BTW, are you using CEDET from bzr, and which Emacs version are you using? hi David, just wanted to let you know that my FSF assignment copy arrived back via email today :) the patches were all done against bzr8071. please come back to me if you think any of them could go in but need more work, and of course no offense taken if you deem any (or all) of them too poor or unsuitable. cheers, Pete. |
From: Jai D. <day...@gm...> - 2011-08-04 23:55:40
|
I'm confused.. was a new version of CEDET released? On Thu, Aug 4, 2011 at 5:39 PM, Pete Beardmore <elb...@ms...> wrote: > David Engster <deng <at> randomsample.de> writes: > > ..but I will need some time digging through your patches anyway. > > BTW, are you using CEDET from bzr, and which Emacs version are you using? > > hi David, just wanted to let you know that my FSF assignment copy arrived > back > via email today :) the patches were all done against bzr8071. please come > back > to me if you think any of them could go in but need more work, and of > course > no offense taken if you deem any (or all) of them too poor or unsuitable. > > cheers, > Pete. > > > > > > ------------------------------------------------------------------------------ > BlackBerry® DevCon Americas, Oct. 18-20, San Francisco, CA > The must-attend event for mobile developers. Connect with experts. > Get tools for creating Super Apps. See the latest technologies. > Sessions, hands-on labs, demos & much more. Register early & save! > http://p.sf.net/sfu/rim-blackberry-1 > _______________________________________________ > cedet-semantic mailing list > ced...@li... > https://lists.sourceforge.net/lists/listinfo/cedet-semantic > |
From: David E. <de...@ra...> - 2011-08-05 08:07:08
|
Pete Beardmore writes: > David Engster <deng <at> randomsample.de> writes: >> ..but I will need some time digging through your patches anyway. >> BTW, are you using CEDET from bzr, and which Emacs version are you using? > > hi David, just wanted to let you know that my FSF assignment copy arrived back > via email today :) the patches were all done against bzr8071. please come back > to me if you think any of them could go in but need more work, and of course > no offense taken if you deem any (or all) of them too poor or unsuitable. Thanks Pete for going through the trouble. I should find time to take a look at the patches in the coming days. -David |
From: David E. <de...@ra...> - 2011-08-08 18:22:38
|
Pete Beardmore writes: > here is a set of patches for several bugs and some improvements to the > inline completion mechanism. Hi Pete, I'm slowly starting to apply your patches. Unfortunately, the diffs are garbled by word-wrapping - could you send me the full patch again, but as an attachment? (No need to send the patches one-by-one, the full diff will suffice). Regarding tooltip completions, you should also take a look at company-mode; it's easily installable from GNU ELPA (M-x list-packages if you're using Emacs24-bzr) and supports Semantic out of the box. What always bothered me with the graphical tooltips was that they're just too slow and easily interfere with typing. Company-mode uses text overlays to mimic tooltips, which is much faster. -David |
From: David E. <de...@ra...> - 2011-08-09 06:08:43
|
Eric M. Ludlam writes: > On 08/08/2011 02:22 PM, David Engster wrote: >> Regarding tooltip completions, you should also take a look at >> company-mode; it's easily installable from GNU ELPA (M-x list-packages >> if you're using Emacs24-bzr) and supports Semantic out of the box. What >> always bothered me with the graphical tooltips was that they're just too >> slow and easily interfere with typing. Company-mode uses text overlays >> to mimic tooltips, which is much faster. > > > I've often been impressed w/ that style tool tip. Has there been a > tooltip using overlays like that integrated into Emacs yes? I think I read on emacs-devel that company-mode is a candidate for integration into Emacs. > If so, it may be time to add a new tip style into Semantic's > completion engine. company-mode is more than just a widget - it also takes care of querying for completions, refining and searching for matches, etc.. So it pretty much does everything that had to be explicitly coded for the Semantic tooltip displayor. The only thing you have to provide is a 'back end' which adheres to the company-mode API, but Nikolaj already wrote one for Semantic, so there really isn't much to do anymore. :-) I use it all the time and it works really great. Of course, there are some drawbacks to using text overlays, the most important being that you're restricted to the buffer's window for display, but I think its speed makes up for that. -David |
From: Eric M. L. <eri...@gm...> - 2011-08-09 13:03:30
|
On 08/09/2011 02:08 AM, David Engster wrote: > Eric M. Ludlam writes: >> On 08/08/2011 02:22 PM, David Engster wrote: >>> Regarding tooltip completions, you should also take a look at >>> company-mode; it's easily installable from GNU ELPA (M-x list-packages >>> if you're using Emacs24-bzr) and supports Semantic out of the box. What >>> always bothered me with the graphical tooltips was that they're just too >>> slow and easily interfere with typing. Company-mode uses text overlays >>> to mimic tooltips, which is much faster. >> >> >> I've often been impressed w/ that style tool tip. Has there been a >> tooltip using overlays like that integrated into Emacs yes? > > I think I read on emacs-devel that company-mode is a candidate for > integration into Emacs. > >> If so, it may be time to add a new tip style into Semantic's >> completion engine. > > company-mode is more than just a widget - it also takes care of querying > for completions, refining and searching for matches, etc.. So it pretty > much does everything that had to be explicitly coded for the Semantic > tooltip displayor. The only thing you have to provide is a 'back end' > which adheres to the company-mode API, but Nikolaj already wrote one for > Semantic, so there really isn't much to do anymore. :-) I use it all the > time and it works really great. Of course, there are some drawbacks to > using text overlays, the most important being that you're restricted to > the buffer's window for display, but I think its speed makes up for > that. That's good to know. I've always been worried about simplified completion engines, in that if someone types: a TAB the size of the options available after "a" can be large, and the query can be slow, so the built in completion engine caches values between completion requests, allowing it to be faster. Of course, that is also semantic's completion engine downfall, as it sometimes gets confused. If a standard full completion request has proven fast enough for all requests, perhaps the old optimizations can be dropped. Eric |
From: Eric M. L. <eri...@gm...> - 2011-08-08 22:32:49
|
On 08/08/2011 02:22 PM, David Engster wrote: > Pete Beardmore writes: >> here is a set of patches for several bugs and some improvements to the >> inline completion mechanism. > > Hi Pete, > > I'm slowly starting to apply your patches. Unfortunately, the diffs are > garbled by word-wrapping - could you send me the full patch again, but > as an attachment? (No need to send the patches one-by-one, the full diff > will suffice). > > Regarding tooltip completions, you should also take a look at > company-mode; it's easily installable from GNU ELPA (M-x list-packages > if you're using Emacs24-bzr) and supports Semantic out of the box. What > always bothered me with the graphical tooltips was that they're just too > slow and easily interfere with typing. Company-mode uses text overlays > to mimic tooltips, which is much faster. I've often been impressed w/ that style tool tip. Has there been a tooltip using overlays like that integrated into Emacs yes? If so, it may be time to add a new tip style into Semantic's completion engine. Eric |
From: David E. <de...@ra...> - 2011-08-16 21:04:16
|
Hi Pete, I think I applied most of your changes now. Here are a few comments: Pete Beardmore writes: > #1. bug #1: Bug Showing Completions: (wrong-type-argument consp nil) > #2. bug #2: Bug Showing Completions: > (wrong-type-argument number-or-marker-p (+ -90)) Both applied. > #3. bug #3: tooltip disappears immediately > > #recipe > place the mouse cursor in the region that the tooltip will be displayed in > #commentary > this is a 'bug' / 'feature' in the low-level C 'x-show-tip' function ..i > won't be looking in there any time soon. I find that difficult to reproduce. I think it depends very much on the used toolkit. Did you maybe manage to produce a recipe for this, only using 'x-show-tip' and starting with 'emacs -Q' ? If so, this should be reported as an Emacs bug. > the patch below is a work around which simply warps the mouse pointer > out of the way. Since I wasn't able to really reproduce this, I haven't applied that patch yet. > #4. bug #4 use last completions when new prefix is subset of old prefix Applied. > #5. 'bug' #5 don't complete if there's no context > > #recipe > apply idle patch > set verbose mode -> (setq semantic-idle-scheduler-verbose-flag t) > *@#k ..cannot reproduce Me neither. :-) > > #location > semantic-complete-analyze-inline-idle > semantic-complete.el:2145 (bzr8071) > > #commentary > a (in)valid overlay ..and no context?! how did i get here? probably just > ignore this as it 'should' be impossible, although i suppose it can't > hurt to add it given that i don't think i was far enough into my hacking > session to have tampered with anything that would obviously leave the > engine in an unrecoverable state (i.e. quiting the debugger so the > clean-up hooks don't run). i patched 'semantic-complete-analyze-idle' > assuming a similar issue could arise from the mini-buffer. I'm not too fond of sprinkling the code with semantic-analyze-current-context calls; I think we should try to find the 'real' bug here... :-) > also note that this error was only evident having patched semantic-idle.el > to not simply ignore problems (which i think should stand going forward!) I agree and have applied that. > #6. misc typo patches.. > #7. improvement #1 collect additional matches when the context/prefix > decreases in size > #8. improvement #2 short-circuit 'display action on TAB All applied. > #9. improvement #3 refine displayor modes of operation, make some properties > customisable, add 'remaining match' counts to tooltips, reset max-tags count > when searching on a shortened prefix I applied most of this with a few changes. > 'quiet-mode' - suppress all matches until the total number of matches > available is less than 'semantic-completion max-tags' number. several > tab presses will show an extended completion list, but only until the > next non-completion key/command is sent, hence truly staying 'quiet'. > > 'standard-mode' - always provide up to 'semantic-completion max-tags' > number of completions when available by default. single TAB will reveal > the extended list of completions up to > 'semantic-completion max-tags-extended' number, and this extended list > will be shown for the remainder of the completion, unless backspace is > keyed which resets the max-tags count back down to > 'semantic-completion-max-tags'. > > 'verbose-mode' - always show the extended completions list. horrible. I think those modes are good and an improvement over the previous 'force-show' option, which was a bit... erm, strange. :-) > +(defcustom semantic-complete-inline-mode-quiet nil > + "When enabled, only show completions when we have narrowed all > +posibilities down to a maximum of 'semantic-complete-inline-max-tags' > +tags. Pressing TAB multiple times will also show completions." > + :group 'semantic > + :type 'boolean > + :set '(lambda (sym var) > + (set-default sym var) > + (setq semantic-complete-inline-mode-standard nil) > + (setq semantic-complete-inline-mode-verbose nil) > + (if var (setq semantic-complete-inline-mode -1)))) I did change that, since you usually implement those kinds of 'radio button' behavior by using the 'choice' type and one variable. I also renamed all variables to make clear that they're related to the tooltip class. Most of my other changes were small and shouldn't touch the actual code you did, but please try it out. A few more remarks: - Use 'delete-trailing-whitespace' to, well, delete trailing whitespaces. :-) - doc-strings are expected to have a certain style in Emacs. For example, the first line should be a sentence describing the function. Also, all documentation in Emacs uses 'sentence spacing', meaning that there should be two whitespaces between sentences. (You can run 'checkdoc' to check your doc-strings and other stuff). - You don't have to use 'progn' in the "else"-branch of an 'if'. Thanks again, -David |
From: Pete B. <elb...@ms...> - 2011-08-16 23:33:49
|
David Engster <deng <at> randomsample.de> writes: > > > #3. bug #3: tooltip disappears immediately > > I find that difficult to reproduce. I think it depends very much on the > used toolkit. Did you maybe manage to produce a recipe for this, only > using 'x-show-tip' and starting with 'emacs -Q' ? If so, this should be > reported as an Emacs bug. i just pulled and compiled bzr8090 and cannot hit this problem at all - a good thing! i'll keep an eye on it though, i have two other sessions running now using the bzr8071 base that both exhibit the problem if i remove my patches. strange. > > > #9. improvement #3 refine displayor modes of operation, make some properties > > customisable, add 'remaining match' counts to tooltips, reset max-tags count > > when searching on a shortened prefix > > I applied most of this with a few changes. > > > > +(defcustom semantic-complete-inline-mode-quiet nil > > + "When enabled, only show completions when we have narrowed all > > +posibilities down to a maximum of 'semantic-complete-inline-max-tags' > > +tags. Pressing TAB multiple times will also show completions." > > + :group 'semantic > > + :type 'boolean > > + :set '(lambda (sym var) > > + (set-default sym var) > > + (setq semantic-complete-inline-mode-standard nil) > > + (setq semantic-complete-inline-mode-verbose nil) > > + (if var (setq semantic-complete-inline-mode -1)))) > > I did change that, since you usually implement those kinds of 'radio > button' behavior by using the 'choice' type and one variable. I also > renamed all variables to make clear that they're related to the tooltip > class. Most of my other changes were small and shouldn't touch the > actual code you did, but please try it out. brilliant thank you. the switch/radio/'choice' is exactly what i wanted to do, but i simply couldn't work out how to do it. > > A few more remarks: > > - Use 'delete-trailing-whitespace' to, well, delete trailing > whitespaces. > > - doc-strings are expected to have a certain style in Emacs. For > example, the first line should be a sentence describing the > function. Also, all documentation in Emacs uses 'sentence spacing', > meaning that there should be two whitespaces between sentences. (You > can run 'checkdoc' to check your doc-strings and other stuff). > > - You don't have to use 'progn' in the "else"-branch of an 'if'. > many thanks for the tips, i will apply all of them going forward. on the last point though, i think i do remember deliberately adding a few superfluous progn forms to try and make the larger else blocks more readable ..a more 'prominent' marker in the sea of parenthesis helps when you have a mismatch (well i know what i mean here even if nobody else is following ;D). clearly frowned upon though. anyway, fingers crossed the changes don't break the ideals of 'how it should work' for anybody but if it does turn out to be the case, i'll have another look at it. i do want to improve it further (time- permitting) ..for example, in playing with it just now it's clear that there should at least be the option to let 'backspace' cancel the current 'completion session', as now, backspacing many times is painful having effectively removed the previous (incomplete) caching actions. it's fast going forwards but slow going backwards. again, thanks for your help 'living the FSF dream'.. Pete. |
From: David E. <de...@ra...> - 2011-08-17 16:26:37
|
Pete Beardmore writes: > on the last point though, i think i do remember deliberately adding a > few superfluous progn forms to try and make the larger else blocks > more readable ..a more 'prominent' marker in the sea of parenthesis > helps when you have a mismatch (well i know what i mean here even if > nobody else is following ;D). clearly frowned upon though. I agree the different branches of `if' statements can sometimes be hard to spot. This is why if there actually is no 'else'-branch, you should always use `when' or `unless' instead of `if', so at least that becomes immediately clear (that's just my opinion and by no means an "official" rule). > anyway, fingers crossed the changes don't break the ideals of 'how it > should work' for anybody but if it does turn out to be the case, i'll > have another look at it. i do want to improve it further (time- > permitting) ..for example, in playing with it just now it's clear that > there should at least be the option to let 'backspace' cancel the > current 'completion session', as now, backspacing many times is painful > having effectively removed the previous (incomplete) caching actions. > it's fast going forwards but slow going backwards. Yes, I noticed that. I usually use backward-kill-word if I'm completely off, so it didn't bother me at least. -David |