]> code.delx.au - gnu-emacs-elpa/blobdiff - packages/f90-interface-browser/f90-interface-browser.el
Merge commit 'af601c4a8a087cc5a12a08e08af094c4e21d417c' from diff-hl
[gnu-emacs-elpa] / packages / f90-interface-browser / f90-interface-browser.el
index 58ed588de5fa85ee90c92b18bef2f21b84ecdc96..8956400deb3b3a4e9244c5078bc620cc2835e9eb 100644 (file)
@@ -1,11 +1,12 @@
 ;;; f90-interface-browser.el --- Parse and browse f90 interfaces
 
-;; Copyright (C) 2011, 2012  Free Software Foundation, Inc
+;; Copyright (C) 2011, 2012, 2013  Free Software Foundation, Inc
 
 ;; Author: Lawrence Mitchell <wence@gmx.li>
 ;; Created: 2011-07-06
-;; Available-from: http://github.com/wence-/f90-iface/
-;; Version: 1.0
+;; URL: http://github.com/wence-/f90-iface/
+;; Version: 1.1
+;; Package-Type: simple
 
 ;; COPYRIGHT NOTICE
 
 ;; so that you can use it on the M-.  keybinding and it will fall back
 ;; to completing tag names if you don't want to look for an interface
 ;; definition.
+;; In addition, if you're in a large procedure and want the list of
+;; the variables in scope (perhaps you want to define a new loop
+;; variable), you can use `f90-list-in-scope-vars' to pop up a buffer
+;; giving a reasonable guess.  Note this doesn't give you module
+;; variables, or the variables of parent procedures if the current
+;; subroutine is contained within another.
 
 ;; Derived types are also parsed, so that slot types of derived types
 ;; are given the correct type (rather than a UNION-TYPE) when arglist
 ;;; Code:
 
 ;;; Preamble
-(eval-when-compile
-  (require 'cl))
+(eval-when-compile (require 'cl))
 (require 'thingatpt)
 (require 'f90)
 (require 'etags)
@@ -200,18 +206,6 @@ level.  For example, a LEVEL of 0 counts top-level commas."
     (when fn
       (funcall fn (f90-get-type type)))))
 
-(defun f90-lazy-completion-table ()
-  "Lazily produce a completion table of all interfaces and tag names."
-  (lexical-let ((buf (current-buffer)))
-    (lambda (string pred action)
-      (with-current-buffer buf
-        (save-excursion
-          ;; If we need to ask for the tag table, allow that.
-          (let ((enable-recursive-minibuffers t))
-            (visit-tags-table-buffer))
-          (complete-with-action action (f90-merge-into-tags-completion-table f90-all-interfaces) string pred))))))
-
-
 (defsubst f90-merge-into-tags-completion-table (ctable)
   "Merge completions in CTABLE into the tags completion table."
   (if (or tags-file-name tags-table-list)
@@ -223,6 +217,17 @@ level.  For example, a LEVEL of 0 counts top-level commas."
         table)
     ctable))
 
+(defun f90-lazy-completion-table ()
+  "Lazily produce a completion table of all interfaces and tag names."
+  (lexical-let ((buf (current-buffer)))
+    (lambda (string pred action)
+      (with-current-buffer buf
+        (save-excursion
+          ;; If we need to ask for the tag table, allow that.
+          (let ((enable-recursive-minibuffers t))
+            (visit-tags-table-buffer))
+          (complete-with-action action (f90-merge-into-tags-completion-table f90-all-interfaces) string pred))))))
+
 (defsubst f90-extract-type-name (name)
   "Return the typename from NAME.
 
@@ -588,7 +593,6 @@ first (length ARGLIST) args of SPECIALISER."
                    (<= n-passed-args n-spec-args)))
       (loop for arg in arglist
             for spec-arg in spec-arglist
-            with match = nil
             unless (or (null arg)
                        (string= (f90-get-parsed-type-typename arg)
                                 (f90-get-parsed-type-typename spec-arg)))
@@ -875,6 +879,51 @@ needs a reference count interface, so insert one."
           (goto-char (point-min))
           (f90-arg-types names))))))
 
+(defun f90-list-in-scope-vars ()
+  "Pop up a buffer showing all variables in scope in the procedure at `point'"
+  (interactive)
+  (let* ((e (save-excursion (f90-end-of-subprogram) (point)))
+         (b (save-excursion (f90-beginning-of-subprogram) (point)))
+         (str (buffer-substring-no-properties b e))
+         types)
+    (with-temp-buffer
+      (with-syntax-table f90-mode-syntax-table
+        (insert str)
+        (goto-char (point-min))
+        (f90-clean-comments)
+        (f90-clean-continuation-lines)
+        (forward-line 1)                ; skip procedure name
+        (let ((not-done t)
+              type)
+          (while (and not-done (not (eobp)))
+            ;; skip "implicit none" which may appear at top of procedure
+            (when (looking-at "\\s-*implicit\\s-+none")
+              (forward-line 1))
+            (when (not (looking-at "^\\s-*$"))
+              (setq type (ignore-errors (f90-parse-single-type-declaration)))
+              ;; If we were on a line with text and failed to parse a
+              ;; type, we must have reached the end of the type
+              ;; definitions, so don't push it on and finish.
+              (if type
+                  (push type types)
+                (setq not-done nil)))
+            (forward-line 1)))))
+    (with-current-buffer (get-buffer-create "*Variables in scope*")
+      (setq buffer-read-only nil)
+      (erase-buffer)
+      (f90-mode)
+      ;; Show types of the same type together
+      (setq types (sort types (lambda (x y)
+                                (string< (cadar x) (cadar y)))))
+      (loop for (type name) in types
+            do
+            (insert (format "%s :: %s\n"
+                            (f90-format-parsed-slot-type type)
+                            (f90-get-parsed-type-varname type))))
+      (pop-to-buffer (current-buffer))
+      (goto-char (point-min))
+      (setq buffer-read-only t))))
+
 (defun f90-arg-types (names)
   "Given NAMES of arguments return their types.
 
@@ -979,13 +1028,12 @@ dealt with correctly."
                           (setcdr (assoc "dimension" dec)
                                   (1+ (f90-count-commas
                                        (match-string 2 name))))
-                        (add-to-list 'dec
-                                     (cons "dimension"
-                                           (1+ (f90-count-commas
-                                                (match-string 2 name))))
-                                     t))
+                        (push (cons "dimension"
+                                    (1+ (f90-count-commas
+                                         (match-string 2 name))))
+                              dec))
                       (setq name (match-string 1 name)))
-            collect (cons name dec)))))
+            collect (cons name (nreverse dec))))))
 
 (defun f90-split-declaration (dec)
   "Split and parse a type declaration DEC.