home *** CD-ROM | disk | FTP | other *** search
/ NetNews Usenet Archive 1992 #27 / NN_1992_27.iso / spool / gnu / emacs / sources / 795 next >
Encoding:
Text File  |  1992-11-15  |  5.9 KB  |  205 lines

  1. Path: sparky!uunet!ogicse!das-news.harvard.edu!cantaloupe.srv.cs.cmu.edu!crabapple.srv.cs.cmu.edu!andrew.cmu.edu!ts49+
  2. From: strong+@CMU.EDU (Thomas W. Strong, Jr.)
  3. Newsgroups: gnu.emacs.sources
  4. Subject: sh-mode.el
  5. Message-ID: <Qf1mBui00VpdM8mzYs@andrew.cmu.edu>
  6. Date: 15 Nov 92 18:28:42 GMT
  7. Article-I.D.: andrew.Qf1mBui00VpdM8mzYs
  8. Organization: Pittsburgh Supercomputing Center, Carnegie Mellon, Pittsburgh, PA
  9. Lines: 194
  10.  
  11. Here's a beginning of sh-mode.el.  Any comments or suggestions for
  12. improvements would be appreciated
  13.  
  14. -------------- cut here -------------------
  15. ;;; sh-mode.el
  16. ;;; 
  17. ;;; hacked out of forth.el from the tile-forth package
  18. ;;;
  19. ;;; comments/complaints/flames to strong+@cmu.edu
  20. ;;;
  21.  
  22. (defvar sh-mode-positives
  23.   " for case while else elif if \) ) "
  24.   "Contains all words which will cause the indent-level to be incremented
  25. on the next line.
  26. OBS! All words in sh-mode-positives must be surrounded by spaces.")
  27.  
  28. (defvar sh-mode-negatives
  29.   " fi else elif done esac \;\; ;; "
  30.   "Contains all words which will cause the indent-level to be decremented
  31. on the current line.
  32. OBS! All words in sh-mode-negatives must be surrounded by spaces.")
  33.  
  34. (defvar sh-mode-zeroes
  35.   " #!/bin/sh "
  36.   "Contains all words which causes the indent to go to zero")
  37.  
  38. (defvar sh-mode-abbrev-table nil
  39.   "Abbrev table in use in sh-mode buffers.")
  40.  
  41. (define-abbrev-table 'sh-mode-abbrev-table ())
  42.  
  43. (defvar sh-mode-map nil
  44.   "Keymap used in sh mode.")
  45.  
  46. (if (not sh-mode-map)
  47.     (setq sh-mode-map (make-sparse-keymap)))
  48.  
  49. (define-key sh-mode-map "\t" 'sh-indent-command)
  50. (define-key sh-mode-map "\C-m" 'reindent-then-newline-and-indent)
  51.  
  52. (defvar sh-mode-syntax-table nil
  53.   "Syntax table in use in sh-mode buffers.")
  54.  
  55. (defvar sh-indent-level 2
  56.   "*Indentation of sh statements.")
  57.  
  58. (defun sh-mode-variables ()
  59.   (setq local-abbrev-table sh-mode-abbrev-table)
  60.   (make-local-variable 'indent-line-function)
  61.   (setq indent-line-function 'sh-indent-line)
  62.   (make-local-variable 'require-final-newline)
  63.   (setq require-final-newline t)
  64.   (make-local-variable 'parse-sexp-ignore-comments)
  65.   (setq parse-sexp-ignore-comments t))
  66.   
  67. (defun sh-mode ()
  68.   "Major mode for editing sh scripts.
  69. \\[sh-indent-command] properly indents subexpressions of multi-line
  70. if, while, foreach, and switch statements, taking nesting into account.
  71. Caveats:
  72. The file must start with '#!/bin/sh' for the indentation to start properly.
  73. Extra spaces should be inserted to make sure the indentation algorithm can
  74. figure out what is a keyword, string, etc.  For example, write
  75.     if ($foo == \"bar\")
  76. not
  77.     if($foo==\"bar\")
  78. or later lines may get indented wrong.  (Many lines like this are also
  79. illegal sh code, so this shouldn't cramp your style.)
  80.  
  81. The variable sh-indent-level controls the amount of indentation.
  82. \\{sh-mode-map}"
  83.   (interactive)
  84.   (kill-all-local-variables)
  85.   (use-local-map sh-mode-map)
  86.   (setq mode-name "sh")
  87.   (setq major-mode 'sh-mode)
  88.   (sh-mode-variables)
  89.   (run-hooks 'sh-mode-hook))
  90.  
  91. (defun sh-current-indentation ()
  92.   (save-excursion
  93.     (beginning-of-line)
  94.     (back-to-indentation)
  95.     (current-column)))
  96.  
  97. (defun sh-delete-indentation ()
  98.   (let
  99.       ((b nil)
  100.        (m nil))
  101.     (save-excursion
  102.       (beginning-of-line)
  103.       (setq b (point))
  104.       (back-to-indentation)
  105.       (setq m (point)))
  106.     (delete-region b m)))
  107.  
  108. (defun sh-indent-line (&optional flag)
  109.   "Correct indentation of the current sh line."
  110.   (let
  111.       ((x (sh-calculate-indent)))
  112.     (sh-indent-to x)))
  113.   
  114. (defun sh-indent-command ()
  115.   (interactive)
  116.   (sh-indent-line t))
  117.  
  118. (defun sh-indent-to (x)
  119.   (let
  120.       ((p nil))
  121.     (setq p (- (current-column) (sh-current-indentation)))
  122.     (sh-delete-indentation)
  123.     (beginning-of-line)
  124.     (indent-to x)
  125.     (if (> p 0) (forward-char p))))
  126.  
  127. ;;Calculate indent
  128. (defun sh-calculate-indent ()
  129.   (let ((w1 nil)
  130.     (indent 0)
  131.     (centre 0))
  132.     (save-excursion
  133.       (beginning-of-line)
  134.       (skip-chars-backward " \t\n")
  135.       (beginning-of-line)
  136.       (back-to-indentation)
  137.       (setq indent (current-column))
  138.       (setq centre indent)
  139.       (setq indent (+ indent (sh-sum-line-indentation))))
  140.     (save-excursion
  141.       (beginning-of-line)
  142.       (back-to-indentation)
  143.       (let ((p (point)))
  144.     (skip-chars-forward "^ \t\n")
  145.     (setq w1 (buffer-substring p (point)))))
  146.     (if (> (- indent centre) sh-indent-level)
  147.     (setq indent (+ centre sh-indent-level)))
  148.     (if (> (- centre indent) sh-indent-level)
  149.     (setq indent (- centre sh-indent-level)))
  150.     (if (< indent 0) (setq indent 0))
  151.     (setq indent (- indent
  152.             (if (string-match 
  153.              (regexp-quote (concat " " w1 " "))
  154.              sh-mode-negatives)
  155.             sh-indent-level 0)))
  156.     (if (string-match (regexp-quote (concat " " w1 " ")) sh-mode-zeroes)
  157.     (setq indent 0))
  158.     indent))
  159.  
  160. (defun sh-sum-line-indentation ()
  161.   "Add up the positive and negative weights of all words on the current line."
  162.   (let ((b (point))
  163.     (e nil)
  164.     (sum 0)
  165.     (w nil)
  166.     (t1 nil)
  167.     (t2 nil)
  168.     (first t))
  169.     (end-of-line) (setq e (point))
  170.     (goto-char b)
  171.     (while (< (point) e)
  172.       (setq w (sh-next-word))
  173.       (setq t1 (string-match (regexp-quote (concat " " w " "))
  174.                  sh-mode-positives))
  175.       (setq t2 (string-match (regexp-quote (concat " " w " "))
  176.                  sh-mode-negatives))
  177.       (if (and t1 t2)
  178.       (setq sum (+ sum sh-indent-level)))
  179.       (if t1
  180.       (setq sum (+ sum sh-indent-level)))
  181.       (if (and t2 (not first))
  182.       (setq sum (- sum sh-indent-level)))
  183.       (skip-chars-forward " \t")
  184.       (setq first nil))
  185.     sum))
  186.  
  187. (defun sh-next-word ()
  188.   "Return the next sh-word. Skip anything enclosed in double quotes."
  189.   (let ((w1 nil))
  190.     (while (not w1)
  191.       (skip-chars-forward " \t\n")
  192.       (if (not (looking-at "\""))
  193.       (let ((p (point)))
  194.         (skip-chars-forward "^ \t\n")
  195.         (setq w1 (buffer-substring p (point))))
  196.     (skip-chars-forward "^\"")
  197.     (forward-char 1)))
  198.     w1))
  199.  
  200. -------------- cut here -------------------
  201.  
  202.  
  203.  -----------------------------------------------------------------
  204.   Tom Strong              N3NBB              ts49+@andrew.cmu.edu
  205.