/ emacs.d / js-comint.el
js-comint.el
  1  ;;; js-comint.el --- Run javascript in an inferior process window.
  2  
  3  ;;; Copyright (C) 2008 Paul Huff
  4       
  5  ;;; Author: Paul Huff <paul.huff@gmail.com>
  6  ;;; Maintainer: Paul Huff <paul.huff@gmail.com>
  7  ;;; Created: 26 May 2008
  8  ;;; Version: 0.0.1
  9  ;;; Package-Requires: ()
 10  ;;; Keywords: javascript, inferior-mode, convenience
 11  
 12  
 13  ;; js-comint.el is free software; you can redistribute it and/or
 14  ;; modify it under the terms of the GNU General Public License as
 15  ;; published by the Free Software Foundation; either version 2, or
 16  ;; {at your option} any later version.
 17  
 18  ;; js-comint.el is distributed in the hope that it will be useful, but
 19  ;; WITHOUT ANY WARRANTY; without even the implied warranty of
 20  ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
 21  ;; General Public License for more details.
 22  
 23  ;; You should have received a copy of the GNU General Public License
 24  ;; along with GNU Emacs; see the file COPYING, or type `C-h C-c'. If
 25  ;; not, write to the Free Software Foundation at this address:
 26  
 27  ;;   Free Software Foundation
 28  ;;   51 Franklin Street, Fifth Floor
 29  ;;   Boston, MA 02110-1301
 30  ;;   USA
 31  
 32  ;;; Commentary:
 33  ;;; js-comint.el let's you run an inferior javascript process in emacs, 
 34  ;;; and defines a few functions for sending javascript input to it quickly.
 35  
 36  ;;  Usage: 
 37  ;;  Put js-comint.el in your load path
 38  ;;  Add (require 'js-comint) to your .emacs
 39  ;;  Set inferior-js-program-command to the execution command for running your javascript REPL
 40  ;;  (setq inferior-js-program-command "/path/to/executable <args>")
 41  ;;  Do: M-x run-js
 42  ;;  Away you go.
 43  
 44  ;;  I've added the following couple of lines to my .emacs to take advantage of 
 45  ;;  cool keybindings for sending things to the javascript interpreter inside
 46  ;;  of Steve Yegge's most excellent js2-mode.
 47  
 48  ;; (add-hook 'js2-mode-hook '(lambda () 
 49  ;;			    (local-set-key "\C-x\C-e" 'js-send-last-sexp)
 50  ;;			    (local-set-key "\C-\M-x" 'js-send-last-sexp-and-go)
 51  ;;			    (local-set-key "\C-cb" 'js-send-buffer)
 52  ;;			    (local-set-key "\C-c\C-b" 'js-send-buffer-and-go)
 53  ;;			    (local-set-key "\C-cl" 'js-load-file-and-go)
 54  ;;			    ))
 55  
 56  ;;  This is version 0.0.1, so I've only tested it on my own version of emacs which is currently:
 57  ;;  GNU Emacs 22.0.90.1 (i386-apple-darwin8.8.1, Carbon Version 1.6.0) of 2006-10-28
 58  ;;  Not sure if it'll work anywhere else, but it doesn't require anything apple-ish, just emacs-ish.
 59  
 60  ;; Additionally, I've only tested this with rhino.  I'm sure it'll probably work with spidermonkey, 
 61  ;; though if it barfs let me know, and I'll update it.
 62  
 63  ;; I'm a newbie elisper, so please let me know if I'm a. doing things the wrong way, b.
 64  ;; making things work they way they shouldn't in the elisp world.
 65  
 66  ;;; History:
 67  ;;
 68  
 69  ;;; Code:
 70  
 71  (require 'comint)
 72  
 73  (provide 'js-comint)
 74  
 75  (defcustom inferior-js-program-command "/usr/bin/java org.mozilla.javascript.tools.shell.Main" "Path to the javascript interpreter")
 76  
 77  (defgroup inferior-js nil
 78    "Run a javascript process in a buffer."
 79    :group 'inferior-js)
 80  
 81  (defcustom inferior-js-mode-hook nil
 82    "*Hook for customizing inferior-js mode."
 83    :type 'hook
 84    :group 'inferior-js)
 85  
 86  ;;;###autoload
 87  (defun run-js (cmd &optional dont-switch-p)
 88    "Run an inferior Javascript process, input and output via buffer `*js*'.
 89  If there is a process already running in `*js*', switch to that buffer.
 90  With argument, allows you to edit the command line (default is value
 91  of `inferior-js-program-command').
 92  Runs the hook `inferior-js-mode-hook' \(after the `comint-mode-hook'
 93  is run).
 94  \(Type \\[describe-mode] in the process buffer for a list of commands.)"
 95  
 96    (interactive (list (if current-prefix-arg
 97  			 (read-string "Run js: " inferior-js-program-command)
 98  			 inferior-js-program-command)))
 99    (if (not (comint-check-proc "*js*"))
100        (save-excursion (let ((cmdlist (split-string cmd)))
101  	(set-buffer (apply 'make-comint "js" (car cmdlist)
102  			   nil (cdr cmdlist)))
103  	(inferior-js-mode))))
104    (setq inferior-js-program-command cmd)
105    (setq inferior-js-buffer "*js*")
106    (if (not dont-switch-p)
107        (pop-to-buffer "*js*")))
108  
109  ;;;###autoload
110  (defun js-send-region (start end)
111    "Send the current region to the inferior Javascript process."
112    (interactive "r")
113    (run-js inferior-js-program-command t)
114    (comint-send-region inferior-js-buffer start end)
115    (comint-send-string inferior-js-buffer "\n"))
116  
117  ;;;###autoload
118  (defun js-send-region-and-go (start end)
119    "Send the current region to the inferior Javascript process."
120    (interactive "r")
121    (run-js inferior-js-program-command t)
122    (comint-send-region inferior-js-buffer start end)
123    (comint-send-string inferior-js-buffer "\n")
124    (switch-to-js inferior-js-buffer))
125  
126  ;;;###autoload
127  (defun js-send-last-sexp-and-go ()
128    "Send the previous sexp to the inferior Js process."
129    (interactive)
130    (js-send-region-and-go (save-excursion (backward-sexp) (point)) (point)))
131  
132  ;;;###autoload
133  (defun js-send-last-sexp ()
134    "Send the previous sexp to the inferior Javascript process."
135    (interactive)
136    (js-send-region (save-excursion (backward-sexp) (point)) (point)))
137  
138  ;;;###autoload
139  (defun js-send-buffer ()
140    "Send the buffer to the inferior Javascript process."
141    (interactive)
142    (js-send-region (point-min) (point-max)))
143  
144  
145  ;;;###autoload
146  (defun js-send-buffer-and-go ()
147    "Send the buffer to the inferior Javascript process."
148    (interactive)
149    (js-send-region-and-go (point-min) (point-max)))
150  
151  ;;;###autoload
152  (defun js-load-file (filename)
153    "Load a file in the javascript interpreter."
154    (interactive "f")
155    (let ((filename (expand-file-name filename)))
156      (run-js inferior-js-program-command t)
157      (comint-send-string inferior-js-buffer (concat "load(\"" filename "\")\n"))))
158  
159  ;;;###autoload
160  (defun js-load-file-and-go (filename)
161    "Load a file in the javascript interpreter."
162    (interactive "f")
163    (let ((filename (expand-file-name filename)))
164      (run-js inferior-js-program-command t)
165      (comint-send-string inferior-js-buffer (concat "load(\"" filename "\")\n"))
166      (switch-to-js inferior-js-buffer)))
167  
168  ;;;###autoload
169  (defun switch-to-js (eob-p)
170    "Switch to the javascript process buffer.
171  With argument, position cursor at end of buffer."
172    (interactive "P")
173    (if (or (and inferior-js-buffer (get-buffer inferior-js-buffer))
174            (js-interactively-start-process))
175        (pop-to-buffer inferior-js-buffer)
176      (error "No current process buffer.  See variable `inferior-js-buffer'"))
177    (when eob-p
178      (push-mark)
179      (goto-char (point-max))))
180  
181  (defvar inferior-js-buffer)
182  
183  (defvar inferior-js-mode-map
184    (let ((m (make-sparse-keymap)))
185      (define-key m "\C-x\C-e" 'js-send-last-sexp)
186      (define-key m "\C-cl" 'js-load-file)
187      m))
188  
189  ;;;###autoload
190  (define-derived-mode inferior-js-mode comint-mode "Inferior Javascript"
191    "Major mode for interacting with an inferior javascript process.
192  
193  The following commands are available:
194  \\{inferior-js-mode-map}
195  
196  A javascript process can be fired up with M-x run-js.
197  
198  Customization: Entry to this mode runs the hooks on comint-mode-hook and
199  inferior-js-mode-hook (in that order).
200  
201  You can send text to the inferior Javascript process from othber buffers containing
202  Javascript source.
203      switch-to-js switches the current buffer to the Javascript process buffer.
204      js-send-region sends the current region to the Javascript process.
205  
206  
207  "
208  (use-local-map inferior-js-mode-map)
209  )