emacs-elpa-diffs
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[nongnu] elpa/inf-ruby 60f9cfa181 001/265: Initial revision.


From: ELPA Syncer
Subject: [nongnu] elpa/inf-ruby 60f9cfa181 001/265: Initial revision.
Date: Sat, 9 Jul 2022 21:59:09 -0400 (EDT)

branch: elpa/inf-ruby
commit 60f9cfa1818f279b281fa1f1db27028136c04de0
Author: Cornelius Mika <cornelius.mika@gmail.com>
Commit: Cornelius Mika <cornelius.mika@gmail.com>

    Initial revision.
---
 inf-ruby.el | 350 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 350 insertions(+)

diff --git a/inf-ruby.el b/inf-ruby.el
new file mode 100755
index 0000000000..182d93a32d
--- /dev/null
+++ b/inf-ruby.el
@@ -0,0 +1,350 @@
+;;; inf-ruby.el --- Run a ruby process in a buffer
+
+;; Copyright (C) 1999-2008 Yukihiro Matsumoto, Nobuyoshi Nakada
+
+;; Authors: Yukihiro Matsumoto, Nobuyoshi Nakada
+;; URL: http://www.emacswiki.org/cgi-bin/wiki/RubyMode
+;; Created: 8 April 1998
+;; Keywords: languages ruby
+;; Version: 2.1
+;; Package-Requires: ((ruby-mode "1.1"))
+
+;;; Commentary:
+;;
+;; inf-ruby.el provides a REPL buffer connected to an IRB subprocess.
+;;
+;; If you're installing manually, you'll need to:
+;; * drop the file somewhere on your load path (perhaps ~/.emacs.d)
+;; * Add the following lines to your .emacs file:
+;;    (autoload 'inf-ruby "inf-ruby" "Run an inferior Ruby process" t)
+;;    (autoload 'inf-ruby-keys "inf-ruby" "" t)
+;;    (eval-after-load 'ruby-mode
+;;      '(add-hook 'ruby-mode-hook 'inf-ruby-keys))
+
+;;; TODO:
+;;
+;; inferior-ruby-error-regexp-alist doesn't match this example
+;;   SyntaxError: /home/eschulte/united/org/work/arf/arf/lib/cluster.rb:35: 
syntax error, unexpected '~', expecting kEND
+;;               similarity = comparison_cache[m][n] ||= clusters[m] ~ 
clusters[n]
+;;
+;; M-p skips the first entry in the input ring.
+;;
+
+(require 'comint)
+(require 'compile)
+(require 'ruby-mode)
+
+(defvar inf-ruby-default-implementation "ruby"
+  "Which ruby implementation to use if none is specified.")
+
+(defvar inf-ruby-first-prompt-pattern "^irb(.*)[0-9:]+0> *"
+  "First prompt regex pattern of ruby interpreter.")
+
+(defvar inf-ruby-prompt-pattern "^\\(irb(.*)[0-9:]+[>*\"'] *\\)+"
+  "Prompt regex pattern of ruby interpreter.")
+
+(defvar inf-ruby-mode-hook nil
+  "*Hook for customising inf-ruby mode.")
+
+(defvar inf-ruby-mode-map
+  (let ((map (copy-keymap comint-mode-map)))
+    (define-key map (kbd "C-c C-l") 'inf-ruby-load-file)
+    (define-key map (kbd "C-x C-e") 'ruby-send-last-sexp)
+    (define-key map (kbd "TAB") 'inf-ruby-complete-or-tab)
+    map)
+  "*Mode map for inf-ruby-mode")
+
+(defvar inf-ruby-implementations
+  '(("ruby"     . "irb --inf-ruby-mode -r irb/completion")
+    ("jruby"    . "jruby -S irb -r irb/completion")
+    ("rubinius" . "rbx -r irb/completion")
+    ("yarv"     . "irb1.9 --inf-ruby-mode -r irb/completion")) ;; TODO: 
ironruby?
+  "An alist of ruby implementations to irb executable names.")
+
+;; TODO: do we need these two defvars?
+(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.")
+
+(defconst inf-ruby-error-regexp-alist
+  '(("SyntaxError: compile error\n^\\([^\(].*\\):\\([1-9][0-9]*\\):" 1 2)
+    ("^\tfrom \\([^\(].*\\):\\([1-9][0-9]*\\)\\(:in `.*'\\)?$" 1 2)))
+
+;;;###autoload
+(defun inf-ruby-keys ()
+  "Set local key defs to invoke inf-ruby from 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" 'ruby-switch-to-inf)
+  (define-key ruby-mode-map "\C-c\C-l" 'ruby-load-file)
+  (define-key ruby-mode-map "\C-c\C-s" 'inf-ruby))
+
+(defvar inf-ruby-buffer nil "Current irb process buffer.")
+
+(defun inf-ruby-mode ()
+  "Major mode for interacting with an inferior ruby (irb) process.
+
+The following commands are available:
+\\{inf-ruby-mode-map}
+
+A ruby process can be fired up with M-x inf-ruby.
+
+Customisation: Entry to this mode runs the hooks on comint-mode-hook and
+inf-ruby-mode-hook (in that order).
+
+You can send text to the inferior ruby process from other buffers containing
+Ruby source.
+    ruby-switch-to-inf 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.
+
+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 arugment, 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)
+  (setq comint-prompt-regexp inf-ruby-prompt-pattern)
+  (ruby-mode-variables)
+  (setq major-mode 'inf-ruby-mode)
+  (setq mode-name "Inf-Ruby")
+  (setq mode-line-process '(":%s"))
+  (use-local-map inf-ruby-mode-map)
+  (setq comint-input-filter (function inf-ruby-input-filter))
+  (setq comint-get-old-input (function inf-ruby-get-old-input))
+  (make-local-variable 'compilation-error-regexp-alist)
+  (setq compilation-error-regexp-alist inf-ruby-error-regexp-alist)
+  (compilation-shell-minor-mode t)
+  (run-hooks 'inf-ruby-mode-hook))
+
+(defvar inf-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 inf-ruby-input-filter (str)
+  "Don't save anything matching inf-ruby-filter-regexp"
+  (not (string-match inf-ruby-filter-regexp str)))
+
+;; adapted from replace-in-string in XEmacs (subr.el)
+(defun inf-ruby-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 inf-ruby-get-old-input ()
+  "Snarf the sexp ending at point"
+  (save-excursion
+    (let ((end (point)))
+      (re-search-backward inf-ruby-first-prompt-pattern)
+      (inf-ruby-remove-in-string (buffer-substring (point) end)
+                                 inf-ruby-prompt-pattern))))
+
+;;;###autoload
+(defun inf-ruby (&optional impl)
+  "Run an inferior Ruby process in a buffer.
+With prefix argument, prompts for which Ruby implementation
+\(from the list `inf-ruby-implementations') to use. Runs the
+hooks `inf-ruby-mode-hook' \(after the `comint-mode-hook' is
+run)."
+
+  (interactive (list (if current-prefix-arg
+                         (completing-read "Ruby Implementation: "
+                                          (mapc #'car 
inf-ruby-implementations))
+                       inf-ruby-default-implementation)))
+  (setq impl (or impl "ruby"))
+
+  (let ((command (cdr (assoc impl inf-ruby-implementations))))
+    (run-ruby command impl)))
+
+;;;###autoload
+(defun run-ruby (&optional command name)
+  "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)
+  (setq command (or command (cdr (assoc inf-ruby-default-implementation
+                                        inf-ruby-implementations))))
+  (setq name (or name "ruby"))
+
+  (if (not (comint-check-proc inf-ruby-buffer))
+      (let ((commandlist (split-string command)))
+        (set-buffer (apply 'make-comint name (car commandlist)
+                           nil (cdr commandlist)))
+        (inf-ruby-mode)))
+  (pop-to-buffer (setq inf-ruby-buffer (format "*%s*" name))))
+
+(defun inf-ruby-proc ()
+  "Returns the current IRB process. See variable inf-ruby-buffer."
+  (or (get-buffer-process (if (eq major-mode 'inf-ruby-mode)
+                              (current-buffer)
+                            inf-ruby-buffer))
+      (error "No current process. See variable inf-ruby-buffer")))
+
+;; These commands are added to the ruby-mode keymap:
+
+(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 (inf-ruby-proc))))
+        (set-buffer (marker-buffer m))
+        (goto-char m)
+        (insert ruby-eval-separator "\n")
+        (set-marker m (point))))
+    (comint-send-string (inf-ruby-proc) (format "eval <<'%s', nil, %S, %d\n" 
term file line))
+    (comint-send-region (inf-ruby-proc) start end)
+    (comint-send-string (inf-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 ruby-switch-to-inf (eob-p)
+  "Switch to the ruby process buffer.
+With argument, positions cursor at end of buffer."
+  (interactive "P")
+  (if (get-buffer inf-ruby-buffer)
+      (pop-to-buffer inf-ruby-buffer)
+    (error "No current process buffer. See variable inf-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)
+  (ruby-switch-to-inf 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)
+  (ruby-switch-to-inf 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)
+  (ruby-switch-to-inf t))
+
+(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 (inf-ruby-proc) (concat "(load \""
+                                              file-name
+                                              "\"\)\n")))
+
+(defun inf-ruby-completions (seed)
+  "Return a list of completions for the line of ruby code starting with SEED."
+  (let* ((proc (get-buffer-process inf-ruby-buffer))
+        (comint-filt (process-filter proc))
+        (kept "") completions)
+    (set-process-filter proc (lambda (proc string) (setf kept (concat kept 
string))))
+    (process-send-string proc (format "puts 
IRB::InputCompletor::CompletionProc.call('%s').compact\n" seed))
+    (while (not (string-match inf-ruby-prompt-pattern kept)) 
(accept-process-output proc))
+    (if (string-match "^[[:alpha:]]+?Error: " kept) (error kept))
+    (setf completions (butlast (split-string kept "[\r\n]") 2))
+    (set-process-filter proc comint-filt)
+    completions))
+
+(defun inf-ruby-complete-or-tab (&optional command)
+  "Either complete the ruby code at point or call
+`indent-for-tab-command' if no completion is available.  Relies
+on the irb/completion Module used by readline when running irb
+through a terminal."
+  (interactive (list (let* ((curr (thing-at-point 'line))
+                           (completions (inf-ruby-completions curr)))
+                      (case (length completions)
+                        (0 nil)
+                        (1 (car completions))
+                        (t (completing-read "possible completions: " 
completions nil 'confirm-only curr))))))
+  (if (not command)
+      (call-interactively 'indent-for-tab-command)
+    (move-beginning-of-line 1)
+    (kill-line 1)
+    (insert command)))
+
+;;;###autoload
+(eval-after-load 'ruby-mode
+  '(add-hook 'ruby-mode-hook 'inf-ruby-keys))
+
+(provide 'inf-ruby)
+;;; inf-ruby.el ends here



reply via email to

[Prev in Thread] Current Thread [Next in Thread]