summaryrefslogtreecommitdiff
path: root/misc/ruby-mode.el
diff options
context:
space:
mode:
Diffstat (limited to 'misc/ruby-mode.el')
-rw-r--r--misc/ruby-mode.el280
1 files changed, 152 insertions, 128 deletions
diff --git a/misc/ruby-mode.el b/misc/ruby-mode.el
index 9144855983..077866fee5 100644
--- a/misc/ruby-mode.el
+++ b/misc/ruby-mode.el
@@ -283,9 +283,9 @@ The variable ruby-indent-level controls the amount of indentation.
(defun ruby-special-char-p (&optional pnt)
(let ((c (char-before pnt)))
- (cond ((or (eq c ??) (eq c ?$)))
- ((eq c ?\\)
- (eq (char-before (1- (or pnt (point)))) ??)))))
+ (cond ((or (eq c ??) (eq c ?$)))
+ ((eq c ?\\)
+ (eq (char-before (1- (or pnt (point)))) ??)))))
(defun ruby-expr-beg (&optional option)
(save-excursion
@@ -296,8 +296,8 @@ The variable ruby-indent-level controls the amount of indentation.
((progn
(forward-char -1)
(and (looking-at "\\?")
- (or (ruby-special-char-p)
- (eq (char-syntax (char-before (point)) ?w)))))
+ (or (eq (char-syntax (char-before (point))) ?w)
+ (ruby-special-char-p))))
nil)
((or (looking-at ruby-operator-re)
(looking-at "[\\[({,;]")
@@ -544,36 +544,42 @@ The variable ruby-indent-level controls the amount of indentation.
(defun ruby-indent-size (pos nest)
(+ pos (* (or nest 1) ruby-indent-level)))
-(defconst ruby-assign-re "\\s *\\(&&\\|||\\|<<\\|>>[-+*/%&|^]\\)?=\\s *")
-
-(defun ruby-backward-arg (limit depth)
- (let ((indent (ruby-indent-size 0 depth))
- beg pnt (last (point)))
- (when limit
- (goto-char limit)
- (ruby-forward-sexp)
- (setq limit (point)))
- (goto-char last)
- (setq pnt (point))
- (ruby-backward-sexp)
- (while (and
- (not (bobp))
- (setq beg (point))
- (progn
- (ruby-backward-sexp)
- (or (looking-at ruby-block-hanging-re)
- (save-excursion
- (ruby-forward-sexp)
- (looking-at ruby-assign-re)))))
- (setq last beg))
- (goto-char last)))
+(defconst ruby-assign-re "\\s *\\(&&\\|||\\|<<\\|>>\\|[-+*/%&|^]\\)?=\\s *")
+
+(defun ruby-beginning-of-arg (start end)
+ (save-restriction
+ (narrow-to-region start (1+ end))
+ (goto-char start)
+ (let ((beg t) arg)
+ (while
+ (progn
+ (skip-chars-forward " \t\n")
+ (and (not (eobp))
+ (= (ruby-forward-sexp) 0)))
+ (skip-syntax-forward " ")
+ (cond ((looking-at ",")
+ (forward-char)
+ (setq arg start beg t))
+ ((ruby-expr-beg) t)
+ ((looking-at "=>\\s *")
+ (goto-char (match-end 0))
+ (setq arg nil beg nil))
+ ((looking-at ruby-assign-re)
+ (goto-char (match-end 0))
+ (if beg (setq beg nil arg (point))))
+ ((looking-at ruby-operator-re)
+ (goto-char (match-end 0))
+ (if beg (setq beg nil arg (match-end 0))))
+ ((not (eq (char-syntax (char-after)) ?\())
+ (setq start (point)))))
+ (goto-char (or arg start)))))
(defun ruby-calculate-indent (&optional parse-start)
(save-excursion
(beginning-of-line)
(let ((indent-point (point))
(case-fold-search nil)
- state bol eol
+ state bol eol begin
(paren (progn (skip-syntax-forward " ")
(and (char-after) (matching-paren (char-after)))))
(indent 0))
@@ -587,51 +593,47 @@ The variable ruby-indent-level controls the amount of indentation.
(cond
((nth 0 state) ; within string
(setq indent nil)) ; do nothing
- ((and (car (nth 1 state)) ; in paren
- (or (not (eq (car (nth 1 state)) ?\{))
- (save-excursion
- (goto-char (1- (cdr (nth 1 state))))
- (or (ruby-expr-beg) (setq paren nil)))))
- (goto-char (cdr (nth 1 state)))
- (if (ruby-deep-indent-paren-p (car (nth 1 state)))
- (let ((s (ruby-parse-region (point) indent-point)))
- (cond
- ((and (nth 2 s) (> (nth 2 s) 0))
- (goto-char (cdr (nth 1 s)))
- (forward-word -1)
- (setq indent (ruby-indent-size (current-column) (nth 2 state))))
- (t
- (setq indent (current-column))
- (cond (paren (setq indent (1- indent)))
- ((eq (car (nth 1 state)) ?\())
- (t (setq indent (ruby-indent-size (1- indent) 1)))))))
- (cond
- ((nth 3 state)
- (goto-char (nth 3 state))
- (setq indent (ruby-indent-size (current-column) (nth 2 state))))
- (t
- (goto-char parse-start)
- (back-to-indentation)
- (setq indent (ruby-indent-size (current-column) (nth 2 state)))))
- ))
- ((and (nth 2 state)(> (nth 2 state) 0)) ; in nest
+ ((car (nth 1 state)) ; in paren
+ (cond
+ ((and (eq (car (nth 1 state)) ?\{) ; brace block
+ (save-excursion
+ (goto-char (1- (cdr (nth 1 state))))
+ (not (ruby-expr-beg))))
+ (setq paren nil)
+ (back-to-indentation)
+ (setq indent (ruby-indent-size (current-column) (nth 2 state))))
+ (t
+ (goto-char (setq begin (cdr (nth 1 state))))
+ (let ((deep (ruby-deep-indent-paren-p (car (nth 1 state)))))
+ (if deep
+ (cond ((and (eq deep t) (eq (car (nth 1 state)) paren))
+ (skip-syntax-backward " ")
+ (setq indent (1- (current-column))))
+ ((let ((s (ruby-parse-region (point) indent-point)))
+ (and (nth 2 s) (> (nth 2 s) 0)
+ (or (goto-char (cdr (nth 1 s))) t)))
+ (forward-word -1)
+ (setq indent (ruby-indent-size (current-column) (nth 2 state))))
+ (t
+ (setq indent (current-column))
+ (cond ((eq deep 'space))
+ (paren (setq indent (1- indent)))
+ (t (setq indent (ruby-indent-size (1- indent) 1))))))
+ (if (nth 3 state) (goto-char (nth 3 state))
+ (goto-char parse-start) (back-to-indentation))
+ (setq indent (ruby-indent-size (current-column) (nth 2 state))))))))
+ ((and (nth 2 state) (> (nth 2 state) 0)) ; in nest
(if (null (cdr (nth 1 state)))
(error "invalid nest"))
(goto-char (cdr (nth 1 state)))
(forward-word -1) ; skip back a keyword
+ (setq begin (point))
(cond
((looking-at "do\\>[^_]") ; iter block is a special case
- (cond
- ((nth 3 state)
- (goto-char (nth 3 state))
- (setq indent (ruby-indent-size (current-column) (nth 2 state))))
- (t
- (goto-char parse-start)
- (back-to-indentation)
- (setq indent (ruby-indent-size (current-column) (nth 2 state))))))
+ (if (nth 3 state) (goto-char (nth 3 state))
+ (goto-char parse-start) (back-to-indentation))
+ (setq indent (ruby-indent-size (current-column) (nth 2 state))))
(t
- (goto-char (1- (cdr (nth 1 state))))
- (ruby-backward-sexp)
(setq indent (+ (current-column) ruby-indent-level)))))
((and (nth 2 state) (< (nth 2 state) 0)) ; in negative nest
@@ -652,7 +654,8 @@ The variable ruby-indent-level controls the amount of indentation.
(save-excursion
(beginning-of-line)
(not (bobp)))
- (null (car (nth 1 state))))
+ (or (ruby-deep-indent-paren-p t)
+ (null (car (nth 1 state)))))
;; goto beginning of non-empty no-comment line
(let (end done)
(while (not done)
@@ -673,6 +676,7 @@ The variable ruby-indent-level controls the amount of indentation.
(and
(setq state (ruby-parse-region parse-start (point)))
(nth 0 state)
+ (setq begin (nth 1 state))
(goto-char pos)))
(or (bobp) (forward-char -1))
(and
@@ -684,8 +688,7 @@ The variable ruby-indent-level controls the amount of indentation.
(goto-char (match-end 0))
(not (looking-at "[a-z_]"))))
(and (looking-at ruby-operator-re)
- (not (eq (char-after (1- (point))) ??))
- (not (eq (char-after (1- (point))) ?$))
+ (not (ruby-special-char-p))
(or (not (eq ?/ (char-after (point))))
(null (nth 0 (ruby-parse-region parse-start (point)))))
(or (not (eq ?| (char-after (point))))
@@ -706,9 +709,9 @@ The variable ruby-indent-level controls the amount of indentation.
(cond
((and
(not (looking-at ruby-block-hanging-re))
- (ruby-deep-indent-paren-p t)
+ (eq (ruby-deep-indent-paren-p t) 'space)
(not (bobp)))
- (ruby-backward-arg (cdr (nth 1 state)) (nth 2 state))
+ (ruby-beginning-of-arg (or begin parse-start) (point))
(current-column))
(t
(+ indent ruby-indent-level))))))))
@@ -799,64 +802,81 @@ An end of a defun is found by moving forward from the beginning of one."
(interactive "p")
(if (and (numberp cnt) (< cnt 0))
(ruby-backward-sexp (- cnt))
- (dotimes (i (or cnt 1))
- (skip-chars-forward " \t\n,.:;|&^~=!?\\+\\-\\*")
- (cond ((looking-at "\\s(")
- (goto-char (scan-sexps (point) 1)))
- ((looking-at ruby-block-beg-re)
- (ruby-end-of-block)
- (forward-word 1))
- ((looking-at "\\(\\$\\|@@?\\)?\\sw")
- (while (progn
- (while (progn (forward-word 1) (looking-at "_")))
- (cond ((looking-at "::") (forward-char 2) t)
- ((> (skip-chars-forward ".") 0))
- ((looking-at "\\?\\|!\\(=[~=>]\\|[^~=]\\)")
- (forward-char 1) nil)))))
- ((let (state expr)
- (while
- (progn
- (setq expr (or expr (ruby-expr-beg)
- (looking-at "%\\sw?\\Sw\\|[\"'`/]")))
- (nth 1 (setq state (apply 'ruby-parse-partial nil state))))
- (setq expr t)
- (skip-chars-forward "<"))
- (not expr)))))))
+ (let ((i (or cnt 1)))
+ (condition-case nil
+ (while (> i 0)
+ (skip-syntax-forward " ")
+ (cond ((looking-at "\\?\\(\\\\[CM]-\\)*\\\\?\\S ")
+ (goto-char (match-end 0)))
+ ((progn
+ (skip-chars-forward ",.:;|&^~=!?\\+\\-\\*")
+ (looking-at "\\s("))
+ (goto-char (scan-sexps (point) 1)))
+ ((looking-at ruby-block-beg-re)
+ (ruby-end-of-block)
+ (forward-word 1))
+ ((looking-at "\\(\\$\\|@@?\\)?\\sw")
+ (while (progn
+ (while (progn (forward-word 1) (looking-at "_")))
+ (cond ((looking-at "::") (forward-char 2) t)
+ ((> (skip-chars-forward ".") 0))
+ ((looking-at "\\?\\|!\\(=[~=>]\\|[^~=]\\)")
+ (forward-char 1) nil)))))
+ ((let (state expr)
+ (while
+ (progn
+ (setq expr (or expr (ruby-expr-beg)
+ (looking-at "%\\sw?\\Sw\\|[\"'`/]")))
+ (nth 1 (setq state (apply 'ruby-parse-partial nil state))))
+ (setq expr t)
+ (skip-chars-forward "<"))
+ (not expr))))
+ (setq i (1- i)))
+ ((error) (forward-word)))
+ i)))
(defun-region-command ruby-backward-sexp (&optional cnt)
(interactive "p")
- (dotimes (i (or cnt 1))
- (skip-chars-backward " \t\n,.:;|&^~=!?\\+\\-\\*")
- (forward-char -1)
- (cond ((looking-at "\\s)")
- (goto-char (scan-sexps (1+ (point)) -1))
- (case (char-before)
- (?% (forward-char -1))
- ('(?q ?Q ?w ?W ?r ?x)
- (if (eq (char-before (1- (point))) ?%) (forward-char -2))))
- nil)
- ((looking-at "\\s\"\\|\\\\\\S_")
- (let ((c (char-to-string (char-before (match-end 0)))))
- (while (and (search-backward c)
- (oddp (skip-chars-backward "\\")))))
- nil)
- ((looking-at "\\s.\\|\\s\\"))
- ((looking-at "\\s(") nil)
- (t
- (forward-char 1)
- (while (progn (forward-word -1)
- (case (char-before)
- (?_ t)
- (?. (forward-char -1) t)
- ((?$ ?@)
- (forward-char -1)
- (and (eq (char-before) (char-after)) (forward-char -1)))
- (?:
- (forward-char -1)
- (eq (char-before) :)))))
- (if (looking-at ruby-block-end-re)
- (ruby-beginning-of-block))
- nil))))
+ (if (and (numberp cnt) (< cnt 0))
+ (ruby-forward-sexp (- cnt))
+ (let ((i (or cnt 1)))
+ (condition-case nil
+ (while (> i 0)
+ (skip-chars-backward " \t\n,.:;|&^~=!?\\+\\-\\*")
+ (forward-char -1)
+ (cond ((looking-at "\\s)")
+ (goto-char (scan-sexps (1+ (point)) -1))
+ (case (char-before)
+ (?% (forward-char -1))
+ ('(?q ?Q ?w ?W ?r ?x)
+ (if (eq (char-before (1- (point))) ?%) (forward-char -2))))
+ nil)
+ ((looking-at "\\s\"\\|\\\\\\S_")
+ (let ((c (char-to-string (char-before (match-end 0)))))
+ (while (and (search-backward c)
+ (oddp (skip-chars-backward "\\")))))
+ nil)
+ ((looking-at "\\s.\\|\\s\\")
+ (if (ruby-special-char-p) (forward-char -1)))
+ ((looking-at "\\s(") nil)
+ (t
+ (forward-char 1)
+ (while (progn (forward-word -1)
+ (case (char-before)
+ (?_ t)
+ (?. (forward-char -1) t)
+ ((?$ ?@)
+ (forward-char -1)
+ (and (eq (char-before) (char-after)) (forward-char -1)))
+ (?:
+ (forward-char -1)
+ (eq (char-before) :)))))
+ (if (looking-at ruby-block-end-re)
+ (ruby-beginning-of-block))
+ nil))
+ (setq i (1- i)))
+ ((error)))
+ i)))
(defun ruby-reindent-then-newline-and-indent ()
(interactive "*")
@@ -1097,7 +1117,11 @@ balanced expression is found."
2 font-lock-reference-face)
;; expression expansion
'("#\\({[^}\n\\\\]*\\(\\\\.[^}\n\\\\]*\\)*}\\|\\(\\$\\|@\\|@@\\)\\(\\w\\|_\\)+\\)"
- 0 font-lock-variable-name-face t))
+ 0 font-lock-variable-name-face t)
+ ;; warn lower camel case
+ ;'("\\<[a-z]+[a-z0-9]*[A-Z][A-Za-z0-9]*\\([!?]?\\|\\>\\)"
+ ; 0 font-lock-warning-face)
+ )
"*Additional expressions to highlight in ruby mode."))
((featurep 'hilit19)