diff options
| author | Stefan Monnier | 2013-10-06 23:38:26 -0400 |
|---|---|---|
| committer | Stefan Monnier | 2013-10-06 23:38:26 -0400 |
| commit | 7ccae3b126e1b01814e8bed7f903f5e2b6d448bd (patch) | |
| tree | c27b63b78e52c5aa573a46e9a9b94affc015c543 | |
| parent | c8af480df782d6ff2d99f34a1672b8640dfb673f (diff) | |
| download | emacs-7ccae3b126e1b01814e8bed7f903f5e2b6d448bd.tar.gz emacs-7ccae3b126e1b01814e8bed7f903f5e2b6d448bd.zip | |
* lisp/progmodes/ruby-mode.el: Fix recently added tests.
(ruby-smie-grammar): Add - and +.
(ruby-smie--redundant-do-p, ruby-smie--forward-id)
(ruby-smie--backward-id): New functions.
(ruby-smie--forward-token, ruby-smie--backward-token): Use them.
(ruby-smie-rules): Handle hanging do. Get rid of hack, not needed
any more.
* test/indent/ruby.rb: Add a few more tests; adjust some indentation.
| -rw-r--r-- | lisp/ChangeLog | 10 | ||||
| -rw-r--r-- | lisp/progmodes/ruby-mode.el | 85 | ||||
| -rw-r--r-- | test/indent/ruby.rb | 21 |
3 files changed, 93 insertions, 23 deletions
diff --git a/lisp/ChangeLog b/lisp/ChangeLog index 9211dfe2356..bf8dad1b621 100644 --- a/lisp/ChangeLog +++ b/lisp/ChangeLog | |||
| @@ -1,3 +1,13 @@ | |||
| 1 | 2013-10-07 Stefan Monnier <monnier@iro.umontreal.ca> | ||
| 2 | |||
| 3 | * progmodes/ruby-mode.el: Fix recently added tests. | ||
| 4 | (ruby-smie-grammar): Add - and +. | ||
| 5 | (ruby-smie--redundant-do-p, ruby-smie--forward-id) | ||
| 6 | (ruby-smie--backward-id): New functions. | ||
| 7 | (ruby-smie--forward-token, ruby-smie--backward-token): Use them. | ||
| 8 | (ruby-smie-rules): Handle hanging do. Get rid of hack, not needed | ||
| 9 | any more. | ||
| 10 | |||
| 1 | 2013-10-07 Leo Liu <sdl.web@gmail.com> | 11 | 2013-10-07 Leo Liu <sdl.web@gmail.com> |
| 2 | 12 | ||
| 3 | * register.el (register-preview-delay) | 13 | * register.el (register-preview-delay) |
diff --git a/lisp/progmodes/ruby-mode.el b/lisp/progmodes/ruby-mode.el index c1f79eb8711..b8c24e8a690 100644 --- a/lisp/progmodes/ruby-mode.el +++ b/lisp/progmodes/ruby-mode.el | |||
| @@ -246,7 +246,7 @@ Also ignores spaces after parenthesis when 'space." | |||
| 246 | '((id) | 246 | '((id) |
| 247 | (insts (inst) (insts ";" insts)) | 247 | (insts (inst) (insts ";" insts)) |
| 248 | (inst (exp) (inst "iuwu-mod" exp)) | 248 | (inst (exp) (inst "iuwu-mod" exp)) |
| 249 | (exp (exp1) (exp "," exp) (exp "=" exp)) | 249 | (exp (exp1) (exp "," exp) (exp "=" exp) (exp "-" exp) (exp "+" exp)) |
| 250 | (exp1 (exp2) (exp2 "?" exp1 ":" exp1)) | 250 | (exp1 (exp2) (exp2 "?" exp1 ":" exp1)) |
| 251 | (exp2 ("def" insts "end") | 251 | (exp2 ("def" insts "end") |
| 252 | ("begin" insts-rescue-insts "end") | 252 | ("begin" insts-rescue-insts "end") |
| @@ -274,7 +274,7 @@ Also ignores spaces after parenthesis when 'space." | |||
| 274 | (itheni (insts) (exp "then" insts)) | 274 | (itheni (insts) (exp "then" insts)) |
| 275 | (ielsei (itheni) (itheni "else" insts)) | 275 | (ielsei (itheni) (itheni "else" insts)) |
| 276 | (if-body (ielsei) (if-body "elsif" if-body))) | 276 | (if-body (ielsei) (if-body "elsif" if-body))) |
| 277 | '((nonassoc "in") (assoc ";") (assoc ",") (right "=")) | 277 | '((nonassoc "in") (assoc ";") (assoc ",") (right "=") (assoc "-" "+")) |
| 278 | '((assoc "when")) | 278 | '((assoc "when")) |
| 279 | '((assoc "elsif")) | 279 | '((assoc "elsif")) |
| 280 | '((assoc "rescue" "ensure")) | 280 | '((assoc "rescue" "ensure")) |
| @@ -297,6 +297,11 @@ Also ignores spaces after parenthesis when 'space." | |||
| 297 | (or (equal tok "?") | 297 | (or (equal tok "?") |
| 298 | (string-match "\\`\\s." tok)))))))) | 298 | (string-match "\\`\\s." tok)))))))) |
| 299 | 299 | ||
| 300 | (defun ruby-smie--redundant-do-p (&optional skip) | ||
| 301 | (save-excursion | ||
| 302 | (if skip (backward-word 1)) | ||
| 303 | (member (nth 2 (smie-backward-sexp ";")) '("while")))) | ||
| 304 | |||
| 300 | (defun ruby-smie--opening-pipe-p () | 305 | (defun ruby-smie--opening-pipe-p () |
| 301 | (save-excursion | 306 | (save-excursion |
| 302 | (if (eq ?| (char-before)) (forward-char -1)) | 307 | (if (eq ?| (char-before)) (forward-char -1)) |
| @@ -304,6 +309,15 @@ Also ignores spaces after parenthesis when 'space." | |||
| 304 | (or (eq ?\{ (char-before)) | 309 | (or (eq ?\{ (char-before)) |
| 305 | (looking-back "\\_<do" (- (point) 2))))) | 310 | (looking-back "\\_<do" (- (point) 2))))) |
| 306 | 311 | ||
| 312 | (defun ruby-smie--forward-id () | ||
| 313 | (when (and (not (eobp)) | ||
| 314 | (eq ?w (char-syntax (char-after)))) | ||
| 315 | (let ((tok (smie-default-forward-token))) | ||
| 316 | (when (eq ?. (char-after)) | ||
| 317 | (forward-char 1) | ||
| 318 | (setq tok (concat tok "." (ruby-smie--forward-id)))) | ||
| 319 | tok))) | ||
| 320 | |||
| 307 | (defun ruby-smie--forward-token () | 321 | (defun ruby-smie--forward-token () |
| 308 | (skip-chars-forward " \t") | 322 | (skip-chars-forward " \t") |
| 309 | (cond | 323 | (cond |
| @@ -316,17 +330,37 @@ Also ignores spaces after parenthesis when 'space." | |||
| 316 | (forward-comment (point-max)) | 330 | (forward-comment (point-max)) |
| 317 | (if (looking-at ":\\s.+") | 331 | (if (looking-at ":\\s.+") |
| 318 | (progn (goto-char (match-end 0)) (match-string 0)) ;; bug#15208. | 332 | (progn (goto-char (match-end 0)) (match-string 0)) ;; bug#15208. |
| 319 | (let ((tok (smie-default-forward-token))) | 333 | (let ((tok (smie-default-forward-token))) |
| 320 | (cond | 334 | (when (eq ?. (char-after)) |
| 321 | ((member tok '("unless" "if" "while" "until")) | 335 | (forward-char 1) |
| 322 | (if (save-excursion (forward-word -1) (ruby-smie--bosp)) | 336 | (setq tok (concat tok "." (ruby-smie--forward-id)))) |
| 323 | tok "iuwu-mod")) | 337 | (cond |
| 338 | ((member tok '("unless" "if" "while" "until")) | ||
| 339 | (if (save-excursion (forward-word -1) (ruby-smie--bosp)) | ||
| 340 | tok "iuwu-mod")) | ||
| 324 | ((equal tok "|") | 341 | ((equal tok "|") |
| 325 | (if (ruby-smie--opening-pipe-p) "opening-|" tok)) | 342 | (if (ruby-smie--opening-pipe-p) "opening-|" tok)) |
| 326 | ((and (equal tok "") (looking-at "\\\\\n")) | 343 | ((and (equal tok "") (looking-at "\\\\\n")) |
| 327 | (goto-char (match-end 0)) (ruby-smie--forward-token)) | 344 | (goto-char (match-end 0)) (ruby-smie--forward-token)) |
| 345 | ((equal tok "do") | ||
| 346 | (cond | ||
| 347 | ((not (ruby-smie--redundant-do-p 'skip)) tok) | ||
| 348 | ((> (save-excursion (forward-comment (point-max)) (point)) | ||
| 349 | (line-end-position)) | ||
| 350 | (ruby-smie--forward-token)) ;Fully redundant. | ||
| 351 | (t ";"))) | ||
| 352 | ((equal tok ".") (concat tok (ruby-smie--forward-id))) | ||
| 328 | (t tok))))))) | 353 | (t tok))))))) |
| 329 | 354 | ||
| 355 | (defun ruby-smie--backward-id () | ||
| 356 | (when (and (not (bobp)) | ||
| 357 | (eq ?w (char-syntax (char-before)))) | ||
| 358 | (let ((tok (smie-default-backward-token))) | ||
| 359 | (when (eq ?. (char-before)) | ||
| 360 | (forward-char -1) | ||
| 361 | (setq tok (concat (ruby-smie--backward-id) "." tok))) | ||
| 362 | tok))) | ||
| 363 | |||
| 330 | (defun ruby-smie--backward-token () | 364 | (defun ruby-smie--backward-token () |
| 331 | (let ((pos (point))) | 365 | (let ((pos (point))) |
| 332 | (forward-comment (- (point))) | 366 | (forward-comment (- (point))) |
| @@ -336,6 +370,9 @@ Also ignores spaces after parenthesis when 'space." | |||
| 336 | ((and (bolp) (not (bobp))) "") ;Presumably a heredoc. | 370 | ((and (bolp) (not (bobp))) "") ;Presumably a heredoc. |
| 337 | (t | 371 | (t |
| 338 | (let ((tok (smie-default-backward-token))) | 372 | (let ((tok (smie-default-backward-token))) |
| 373 | (when (eq ?. (char-before)) | ||
| 374 | (forward-char -1) | ||
| 375 | (setq tok (concat (ruby-smie--backward-id) "." tok))) | ||
| 339 | (when (and (eq ?: (char-before)) (string-match "\\`\\s." tok)) | 376 | (when (and (eq ?: (char-before)) (string-match "\\`\\s." tok)) |
| 340 | (forward-char -1) (setq tok (concat ":" tok))) ;; bug#15208. | 377 | (forward-char -1) (setq tok (concat ":" tok))) ;; bug#15208. |
| 341 | (cond | 378 | (cond |
| @@ -346,6 +383,16 @@ Also ignores spaces after parenthesis when 'space." | |||
| 346 | (if (ruby-smie--opening-pipe-p) "opening-|" tok)) | 383 | (if (ruby-smie--opening-pipe-p) "opening-|" tok)) |
| 347 | ((and (equal tok "") (eq ?\\ (char-before)) (looking-at "\n")) | 384 | ((and (equal tok "") (eq ?\\ (char-before)) (looking-at "\n")) |
| 348 | (forward-char -1) (ruby-smie--backward-token)) | 385 | (forward-char -1) (ruby-smie--backward-token)) |
| 386 | ((equal tok "do") | ||
| 387 | (cond | ||
| 388 | ((not (ruby-smie--redundant-do-p)) tok) | ||
| 389 | ((> (save-excursion (forward-word 1) | ||
| 390 | (forward-comment (point-max)) (point)) | ||
| 391 | (line-end-position)) | ||
| 392 | (ruby-smie--backward-token)) ;Fully redundant. | ||
| 393 | (t ";"))) | ||
| 394 | ((equal tok ".") | ||
| 395 | (concat (ruby-smie--backward-id) tok)) | ||
| 349 | (t tok))))))) | 396 | (t tok))))))) |
| 350 | 397 | ||
| 351 | (defun ruby-smie-rules (kind token) | 398 | (defun ruby-smie-rules (kind token) |
| @@ -370,24 +417,22 @@ Also ignores spaces after parenthesis when 'space." | |||
| 370 | (if (smie-rule-hanging-p) (smie-rule-parent))) | 417 | (if (smie-rule-hanging-p) (smie-rule-parent))) |
| 371 | (`(:after . "=") 2) | 418 | (`(:after . "=") 2) |
| 372 | (`(:before . "do") | 419 | (`(:before . "do") |
| 373 | (when | 420 | (when (or (smie-rule-hanging-p) |
| 374 | (save-excursion | 421 | (save-excursion |
| 375 | (forward-word 1) ;Skip "do" | 422 | (forward-word 1) ;Skip "do" |
| 376 | (skip-chars-forward " \t") | 423 | (skip-chars-forward " \t") |
| 377 | (and (equal (save-excursion (ruby-smie--forward-token)) "opening-|") | 424 | (and (equal (save-excursion (ruby-smie--forward-token)) |
| 378 | (save-excursion (forward-sexp 1) | 425 | "opening-|") |
| 379 | (skip-chars-forward " \t") | 426 | (save-excursion (forward-sexp 1) |
| 380 | (or (eolp) | 427 | (skip-chars-forward " \t") |
| 381 | (looking-at comment-start-skip))))) | 428 | (or (eolp) |
| 429 | (looking-at comment-start-skip)))))) | ||
| 382 | ;; `(column . ,(smie-indent-virtual)) | 430 | ;; `(column . ,(smie-indent-virtual)) |
| 383 | (smie-rule-parent))) | 431 | (smie-rule-parent))) |
| 384 | (`(:before . ,(or `"else" `"then" `"elsif" `"rescue" `"ensure")) 0) | 432 | (`(:before . ,(or `"else" `"then" `"elsif" `"rescue" `"ensure")) 0) |
| 385 | (`(:before . ,(or `"when")) | 433 | (`(:before . ,(or `"when")) |
| 386 | (if (not (smie-rule-sibling-p)) 0)) ;; ruby-indent-level | 434 | (if (not (smie-rule-sibling-p)) 0)) ;; ruby-indent-level |
| 387 | ;; Hack attack: Since newlines are separators, don't try to align args that | 435 | )) |
| 388 | ;; appear on a separate line. "" is for the case where the "previous | ||
| 389 | ;; separator" was not an implicit ";" but the BOB. | ||
| 390 | (`(:list-intro . ,(or `";" `"")) t))) | ||
| 391 | 436 | ||
| 392 | (defun ruby-imenu-create-index-in-block (prefix beg end) | 437 | (defun ruby-imenu-create-index-in-block (prefix beg end) |
| 393 | "Create an imenu index of methods inside a block." | 438 | "Create an imenu index of methods inside a block." |
diff --git a/test/indent/ruby.rb b/test/indent/ruby.rb index e40ef217e54..7c8de323bdb 100644 --- a/test/indent/ruby.rb +++ b/test/indent/ruby.rb | |||
| @@ -99,6 +99,14 @@ if something == :== | |||
| 99 | do_something | 99 | do_something |
| 100 | end | 100 | end |
| 101 | 101 | ||
| 102 | # Example from http://www.ruby-doc.org/docs/ProgrammingRuby/html/language.html | ||
| 103 | d = 4 + 5 + # no '\' needed | ||
| 104 | 6 + 7 | ||
| 105 | |||
| 106 | # Example from http://www.ruby-doc.org/docs/ProgrammingRuby/html/language.html | ||
| 107 | e = 8 + 9 \ | ||
| 108 | + 10 # '\' needed | ||
| 109 | |||
| 102 | begin | 110 | begin |
| 103 | foo | 111 | foo |
| 104 | ensure | 112 | ensure |
| @@ -109,20 +117,27 @@ end | |||
| 109 | MSG = 'Separate every 3 digits in the integer portion of a number' + | 117 | MSG = 'Separate every 3 digits in the integer portion of a number' + |
| 110 | 'with underscores(_).' | 118 | 'with underscores(_).' |
| 111 | 119 | ||
| 112 | # Examples below fail with SMIE. | 120 | class C |
| 121 | def foo | ||
| 122 | self.end | ||
| 123 | D.new.class | ||
| 124 | end | ||
| 125 | end | ||
| 113 | 126 | ||
| 114 | a = foo(j, k) - | 127 | a = foo(j, k) - |
| 115 | bar_tee | 128 | bar_tee |
| 116 | 129 | ||
| 117 | while a < b do # "do" is optional | 130 | while a < b do # "do" is optional |
| 118 | foo | 131 | foo |
| 119 | end | 132 | end |
| 120 | 133 | ||
| 121 | desc "foo foo" \ | 134 | desc "foo foo" \ |
| 122 | "bar bar" | 135 | "bar bar" |
| 123 | 136 | ||
| 124 | foo. | 137 | foo. |
| 125 | bar | 138 | bar |
| 126 | 139 | ||
| 140 | # FIXME: is this really valid Ruby? Isn't the newline after "foo" treated as | ||
| 141 | # an implicit semi-colon? | ||
| 127 | foo | 142 | foo |
| 128 | .bar | 143 | .bar |