unofficial mirror of emacs-devel@gnu.org 
 help / color / mirror / code / Atom feed
From: David McKee <dmckee@jlab.org>
Subject: hide/show mode definitions for g77
Date: Mon, 25 Oct 2004 13:16:07 -0400 (EDT)	[thread overview]
Message-ID: <Pine.SOL.4.10.10410251244050.11640-100000@jlabs2.jlab.org> (raw)

Folks,
   Please find, below, a first stab at hide/show mode definitions for the
g77 dialect of Fortran. 

The code is derived from a f90 mode posted to the Usenet in 2002 by Glenn
Morris---who has given me his permission to submit this work---and
functions pretty well for programs written using structured block pairs. No
attempt is made to handle strict fortran 77 syntax in which blocks are
delimited with CONTINUEs and GO TOs.

This code has received little testing to date---I have show it to some
colleagues working on the same code I wanted it for, but have not heard
back from anyone. Also note that I am by no means a lisp programmer.

No guarantees or warranty, etc.

The code is also availible at:

	<http://www.jlab.org/~dmckee/G0/g77_hs_mode.el>

-- 
-- David McKee
-- dmckee@jlab.org
-- (757) 269-7492    (Office)


===========================

;; g77 fortran dialect hide-show mode definition.
;;
;; 19--22 October 2004  David W. McKee
;; Version 0.1  
;; Initial implementation.
;;
;; Hacked up from a f90 mode posted to the usenet:
;; From: Glenn Morris
;; Newsgroups: gnu.emacs.help </groups?hl=en&lr=&group=gnu.emacs.help>
;; Date: 2002-04-26 18:58:34 PST

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; Features and what not:
;; ----------------------
;; ==> Tries to work with the g77 dialect
;;
;; ==> Assume that the code is as structured as possible.  Indeed, we
;; make no attempt to deal with unstructured code. If you don't use
;; endif, enddo, etc. this code won't help you.
;;
;; ==> Identifies "IF" statements as block starts by finding the
;; "THEN" part, so that the condition remains visible after hiding.
;; Similarly for "WHILE (..) DO"

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; Known bugs in the f77 version:
;; ------------------------------
;; 22 October 2004 David McKee 
;;
;; ==> Comment hiding doesn't seem to work work. I don't understand
;; what it's supposed to do so I don't know where to go from here.
;;
;; ==> "CONTINUE" is a difficult case and is not treated at all.
;;
;; ==> Condition-at-the-end loops are often implemented as:
;;
;;    10   DO
;;         ...
;;         IF (...) GOTO 10
;;         ENDDO
;;
;; which will have the conditional hidden. Too bad.
;;
;; ==> I've cheeted in the ident-or-num regular expression, and it
;; will accept some constructions that the compiler will
;; reject. eg. "1abc" and the like...
;;
;; ==> So far it has recieved very little testing.

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
(defvar fortran-line-start-regexp "^\\ *[0-9]*\\ *" 
  "Allow for arbitrary white space at the start of a line.")

(defvar fortran-ident-regexp "\\<[A-Za-z][A-Za-z0-9_]*\\>" 
  "Regular expresion for fortran identifiers.")

;; Not precisly correct, but probably do the trick anyway
(defvar fortran-ident-or-num-regexp "\\<[A-Za-z0-9][A-Za-z0-9_]*\\>" 
  "")

;; Block "IF (..) THEN" and "WHIE (...) DO" statements could easily span
;; lines, so we select the block start on the ending keyword...
(defvar fortran-block-start-regexp
  (concat fortran-line-start-regexp
          "\\("
	  "\\(" "\\<program\\>[ \t]+" fortran-ident-regexp "\\)" "\\|" 
 	  "\\(" "\\<subroutine\\>[ \t]+" fortran-ident-regexp 
	                                 "[ \t]*([^)]*)" "\\)" "\\|" 
 	  "\\(" fortran-ident-regexp "[ \t]+\\<function\\>[ \t]+" 
	                             fortran-ident-regexp "[ \t]*([^)]*)" 
				     "\\)" "\\|"
	  ;; 'if (...) then'
	  ;; Note that 'if' without 'then' does not mark a block
 	  "\\(" ".*\\<then\\>" "\\)" "\\|"
	  ;; basic iterative 'do's
 	  "\\(" "\\<do\\>[ \t]*[0-9]*[ \t]+" fortran-ident-regexp 
                                       "[ \t]*=[ \t]*"
				       fortran-ident-or-num-regexp 
				       "\\([ \t]*,[ \t]*" 
				           fortran-ident-or-num-regexp 
				       "\\)+" "\\)" "\\|"
	  ;; do forever syle unconditional loop,
	  ;; also picks up 'while (...) do' constructs...
	  ;;
	  ;; Should proceed the while (..) do branch
 	  "\\(" "\\<do\\>[ \t]$" "\\)" "\\|"
	  ;; 'do while (...)'
	  ;; fails when the condition spans lines...
	  ;; but this does not seem to be part of the g77 dialect in any case
 	  "\\(" ".*\\<while\\>[ \t]*([^)]*)" "\\([ \t]*\\<do\\>\\)?" 
	                                     "\\)" "\\|"
	  ;;
	  ;; ELSE only starts a block if it is not followed by an IF
	  ;; for ELSE IF constructs, we start on the THEN.
	  ;; Look at fortran-block-end-start-regexp and the handling
	  ;; in fortran-forward-block...
	  "\\(" "\\<else\\>\\s *\\(!.*\\)?$" "\\)"
	  "\\)"
	  )
  "Regexp matching the start of a \"block\" of FORTRAN code.")

(defvar fortran-block-end-regexp
  (concat fortran-line-start-regexp 
	  "\\("
	  ;; structured fortran uses 'end<stuff>'
 	  "\\(" "\\<enddo\\>" "\\)" "\\|" 
 	  "\\(" "\\<endif\\>" "\\)" "\\|" 
	  ;; some dialects
 	  "\\(" "\\<endwhile\\>" "\\)" "\\|" 
	  ;; end<space>[if|do|while]type stuff
	  "\\(" "\\<end\\>[ \t]+" fortran-ident-regexp "\\)" "\\|" 
	  ;; catchall
	  "\\(" "\\<end\\>" "\\)" "\\|"
	  ;; CONTINUE causes trouble, it marks the end of old-fashioned
	  ;; do i=start,stop,inc type loops, but also serves as a 
	  ;; general labeling construct.
	  ;;
	  ;; leave it out by default
 	     ;; "\\(" "\\<continue\\>" "\\)" 
	  ;;
	  ;; Start and end bock markers...
	  ;;
	  "\\(" "\\<elseif\\>" "\\)" "\\|"
	  "\\(" "\\<else\\>\\s +\\<if\\>" "\\)" "\\|"
	  "\\(" "\\<else\\>" "\\)"
	  "\\)"
	  )
  "Regexp matching the end of a \"block\" of FORTRAN code.")

(defvar fortran-block-end-start-regexp
  (concat fortran-line-start-regexp
	  "\\("
	  "\\(" "\\<elseif\\>" "\\)" "\\|"
	  "\\(" "\\<else\\>\\s +\\<if\\>" "\\)" "\\|"
	  "\\(" "\\<else\\>\\s +\\<if\\>" "\\)"
	  "\\)"
	  )
  "Regexp matching a construct that marks the end of one \"block\" of
FORTRAN code, and the start of another. At this time this is only
ELSEIF constructs and ELSE statements.")

(defvar fortran-comment-regexp
  (concat ;;"\\("
	  "\\(" "^[CcDd\\*]" "\\)" ;;"\\|" 
          ;;"\\(" "^\\s *!.*$" "\\)"
	  ;;"\\)"
	  )
  "Regular expression for identifiying block comments in fortran")

;; Utility functions for checking my regexps
(defun fortran-find-next-block-start ()
  "Search forward to the next line matching fortran-block-end-regexp."
  (interactive)
  (search-forward-regexp fortran-block-start-regexp))

(defun fortran-find-next-block-end ()
  "Search forward to the next line matching fortran-block-end-regexp."
  (interactive)
  (search-forward-regexp fortran-block-end-regexp))

(defun fortran-next-block-start (arg)
  "Move forward a line at a time until we reach one matching fortran-block-start-regexp." 
  (interactive "p")
  (while (and (zerop (forward-line 1))
	      (not (looking-at fortran-block-start-regexp))) 
    (forward-line 1)))

(defun fortran-find-end-start-start ()
  "Move the point to the beginning of the next line--including the current
line--which matches fortran-block-start-regexp"
  (interactive)
  ((beginning-of-line)
   (while (null (looking-at fortran-block-start-regexg))
     (forward-line 1))
   (begining-of-line)))

(defun fortran-find-end-start-end ()
  "Move the point to the beginning of the most recent line--including
the current line--which matches fortran-block-end-regexp"
  (interactive)
  (beginning-of-line)
  (while (null (looking-at fortran-block-end-regexg))
    (forward-line -1))
  (beginning-of-line))

(defun fortran-forward-block (arg)
  "Move point to the forward until reaching exiting ARG levels of blocks"
  (interactive "p")
  (let ((count (or arg 1)))
    (while (and (> count 0) (zerop (forward-line 1)))
      (if (looking-at fortran-block-end-regexp) (setq count (1- count)))
      (and (> count 0) ()
	(if (looking-at fortran-block-end-start-regexp) 
	    (fortran-find-end-start-end))
	(if (looking-at fortran-block-start-regexp) 
	    (setq count (1+ count)))))))

(defun fortran-forward-block-adjust (arg)
  "Execute fortran-forward-block, then adjust the point to the end of the preceding line. Serves to leaves block ending constructs visible in hs-node."
  (interactive "p")
  (let ((count (or 1 arg)))
   (fortran-forward-block count)
   (forward-line -1)
   (end-of-line)))

;; Should have a fortran-backward-block for completeness
;; ...

(add-to-list 'hs-special-modes-alist
	     `(fortran-mode 
               ,fortran-block-start-regexp
               ,fortran-block-end-regexp
	       ,fortran-comment-regexp
	       fortran-forward-block-adjust ; forward-sexp-like behavior
	       nil
	       ))

             reply	other threads:[~2004-10-25 17:16 UTC|newest]

Thread overview: 5+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2004-10-25 17:16 David McKee [this message]
2004-11-02  9:48 ` hide/show mode definitions for g77 Thien-Thi Nguyen
2004-11-02 11:05   ` Glenn Morris
2004-11-02 17:26     ` Thien-Thi Nguyen
2004-11-11 18:38     ` David McKee

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

  List information: https://www.gnu.org/software/emacs/

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=Pine.SOL.4.10.10410251244050.11640-100000@jlabs2.jlab.org \
    --to=dmckee@jlab.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
Code repositories for project(s) associated with this public inbox

	https://git.savannah.gnu.org/cgit/emacs.git

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).