From: Dmitry Gutov Date: Fri, 8 Nov 2013 02:31:51 +0000 (+0200) Subject: * lisp/progmodes/ruby-mode.el (ruby-smie-grammar): Improve precedences X-Git-Tag: emacs-24.3.90~173^2^2~42^2~45^2~387^2~911 X-Git-Url: http://git.eshelyaron.com/gitweb/?a=commitdiff_plain;h=1f9239238301d92e539260f908916d3c188ffead;p=emacs.git * lisp/progmodes/ruby-mode.el (ruby-smie-grammar): Improve precedences of "and", "or", "&&" and "||". (ruby-smie--args-separator-p): Prohibit keyword "do" as the first argument. Prohibit opening curly brace because it could only be a block opener in that position. (ruby-smie--forward-token, ruby-smie--backward-token): Separate "|" from "&" or "*" going after it. That can happen in block arguments. (ruby-smie--indent-to-stmt): New function, seeks the end of previous statement or beginning of buffer. (ruby-smie-rules): Use it. (ruby-smie-rules): Check if there's a ":" before a curly block opener candidate; if there is, it's a hash. * test/indent/ruby.rb: New examples. --- diff --git a/lisp/ChangeLog b/lisp/ChangeLog index 43e48cacd06..f1c25984a54 100644 --- a/lisp/ChangeLog +++ b/lisp/ChangeLog @@ -1,3 +1,19 @@ +2013-11-08 Dmitry Gutov + + * progmodes/ruby-mode.el (ruby-smie-grammar): Improve precedences + of "and", "or", "&&" and "||". + (ruby-smie--args-separator-p): Prohibit keyword "do" as the first + argument. Prohibit opening curly brace because it could only be a + block opener in that position. + (ruby-smie--forward-token, ruby-smie--backward-token): Separate + "|" from "&" or "*" going after it. That can happen in block + arguments. + (ruby-smie--indent-to-stmt): New function, seeks the end of + previous statement or beginning of buffer. + (ruby-smie-rules): Use it. + (ruby-smie-rules): Check if there's a ":" before a curly block + opener candidate; if there is, it's a hash. + 2013-11-07 Stefan Monnier * emacs-lisp/cl-macs.el (cl-symbol-macrolet): Use macroexp-progn. diff --git a/lisp/progmodes/ruby-mode.el b/lisp/progmodes/ruby-mode.el index 05fac2b42f2..c3bafa47f70 100644 --- a/lisp/progmodes/ruby-mode.el +++ b/lisp/progmodes/ruby-mode.el @@ -277,7 +277,10 @@ explicitly declared in magic comment." (smie-bnf->prec2 '((id) (insts (inst) (insts ";" insts)) - (inst (exp) (inst "iuwu-mod" exp)) + (inst (exp) (inst "iuwu-mod" exp) + ;; Somewhat incorrect (both can be used multiple times), + ;; but avoids lots of conflicts: + (exp "and" exp) (exp "or" exp)) (exp (exp1) (exp "," exp) (exp "=" exp) (id " @ " exp) (exp "." id)) @@ -323,14 +326,13 @@ explicitly declared in magic comment." (left "+" "-") (left "*" "/" "%" "**") ;; (left "|") ; FIXME: Conflicts with | after block parameters. + (left "&&" "||") (left "^" "&") (nonassoc "<=>") (nonassoc ">" ">=" "<" "<=") (nonassoc "==" "===" "!=") (nonassoc "=~" "!~") - (left "<<" ">>") - (left "&&" "||") - (left "and" "or")))))) + (left "<<" ">>")))))) (defun ruby-smie--bosp () (save-excursion (skip-chars-backward " \t") @@ -379,13 +381,11 @@ explicitly declared in magic comment." (save-excursion (goto-char pos) (or (and (eq (char-syntax (char-after)) ?w) - ;; FIXME: Also "do". But alas, that breaks some - ;; indentation cases. (not (looking-at (regexp-opt '("unless" "if" "while" "until" - "else" "elsif" "end" "and" "or") + "else" "elsif" "do" "end" "and" "or") 'symbols)))) (memq (syntax-after pos) '(7 15)) - (looking-at "\\s(\\|[-+!~:]\\sw"))))) + (looking-at "[([]\\|[-+!~:]\\sw"))))) (defun ruby-smie--at-dot-call () (and (eq ?w (char-syntax (following-char))) @@ -424,7 +424,9 @@ explicitly declared in magic comment." ((member tok '("unless" "if" "while" "until")) (if (save-excursion (forward-word -1) (ruby-smie--bosp)) tok "iuwu-mod")) - ((equal tok "|") + ((string-match "|[*&]?" tok) + (forward-char (- 1 (length tok))) + (setq tok "|") (if (ruby-smie--opening-pipe-p) "opening-|" tok)) ((and (equal tok "") (looking-at "\\\\\n")) (goto-char (match-end 0)) (ruby-smie--forward-token)) @@ -466,6 +468,9 @@ explicitly declared in magic comment." tok "iuwu-mod")) ((equal tok "|") (if (ruby-smie--opening-pipe-p) "opening-|" tok)) + ((string-match-p "|[*&]" tok) + (forward-char 1) + (substring tok 1)) ((and (equal tok "") (eq ?\\ (char-before)) (looking-at "\n")) (forward-char -1) (ruby-smie--backward-token)) ((equal tok "do") @@ -478,6 +483,16 @@ explicitly declared in magic comment." (t ";"))) (t tok))))))) +(defun ruby-smie--indent-to-stmt () + (save-excursion + (let (parent) + (while (not (or (eq (car parent) t) + (equal (nth 2 parent) ";"))) + (setq parent (let (smie--parent) (smie-indent--parent))) + (when (numberp (nth 1 parent)) + (goto-char (nth 1 parent)))) + (cons 'column (smie-indent-virtual))))) + (defun ruby-smie-rules (kind token) (pcase (cons kind token) (`(:elem . basic) ruby-indent-level) @@ -498,9 +513,12 @@ explicitly declared in magic comment." (`(:before . ,(or `"(" `"[" `"{")) (cond ((and (equal token "{") - (not (smie-rule-prev-p "(" "{" "[" "," "=>" "=" "return" ";"))) + (not (smie-rule-prev-p "(" "{" "[" "," "=>" "=" "return" ";")) + (save-excursion + (forward-comment -1) + (not (eq (preceding-char) ?:)))) ;; Curly block opener. - (smie-rule-parent)) + (ruby-smie--indent-to-stmt)) ((smie-rule-hanging-p) ;; Treat purely syntactic block-constructs as being part of their parent, ;; when the opening statement is hanging. @@ -508,7 +526,7 @@ explicitly declared in magic comment." (when (eq t (car state)) (goto-char (cadr state)))) (cons 'column (smie-indent-virtual))))) (`(:after . " @ ") (smie-rule-parent)) - (`(:before . "do") (smie-rule-parent)) + (`(:before . "do") (ruby-smie--indent-to-stmt)) (`(,(or :before :after) . ".") (unless (smie-rule-parent-p ".") (smie-rule-parent ruby-indent-level))) diff --git a/test/ChangeLog b/test/ChangeLog index 281ce981b5e..2e8b8a6dca8 100644 --- a/test/ChangeLog +++ b/test/ChangeLog @@ -1,3 +1,7 @@ +2013-11-08 Dmitry Gutov + + * indent/ruby.rb: New examples. + 2013-11-06 Glenn Morris * automated/Makefile.in (setwins): Avoid accidental matches. diff --git a/test/indent/ruby.rb b/test/indent/ruby.rb index 31ad32e1eac..47c9b71078b 100644 --- a/test/indent/ruby.rb +++ b/test/indent/ruby.rb @@ -117,6 +117,9 @@ d = 4 + 5 + # no '\' needed e = 8 + 9 \ + 10 # '\' needed +foo = obj.bar { |m| tee(m) } + + obj.qux { |m| hum(m) } + begin foo ensure @@ -210,6 +213,14 @@ foo + foo and bar +foo > bar && + tee < qux + +zux do + foo == bar and + tee == qux +end + foo ^ bar @@ -244,6 +255,14 @@ foo :bar do qux end +foo do |*args| + tee +end + +bar do |&block| + tee +end + foo = [1, 2, 3].map do |i| i + 1 end @@ -252,8 +271,16 @@ bar.foo do bar end -# Examples below still fail with `ruby-use-smie' on: +bar.foo(tee) do + bar +end -bar.foo(tee) do # "." is parent to "do"; it shouldn't be. +bar.foo(tee) { bar +} + +bar 1 do + foo 2 do + tee + end end