From 6cddebc11bdf10eabf55cac829d06bdec7afab89 Mon Sep 17 00:00:00 2001 From: Dmitry Gutov Date: Sun, 22 Dec 2013 06:57:00 +0200 Subject: [PATCH] Integrate ruby-mode with electric-indent-mode better * lisp/progmodes/ruby-mode.el (ruby--at-indentation-p): New function, extracted from `ruby-smie-rules'. (ruby--electric-indent-chars): New variable. (ruby--electric-indent-p): New function. (ruby-mode): Use `electric-indent-functions' instead of `electric-indent-chars'. --- etc/NEWS | 2 ++ lisp/ChangeLog | 9 +++++++++ lisp/progmodes/ruby-mode.el | 35 ++++++++++++++++++++++++++++++++--- 3 files changed, 43 insertions(+), 3 deletions(-) diff --git a/etc/NEWS b/etc/NEWS index f681068c1d9..42a81429778 100644 --- a/etc/NEWS +++ b/etc/NEWS @@ -599,6 +599,8 @@ rather than mboxo. Customize `unrmail-mbox-format' to change this. *** New option `ruby-align-to-stmt-keywords'. +*** New `electric-indent-mode' integration. + ** Search and Replace *** New global command `M-s .' (`isearch-forward-symbol-at-point') diff --git a/lisp/ChangeLog b/lisp/ChangeLog index 36877e3dbbe..f6b51d21a30 100644 --- a/lisp/ChangeLog +++ b/lisp/ChangeLog @@ -1,3 +1,12 @@ +2013-12-22 Dmitry Gutov + + * progmodes/ruby-mode.el (ruby--at-indentation-p): New function, + extracted from `ruby-smie-rules'. + (ruby--electric-indent-chars): New variable. + (ruby--electric-indent-p): New function. + (ruby-mode): Use `electric-indent-functions' instead of + `electric-indent-chars'. + 2013-12-22 Dmitry Gutov * progmodes/ruby-mode.el (ruby-align-to-stmt-keywords): Tweak the diff --git a/lisp/progmodes/ruby-mode.el b/lisp/progmodes/ruby-mode.el index fae7ce1f8e6..89c0cfad913 100644 --- a/lisp/progmodes/ruby-mode.el +++ b/lisp/progmodes/ruby-mode.el @@ -631,12 +631,19 @@ It is used when `ruby-encoding-magic-comment-style' is set to `custom'." ruby-indent-level)) (`(:after . ,(or "?" ":")) ruby-indent-level) (`(:before . ,(or "if" "while" "unless" "until" "begin" "case" "for")) - (when (not (save-excursion (skip-chars-backward " \t") (bolp))) + (when (not (ruby--at-indentation-p)) (if (ruby-smie--indent-to-stmt-p token) (ruby-smie--indent-to-stmt) (cons 'column (current-column))))) )) +(defun ruby--at-indentation-p (&optional point) + (save-excursion + (unless point (setq point (point))) + (forward-line 0) + (skip-chars-forward " \t") + (eq (point) point))) + (defun ruby-imenu-create-index-in-block (prefix beg end) "Create an imenu index of methods inside a block." (let ((index-alist '()) (case-fold-search nil) @@ -767,6 +774,29 @@ The style of the comment is controlled by `ruby-encoding-magic-comment-style'." (when (buffer-modified-p) (basic-save-buffer-1))))))) +(defvar ruby--electric-indent-chars '(?. ?\) ?} ?\])) + +(defun ruby--electric-indent-p (char) + (cond + ((memq char ruby--electric-indent-chars) + ;; Outdent after typing a closing paren. + (ruby--at-indentation-p (1- (point)))) + ((memq (char-after) ruby--electric-indent-chars) + ;; Reindent after inserting something before a closing paren. + (ruby--at-indentation-p (1- (point)))) + ((or (memq (char-syntax char) '(?w ?_))) + (let ((pt (point))) + (save-excursion + (skip-syntax-backward "w_") + (and (ruby--at-indentation-p) + (looking-at (regexp-opt (cons "end" ruby-block-mid-keywords))) + ;; Outdent after typing a keyword. + (or (eq (match-end 0) pt) + ;; Reindent if it wasn't a keyword after all. + (eq (match-end 0) (1- pt))))))))) + +;; FIXME: Remove this? It's unused here, but some redefinitions of +;; `ruby-calculate-indent' in user init files still call it. (defun ruby-current-indentation () "Return the indentation level of current line." (save-excursion @@ -2081,8 +2111,7 @@ See `font-lock-syntax-table'.") (setq-local end-of-defun-function 'ruby-end-of-defun) (add-hook 'after-save-hook 'ruby-mode-set-encoding nil 'local) - - (setq-local electric-indent-chars (append '(?\{ ?\}) electric-indent-chars)) + (add-hook 'electric-indent-functions 'ruby--electric-indent-p nil 'local) (setq-local font-lock-defaults '((ruby-font-lock-keywords) nil nil)) (setq-local font-lock-keywords ruby-font-lock-keywords) -- 2.39.2