home *** CD-ROM | disk | FTP | other *** search
/ InfoMagic Source Code 1993 July / THE_SOURCE_CODE_CD_ROM.iso / gnu / lucid / lemacs-19.6 / lisp / modes / postscript.el < prev    next >
Encoding:
Text File  |  1992-09-08  |  8.2 KB  |  254 lines

  1. ;; Major mode for editing PostScript programs.
  2. ;;
  3. ;; Author:    Chris Maio
  4. ;; Last edit:    4 Sep 1988
  5. ;; Includes patches from relph@presto.ig.com (John M. Relph) posted to
  6. ;; gnu.emacs.sources on 22 Nov 90 04:53:43 GMT.
  7. ;;
  8. ;; The following two statements, placed in your .emacs file or site-init.el,
  9. ;; will cause this file to be autoloaded, and postscript-mode invoked, when
  10. ;; visiting .ps or .cps files:
  11. ;;
  12. ;;    (autoload 'postscript-mode "postscript.el" "" t)
  13. ;;    (setq auto-mode-alist
  14. ;;          (cons '("\\.c?ps$".postscript-mode) auto-mode-alist))
  15. ;;
  16.  
  17. (provide 'postscript)
  18.  
  19. (defconst ps-indent-level 2
  20.   "*Indentation to be used inside of PostScript blocks or arrays")
  21.  
  22. (defconst ps-tab-width 8
  23.   "*Tab stop width for PostScript mode")
  24.  
  25. (defun ps-make-tabs (stop)
  26.   (and (< stop 132) (cons stop (ps-make-tabs (+ stop ps-tab-width)))))
  27.  
  28. (defconst ps-tab-stop-list (ps-make-tabs ps-tab-width)
  29.   "*Tab stop list for PostScript mode")
  30.  
  31. (defconst ps-postscript-command "gs -"
  32.   "*Command used to invoke with a printer spooler or NeWS server.")
  33.  
  34. (defvar ps-mode-map nil
  35.   "Keymap used in PostScript mode buffers")
  36.  
  37. (defvar ps-mode-syntax-table nil
  38.   "PostScript mode syntax table")
  39.  
  40. (defun postscript-mode nil
  41.   "Major mode for editing PostScript files.
  42.  
  43. \\[ps-execute-buffer] will send the contents of the buffer to the NeWS
  44. server using psh(1).  \\[ps-execute-region] sends the current region.
  45. \\[ps-shell] starts an interactive psh(1) window which will be used for
  46. subsequent \\[ps-execute-buffer] or \\[ps-execute-region] commands.
  47.  
  48. In this mode, TAB and \\[indent-region] attempt to indent code
  49. based on the position of {}, [], and begin/end pairs.  The variable
  50. ps-indent-level controls the amount of indentation used inside
  51. arrays and begin/end pairs.  
  52.  
  53. \\{ps-mode-map}
  54.  
  55. \\[postscript-mode] calls the value of the variable postscript-mode-hook 
  56. with no args, if that value is non-nil."
  57.   (interactive)
  58.   (kill-all-local-variables)
  59.   (use-local-map ps-mode-map)
  60.   (if ps-mode-syntax-table
  61.       (set-syntax-table ps-mode-syntax-table)
  62.       (progn
  63.     (setq ps-mode-syntax-table (make-syntax-table))
  64.     (set-syntax-table ps-mode-syntax-table)
  65.     (modify-syntax-entry ?\( "(")
  66.     (modify-syntax-entry ?\) ")")
  67.     ;(modify-syntax-entry ?\( "<")
  68.     ;(modify-syntax-entry ?\) ">")
  69.     (modify-syntax-entry ?\[ "(\]")
  70.     (modify-syntax-entry ?\] ")\[")
  71.     (modify-syntax-entry ?\% "<")
  72.     (modify-syntax-entry ?\n ">")))
  73.   (make-local-variable 'comment-start)
  74.   (make-local-variable 'comment-start-skip)
  75.   (make-local-variable 'comment-column)
  76.   (make-local-variable 'indent-line-function)
  77.   (make-local-variable 'tab-stop-list)
  78.   (make-local-variable 'page-delimiter)
  79.   (setq comment-start "% "
  80.     comment-start-skip "% *"
  81.     comment-column 40
  82.     indent-line-function 'ps-indent-line
  83.     page-delimiter "^showpage"
  84.     tab-stop-list ps-tab-stop-list)
  85.   (setq mode-name "PostScript")
  86.   (setq major-mode 'postscript-mode)
  87.   (run-hooks 'ps-mode-hook) ; bad name!  Kept for compatibility.
  88.   (run-hooks 'postscript-mode-hook)
  89.   )
  90.  
  91. (defun ps-tab ()
  92.   "Command assigned to the TAB key in PostScript mode."
  93.   (interactive)
  94.   (if (save-excursion (skip-chars-backward " \t") (bolp))
  95.       (ps-indent-line)
  96.     (save-excursion
  97.       (ps-indent-line))))
  98.  
  99. (defun ps-indent-line nil
  100.   "Indents a line of PostScript code."
  101.   (interactive)
  102.   (beginning-of-line)
  103.   (delete-horizontal-space)
  104.   (if (not (or (looking-at "%%")    ; "%%" comments stay at left margin
  105.            (ps-top-level-p)))
  106.       (if (and (< (point) (point-max))
  107.            (eq ?\) (char-syntax (char-after (point)))))
  108.       (ps-indent-close)        ; indent close-delimiter
  109.     (if (looking-at "\\(dict\\|class\\)?end\\|cdef\\|grestore")
  110.         (ps-indent-end)        ; indent end token
  111.       (ps-indent-in-block)))))    ; indent line after open delimiter
  112.   
  113. (defun ps-open nil
  114.   (interactive)
  115.   (insert last-command-char))
  116.  
  117. (defun ps-insert-d-char (arg)
  118.   "Awful hack to make \"end\" and \"cdef\" keywords indent themselves."
  119.   (interactive "p")
  120.   (insert-char last-command-char arg)
  121.   (save-excursion
  122.     (beginning-of-line)
  123.     (if (looking-at "^[ \t]*\\(\\(dict\\|class\\)?end\\|cdef\\|grestore\\)")
  124.     (progn
  125.       (delete-horizontal-space)
  126.       (ps-indent-end)))))
  127.  
  128. (defun ps-close nil
  129.   "Inserts and indents a close delimiter."
  130.   (interactive)
  131.   (insert last-command-char)
  132.   (backward-char 1)
  133.   (ps-indent-close)
  134.   (forward-char 1)
  135.   (blink-matching-open))
  136.  
  137. (defun ps-indent-close nil
  138.   "Internal function to indent a line containing a an array close delimiter."
  139.   (if (save-excursion (skip-chars-backward " \t") (bolp))
  140.       (let (x (oldpoint (point)))
  141.     (forward-char) (backward-sexp)    ;XXX
  142.     (if (and (eq 1 (count-lines (point) oldpoint))
  143.          (> 1 (- oldpoint (point))))
  144.         (goto-char oldpoint)
  145.       (beginning-of-line)
  146.       (skip-chars-forward " \t")
  147.       (setq x (current-column))
  148.       (goto-char oldpoint)
  149.       (delete-horizontal-space)
  150.       (indent-to x)))))
  151.  
  152. (defun ps-indent-end nil
  153.   "Indent an \"end\" token or array close delimiter."
  154.   (let ((goal (ps-block-start)))
  155.     (if (not goal)
  156.     (indent-relative)
  157.       (setq goal (save-excursion
  158.            (goto-char goal) (back-to-indentation) (current-column)))
  159.       (indent-to goal))))
  160.  
  161. (defun ps-indent-in-block nil
  162.   "Indent a line which does not open or close a block."
  163.   (let ((goal (ps-block-start)))
  164.     (setq goal (save-excursion
  165.          (goto-char goal)
  166.          (back-to-indentation)
  167.          (if (bolp)
  168.              ps-indent-level
  169.            (back-to-indentation)
  170.            (+ (current-column) ps-indent-level))))
  171.     (indent-to goal)))
  172.  
  173. ;;; returns nil if at top-level, or char pos of beginning of current block
  174.  
  175. (defun ps-block-start nil
  176.   "Returns the character position of the character following the nearest
  177. enclosing `[' `{' or `begin' keyword."
  178.   (save-excursion
  179.     (let (open (skip 0))
  180.       (setq open (condition-case nil
  181.              (save-excursion
  182.                (backward-up-list 1)
  183.                (1+ (point)))
  184.            (error nil)))
  185.       (ps-begin-end-hack open))))
  186.  
  187. (defun ps-begin-end-hack (start)
  188.   "Search backwards from point to START for enclosing `begin' and returns the
  189. character number of the character following `begin' or START if not found."
  190.   (save-excursion
  191.     (let ((depth 1) match)
  192.       (while (and (> depth 0)
  193.           (or (re-search-backward
  194.  "^[ \t]*\\(dict\\|class\\)?\\(end\\|grestore\\)\\|\\(begin\\|gsave\\)[ \t]*\\(%.*\\)*$" start t)
  195.               (re-search-backward "^[ \t]*cdef.*$" start t)))
  196.      (setq depth (if (looking-at "[ \t]*\\(dict\\|class\\)?\\(end\\|grestore\\)")
  197.             (1+ depth) (1- depth))))
  198.       (if (not (eq 0 depth))
  199.       start
  200.     (forward-word 1)
  201.     (point)))))
  202.  
  203. (defun ps-top-level-p nil
  204.   "Awful test to see whether we are inside some sort of PostScript block."
  205.   (and (condition-case nil
  206.        (not (scan-lists (point) -1 1))
  207.      (error t))
  208.        (not (ps-begin-end-hack nil))))
  209.  
  210. ;;; initialize the keymap if it doesn't already exist
  211. (if (null ps-mode-map)
  212.     (progn
  213.       (setq ps-mode-map (make-sparse-keymap))
  214.       (define-key ps-mode-map "d" 'ps-insert-d-char)
  215.       (define-key ps-mode-map "f" 'ps-insert-d-char)
  216.       (define-key ps-mode-map "{" 'ps-open)
  217.       (define-key ps-mode-map "}" 'ps-close)
  218.       (define-key ps-mode-map "[" 'ps-open)
  219.       (define-key ps-mode-map "]" 'ps-close)
  220.       (define-key ps-mode-map "\t" 'ps-tab)
  221.       (define-key ps-mode-map "\C-c\C-c" 'ps-execute-buffer)
  222.       (define-key ps-mode-map "\C-c|" 'ps-execute-region)
  223.       (define-key ps-mode-map "\C-c!" 'ps-shell)))
  224.  
  225. (defun ps-execute-buffer nil
  226.   "Send the contents of the buffer to a printer or NeWS server."
  227.   (interactive)
  228.   (save-excursion
  229.     (mark-whole-buffer)
  230.     (ps-execute-region (point-min) (point-max))))
  231.  
  232. (defun ps-execute-region (start end)
  233.   "Send the region between START and END to a printer or NeWS server.
  234. You should kill any existing *PostScript* buffer unless you want the
  235. PostScript text to be executed in that process."
  236.   (interactive "r")
  237.   (let ((start (min (point) (mark)))
  238.     (end (max (point) (mark))))
  239.     (condition-case nil
  240.     (process-send-string "PostScript" (buffer-substring start end))
  241.       (error (shell-command-on-region start end ps-postscript-command nil)))))
  242.  
  243. (defun ps-shell nil
  244.   "Start a shell communicating with a PostScript printer or NeWS server."
  245.   (interactive)
  246.   (require 'shell)
  247.   (switch-to-buffer-other-window
  248.     (make-shell "PostScript" ps-postscript-command))
  249.   (make-local-variable 'shell-prompt-pattern)
  250. ;  (setq shell-prompt-pattern "PS>")
  251.   (setq shell-prompt-pattern "GS>")
  252. ;  (process-send-string "PostScript" "executive\n")
  253.   )
  254.