[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Emacs-diffs] /srv/bzr/emacs/trunk r112522: * lisp/progmodes/ruby-mode.e
From: |
Stefan Monnier |
Subject: |
[Emacs-diffs] /srv/bzr/emacs/trunk r112522: * lisp/progmodes/ruby-mode.el: First cut at SMIE support. |
Date: |
Wed, 08 May 2013 16:25:57 -0400 |
User-agent: |
Bazaar (2.6b2) |
------------------------------------------------------------
revno: 112522
committer: Stefan Monnier <address@hidden>
branch nick: trunk
timestamp: Wed 2013-05-08 16:25:57 -0400
message:
* lisp/progmodes/ruby-mode.el: First cut at SMIE support.
(ruby-use-smie): New var.
(ruby-smie-grammar): New constant.
(ruby-smie--bosp, ruby-smie--implicit-semi-p)
(ruby-smie--forward-token, ruby-smie--backward-token)
(ruby-smie-rules): New functions.
(ruby-mode-variables): Setup SMIE if applicable.
* test/indent/ruby.rb: Fix indentation after =; add more cases.
modified:
lisp/ChangeLog
lisp/progmodes/ruby-mode.el
test/ChangeLog
test/indent/ruby.rb
=== modified file 'lisp/ChangeLog'
--- a/lisp/ChangeLog 2013-05-08 18:05:40 +0000
+++ b/lisp/ChangeLog 2013-05-08 20:25:57 +0000
@@ -1,3 +1,13 @@
+2013-05-08 Stefan Monnier <address@hidden>
+
+ * progmodes/ruby-mode.el: First cut at SMIE support.
+ (ruby-use-smie): New var.
+ (ruby-smie-grammar): New constant.
+ (ruby-smie--bosp, ruby-smie--implicit-semi-p)
+ (ruby-smie--forward-token, ruby-smie--backward-token)
+ (ruby-smie-rules): New functions.
+ (ruby-mode-variables): Setup SMIE if applicable.
+
2013-05-08 Eli Zaretskii <address@hidden>
* simple.el (line-move-visual): Signal beginning/end of buffer
=== modified file 'lisp/progmodes/ruby-mode.el'
--- a/lisp/progmodes/ruby-mode.el 2013-04-15 23:07:14 +0000
+++ b/lisp/progmodes/ruby-mode.el 2013-05-08 20:25:57 +0000
@@ -148,13 +148,16 @@
(define-abbrev-table 'ruby-mode-abbrev-table ()
"Abbrev table in use in Ruby mode buffers.")
+(defvar ruby-use-smie nil)
+
(defvar ruby-mode-map
(let ((map (make-sparse-keymap)))
- (define-key map (kbd "M-C-b") 'ruby-backward-sexp)
- (define-key map (kbd "M-C-f") 'ruby-forward-sexp)
+ (unless ruby-use-smie
+ (define-key map (kbd "M-C-b") 'ruby-backward-sexp)
+ (define-key map (kbd "M-C-f") 'ruby-forward-sexp)
+ (define-key map (kbd "M-C-q") 'ruby-indent-exp))
(define-key map (kbd "M-C-p") 'ruby-beginning-of-block)
(define-key map (kbd "M-C-n") 'ruby-end-of-block)
- (define-key map (kbd "M-C-q") 'ruby-indent-exp)
(define-key map (kbd "C-c {") 'ruby-toggle-block)
map)
"Keymap used in Ruby mode.")
@@ -236,6 +239,111 @@
(put 'ruby-comment-column 'safe-local-variable 'integerp)
(put 'ruby-deep-arglist 'safe-local-variable 'booleanp)
+;;; SMIE support
+
+(require 'smie)
+
+(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))
+ (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 "}")
+ ("while" insts "end")
+ ("until" insts "end")
+ ("unless" insts "end")
+ ("if" if-body "end")
+ ("case" cases "end"))
+ (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 ";") (assoc ","))
+ '((assoc "when"))
+ '((assoc "elsif"))
+ '((assoc "rescue" "ensure"))
+ '((assoc ",")))))
+
+(defun ruby-smie--bosp ()
+ (save-excursion (skip-chars-backward " \t")
+ (or (bolp) (eq (char-before) ?\;))))
+
+(defun ruby-smie--implicit-semi-p ()
+ (save-excursion
+ (skip-chars-backward " \t")
+ (not (or (bolp)
+ (memq (char-before) '(?\; ?- ?+ ?* ?/ ?:))
+ (and (memq (char-before) '(?\? ?=))
+ (not (memq (char-syntax (char-before (1- (point))))
+ '(?w ?_))))))))
+
+(defun ruby-smie--forward-token ()
+ (skip-chars-forward " \t")
+ (if (and (looking-at "[\n#]")
+ ;; Only add implicit ; when needed.
+ (ruby-smie--implicit-semi-p))
+ (progn
+ (if (eolp) (forward-char 1) (forward-comment 1))
+ ";")
+ (forward-comment (point-max))
+ (let ((tok (smie-default-forward-token)))
+ (cond
+ ((member tok '("unless" "if" "while" "until"))
+ (if (save-excursion (forward-word -1) (ruby-smie--bosp))
+ tok "iuwu-mod"))
+ (t tok)))))
+
+(defun ruby-smie--backward-token ()
+ (let ((pos (point)))
+ (forward-comment (- (point)))
+ (if (and (> pos (line-end-position))
+ (ruby-smie--implicit-semi-p))
+ (progn (skip-chars-forward " \t")
+ ";")
+ (let ((tok (smie-default-backward-token)))
+ (cond
+ ((member tok '("unless" "if" "while" "until"))
+ (if (ruby-smie--bosp)
+ tok "iuwu-mod"))
+ (t tok))))))
+
+(defun ruby-smie-rules (kind token)
+ (pcase (cons kind token)
+ (`(:elem . basic) ruby-indent-level)
+ (`(:after . ";")
+ (if (smie-rule-parent-p "def" "begin" "do" "class" "module" "for"
+ "[" "{" "while" "until" "unless"
+ "if" "then" "elsif" "else" "when"
+ "rescue" "ensure")
+ (smie-rule-parent ruby-indent-level)
+ ;; For (invalid) code between switch and case.
+ ;; (if (smie-parent-p "switch") 4)
+ 0))
+ (`(:before . ,(or `"else" `"then" `"elsif")) 0)
+ (`(:before . ,(or `"when"))
+ (if (not (smie-rule-sibling-p)) 0)) ;; ruby-indent-level
+ ;; Hack attack: Since newlines are separators, don't try to align args that
+ ;; appear on a separate line.
+ (`(:list-intro . ";") t)))
+
(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)
@@ -290,7 +398,11 @@
(set-syntax-table ruby-mode-syntax-table)
(setq local-abbrev-table ruby-mode-abbrev-table)
(setq indent-tabs-mode ruby-indent-tabs-mode)
- (set (make-local-variable 'indent-line-function) 'ruby-indent-line)
+ (if ruby-use-smie
+ (smie-setup ruby-smie-grammar #'ruby-smie-rules
+ :forward-token #'ruby-smie--forward-token
+ :backward-token #'ruby-smie--backward-token)
+ (set (make-local-variable 'indent-line-function) 'ruby-indent-line))
(set (make-local-variable 'require-final-newline) t)
(set (make-local-variable 'comment-start) "# ")
(set (make-local-variable 'comment-end) "")
=== modified file 'test/ChangeLog'
--- a/test/ChangeLog 2013-05-05 02:26:38 +0000
+++ b/test/ChangeLog 2013-05-08 20:25:57 +0000
@@ -1,3 +1,7 @@
+2013-05-08 Stefan Monnier <address@hidden>
+
+ * indent/ruby.rb: Fix indentation after =; add more cases.
+
2013-05-05 Stefan Monnier <address@hidden>
* indent/pascal.pas: Add test for mis-identified comments.
=== modified file 'test/indent/ruby.rb'
--- a/test/indent/ruby.rb 2012-08-14 12:38:11 +0000
+++ b/test/indent/ruby.rb 2013-05-08 20:25:57 +0000
@@ -10,7 +10,7 @@
# Or inside comments.
x = # "tot %q/to"; =
-y = 2 / 3
+ y = 2 / 3
# Regexp after whitelisted method.
"abc".sub /b/, 'd'
@@ -21,6 +21,40 @@
# Highlight the regexp after "if".
x = toto / foo if /do bar/ =~ "dobar"
+def test1(arg)
+ puts "hello"
+end
+
+def test2 (arg)
+ a = "apple"
+
+ if a == 2
+ puts "hello"
+ else
+ puts "there"
+ end
+
+ if a == 2 then
+ puts "hello"
+ elsif a == 3
+ puts "hello3"
+ elsif a == 3 then
+ puts "hello3"
+ else
+ puts "there"
+ end
+
+ case a
+ when "a"
+ 6
+ # when "b" :
+ # 7
+ # when "c" : 2
+ when "d" then 4
+ else 5
+ end
+end
+
# Some Cucumber code:
Given /toto/ do
print "hello"
- [Emacs-diffs] /srv/bzr/emacs/trunk r112522: * lisp/progmodes/ruby-mode.el: First cut at SMIE support.,
Stefan Monnier <=
- Re: [Emacs-diffs] /srv/bzr/emacs/trunk r112522: * lisp/progmodes/ruby-mode.el: First cut at SMIE support., Dmitry Gutov, 2013/05/19
- Re: [Emacs-diffs] /srv/bzr/emacs/trunk r112522: * lisp/progmodes/ruby-mode.el: First cut at SMIE support., Stefan Monnier, 2013/05/22
- Re: [Emacs-diffs] /srv/bzr/emacs/trunk r112522: * lisp/progmodes/ruby-mode.el: First cut at SMIE support., Dmitry Gutov, 2013/05/22
- Re: [Emacs-diffs] /srv/bzr/emacs/trunk r112522: * lisp/progmodes/ruby-mode.el: First cut at SMIE support., Dmitry Gutov, 2013/05/22
- Re: [Emacs-diffs] /srv/bzr/emacs/trunk r112522: * lisp/progmodes/ruby-mode.el: First cut at SMIE support., Stefan Monnier, 2013/05/22
- Re: [Emacs-diffs] /srv/bzr/emacs/trunk r112522: * lisp/progmodes/ruby-mode.el: First cut at SMIE support., Dmitry Gutov, 2013/05/22
- Re: [Emacs-diffs] /srv/bzr/emacs/trunk r112522: * lisp/progmodes/ruby-mode.el: First cut at SMIE support., Stefan Monnier, 2013/05/22
- Re: [Emacs-diffs] /srv/bzr/emacs/trunk r112522: * lisp/progmodes/ruby-mode.el: First cut at SMIE support., Dmitry Gutov, 2013/05/22
- Re: [Emacs-diffs] /srv/bzr/emacs/trunk r112522: * lisp/progmodes/ruby-mode.el: First cut at SMIE support., Stefan Monnier, 2013/05/22
- Re: [Emacs-diffs] /srv/bzr/emacs/trunk r112522: * lisp/progmodes/ruby-mode.el: First cut at SMIE support., Dmitry Gutov, 2013/05/22