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 )