[Add mozrepl support clinton@unknownlamer.org**20070621090659] { addfile ./site-lisp/moz.el hunk ./site-lisp/moz.el 1 - +;;; moz.el --- Lets current buffer interact with inferior mozilla. + +;; Copyright (C) 2006 by Massimiliano Mirra +;; +;; This program is free software; you can redistribute it and/or modify +;; it under the terms of the GNU General Public License as published by +;; the Free Software Foundation; either version 2 of the License, or +;; (at your option) any later version. +;; +;; This program is distributed in the hope that it will be useful, +;; but WITHOUT ANY WARRANTY; without even the implied warranty of +;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +;; GNU General Public License for more details. +;; +;; You should have received a copy of the GNU General Public License +;; along with this program; if not, write to the Free Software +;; Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +;; +;; Author: Massimiliano Mirra, + +;;; Code: + +(require 'comint) + +(define-minor-mode moz-minor-mode + "Toggle Mozilla mode. +With no argument, this command toggles the mode. +Non-null prefix argument turns on the mode. +Null prefix argument turns off the mode. + +When Mozilla mode is enabled, some commands become available to +send current code area (as understood by c-mark-function) or +region or buffer to an inferior mozilla process (which will be +started as needed)." + nil + " Moz" + '(("\C-c\C-s" . run-mozilla) + ("\C-\M-x" . moz-send-defun) + ("\C-c\C-c" . moz-send-defun-and-go) + ("\C-c\C-r" . moz-send-region) + ("\C-c\C-l" . moz-save-buffer-and-send))) + +(defalias 'run-mozilla 'inferior-moz-switch-to-mozilla) + +(defvar moz-repl-name "repl" + "The current name of the repl.") + +(defvar moz-input-separator "\n--end-remote-input\n") + +(defun moz-temporary-file () + (if (and moz-temporary-file + (file-readable-p moz-temporary-file)) + moz-temporary-file + (setq moz-temporary-file (make-temp-file "emacs-mozrepl")))) + +(defun moz-send-region (start end) + (interactive "r") + (comint-send-string (inferior-moz-process) + (concat moz-repl-name ".pushenv('printPrompt', 'inputMode'); " + moz-repl-name ".setenv('printPrompt', false); " + moz-repl-name ".setenv('inputMode', 'multiline'); " + "undefined; \n")) + ;; Give the previous line a chance to be evaluated on its own. If + ;; it gets concatenated to the following ones, we are doomed. + (sleep-for 0 1) + (comint-send-region (inferior-moz-process) + start end) + (comint-send-string (inferior-moz-process) + "\n--end-remote-input\n") + (comint-send-string (inferior-moz-process) + (concat moz-repl-name ".popenv('inputMode', 'printPrompt'); " + "undefined; \n")) + (comint-send-string (inferior-moz-process) + "\n--end-remote-input\n") + (display-buffer (process-buffer (inferior-moz-process)))) + +(defun moz-send-defun () + (interactive) + (save-excursion + (c-mark-function) + (moz-send-region (point) (mark)))) + +(defun moz-send-defun-and-go () + (interactive) + (moz-send-defun) + (inferior-moz-switch-to-mozilla)) + +(defun moz-save-buffer-and-send () + (interactive) + (save-buffer) + (comint-send-string (inferior-moz-process) + (concat moz-repl-name ".pushenv('printPrompt', 'inputMode'); " + moz-repl-name ".setenv('inputMode', 'line'); " + moz-repl-name ".setenv('printPrompt', false); undefined; ")) + (comint-send-string (inferior-moz-process) + (concat moz-repl-name ".load('file://localhost/" (buffer-file-name) "');\n" + moz-repl-name ".popenv('inputMode', 'printPrompt'); undefined;\n")) + (display-buffer (process-buffer (inferior-moz-process)))) + +;;; Inferior Mode + +(defvar inferior-moz-buffer nil + "The buffer in which the inferior process is running.") + +(define-derived-mode inferior-moz-mode comint-mode "Inf-Mozilla" + "Major mode for interacting with a Mozilla browser." + :syntax-table js-mode-syntax-table + (setq comint-input-sender 'inferior-moz-input-sender) + (define-key inferior-moz-mode-map "\C-cc" (lambda () (interactive) (insert moz-repl-name "."))) + (add-hook 'comint-output-filter-functions 'inferior-moz-track-repl-name nil t)) + +(defun inferior-moz-track-repl-name (comint-output) + (when (string-match "\\(\\w+\\)> $" comint-output) + (setq moz-repl-name (match-string 1 comint-output)))) + +(defun inferior-moz-self-insert-or-repl-name () + (interactive) + (if (looking-back "\\(\\w+\\)> $") + (insert moz-repl-name ".") + (insert last-command-char))) + +(defun inferior-moz-input-sender (proc string) + "Custom function to send input with comint-send-input. +Instead of sending input and newline separately like in +comint-simple-send, here we *first* concatenate input and +newline, then send it all together. This prevents newline to be +interpreted on its own." + (comint-send-string proc (concat string "\n"))) + +(defun inferior-moz-switch-to-mozilla () + "Show the inferior mozilla buffer. Start the process if needed." + (interactive) + (pop-to-buffer (process-buffer (inferior-moz-process))) + (goto-char (process-mark (inferior-moz-process)))) + +(defun inferior-moz-process () + "Return inferior mozilla process. Start it if necessary." + (or (if (buffer-live-p inferior-moz-buffer) + (get-buffer-process inferior-moz-buffer)) + (progn + (inferior-moz-start-process) + (inferior-moz-process)))) + +(defun inferior-moz-start-process () + "Start an inferior mozilla process. +It runs the hook `inferior-moz-hook' after starting the process +and setting up the inferior-mozilla buffer." + (interactive) + (setq inferior-moz-buffer + (apply 'make-comint "Moz" '("localhost" . 4242) nil nil)) + (sleep-for 0 100) + (with-current-buffer inferior-moz-buffer + (inferior-moz-mode) + (run-hooks 'inferior-moz-hook))) + +(provide 'moz) + +;;; moz.el ends here }