Re: [CEDET-devel] CEDET and Matlab
Brought to you by:
zappo
From: David <de...@ar...> - 2008-07-18 14:11:37
|
Following up on a thread from May '08... "Eric M. Ludlam" <er...@si...> writes: >>>> David <de...@ar...> seems to think that: >>OK, I managed to scan all the tags in my Matlab files with >>semanticdb-mk.el. This works nicely for completing/searching tags for >>files in the current directory, but how do I get CEDET/semantic to also >>use the tags in all the subdirectories? As you said, Matlab doesn't have >>an 'include' statement, so I guess I would somehow have to specify >>"manually" which subdirectories should be included? > > Since MATLAB doesn't conform to the C like mechanisms, getting this > sort of thing to work requires overloading all the functions that are > too C centric. For example, `semanticdb-find-tag-by-name' calls > something that builds a `path'. That semanticdb-find-translate-path > should be overridden to include the local file, anything in private > with the specified name, and anything on the MATLAB path with the > specified name. (Find-translate-path builds a map of DB tables to > search, and is different from a what might be considered an include > path.) OK, after some Emacs Lisp I now got back to Matlab. :-) Matlab doesn't have an include mechanism, instead you could say it simply includes every function it finds in its path. So I overloaded semantidb-find-translate-path for matlab-mode to make semantic believe a M-file just does that. The Matlab path is for now simply specified by a new variable (semantic-matlab-include-paths), but should be better replaced by what you already suggested: > A second thing is to write a simple EDE project for MATLAB that knows > how to look at a MATLAB install, and extract the file path. But since not everyone uses EDE, I guess it also makes sense to have a variable to manually specify the search path. I attached to this message how far I've come. This is all pretty crude yet and needs some serious cleaning up; I just copied most of the stuff from semantidb-find.el, but it already works reasonably well, with the notable exception of caching. First, caching seems to work: If I initiate a completion, the find-translate-path function gets called, the M-files are scanned, and in the subsequent calls to find-translate-path (still for the same completion) the cached values are used. However, every time I initiate a *new* completion, the files get re-scanned. Somehow the include-path in the tag object is not saved between completions. Maybe you immediately know what the problem is here, otherwise I'll further have to dig into it. I don't know if these is even a good way to do this. Maybe one should better use an omniscient databases for this, like in Emacs Lisp mode? Thanks for your help, David Here's the code I put into semantic-matlab.el: (defvar semantic-matlab-include-paths '("/usr/matlab/7.4/toolbox/matlab/general" "/home/david/someproject") "Directories which should be scanned for m-files.") (defun semantic-matlab-generate-include-tags (dirs) "Create include tags with m-files in DIRS. DIRS is a list of directories." (let (tags) (dolist (dir dirs) (dolist (cur (directory-files dir t "\\.m$" t)) (push (semantic-tag-new-include cur nil) tags))) tags)) (define-mode-local-override semanticdb-find-translate-path matlab-mode (path brutish) "Translate PATH into a list of semantic tables." (if (semanticdb-find-results-p path) ;; Perform the search over these results. nil (if brutish (semanticdb-find-translate-path-brutish-default path) (let ((table (cond ((null path) semanticdb-current-table) ((semanticdb-abstract-table-child-p path) path) (t nil)))) (if table ;; If we were passed in something related to a TABLE, ;; do a caching lookup. (let ((index (semanticdb-get-table-index table))) (if (semanticdb-find-need-cache-update-p table) ;; Lets go look up our indicies (let ((ans (semantic-matlab-translate-path-includes--internal path))) (oset index include-path ans) ;; Once we have our new indicies set up, notify those ;; who depend on us if we found something for them to ;; depend on. (when ans (semanticdb-refresh-references table)) ans) ;; ELSE ;; ;; Just return the cache. (oref index include-path))) ;; If we were passed in something like a tag list, or other boring ;; searchable item, then instead do the regular thing without caching. (semantic-matlab-translate-path-includes--internal path)))))) (defun semantic-matlab-translate-path-includes--internal (path) "Include all m-files found in `semantic-matlab-include-paths' in PATH." (let ((includetags nil) (curtable nil) (matchedtables (list semanticdb-current-table)) (matchedincludes nil) (lostincludes nil) (scannedincludes nil) (incfname nil) nexttable) (setq includetags (semantic-matlab-generate-include-tags semantic-matlab-include-paths)) (cond ((null path) (setq curtable semanticdb-current-table incfname (buffer-file-name)) ) ((semanticdb-table-p path) (setq curtable path incfname (semanticdb-full-filename path)) ) ((bufferp path) (setq curtable (save-excursion (set-buffer path) semanticdb-current-table) incfname (buffer-file-name path))) (t (when includetags ;; If we have some tags, derive a table from them. ;; else we will do nothing, so the table is useless. ;; @todo - derive some tables (message "Need to derive tables for %S in translate-path-includes--default." path) ))) ;; Make sure each found include tag has an originating file name associated ;; with it. (when incfname (dolist (it includetags) (semantic--tag-put-property it :filename incfname))) ;; Loop over all include tags adding to matchedtables (while includetags (semantic-throw-on-input 'semantic-find-translate-path-includes-default) ;; If we've seen this include string before, lets skip it. (if (member (semantic-tag-name (car includetags)) matchedincludes) (progn (setq nexttable nil) (push (cons 'duplicate (semantic-tag-clone (car includetags))) scannedincludes) ) (setq nexttable (semanticdb-find-table-for-include (car includetags) curtable)) (when (not nexttable) ;; Save the lost include. (push (car includetags) lostincludes) (push (cons 'lost (semantic-tag-clone (car includetags))) scannedincludes) ) ) ;; Push the include file, so if we can't find it, we only ;; can't find it once. (push (semantic-tag-name (car includetags)) matchedincludes) (message "Scanning %s" (semantic-tag-name (car includetags))) (when (and nexttable (not (memq nexttable matchedtables)) (semanticdb-equivalent-mode-for-search nexttable (current-buffer)) ) ;; Add to list of tables (push nexttable matchedtables) ) (setq includetags (cdr includetags))) (setq semanticdb-find-lost-includes lostincludes) (setq semanticdb-find-scanned-include-tags (reverse scannedincludes)) (nreverse matchedtables))) |