diff lisp/modes/ksh-mode.el @ 2:ac2d302a0011 r19-15b2

Import from CVS: tag r19-15b2
author cvs
date Mon, 13 Aug 2007 08:46:35 +0200
parents 376386a54a3c
children 0293115a14e9
line wrap: on
line diff
--- a/lisp/modes/ksh-mode.el	Mon Aug 13 08:45:53 2007 +0200
+++ b/lisp/modes/ksh-mode.el	Mon Aug 13 08:46:35 2007 +0200
@@ -1,6 +1,6 @@
 ;; ksh-mode.el --- sh (ksh, bash) script editing mode for GNU Emacs.
 
-;; Copyright (C) 1992-95 Gary Ellison.
+;; Copyright (C) 1992-96 Gary Ellison.
 
 ;; This file is part of XEmacs.
 
@@ -18,25 +18,27 @@
 ;; along with XEmacs; see the file COPYING.  If not, write to the Free
 ;; Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
 
+;; $Source: /afs/informatik.uni-tuebingen.de/local/web/xemacs/xemacs-cvs/XEmacs/xemacs-19/lisp/modes/ksh-mode.el,v $ --  
+;;
 ;; LCD Archive Entry:
-;; ksh-mode|Gary F. Ellison|Gary_F_Ellison@ATT.COM
-;; Mode for editing sh/ksh/bash scripts
-;; 23-Feb-95|2.6|~/modes/ksh-mode.el.Z|
+;; ksh-mode|Gary F. Ellison|Gary.F.Ellison@ATT.COM
+;; |Mode for editing sh/ksh/bash scripts
+;; |$Date: 1996/12/18 03:44:42 $|$Revision: 1.1.1.2 $|~/modes/ksh-mode.el.Z|
 
 ;; Author: Gary F. Ellison <Gary.F.Ellison@ATT.COM>
-;;                   AT&T Bell Laboratories
+;;                   AT&T  Laboratories
 ;;                   6200 East Broad Street
 ;;                   Columbus, Ohio 43213 USA
 ;;
 ;; Maintainer: Gary F. Ellison <Gary.F.Ellison@ATT.COM>
 ;; Created: Fri Jun 19
-;; Version: 2.6
-;; Keywords: languages, shell, korn, bourne, sh, ksh, bash, unix
+;; $Revision: 1.1.1.2 $
+;; Keywords: shell, korn, bourne, sh, ksh, bash
 ;;
-;; Delta On        : 2/23/95
+;; Delta On   $Date: 1996/12/18 03:44:42 $
 ;; Last Modified By: Gary Ellison
-;; Last Modified On: Thu Feb 23 11:32:03 1995
-;; Update Count    : 33
+;; Last Modified On: Mon Sep 11 12:26:47 1995
+;; Update Count    : 35
 ;; Status          : Highly Functional
 ;;
 
@@ -78,6 +80,10 @@
 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 ;;
 ;; HISTORY 
+;; 6-Apr-96             Gary Ellison <gary.f.ellison@att.com>
+;;    Depreciated font-lock-doc-string-face.
+;;    Narly keywords inside strings bug fixed. 
+;;
 ;; 8-Aug-95		Jack Repenning <jackr@sgi.com>
 ;;    Fix documentation of `ksh-align-to-keyword' to conform to the 23
 ;;    Feb default change.  Search for keywords obeying case, since the
@@ -224,7 +230,7 @@
 ;;    Conception of this mode.
 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 
-(defconst ksh-mode-version "2.6"
+(defconst ksh-mode-version "$Revision: 1.1.1.2 $"
   "*Version numbers of this version of ksh-mode")
 
 ;;
@@ -262,8 +268,7 @@
 the current indentation. If non-nil, indentation will be relative to
 the column the keyword starts. If nil, indentation will be relative to
 the current indentation of the line the keyword is on.
-The default value is nil.
-The non-nil case doesn't work very well.")
+The default value is non-nil.  The non-nil case doesn't work very well.")
 
 (defvar ksh-comment-regexp "^\\s *#"
   "*Regular expression used to recognize comments. Customize to support
@@ -301,15 +306,15 @@
 ;;
 (defvar ksh-keywords '("for" "in" "do" "done" "select" "case" "esac" "if"
 "then" "elif" "else" "fi" "while" "until" "function" "time"
-"alias" "bg" "break" "continue" "cd" "echo" "fc" "fg" "getopts" "jobs" "kill"
-"let" "newgrp" "print" "pwd" "read" "readonly" "return" "set" "shift" "test"
-"times" "trap" "typeset" "ulimit" "umask" "unalias" "unset" "wait" "whence"))
+"alias" "bg" "break" "continue" "cd" "exit" "echo" "fc" "fg" "getopts" "jobs"
+"kill" "let" "newgrp" "print" "pwd" "read" "readonly" "return" "set" "shift"
+"test" "times" "trap" "typeset" "ulimit" "umask" "unalias" "unset" "wait" "whence"))
 
 ;;       '("\\<function[ \t]+\\([^(; \t]+\\)" 1 font-lock-function-name-face)
 (defconst ksh-font-lock-keywords
       (list
        ;; Fontify [[ ]] expressions
-       '("\\(\\[.*\\]\\)"  1 font-lock-doc-string-face t)
+       '("\\(\\[.*\\]\\)"  1 font-lock-string-face t)
        ;; Fontify keywords
        (cons (concat
 	      "\\(\\<"
@@ -321,65 +326,53 @@
        '("\\(^[ \t]*[A-Za-z_][A-Za-z_0-9]*[ \t]*()\\)" 1 font-lock-function-name-face)
        ))
 
+;; XEmacs addition
 (put 'ksh-mode	'font-lock-keywords 'ksh-font-lock-keywords)
 
-;; XEmacs change -- This can incorrectly set some Perl scripts to
-;; ksh-mode.  It also won't work for some other shells which ksh-mode
-;; nominally works with.
-;(defun ksh-check-hook ()
-;    (save-excursion
-;     (save-restriction
-;       (widen)
-;       (goto-char (point-min))
-;       (cond ((looking-at "#![ \t]*/.*/k?sh[ \t]*")
-;	      (ksh-mode))))))
-;
-;(add-hook 'find-file-hooks 'ksh-check-hook)
-
 ;;
 ;; Context/indentation regular expressions
 ;; 
 ;; indenting expressions
 ;;
-(defconst ksh-then-do-re     "^[^#\n]*\\s\"*\\b\\(then\\|do\\)\\b"
+;(defconst ksh-then-do-re     "^[^#\n]*\\s\"*\\b\\(then\\|do\\)\\b"
+(defconst ksh-then-do-re     "\\s *\\b\\(then\\|do\\)\\b"
   "*Regexp used to locate grouping keywords: \"then\" and \"do\"" )
 
-;;(defconst ksh-do-re          "^[ \t]*\\bdo\\(\\b\\|$\\)"
-(defconst ksh-do-re          "^\\s *\\bdo\\(\\b\\|$\\)"
+(defconst ksh-do-re          "\\s *\\bdo\\(\\b\\|$\\)"
   "*Regexp used to match keyword: do")
 
-(defconst ksh-then-re        "^\\s *\\bthen\\(\\b\\|$\\)"
+(defconst ksh-then-re        "\\s *\\bthen\\(\\b\\|$\\)"
   "*Regexp used to match keyword: then")
 
 ;;
 ;; Structure starting/indenting keywords
 ;;
-(defconst ksh-else-re           "^\\s *\\belse\\(\\b\\|$\\)"
+(defconst ksh-else-re           "\\s *\\belse\\(\\b\\|$\\)"
   "*Regexp used to match keyword: else")
 
-(defconst ksh-elif-re           "^\\s *\\belif\\(\\b\\|$\\)"
+(defconst ksh-elif-re           "\\s *\\belif\\(\\b\\|$\\)"
   "*Regexp used to match keyword: elif")
 
-(defconst ksh-brace-re           "^\\S>*{[ \t\n]"
+(defconst ksh-brace-re           "\\S>*{[ \t\n]"
   "*Regexp used to match syntactic entity: { ")
 
-(defconst ksh-case-item-end-re           "^\\S>*;;[ \t\n]"
+(defconst ksh-case-item-end-re           "\\S>*;;[ \t\n]"
   "*Regexp used to match case item end syntactic entity: ;;")
 
 (defconst ksh-keywords-re
-  "^[^#\n]*\\s\"*\\b\\(else\\|if\\|elif\\|case\\|while\\|for\\|until\\|select\\)\\b"
+  "\\s *\\b\\(else\\|if\\|elif\\|case\\|while\\|for\\|until\\|select\\)\\b"
   "*Regexp used to detect compound command keywords: if, else, elif case, 
 while, for, until, and select")
 
 
-(defconst ksh-if-re         "^[^#\n]*\\s\"*\\b\\(if\\)\\b"
+(defconst ksh-if-re         "\\s *\\b\\(if\\)\\b"
   "*Regexp used to match keyword: if")
 
 (defconst ksh-iteration-keywords-re 
-  "^[^#\n]*\\s\"*\\b\\(while\\|for\\|until\\|select\\)\\b"
+  "\\s *\\b\\(while\\|for\\|until\\|select\\)\\b"
   "*Match one of the keywords: while, until, for, select")
 
-(defconst ksh-case-re           "^[^#\n]*\\s\"*\\b\\(case\\)\\b"
+(defconst ksh-case-re           "\\s *\\bcase\\b"
   "*Regexp used to match keyword: case")
 
 (defconst ksh-explicit-func-re
@@ -403,16 +396,16 @@
 
 ;;
 ;; structure ending keyword regular expressions
-(defconst ksh-fi-re            "^\\s *fi\\b"
+(defconst ksh-fi-re            "\\s *\\bfi\\b"
   "*Regexp used to match keyword: fi")
 
-(defconst ksh-esac-re          "^\\s *esac\\b"
+(defconst ksh-esac-re          "\\s *\\besac\\b"
   "*Regexp used to match keyword: esac")
 
-(defconst ksh-done-re          "^\\s *done\\b"
+(defconst ksh-done-re          "\\s *\\bdone\\b"
   "*Regexp used to match keyword: done")
 
-(defconst ksh-brace-end-re  "^\\s *}\\s *"
+(defconst ksh-brace-end-re  "\\s *}\\s *"
   "*Regexp used to match function brace-groups")
 
 (defconst ksh-multiline-re "^.*\\\\$"
@@ -425,7 +418,13 @@
   "Syntax table used while in ksh mode.")
 (if ksh-mode-syntax-table
     ()
-  (setq ksh-mode-syntax-table (make-syntax-table))
+  (setq ksh-mode-syntax-table (make-syntax-table (standard-syntax-table)))
+  (modify-syntax-entry ?\( "." ksh-mode-syntax-table)
+  (modify-syntax-entry ?\) "." ksh-mode-syntax-table)
+  (modify-syntax-entry ?{ "." ksh-mode-syntax-table)
+  (modify-syntax-entry ?} "." ksh-mode-syntax-table)
+  (modify-syntax-entry ?\[ "(]" ksh-mode-syntax-table)
+  (modify-syntax-entry ?\] ")[" ksh-mode-syntax-table)
   (modify-syntax-entry ?\' "\"" ksh-mode-syntax-table)
   (modify-syntax-entry ?` "\"" ksh-mode-syntax-table)
   (modify-syntax-entry ?\n ">" ksh-mode-syntax-table)
@@ -436,7 +435,7 @@
   (modify-syntax-entry ?> "." ksh-mode-syntax-table)
   (modify-syntax-entry ?& "." ksh-mode-syntax-table)
   (modify-syntax-entry ?| "." ksh-mode-syntax-table)
-  (modify-syntax-entry ?$ "." ksh-mode-syntax-table)
+  (modify-syntax-entry ?$ "\\" ksh-mode-syntax-table)
   (modify-syntax-entry ?% "." ksh-mode-syntax-table)
   (modify-syntax-entry ?= "." ksh-mode-syntax-table)
   (modify-syntax-entry ?/ "." ksh-mode-syntax-table)
@@ -444,6 +443,7 @@
   (modify-syntax-entry ?* "." ksh-mode-syntax-table)
   (modify-syntax-entry ?- "." ksh-mode-syntax-table)
   (modify-syntax-entry ?\; "." ksh-mode-syntax-table)
+  (modify-syntax-entry ?: "." ksh-mode-syntax-table)
   )
 
 (defvar ksh-mode-abbrev-table nil
@@ -457,8 +457,6 @@
     ()
   (setq ksh-mode-map (make-sparse-keymap))
   (define-key ksh-mode-map "\t"    'ksh-indent-command)
-;;  (define-key ksh-mode-map "\n"    'reindent-then-newline-and-indent)
-;;  (define-key ksh-mode-map '[return] 'reindent-then-newline-and-indent)
 ;;  (define-key ksh-mode-map "\t"    'ksh-indent-line)
 ;;  (define-key ksh-mode-map "\177"    'backward-delete-char-untabify)
   (define-key ksh-mode-map "\C-j"    'reindent-then-newline-and-indent)
@@ -469,7 +467,7 @@
 
 ;;;###autoload
 (defun ksh-mode ()
-  "ksh-mode 2.6 - Major mode for editing (Bourne, Korn or Bourne again)
+  "ksh-mode $Revision: 1.1.1.2 $ - Major mode for editing (Bourne, Korn or Bourne again)
 shell scripts.
 Special key bindings and commands:
 \\{ksh-mode-map}
@@ -566,27 +564,19 @@
     
 
 Installation:
-  Put ksh-mode.el in some directory in your load-path.
-  Put the following forms in your .emacs file.
-
- (setq auto-mode-alist
-      (append auto-mode-alist
-              (list
-               '(\"\\\\.sh$\" . ksh-mode)
-               '(\"\\\\.ksh$\" . ksh-mode)
-               '(\"\\\\.bashrc\" . ksh-mode)
-               '(\"\\\\..*profile\" . ksh-mode))))
 
  (setq ksh-mode-hook
       (function (lambda ()
          (font-lock-mode 1)             ;; font-lock the buffer
          (setq ksh-indent 8)
-	 (setq ksh-group-offset -8))
+	 (setq ksh-group-offset -8)
 	 (setq ksh-brace-offset -8)   
          (setq ksh-tab-always-indent t)
          (setq ksh-match-and-tell t)
          (setq ksh-align-to-keyword t)	;; Turn on keyword alignment
 	 )))"
+  ;;
+  ;; and away we go
   (interactive)
   (kill-all-local-variables)
   (use-local-map ksh-mode-map)
@@ -663,7 +653,7 @@
   "Return a 2 element list (nest-level nest-line) describing where the
 current line should nest."
   (let ((case-fold-search)
-    	(level))
+	(level))
     (save-excursion
       (forward-line -1)
       (while (and (not (bobp))
@@ -715,6 +705,7 @@
     )
   ) ;; defun
 
+
 (defun ksh-get-case-indent ()
   "Return the column of the closest open case statement"
   (save-excursion
@@ -730,6 +721,7 @@
     )
   )
 
+
 ;;
 ;; Functions which make this mode what it is
 ;;
@@ -739,118 +731,126 @@
 into consideration keywords and other nesting constructs."
   (save-excursion 
     (let ((fence-post)
+;	  (start-post)
 	  (nester-column)
-	  (case-fold-search)
+ 	  (case-fold-search)
 	  (start-line (ksh-current-line)))
-      ;;
-      ;; Handle case item indentation constructs for this line
-      (cond ((ksh-looking-at-case-item)
-	     (save-excursion
-	       (goto-line nest-line)
-	       (let ((fence-post (save-excursion (end-of-line) (point))))
-		 ;;
-		 ;; Now know there is a case-item so detect whether
-		 ;; it is first under case, just another case-item, or
-		 ;; a case-item and case-item-end all rolled together.
-		 ;;
-		 (cond ((re-search-forward ksh-case-re fence-post t)
-			(goto-char (match-beginning 1))
-			(+ (ksh-current-indentation) ksh-case-item-offset))
-
-		       ((ksh-looking-at-case-item)
-			(current-indentation))
-
-		       ((looking-at ksh-case-item-end-re)
-			(end-of-line)
-			(+ (ksh-get-case-indent) ksh-case-item-offset))
-		       )
-		 )))
-	    (t;; Not a case-item.  What to do relative to the nest-line?
-	     (save-excursion
-	       (goto-line nest-line)
-	       (setq fence-post (save-excursion (end-of-line) (point)))
-	       (setq nester-column
-		     (save-excursion
-		       (cond
-			;;
-			;; Check if we are in a continued statement
-			((and (looking-at ksh-multiline-re)
-			      (save-excursion
-				(goto-line (1- start-line))
-				(looking-at ksh-multiline-re)))
-			 (+ (current-indentation) ksh-multiline-offset))
-
-			;; In order to locate the column of the keyword,
-			;; which might be embedded within a case-item,
-			;; it is necessary to use re-search-forward.
-			;; Search by literal case, since shell is
-			;; case-sensitive.
-			((re-search-forward ksh-keywords-re fence-post t)
-			 (goto-char (match-beginning 1))
-			 (if (looking-at ksh-case-re)
-			     (+ (ksh-current-indentation) ksh-case-item-offset)
-			   (+ (ksh-current-indentation)
+      (cond
+       ;;
+       ;; Handle case item indentation constructs for this line
+       ((ksh-looking-at-case-item)
+	(save-excursion
+	  (goto-line nest-line)
+	  (back-to-indentation)
+	  (let ((fence-post (ksh-eol-point)))
+	    ;;
+	    ;; Now know there is a case-item so detect whether
+	    ;; it is first under case, just another case-item, or
+	    ;; a case-item and case-item-end all rolled together.
+	    ;;
+	    (cond ((ksh-search-forward-sexp ksh-case-re fence-post)
+		   (+ (ksh-current-indentation) ksh-case-item-offset))
+		  
+		  ((ksh-looking-at-case-item)
+		   (current-indentation))
+		  
+		  ((looking-at ksh-case-item-end-re)
+		   (end-of-line)
+		   (+ (ksh-get-case-indent) ksh-case-item-offset))
+		  )
+	    )))
+       (t;; Not a case-item.  What to do relative to the nest-line?
+	(save-excursion
+	  (goto-line nest-line)
+;	  (setq start-post (point))
+	  (setq fence-post (ksh-eol-point))
+	  (setq nester-column
+		(save-excursion
+		  (cond
+		   ;;
+		   ;; Check if we are in a continued statement
+		   ((and (looking-at ksh-multiline-re)
+			 (save-excursion
+			   (goto-line (1- start-line))
+			   (looking-at ksh-multiline-re)))
+		    (+ (current-indentation) ksh-multiline-offset))
+		   ;; In order to locate the column of the keyword,
+		   ;; which might be embedded within a case-item,
+		   ;; it is necessary to iterate over sexp.
+		   ((progn
+		      (save-excursion
+			(back-to-indentation)
+			(if (ksh-search-forward-sexp ksh-keywords-re fence-post)
+			    (progn
+			      ;;
+			      ;; special pun intended 'case'
+			      (if (looking-at ksh-case-re)
+				  (+ (ksh-current-indentation)
+				     ksh-case-item-offset)
+				(+ (ksh-current-indentation)
+				   (if (null ksh-indent)
+				       2 ksh-indent))))	
+			  nil))
+		      ))
+		   ;;
+		   ;;  handle then or do
+		   ((progn
+		      (save-excursion
+			(back-to-indentation)
+			(if (ksh-search-forward-sexp ksh-then-do-re fence-post)
+			    (progn
 			      (if (null ksh-indent)
-				  2 ksh-indent)
-			      )))
+				  (+ (ksh-current-indentation) 1)
+				(+ (ksh-current-indentation) ksh-indent)))
+			  nil))))
 
-			((re-search-forward ksh-then-do-re fence-post t)
-			 (if (null ksh-indent)
-			     (progn 
-			       (goto-char (match-end 1))
-			       (+ (ksh-current-indentation) 1))
-			   (progn
-			     (goto-char (match-beginning 1))
-			     (+ (ksh-current-indentation) ksh-indent))
-			   ))
-
-			((looking-at ksh-brace-re)
-			 (+ (current-indentation)
-			    (if (null ksh-indent)
-				2 ksh-indent)
-			    ))
-			;;
-			;; Forces functions to first column
-			((or (looking-at ksh-implicit-func-re)
-			     (looking-at ksh-explicit-func-re))
-			 (if (looking-at ksh-func-brace-re)
-			     (if (null ksh-indent)
-				 2 ksh-indent)
-			   ksh-brace-offset))
+		   ((looking-at ksh-brace-re)
+		    (+ (current-indentation)
+		       (if (null ksh-indent)
+			   2 ksh-indent)
+		       ))
+		   ;;
+		   ;; Forces functions to first column
+		   ((or (looking-at ksh-implicit-func-re)
+			(looking-at ksh-explicit-func-re))
+		    (if (looking-at ksh-func-brace-re)
+			(if (null ksh-indent)
+			    2 ksh-indent)
+		      ksh-brace-offset))
 
-			;;
-			;; Need to first detect the end of a case-item
-			((looking-at ksh-case-item-end-re)
-			 (end-of-line)
-			 (+ (ksh-get-case-indent) ksh-case-item-offset))
-			;;
-			;; Now detect first statement under a case item
-			((ksh-looking-at-case-item)
-			 (if (null ksh-case-indent)
-			     (progn
-			       (re-search-forward ksh-case-item-re fence-post t)
-			       (goto-char (match-end 1))
-			       (+ (current-column) 1))
-			   (+ (current-indentation) ksh-case-indent)))
-
-			;; This is hosed when using current-column
-			;; and there is a multi-command expression as the
-			;; nester.
-			(t (current-indentation)))
-		       )
-		     ));; excursion over
-	     ;;
-	     ;; Handle additional indentation constructs for this line
-	     (cond ((ksh-looking-at-compound-list)
-		    (+ nester-column ksh-group-offset))
-		   ((looking-at ksh-brace-re)
-		    (+ nester-column ksh-brace-offset))
-		   (t nester-column))
-	     );; Not a case-item
-	    )
+		   ;;
+		   ;; Need to first detect the end of a case-item
+		   ((looking-at ksh-case-item-end-re)
+		    (end-of-line)
+		    (+ (ksh-get-case-indent) ksh-case-item-offset))
+		   ;;
+		   ;; Now detect first statement under a case item
+		   ((ksh-looking-at-case-item)
+		    (if (null ksh-case-indent)
+			(progn
+			  (re-search-forward ksh-case-item-re fence-post t)
+			  (goto-char (match-end 1))
+			  (+ (current-column) 1))
+		      (+ (current-indentation) ksh-case-indent)))
+		   
+		   ;; This is hosed when using current-column
+		   ;; and there is a multi-command expression as the
+		   ;; nester.
+		   (t (current-indentation)))
+		  )
+		));; excursion over
+	;;
+	;; Handle additional indentation constructs for this line
+	(cond ((ksh-looking-at-compound-list)
+	       (+ nester-column ksh-group-offset))
+	      ((looking-at ksh-brace-re)
+	       (+ nester-column ksh-brace-offset))
+	      (t nester-column))
+	);; Not a case-item
+       )
       );;let
     );; excursion
-  );; defun
+  ) ;; defun
 
 (defun ksh-indent-command ()
   "Indent current line relative to containing block and allow for
@@ -905,9 +905,7 @@
     (let*
 	(
 	 (this-line-level (current-indentation))
-	 (this-bol (save-excursion
-		     (beginning-of-line)
-		     (point)))
+	 (this-bol (ksh-bol-point))
 	 (this-point (- (point) this-bol))
 	 )
       (cond ((> this-line-level this-point);; point in initial white space
@@ -959,6 +957,7 @@
   (let (case-fold-search)
     (save-excursion
       (beginning-of-line)
+      (back-to-indentation)
       (cond ((looking-at ksh-else-re)
 	     (ksh-match-indent-level ksh-if-re ksh-fi-re))
 	    ((looking-at ksh-elif-re)
@@ -981,14 +980,83 @@
       )
     ))
 
-(defun ksh-get-compound-level 
+
+(defun ksh-search-backward-sexp (sexp-re fence-post)
+  (let
+      ((old-pnt (point))
+       (sentinal nil)
+       )
+    (while
+	(progn
+	  (if (not sentinal)
+	      (backward-sexp 1))
+	  (and (> (point) fence-post)
+	       (not sentinal))
+	  )
+      (if (looking-at sexp-re)
+	  (save-excursion			;avoid comment foolage
+	    (let ((key-fence (point)))
+	      (beginning-of-line)
+	      (back-to-indentation)
+	      (while (and (ksh-search-forward-sexp sexp-re key-fence)
+			  (< (point) key-fence)))
+	      
+	      (if (= key-fence (point))
+		  (setq sentinal t))
+	      ))
+	))
+      
+      (if (< (point) fence-post)
+	  (progn (goto-char old-pnt)
+		 nil)
+	t)
+      ))
+
+(defun ksh-forward-sexp ()
+  "Special incantation to march over syntax expressions and
+avoid all sorts of nonsense"
+  (if (char-equal ?< (char-syntax (char-after (point))))
+      (end-of-line)
+    (if (char-equal ?. (char-syntax (char-after (point))))
+	(forward-char)
+      (forward-sexp 1))
+    )
+  (if (eolp)
+      (forward-line))
+  (skip-chars-forward ") \t")		;damn case
+  )
+
+(defun ksh-search-forward-sexp (sexp-re fence-post)
+  "Search for an sexp. Return t on success with point at the
+beginning of the sexp. Return nil on failure and restoring point
+to it's original position"
+  (let
+      ((old-pnt (point))
+       )
+    (while (and (< (point) fence-post)
+		(not (looking-at sexp-re)))
+      (ksh-forward-sexp))
+    
+    (if (> (point) fence-post)
+	(progn (goto-char old-pnt)
+	       nil)
+      t)
+    ))
+
+
+(defun ksh-get-compound-level
   (begin-re end-re anchor-point &optional balance-list)
   "Determine how much to indent this structure. Return a list (level line) 
 of the matching compound command or nil if no match found."
   (let* 
       (;; Locate the next compound begin keyword bounded by point-min
-       (match-point (if (re-search-backward begin-re (point-min) t)
-			(match-beginning 1) 0))
+       (match-point
+	(if (and (ksh-search-backward-sexp begin-re (point-min))
+		 (>= (point) (point-min))
+		 )
+	    (point)
+	  0))
+
        (nest-column (if (zerop match-point)
 			1 
 		      (progn
@@ -1002,16 +1070,21 @@
 	(if (nlistp balance-list)
 	    (setq balance-list (list)))
 	;; Now search forward from matching start keyword for end keyword
+	;; which will locate interceding compound commands
 	(while (and (consp nest-list) (zerop (cdr nest-list))
-		    (re-search-forward end-re anchor-point t))
+		    (ksh-search-forward-sexp end-re anchor-point)
+		    (> anchor-point (point))
+		    )
 	  (if (not (memq (point) balance-list))
 	      (progn
 		(setq balance-list (cons (point) balance-list))
 		(goto-char match-point)  ;; beginning of compound cmd
 		(setq nest-list
 		      (ksh-get-compound-level begin-re end-re
-					     anchor-point balance-list))
-		)))
+					      anchor-point balance-list))
+		)
+	    (ksh-forward-sexp)
+	    ))
 
 	(cond ((consp nest-list)
 	       (if (zerop (cdr nest-list))