mirror of
				https://github.com/ruby/ruby.git
				synced 2022-11-09 12:17:21 -05:00 
			
		
		
		
	 4cbbf3bdfc
			
		
	
	
		4cbbf3bdfc
		
	
	
	
	
		
			
			with standard Emacs elisp files. git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@19206 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
		
			
				
	
	
		
			416 lines
		
	
	
	
		
			15 KiB
		
	
	
	
		
			EmacsLisp
		
	
	
	
	
	
			
		
		
	
	
			416 lines
		
	
	
	
		
			15 KiB
		
	
	
	
		
			EmacsLisp
		
	
	
	
	
	
| ;;; -*-Emacs-Lisp-*-
 | |
| ;;;
 | |
| ;;;  $Id$
 | |
| ;;;  $Author$
 | |
| ;;;
 | |
| ;;; Inferior Ruby Mode - ruby process in a buffer.
 | |
| ;;;                      adapted from cmuscheme.el
 | |
| ;;;
 | |
| ;;; Usage:
 | |
| ;;;
 | |
| ;;; (0) check ruby-program-name variable that can run your environment.
 | |
| ;;;
 | |
| ;;; (1) modify .emacs to use ruby-mode 
 | |
| ;;;     for example :
 | |
| ;;;
 | |
| ;;;    (autoload 'ruby-mode "ruby-mode"
 | |
| ;;;      "Mode for editing ruby source files" t)
 | |
| ;;;    (setq auto-mode-alist
 | |
| ;;;          (append '(("\\.rb$" . ruby-mode)) auto-mode-alist))
 | |
| ;;;    (setq interpreter-mode-alist (append '(("ruby" . ruby-mode))
 | |
| ;;;                                  interpreter-mode-alist))
 | |
| ;;;    
 | |
| ;;; (2) set to load inf-ruby and set inf-ruby key definition in ruby-mode.
 | |
| ;;;
 | |
| ;;;    (autoload 'run-ruby "inf-ruby"
 | |
| ;;;      "Run an inferior Ruby process")
 | |
| ;;;    (autoload 'inf-ruby-keys "inf-ruby"
 | |
| ;;;      "Set local key defs for inf-ruby in ruby-mode")
 | |
| ;;;    (add-hook 'ruby-mode-hook
 | |
| ;;;          '(lambda ()
 | |
| ;;;             (inf-ruby-keys)
 | |
| ;;;    ))
 | |
| ;;;
 | |
| ;;; HISTORY
 | |
| ;;; senda -  8 Apr 1998: Created.
 | |
| ;;;      $Log$
 | |
| ;;;      Revision 1.7  2004/07/27 08:11:36  matz
 | |
| ;;;      * eval.c (rb_eval): copy on write for argument local variable
 | |
| ;;;        assignment.
 | |
| ;;;
 | |
| ;;;      * eval.c (assign): ditto.
 | |
| ;;;
 | |
| ;;;      * eval.c (rb_call0): update ruby_frame->argv with the default
 | |
| ;;;        value used for the optional arguments.
 | |
| ;;;
 | |
| ;;;      * object.c (Init_Object): "===" calls rb_obj_equal() directly.
 | |
| ;;;        [ruby-list:39937]
 | |
| ;;;
 | |
| ;;;      Revision 1.6  2002/09/07 14:35:46  nobu
 | |
| ;;;      * misc/inf-ruby.el (inferior-ruby-error-regexp-alist): regexp
 | |
| ;;;        alist for error message from ruby.
 | |
| ;;;     
 | |
| ;;;      * misc/inf-ruby.el (inferior-ruby-mode): fixed for Emacs.
 | |
| ;;;     
 | |
| ;;;      * misc/inf-ruby.el (ruby-send-region): compilation-parse-errors
 | |
| ;;;        doesn't parse first line, so insert separators before each
 | |
| ;;;        evaluations.
 | |
| ;;;     
 | |
| ;;;      Revision 1.5  2002/08/19 10:05:47  nobu
 | |
| ;;;      * misc/inf-ruby.el (inf-ruby-keys): ruby-send-definition
 | |
| ;;;        conflicted with ruby-insert-end.
 | |
| ;;;     
 | |
| ;;;      * misc/inf-ruby.el (inferior-ruby-mode): compilation-minor-mode.
 | |
| ;;;     
 | |
| ;;;      * misc/inf-ruby.el (ruby-send-region): send as here document to
 | |
| ;;;        adjust source file/line.  [ruby-talk:47113], [ruby-dev:17965]
 | |
| ;;;     
 | |
| ;;;      * misc/inf-ruby.el (ruby-send-terminator): added to make unique
 | |
| ;;;        terminator.
 | |
| ;;;     
 | |
| ;;;      Revision 1.4  2002/01/29 07:16:09  matz
 | |
| ;;;      * file.c (rb_stat_rdev_major): added. [new]
 | |
| ;;;     
 | |
| ;;;      * file.c (rb_stat_rdev_minor): added. [new]
 | |
| ;;;     
 | |
| ;;;      * file.c (rb_stat_inspect): print mode in octal.
 | |
| ;;;     
 | |
| ;;;      Revision 1.3  1999/12/01 09:24:18  matz
 | |
| ;;;      19991201
 | |
| ;;;     
 | |
| ;;;      Revision 1.2  1999/08/13 05:45:18  matz
 | |
| ;;;      1.4.0
 | |
| ;;;     
 | |
| ;;;      Revision 1.1.1.1.2.1  1999/07/15 07:59:59  matz
 | |
| ;;;      990715
 | |
| ;;;     
 | |
| ;;;      Revision 1.1.1.1  1999/01/20 04:59:36  matz
 | |
| ;;;      ruby 1.3 cycle
 | |
| ;;;     
 | |
| ;;;      Revision 1.1.2.1  1998/12/16 07:30:36  matz
 | |
| ;;;      first public release of 1.1d (pre1.2) series
 | |
| ;;;     
 | |
| ;;;      Revision 1.4  1998/05/20 02:45:58  senda
 | |
| ;;;      default program to irb
 | |
| ;;;
 | |
| ;;;      Revision 1.3  1998/04/10 04:11:30  senda
 | |
| ;;;      modification by Matsumoto san (1.1b9_09)
 | |
| ;;;      remove-in-string defined
 | |
| ;;;      global variable :
 | |
| ;;;              inferior-ruby-first-prompt-pattern
 | |
| ;;;            inferior-ruby-prompt-pattern
 | |
| ;;;      defined
 | |
| ;;;
 | |
| ;;;      Revision 1.2  1998/04/09 07:53:42  senda
 | |
| ;;;      remove M-C-x in inferior-ruby-mode
 | |
| ;;;
 | |
| ;;;      Revision 1.1  1998/04/09 07:28:36  senda
 | |
| ;;;      Initial revision
 | |
| ;;;
 | |
| ;;;
 | |
| 
 | |
| (require 'comint)
 | |
| (require 'compile)
 | |
| (require 'ruby-mode)
 | |
| 
 | |
| ;;
 | |
| ;; you may change these variables
 | |
| ;;
 | |
| ;(defvar ruby-program-name "rbc --noreadline"
 | |
| ;  "*Program invoked by the run-ruby command")
 | |
| ;
 | |
| ;(defvar inferior-ruby-first-prompt-pattern "^rbc0> *"
 | |
| ;  "first prompt regex pattern of ruby interpreter.")
 | |
| ;
 | |
| ;(defvar inferior-ruby-prompt-pattern "^\\(rbc.[>*\"'] *\\)+"
 | |
| ;  "prompt regex pattern of ruby interpreter.")
 | |
| 
 | |
| ;;;; for irb
 | |
| (defvar ruby-program-name "irb --inf-ruby-mode"
 | |
|   "*Program invoked by the run-ruby command")
 | |
| 
 | |
| (defvar inferior-ruby-first-prompt-pattern "^irb(.*)[0-9:]+0> *"
 | |
|   "first prompt regex pattern of ruby interpreter.")
 | |
| 
 | |
| (defvar inferior-ruby-prompt-pattern "^\\(irb(.*)[0-9:]+[>*\"'] *\\)+"
 | |
|   "prompt regex pattern of ruby interpreter.")
 | |
| 
 | |
| ;;
 | |
| ;; mode variables
 | |
| ;;
 | |
| (defvar inferior-ruby-mode-hook nil
 | |
|   "*Hook for customising inferior-ruby mode.")
 | |
| (defvar inferior-ruby-mode-map nil
 | |
|   "*Mode map for inferior-ruby-mode")
 | |
| 
 | |
| (defconst inferior-ruby-error-regexp-alist
 | |
|        '(("SyntaxError: compile error\n^\\([^\(].*\\):\\([1-9][0-9]*\\):" 1 2)
 | |
|          ("^\tfrom \\([^\(].*\\):\\([1-9][0-9]*\\)\\(:in `.*'\\)?$" 1 2)))
 | |
| 
 | |
| (cond ((not inferior-ruby-mode-map)
 | |
|        (setq inferior-ruby-mode-map
 | |
|              (copy-keymap comint-mode-map))
 | |
| ;       (define-key inferior-ruby-mode-map "\M-\C-x" ;gnu convention
 | |
| ;                  'ruby-send-definition)
 | |
| ;       (define-key inferior-ruby-mode-map "\C-x\C-e" 'ruby-send-last-sexp)
 | |
|        (define-key inferior-ruby-mode-map "\C-c\C-l" 'ruby-load-file)
 | |
| ))
 | |
| 
 | |
| (defun inf-ruby-keys ()
 | |
|   "Set local key defs for inf-ruby in ruby-mode"
 | |
|   (define-key ruby-mode-map "\M-\C-x" 'ruby-send-definition)
 | |
| ;  (define-key ruby-mode-map "\C-x\C-e" 'ruby-send-last-sexp)
 | |
|   (define-key ruby-mode-map "\C-c\C-b" 'ruby-send-block)
 | |
|   (define-key ruby-mode-map "\C-c\M-b" 'ruby-send-block-and-go)
 | |
|   (define-key ruby-mode-map "\C-c\C-x" 'ruby-send-definition)
 | |
|   (define-key ruby-mode-map "\C-c\M-x" 'ruby-send-definition-and-go)
 | |
|   (define-key ruby-mode-map "\C-c\C-r" 'ruby-send-region)
 | |
|   (define-key ruby-mode-map "\C-c\M-r" 'ruby-send-region-and-go)
 | |
|   (define-key ruby-mode-map "\C-c\C-z" 'switch-to-ruby)
 | |
|   (define-key ruby-mode-map "\C-c\C-l" 'ruby-load-file)
 | |
|   (define-key ruby-mode-map "\C-c\C-s" 'run-ruby)
 | |
| )
 | |
| 
 | |
| (defvar ruby-buffer nil "current ruby (actually irb) process buffer.")
 | |
| 
 | |
| (defun inferior-ruby-mode ()
 | |
|   "Major mode for interacting with an inferior ruby (irb) process.
 | |
| 
 | |
| The following commands are available:
 | |
| \\{inferior-ruby-mode-map}
 | |
| 
 | |
| A ruby process can be fired up with M-x run-ruby.
 | |
| 
 | |
| Customisation: Entry to this mode runs the hooks on comint-mode-hook and
 | |
| inferior-ruby-mode-hook (in that order).
 | |
| 
 | |
| You can send text to the inferior ruby process from other buffers containing
 | |
| Ruby source.
 | |
|     switch-to-ruby switches the current buffer to the ruby process buffer.
 | |
|     ruby-send-definition sends the current definition to the ruby process.
 | |
|     ruby-send-region sends the current region to the ruby process.
 | |
| 
 | |
|     ruby-send-definition-and-go, ruby-send-region-and-go,
 | |
|         switch to the ruby process buffer after sending their text.
 | |
| For information on running multiple processes in multiple buffers, see
 | |
| documentation for variable ruby-buffer.
 | |
| 
 | |
| Commands:
 | |
| Return after the end of the process' output sends the text from the 
 | |
|     end of process to point.
 | |
| Return before the end of the process' output copies the sexp ending at point
 | |
|     to the end of the process' output, and sends it.
 | |
| Delete converts tabs to spaces as it moves back.
 | |
| Tab indents for ruby; with argument, shifts rest
 | |
|     of expression rigidly with the current line.
 | |
| C-M-q does Tab on each line starting within following expression.
 | |
| Paragraphs are separated only by blank lines.  # start comments.
 | |
| If you accidentally suspend your process, use \\[comint-continue-subjob]
 | |
| to continue it."
 | |
|   (interactive)
 | |
|   (comint-mode)
 | |
|   ;; Customise in inferior-ruby-mode-hook
 | |
|   ;(setq comint-prompt-regexp "^[^>\n]*>+ *")
 | |
|   (setq comint-prompt-regexp inferior-ruby-prompt-pattern)
 | |
|   ;;(scheme-mode-variables)
 | |
|   (ruby-mode-variables)
 | |
|   (setq major-mode 'inferior-ruby-mode)
 | |
|   (setq mode-name "Inferior Ruby")
 | |
|   (setq mode-line-process '(":%s"))
 | |
|   (use-local-map inferior-ruby-mode-map)
 | |
|   (setq comint-input-filter (function ruby-input-filter))
 | |
|   (setq comint-get-old-input (function ruby-get-old-input))
 | |
|   (compilation-shell-minor-mode t)
 | |
|   (make-local-variable 'compilation-error-regexp-alist)
 | |
|   (setq compilation-error-regexp-alist inferior-ruby-error-regexp-alist)
 | |
|   (run-hooks 'inferior-ruby-mode-hook))
 | |
| 
 | |
| (defvar inferior-ruby-filter-regexp "\\`\\s *\\S ?\\S ?\\s *\\'"
 | |
|   "*Input matching this regexp are not saved on the history list.
 | |
| Defaults to a regexp ignoring all inputs of 0, 1, or 2 letters.")
 | |
| 
 | |
| (defun ruby-input-filter (str)
 | |
|   "Don't save anything matching inferior-ruby-filter-regexp"
 | |
|   (not (string-match inferior-ruby-filter-regexp str)))
 | |
| 
 | |
| ;; adapted from replace-in-string in XEmacs (subr.el)
 | |
| (defun remove-in-string (str regexp)
 | |
|   "Remove all matches in STR for REGEXP and returns the new string."
 | |
|   (let ((rtn-str "") (start 0) match prev-start)
 | |
|     (while (setq match (string-match regexp str start))
 | |
|       (setq prev-start start
 | |
|             start (match-end 0)
 | |
|             rtn-str (concat rtn-str (substring str prev-start match))))
 | |
|     (concat rtn-str (substring str start))))
 | |
| 
 | |
| (defun ruby-get-old-input ()
 | |
|   "Snarf the sexp ending at point"
 | |
|   (save-excursion
 | |
|     (let ((end (point)))
 | |
|       (re-search-backward inferior-ruby-first-prompt-pattern)
 | |
|       (remove-in-string (buffer-substring (point) end)
 | |
|                         inferior-ruby-prompt-pattern)
 | |
|       )))
 | |
| 
 | |
| (defun ruby-args-to-list (string)
 | |
|   (let ((where (string-match "[ \t]" string)))
 | |
|     (cond ((null where) (list string))
 | |
|           ((not (= where 0))
 | |
|            (cons (substring string 0 where)
 | |
|                  (ruby-args-to-list (substring string (+ 1 where)
 | |
|                                                  (length string)))))
 | |
|           (t (let ((pos (string-match "[^ \t]" string)))
 | |
|                (if (null pos)
 | |
|                    nil
 | |
|                  (ruby-args-to-list (substring string pos
 | |
|                                                  (length string)))))))))
 | |
| 
 | |
| (defun run-ruby (cmd)
 | |
|   "Run an inferior Ruby process, input and output via buffer *ruby*.
 | |
| If there is a process already running in `*ruby*', switch to that buffer.
 | |
| With argument, allows you to edit the command line (default is value
 | |
| of `ruby-program-name').  Runs the hooks `inferior-ruby-mode-hook'
 | |
| \(after the `comint-mode-hook' is run).
 | |
| \(Type \\[describe-mode] in the process buffer for a list of commands.)"
 | |
| 
 | |
|   (interactive (list (if current-prefix-arg
 | |
|                          (read-string "Run Ruby: " ruby-program-name)
 | |
|                          ruby-program-name)))
 | |
|   (if (not (comint-check-proc "*ruby*"))
 | |
|       (let ((cmdlist (ruby-args-to-list cmd)))
 | |
|         (set-buffer (apply 'make-comint "ruby" (car cmdlist)
 | |
|                            nil (cdr cmdlist)))
 | |
|         (inferior-ruby-mode)))
 | |
|   (setq ruby-program-name cmd)
 | |
|   (setq ruby-buffer "*ruby*")
 | |
|   (pop-to-buffer "*ruby*"))
 | |
| 
 | |
| (defconst ruby-send-terminator "--inf-ruby-%x-%d-%d-%d--"
 | |
|   "Template for irb here document terminator.
 | |
| Must not contain ruby meta characters.")
 | |
| 
 | |
| (defconst ruby-eval-separator "")
 | |
| 
 | |
| (defun ruby-send-region (start end)
 | |
|   "Send the current region to the inferior Ruby process."
 | |
|   (interactive "r")
 | |
|   (let (term (file (buffer-file-name)) line)
 | |
|     (save-excursion
 | |
|       (save-restriction
 | |
|         (widen)
 | |
|         (goto-char start)
 | |
|         (setq line (+ start (forward-line (- start)) 1))
 | |
|         (goto-char start)
 | |
|         (while (progn
 | |
|                  (setq term (apply 'format ruby-send-terminator (random) (current-time)))
 | |
|                  (re-search-forward (concat "^" (regexp-quote term) "$") end t)))))
 | |
|     ;; compilation-parse-errors parses from second line.
 | |
|     (save-excursion
 | |
|       (let ((m (process-mark (ruby-proc))))
 | |
|         (set-buffer (marker-buffer m))
 | |
|         (goto-char m)
 | |
|         (insert ruby-eval-separator "\n")
 | |
|         (set-marker m (point))))
 | |
|     (comint-send-string (ruby-proc) (format "eval <<'%s', nil, %S, %d\n" term file line))
 | |
|     (comint-send-region (ruby-proc) start end)
 | |
|     (comint-send-string (ruby-proc) (concat "\n" term "\n"))))
 | |
| 
 | |
| (defun ruby-send-definition ()
 | |
|   "Send the current definition to the inferior Ruby process."
 | |
|   (interactive)
 | |
|   (save-excursion
 | |
|     (ruby-end-of-defun)
 | |
|     (let ((end (point)))
 | |
|       (ruby-beginning-of-defun)
 | |
|       (ruby-send-region (point) end))))
 | |
| 
 | |
| ;(defun ruby-send-last-sexp ()
 | |
| ;  "Send the previous sexp to the inferior Ruby process."
 | |
| ;  (interactive)
 | |
| ;  (ruby-send-region (save-excursion (backward-sexp) (point)) (point)))
 | |
| 
 | |
| (defun ruby-send-block ()
 | |
|   "Send the current block to the inferior Ruby process."
 | |
|   (interactive)
 | |
|   (save-excursion
 | |
|     (ruby-end-of-block)
 | |
|     (end-of-line)
 | |
|     (let ((end (point)))
 | |
|       (ruby-beginning-of-block)
 | |
|       (ruby-send-region (point) end))))
 | |
| 
 | |
| (defun switch-to-ruby (eob-p)
 | |
|   "Switch to the ruby process buffer.
 | |
| With argument, positions cursor at end of buffer."
 | |
|   (interactive "P")
 | |
|   (if (get-buffer ruby-buffer)
 | |
|       (pop-to-buffer ruby-buffer)
 | |
|       (error "No current process buffer. See variable ruby-buffer."))
 | |
|   (cond (eob-p
 | |
|          (push-mark)
 | |
|          (goto-char (point-max)))))
 | |
| 
 | |
| (defun ruby-send-region-and-go (start end)
 | |
|   "Send the current region to the inferior Ruby process.
 | |
| Then switch to the process buffer."
 | |
|   (interactive "r")
 | |
|   (ruby-send-region start end)
 | |
|   (switch-to-ruby t))
 | |
| 
 | |
| (defun ruby-send-definition-and-go ()
 | |
|   "Send the current definition to the inferior Ruby. 
 | |
| Then switch to the process buffer."
 | |
|   (interactive)
 | |
|   (ruby-send-definition)
 | |
|   (switch-to-ruby t))
 | |
| 
 | |
| (defun ruby-send-block-and-go ()
 | |
|   "Send the current block to the inferior Ruby. 
 | |
| Then switch to the process buffer."
 | |
|   (interactive)
 | |
|   (ruby-send-block)
 | |
|   (switch-to-ruby t))
 | |
| 
 | |
| (defvar ruby-source-modes '(ruby-mode)
 | |
|   "*Used to determine if a buffer contains Ruby source code.
 | |
| If it's loaded into a buffer that is in one of these major modes, it's
 | |
| considered a ruby source file by ruby-load-file.
 | |
| Used by these commands to determine defaults.")
 | |
| 
 | |
| (defvar ruby-prev-l/c-dir/file nil
 | |
|   "Caches the last (directory . file) pair.
 | |
| Caches the last pair used in the last ruby-load-file command.
 | |
| Used for determining the default in the 
 | |
| next one.")
 | |
| 
 | |
| (defun ruby-load-file (file-name)
 | |
|   "Load a Ruby file into the inferior Ruby process."
 | |
|   (interactive (comint-get-source "Load Ruby file: " ruby-prev-l/c-dir/file
 | |
|                                   ruby-source-modes t)) ; T because LOAD 
 | |
|                                                           ; needs an exact name
 | |
|   (comint-check-source file-name) ; Check to see if buffer needs saved.
 | |
|   (setq ruby-prev-l/c-dir/file (cons (file-name-directory    file-name)
 | |
|                                        (file-name-nondirectory file-name)))
 | |
|   (comint-send-string (ruby-proc) (concat "(load \""
 | |
|                                             file-name
 | |
|                                             "\"\)\n")))
 | |
| 
 | |
| (defun ruby-proc ()
 | |
|   "Returns the current ruby process. See variable ruby-buffer."
 | |
|   (let ((proc (get-buffer-process (if (eq major-mode 'inferior-ruby-mode)
 | |
|                                       (current-buffer)
 | |
|                                     ruby-buffer))))
 | |
|     (or proc
 | |
|         (error "No current process. See variable ruby-buffer"))))
 | |
| 
 | |
| ;;; Do the user's customisation...
 | |
| 
 | |
| (defvar inf-ruby-load-hook nil
 | |
|   "This hook is run when inf-ruby is loaded in.
 | |
| This is a good place to put keybindings.")
 | |
|         
 | |
| (run-hooks 'inf-ruby-load-hook)
 | |
| 
 | |
| (provide 'inf-ruby)
 | |
| 
 | |
| ;;; inf-ruby.el ends here
 |