home *** CD-ROM | disk | FTP | other *** search
/ InfoMagic Source Code 1993 July / THE_SOURCE_CODE_CD_ROM.iso / languages / elisp / modes / sh-mode.el < prev    next >
Encoding:
Text File  |  1992-11-25  |  6.0 KB  |  208 lines

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