From cfef16c08413b62d33a380d41916be1003380b71 Mon Sep 17 00:00:00 2001 From: Dmitry Gutov Date: Mon, 21 Oct 2013 09:54:18 +0400 Subject: [PATCH] * lisp/progmodes/ruby-mode.el (ruby-smie-grammar): Add (almost) all infix operators. (ruby-smie--implicit-semi-p): Add new operator chars. --- lisp/ChangeLog | 3 ++ lisp/progmodes/ruby-mode.el | 99 +++++++++++++++++++++++++++------------------ test/indent/ruby.rb | 8 ++-- 3 files changed, 66 insertions(+), 44 deletions(-) diff --git a/lisp/ChangeLog b/lisp/ChangeLog index c57ac41171c..e9de6a7669c 100644 --- a/lisp/ChangeLog +++ b/lisp/ChangeLog @@ -1,5 +1,8 @@ 2013-10-21 Dmitry Gutov + * progmodes/ruby-mode.el (ruby-smie-grammar): Add (almost) all infix operators. + (ruby-smie--implicit-semi-p): Add new operator chars. + * progmodes/ruby-mode.el (ruby-mode-map): Add binding for `smie-down-list'. (ruby-smie--args-separator-p): Check that there's no newline diff --git a/lisp/progmodes/ruby-mode.el b/lisp/progmodes/ruby-mode.el index 6abc525f705..fcbe4fdb7c4 100644 --- a/lisp/progmodes/ruby-mode.el +++ b/lisp/progmodes/ruby-mode.el @@ -248,48 +248,67 @@ explicitly declared in magic comment." (require 'smie) +;; Here's a simplified BNF grammar, for reference: +;; http://www.cse.buffalo.edu/~regan/cse305/RubyBNF.pdf (defconst ruby-smie-grammar ;; FIXME: Add support for Cucumber. (smie-prec2->grammar - (smie-bnf->prec2 - '((id) - (insts (inst) (insts ";" insts)) - (inst (exp) (inst "iuwu-mod" exp)) - (exp (exp1) (exp "," exp) (exp "=" exp) (exp "-" exp) (exp "+" exp) - (id " @ " exp)) - (exp1 (exp2) (exp2 "?" exp1 ":" exp1)) - (exp2 ("def" insts "end") - ("begin" insts-rescue-insts "end") - ("do" insts "end") - ("class" insts "end") ("module" insts "end") - ("for" for-body "end") - ("[" expseq "]") - ("{" hashvals "}") - ("{" insts "}") - ("while" insts "end") - ("until" insts "end") - ("unless" insts "end") - ("if" if-body "end") - ("case" cases "end")) - (formal-params ("opening-|" exp "|")) - (for-body (for-head ";" insts)) - (for-head (id "in" exp)) - (cases (exp "then" insts) ;; FIXME: Ruby also allows (exp ":" insts). - (cases "when" cases) (insts "else" insts)) - (expseq (exp) );;(expseq "," expseq) - (hashvals (id "=>" exp1) (hashvals "," hashvals)) - (insts-rescue-insts (insts) - (insts-rescue-insts "rescue" insts-rescue-insts) - (insts-rescue-insts "ensure" insts-rescue-insts)) - (itheni (insts) (exp "then" insts)) - (ielsei (itheni) (itheni "else" insts)) - (if-body (ielsei) (if-body "elsif" if-body))) - '((nonassoc "in") (assoc ";") (right " @ ") - (assoc ",") (right "=") (assoc "-" "+")) - '((assoc "when")) - '((assoc "elsif")) - '((assoc "rescue" "ensure")) - '((assoc ","))))) + (smie-merge-prec2s + (smie-bnf->prec2 + '((id) + (insts (inst) (insts ";" insts)) + (inst (exp) (inst "iuwu-mod" exp)) + (exp (exp1) (exp "," exp) (exp "=" exp) + (id " @ " exp)) + (exp1 (exp2) (exp2 "?" exp1 ":" exp1)) + (exp2 ("def" insts "end") + ("begin" insts-rescue-insts "end") + ("do" insts "end") + ("class" insts "end") ("module" insts "end") + ("for" for-body "end") + ("[" expseq "]") + ("{" hashvals "}") + ("{" insts "}") + ("while" insts "end") + ("until" insts "end") + ("unless" insts "end") + ("if" if-body "end") + ("case" cases "end")) + (formal-params ("opening-|" exp "|")) + (for-body (for-head ";" insts)) + (for-head (id "in" exp)) + (cases (exp "then" insts) ;; FIXME: Ruby also allows (exp ":" insts). + (cases "when" cases) (insts "else" insts)) + (expseq (exp) );;(expseq "," expseq) + (hashvals (id "=>" exp1) (hashvals "," hashvals)) + (insts-rescue-insts (insts) + (insts-rescue-insts "rescue" insts-rescue-insts) + (insts-rescue-insts "ensure" insts-rescue-insts)) + (itheni (insts) (exp "then" insts)) + (ielsei (itheni) (itheni "else" insts)) + (if-body (ielsei) (if-body "elsif" if-body))) + '((nonassoc "in") (assoc ";") (right " @ ") + (assoc ",") (right "=")) + '((assoc "when")) + '((assoc "elsif")) + '((assoc "rescue" "ensure")) + '((assoc ","))) + + (smie-precs->prec2 + '((right "=") + (right "+=" "-=" "*=" "/=" "%=" "**=" "&=" "|=" "^=" + "<<=" ">>=" "&&=" "||=") + (left ".." "...") + (left "+" "-") + (left "*" "/" "%" "**") + ;; (left "|") ; FIXME: Conflicts with | after block parameters. + (left "^" "&") + (nonassoc "<=>") + (nonassoc ">" ">=" "<" "<=") + (nonassoc "==" "===" "!=") + (nonassoc "=~" "!~") + (left "<<" ">>") + (left "&&" "||")))))) (defun ruby-smie--bosp () (save-excursion (skip-chars-backward " \t") @@ -300,7 +319,7 @@ explicitly declared in magic comment." (skip-chars-backward " \t") (not (or (bolp) (and (memq (char-before) - '(?\; ?- ?+ ?* ?/ ?: ?. ?, ?\[ ?\( ?\{ ?\\)) + '(?\; ?- ?+ ?* ?/ ?: ?. ?, ?\[ ?\( ?\{ ?\\ ?& ?> ?< ?% ?~)) ;; Make sure it's not the end of a regexp. (not (eq (car (syntax-after (1- (point)))) 7))) (and (eq (char-before) ?\?) diff --git a/test/indent/ruby.rb b/test/indent/ruby.rb index 56966ebb8c0..c898dbc5cf8 100644 --- a/test/indent/ruby.rb +++ b/test/indent/ruby.rb @@ -182,6 +182,10 @@ and_this_one(has) { |block, parameters| tee } +if foo + + bar +end + # Examples below still fail with `ruby-use-smie' on: foo + @@ -194,10 +198,6 @@ end foo_bar_tee(1, 2, 3) .qux -if foo && - bar -end - method !arg1, arg2 -- 2.11.4.GIT