Annotation of mdee/xpcshell.el, revision 1.1.1.1

1.1       kevin       1: ;;; xpcshell.el --- Mozilla xpcshell integration for Emacs.
                      2: 
                      3: ;; $Id: xpcshell.el,v 1.2 2003/01/14 10:22:50 burton Exp $
                      4: 
                      5: ;; Copyright (C) 2000-2003 Free Software Foundation, Inc.
                      6: ;; Copyright (C) 2000-2003 Kevin A. Burton (burton@openprivacy.org)
                      7: 
                      8: ;; Author: Kevin A. Burton (burton@openprivacy.org)
                      9: ;; Maintainer: Kevin A. Burton (burton@openprivacy.org)
                     10: ;; Location: http://relativity.yi.org
                     11: ;; Keywords: 
                     12: ;; Version: 1.0.0
                     13: 
                     14: ;; This file is [not yet] part of GNU Emacs.
                     15: 
                     16: ;; This program is free software; you can redistribute it and/or modify it under
                     17: ;; the terms of the GNU General Public License as published by the Free Software
                     18: ;; Foundation; either version 2 of the License, or any later version.
                     19: ;;
                     20: ;; This program is distributed in the hope that it will be useful, but WITHOUT
                     21: ;; ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
                     22: ;; FOR A PARTICULAR PURPOSE.  See the GNU General Public License for more
                     23: ;; details.
                     24: ;;
                     25: ;; You should have received a copy of the GNU General Public License along with
                     26: ;; this program; if not, write to the Free Software Foundation, Inc., 59 Temple
                     27: ;; Place - Suite 330, Boston, MA 02111-1307, USA.
                     28: 
                     29: ;;; Commentary:
                     30: ;;
                     31: ;; Mozilla xpcshell javascript interpreter shell implementation.
                     32: 
                     33: ;; NOTE: If you enjoy this software, please consider a donation to the EFF
                     34: ;; (http://www.eff.org)
                     35: 
                     36: ;;; Code:
                     37: 
                     38: ;;FIXME: we should try to find out if this is in the PATH or default to
                     39: ;;/usr/lib/mozilla/xpcshell or test other locations.
                     40: (defcustom xpcshell-shell-command "xpcshell"
                     41:   "Command to use to execute xpcshell."
                     42:   :type 'string
                     43:   :group 'xpcshell)
                     44: 
                     45: ;;do some sanity checks on xpcshell-shell-command to see if we have a better
                     46: ;;place for it
                     47: 
                     48: (defcustom xpcshell-shell-command-args  '()
                     49:   "*Command line arguments for `xpcshell-shell-command'."
                     50:   :type '(repeat (string :tag "Argument"))
                     51:   :group 'xpcshell)
                     52: 
                     53: (defcustom xpcshell-shell-prompt-pattern "^js> *"
                     54:   "*xpcshell shell prompt pattern."
                     55:   :type 'regexp
                     56:   :group 'xpcshell)
                     57: 
                     58: (defcustom xpcshell-shell-mode-hook nil
                     59:   "Hook for customizing `xpcshell-shell-mode'."
                     60:   :type 'hook
                     61:   :group 'xpcshell)
                     62: 
                     63: (defcustom xpcshell-init-on-startup nil
                     64:   "When enabled we will startup xpcshell when Emacs starts up.  This is a nice
                     65: feature because this allows us to be certain that the xpcshell is always running
                     66: and since it is mostly async code we don't have much of a performance hit."
                     67:   :type 'boolean
                     68:   :group 'xpcshell)
                     69: 
                     70: (defcustom xpcshell-suppress-function-bodies t
                     71:   "*When enabled we will replace function body definitions with ... bodies so
                     72: that the xpcshell output isn't as verbose."
                     73:   :type 'boolean
                     74:   :group 'xpcshell)
                     75: 
                     76: (defvar xpcshell-buffer-name "*xpcshell*" "Temp buffer name for xpcshell.")
                     77: 
                     78: (defun xpcshell()
                     79:   "Mozilla xpcshell integration."
                     80: 
                     81:   (interactive)
                     82: 
                     83:   ;;make sure we init required environment variables under Linux
                     84:   (dolist(var '("LD_LIBRARY_PATH" "MOZILLA_FIVE_HOME"))
                     85:     (when (null (getenv var))
                     86:       (setenv var (file-name-directory xpcshell-shell-command))))
                     87: 
                     88:   ;;FIXME: become much smarter to verify that the 'xpcshell' command can be
                     89:   ;;executed.  Also check the PATH to see if it is there too.
                     90:   
                     91:   (unless (comint-check-proc xpcshell-buffer-name)
                     92: 
                     93:     (set-buffer (get-buffer-create xpcshell-buffer-name))
                     94:     
                     95:     ;;use the default directory of xpcshell for all new shells so we can
                     96:     ;;have a chance to load .js files
                     97:     (let((default-directory (file-name-directory (locate-library "xpcshell"))) )
                     98:       (apply 'make-comint "xpcshell"
                     99:              xpcshell-shell-command nil xpcshell-shell-command-args))
                    100:     
                    101:     (xpcshell-shell-mode))
                    102: 
                    103:   (display-buffer xpcshell-buffer-name)
                    104:   (set-window-point (get-buffer-window xpcshell-buffer-name)
                    105:                     (save-excursion
                    106:                       (set-buffer xpcshell-buffer-name)
                    107:                       (point-max))))
                    108: 
                    109: (defun xpcshell-shell-mode ()
                    110:   "Major mode for interacting with a xpcshell shell."
                    111:   (comint-mode)
                    112:   (setq comint-prompt-regexp xpcshell-shell-prompt-pattern)
                    113:   (setq major-mode 'xpcshell-shell-mode)
                    114:   (setq mode-name "xpcshell")
                    115:   (setq mode-line-process '(":%s"))
                    116:   (run-hooks 'xpcshell-shell-mode-hook))
                    117: 
                    118: (defun xpcshell-eval-region(begin end)
                    119:   "Evaluate the region in the xpcshell.  See `eval-region' for an example in
                    120: lisp."
                    121:   (interactive "r")
                    122: 
                    123:   (xpcshell-eval-string (buffer-substring-no-properties begin end)))
                    124: 
                    125: (defun xpcshell-eval-string(string)
                    126:   "Evaluate the region in the xpcshell.  See `eval-region' for an example in
                    127: lisp."
                    128:   (interactive
                    129:    (read-string "Eval javascript: "))
                    130:   
                    131:   (let* ((process (get-process "xpcshell"))
                    132:          (comint-eol-on-send nil)
                    133:          (point-at-end-before-eval nil) ;;the point at the end of the buffer before we eval
                    134:          (temp-file (make-temp-file "xpcshell"))
                    135:          (comint-process-echoes nil))
                    136: 
                    137:     ;;FIXME: the default directory hack is not working 
                    138:     
                    139:     ;;make the region one long string so that multiple shell prompts aren't issued
                    140: 
                    141:     ;;get rid of comments... 
                    142: 
                    143:     ;;try to startup the xpcshell
                    144:     (when (not process)
                    145:       (xpcshell))
                    146:     
                    147:     (if process
                    148:         (save-excursion
                    149:           (set-buffer (process-buffer process))
                    150:           (goto-char (point-max))
                    151: 
                    152:           (setq point-at-end-before-eval (point-max))
                    153: 
                    154:           ;;write out the temp file
                    155:           (save-excursion
                    156:             (set-buffer (get-buffer-create "*temp*"))
                    157:             (insert string)
                    158: 
                    159:             (write-region (point-min) (point-max) temp-file nil 'no-wrote)
                    160:           
                    161:             (kill-buffer (current-buffer)))
                    162:         
                    163:           (comint-send-string process (format "load( \"%s\");" temp-file))
                    164:           (call-interactively 'comint-send-input)
                    165: 
                    166:           (if (not (accept-process-output process 10 100))
                    167:               (error "No reply from xpcshell"))
                    168: 
                    169:           ;;we should be using a process sentinel
                    170:           (xpcshell-cleanup-prompts point-at-end-before-eval
                    171:                                     (point-max))
                    172: 
                    173:           ;;remove the temp file?
                    174:           (delete-file temp-file)
                    175:         
                    176:           (goto-char (point-max))
                    177:         
                    178:           ;;go back to the xpcshell buffer
                    179:           (xpcshell))
                    180:       (error "xpcshell process not running"))))
                    181: 
                    182: (defun xpcshell-cleanup-prompts(begin end)
                    183:   "Given a region, clean up the extra prompts within it.  This is necessary
                    184: because the xpcshell process will echo a 'js> ' prompt for every variable or
                    185: function we declare.  For large files this will result in a long string of
                    186: repeated prompts which is annoying (we really only want one)."
                    187:   (interactive "r")
                    188: 
                    189:   (let((prompt-pattern "js> "))
                    190: 
                    191:     ;;cleanup function bodies
                    192:     (when xpcshell-suppress-function-bodies
                    193:       (save-excursion
                    194:         (goto-char begin)
                    195:         
                    196:         (while (re-search-forward "^function .*$" nil t)
                    197:           (let((function-end (match-end 0)))
                    198:             (when (re-search-forward prompt-pattern nil t)
                    199:               (save-excursion
                    200:                 (goto-char function-end)
                    201:                 
                    202:                 (insert " ... }")
                    203:                 
                    204:                 (delete-region (+ 6 function-end) (match-end 0))
                    205:                 
                    206:                 ))))))
                    207: 
                    208:     ;;clean up js prompts
                    209:     (save-excursion
                    210: 
                    211:       ;;find the bounds off our cleanup
                    212:       (goto-char end)
                    213:       (when (re-search-backward prompt-pattern begin t)
                    214:         (save-restriction
                    215: 
                    216:           (narrow-to-region begin
                    217:                             (match-beginning 0))
                    218: 
                    219:           ;;now search from the beginning to the bounds replaceing the prompts
                    220:           (goto-char (point-min))
                    221: 
                    222:           (while (re-search-forward prompt-pattern nil t)
                    223:             (replace-match "")))))))
                    224: 
                    225: (defun xpcshell-eval-buffer(&optional buffer)
                    226:   "Evaluate the current buffer."
                    227:   (interactive)
                    228: 
                    229:   (when (null buffer)
                    230:     (setq buffer (current-buffer)))
                    231: 
                    232:   (xpcshell-eval-region (point-min) (point-max)))
                    233: 
                    234: (defun xpcshell-emacs-startup-hook()
                    235:   "Perform all operations we need on emacs startup."
                    236:   
                    237:   (when xpcshell-init-on-startup
                    238:     (save-window-excursion
                    239:       (xpcshell))))
                    240: 
                    241: ;;add support for javascript mode style eval like in lisp-interaction-mode
                    242: (when (boundp 'javascript-mode-map)
                    243:   (define-key javascript-mode-map [?\C-c?\C-e] 'xpcshell-eval-buffer))
                    244: 
                    245: ;;add ECB compilation buffer suppprt
                    246: (when (boundp 'ecb-compilation-buffer-names)
                    247:   (add-to-list 'ecb-compilation-buffer-names (cons xpcshell-buffer-name nil)))
                    248: 
                    249: (add-hook 'emacs-startup-hook 'xpcshell-emacs-startup-hook)
                    250: 
                    251: (provide 'xpcshell)
                    252: 
                    253: ;;; xpcshell.el ends here

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>