CVS update by graaff packages/xemacs-packages/ruby-modes, README, package-info.in ...

[email protected]
Newsgroups gmane.emacs.xemacs.cvs
Message-ID <[email protected]>
  User: graaff  
  Date: 09/07/19 10:18:21

  Modified:    packages/xemacs-packages/ruby-modes ChangeLog Makefile
                        README inf-ruby.el inf-ruby.el.upstream
                        package-info.in ruby-mode.el ruby-mode.el.upstream
  Added:       packages/xemacs-packages/ruby-modes ruby-electric.el
Log:
Sync to upsteam 1.8.5_pre4.

Revision  Changes    Path
1.11      +6 -0      XEmacs/packages/xemacs-packages/ruby-modes/ChangeLog

Index: ChangeLog
===================================================================
RCS file: /pack/xemacscvs/XEmacs/packages/xemacs-packages/ruby-modes/ChangeLog,v
retrieving revision 1.10
retrieving revision 1.11
diff -u -p -r1.10 -r1.11
--- ChangeLog	2003/10/31 17:05:54	1.10
+++ ChangeLog	2009/07/19 08:18:14	1.11
@@ -1,3 +1,9 @@
+2009-07-19  Hans de Graaff  <[email protected]>
+
+	* Sync with upstream 1.8.5_pre4
+
+	* ruby-electric.el: New.
+
 2003-10-31  Norbert Koch  <[email protected]>
 
 	* Makefile (VERSION): XEmacs package 1.02 released.



1.10      +3 -3      XEmacs/packages/xemacs-packages/ruby-modes/Makefile

Index: Makefile
===================================================================
RCS file: /pack/xemacscvs/XEmacs/packages/xemacs-packages/ruby-modes/Makefile,v
retrieving revision 1.9
retrieving revision 1.10
diff -u -p -r1.9 -r1.10
--- Makefile	2009/07/19 07:52:35	1.9
+++ Makefile	2009/07/19 08:18:14	1.10
@@ -18,14 +18,14 @@
 # Boston, MA 02111-1307, USA.
 
 VERSION = 1.02
-AUTHOR_VERSION = 1.6.8
-MAINTAINER = Hans de Graaff <[email protected]>
+AUTHOR_VERSION = 1.8.5_pre4
+MAINTAINER = Hans de Graaff <[email protected]>
 PACKAGE = ruby-modes
 PKG_TYPE = regular
 REQUIRES = xemacs-base debug
 CATEGORY = standard
 
-ELCS = inf-ruby.elc ruby-mode.elc rubydb3x.elc
+ELCS = inf-ruby.elc ruby-electric.elc ruby-mode.elc rubydb3x.elc
 
 EXTRA_SOURCES = README
 



1.2       +1 -1      XEmacs/packages/xemacs-packages/ruby-modes/README

Index: README
===================================================================
RCS file: /pack/xemacscvs/XEmacs/packages/xemacs-packages/ruby-modes/README,v
retrieving revision 1.1
retrieving revision 1.2
diff -u -p -r1.1 -r1.2
--- README	2003/01/06 21:07:15	1.1
+++ README	2009/07/19 08:18:14	1.2
@@ -1,5 +1,5 @@
 README		this file
 inf-ruby.el	program to run ruby under emacs
+ruby-electric.el	electric minor mode for ruby
 ruby-mode.el	ruby mode for emacs
-rubydb2x.el	ruby debugger support for emacs 19.2x or before
 rubydb3x.el	ruby debugger support for emacs 19.3x or later



1.4       +22 -11    XEmacs/packages/xemacs-packages/ruby-modes/inf-ruby.el

Index: inf-ruby.el
===================================================================
RCS file: /pack/xemacscvs/XEmacs/packages/xemacs-packages/ruby-modes/inf-ruby.el,v
retrieving revision 1.3
retrieving revision 1.4
diff -u -p -r1.3 -r1.4
--- inf-ruby.el	2003/01/06 21:07:15	1.3
+++ inf-ruby.el	2009/07/19 08:18:14	1.4
@@ -1,8 +1,8 @@
 ;;; -*-Emacs-Lisp-*-
 ;;;
-;;;  $Id: inf-ruby.el,v 1.3.2.3 2002/09/07 14:37:26 nobu Exp $
-;;;  $Author: nobu $
-;;;  $Date: 2002/09/07 14:37:26 $
+;;;  $Id: inf-ruby.el,v 1.6.2.1 2004/07/27 07:51:28 matz Exp $
+;;;  $Author: matz $
+;;;  $Date: 2004/07/27 07:51:28 $
 ;;;
 ;;; Inferior Ruby Mode - ruby process in a buffer.
 ;;;                      adapted from cmuscheme.el
@@ -15,13 +15,13 @@
 ;;;     for example :
 ;;;
 ;;;    (autoload 'ruby-mode "ruby-mode"
-;;;      "Mode for editing ruby source files")
+;;;      "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 road inf-ruby and set inf-ruby key definition in ruby-mode.
+;;; (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")
@@ -35,7 +35,11 @@
 ;;; HISTORY
 ;;; senda -  8 Apr 1998: Created.
 ;;;	 $Log: inf-ruby.el,v $
-;;;	 Revision 1.3.2.3  2002/09/07 14:37:26  nobu
+;;;	 Revision 1.6.2.1  2004/07/27 07:51:28  matz
+;;;	 * 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.
 ;;;	
@@ -45,18 +49,25 @@
 ;;;	   doesn't parse first line, so insert separators before each
 ;;;	   evaluations.
 ;;;	
-;;;	 Revision 1.3.2.2  2002/08/19 10:06:20  nobu
+;;;	 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
 ;;;	



1.3       +16 -8     XEmacs/packages/xemacs-packages/ruby-modes/inf-ruby.el.upstream

Index: inf-ruby.el.upstream
===================================================================
RCS file: /pack/xemacscvs/XEmacs/packages/xemacs-packages/ruby-modes/inf-ruby.el.upstream,v
retrieving revision 1.2
retrieving revision 1.3
diff -u -p -r1.2 -r1.3
--- inf-ruby.el.upstream	2003/01/06 21:07:15	1.2
+++ inf-ruby.el.upstream	2009/07/19 08:18:14	1.3
@@ -1,8 +1,8 @@
 ;;; -*-Emacs-Lisp-*-
 ;;;
-;;;  $Id: inf-ruby.el,v 1.3.2.3 2002/09/07 14:37:26 nobu Exp $
-;;;  $Author: nobu $
-;;;  $Date: 2002/09/07 14:37:26 $
+;;;  $Id: inf-ruby.el,v 1.6.2.1 2004/07/27 07:51:28 matz Exp $
+;;;  $Author: matz $
+;;;  $Date: 2004/07/27 07:51:28 $
 ;;;
 ;;; Inferior Ruby Mode - ruby process in a buffer.
 ;;;                      adapted from cmuscheme.el
@@ -21,7 +21,7 @@
 ;;;    (setq interpreter-mode-alist (append '(("ruby" . ruby-mode))
 ;;;    				     interpreter-mode-alist))
 ;;;    
-;;; (2) set to road inf-ruby and set inf-ruby key definition in ruby-mode.
+;;; (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")
@@ -35,7 +35,11 @@
 ;;; HISTORY
 ;;; senda -  8 Apr 1998: Created.
 ;;;	 $Log: inf-ruby.el,v $
-;;;	 Revision 1.3.2.3  2002/09/07 14:37:26  nobu
+;;;	 Revision 1.6.2.1  2004/07/27 07:51:28  matz
+;;;	 * 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.
 ;;;	
@@ -45,7 +49,7 @@
 ;;;	   doesn't parse first line, so insert separators before each
 ;;;	   evaluations.
 ;;;	
-;;;	 Revision 1.3.2.2  2002/08/19 10:06:20  nobu
+;;;	 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.
 ;;;	
@@ -56,9 +60,13 @@
 ;;;	
 ;;;	 * 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]
 ;;;	
-;;;	 Revision 1.3.2.1  2002/02/01 06:01:51  matz
-;;;	 * re.c (rb_reg_search): should set regs.allocated.
+;;;	 * file.c (rb_stat_inspect): print mode in octal.
 ;;;	
 ;;;	 Revision 1.3  1999/12/01 09:24:18  matz
 ;;;	 19991201



1.3       +1 -1      XEmacs/packages/xemacs-packages/ruby-modes/package-info.in

Index: package-info.in
===================================================================
RCS file: /pack/xemacscvs/XEmacs/packages/xemacs-packages/ruby-modes/package-info.in,v
retrieving revision 1.2
retrieving revision 1.3
diff -u -p -r1.2 -r1.3
--- package-info.in	2003/01/06 21:07:15	1.2
+++ package-info.in	2009/07/19 08:18:14	1.3
@@ -13,7 +13,7 @@
    filename FILENAME
    md5sum MD5SUM
    size SIZE
-   provides (inf-ruby ruby-mode rubydb)
+   provides (inf-ruby ruby-electric ruby-mode rubydb)
    requires (REQUIRES)
    type regular
 ))



1.4       +751 -406  XEmacs/packages/xemacs-packages/ruby-modes/ruby-mode.el

Index: ruby-mode.el
===================================================================
RCS file: /pack/xemacscvs/XEmacs/packages/xemacs-packages/ruby-modes/ruby-mode.el,v
retrieving revision 1.3
retrieving revision 1.4
diff -u -p -r1.3 -r1.4
--- ruby-mode.el	2003/01/06 21:07:16	1.3
+++ ruby-mode.el	2009/07/19 08:18:15	1.4
@@ -2,11 +2,11 @@
 ;;;  ruby-mode.el -
 ;;;
 ;;;  $Author: matz $
-;;;  $Date: 2002/12/06 05:15:56 $
+;;;  $Date: 2005/11/30 15:56:57 $
 ;;;  created at: Fri Feb  4 14:49:13 JST 1994
 ;;;
 
-(defconst ruby-mode-revision "$Revision: 1.25.2.11 $")
+(defconst ruby-mode-revision "$Revision: 1.74.2.14 $")
 
 (defconst ruby-mode-version
   (progn
@@ -57,11 +57,22 @@
 
 (defconst ruby-block-end-re "end")
 
+(defconst ruby-here-doc-beg-re
+  "<<\\(-\\)?\\(\\([a-zA-Z0-9_]+\\)\\|[\"]\\([^\"]+\\)[\"]\\|[']\\([^']+\\)[']\\)")
+
+(defun ruby-here-doc-end-match ()
+  (concat "^"
+	  (if (match-string 1) "[ \t]*" nil)
+	  (regexp-quote
+	   (or (match-string 3)
+	       (match-string 4)
+	       (match-string 5)))))
+
 (defconst ruby-delimiter
-  (concat "[?$/%(){}#\"'`.:]\\|\\[\\|\\]\\|\\<\\("
+  (concat "[?$/%(){}#\"'`.:]\\|<<\\|\\[\\|\\]\\|\\<\\("
 	  ruby-block-beg-re
 	  "\\|" ruby-block-end-re
-	  "\\)\\>\\|^=begin")
+	  "\\)\\>\\|^=begin\\|" ruby-here-doc-beg-re)
   )
 
 (defconst ruby-negative
@@ -89,11 +100,12 @@
   (define-key ruby-mode-map "}" 'ruby-electric-brace)
   (define-key ruby-mode-map "\e\C-a" 'ruby-beginning-of-defun)
   (define-key ruby-mode-map "\e\C-e" 'ruby-end-of-defun)
-  (define-key ruby-mode-map "\e\C-b" 'ruby-beginning-of-block)
-  (define-key ruby-mode-map "\e\C-f" 'ruby-end-of-block)
+  (define-key ruby-mode-map "\e\C-b" 'ruby-backward-sexp)
+  (define-key ruby-mode-map "\e\C-f" 'ruby-forward-sexp)
   (define-key ruby-mode-map "\e\C-p" 'ruby-beginning-of-block)
   (define-key ruby-mode-map "\e\C-n" 'ruby-end-of-block)
   (define-key ruby-mode-map "\e\C-h" 'ruby-mark-defun)
+  (define-key ruby-mode-map "\e\C-q" 'ruby-indent-exp)
   (define-key ruby-mode-map "\t" 'ruby-indent-command)
   (define-key ruby-mode-map "\C-c\C-e" 'ruby-insert-end)
   (define-key ruby-mode-map "\C-j" 'ruby-reindent-then-newline-and-indent)
@@ -133,31 +145,79 @@
   (modify-syntax-entry ?\] ")[" ruby-mode-syntax-table)
   )
 
+(defcustom ruby-indent-tabs-mode nil
+  "*Indentation can insert tabs in ruby mode if this is non-nil."
+:type 'boolean :group 'ruby)
+
+(defcustom ruby-indent-level 2
+  "*Indentation of ruby statements."
+:type 'integer :group 'ruby)
+
+(defcustom ruby-comment-column 32
+  "*Indentation column of comments."
+:type 'integer :group 'ruby)
+
+(defcustom ruby-deep-arglist t
+  "*Deep indent lists in parenthesis when non-nil.
+Also ignores spaces after parenthesis when 'space."
+:group 'ruby)
+
+(defcustom ruby-deep-indent-paren '(?\( ?\[ ?\] t)
+  "*Deep indent lists in parenthesis when non-nil. t means continuous line.
+Also ignores spaces after parenthesis when 'space."
+:group 'ruby)
+
+(defcustom ruby-deep-indent-paren-style 'space
+  "Default deep indent style."
+:options '(t nil space) :group 'ruby)
+
 (eval-when-compile (require 'cl))
-(defun ruby-imenu-create-index ()
-  (let ((index-alist '())
-	class-name class-begin method-name method-begin decl)
-    (goto-char (point-min))
-    (while (re-search-forward "^\\s *\\(class\\|def\\)\\s *\\([^(\n ]+\\)" nil t)
-      (setq decl (buffer-substring (match-beginning 1) (match-end 1)))
+(defun ruby-imenu-create-index-in-block (prefix beg end)
+  (let ((index-alist '()) (case-fold-search nil)
+	name next pos decl sing)
+    (goto-char beg)
+    (while (re-search-forward "^\\s *\\(\\(class\\>\\(\\s *<<\\)?\\|module\\>\\)\\s *\\([^\(<\n ]+\\)\\|\\(def\\|alias\\)\\>\\s *\\([^\(\n ]+\\)\\)" end t)
+      (setq sing (match-beginning 3))
+      (setq decl (match-string 5))
+      (setq next (match-end 0))
+      (setq name (or (match-string 4) (match-string 6)))
+      (setq pos (match-beginning 0))
       (cond
-       ((string= "class" decl)
-	(setq class-begin (match-beginning 2))
-	(setq class-name (buffer-substring class-begin (match-end 2)))
-	(push (cons class-name (match-beginning 0)) index-alist)
-	(ruby-mark-defun)
-	(save-restriction
-	  (narrow-to-region (region-beginning) (region-end))
-         (while (re-search-forward "^\\s *def\\s *\\([^(\n ]+\\)" nil 'move)
-	    (setq method-begin (match-beginning 1))
-	    (setq method-name (buffer-substring method-begin (match-end 1)))
-	    (push (cons (concat class-name "#" method-name) (match-beginning 0)) index-alist))))
+       ((string= "alias" decl)
+	(if prefix (setq name (concat prefix name)))
+	(push (cons name pos) index-alist))
        ((string= "def" decl)
-	(setq method-begin (match-beginning 2))
-	(setq method-name (buffer-substring method-begin (match-end 2)))
-	(push (cons method-name (match-beginning 0)) index-alist))))
+	(if prefix
+	    (setq name
+		  (cond
+		   ((string-match "^self\." name)
+		    (concat (substring prefix 0 -1) (substring name 4)))
+		  (t (concat prefix name)))))
+	(push (cons name pos) index-alist)
+	(ruby-accurate-end-of-block end))
+       (t
+	(if (string= "self" name)
+	    (if prefix (setq name (substring prefix 0 -1)))
+	  (if prefix (setq name (concat (substring prefix 0 -1) "::" name)))
+	  (push (cons name pos) index-alist))
+	(ruby-accurate-end-of-block end)
+	(setq beg (point))
+	(setq index-alist
+	      (nconc (ruby-imenu-create-index-in-block
+		      (concat name (if sing "." "#"))
+		      next beg) index-alist))
+	(goto-char beg))))
     index-alist))
 
+(defun ruby-imenu-create-index ()
+  (nreverse (ruby-imenu-create-index-in-block nil (point-min) nil)))
+
+(defun ruby-accurate-end-of-block (&optional end)
+  (let (state)
+    (or end (setq end (point-max)))
+    (while (and (setq state (apply 'ruby-parse-partial end state))
+		(>= (nth 2 state) 0) (< (point) end)))))
+
 (defun ruby-mode-variables ()
   (set-syntax-table ruby-mode-syntax-table)
   (setq local-abbrev-table ruby-mode-abbrev-table)
@@ -170,9 +230,10 @@
   (make-variable-buffer-local 'comment-end)
   (setq comment-end "")
   (make-variable-buffer-local 'comment-column)
-  (setq comment-column 32)
+  (setq comment-column ruby-comment-column)
   (make-variable-buffer-local 'comment-start-skip)
-  (setq comment-start-skip "\\(^\\|\\s-\\);?#+ *")
+  (setq comment-start-skip "#+ *")
+  (setq indent-tabs-mode ruby-indent-tabs-mode)
   (make-local-variable 'parse-sexp-ignore-comments)
   (setq parse-sexp-ignore-comments t)
   (make-local-variable 'paragraph-start)
@@ -201,6 +262,9 @@ The variable `ruby-indent-level' control
   (make-local-variable 'imenu-create-index-function)
   (setq imenu-create-index-function 'ruby-imenu-create-index)
 
+  (make-local-variable 'add-log-current-defun-function)
+  (setq add-log-current-defun-function 'ruby-add-log-current-method)
+
   (run-hooks 'ruby-mode-hook))
 
 (defun ruby-current-indentation ()
@@ -238,32 +302,46 @@ The variable `ruby-indent-level' control
 	  (indent-to x)
 	  (move-to-column (+ x shift))))))
 
+(defun ruby-special-char-p (&optional pnt)
+  (setq pnt (or pnt (point)))
+  (let ((c (char-before pnt)) (b (and (< (point-min) pnt) (char-before (1- pnt)))))
+    (cond ((or (eq c ??) (eq c ?$)))
+	  ((and (eq c ?:) (or (not b) (eq (char-syntax b) ? ))))
+	  ((eq c ?\\) (eq b ??)))))
+
 (defun ruby-expr-beg (&optional option)
   (save-excursion
     (store-match-data nil)
-    (skip-chars-backward " \t")
-    (cond
-     ((bolp) t)
-     ((looking-at "\\?")
-      (or (bolp) (forward-char -1))
-      (not (looking-at "\\sw")))
-     (t
-      (forward-char -1)
-      (or (looking-at ruby-operator-re)
-	  (looking-at "[\\[({,;]")
-	  (and (not (eq option 'modifier))
-	       (looking-at "[!?]"))
-	  (and (looking-at ruby-symbol-re)
-	       (skip-chars-backward ruby-symbol-chars)
-	       (cond
-		((or (looking-at ruby-block-beg-re)
-		     (looking-at ruby-block-op-re)
-		     (looking-at ruby-block-mid-re))
-		 (goto-char (match-end 0))
-		 (looking-at "\\>"))
-		(t
-		 (and (not (eq option 'expr-arg))
-		      (looking-at "[a-zA-Z][a-zA-z0-9_]* +/[^ \t]"))))))))))
+    (let ((space (skip-chars-backward " \t"))
+	  (start (point)))
+      (cond
+       ((bolp) t)
+       ((progn
+	  (forward-char -1)
+	  (and (looking-at "\\?")
+	       (or (eq (char-syntax (char-before (point))) ?w)
+		   (ruby-special-char-p))))
+	nil)
+       ((and (eq option 'heredoc) (< space 0)) t)
+       ((or (looking-at ruby-operator-re)
+	    (looking-at "[\\[({,;]")
+	    (and (looking-at "[!?]")
+		 (or (not (eq option 'modifier))
+		     (bolp)
+		     (save-excursion (forward-char -1) (looking-at "\\Sw$"))))
+	    (and (looking-at ruby-symbol-re)
+		 (skip-chars-backward ruby-symbol-chars)
+		 (cond
+		  ((or (looking-at (concat "\\<\\(" ruby-block-beg-re
+					   "|" ruby-block-op-re
+					   "|" ruby-block-mid-re "\\)\\>")))
+		   (goto-char (match-end 0))
+		   (not (looking-at "\\s_")))
+		  ((eq option 'expr-qstr)
+		   (looking-at "[a-zA-Z][a-zA-z0-9_]* +%[^ \t]"))
+		  ((eq option 'expr-re)
+		   (looking-at "[a-zA-Z][a-zA-z0-9_]* +/[^ \t]"))
+		  (t nil)))))))))
 
 (defun ruby-forward-string (term &optional end no-error expand)
   (let ((n 1) (c (string-to-char term))
@@ -278,327 +356,413 @@ The variable `ruby-indent-level' control
       (forward-char -1))
     (cond ((zerop n))
 	  (no-error nil)
-	  (error "unterminated string"))))
+	  ((error "unterminated string")))))
 
-(defun ruby-parse-region (start end)
-  (let ((indent-point end)
-	  (indent 0)
-	  (in-string nil)
-	  (in-paren nil)
-	  (depth 0)
-	  (nest nil)
-	  (pcol nil))
-    (save-excursion
-	(if start
-	    (goto-char start)
-	  (ruby-beginning-of-indent))
-	(save-restriction
-	  (narrow-to-region (point) end)
-	  (while (and (> indent-point (point))
-		      (re-search-forward ruby-delimiter indent-point t))
-	    (or depth (setq depth 0))
-	    (let ((pnt (point)) w re expand)
-	      (goto-char (match-beginning 0))
-	      (cond
-	       ((or (looking-at "\"")	;skip string
-		    (looking-at "`"))
-		(cond
-		 ((and (not (eobp))
-		       (ruby-forward-string (buffer-substring (point) (1+ (point))) indent-point t t))
-		  nil)
-		 (t
-		  (setq in-string (point))
-		  (goto-char indent-point))))
-	       ((looking-at "'")
-		(cond
-		 ((and (not (eobp))
-		       (re-search-forward "[^\\]\\(\\\\\\\\\\)*'" indent-point t))
-		  nil)
-		 (t
-		  (setq in-string (point))
-		  (goto-char indent-point))))
-	       ((looking-at "/")
-		(cond
-		 ((and (not (eobp)) (ruby-expr-beg))
-		  (if (ruby-forward-string "/" indent-point t t)
-		      nil
-		    (setq in-string (point))
-		    (goto-char indent-point)))
-		 (t
-		  (goto-char pnt))))
-	       ((looking-at "%")
-		(cond
-		 ((and (not (eobp)) (ruby-expr-beg 'expr-arg)
-		       (not (looking-at "%="))
-		       (looking-at "%[Qqrxw]?\\(.\\)"))
-		  (goto-char (match-beginning 1))
-		  (setq expand (not (eq (char-before) ?q)))
-		  (setq w (buffer-substring (match-beginning 1)
-					    (match-end 1)))
-		  (cond
-		   ((string= w "[") (setq re "]["))
-		   ((string= w "{") (setq re "}{"))
-		   ((string= w "(") (setq re ")("))
-		   ((string= w "<") (setq re "><"))
-		   ((or (and expand (string= w "\\"))
-			(member w '("*" "." "+" "?" "^" "$")))
-		    (setq w (concat "\\" w))))
-		  (unless (cond (re (ruby-forward-string re indent-point t expand))
-				(expand (ruby-forward-string w indent-point t t))
-				(t (re-search-forward
-				    (if (string= w "\\")
-					"\\\\[^\\]*\\\\"
-				      (concat "[^\\]\\(\\\\\\\\\\)*" w))
-				    indent-point t)))
-		    (setq in-string (point))
-		    (goto-char indent-point)))
-		 (t
-		  (goto-char pnt))))
-	       ((looking-at "\\?")	;skip ?char
-		(cond
-		 ((ruby-expr-beg)
-		  (looking-at "?\\(\\\\C-\\|\\\\M-\\)*.")
-		  (goto-char (match-end 0)))
-		 (t
-		  (goto-char pnt))))
-	       ((looking-at "\\$")	;skip $char
-		(goto-char pnt)
-		(forward-char 1))
-	       ((looking-at "#")	;skip comment
-		(forward-line 1)
-		(goto-char (point))
-		)
-	       ((looking-at "(")
+(defun ruby-deep-indent-paren-p (c)
+  (cond ((listp ruby-deep-indent-paren)
+	 (let ((deep (assoc c ruby-deep-indent-paren)))
+	   (cond (deep
+		  (or (cdr deep) ruby-deep-indent-paren-style))
+		 ((memq c ruby-deep-indent-paren)
+		  ruby-deep-indent-paren-style))))
+	((eq c ruby-deep-indent-paren) ruby-deep-indent-paren-style)
+	((eq c ?\( ) ruby-deep-arglist)))
+
+(defun ruby-parse-partial (&optional end in-string nest depth pcol indent)
+  (or depth (setq depth 0))
+  (or indent (setq indent 0))
+  (when (re-search-forward ruby-delimiter end 'move)
+    (let ((pnt (point)) w re expand)
+      (goto-char (match-beginning 0))
+      (cond
+       ((and (memq (char-before) '(?@ ?$)) (looking-at "\\sw"))
+	(goto-char pnt))
+       ((looking-at "[\"`]")		;skip string
+	(cond
+	 ((and (not (eobp))
+	       (ruby-forward-string (buffer-substring (point) (1+ (point))) end t t))
+	  nil)
+	 (t
+	  (setq in-string (point))
+	  (goto-char end))))
+       ((looking-at "'")
+	(cond
+	 ((and (not (eobp))
+	       (re-search-forward "[^\\]\\(\\\\\\\\\\)*'" end t))
+	  nil)
+	 (t
+	  (setq in-string (point))
+	  (goto-char end))))
+       ((looking-at "/")
+	(cond
+	 ((and (not (eobp)) (ruby-expr-beg 'expr-re))
+	  (if (ruby-forward-string "/" end t t)
+	      nil
+	    (setq in-string (point))
+	    (goto-char end)))
+	 (t
+	  (goto-char pnt))))
+       ((looking-at "%")
+	(cond
+	 ((and (not (eobp))
+	       (ruby-expr-beg 'expr-qstr)
+	       (not (looking-at "%="))
+	       (looking-at "%[QqrxWw]?\\([^a-zA-Z0-9 \t\n]\\)"))
+	  (goto-char (match-beginning 1))
+	  (setq expand (not (memq (char-before) '(?q ?w))))
+	  (setq w (match-string 1))
+	  (cond
+	   ((string= w "[") (setq re "]["))
+	   ((string= w "{") (setq re "}{"))
+	   ((string= w "(") (setq re ")("))
+	   ((string= w "<") (setq re "><"))
+	   ((and expand (string= w "\\"))
+	    (setq w (concat "\\" w))))
+	  (unless (cond (re (ruby-forward-string re end t expand))
+			(expand (ruby-forward-string w end t t))
+			(t (re-search-forward
+			    (if (string= w "\\")
+				"\\\\[^\\]*\\\\"
+			      (concat "[^\\]\\(\\\\\\\\\\)*" w))
+			    end t)))
+	    (setq in-string (point))
+	    (goto-char end)))
+	 (t
+	  (goto-char pnt))))
+       ((looking-at "\\?")		;skip ?char
+	(cond
+	 ((and (ruby-expr-beg)
+	       (looking-at "?\\(\\\\C-\\|\\\\M-\\)*\\\\?."))
+	  (goto-char (match-end 0)))
+	 (t
+	  (goto-char pnt))))
+       ((looking-at "\\$")		;skip $char
+	(goto-char pnt)
+	(forward-char 1))
+       ((looking-at "#")		;skip comment
+	(forward-line 1)
+	(goto-char (point))
+	)
+       ((looking-at "[\\[{(]")
+	(let ((deep (ruby-deep-indent-paren-p (char-after))))
+	  (if (and deep (or (not (eq (char-after) ?\{)) (ruby-expr-beg)))
+	      (progn
+		(and (eq deep 'space) (looking-at ".\\s +[^# \t\n]")
+		     (setq pnt (1- (match-end 0))))
 		(setq nest (cons (cons (char-after (point)) pnt) nest))
 		(setq pcol (cons (cons pnt depth) pcol))
-		(setq depth 0)
-		(goto-char pnt)
-		)
-	       ((looking-at "[\\[{]")
-		(setq nest (cons (cons (char-after (point)) pnt) nest))
-		(setq depth (1+ depth))
-		(goto-char pnt)
-		)
-	       ((looking-at ")")
-		(setq nest (cdr nest))
-		(setq depth (cdr (car pcol)))
-		(setq pcol (cdr pcol))
-		(goto-char pnt))
-	       ((looking-at "[])}]")
-		(setq nest (cdr nest))
-		(setq depth (1- depth))
-		(goto-char pnt))
-	       ((looking-at ruby-block-end-re)
-		(if (or (and (not (bolp))
-			     (progn
-			       (forward-char -1)
-			       (setq w (char-after (point)))
-			       (or (eq ?_ w)
-				   (eq ?. w))))
-			(progn
-			  (goto-char pnt)
-			  (setq w (char-after (point)))
-			  (or (eq ?_ w)
-			      (eq ?! w)
-			      (eq ?? w))))
-		    nil
-		  (setq nest (cdr nest))
-		  (setq depth (1- depth)))
-		(goto-char pnt))
-	       ((looking-at "def\\s +[^(\n;]*")
-		(if (or (bolp)
-			(progn
-			  (forward-char -1)
-			  (not (eq ?_ (char-after (point))))))
-		    (progn
-		      (setq nest (cons (cons nil pnt) nest))
-		      (setq depth (1+ depth))))
-		(goto-char (match-end 0)))
-	       ((looking-at ruby-block-beg-re)
-		(and
-		 (save-match-data
-                   (or (not (looking-at "do\\>[^_]"))
-                       (save-excursion
-                         (back-to-indentation)
-			 (not (looking-at ruby-non-block-do-re)))))
-		 (or (bolp)
+		(setq depth 0))
+	    (setq nest (cons (cons (char-after (point)) pnt) nest))
+	    (setq depth (1+ depth))))
+	(goto-char pnt)
+	)
+       ((looking-at "[])}]")
+	(if (ruby-deep-indent-paren-p (matching-paren (char-after)))
+	    (setq depth (cdr (car pcol)) pcol (cdr pcol))
+	  (setq depth (1- depth)))
+	(setq nest (cdr nest))
+	(goto-char pnt))
+       ((looking-at (concat "\\<\\(" ruby-block-end-re "\\)\\>"))
+	(if (or (and (not (bolp))
 		     (progn
 		       (forward-char -1)
 		       (setq w (char-after (point)))
-		       (not (or (eq ?_ w)
-				(eq ?. w)))))
-		 (goto-char pnt)
-		 (setq w (char-after (point)))
-		 (not (eq ?_ w))
-		 (not (eq ?! w))
-		 (not (eq ?? w))
-		 (skip-chars-forward " \t")
-		 (goto-char (match-beginning 0))
-		 (or (not (looking-at ruby-modifier-re))
-		     (ruby-expr-beg 'modifier))
-		 (goto-char pnt)
-		 (setq nest (cons (cons nil pnt) nest))
-		 (setq depth (1+ depth)))
-		(goto-char pnt))
-	       ((looking-at ":\\([a-zA-Z_][a-zA-Z_0-9]*\\)?")
-		(goto-char (match-end 0)))
-	       ((or (looking-at "\\.")
-		    (looking-at "\\.\\.\\.?")
-		    (looking-at "\\.[0-9]+")
-		    (looking-at "\\.[a-zA-Z_0-9]+"))
-		(goto-char (match-end 0)))
-	       ((looking-at "^=begin")
-		(if (re-search-forward "^=end" indent-point t)
-		    (forward-line 1)
-		  (setq in-string (match-end 0))
-		  (goto-char indent-point)))
-	       (t
-		(error (format "bad string %s"
-			       (buffer-substring (point) pnt)
-			       )))))))
-	(list in-string (car nest) depth (car (car pcol))))))
+		       (or (eq ?_ w)
+			   (eq ?. w))))
+		(progn
+		  (goto-char pnt)
+		  (setq w (char-after (point)))
+		  (or (eq ?_ w)
+		      (eq ?! w)
+		      (eq ?? w))))
+	    nil
+	  (setq nest (cdr nest))
+	  (setq depth (1- depth)))
+	(goto-char pnt))
+       ((looking-at "def\\s +[^(\n;]*")
+	(if (or (bolp)
+		(progn
+		  (forward-char -1)
+		  (not (eq ?_ (char-after (point))))))
+	    (progn
+	      (setq nest (cons (cons nil pnt) nest))
+	      (setq depth (1+ depth))))
+	(goto-char (match-end 0)))
+       ((looking-at (concat "\\<\\(" ruby-block-beg-re "\\)\\>"))
+	(and
+	 (save-match-data
+	   (or (not (looking-at "do\\>[^_]"))
+	       (save-excursion
+		 (back-to-indentation)
+		 (not (looking-at ruby-non-block-do-re)))))
+	 (or (bolp)
+	     (progn
+	       (forward-char -1)
+	       (setq w (char-after (point)))
+	       (not (or (eq ?_ w)
+			(eq ?. w)))))
+	 (goto-char pnt)
+	 (setq w (char-after (point)))
+	 (not (eq ?_ w))
+	 (not (eq ?! w))
+	 (not (eq ?? w))
+	 (skip-chars-forward " \t")
+	 (goto-char (match-beginning 0))
+	 (or (not (looking-at ruby-modifier-re))
+	     (ruby-expr-beg 'modifier))
+	 (goto-char pnt)
+	 (setq nest (cons (cons nil pnt) nest))
+	 (setq depth (1+ depth)))
+	(goto-char pnt))
+       ((looking-at ":\\(['\"]\\)\\(\\\\.\\|[^\\\\]\\)*\\1")
+	(goto-char (match-end 0)))
+       ((looking-at ":\\([-,.+*/%&|^~<>]=?\\|===?\\|<=>\\)")
+	(goto-char (match-end 0)))
+       ((looking-at ":\\([a-zA-Z_][a-zA-Z_0-9]*[!?=]?\\)?")
+	(goto-char (match-end 0)))
+       ((or (looking-at "\\.\\.\\.?")
+	    (looking-at "\\.[0-9]+")
+	    (looking-at "\\.[a-zA-Z_0-9]+")
+	    (looking-at "\\."))
+	(goto-char (match-end 0)))
+       ((looking-at "^=begin")
+	(if (re-search-forward "^=end" end t)
+	    (forward-line 1)
+	  (setq in-string (match-end 0))
+	  (goto-char end)))
+       ((looking-at "<<")
+	(cond
+	 ((and (ruby-expr-beg 'heredoc)
+	       (looking-at "<<\\(-\\)?\\(\\([\"'`]\\)\\([^\n]+?\\)\\3\\|\\sw+\\)"))
+	  (setq re (regexp-quote (or (match-string 4) (match-string 2))))
+	  (if (match-beginning 1) (setq re (concat "\\s *" re)))
+	  (let* ((id-end (goto-char (match-end 0)))
+		 (line-end-position (save-excursion (end-of-line) (point)))
+		 (state (list in-string nest depth pcol indent)))
+	    ;; parse the rest of the line
+	    (while (and (> line-end-position (point))
+			(setq state (apply 'ruby-parse-partial
+					   line-end-position state))))
+	    (setq in-string (car state)
+		  nest (nth 1 state)
+		  depth (nth 2 state)
+		  pcol (nth 3 state)
+		  indent (nth 4 state))
+	    ;; skip heredoc section
+	    (if (re-search-forward (concat "^" re "$") end 'move)
+		(forward-line 1)
+	      (setq in-string id-end)
+	      (goto-char end))))
+	 (t
+	  (goto-char pnt))))
+       ((looking-at "^__END__$")
+	(goto-char pnt))
+       ((looking-at ruby-here-doc-beg-re)
+	(if (re-search-forward (ruby-here-doc-end-match)
+			       indent-point t)
+	    (forward-line 1)
+	  (setq in-string (match-end 0))
+	  (goto-char indent-point)))
+       (t
+	(error (format "bad string %s"
+		       (buffer-substring (point) pnt)
+		       ))))))
+  (list in-string nest depth pcol))
+
+(defun ruby-parse-region (start end)
+  (let (state)
+    (save-excursion
+      (if start
+	  (goto-char start)
+	(ruby-beginning-of-indent))
+      (save-restriction
+	(narrow-to-region (point) end)
+	(while (and (> end (point))
+		    (setq state (apply 'ruby-parse-partial end state))))))
+    (list (nth 0 state)			; in-string
+	  (car (nth 1 state))		; nest
+	  (nth 2 state)			; depth
+	  (car (car (nth 3 state)))	; pcol
+	  ;(car (nth 5 state))		; indent
+	  )))
 
 (defun ruby-indent-size (pos nest)
-  (+ pos (* (if nest nest 1) ruby-indent-level)))
+  (+ pos (* (or nest 1) ruby-indent-level)))
 
 (defun ruby-calculate-indent (&optional parse-start)
   (save-excursion
     (beginning-of-line)
     (let ((indent-point (point))
-	    (case-fold-search nil)
-	    state bol eol
-	    (indent 0))
-	(if parse-start
-	    (goto-char parse-start)
-	  (ruby-beginning-of-indent)
-	  (setq parse-start (point)))
-	(back-to-indentation)
-	(setq indent (current-column))
-	(setq state (ruby-parse-region parse-start indent-point))
+	  (case-fold-search nil)
+	  state bol eol begin op-end
+	  (paren (progn (skip-syntax-forward " ")
+			(and (char-after) (matching-paren (char-after)))))
+	  (indent 0))
+      (if parse-start
+	  (goto-char parse-start)
+	(ruby-beginning-of-indent)
+	(setq parse-start (point)))
+      (back-to-indentation)
+      (setq indent (current-column))
+      (setq state (ruby-parse-region parse-start indent-point))
+      (cond
+       ((nth 0 state)			; within string
+	(setq indent nil))		;  do nothing
+       ((car (nth 1 state))		; in paren
+	(goto-char (setq begin (cdr (nth 1 state))))
+	(let ((deep (ruby-deep-indent-paren-p (car (nth 1 state)))))
+	  (if deep
+	      (cond ((and (eq deep t) (eq (car (nth 1 state)) paren))
+		     (skip-syntax-backward " ")
+		     (setq indent (1- (current-column))))
+		    ((let ((s (ruby-parse-region (point) indent-point)))
+		       (and (nth 2 s) (> (nth 2 s) 0)
+			    (or (goto-char (cdr (nth 1 s))) t)))
+		     (forward-word -1)
+		     (setq indent (ruby-indent-size (current-column) (nth 2 state))))
+		    (t
+		     (setq indent (current-column))
+		     (cond ((eq deep 'space))
+			   (paren (setq indent (1- indent)))
+			   (t (setq indent (ruby-indent-size (1- indent) 1))))))
+	    (if (nth 3 state) (goto-char (nth 3 state))
+	      (goto-char parse-start) (back-to-indentation))
+	    (setq indent (ruby-indent-size (current-column) (nth 2 state))))
+	  (and (eq (car (nth 1 state)) paren)
+	       (ruby-deep-indent-paren-p (matching-paren paren))
+	       (search-backward (char-to-string paren))
+	       (setq indent (current-column)))))
+       ((and (nth 2 state) (> (nth 2 state) 0)) ; in nest
+	(if (null (cdr (nth 1 state)))
+	    (error "invalid nest"))
+	(goto-char (cdr (nth 1 state)))
+	(forward-word -1)		; skip back a keyword
+	(setq begin (point))
 	(cond
-	 ((nth 0 state)			; within string
-	  (setq indent nil))		;  do nothing
-	 ((car (nth 1 state))		; in paren
-	  (goto-char (cdr (nth 1 state)))
-	  (if (eq (car (nth 1 state)) ?\( )
-	      (let ((column (current-column))
-		    (s (ruby-parse-region (point) indent-point)))
-		(cond
-		 ((and (nth 2 s) (> (nth 2 s) 0))
-		  (goto-char (cdr (nth 1 s)))
-		  (forward-word -1)
-		  (setq indent (ruby-indent-size (current-column) (nth 2 state))))
-		 (t
-		  (setq indent (current-column)))))
-	    (cond
-	     ((nth 3 state)
-	      (goto-char (nth 3 state))
-	      (setq indent (ruby-indent-size (current-column) (nth 2 state))))
-	     (t
-	      (goto-char parse-start)
-	      (back-to-indentation)
-	      (setq indent (ruby-indent-size (current-column) (nth 2 state)))))
-	    ))
-	 ((and (nth 2 state)(> (nth 2 state) 0)) ; in nest
-	  (if (null (cdr (nth 1 state)))
-	      (error "invalid nest"))
-	  (goto-char (cdr (nth 1 state)))
-	  (forward-word -1)		; skip back a keyword
-	  (cond
-	   ((looking-at "do\\>[^_]")	; iter block is a special case
-	    (cond
-	     ((nth 3 state)
-	      (goto-char (nth 3 state))
-	      (setq indent (ruby-indent-size (current-column) (nth 2 state))))
-	     (t
-	      (goto-char parse-start)
-	      (back-to-indentation)
-	      (setq indent (ruby-indent-size (current-column) (nth 2 state))))))
-	   (t
-	    (setq indent (+ (current-column) ruby-indent-level)))))
-
-	 ((and (nth 2 state) (< (nth 2 state) 0)) ; in negative nest
-	  (setq indent (ruby-indent-size (current-column) (nth 2 state)))))
-
+	 ((looking-at "do\\>[^_]")	; iter block is a special case
+	  (if (nth 3 state) (goto-char (nth 3 state))
+	    (goto-char parse-start) (back-to-indentation))
+	  (setq indent (ruby-indent-size (current-column) (nth 2 state))))
+	 (t
+	  (setq indent (+ (current-column) ruby-indent-level)))))
+       
+       ((and (nth 2 state) (< (nth 2 state) 0)) ; in negative nest
+	(setq indent (ruby-indent-size (current-column) (nth 2 state)))))
+      (when indent
+	(goto-char indent-point)
+	(end-of-line)
+	(setq eol (point))
+	(beginning-of-line)
 	(cond
-	 (indent
-	  (goto-char indent-point)
+	 ((and (not (ruby-deep-indent-paren-p paren))
+	       (re-search-forward ruby-negative eol t))
+	  (and (not (eq ?_ (char-after (match-end 0))))
+	       (setq indent (- indent ruby-indent-level))))
+	 ((and
+	   (save-excursion
+	     (beginning-of-line)
+	     (not (bobp)))
+	   (or (ruby-deep-indent-paren-p t)
+	       (null (car (nth 1 state)))))
+	  ;; goto beginning of non-empty no-comment line
+	  (let (end done)
+	    (while (not done)
+	      (skip-chars-backward " \t\n")
+	      (setq end (point))
+	      (beginning-of-line)
+	      (if (re-search-forward "^\\s *#" end t)
+		  (beginning-of-line)
+		(setq done t))))
+	  (setq bol (point))
 	  (end-of-line)
-	  (setq eol (point))
-	  (beginning-of-line)
-	  (cond
-	   ((re-search-forward ruby-negative eol t)
-	    (and (not (eq ?_ (char-after (match-end 0))))
-		 (setq indent (- indent ruby-indent-level))))
-	   ;;operator terminated lines
-	   ((and
-	     (save-excursion
-	       (beginning-of-line)
-	       (not (bobp)))
-	     (or (null (car (nth 1 state))) ;not in parens
-		 (and (eq (car (nth 1 state)) ?\{)
-		      (save-excursion	;except non-block braces
-			(goto-char (cdr (nth 1 state)))
-			(or (bobp) (forward-char -1))
-			(not (ruby-expr-beg))))))
-	    ;; goto beginning of non-empty no-comment line
-	    (let (end done)
-	      (while (not done)
-		(skip-chars-backward " \t\n")
-		(setq end (point))
-		(beginning-of-line)
-		(if (re-search-forward "^\\s *#" end t)
-		    (beginning-of-line)
-		  (setq done t))))
-	    (setq bol (point))
-	    (end-of-line)
+	  ;; skip the comment at the end
+	  (skip-chars-backward " \t")
+	  (let (end (pos (point)))
+	    (beginning-of-line)
+	    (while (and (re-search-forward "#" pos t)
+			(setq end (1- (point)))
+			(or (ruby-special-char-p end)
+			    (and (setq state (ruby-parse-region parse-start end))
+				 (nth 0 state))))
+	      (setq end nil))
+	    (goto-char (or end pos))
 	    (skip-chars-backward " \t")
-	    (let ((pos (point)))
-	      (while (and (re-search-backward "#" bol t)
-			  (eq (char-before) ??))
-		(forward-char -1))
-	      (skip-chars-backward " \t")
-	      (and
-	       (setq state (ruby-parse-region parse-start (point)))
-	       (nth 0 state)
-	       (goto-char pos)))
-	    (or (bobp) (forward-char -1))
-	    (and
-	     (or (and (looking-at ruby-symbol-re)
-		      (skip-chars-backward ruby-symbol-chars)
-		      (looking-at ruby-block-hanging-re)
-		      (not (eq (point) (nth 3 state)))
-		      (save-excursion
-			(goto-char (match-end 0))
-			(not (looking-at "[a-z_]"))))
-		 (and (looking-at ruby-operator-re)
-		      (not (eq (char-after (1- (point))) ??))
-		      (not (eq (char-after (1- (point))) ?$))
-		      (or (not (eq ?/ (char-after (point))))
-			  (null (nth 0 (ruby-parse-region parse-start (point)))))
-		      (or (not (eq ?| (char-after (point))))
-			  (save-excursion
-			    (or (eolp) (forward-char -1))
-			    (cond
-			     ((search-backward "|" nil t)
-			      (skip-chars-backward " \t\n")
-			      (and (not (eolp))
-				   (progn
-				     (forward-char -1)
-				     (not (looking-at "{")))
-				   (progn
-				     (forward-word -1)
-				     (not (looking-at "do\\>[^_]")))))
-			     (t t))))))
-	     (setq indent (+ indent ruby-indent-level)))))))
-	indent)))
+	    (setq begin (if (nth 0 state) pos (cdr (nth 1 state))))
+	    (setq state (ruby-parse-region parse-start (point))))
+	  (or (bobp) (forward-char -1))
+	  (and
+	   (or (and (looking-at ruby-symbol-re)
+		    (skip-chars-backward ruby-symbol-chars)
+		    (looking-at (concat "\\<\\(" ruby-block-hanging-re "\\)\\>"))
+		    (not (eq (point) (nth 3 state)))
+		    (save-excursion
+		      (goto-char (match-end 0))
+		      (not (looking-at "[a-z_]"))))
+	       (and (looking-at ruby-operator-re)
+		    (not (ruby-special-char-p))
+		    ;; operator at the end of line
+		    (let ((c (char-after (point))))
+		      (and
+;; 		       (or (null begin)
+;; 			   (save-excursion
+;; 			     (goto-char begin)
+;; 			     (skip-chars-forward " \t")
+;; 			     (not (or (eolp) (looking-at "#")
+;; 				      (and (eq (car (nth 1 state)) ?{)
+;; 					   (looking-at "|"))))))
+		       (or (not (eq ?/ c))
+			   (null (nth 0 (ruby-parse-region (or begin parse-start) (point)))))
+		       (or (not (eq ?| (char-after (point))))
+			   (save-excursion
+			     (or (eolp) (forward-char -1))
+			     (cond
+			      ((search-backward "|" nil t)
+			       (skip-chars-backward " \t\n")
+			       (and (not (eolp))
+				    (progn
+				      (forward-char -1)
+				      (not (looking-at "{")))
+				    (progn
+				      (forward-word -1)
+				      (not (looking-at "do\\>[^_]")))))
+			      (t t))))
+		       (not (eq ?, c))
+		       (setq op-end t)))))
+	   (setq indent
+		 (cond
+		  ((and
+		    (null op-end)
+		    (not (looking-at (concat "\\<\\(" ruby-block-hanging-re "\\)\\>")))
+		    (eq (ruby-deep-indent-paren-p t) 'space)
+		    (not (bobp)))
+		   (save-excursion
+		     (widen)
+		     (goto-char (or begin parse-start))
+		     (skip-syntax-forward " ")
+		     (current-column)))
+		  ((car (nth 1 state)) indent)
+		  (t
+		   (+ indent ruby-indent-level))))))))
+      indent)))
 
 (defun ruby-electric-brace (arg)
   (interactive "P")
-  (self-insert-command (prefix-numeric-value arg))
-  (ruby-indent-line t))
+  (insert-char last-command-char 1)
+  (ruby-indent-line t)
+  (delete-char -1)
+  (self-insert-command (prefix-numeric-value arg)))
 
-(defun ruby-beginning-of-defun (&optional arg)
+(eval-when-compile
+  (defmacro defun-region-command (func args &rest body)
+    (let ((intr (car body)))
+      (when (featurep 'xemacs)
+	(if (stringp intr) (setq intr (cadr body)))
+	(and (eq (car intr) 'interactive)
+	     (setq intr (cdr intr))
+	     (setcar intr (concat "_" (car intr)))))
+      (cons 'defun (cons func (cons args body))))))
+
+(defun-region-command ruby-beginning-of-defun (&optional arg)
   "Move backward to next beginning-of-defun.
 With argument, do this that many times.
 Returns t unless search stops due to end of buffer."
@@ -614,7 +778,7 @@ Returns t unless search stops due to end
 	 (beginning-of-line)
 	 t)))
 
-(defun ruby-end-of-defun (&optional arg)
+(defun-region-command ruby-end-of-defun (&optional arg)
   "Move forward to next end of defun.
 An end of a defun is found by moving forward from the beginning of one."
   (interactive "p")
@@ -626,38 +790,123 @@ An end of a defun is found by moving for
 (defun ruby-move-to-block (n)
   (let (start pos done down)
     (setq start (ruby-calculate-indent))
-    (if (eobp)
-	nil
-      (while (and (not (bobp)) (not (eobp)) (not done))
-	(forward-line n)
+    (setq down (looking-at (concat "\\<\\(" (if (< n 0) ruby-block-end-re ruby-block-beg-re) "\\)\\>")))
+    (while (and (not done) (not (if (< n 0) (bobp) (eobp))))
+      (forward-line n)
+      (cond
+       ((looking-at "^\\s *$"))
+       ((looking-at "^\\s *#"))
+       ((and (> n 0) (looking-at "^=begin\\>"))
+	(re-search-forward "^=end\\>"))
+       ((and (< n 0) (looking-at "^=end\\>"))
+	(re-search-backward "^=begin\\>"))
+       (t
+	(setq pos (current-indentation))
 	(cond
-	 ((looking-at "^$"))
-	 ((looking-at "^\\s *#"))
-	 (t
-	  (setq pos (current-indentation))
-	  (cond
-	   ((< start pos)
-	    (setq down t))
-	   ((and down (= pos start))
-	    (setq done t))
-	   ((> start pos)
-	    (setq done t)))))
-	(if done
-	    (progn
-	      (back-to-indentation)
-	      (if (looking-at ruby-block-mid-re)
-		  (setq done nil)))))))
+	 ((< start pos)
+	  (setq down t))
+	 ((and down (= pos start))
+	  (setq done t))
+	 ((> start pos)
+	  (setq done t)))))
+      (if done
+	  (save-excursion
+	    (back-to-indentation)
+	    (if (looking-at (concat "\\<\\(" ruby-block-mid-re "\\)\\>"))
+		(setq done nil))))))
   (back-to-indentation))
 
-(defun ruby-beginning-of-block ()
-  "Move backward to next beginning-of-block."
-  (interactive)
-  (ruby-move-to-block -1))
+(defun-region-command ruby-beginning-of-block (&optional arg)
+  "Move backward to next beginning-of-block"
+  (interactive "p")
+  (ruby-move-to-block (- (or arg 1))))
 
-(defun ruby-end-of-block ()
-  "Move forward to next beginning-of-block."
-  (interactive)
-  (ruby-move-to-block 1))
+(defun-region-command ruby-end-of-block (&optional arg)
+  "Move forward to next beginning-of-block"
+  (interactive "p")
+  (ruby-move-to-block (or arg 1)))
+
+(defun-region-command ruby-forward-sexp (&optional cnt)
+  (interactive "p")
+  (if (and (numberp cnt) (< cnt 0))
+      (ruby-backward-sexp (- cnt))
+    (let ((i (or cnt 1)))
+      (condition-case nil
+	  (while (> i 0)
+	    (skip-syntax-forward " ")
+	    (cond ((looking-at "\\?\\(\\\\[CM]-\\)*\\\\?\\S ")
+		   (goto-char (match-end 0)))
+		  ((progn
+		     (skip-chars-forward ",.:;|&^~=!?\\+\\-\\*")
+		     (looking-at "\\s("))
+		   (goto-char (scan-sexps (point) 1)))
+		  ((and (looking-at (concat "\\<\\(" ruby-block-beg-re "\\)\\>"))
+			(not (eq (char-before (point)) ?.))
+			(not (eq (char-before (point)) ?:)))
+		   (ruby-end-of-block)
+		   (forward-word 1))
+		  ((looking-at "\\(\\$\\|@@?\\)?\\sw")
+		   (while (progn
+			    (while (progn (forward-word 1) (looking-at "_")))
+			    (cond ((looking-at "::") (forward-char 2) t)
+				  ((> (skip-chars-forward ".") 0))
+				  ((looking-at "\\?\\|!\\(=[~=>]\\|[^~=]\\)")
+				   (forward-char 1) nil)))))
+		  ((let (state expr)
+		     (while
+			 (progn
+			   (setq expr (or expr (ruby-expr-beg)
+					  (looking-at "%\\sw?\\Sw\\|[\"'`/]")))
+			   (nth 1 (setq state (apply 'ruby-parse-partial nil state))))
+		       (setq expr t)
+		       (skip-chars-forward "<"))
+		     (not expr))))
+	    (setq i (1- i)))
+	((error) (forward-word 1)))
+      i)))
+
+(defun-region-command ruby-backward-sexp (&optional cnt)
+  (interactive "p")
+  (if (and (numberp cnt) (< cnt 0))
+      (ruby-forward-sexp (- cnt))
+    (let ((i (or cnt 1)))
+      (condition-case nil
+	  (while (> i 0)
+	    (skip-chars-backward " \t\n,.:;|&^~=!?\\+\\-\\*")
+	    (forward-char -1)
+	    (cond ((looking-at "\\s)")
+		   (goto-char (scan-sexps (1+ (point)) -1))
+		   (case (char-before)
+		     (?% (forward-char -1))
+		     ('(?q ?Q ?w ?W ?r ?x)
+		      (if (eq (char-before (1- (point))) ?%) (forward-char -2))))
+		   nil)
+		  ((looking-at "\\s\"\\|\\\\\\S_")
+		   (let ((c (char-to-string (char-before (match-end 0)))))
+		     (while (and (search-backward c)
+				 (oddp (skip-chars-backward "\\")))))
+		   nil)
+		  ((looking-at "\\s.\\|\\s\\")
+		   (if (ruby-special-char-p) (forward-char -1)))
+		  ((looking-at "\\s(") nil)
+		  (t
+		   (forward-char 1)
+		   (while (progn (forward-word -1)
+				 (case (char-before)
+				   (?_ t)
+				   (?. (forward-char -1) t)
+				   ((?$ ?@)
+				    (forward-char -1)
+				    (and (eq (char-before) (char-after)) (forward-char -1)))
+				   (?:
+				    (forward-char -1)
+				    (eq (char-before) :)))))
+		   (if (looking-at (concat "\\<\\(" ruby-block-end-re "\\)\\>"))
+		       (ruby-beginning-of-block))
+		   nil))
+	    (setq i (1- i)))
+	((error)))
+      i)))
 
 (defun ruby-reindent-then-newline-and-indent ()
   (interactive "*")
@@ -694,6 +943,65 @@ An end of a defun is found by moving for
   (ruby-beginning-of-defun)
   (re-search-backward "^\n" (- (point) 1) t))
 
+(defun ruby-indent-exp (&optional shutup-p)
+  "Indent each line in the balanced expression following point syntactically.
+If optional SHUTUP-P is non-nil, no errors are signalled if no
+balanced expression is found."
+  (interactive "*P")
+  (let ((here (point-marker)) start top column (nest t))
+    (set-marker-insertion-type here t)
+    (unwind-protect
+	(progn
+	  (beginning-of-line)
+	  (setq start (point) top (current-indentation))
+	  (while (and (not (eobp))
+		      (progn
+			(setq column (ruby-calculate-indent start))
+			(cond ((> column top)
+			       (setq nest t))
+			      ((and (= column top) nest)
+			       (setq nest nil) t))))
+	    (ruby-indent-to column)
+	    (beginning-of-line 2)))
+      (goto-char here)
+      (set-marker here nil))))
+
+(defun ruby-add-log-current-method ()
+  "Return current method string."
+  (condition-case nil
+      (save-excursion
+	(let ((mlist nil) (indent 0))
+	  ;; get current method (or class/module)
+	  (if (re-search-backward
+	       (concat "^[ \t]*\\(def\\|class\\|module\\)[ \t]+"
+		       "\\(" 
+		       ;; \\. for class method
+			"\\(" ruby-symbol-re "\\|\\." "\\)" 
+			"+\\)")
+	       nil t)
+	      (progn
+		(setq mlist (list (match-string 2)))
+		(goto-char (match-beginning 1))
+		(setq indent (current-column))
+		(beginning-of-line)))
+	  ;; nest class/module
+	  (while (and (> indent 0)
+		      (re-search-backward
+		       (concat
+			"^[ \t]*\\(class\\|module\\)[ \t]+"
+			"\\([A-Z]" ruby-symbol-re "+\\)")
+		       nil t))
+	    (goto-char (match-beginning 1))
+	    (if (< (current-column) indent)
+		(progn
+		  (setq mlist (cons (match-string 2) mlist))
+		  (setq indent (current-column))
+		  (beginning-of-line))))
+	  ;; generate string
+	  (if (consp mlist)
+	      (mapconcat (function identity) mlist "::")
+	    nil)))))
+
 (cond
  ((featurep 'font-lock)
   (or (boundp 'font-lock-variable-name-face)
@@ -703,32 +1011,18 @@ An end of a defun is found by moving for
 	'(
 	  ;; #{ }, #$hoge, #@foo are not comments
 	  ("\\(#\\)[{$@]" 1 (1 . nil))
-	  ;; the last $' in the string ,'...$' is not variable
-	  ;; the last ?' in the string ,'...?' is not ascii code
-	  ("\\(^\\|[[\\s <+(,=]\\)\\('\\)[^'\n\\\\]*\\(\\\\.[^'\n\\\\]*\\)*[?$]\\('\\)"
-	   (2 (7 . nil))
-	   (4 (7 . nil)))
-	  ;; the last $` in the string ,`...$` is not variable
-	  ;; the last ?` in the string ,`...?` is not ascii code
-	  ("\\(^\\|[[\\s <+(,=]\\)\\(`\\)[^`\n\\\\]*\\(\\\\.[^`\n\\\\]*\\)*[?$]\\(`\\)"
+	  ;; the last $', $", $` in the respective string is not variable
+	  ;; the last ?', ?", ?` in the respective string is not ascii code
+	  ("\\(^\\|[\[ \t\n<+\(,=]\\)\\(['\"`]\\)\\(\\\\.\\|\\2\\|[^'\"`\n\\\\]\\)*?\\\\?[?$]\\(\\2\\)"
 	   (2 (7 . nil))
 	   (4 (7 . nil)))
-	  ;; the last $" in the string ,"...$" is not variable
-	  ;; the last ?" in the string ,"...?" is not ascii code
-	  ("\\(^\\|[[\\s <+(,=]\\)\\(\"\\)[^\"\n\\\\]*\\(\\\\.[^\"\n\\\\]*\\)*[?$]\\(\"\\)"
-	   (2 (7 . nil))
-	   (4 (7 . nil)))
 	  ;; $' $" $` .... are variables
 	  ;; ?' ?" ?` are ascii codes
-	  ("[?$][#\"'`]" 0 (1 . nil))
+	  ("\\(^\\|[^\\\\]\\)\\(\\\\\\\\\\)*[?$]\\([#\"'`]\\)" 3 (1 . nil))
 	  ;; regexps
 	  ("\\(^\\|[=(,~?:;]\\|\\(^\\|\\s \\)\\(if\\|elsif\\|unless\\|while\\|until\\|when\\|and\\|or\\|&&\\|||\\)\\|g?sub!?\\|scan\\|split!?\\)\\s *\\(/\\)[^/\n\\\\]*\\(\\\\.[^/\n\\\\]*\\)*\\(/\\)"
 	   (4 (7 . ?/))
 	   (6 (7 . ?/)))
-	  ;; %Q!...!
-	  ("\\(^\\|[[\\s <+(,=]\\)%[xrqQ]?\\([^a-zA-Z0-9 \n]\\)[^\n\\\\]*\\(\\\\.[^\n\\\\]*\\)*\\(\\2\\)"
-	   (2 (7 . nil))
-	   (4 (7 . nil)))
 	  ("^\\(=\\)begin\\(\\s \\|$\\)" 1 (7 . nil))
 	  ("^\\(=\\)end\\(\\s \\|$\\)" 1 (7 . nil))))
 
@@ -744,9 +1038,11 @@ An end of a defun is found by moving for
 	    '(lambda ()
 	       (make-local-variable 'font-lock-defaults)
 	       (make-local-variable 'font-lock-keywords)
+	       (make-local-variable 'font-lock-syntax-table)
 	       (make-local-variable 'font-lock-syntactic-keywords)
 	       (setq font-lock-defaults '((ruby-font-lock-keywords) nil nil))
 	       (setq font-lock-keywords ruby-font-lock-keywords)
+	       (setq font-lock-syntax-table ruby-font-lock-syntax-table)
 	       (setq font-lock-syntactic-keywords ruby-font-lock-syntactic-keywords)))))
 
   (defun ruby-font-lock-docs (limit)
@@ -775,10 +1071,47 @@ An end of a defun is found by moving for
 	    t)
 	nil)))
 
+  (defvar ruby-font-lock-syntax-table
+    (let* ((tbl (copy-syntax-table ruby-mode-syntax-table)))
+      (modify-syntax-entry ?_ "w" tbl)
+      tbl))
+
+  (defun ruby-font-lock-here-docs (limit)
+    (if (re-search-forward ruby-here-doc-beg-re limit t)
+	(let (beg)
+	  (beginning-of-line)
+          (forward-line)
+	  (setq beg (point))
+	  (if (re-search-forward (ruby-here-doc-end-match) nil t)
+	      (progn
+		(set-match-data (list beg (point)))
+		t)))))
+
+  (defun ruby-font-lock-maybe-here-docs (limit)
+    (let (beg)
+      (save-excursion
+	(if (re-search-backward ruby-here-doc-beg-re nil t)
+	    (progn
+	      (beginning-of-line)
+              (forward-line)
+	      (setq beg (point)))))
+      (if (and beg
+	       (let ((end-match (ruby-here-doc-end-match)))
+                 (and (not (re-search-backward end-match beg t))
+		      (re-search-forward end-match nil t))))
+	  (progn
+	    (set-match-data (list beg (point)))
+	    t)
+          nil)))
+
   (defvar ruby-font-lock-keywords
     (list
+     ;; functions
+     '("^\\s *def\\s +\\([^( \t\n]+\\)"
+       1 font-lock-function-name-face)
+     ;; keywords
      (cons (concat
-	    "\\(^\\|[^_:.@$]\\|\\.\\.\\)\\b\\("
+	    "\\(^\\|[^_:.@$]\\|\\.\\.\\)\\b\\(defined\\?\\|\\("
 	    (mapconcat
 	     'identity
 	     '("alias"
@@ -818,10 +1151,10 @@ An end of a defun is found by moving for
 	       "yield"
 	       )
 	     "\\|")
-	    "\\)\\>\\([^_]\\|$\\)")
+	    "\\)\\>\\)")
 	   2)
      ;; variables
-     '("\\(^\\|[^_:.@$]\\|\\.\\.\\)\\b\\(nil\\|self\\|true\\|false\\)\\b\\([^_]\\|$\\)"
+     '("\\(^\\|[^_:.@$]\\|\\.\\.\\)\\b\\(nil\\|self\\|true\\|false\\)\\>"
        2 font-lock-variable-name-face)
      ;; variables
      '("\\(\\$\\([^a-zA-Z0-9 \n]\\|[0-9]\\)\\)\\W"
@@ -833,19 +1166,30 @@ An end of a defun is found by moving for
        0 font-lock-comment-face t)
      '(ruby-font-lock-maybe-docs
        0 font-lock-comment-face t)
+     ;; "here" document
+     '(ruby-font-lock-here-docs
+       0 font-lock-string-face t)
+     '(ruby-font-lock-maybe-here-docs
+       0 font-lock-string-face t)
+     `(,ruby-here-doc-beg-re
+       0 font-lock-string-face t)
+     ;; general delimited string
+     '("\\(^\\|[[ \t\n<+(,=]\\)\\(%[xrqQwW]?\\([^<[{(a-zA-Z0-9 \n]\\)[^\n\\\\]*\\(\\\\.[^\n\\\\]*\\)*\\(\\3\\)\\)"
+       (2 font-lock-string-face))
      ;; constants
      '("\\(^\\|[^_]\\)\\b\\([A-Z]+\\(\\w\\|_\\)*\\)"
        2 font-lock-type-face)
-     ;; functions
-     '("^\\s *def\\s +\\([^( ]+\\)"
-       1 font-lock-function-name-face)
      ;; symbols
      '("\\(^\\|[^:]\\)\\(:\\([-+~]@?\\|[/%&|^`]\\|\\*\\*?\\|<\\(<\\|=>?\\)?\\|>[>=]?\\|===?\\|=~\\|\\[\\]=?\\|\\(\\w\\|_\\)+\\([!?=]\\|\\b_*\\)\\|#{[^}\n\\\\]*\\(\\\\.[^}\n\\\\]*\\)*}\\)\\)"
        2 font-lock-reference-face)
      ;; expression expansion
      '("#\\({[^}\n\\\\]*\\(\\\\.[^}\n\\\\]*\\)*}\\|\\(\\$\\|@\\|@@\\)\\(\\w\\|_\\)+\\)"
-       0 font-lock-variable-name-face t))
-    "Additional expressions to highlight in `ruby-mode'."))
+       0 font-lock-variable-name-face t)
+     ;; warn lower camel case
+     ;'("\\<[a-z]+[a-z0-9]*[A-Z][A-Za-z0-9]*\\([!?]?\\|\\>\\)"
+     ;  0 font-lock-warning-face)
+     )
+    "*Additional expressions to highlight in ruby mode."))
 
  ((featurep 'hilit19)
   (hilit-set-mode-patterns
@@ -868,6 +1212,7 @@ An end of a defun is found by moving for
 
 ;; XEmacs addition
 ;;;###autoload(add-to-list 'auto-mode-alist '("\\.rb$" . ruby-mode))
+;;;###autoload(add-to-list 'auto-mode-alist '("\\.rake$" . ruby-mode))
 
 (provide 'ruby-mode)
 



1.3       +746 -405  XEmacs/packages/xemacs-packages/ruby-modes/ruby-mode.el.upstream

Index: ruby-mode.el.upstream
===================================================================
RCS file: /pack/xemacscvs/XEmacs/packages/xemacs-packages/ruby-modes/ruby-mode.el.upstream,v
retrieving revision 1.2
retrieving revision 1.3
diff -u -p -r1.2 -r1.3
--- ruby-mode.el.upstream	2003/01/06 21:07:16	1.2
+++ ruby-mode.el.upstream	2009/07/19 08:18:15	1.3
@@ -2,11 +2,11 @@
 ;;;  ruby-mode.el -
 ;;;
 ;;;  $Author: matz $
-;;;  $Date: 2002/12/06 05:15:56 $
+;;;  $Date: 2005/11/30 15:56:57 $
 ;;;  created at: Fri Feb  4 14:49:13 JST 1994
 ;;;
 
-(defconst ruby-mode-revision "$Revision: 1.25.2.11 $")
+(defconst ruby-mode-revision "$Revision: 1.74.2.14 $")
 
 (defconst ruby-mode-version
   (progn
@@ -47,11 +47,22 @@
 
 (defconst ruby-block-end-re "end")
 
+(defconst ruby-here-doc-beg-re
+  "<<\\(-\\)?\\(\\([a-zA-Z0-9_]+\\)\\|[\"]\\([^\"]+\\)[\"]\\|[']\\([^']+\\)[']\\)")
+
+(defun ruby-here-doc-end-match ()
+  (concat "^"
+	  (if (match-string 1) "[ \t]*" nil)
+	  (regexp-quote
+	   (or (match-string 3)
+	       (match-string 4)
+	       (match-string 5)))))
+
 (defconst ruby-delimiter
-  (concat "[?$/%(){}#\"'`.:]\\|\\[\\|\\]\\|\\<\\("
+  (concat "[?$/%(){}#\"'`.:]\\|<<\\|\\[\\|\\]\\|\\<\\("
 	  ruby-block-beg-re
 	  "\\|" ruby-block-end-re
-	  "\\)\\>\\|^=begin")
+	  "\\)\\>\\|^=begin\\|" ruby-here-doc-beg-re)
   )
 
 (defconst ruby-negative
@@ -79,11 +90,12 @@
   (define-key ruby-mode-map "}" 'ruby-electric-brace)
   (define-key ruby-mode-map "\e\C-a" 'ruby-beginning-of-defun)
   (define-key ruby-mode-map "\e\C-e" 'ruby-end-of-defun)
-  (define-key ruby-mode-map "\e\C-b" 'ruby-beginning-of-block)
-  (define-key ruby-mode-map "\e\C-f" 'ruby-end-of-block)
+  (define-key ruby-mode-map "\e\C-b" 'ruby-backward-sexp)
+  (define-key ruby-mode-map "\e\C-f" 'ruby-forward-sexp)
   (define-key ruby-mode-map "\e\C-p" 'ruby-beginning-of-block)
   (define-key ruby-mode-map "\e\C-n" 'ruby-end-of-block)
   (define-key ruby-mode-map "\e\C-h" 'ruby-mark-defun)
+  (define-key ruby-mode-map "\e\C-q" 'ruby-indent-exp)
   (define-key ruby-mode-map "\t" 'ruby-indent-command)
   (define-key ruby-mode-map "\C-c\C-e" 'ruby-insert-end)
   (define-key ruby-mode-map "\C-j" 'ruby-reindent-then-newline-and-indent)
@@ -123,34 +135,79 @@
   (modify-syntax-entry ?\] ")[" ruby-mode-syntax-table)
   )
 
-(defvar ruby-indent-level 2
-  "*Indentation of ruby statements.")
+(defcustom ruby-indent-tabs-mode nil
+  "*Indentation can insert tabs in ruby mode if this is non-nil."
+:type 'boolean :group 'ruby)
+
+(defcustom ruby-indent-level 2
+  "*Indentation of ruby statements."
+:type 'integer :group 'ruby)
+
+(defcustom ruby-comment-column 32
+  "*Indentation column of comments."
+:type 'integer :group 'ruby)
+
+(defcustom ruby-deep-arglist t
+  "*Deep indent lists in parenthesis when non-nil.
+Also ignores spaces after parenthesis when 'space."
+:group 'ruby)
+
+(defcustom ruby-deep-indent-paren '(?\( ?\[ ?\] t)
+  "*Deep indent lists in parenthesis when non-nil. t means continuous line.
+Also ignores spaces after parenthesis when 'space."
+:group 'ruby)
+
+(defcustom ruby-deep-indent-paren-style 'space
+  "Default deep indent style."
+:options '(t nil space) :group 'ruby)
 
 (eval-when-compile (require 'cl))
-(defun ruby-imenu-create-index ()
-  (let ((index-alist '())
-	class-name class-begin method-name method-begin decl)
-    (goto-char (point-min))
-    (while (re-search-forward "^\\s *\\(class\\|def\\)\\s *\\([^(\n ]+\\)" nil t)
-      (setq decl (buffer-substring (match-beginning 1) (match-end 1)))
+(defun ruby-imenu-create-index-in-block (prefix beg end)
+  (let ((index-alist '()) (case-fold-search nil)
+	name next pos decl sing)
+    (goto-char beg)
+    (while (re-search-forward "^\\s *\\(\\(class\\>\\(\\s *<<\\)?\\|module\\>\\)\\s *\\([^\(<\n ]+\\)\\|\\(def\\|alias\\)\\>\\s *\\([^\(\n ]+\\)\\)" end t)
+      (setq sing (match-beginning 3))
+      (setq decl (match-string 5))
+      (setq next (match-end 0))
+      (setq name (or (match-string 4) (match-string 6)))
+      (setq pos (match-beginning 0))
       (cond
-       ((string= "class" decl)
-	(setq class-begin (match-beginning 2))
-	(setq class-name (buffer-substring class-begin (match-end 2)))
-	(push (cons class-name (match-beginning 0)) index-alist)
-	(ruby-mark-defun)
-	(save-restriction
-	  (narrow-to-region (region-beginning) (region-end))
-         (while (re-search-forward "^\\s *def\\s *\\([^(\n ]+\\)" nil 'move)
-	    (setq method-begin (match-beginning 1))
-	    (setq method-name (buffer-substring method-begin (match-end 1)))
-	    (push (cons (concat class-name "#" method-name) (match-beginning 0)) index-alist))))
+       ((string= "alias" decl)
+	(if prefix (setq name (concat prefix name)))
+	(push (cons name pos) index-alist))
        ((string= "def" decl)
-	(setq method-begin (match-beginning 2))
-	(setq method-name (buffer-substring method-begin (match-end 2)))
-	(push (cons method-name (match-beginning 0)) index-alist))))
+	(if prefix
+	    (setq name
+		  (cond
+		   ((string-match "^self\." name)
+		    (concat (substring prefix 0 -1) (substring name 4)))
+		  (t (concat prefix name)))))
+	(push (cons name pos) index-alist)
+	(ruby-accurate-end-of-block end))
+       (t
+	(if (string= "self" name)
+	    (if prefix (setq name (substring prefix 0 -1)))
+	  (if prefix (setq name (concat (substring prefix 0 -1) "::" name)))
+	  (push (cons name pos) index-alist))
+	(ruby-accurate-end-of-block end)
+	(setq beg (point))
+	(setq index-alist
+	      (nconc (ruby-imenu-create-index-in-block
+		      (concat name (if sing "." "#"))
+		      next beg) index-alist))
+	(goto-char beg))))
     index-alist))
 
+(defun ruby-imenu-create-index ()
+  (nreverse (ruby-imenu-create-index-in-block nil (point-min) nil)))
+
+(defun ruby-accurate-end-of-block (&optional end)
+  (let (state)
+    (or end (setq end (point-max)))
+    (while (and (setq state (apply 'ruby-parse-partial end state))
+		(>= (nth 2 state) 0) (< (point) end)))))
+
 (defun ruby-mode-variables ()
   (set-syntax-table ruby-mode-syntax-table)
   (setq local-abbrev-table ruby-mode-abbrev-table)
@@ -163,9 +220,10 @@
   (make-variable-buffer-local 'comment-end)
   (setq comment-end "")
   (make-variable-buffer-local 'comment-column)
-  (setq comment-column 32)
+  (setq comment-column ruby-comment-column)
   (make-variable-buffer-local 'comment-start-skip)
-  (setq comment-start-skip "\\(^\\|\\s-\\);?#+ *")
+  (setq comment-start-skip "#+ *")
+  (setq indent-tabs-mode ruby-indent-tabs-mode)
   (make-local-variable 'parse-sexp-ignore-comments)
   (setq parse-sexp-ignore-comments t)
   (make-local-variable 'paragraph-start)
@@ -194,6 +252,9 @@ The variable ruby-indent-level controls 
   (make-local-variable 'imenu-create-index-function)
   (setq imenu-create-index-function 'ruby-imenu-create-index)
 
+  (make-local-variable 'add-log-current-defun-function)
+  (setq add-log-current-defun-function 'ruby-add-log-current-method)
+
   (run-hooks 'ruby-mode-hook))
 
 (defun ruby-current-indentation ()
@@ -231,32 +292,46 @@ The variable ruby-indent-level controls 
 	  (indent-to x)
 	  (move-to-column (+ x shift))))))
 
+(defun ruby-special-char-p (&optional pnt)
+  (setq pnt (or pnt (point)))
+  (let ((c (char-before pnt)) (b (and (< (point-min) pnt) (char-before (1- pnt)))))
+    (cond ((or (eq c ??) (eq c ?$)))
+	  ((and (eq c ?:) (or (not b) (eq (char-syntax b) ? ))))
+	  ((eq c ?\\) (eq b ??)))))
+
 (defun ruby-expr-beg (&optional option)
   (save-excursion
     (store-match-data nil)
-    (skip-chars-backward " \t")
-    (cond
-     ((bolp) t)
-     ((looking-at "\\?")
-      (or (bolp) (forward-char -1))
-      (not (looking-at "\\sw")))
-     (t
-      (forward-char -1)
-      (or (looking-at ruby-operator-re)
-	  (looking-at "[\\[({,;]")
-	  (and (not (eq option 'modifier))
-	       (looking-at "[!?]"))
-	  (and (looking-at ruby-symbol-re)
-	       (skip-chars-backward ruby-symbol-chars)
-	       (cond
-		((or (looking-at ruby-block-beg-re)
-		     (looking-at ruby-block-op-re)
-		     (looking-at ruby-block-mid-re))
-		 (goto-char (match-end 0))
-		 (looking-at "\\>"))
-		(t
-		 (and (not (eq option 'expr-arg))
-		      (looking-at "[a-zA-Z][a-zA-z0-9_]* +/[^ \t]"))))))))))
+    (let ((space (skip-chars-backward " \t"))
+	  (start (point)))
+      (cond
+       ((bolp) t)
+       ((progn
+	  (forward-char -1)
+	  (and (looking-at "\\?")
+	       (or (eq (char-syntax (char-before (point))) ?w)
+		   (ruby-special-char-p))))
+	nil)
+       ((and (eq option 'heredoc) (< space 0)) t)
+       ((or (looking-at ruby-operator-re)
+	    (looking-at "[\\[({,;]")
+	    (and (looking-at "[!?]")
+		 (or (not (eq option 'modifier))
+		     (bolp)
+		     (save-excursion (forward-char -1) (looking-at "\\Sw$"))))
+	    (and (looking-at ruby-symbol-re)
+		 (skip-chars-backward ruby-symbol-chars)
+		 (cond
+		  ((or (looking-at (concat "\\<\\(" ruby-block-beg-re
+					   "|" ruby-block-op-re
+					   "|" ruby-block-mid-re "\\)\\>")))
+		   (goto-char (match-end 0))
+		   (not (looking-at "\\s_")))
+		  ((eq option 'expr-qstr)
+		   (looking-at "[a-zA-Z][a-zA-z0-9_]* +%[^ \t]"))
+		  ((eq option 'expr-re)
+		   (looking-at "[a-zA-Z][a-zA-z0-9_]* +/[^ \t]"))
+		  (t nil)))))))))
 
 (defun ruby-forward-string (term &optional end no-error expand)
   (let ((n 1) (c (string-to-char term))
@@ -271,327 +346,413 @@ The variable ruby-indent-level controls 
       (forward-char -1))
     (cond ((zerop n))
 	  (no-error nil)
-	  (error "unterminated string"))))
+	  ((error "unterminated string")))))
 
-(defun ruby-parse-region (start end)
-  (let ((indent-point end)
-	  (indent 0)
-	  (in-string nil)
-	  (in-paren nil)
-	  (depth 0)
-	  (nest nil)
-	  (pcol nil))
-    (save-excursion
-	(if start
-	    (goto-char start)
-	  (ruby-beginning-of-indent))
-	(save-restriction
-	  (narrow-to-region (point) end)
-	  (while (and (> indent-point (point))
-		      (re-search-forward ruby-delimiter indent-point t))
-	    (or depth (setq depth 0))
-	    (let ((pnt (point)) w re expand)
-	      (goto-char (match-beginning 0))
-	      (cond
-	       ((or (looking-at "\"")	;skip string
-		    (looking-at "`"))
-		(cond
-		 ((and (not (eobp))
-		       (ruby-forward-string (buffer-substring (point) (1+ (point))) indent-point t t))
-		  nil)
-		 (t
-		  (setq in-string (point))
-		  (goto-char indent-point))))
-	       ((looking-at "'")
-		(cond
-		 ((and (not (eobp))
-		       (re-search-forward "[^\\]\\(\\\\\\\\\\)*'" indent-point t))
-		  nil)
-		 (t
-		  (setq in-string (point))
-		  (goto-char indent-point))))
-	       ((looking-at "/")
-		(cond
-		 ((and (not (eobp)) (ruby-expr-beg))
-		  (if (ruby-forward-string "/" indent-point t t)
-		      nil
-		    (setq in-string (point))
-		    (goto-char indent-point)))
-		 (t
-		  (goto-char pnt))))
-	       ((looking-at "%")
-		(cond
-		 ((and (not (eobp)) (ruby-expr-beg 'expr-arg)
-		       (not (looking-at "%="))
-		       (looking-at "%[Qqrxw]?\\(.\\)"))
-		  (goto-char (match-beginning 1))
-		  (setq expand (not (eq (char-before) ?q)))
-		  (setq w (buffer-substring (match-beginning 1)
-					    (match-end 1)))
-		  (cond
-		   ((string= w "[") (setq re "]["))
-		   ((string= w "{") (setq re "}{"))
-		   ((string= w "(") (setq re ")("))
-		   ((string= w "<") (setq re "><"))
-		   ((or (and expand (string= w "\\"))
-			(member w '("*" "." "+" "?" "^" "$")))
-		    (setq w (concat "\\" w))))
-		  (unless (cond (re (ruby-forward-string re indent-point t expand))
-				(expand (ruby-forward-string w indent-point t t))
-				(t (re-search-forward
-				    (if (string= w "\\")
-					"\\\\[^\\]*\\\\"
-				      (concat "[^\\]\\(\\\\\\\\\\)*" w))
-				    indent-point t)))
-		    (setq in-string (point))
-		    (goto-char indent-point)))
-		 (t
-		  (goto-char pnt))))
-	       ((looking-at "\\?")	;skip ?char
-		(cond
-		 ((ruby-expr-beg)
-		  (looking-at "?\\(\\\\C-\\|\\\\M-\\)*.")
-		  (goto-char (match-end 0)))
-		 (t
-		  (goto-char pnt))))
-	       ((looking-at "\\$")	;skip $char
-		(goto-char pnt)
-		(forward-char 1))
-	       ((looking-at "#")	;skip comment
-		(forward-line 1)
-		(goto-char (point))
-		)
-	       ((looking-at "(")
+(defun ruby-deep-indent-paren-p (c)
+  (cond ((listp ruby-deep-indent-paren)
+	 (let ((deep (assoc c ruby-deep-indent-paren)))
+	   (cond (deep
+		  (or (cdr deep) ruby-deep-indent-paren-style))
+		 ((memq c ruby-deep-indent-paren)
+		  ruby-deep-indent-paren-style))))
+	((eq c ruby-deep-indent-paren) ruby-deep-indent-paren-style)
+	((eq c ?\( ) ruby-deep-arglist)))
+
+(defun ruby-parse-partial (&optional end in-string nest depth pcol indent)
+  (or depth (setq depth 0))
+  (or indent (setq indent 0))
+  (when (re-search-forward ruby-delimiter end 'move)
+    (let ((pnt (point)) w re expand)
+      (goto-char (match-beginning 0))
+      (cond
+       ((and (memq (char-before) '(?@ ?$)) (looking-at "\\sw"))
+	(goto-char pnt))
+       ((looking-at "[\"`]")		;skip string
+	(cond
+	 ((and (not (eobp))
+	       (ruby-forward-string (buffer-substring (point) (1+ (point))) end t t))
+	  nil)
+	 (t
+	  (setq in-string (point))
+	  (goto-char end))))
+       ((looking-at "'")
+	(cond
+	 ((and (not (eobp))
+	       (re-search-forward "[^\\]\\(\\\\\\\\\\)*'" end t))
+	  nil)
+	 (t
+	  (setq in-string (point))
+	  (goto-char end))))
+       ((looking-at "/")
+	(cond
+	 ((and (not (eobp)) (ruby-expr-beg 'expr-re))
+	  (if (ruby-forward-string "/" end t t)
+	      nil
+	    (setq in-string (point))
+	    (goto-char end)))
+	 (t
+	  (goto-char pnt))))
+       ((looking-at "%")
+	(cond
+	 ((and (not (eobp))
+	       (ruby-expr-beg 'expr-qstr)
+	       (not (looking-at "%="))
+	       (looking-at "%[QqrxWw]?\\([^a-zA-Z0-9 \t\n]\\)"))
+	  (goto-char (match-beginning 1))
+	  (setq expand (not (memq (char-before) '(?q ?w))))
+	  (setq w (match-string 1))
+	  (cond
+	   ((string= w "[") (setq re "]["))
+	   ((string= w "{") (setq re "}{"))
+	   ((string= w "(") (setq re ")("))
+	   ((string= w "<") (setq re "><"))
+	   ((and expand (string= w "\\"))
+	    (setq w (concat "\\" w))))
+	  (unless (cond (re (ruby-forward-string re end t expand))
+			(expand (ruby-forward-string w end t t))
+			(t (re-search-forward
+			    (if (string= w "\\")
+				"\\\\[^\\]*\\\\"
+			      (concat "[^\\]\\(\\\\\\\\\\)*" w))
+			    end t)))
+	    (setq in-string (point))
+	    (goto-char end)))
+	 (t
+	  (goto-char pnt))))
+       ((looking-at "\\?")		;skip ?char
+	(cond
+	 ((and (ruby-expr-beg)
+	       (looking-at "?\\(\\\\C-\\|\\\\M-\\)*\\\\?."))
+	  (goto-char (match-end 0)))
+	 (t
+	  (goto-char pnt))))
+       ((looking-at "\\$")		;skip $char
+	(goto-char pnt)
+	(forward-char 1))
+       ((looking-at "#")		;skip comment
+	(forward-line 1)
+	(goto-char (point))
+	)
+       ((looking-at "[\\[{(]")
+	(let ((deep (ruby-deep-indent-paren-p (char-after))))
+	  (if (and deep (or (not (eq (char-after) ?\{)) (ruby-expr-beg)))
+	      (progn
+		(and (eq deep 'space) (looking-at ".\\s +[^# \t\n]")
+		     (setq pnt (1- (match-end 0))))
 		(setq nest (cons (cons (char-after (point)) pnt) nest))
 		(setq pcol (cons (cons pnt depth) pcol))
-		(setq depth 0)
-		(goto-char pnt)
-		)
-	       ((looking-at "[\\[{]")
-		(setq nest (cons (cons (char-after (point)) pnt) nest))
-		(setq depth (1+ depth))
-		(goto-char pnt)
-		)
-	       ((looking-at ")")
-		(setq nest (cdr nest))
-		(setq depth (cdr (car pcol)))
-		(setq pcol (cdr pcol))
-		(goto-char pnt))
-	       ((looking-at "[])}]")
-		(setq nest (cdr nest))
-		(setq depth (1- depth))
-		(goto-char pnt))
-	       ((looking-at ruby-block-end-re)
-		(if (or (and (not (bolp))
-			     (progn
-			       (forward-char -1)
-			       (setq w (char-after (point)))
-			       (or (eq ?_ w)
-				   (eq ?. w))))
-			(progn
-			  (goto-char pnt)
-			  (setq w (char-after (point)))
-			  (or (eq ?_ w)
-			      (eq ?! w)
-			      (eq ?? w))))
-		    nil
-		  (setq nest (cdr nest))
-		  (setq depth (1- depth)))
-		(goto-char pnt))
-	       ((looking-at "def\\s +[^(\n;]*")
-		(if (or (bolp)
-			(progn
-			  (forward-char -1)
-			  (not (eq ?_ (char-after (point))))))
-		    (progn
-		      (setq nest (cons (cons nil pnt) nest))
-		      (setq depth (1+ depth))))
-		(goto-char (match-end 0)))
-	       ((looking-at ruby-block-beg-re)
-		(and
-		 (save-match-data
-                   (or (not (looking-at "do\\>[^_]"))
-                       (save-excursion
-                         (back-to-indentation)
-			 (not (looking-at ruby-non-block-do-re)))))
-		 (or (bolp)
+		(setq depth 0))
+	    (setq nest (cons (cons (char-after (point)) pnt) nest))
+	    (setq depth (1+ depth))))
+	(goto-char pnt)
+	)
+       ((looking-at "[])}]")
+	(if (ruby-deep-indent-paren-p (matching-paren (char-after)))
+	    (setq depth (cdr (car pcol)) pcol (cdr pcol))
+	  (setq depth (1- depth)))
+	(setq nest (cdr nest))
+	(goto-char pnt))
+       ((looking-at (concat "\\<\\(" ruby-block-end-re "\\)\\>"))
+	(if (or (and (not (bolp))
 		     (progn
 		       (forward-char -1)
 		       (setq w (char-after (point)))
-		       (not (or (eq ?_ w)
-				(eq ?. w)))))
-		 (goto-char pnt)
-		 (setq w (char-after (point)))
-		 (not (eq ?_ w))
-		 (not (eq ?! w))
-		 (not (eq ?? w))
-		 (skip-chars-forward " \t")
-		 (goto-char (match-beginning 0))
-		 (or (not (looking-at ruby-modifier-re))
-		     (ruby-expr-beg 'modifier))
-		 (goto-char pnt)
-		 (setq nest (cons (cons nil pnt) nest))
-		 (setq depth (1+ depth)))
-		(goto-char pnt))
-	       ((looking-at ":\\([a-zA-Z_][a-zA-Z_0-9]*\\)?")
-		(goto-char (match-end 0)))
-	       ((or (looking-at "\\.")
-		    (looking-at "\\.\\.\\.?")
-		    (looking-at "\\.[0-9]+")
-		    (looking-at "\\.[a-zA-Z_0-9]+"))
-		(goto-char (match-end 0)))
-	       ((looking-at "^=begin")
-		(if (re-search-forward "^=end" indent-point t)
-		    (forward-line 1)
-		  (setq in-string (match-end 0))
-		  (goto-char indent-point)))
-	       (t
-		(error (format "bad string %s"
-			       (buffer-substring (point) pnt)
-			       )))))))
-	(list in-string (car nest) depth (car (car pcol))))))
+		       (or (eq ?_ w)
+			   (eq ?. w))))
+		(progn
+		  (goto-char pnt)
+		  (setq w (char-after (point)))
+		  (or (eq ?_ w)
+		      (eq ?! w)
+		      (eq ?? w))))
+	    nil
+	  (setq nest (cdr nest))
+	  (setq depth (1- depth)))
+	(goto-char pnt))
+       ((looking-at "def\\s +[^(\n;]*")
+	(if (or (bolp)
+		(progn
+		  (forward-char -1)
+		  (not (eq ?_ (char-after (point))))))
+	    (progn
+	      (setq nest (cons (cons nil pnt) nest))
+	      (setq depth (1+ depth))))
+	(goto-char (match-end 0)))
+       ((looking-at (concat "\\<\\(" ruby-block-beg-re "\\)\\>"))
+	(and
+	 (save-match-data
+	   (or (not (looking-at "do\\>[^_]"))
+	       (save-excursion
+		 (back-to-indentation)
+		 (not (looking-at ruby-non-block-do-re)))))
+	 (or (bolp)
+	     (progn
+	       (forward-char -1)
+	       (setq w (char-after (point)))
+	       (not (or (eq ?_ w)
+			(eq ?. w)))))
+	 (goto-char pnt)
+	 (setq w (char-after (point)))
+	 (not (eq ?_ w))
+	 (not (eq ?! w))
+	 (not (eq ?? w))
+	 (skip-chars-forward " \t")
+	 (goto-char (match-beginning 0))
+	 (or (not (looking-at ruby-modifier-re))
+	     (ruby-expr-beg 'modifier))
+	 (goto-char pnt)
+	 (setq nest (cons (cons nil pnt) nest))
+	 (setq depth (1+ depth)))
+	(goto-char pnt))
+       ((looking-at ":\\(['\"]\\)\\(\\\\.\\|[^\\\\]\\)*\\1")
+	(goto-char (match-end 0)))
+       ((looking-at ":\\([-,.+*/%&|^~<>]=?\\|===?\\|<=>\\)")
+	(goto-char (match-end 0)))
+       ((looking-at ":\\([a-zA-Z_][a-zA-Z_0-9]*[!?=]?\\)?")
+	(goto-char (match-end 0)))
+       ((or (looking-at "\\.\\.\\.?")
+	    (looking-at "\\.[0-9]+")
+	    (looking-at "\\.[a-zA-Z_0-9]+")
+	    (looking-at "\\."))
+	(goto-char (match-end 0)))
+       ((looking-at "^=begin")
+	(if (re-search-forward "^=end" end t)
+	    (forward-line 1)
+	  (setq in-string (match-end 0))
+	  (goto-char end)))
+       ((looking-at "<<")
+	(cond
+	 ((and (ruby-expr-beg 'heredoc)
+	       (looking-at "<<\\(-\\)?\\(\\([\"'`]\\)\\([^\n]+?\\)\\3\\|\\sw+\\)"))
+	  (setq re (regexp-quote (or (match-string 4) (match-string 2))))
+	  (if (match-beginning 1) (setq re (concat "\\s *" re)))
+	  (let* ((id-end (goto-char (match-end 0)))
+		 (line-end-position (save-excursion (end-of-line) (point)))
+		 (state (list in-string nest depth pcol indent)))
+	    ;; parse the rest of the line
+	    (while (and (> line-end-position (point))
+			(setq state (apply 'ruby-parse-partial
+					   line-end-position state))))
+	    (setq in-string (car state)
+		  nest (nth 1 state)
+		  depth (nth 2 state)
+		  pcol (nth 3 state)
+		  indent (nth 4 state))
+	    ;; skip heredoc section
+	    (if (re-search-forward (concat "^" re "$") end 'move)
+		(forward-line 1)
+	      (setq in-string id-end)
+	      (goto-char end))))
+	 (t
+	  (goto-char pnt))))
+       ((looking-at "^__END__$")
+	(goto-char pnt))
+       ((looking-at ruby-here-doc-beg-re)
+	(if (re-search-forward (ruby-here-doc-end-match)
+			       indent-point t)
+	    (forward-line 1)
+	  (setq in-string (match-end 0))
+	  (goto-char indent-point)))
+       (t
+	(error (format "bad string %s"
+		       (buffer-substring (point) pnt)
+		       ))))))
+  (list in-string nest depth pcol))
 
+(defun ruby-parse-region (start end)
+  (let (state)
+    (save-excursion
+      (if start
+	  (goto-char start)
+	(ruby-beginning-of-indent))
+      (save-restriction
+	(narrow-to-region (point) end)
+	(while (and (> end (point))
+		    (setq state (apply 'ruby-parse-partial end state))))))
+    (list (nth 0 state)			; in-string
+	  (car (nth 1 state))		; nest
+	  (nth 2 state)			; depth
+	  (car (car (nth 3 state)))	; pcol
+	  ;(car (nth 5 state))		; indent
+	  )))
+
 (defun ruby-indent-size (pos nest)
-  (+ pos (* (if nest nest 1) ruby-indent-level)))
+  (+ pos (* (or nest 1) ruby-indent-level)))
 
 (defun ruby-calculate-indent (&optional parse-start)
   (save-excursion
     (beginning-of-line)
     (let ((indent-point (point))
-	    (case-fold-search nil)
-	    state bol eol
-	    (indent 0))
-	(if parse-start
-	    (goto-char parse-start)
-	  (ruby-beginning-of-indent)
-	  (setq parse-start (point)))
-	(back-to-indentation)
-	(setq indent (current-column))
-	(setq state (ruby-parse-region parse-start indent-point))
+	  (case-fold-search nil)
+	  state bol eol begin op-end
+	  (paren (progn (skip-syntax-forward " ")
+			(and (char-after) (matching-paren (char-after)))))
+	  (indent 0))
+      (if parse-start
+	  (goto-char parse-start)
+	(ruby-beginning-of-indent)
+	(setq parse-start (point)))
+      (back-to-indentation)
+      (setq indent (current-column))
+      (setq state (ruby-parse-region parse-start indent-point))
+      (cond
+       ((nth 0 state)			; within string
+	(setq indent nil))		;  do nothing
+       ((car (nth 1 state))		; in paren
+	(goto-char (setq begin (cdr (nth 1 state))))
+	(let ((deep (ruby-deep-indent-paren-p (car (nth 1 state)))))
+	  (if deep
+	      (cond ((and (eq deep t) (eq (car (nth 1 state)) paren))
+		     (skip-syntax-backward " ")
+		     (setq indent (1- (current-column))))
+		    ((let ((s (ruby-parse-region (point) indent-point)))
+		       (and (nth 2 s) (> (nth 2 s) 0)
+			    (or (goto-char (cdr (nth 1 s))) t)))
+		     (forward-word -1)
+		     (setq indent (ruby-indent-size (current-column) (nth 2 state))))
+		    (t
+		     (setq indent (current-column))
+		     (cond ((eq deep 'space))
+			   (paren (setq indent (1- indent)))
+			   (t (setq indent (ruby-indent-size (1- indent) 1))))))
+	    (if (nth 3 state) (goto-char (nth 3 state))
+	      (goto-char parse-start) (back-to-indentation))
+	    (setq indent (ruby-indent-size (current-column) (nth 2 state))))
+	  (and (eq (car (nth 1 state)) paren)
+	       (ruby-deep-indent-paren-p (matching-paren paren))
+	       (search-backward (char-to-string paren))
+	       (setq indent (current-column)))))
+       ((and (nth 2 state) (> (nth 2 state) 0)) ; in nest
+	(if (null (cdr (nth 1 state)))
+	    (error "invalid nest"))
+	(goto-char (cdr (nth 1 state)))
+	(forward-word -1)		; skip back a keyword
+	(setq begin (point))
 	(cond
-	 ((nth 0 state)			; within string
-	  (setq indent nil))		;  do nothing
-	 ((car (nth 1 state))		; in paren
-	  (goto-char (cdr (nth 1 state)))
-	  (if (eq (car (nth 1 state)) ?\( )
-	      (let ((column (current-column))
-		    (s (ruby-parse-region (point) indent-point)))
-		(cond
-		 ((and (nth 2 s) (> (nth 2 s) 0))
-		  (goto-char (cdr (nth 1 s)))
-		  (forward-word -1)
-		  (setq indent (ruby-indent-size (current-column) (nth 2 state))))
-		 (t
-		  (setq indent (current-column)))))
-	    (cond
-	     ((nth 3 state)
-	      (goto-char (nth 3 state))
-	      (setq indent (ruby-indent-size (current-column) (nth 2 state))))
-	     (t
-	      (goto-char parse-start)
-	      (back-to-indentation)
-	      (setq indent (ruby-indent-size (current-column) (nth 2 state)))))
-	    ))
-	 ((and (nth 2 state)(> (nth 2 state) 0)) ; in nest
-	  (if (null (cdr (nth 1 state)))
-	      (error "invalid nest"))
-	  (goto-char (cdr (nth 1 state)))
-	  (forward-word -1)		; skip back a keyword
-	  (cond
-	   ((looking-at "do\\>[^_]")	; iter block is a special case
-	    (cond
-	     ((nth 3 state)
-	      (goto-char (nth 3 state))
-	      (setq indent (ruby-indent-size (current-column) (nth 2 state))))
-	     (t
-	      (goto-char parse-start)
-	      (back-to-indentation)
-	      (setq indent (ruby-indent-size (current-column) (nth 2 state))))))
-	   (t
-	    (setq indent (+ (current-column) ruby-indent-level)))))
-
-	 ((and (nth 2 state) (< (nth 2 state) 0)) ; in negative nest
-	  (setq indent (ruby-indent-size (current-column) (nth 2 state)))))
-
+	 ((looking-at "do\\>[^_]")	; iter block is a special case
+	  (if (nth 3 state) (goto-char (nth 3 state))
+	    (goto-char parse-start) (back-to-indentation))
+	  (setq indent (ruby-indent-size (current-column) (nth 2 state))))
+	 (t
+	  (setq indent (+ (current-column) ruby-indent-level)))))
+       
+       ((and (nth 2 state) (< (nth 2 state) 0)) ; in negative nest
+	(setq indent (ruby-indent-size (current-column) (nth 2 state)))))
+      (when indent
+	(goto-char indent-point)
+	(end-of-line)
+	(setq eol (point))
+	(beginning-of-line)
 	(cond
-	 (indent
-	  (goto-char indent-point)
+	 ((and (not (ruby-deep-indent-paren-p paren))
+	       (re-search-forward ruby-negative eol t))
+	  (and (not (eq ?_ (char-after (match-end 0))))
+	       (setq indent (- indent ruby-indent-level))))
+	 ((and
+	   (save-excursion
+	     (beginning-of-line)
+	     (not (bobp)))
+	   (or (ruby-deep-indent-paren-p t)
+	       (null (car (nth 1 state)))))
+	  ;; goto beginning of non-empty no-comment line
+	  (let (end done)
+	    (while (not done)
+	      (skip-chars-backward " \t\n")
+	      (setq end (point))
+	      (beginning-of-line)
+	      (if (re-search-forward "^\\s *#" end t)
+		  (beginning-of-line)
+		(setq done t))))
+	  (setq bol (point))
 	  (end-of-line)
-	  (setq eol (point))
-	  (beginning-of-line)
-	  (cond
-	   ((re-search-forward ruby-negative eol t)
-	    (and (not (eq ?_ (char-after (match-end 0))))
-		 (setq indent (- indent ruby-indent-level))))
-	   ;;operator terminated lines
-	   ((and
-	     (save-excursion
-	       (beginning-of-line)
-	       (not (bobp)))
-	     (or (null (car (nth 1 state))) ;not in parens
-		 (and (eq (car (nth 1 state)) ?\{)
-		      (save-excursion	;except non-block braces
-			(goto-char (cdr (nth 1 state)))
-			(or (bobp) (forward-char -1))
-			(not (ruby-expr-beg))))))
-	    ;; goto beginning of non-empty no-comment line
-	    (let (end done)
-	      (while (not done)
-		(skip-chars-backward " \t\n")
-		(setq end (point))
-		(beginning-of-line)
-		(if (re-search-forward "^\\s *#" end t)
-		    (beginning-of-line)
-		  (setq done t))))
-	    (setq bol (point))
-	    (end-of-line)
+	  ;; skip the comment at the end
+	  (skip-chars-backward " \t")
+	  (let (end (pos (point)))
+	    (beginning-of-line)
+	    (while (and (re-search-forward "#" pos t)
+			(setq end (1- (point)))
+			(or (ruby-special-char-p end)
+			    (and (setq state (ruby-parse-region parse-start end))
+				 (nth 0 state))))
+	      (setq end nil))
+	    (goto-char (or end pos))
 	    (skip-chars-backward " \t")
-	    (let ((pos (point)))
-	      (while (and (re-search-backward "#" bol t)
-			  (eq (char-before) ??))
-		(forward-char -1))
-	      (skip-chars-backward " \t")
-	      (and
-	       (setq state (ruby-parse-region parse-start (point)))
-	       (nth 0 state)
-	       (goto-char pos)))
-	    (or (bobp) (forward-char -1))
-	    (and
-	     (or (and (looking-at ruby-symbol-re)
-		      (skip-chars-backward ruby-symbol-chars)
-		      (looking-at ruby-block-hanging-re)
-		      (not (eq (point) (nth 3 state)))
-		      (save-excursion
-			(goto-char (match-end 0))
-			(not (looking-at "[a-z_]"))))
-		 (and (looking-at ruby-operator-re)
-		      (not (eq (char-after (1- (point))) ??))
-		      (not (eq (char-after (1- (point))) ?$))
-		      (or (not (eq ?/ (char-after (point))))
-			  (null (nth 0 (ruby-parse-region parse-start (point)))))
-		      (or (not (eq ?| (char-after (point))))
-			  (save-excursion
-			    (or (eolp) (forward-char -1))
-			    (cond
-			     ((search-backward "|" nil t)
-			      (skip-chars-backward " \t\n")
-			      (and (not (eolp))
-				   (progn
-				     (forward-char -1)
-				     (not (looking-at "{")))
-				   (progn
-				     (forward-word -1)
-				     (not (looking-at "do\\>[^_]")))))
-			     (t t))))))
-	     (setq indent (+ indent ruby-indent-level)))))))
-	indent)))
+	    (setq begin (if (nth 0 state) pos (cdr (nth 1 state))))
+	    (setq state (ruby-parse-region parse-start (point))))
+	  (or (bobp) (forward-char -1))
+	  (and
+	   (or (and (looking-at ruby-symbol-re)
+		    (skip-chars-backward ruby-symbol-chars)
+		    (looking-at (concat "\\<\\(" ruby-block-hanging-re "\\)\\>"))
+		    (not (eq (point) (nth 3 state)))
+		    (save-excursion
+		      (goto-char (match-end 0))
+		      (not (looking-at "[a-z_]"))))
+	       (and (looking-at ruby-operator-re)
+		    (not (ruby-special-char-p))
+		    ;; operator at the end of line
+		    (let ((c (char-after (point))))
+		      (and
+;; 		       (or (null begin)
+;; 			   (save-excursion
+;; 			     (goto-char begin)
+;; 			     (skip-chars-forward " \t")
+;; 			     (not (or (eolp) (looking-at "#")
+;; 				      (and (eq (car (nth 1 state)) ?{)
+;; 					   (looking-at "|"))))))
+		       (or (not (eq ?/ c))
+			   (null (nth 0 (ruby-parse-region (or begin parse-start) (point)))))
+		       (or (not (eq ?| (char-after (point))))
+			   (save-excursion
+			     (or (eolp) (forward-char -1))
+			     (cond
+			      ((search-backward "|" nil t)
+			       (skip-chars-backward " \t\n")
+			       (and (not (eolp))
+				    (progn
+				      (forward-char -1)
+				      (not (looking-at "{")))
+				    (progn
+				      (forward-word -1)
+				      (not (looking-at "do\\>[^_]")))))
+			      (t t))))
+		       (not (eq ?, c))
+		       (setq op-end t)))))
+	   (setq indent
+		 (cond
+		  ((and
+		    (null op-end)
+		    (not (looking-at (concat "\\<\\(" ruby-block-hanging-re "\\)\\>")))
+		    (eq (ruby-deep-indent-paren-p t) 'space)
+		    (not (bobp)))
+		   (save-excursion
+		     (widen)
+		     (goto-char (or begin parse-start))
+		     (skip-syntax-forward " ")
+		     (current-column)))
+		  ((car (nth 1 state)) indent)
+		  (t
+		   (+ indent ruby-indent-level))))))))
+      indent)))
 
 (defun ruby-electric-brace (arg)
   (interactive "P")
-  (self-insert-command (prefix-numeric-value arg))
-  (ruby-indent-line t))
+  (insert-char last-command-char 1)
+  (ruby-indent-line t)
+  (delete-char -1)
+  (self-insert-command (prefix-numeric-value arg)))
+
+(eval-when-compile
+  (defmacro defun-region-command (func args &rest body)
+    (let ((intr (car body)))
+      (when (featurep 'xemacs)
+	(if (stringp intr) (setq intr (cadr body)))
+	(and (eq (car intr) 'interactive)
+	     (setq intr (cdr intr))
+	     (setcar intr (concat "_" (car intr)))))
+      (cons 'defun (cons func (cons args body))))))
 
-(defun ruby-beginning-of-defun (&optional arg)
+(defun-region-command ruby-beginning-of-defun (&optional arg)
   "Move backward to next beginning-of-defun.
 With argument, do this that many times.
 Returns t unless search stops due to end of buffer."
@@ -607,7 +768,7 @@ Returns t unless search stops due to end
 	 (beginning-of-line)
 	 t)))
 
-(defun ruby-end-of-defun (&optional arg)
+(defun-region-command ruby-end-of-defun (&optional arg)
   "Move forward to next end of defun.
 An end of a defun is found by moving forward from the beginning of one."
   (interactive "p")
@@ -619,39 +780,124 @@ An end of a defun is found by moving for
 (defun ruby-move-to-block (n)
   (let (start pos done down)
     (setq start (ruby-calculate-indent))
-    (if (eobp)
-	nil
-      (while (and (not (bobp)) (not (eobp)) (not done))
-	(forward-line n)
+    (setq down (looking-at (concat "\\<\\(" (if (< n 0) ruby-block-end-re ruby-block-beg-re) "\\)\\>")))
+    (while (and (not done) (not (if (< n 0) (bobp) (eobp))))
+      (forward-line n)
+      (cond
+       ((looking-at "^\\s *$"))
+       ((looking-at "^\\s *#"))
+       ((and (> n 0) (looking-at "^=begin\\>"))
+	(re-search-forward "^=end\\>"))
+       ((and (< n 0) (looking-at "^=end\\>"))
+	(re-search-backward "^=begin\\>"))
+       (t
+	(setq pos (current-indentation))
 	(cond
-	 ((looking-at "^$"))
-	 ((looking-at "^\\s *#"))
-	 (t
-	  (setq pos (current-indentation))
-	  (cond
-	   ((< start pos)
-	    (setq down t))
-	   ((and down (= pos start))
-	    (setq done t))
-	   ((> start pos)
-	    (setq done t)))))
-	(if done
-	    (progn
-	      (back-to-indentation)
-	      (if (looking-at ruby-block-mid-re)
-		  (setq done nil)))))))
+	 ((< start pos)
+	  (setq down t))
+	 ((and down (= pos start))
+	  (setq done t))
+	 ((> start pos)
+	  (setq done t)))))
+      (if done
+	  (save-excursion
+	    (back-to-indentation)
+	    (if (looking-at (concat "\\<\\(" ruby-block-mid-re "\\)\\>"))
+		(setq done nil))))))
   (back-to-indentation))
 
-(defun ruby-beginning-of-block ()
+(defun-region-command ruby-beginning-of-block (&optional arg)
   "Move backward to next beginning-of-block"
-  (interactive)
-  (ruby-move-to-block -1))
+  (interactive "p")
+  (ruby-move-to-block (- (or arg 1))))
 
-(defun ruby-end-of-block ()
+(defun-region-command ruby-end-of-block (&optional arg)
   "Move forward to next beginning-of-block"
-  (interactive)
-  (ruby-move-to-block 1))
+  (interactive "p")
+  (ruby-move-to-block (or arg 1)))
 
+(defun-region-command ruby-forward-sexp (&optional cnt)
+  (interactive "p")
+  (if (and (numberp cnt) (< cnt 0))
+      (ruby-backward-sexp (- cnt))
+    (let ((i (or cnt 1)))
+      (condition-case nil
+	  (while (> i 0)
+	    (skip-syntax-forward " ")
+	    (cond ((looking-at "\\?\\(\\\\[CM]-\\)*\\\\?\\S ")
+		   (goto-char (match-end 0)))
+		  ((progn
+		     (skip-chars-forward ",.:;|&^~=!?\\+\\-\\*")
+		     (looking-at "\\s("))
+		   (goto-char (scan-sexps (point) 1)))
+		  ((and (looking-at (concat "\\<\\(" ruby-block-beg-re "\\)\\>"))
+			(not (eq (char-before (point)) ?.))
+			(not (eq (char-before (point)) ?:)))
+		   (ruby-end-of-block)
+		   (forward-word 1))
+		  ((looking-at "\\(\\$\\|@@?\\)?\\sw")
+		   (while (progn
+			    (while (progn (forward-word 1) (looking-at "_")))
+			    (cond ((looking-at "::") (forward-char 2) t)
+				  ((> (skip-chars-forward ".") 0))
+				  ((looking-at "\\?\\|!\\(=[~=>]\\|[^~=]\\)")
+				   (forward-char 1) nil)))))
+		  ((let (state expr)
+		     (while
+			 (progn
+			   (setq expr (or expr (ruby-expr-beg)
+					  (looking-at "%\\sw?\\Sw\\|[\"'`/]")))
+			   (nth 1 (setq state (apply 'ruby-parse-partial nil state))))
+		       (setq expr t)
+		       (skip-chars-forward "<"))
+		     (not expr))))
+	    (setq i (1- i)))
+	((error) (forward-word 1)))
+      i)))
+
+(defun-region-command ruby-backward-sexp (&optional cnt)
+  (interactive "p")
+  (if (and (numberp cnt) (< cnt 0))
+      (ruby-forward-sexp (- cnt))
+    (let ((i (or cnt 1)))
+      (condition-case nil
+	  (while (> i 0)
+	    (skip-chars-backward " \t\n,.:;|&^~=!?\\+\\-\\*")
+	    (forward-char -1)
+	    (cond ((looking-at "\\s)")
+		   (goto-char (scan-sexps (1+ (point)) -1))
+		   (case (char-before)
+		     (?% (forward-char -1))
+		     ('(?q ?Q ?w ?W ?r ?x)
+		      (if (eq (char-before (1- (point))) ?%) (forward-char -2))))
+		   nil)
+		  ((looking-at "\\s\"\\|\\\\\\S_")
+		   (let ((c (char-to-string (char-before (match-end 0)))))
+		     (while (and (search-backward c)
+				 (oddp (skip-chars-backward "\\")))))
+		   nil)
+		  ((looking-at "\\s.\\|\\s\\")
+		   (if (ruby-special-char-p) (forward-char -1)))
+		  ((looking-at "\\s(") nil)
+		  (t
+		   (forward-char 1)
+		   (while (progn (forward-word -1)
+				 (case (char-before)
+				   (?_ t)
+				   (?. (forward-char -1) t)
+				   ((?$ ?@)
+				    (forward-char -1)
+				    (and (eq (char-before) (char-after)) (forward-char -1)))
+				   (?:
+				    (forward-char -1)
+				    (eq (char-before) :)))))
+		   (if (looking-at (concat "\\<\\(" ruby-block-end-re "\\)\\>"))
+		       (ruby-beginning-of-block))
+		   nil))
+	    (setq i (1- i)))
+	((error)))
+      i)))
+
 (defun ruby-reindent-then-newline-and-indent ()
   (interactive "*")
   (newline)
@@ -687,6 +933,65 @@ An end of a defun is found by moving for
   (ruby-beginning-of-defun)
   (re-search-backward "^\n" (- (point) 1) t))
 
+(defun ruby-indent-exp (&optional shutup-p)
+  "Indent each line in the balanced expression following point syntactically.
+If optional SHUTUP-P is non-nil, no errors are signalled if no
+balanced expression is found."
+  (interactive "*P")
+  (let ((here (point-marker)) start top column (nest t))
+    (set-marker-insertion-type here t)
+    (unwind-protect
+	(progn
+	  (beginning-of-line)
+	  (setq start (point) top (current-indentation))
+	  (while (and (not (eobp))
+		      (progn
+			(setq column (ruby-calculate-indent start))
+			(cond ((> column top)
+			       (setq nest t))
+			      ((and (= column top) nest)
+			       (setq nest nil) t))))
+	    (ruby-indent-to column)
+	    (beginning-of-line 2)))
+      (goto-char here)
+      (set-marker here nil))))
+
+(defun ruby-add-log-current-method ()
+  "Return current method string."
+  (condition-case nil
+      (save-excursion
+	(let ((mlist nil) (indent 0))
+	  ;; get current method (or class/module)
+	  (if (re-search-backward
+	       (concat "^[ \t]*\\(def\\|class\\|module\\)[ \t]+"
+		       "\\(" 
+		       ;; \\. for class method
+			"\\(" ruby-symbol-re "\\|\\." "\\)" 
+			"+\\)")
+	       nil t)
+	      (progn
+		(setq mlist (list (match-string 2)))
+		(goto-char (match-beginning 1))
+		(setq indent (current-column))
+		(beginning-of-line)))
+	  ;; nest class/module
+	  (while (and (> indent 0)
+		      (re-search-backward
+		       (concat
+			"^[ \t]*\\(class\\|module\\)[ \t]+"
+			"\\([A-Z]" ruby-symbol-re "+\\)")
+		       nil t))
+	    (goto-char (match-beginning 1))
+	    (if (< (current-column) indent)
+		(progn
+		  (setq mlist (cons (match-string 2) mlist))
+		  (setq indent (current-column))
+		  (beginning-of-line))))
+	  ;; generate string
+	  (if (consp mlist)
+	      (mapconcat (function identity) mlist "::")
+	    nil)))))
+
 (cond
  ((featurep 'font-lock)
   (or (boundp 'font-lock-variable-name-face)
@@ -696,32 +1001,18 @@ An end of a defun is found by moving for
 	'(
 	  ;; #{ }, #$hoge, #@foo are not comments
 	  ("\\(#\\)[{$@]" 1 (1 . nil))
-	  ;; the last $' in the string ,'...$' is not variable
-	  ;; the last ?' in the string ,'...?' is not ascii code
-	  ("\\(^\\|[[\\s <+(,=]\\)\\('\\)[^'\n\\\\]*\\(\\\\.[^'\n\\\\]*\\)*[?$]\\('\\)"
-	   (2 (7 . nil))
-	   (4 (7 . nil)))
-	  ;; the last $` in the string ,`...$` is not variable
-	  ;; the last ?` in the string ,`...?` is not ascii code
-	  ("\\(^\\|[[\\s <+(,=]\\)\\(`\\)[^`\n\\\\]*\\(\\\\.[^`\n\\\\]*\\)*[?$]\\(`\\)"
-	   (2 (7 . nil))
-	   (4 (7 . nil)))
-	  ;; the last $" in the string ,"...$" is not variable
-	  ;; the last ?" in the string ,"...?" is not ascii code
-	  ("\\(^\\|[[\\s <+(,=]\\)\\(\"\\)[^\"\n\\\\]*\\(\\\\.[^\"\n\\\\]*\\)*[?$]\\(\"\\)"
+	  ;; the last $', $", $` in the respective string is not variable
+	  ;; the last ?', ?", ?` in the respective string is not ascii code
+	  ("\\(^\\|[\[ \t\n<+\(,=]\\)\\(['\"`]\\)\\(\\\\.\\|\\2\\|[^'\"`\n\\\\]\\)*?\\\\?[?$]\\(\\2\\)"
 	   (2 (7 . nil))
 	   (4 (7 . nil)))
 	  ;; $' $" $` .... are variables
 	  ;; ?' ?" ?` are ascii codes
-	  ("[?$][#\"'`]" 0 (1 . nil))
+	  ("\\(^\\|[^\\\\]\\)\\(\\\\\\\\\\)*[?$]\\([#\"'`]\\)" 3 (1 . nil))
 	  ;; regexps
 	  ("\\(^\\|[=(,~?:;]\\|\\(^\\|\\s \\)\\(if\\|elsif\\|unless\\|while\\|until\\|when\\|and\\|or\\|&&\\|||\\)\\|g?sub!?\\|scan\\|split!?\\)\\s *\\(/\\)[^/\n\\\\]*\\(\\\\.[^/\n\\\\]*\\)*\\(/\\)"
 	   (4 (7 . ?/))
 	   (6 (7 . ?/)))
-	  ;; %Q!...!
-	  ("\\(^\\|[[\\s <+(,=]\\)%[xrqQ]?\\([^a-zA-Z0-9 \n]\\)[^\n\\\\]*\\(\\\\.[^\n\\\\]*\\)*\\(\\2\\)"
-	   (2 (7 . nil))
-	   (4 (7 . nil)))
 	  ("^\\(=\\)begin\\(\\s \\|$\\)" 1 (7 . nil))
 	  ("^\\(=\\)end\\(\\s \\|$\\)" 1 (7 . nil))))
 
@@ -737,9 +1028,11 @@ An end of a defun is found by moving for
 	    '(lambda ()
 	       (make-local-variable 'font-lock-defaults)
 	       (make-local-variable 'font-lock-keywords)
+	       (make-local-variable 'font-lock-syntax-table)
 	       (make-local-variable 'font-lock-syntactic-keywords)
 	       (setq font-lock-defaults '((ruby-font-lock-keywords) nil nil))
 	       (setq font-lock-keywords ruby-font-lock-keywords)
+	       (setq font-lock-syntax-table ruby-font-lock-syntax-table)
 	       (setq font-lock-syntactic-keywords ruby-font-lock-syntactic-keywords)))))
 
   (defun ruby-font-lock-docs (limit)
@@ -768,10 +1061,47 @@ An end of a defun is found by moving for
 	    t)
 	nil)))
 
+  (defvar ruby-font-lock-syntax-table
+    (let* ((tbl (copy-syntax-table ruby-mode-syntax-table)))
+      (modify-syntax-entry ?_ "w" tbl)
+      tbl))
+
+  (defun ruby-font-lock-here-docs (limit)
+    (if (re-search-forward ruby-here-doc-beg-re limit t)
+	(let (beg)
+	  (beginning-of-line)
+          (forward-line)
+	  (setq beg (point))
+	  (if (re-search-forward (ruby-here-doc-end-match) nil t)
+	      (progn
+		(set-match-data (list beg (point)))
+		t)))))
+
+  (defun ruby-font-lock-maybe-here-docs (limit)
+    (let (beg)
+      (save-excursion
+	(if (re-search-backward ruby-here-doc-beg-re nil t)
+	    (progn
+	      (beginning-of-line)
+              (forward-line)
+	      (setq beg (point)))))
+      (if (and beg
+	       (let ((end-match (ruby-here-doc-end-match)))
+                 (and (not (re-search-backward end-match beg t))
+		      (re-search-forward end-match nil t))))
+	  (progn
+	    (set-match-data (list beg (point)))
+	    t)
+          nil)))
+
   (defvar ruby-font-lock-keywords
     (list
+     ;; functions
+     '("^\\s *def\\s +\\([^( \t\n]+\\)"
+       1 font-lock-function-name-face)
+     ;; keywords
      (cons (concat
-	    "\\(^\\|[^_:.@$]\\|\\.\\.\\)\\b\\("
+	    "\\(^\\|[^_:.@$]\\|\\.\\.\\)\\b\\(defined\\?\\|\\("
 	    (mapconcat
 	     'identity
 	     '("alias"
@@ -811,10 +1141,10 @@ An end of a defun is found by moving for
 	       "yield"
 	       )
 	     "\\|")
-	    "\\)\\>\\([^_]\\|$\\)")
+	    "\\)\\>\\)")
 	   2)
      ;; variables
-     '("\\(^\\|[^_:.@$]\\|\\.\\.\\)\\b\\(nil\\|self\\|true\\|false\\)\\b\\([^_]\\|$\\)"
+     '("\\(^\\|[^_:.@$]\\|\\.\\.\\)\\b\\(nil\\|self\\|true\\|false\\)\\>"
        2 font-lock-variable-name-face)
      ;; variables
      '("\\(\\$\\([^a-zA-Z0-9 \n]\\|[0-9]\\)\\)\\W"
@@ -826,18 +1156,29 @@ An end of a defun is found by moving for
        0 font-lock-comment-face t)
      '(ruby-font-lock-maybe-docs
        0 font-lock-comment-face t)
+     ;; "here" document
+     '(ruby-font-lock-here-docs
+       0 font-lock-string-face t)
+     '(ruby-font-lock-maybe-here-docs
+       0 font-lock-string-face t)
+     `(,ruby-here-doc-beg-re
+       0 font-lock-string-face t)
+     ;; general delimited string
+     '("\\(^\\|[[ \t\n<+(,=]\\)\\(%[xrqQwW]?\\([^<[{(a-zA-Z0-9 \n]\\)[^\n\\\\]*\\(\\\\.[^\n\\\\]*\\)*\\(\\3\\)\\)"
+       (2 font-lock-string-face))
      ;; constants
      '("\\(^\\|[^_]\\)\\b\\([A-Z]+\\(\\w\\|_\\)*\\)"
        2 font-lock-type-face)
-     ;; functions
-     '("^\\s *def\\s +\\([^( ]+\\)"
-       1 font-lock-function-name-face)
      ;; symbols
      '("\\(^\\|[^:]\\)\\(:\\([-+~]@?\\|[/%&|^`]\\|\\*\\*?\\|<\\(<\\|=>?\\)?\\|>[>=]?\\|===?\\|=~\\|\\[\\]=?\\|\\(\\w\\|_\\)+\\([!?=]\\|\\b_*\\)\\|#{[^}\n\\\\]*\\(\\\\.[^}\n\\\\]*\\)*}\\)\\)"
        2 font-lock-reference-face)
      ;; expression expansion
      '("#\\({[^}\n\\\\]*\\(\\\\.[^}\n\\\\]*\\)*}\\|\\(\\$\\|@\\|@@\\)\\(\\w\\|_\\)+\\)"
-       0 font-lock-variable-name-face t))
+       0 font-lock-variable-name-face t)
+     ;; warn lower camel case
+     ;'("\\<[a-z]+[a-z0-9]*[A-Z][A-Za-z0-9]*\\([!?]?\\|\\>\\)"
+     ;  0 font-lock-warning-face)
+     )
     "*Additional expressions to highlight in ruby mode."))
 
  ((featurep 'hilit19)



1.1                  XEmacs/packages/xemacs-packages/ruby-modes/ruby-electric.el

Index: ruby-electric.el
===================================================================
;; -*-Emacs-Lisp-*-
;;
;; ruby-electric.el --- electric editing commands for ruby files
;;
;; Copyright (C) 2005 by Dee Zsombor <dee dot zsombor at gmail dot com>.
;; Released under same license terms as Ruby.
;;
;; Due credit: this work was inspired by a code snippet posted by
;; Frederick Ros at http://rubygarden.org/ruby?EmacsExtensions.
;;
;; Following improvements where added:
;;
;;       - handling of strings of type 'here document'
;;       - more keywords, with special handling for 'do'
;;       - packaged into a minor mode
;;
;; Usage:
;;
;;    0) copy ruby-electric.el into directory where emacs can find it.
;;
;;    1) modify your startup file (.emacs or whatever) by adding
;;       following line:
;;
;;            (require 'ruby-electric)
;;
;;       note that you need to have font lock enabled beforehand.
;;
;;    2) toggle Ruby Electric Mode on/off with ruby-electric-mode.
;;
;; Changelog:
;;
;;  2005/Jan/14: inserts matching pair delimiters like {, [, (, ', ",
;;  ' and | .
;;
;;  2005/Jan/14: added basic Custom support for configuring keywords
;;  with electric closing.
;;
;;  2005/Jan/18: more Custom support for configuring characters for
;;  which matching expansion should occur.
;;
;;  2005/Jan/18: no longer uses 'looking-back' or regexp character
;;  classes like [:space:] since they are not implemented on XEmacs.
;;
;;  2005/Feb/01: explicitly provide default argument of 1 to
;;  'backward-word' as it requires it on Emacs 21.3
;;
;;  2005/Mar/06: now stored inside ruby CVS; customize pages now have
;;  ruby as parent; cosmetic fixes.


(require 'ruby-mode)

(defgroup ruby-electric nil
  "Minor mode providing electric editing commands for ruby files"
  :group 'ruby) 

(defconst ruby-electric-expandable-do-re
  "do\\s-$")

(defconst ruby-electric-expandable-bar
  "\\s-\\(do\\|{\\)\\s-+|")

(defvar ruby-electric-matching-delimeter-alist
  '((?\[ . ?\])
    (?\( . ?\))
    (?\' . ?\')
    (?\` . ?\`)
    (?\" . ?\")))

(defcustom ruby-electric-simple-keywords-re 
  "\\(def\\|if\\|class\\|module\\|unless\\|case\\|while\\|do\\|until\\|for\\|begin\\)"
  "*Regular expresion matching keywords for which closing 'end'
is to be inserted."
  :type 'regexp :group 'ruby-electric)

(defcustom ruby-electric-expand-delimiters-list '(all)
  "*List of contexts where matching delimiter should be
inserted. The word 'all' will do all insertions."
  :type '(set :extra-offset 8
	      (const :tag "Everything" all )
	      (const :tag "Curly brace" ?\{ )
	      (const :tag "Square brace" ?\[ )
	      (const :tag "Round brace" ?\( )
	      (const :tag "Quote" ?\' )
	      (const :tag "Double quote" ?\" )
	      (const :tag "Back quote" ?\` )
	      (const :tag "Vertical bar" ?\| ))
  :group 'ruby-electric) 

(defcustom ruby-electric-newline-before-closing-bracket nil
  "*Controls whether a newline should be inserted before the
closing bracket or not."
  :type 'boolean :group 'ruby-electric)

;;;###autoload (autoload 'ruby-electric-mode "ruby-electric" "Toggle Ruby Electric minor mode" t)
(define-minor-mode ruby-electric-mode
  "Toggle Ruby Electric minor 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 Ruby Electric mode is enabled, an indented 'end' is
heuristicaly inserted whenever typing a word like 'module',
'class', 'def', 'if', 'unless', 'case', 'until', 'for', 'begin',
'do'. Simple, double and back quotes as well as braces are paired
auto-magically. Expansion does not occur inside comments and
strings. Note that you must have Font Lock enabled."
  ;; initial value.
  nil
  ;;indicator for the mode line.
  " REl"
  ;;keymap
  ruby-mode-map
  (ruby-electric-setup-keymap))

(defun ruby-electric-setup-keymap()
  (define-key ruby-mode-map " " 'ruby-electric-space)
  (define-key ruby-mode-map "{" 'ruby-electric-curlies)
  (define-key ruby-mode-map "(" 'ruby-electric-matching-char)
  (define-key ruby-mode-map "[" 'ruby-electric-matching-char)
  (define-key ruby-mode-map "\"" 'ruby-electric-matching-char)
  (define-key ruby-mode-map "\'" 'ruby-electric-matching-char)
  (define-key ruby-mode-map "|" 'ruby-electric-bar))

(defun ruby-electric-space (arg)
  (interactive "P")
  (self-insert-command (prefix-numeric-value arg))
  (if (ruby-electric-space-can-be-expanded-p)
      (save-excursion
	(ruby-indent-line t)
	(newline)
	(ruby-insert-end))))

(defun ruby-electric-code-at-point-p()
  (and ruby-electric-mode
       (let* ((properties (text-properties-at (point))))
	 (and (null (memq 'font-lock-string-face properties))
	      (null (memq 'font-lock-comment-face properties))))))

(defun ruby-electric-string-at-point-p()
  (and ruby-electric-mode
       (consp (memq 'font-lock-string-face (text-properties-at (point))))))

(defun ruby-electric-is-last-command-char-expandable-punct-p()
  (or (memq 'all ruby-electric-expand-delimiters-list)
      (memq last-command-char ruby-electric-expand-delimiters-list))) 

(defun ruby-electric-space-can-be-expanded-p()
  (if (ruby-electric-code-at-point-p)
      (let* ((ruby-electric-keywords-re 
	      (concat ruby-electric-simple-keywords-re "\\s-$"))
	     (ruby-electric-single-keyword-in-line-re 
	      (concat "\\s-*" ruby-electric-keywords-re)))
	(save-excursion
	  (backward-word 1)
	  (or (looking-at ruby-electric-expandable-do-re)
	      (and (looking-at ruby-electric-keywords-re)
		   (not (string= "do" (match-string 1)))
		   (progn
		     (beginning-of-line)
		     (looking-at ruby-electric-single-keyword-in-line-re))))))))


(defun ruby-electric-curlies(arg)
  (interactive "P")
  (self-insert-command (prefix-numeric-value arg))
  (if (ruby-electric-is-last-command-char-expandable-punct-p)
      (cond ((ruby-electric-code-at-point-p)
	     (insert " ")
	     (save-excursion
	       (if ruby-electric-newline-before-closing-bracket
		   (newline))
	       (insert "}")))
	    ((ruby-electric-string-at-point-p)
	     (save-excursion
	       (backward-char 1)
	       (when (char-equal ?\# (preceding-char))
		 (forward-char 1)
		 (insert "}")))))))

(defun ruby-electric-matching-char(arg)
  (interactive "P")
  (self-insert-command (prefix-numeric-value arg))
  (and (ruby-electric-is-last-command-char-expandable-punct-p)
       (ruby-electric-code-at-point-p)
       (save-excursion
	 (insert (cdr (assoc last-command-char 
			     ruby-electric-matching-delimeter-alist))))))

(defun ruby-electric-bar(arg)
  (interactive "P")
  (self-insert-command (prefix-numeric-value arg))
  (and (ruby-electric-is-last-command-char-expandable-punct-p)
       (ruby-electric-code-at-point-p)
       (and (save-excursion (re-search-backward ruby-electric-expandable-bar nil t))
	    (= (point) (match-end 0))) ;looking-back is missing on XEmacs
       (save-excursion 
	 (insert "|"))))

(provide 'ruby-electric)

;;; ruby-electric.el ends here
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.