X-Git-Url: https://cgit.sxemacs.org/?p=riece;a=blobdiff_plain;f=lisp%2Friece-ruby.el;h=26b0f0411e3f64ca13e183e316823a3e266ae00b;hp=a0006e44be2e37e3b6425ed5d8db5ec085f7d5d0;hb=3a53a2588a8095152dffbc9ccc37fd0446212333;hpb=ea8c164a707eb049ec18cc4564e9ebdb114a026e diff --git a/lisp/riece-ruby.el b/lisp/riece-ruby.el index a0006e4..26b0f04 100644 --- a/lisp/riece-ruby.el +++ b/lisp/riece-ruby.el @@ -1,4 +1,4 @@ -;;; riece-ruby.el --- interact with ruby interpreter +;;; riece-ruby.el --- interact with Ruby interpreter ;; Copyright (C) 1998-2005 Daiki Ueno ;; Author: Daiki Ueno @@ -22,11 +22,43 @@ ;; Free Software Foundation, Inc., 59 Temple Place - Suite 330, ;; Boston, MA 02111-1307, USA. +;;; Commentary: + +;; riece-ruby.el is a library to interact with the Ruby interpreter. +;; It supports concurrent execution of Ruby programs in a single +;; session. For example: +;; +;; (riece-ruby-execute "t1" "sleep 30"); returns immediately +;; => nil +;; (riece-ruby-execute "t2" "1 + 1") +;; => nil +;; (riece-ruby-execute "t3" "\"") +;; => nil +;; +;; (riece-ruby-inspect "t1") +;; => ((OK nil) nil "running") +;; (riece-ruby-inspect "t2") +;; => ((OK nil) "2" "finished") +;; (riece-ruby-inspect "t3") +;; => ((OK nil) "(eval):1:in `dispatch_eval': compile error +;; (eval):1: unterminated string meets end of file" "exited") + ;;; Code: (defvar riece-ruby-command "ruby" "Command name for Ruby interpreter.") +(defvar riece-ruby-process nil) + +(defvar riece-ruby-lock nil) +(defvar riece-ruby-response nil) +(defvar riece-ruby-data nil) +(defvar riece-ruby-input nil) +(defvar riece-ruby-status nil) + +(defvar riece-ruby-output-handler-alist nil) +(defvar riece-ruby-exit-handler-alist nil) + (defun riece-ruby-substitute-variables (program variable value) (setq program (copy-sequence program)) (let ((pointer program)) @@ -56,25 +88,51 @@ index (- (match-end 0) 2))) data)) -(defun riece-ruby-start () - (start-process "riece-ruby" - (generate-new-buffer " *Ruby*") - riece-ruby-command - (expand-file-name "rubyserv.rb" - (file-name-directory - (symbol-file 'riece-ruby-start))))) - -(defun riece-ruby-execute (process program &optional callback) - (set-process-filter process #'riece-ruby-filter) - (set-process-sentinel process #'riece-ruby-sentinel) - (with-current-buffer (process-buffer process) - (make-local-variable 'riece-ruby-callback) - (setq riece-ruby-callback callback) +(defun riece-ruby-send-eval (name program) + (let* ((string (riece-ruby-escape-data program)) + (length (- (length string) 998)) + (index 0) + data) + (while (< index length) + (setq data (cons (substring string index (setq index (+ index 998))) + data))) + (setq data (cons (substring string index) data) + data (nreverse data)) + (save-excursion + (set-buffer (process-buffer riece-ruby-process)) + (make-local-variable 'riece-ruby-lock) + (setq riece-ruby-lock nil) + (make-local-variable 'riece-ruby-response) + (setq riece-ruby-response nil) + (make-local-variable 'riece-ruby-data) + (setq riece-ruby-data nil) + (make-local-variable 'riece-ruby-input) + (setq riece-ruby-input nil) + (make-local-variable 'riece-ruby-status) + (setq riece-ruby-status nil)) + (process-send-string riece-ruby-process + (concat "EVAL " name "\r\n")) + (while data + (process-send-string riece-ruby-process + (concat "D " (car data) "\r\n")) + (setq data (cdr data))) + (process-send-string riece-ruby-process "END\r\n"))) + +(defun riece-ruby-send-poll (name) + (save-excursion + (set-buffer (process-buffer riece-ruby-process)) + (make-local-variable 'riece-ruby-lock) + (setq riece-ruby-lock nil) + (make-local-variable 'riece-ruby-response) + (setq riece-ruby-response nil) (make-local-variable 'riece-ruby-data) - (setq riece-ruby-data nil)) - (process-send-string process - (concat "EVAL " (riece-ruby-escape-data program) - "\n"))) + (setq riece-ruby-data nil) + (make-local-variable 'riece-ruby-input) + (setq riece-ruby-input nil) + (make-local-variable 'riece-ruby-status) + (setq riece-ruby-status nil)) + (process-send-string riece-ruby-process + (concat "POLL " name "\r\n"))) (defun riece-ruby-filter (process input) (save-excursion @@ -84,30 +142,71 @@ (goto-char (process-mark process)) (beginning-of-line) (while (looking-at ".*\r?\n") - (if (looking-at "OK\\( \\(.*\\)\\)?") + (if (looking-at "OK\\( \\(.*\\)\\)?\r") (progn - (funcall riece-ruby-callback - (list 'OK - (match-string 2) - (riece-ruby-unescape-data - (apply #'concat (nreverse riece-ruby-data))))) - (setq riece-ruby-data nil)) - (if (looking-at "ERR \\([0-9]+\\)\\( \\(.*\\)\\)?") + (if riece-ruby-input + (setq riece-ruby-data (mapconcat #'riece-ruby-unescape-data + riece-ruby-input ""))) + (setq riece-ruby-input nil + riece-ruby-response (list 'OK (match-string 2)) + riece-ruby-lock nil)) + (if (looking-at "ERR \\([0-9]+\\)\\( \\(.*\\)\\)?\r") (progn - (funcall riece-ruby-callback - (list 'ERR - (number-to-string (match-string 1)) - (match-string 3) - (riece-ruby-unescape-data - (apply #'concat (nreverse riece-ruby-data))))) - (setq riece-ruby-data nil)) - (if (looking-at "D \\(.*\\)") - (setq riece-ruby-data (cons (match-string 1) riece-ruby-data))))) - (forward-line)))) + (setq riece-ruby-input nil + riece-ruby-response + (list 'ERR (string-to-number (match-string 2)) + (match-string 3)) + riece-ruby-lock nil)) + (if (looking-at "D \\(.*\\)\r") + (setq riece-ruby-input (cons (match-string 1) riece-ruby-input)) + (if (looking-at "S program \\(.*\\)\r") + (setq riece-ruby-status (match-string 1)) + (if (looking-at "# output \\(.*\\) \\(.*\\)\r") + (let ((entry (assoc (match-string 1) + riece-ruby-output-handler-alist))) + (if entry + (funcall (cdr entry) (match-string 2)))) + (if (looking-at "# exit \\(.*\\)\r") + (let ((entry (assoc (match-string 1) + riece-ruby-exit-handler-alist))) + (if entry + (funcall (cdr entry)))))))))) + (forward-line)) + (set-marker (process-mark process) (point-marker)))) (defun riece-ruby-sentinel (process status) (kill-buffer (process-buffer process))) +(defun riece-ruby-execute (name program) + (unless (and riece-ruby-process + (eq (process-status riece-ruby-process) 'run)) + (setq riece-ruby-process + (start-process "riece-ruby" (generate-new-buffer " *Ruby*") + riece-ruby-command + (expand-file-name + "rubyserv.rb" + (file-name-directory + (symbol-file 'riece-ruby-execute))))) + (set-process-filter riece-ruby-process #'riece-ruby-filter) + (set-process-sentinel riece-ruby-process #'riece-ruby-sentinel)) + (save-excursion + (set-buffer (process-buffer riece-ruby-process)) + (setq riece-ruby-lock t) + (riece-ruby-send-eval name program) + (while riece-ruby-lock + (accept-process-output riece-ruby-process)))) + +(defun riece-ruby-inspect (name) + (save-excursion + (set-buffer (process-buffer riece-ruby-process)) + (setq riece-ruby-lock t) + (riece-ruby-send-poll name) + (while (null riece-ruby-response) + (accept-process-output riece-ruby-process)) + (list riece-ruby-response + riece-ruby-data + riece-ruby-status))) + (provide 'riece-ruby) ;;; riece-ruby.el ends here