|
|
;;; haskell-bot.el --- A Lambdabot interaction mode -*- lexical-binding: t -*- |
|
|
|
|
|
;; Copyright (C) 2004, 2005, 2006, 2007 Free Software Foundation, Inc. |
|
|
;; Copyright (C) 2001 Chris Webb |
|
|
;; Copyright (C) 1998, 1999 Guy Lapalme |
|
|
|
|
|
;; Keywords: inferior mode, Bot interaction mode, Haskell |
|
|
|
|
|
;;; This file is not part of GNU Emacs. |
|
|
|
|
|
;; This file 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 3, or (at your option) |
|
|
;; any later version. |
|
|
|
|
|
;; This file 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 GNU Emacs; see the file COPYING. If not, write to the |
|
|
;; Free Software Foundation, Inc., 59 Temple Place - Suite 330, |
|
|
;; Boston, MA 02111-1307, USA. |
|
|
|
|
|
|
|
|
;;; Commentary: |
|
|
|
|
|
;; Purpose: |
|
|
;; |
|
|
;; To send a Haskell buffer to another buffer running a Bot |
|
|
;; interpreter. |
|
|
;; |
|
|
;; This mode is derived from version 1.1 of Guy Lapalme's |
|
|
;; haskell-hugs.el, which can be obtained from: |
|
|
;; |
|
|
;; http://www.iro.umontreal.ca/~lapalme/Hugs-interaction.html |
|
|
;; |
|
|
;; This in turn was adapted from Chris Van Humbeeck's hugs-mode.el, |
|
|
;; which can be obtained from: |
|
|
;; |
|
|
;; http://www-i2.informatik.rwth-aachen.de/Forschung/FP/Haskell/hugs-mode.el |
|
|
;; |
|
|
;; |
|
|
;; Installation: |
|
|
;; |
|
|
;; To use with Moss and Thorn's haskell-mode.el |
|
|
;; |
|
|
;; http://www.haskell.org/haskell-mode |
|
|
;; |
|
|
;; add this to .emacs: |
|
|
;; |
|
|
;; (add-hook 'haskell-mode-hook 'haskell-bot-mode) |
|
|
;; |
|
|
;; |
|
|
;; Customisation: |
|
|
;; |
|
|
;; The name of the Bot interpreter is in haskell-bot-program-name. |
|
|
;; |
|
|
;; Arguments can be sent to the Bot interpreter when it is started by |
|
|
;; setting haskell-bot-program-args (empty by default) to a list of |
|
|
;; string args to pass it. This value can be set interactively by |
|
|
;; calling C-c C-s with an argument (i.e. C-u C-c C-s). |
|
|
;; |
|
|
;; `haskell-bot-hook' is invoked in the *bot* buffer once Bot is |
|
|
;; started. |
|
|
;; |
|
|
;; All functions/variables start with `turn-{on,off}-haskell-bot' or |
|
|
;; `haskell-bot-'. |
|
|
|
|
|
;;; Code: |
|
|
|
|
|
(require 'comint) |
|
|
|
|
|
;;;###autoload |
|
|
(defgroup haskell-bot nil |
|
|
"Major mode for interacting with an inferior Bot session." |
|
|
:group 'haskell |
|
|
:prefix "haskell-bot-") |
|
|
|
|
|
(define-derived-mode haskell-bot-mode comint-mode "Lambdabot") |
|
|
|
|
|
;; Bot interface: |
|
|
|
|
|
(require 'comint) |
|
|
(require 'shell) |
|
|
|
|
|
(defvar haskell-bot-process nil |
|
|
"The active Bot subprocess corresponding to current buffer.") |
|
|
|
|
|
(defvar haskell-bot-process-buffer nil |
|
|
"*Buffer used for communication with Bot subprocess for current buffer.") |
|
|
|
|
|
;;;###autoload |
|
|
(defcustom haskell-bot-program-name "lambdabot" |
|
|
"*The name of the Bot interpreter program." |
|
|
:type 'string |
|
|
:group 'haskell-bot) |
|
|
|
|
|
;;;###autoload |
|
|
(defcustom haskell-bot-program-args nil |
|
|
"*A list of string args to pass when starting the Bot interpreter." |
|
|
:type '(repeat string) |
|
|
:group 'haskell-bot) |
|
|
|
|
|
(defvar haskell-bot-load-end nil |
|
|
"Position of the end of the last load command.") |
|
|
|
|
|
(defvar haskell-bot-error-pos nil |
|
|
"Position of the end of the last load command.") |
|
|
|
|
|
(defvar haskell-bot-send-end nil |
|
|
"Position of the end of the last send command.") |
|
|
|
|
|
(defvar haskell-bot-comint-prompt-regexp |
|
|
"^lambdabot> " |
|
|
"A regexp that matches the Bot prompt.") |
|
|
|
|
|
(defun haskell-bot-start-process (arg) |
|
|
"Start a Bot process and invoke `haskell-bot-hook' if not nil. |
|
|
Prompt for a list of args if called with an argument." |
|
|
(interactive "P") |
|
|
(if arg |
|
|
;; XXX [CDW] Fix to use more natural 'string' version of the |
|
|
;; XXX arguments rather than a sexp. |
|
|
(setq haskell-bot-program-args |
|
|
(read-minibuffer (format "List of args for %s:" |
|
|
haskell-bot-program-name) |
|
|
(prin1-to-string haskell-bot-program-args)))) |
|
|
|
|
|
;; Start the Bot process in a new comint buffer. |
|
|
(message "Starting Lambdabot process `%s'." haskell-bot-program-name) |
|
|
(setq haskell-bot-process-buffer |
|
|
(apply 'make-comint |
|
|
"lambdabot" haskell-bot-program-name nil |
|
|
haskell-bot-program-args)) |
|
|
(setq haskell-bot-process |
|
|
(get-buffer-process haskell-bot-process-buffer)) |
|
|
|
|
|
;; Select Bot buffer temporarily. |
|
|
(set-buffer haskell-bot-process-buffer) |
|
|
(haskell-bot-mode) |
|
|
(setq comint-prompt-regexp haskell-bot-comint-prompt-regexp) |
|
|
|
|
|
;; History syntax of comint conflicts with Haskell, e.g. !!, so better |
|
|
;; turn it off. |
|
|
(setq comint-input-autoexpand nil) |
|
|
(setq comint-process-echoes nil) |
|
|
(run-hooks 'haskell-bot-hook) |
|
|
|
|
|
;; Clear message area. |
|
|
(message "")) |
|
|
|
|
|
(defun haskell-bot-wait-for-output () |
|
|
"Wait until output arrives and go to the last input." |
|
|
(while (progn |
|
|
(goto-char comint-last-input-end) |
|
|
(not (re-search-forward comint-prompt-regexp nil t))) |
|
|
(accept-process-output haskell-bot-process))) |
|
|
|
|
|
(defun haskell-bot-send (&rest string) |
|
|
"Send `haskell-bot-process' the arguments (one or more strings). |
|
|
A newline is sent after the strings and they are inserted into the |
|
|
current buffer after the last output." |
|
|
(haskell-bot-wait-for-output) ; wait for prompt |
|
|
(goto-char (point-max)) ; position for this input |
|
|
(apply 'insert string) |
|
|
(comint-send-input) |
|
|
(setq haskell-bot-send-end (marker-position comint-last-input-end))) |
|
|
|
|
|
(defun haskell-bot-show-bot-buffer () |
|
|
"Go to the *bot* buffer." |
|
|
(interactive) |
|
|
(if (or (not haskell-bot-process-buffer) |
|
|
(not (buffer-live-p haskell-bot-process-buffer))) |
|
|
(haskell-bot-start-process nil)) |
|
|
(pop-to-buffer haskell-bot-process-buffer)) |
|
|
|
|
|
(provide 'haskell-bot) |
|
|
|
|
|
;;; haskell-bot.el ends here
|
|
|
|