X-Git-Url: https://code.delx.au/gnu-emacs/blobdiff_plain/7ffd37219b311035fd346a126d7799cb53c6c73d..56cd894e90949294d9578fd9fa45a179389f3306:/lisp/progmodes/ruby-mode.el diff --git a/lisp/progmodes/ruby-mode.el b/lisp/progmodes/ruby-mode.el index 75c59ebe1f..28c44307ff 100644 --- a/lisp/progmodes/ruby-mode.el +++ b/lisp/progmodes/ruby-mode.el @@ -39,8 +39,6 @@ ;;; Code: -(eval-when-compile (require 'cl)) - (defgroup ruby nil "Major mode for editing Ruby code." :prefix "ruby-" @@ -258,9 +256,28 @@ explicitly declared in magic comment." :group 'ruby) (defcustom ruby-insert-encoding-magic-comment t - "Insert a magic Emacs 'coding' comment upon save if this is non-nil." + "Insert a magic Ruby encoding comment upon save if this is non-nil. +The encoding will be auto-detected. The format of the encoding comment +is customizable via `ruby-encoding-magic-comment-style'. + +When set to `always-utf8' an utf-8 comment will always be added, +even if it's not required." :type 'boolean :group 'ruby) +(defcustom ruby-encoding-magic-comment-style 'ruby + "The style of the magic encoding comment to use." + :type '(choice + (const :tag "Emacs Style" emacs) + (const :tag "Ruby Style" ruby) + (const :tag "Custom Style" custom)) + :group 'ruby) + +(defcustom ruby-custom-encoding-magic-comment-template "# coding: %s" + "The encoding comment template to be used when +`ruby-encoding-magic-comment-style' is set to `custom'." + :type 'string + :group 'ruby) + (defcustom ruby-use-encoding-map t "Use `ruby-encoding-map' to set encoding magic comment if this is non-nil." :type 'boolean :group 'ruby) @@ -277,10 +294,13 @@ 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 "." exp)) + (exp "." id)) (exp1 (exp2) (exp2 "?" exp1 ":" exp1)) (exp2 ("def" insts "end") ("begin" insts-rescue-insts "end") @@ -295,10 +315,10 @@ explicitly declared in magic comment." ("unless" insts "end") ("if" if-body "end") ("case" cases "end")) - (formal-params ("opening-|" exp "|")) + (formal-params ("opening-|" exp "closing-|")) (for-body (for-head ";" insts)) (for-head (id "in" exp)) - (cases (exp "then" insts) ;; FIXME: Ruby also allows (exp ":" insts). + (cases (exp "then" insts) (cases "when" cases) (insts "else" insts)) (expseq (exp) );;(expseq "," expseq) (hashvals (id "=>" exp1) (hashvals "," hashvals)) @@ -322,14 +342,13 @@ explicitly declared in magic comment." (left ".." "...") (left "+" "-") (left "*" "/" "%" "**") - ;; (left "|") ; FIXME: Conflicts with | after block parameters. - (left "^" "&") + (left "&&" "||") + (left "^" "&" "|") (nonassoc "<=>") (nonassoc ">" ">=" "<" "<=") (nonassoc "==" "===" "!=") (nonassoc "=~" "!~") - (left "<<" ">>") - (left "&&" "||")))))) + (left "<<" ">>")))))) (defun ruby-smie--bosp () (save-excursion (skip-chars-backward " \t") @@ -340,7 +359,8 @@ 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) ?\?) @@ -348,9 +368,12 @@ explicitly declared in magic comment." (and (eq (char-before) ?=) (string-match "\\`\\s." (save-excursion (ruby-smie--backward-token)))) + (and (eq (char-before) ?|) + (member (save-excursion (ruby-smie--backward-token)) + '("|" "||"))) (and (eq (car (syntax-after (1- (point)))) 2) - (equal (save-excursion (ruby-smie--backward-token)) - "iuwu-mod")) + (member (save-excursion (ruby-smie--backward-token)) + '("iuwu-mod" "and" "or"))) (save-excursion (forward-comment 1) (eq (char-after) ?.)))))) @@ -367,6 +390,12 @@ explicitly declared in magic comment." (or (eq ?\{ (char-before)) (looking-back "\\_ pos (line-end-position)) (ruby-smie--implicit-semi-p)) (skip-chars-forward " \t") ";") - ((and (bolp) (not (bobp))) "") ;Presumably a heredoc. + ((and (bolp) (not (bobp))) ;Presumably a heredoc. + ;; Tokenize the whole heredoc as semicolon. + (goto-char (scan-sexps (point) -1)) + ";") ((and (> pos (point)) (not (bolp)) (ruby-smie--args-separator-p pos)) ;; We have "ID SPC ID", which is a method call, but it binds less tightly @@ -454,7 +496,13 @@ explicitly declared in magic comment." (if (ruby-smie--bosp) tok "iuwu-mod")) ((equal tok "|") - (if (ruby-smie--opening-pipe-p) "opening-|" tok)) + (cond + ((ruby-smie--opening-pipe-p) "opening-|") + ((ruby-smie--closing-pipe-p) "closing-|") + (t 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") @@ -467,6 +515,11 @@ explicitly declared in magic comment." (t ";"))) (t tok))))))) +(defun ruby-smie--indent-to-stmt () + (save-excursion + (smie-backward-sexp ";") + (cons 'column (smie-indent-virtual)))) + (defun ruby-smie-rules (kind token) (pcase (cons kind token) (`(:elem . basic) ruby-indent-level) @@ -487,26 +540,34 @@ 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. (let ((state (smie-backward-sexp 'halfsexp))) (when (eq t (car state)) (goto-char (cadr state)))) (cons 'column (smie-indent-virtual))))) - (`(:after . ,(or "=" "iuwu-mod")) 2) (`(: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))) (`(:before . ,(or `"else" `"then" `"elsif" `"rescue" `"ensure")) 0) (`(:before . ,(or `"when")) (if (not (smie-rule-sibling-p)) 0)) ;; ruby-indent-level - (`(:after . "+") ;FIXME: Probably applicable to most infix operators. - (if (smie-rule-parent-p ";") ruby-indent-level)) + (`(:after . ,(or "=" "iuwu-mod" "+" "-" "*" "/" "&&" "||" "%" "**" "^" "&" + "<=>" ">" "<" ">=" "<=" "==" "===" "!=" "<<" ">>" + "+=" "-=" "*=" "/=" "%=" "**=" "&=" "|=" "^=" "|" + "<<=" ">>=" "&&=" "||=" "and" "or")) + (if (smie-rule-parent-p ";" nil) ruby-indent-level)) + (`(:before . "begin") + (unless (save-excursion (skip-chars-backward " \t") (bolp)) + (smie-rule-parent))) )) (defun ruby-imenu-create-index-in-block (prefix beg end) @@ -577,43 +638,60 @@ explicitly declared in magic comment." (setq-local paragraph-separate paragraph-start) (setq-local paragraph-ignore-fill-prefix t)) +(defun ruby--insert-coding-comment (encoding) + "Insert a magic coding comment for ENCODING. +The style of the comment is controlled by `ruby-encoding-magic-comment-style'." + (let ((encoding-magic-comment-template + (pcase ruby-encoding-magic-comment-style + (`ruby "# coding: %s") + (`emacs "# -*- coding: %s -*-") + (`custom + ruby-custom-encoding-magic-comment-template)))) + (insert + (format encoding-magic-comment-template encoding) + "\n"))) + +(defun ruby--detect-encoding () + (if (eq ruby-insert-encoding-magic-comment 'always-utf8) + "utf-8" + (let ((coding-system + (or save-buffer-coding-system + buffer-file-coding-system))) + (if coding-system + (setq coding-system + (or (coding-system-get coding-system 'mime-charset) + (coding-system-change-eol-conversion coding-system nil)))) + (if coding-system + (symbol-name + (if ruby-use-encoding-map + (let ((elt (assq coding-system ruby-encoding-map))) + (if elt (cdr elt) coding-system)) + coding-system)) + "ascii-8bit")))) + +(defun ruby--encoding-comment-required-p () + (or (eq ruby-insert-encoding-magic-comment 'always-utf8) + (re-search-forward "[^\0-\177]" nil t))) + (defun ruby-mode-set-encoding () "Insert a magic comment header with the proper encoding if necessary." (save-excursion (widen) (goto-char (point-min)) - (when (re-search-forward "[^\0-\177]" nil t) + (when (ruby--encoding-comment-required-p) (goto-char (point-min)) - (let ((coding-system - (or save-buffer-coding-system - buffer-file-coding-system))) - (if coding-system - (setq coding-system - (or (coding-system-get coding-system 'mime-charset) - (coding-system-change-eol-conversion coding-system nil)))) - (setq coding-system - (if coding-system - (symbol-name - (if ruby-use-encoding-map - (let ((elt (assq coding-system ruby-encoding-map))) - (if elt (cdr elt) coding-system)) - coding-system)) - "ascii-8bit")) + (let ((coding-system (ruby--detect-encoding))) (when coding-system (if (looking-at "^#!") (beginning-of-line 2)) - (cond ((looking-at "\\s *#.*-\*-\\s *\\(en\\)?coding\\s *:\\s *\\([-a-z0-9_]*\\)\\s *\\(;\\|-\*-\\)") + (cond ((looking-at "\\s *#\\s *.*\\(en\\)?coding\\s *:\\s *\\([-a-z0-9_]*\\)") + ;; update existing encoding comment if necessary (unless (string= (match-string 2) coding-system) (goto-char (match-beginning 2)) (delete-region (point) (match-end 2)) - (and (looking-at "-\*-") - (let ((n (skip-chars-backward " "))) - (cond ((= n 0) (insert " ") (backward-char)) - ((= n -1) (insert " ")) - ((forward-char))))) (insert coding-system))) ((looking-at "\\s *#.*coding\\s *[:=]")) (t (when ruby-insert-encoding-magic-comment - (insert "# -*- coding: " coding-system " -*-\n")))) + (ruby--insert-coding-comment coding-system)))) (when (buffer-modified-p) (basic-save-buffer-1))))))) @@ -633,7 +711,7 @@ explicitly declared in magic comment." "Indent the current line to COLUMN." (when column (let (shift top beg) - (and (< column 0) (error "invalid nest")) + (and (< column 0) (error "Invalid nesting")) (setq shift (current-column)) (beginning-of-line) (setq beg (point)) @@ -724,7 +802,7 @@ Can be one of `heredoc', `modifier', `expr-qstr', `expr-re'." (forward-char -1)) (cond ((zerop n)) (no-error nil) - ((error "unterminated string"))))) + ((error "Unterminated string"))))) (defun ruby-deep-indent-paren-p (c) "TODO: document." @@ -750,7 +828,8 @@ Can be one of `heredoc', `modifier', `expr-qstr', `expr-re'." ((looking-at "[\"`]") ;skip string (cond ((and (not (eobp)) - (ruby-forward-string (buffer-substring (point) (1+ (point))) end t t)) + (ruby-forward-string (buffer-substring (point) (1+ (point))) + end t t)) nil) (t (setq in-string (point)) @@ -935,7 +1014,7 @@ Can be one of `heredoc', `modifier', `expr-qstr', `expr-re'." (setq in-string (match-end 0)) (goto-char ruby-indent-point))) (t - (error (format "bad string %s" + (error (format "Bad string %s" (buffer-substring (point) pnt) )))))) (list in-string nest depth pcol)) @@ -1010,7 +1089,7 @@ Can be one of `heredoc', `modifier', `expr-qstr', `expr-re'." (setq indent (current-column))))) ((and (nth 2 state) (> (nth 2 state) 0)) ; in nest (if (null (cdr (nth 1 state))) - (error "invalid nest")) + (error "Invalid nesting")) (goto-char (cdr (nth 1 state))) (forward-word -1) ; skip back a keyword (setq begin (point)) @@ -1057,7 +1136,8 @@ Can be one of `heredoc', `modifier', `expr-qstr', `expr-re'." (while (and (re-search-forward "#" pos t) (setq end (1- (point))) (or (ruby-special-char-p end) - (and (setq state (ruby-parse-region parse-start end)) + (and (setq state (ruby-parse-region + parse-start end)) (nth 0 state)))) (setq end nil)) (goto-char (or end pos)) @@ -1068,7 +1148,8 @@ Can be one of `heredoc', `modifier', `expr-qstr', `expr-re'." (and (or (and (looking-at ruby-symbol-re) (skip-chars-backward ruby-symbol-chars) - (looking-at (concat "\\<\\(" ruby-block-hanging-re "\\)\\>")) + (looking-at (concat "\\<\\(" ruby-block-hanging-re + "\\)\\>")) (not (eq (point) (nth 3 state))) (save-excursion (goto-char (match-end 0)) @@ -1112,7 +1193,8 @@ Can be one of `heredoc', `modifier', `expr-qstr', `expr-re'." (cond ((and (null op-end) - (not (looking-at (concat "\\<\\(" ruby-block-hanging-re "\\)\\>"))) + (not (looking-at (concat "\\<\\(" ruby-block-hanging-re + "\\)\\>"))) (eq (ruby-deep-indent-paren-p t) 'space) (not (bobp))) (widen) @@ -1249,7 +1331,8 @@ With ARG, do it many times. Negative ARG means move backward." (skip-chars-forward ",.:;|&^~=!?\\+\\-\\*") (looking-at "\\s(")) (goto-char (scan-sexps (point) 1))) - ((and (looking-at (concat "\\<\\(" ruby-block-beg-re "\\)\\>")) + ((and (looking-at (concat "\\<\\(" ruby-block-beg-re + "\\)\\>")) (not (eq (char-before (point)) ?.)) (not (eq (char-before (point)) ?:))) (ruby-end-of-block) @@ -1266,7 +1349,8 @@ With ARG, do it many times. Negative ARG means move backward." (progn (setq expr (or expr (ruby-expr-beg) (looking-at "%\\sw?\\Sw\\|[\"'`/]"))) - (nth 1 (setq state (apply 'ruby-parse-partial nil state)))) + (nth 1 (setq state (apply #'ruby-parse-partial + nil state)))) (setq expr t) (skip-chars-forward "<")) (not expr)))) @@ -1290,10 +1374,11 @@ With ARG, do it many times. Negative ARG means move forward." (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)))) + (pcase (char-before) + (`?% (forward-char -1)) + ((or `?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))))) @@ -1307,13 +1392,14 @@ With ARG, do it many times. Negative ARG means move forward." (t (forward-char 1) (while (progn (forward-word -1) - (case (char-before) - (?_ t) - (?. (forward-char -1) t) - ((?$ ?@) + (pcase (char-before) + (`?_ t) + (`?. (forward-char -1) t) + ((or `?$ `?@) (forward-char -1) - (and (eq (char-before) (char-after)) (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) @@ -1504,8 +1590,9 @@ If the result is do-end block, it will always be multiline." (let ((start (point)) beg end) (end-of-line) (unless - (if (and (re-search-backward "\\({\\)\\|\\_\\)") (progn + (goto-char (or (match-beginning 1) (match-beginning 2))) (setq beg (point)) (save-match-data (ruby-forward-sexp)) (setq end (point)) @@ -1723,153 +1810,155 @@ See `font-lock-syntax-table'.") (defconst ruby-font-lock-keyword-beg-re "\\(?:^\\|[^.@$]\\|\\.\\.\\)") (defconst ruby-font-lock-keywords - (list - ;; functions - '("^\\s *def\\s +\\(?:[^( \t\n.]*\\.\\)?\\([^( \t\n]+\\)" + `(;; Functions. + ("^\\s *def\\s +\\(?:[^( \t\n.]*\\.\\)?\\([^( \t\n]+\\)" 1 font-lock-function-name-face) - ;; keywords - (list (concat - ruby-font-lock-keyword-beg-re - (regexp-opt - '("alias" - "and" - "begin" - "break" - "case" - "class" - "def" - "defined?" - "do" - "elsif" - "else" - "fail" - "ensure" - "for" - "end" - "if" - "in" - "module" - "next" - "not" - "or" - "redo" - "rescue" - "retry" - "return" - "then" - "super" - "unless" - "undef" - "until" - "when" - "while" - "yield") - 'symbols)) - 1 'font-lock-keyword-face) - ;; some core methods - (list (concat - ruby-font-lock-keyword-beg-re - (regexp-opt - '(;; built-in methods on Kernel - "__callee__" - "__dir__" - "__method__" - "abort" - "at_exit" - "autoload" - "autoload?" - "binding" - "block_given?" - "caller" - "catch" - "eval" - "exec" - "exit" - "exit!" - "fail" - "fork" - "format" - "lambda" - "load" - "loop" - "open" - "p" - "print" - "printf" - "proc" - "putc" - "puts" - "raise" - "rand" - "readline" - "readlines" - "require" - "require_relative" - "sleep" - "spawn" - "sprintf" - "srand" - "syscall" - "system" - "throw" - "trap" - "warn" - ;; keyword-like private methods on Module - "alias_method" - "attr" - "attr_accessor" - "attr_reader" - "attr_writer" - "define_method" - "extend" - "include" - "module_function" - "prepend" - "private" - "protected" - "public" - "refine" - "using") - 'symbols)) - 1 'font-lock-builtin-face) - ;; here-doc beginnings - `(,ruby-here-doc-beg-re 0 (unless (ruby-singleton-class-p (match-beginning 0)) - 'font-lock-string-face)) - ;; Perl-ish keywords - "\\_<\\(?:BEGIN\\|END\\)\\_>\\|^__END__$" - ;; variables - `(,(concat ruby-font-lock-keyword-beg-re - "\\_<\\(nil\\|self\\|true\\|false\\)\\>") + ;; Keywords. + (,(concat + ruby-font-lock-keyword-beg-re + (regexp-opt + '("alias" + "and" + "begin" + "break" + "case" + "class" + "def" + "defined?" + "do" + "elsif" + "else" + "fail" + "ensure" + "for" + "end" + "if" + "in" + "module" + "next" + "not" + "or" + "redo" + "rescue" + "retry" + "return" + "then" + "super" + "unless" + "undef" + "until" + "when" + "while" + "yield") + 'symbols)) + (1 font-lock-keyword-face)) + ;; Some core methods. + (,(concat + ruby-font-lock-keyword-beg-re + (regexp-opt + '( ;; built-in methods on Kernel + "__callee__" + "__dir__" + "__method__" + "abort" + "at_exit" + "autoload" + "autoload?" + "binding" + "block_given?" + "caller" + "catch" + "eval" + "exec" + "exit" + "exit!" + "fail" + "fork" + "format" + "lambda" + "load" + "loop" + "open" + "p" + "print" + "printf" + "proc" + "putc" + "puts" + "raise" + "rand" + "readline" + "readlines" + "require" + "require_relative" + "sleep" + "spawn" + "sprintf" + "srand" + "syscall" + "system" + "throw" + "trap" + "warn" + ;; keyword-like private methods on Module + "alias_method" + "attr" + "attr_accessor" + "attr_reader" + "attr_writer" + "define_method" + "extend" + "include" + "module_function" + "prepend" + "private" + "protected" + "public" + "refine" + "using") + 'symbols)) + (1 font-lock-builtin-face)) + ;; Here-doc beginnings. + (,ruby-here-doc-beg-re + (0 (unless (ruby-singleton-class-p (match-beginning 0)) + 'font-lock-string-face))) + ;; Perl-ish keywords. + "\\_<\\(?:BEGIN\\|END\\)\\_>\\|^__END__$" + ;; Variables. + (,(concat ruby-font-lock-keyword-beg-re + "\\_<\\(nil\\|self\\|true\\|false\\)\\_>") 1 font-lock-variable-name-face) - ;; keywords that evaluate to certain values - '("\\_<__\\(?:LINE\\|ENCODING\\|FILE\\)__\\_>" 0 font-lock-variable-name-face) - ;; symbols - '("\\(^\\|[^:]\\)\\(:\\([-+~]@?\\|[/%&|^`]\\|\\*\\*?\\|<\\(<\\|=>?\\)?\\|>[>=]?\\|===?\\|=~\\|![~=]?\\|\\[\\]=?\\|@?\\(\\w\\|_\\)+\\([!?=]\\|\\b_*\\)\\|#{[^}\n\\\\]*\\(\\\\.[^}\n\\\\]*\\)*}\\)\\)" + ;; Keywords that evaluate to certain values. + ("\\_<__\\(?:LINE\\|ENCODING\\|FILE\\)__\\_>" + (0 font-lock-variable-name-face)) + ;; Symbols. + ("\\(^\\|[^:]\\)\\(:\\([-+~]@?\\|[/%&|^`]\\|\\*\\*?\\|<\\(<\\|=>?\\)?\\|>[>=]?\\|===?\\|=~\\|![~=]?\\|\\[\\]=?\\|@?\\(\\w\\|_\\)+\\([!?=]\\|\\b_*\\)\\|#{[^}\n\\\\]*\\(\\\\.[^}\n\\\\]*\\)*}\\)\\)" 2 font-lock-constant-face) - ;; variables - '("\\(\\$\\([^a-zA-Z0-9 \n]\\|[0-9]\\)\\)\\W" + ;; Variables. + ("\\(\\$\\([^a-zA-Z0-9 \n]\\|[0-9]\\)\\)\\W" 1 font-lock-variable-name-face) - '("\\(\\$\\|@\\|@@\\)\\(\\w\\|_\\)+" + ("\\(\\$\\|@\\|@@\\)\\(\\w\\|_\\)+" 0 font-lock-variable-name-face) - ;; constants - '("\\(?:\\_<\\|::\\)\\([A-Z]+\\(\\w\\|_\\)*\\)" + ;; Constants. + ("\\(?:\\_<\\|::\\)\\([A-Z]+\\(\\w\\|_\\)*\\)" 1 (unless (eq ?\( (char-after)) font-lock-type-face)) - '("\\(^\\s *\\|[\[\{\(,]\\s *\\|\\sw\\s +\\)\\(\\(\\sw\\|_\\)+\\):[^:]" 2 font-lock-constant-face) - ;; conversion methods on Kernel - (list (concat ruby-font-lock-keyword-beg-re - (regexp-opt '("Array" "Complex" "Float" "Hash" - "Integer" "Rational" "String") 'symbols)) - 1 font-lock-builtin-face) - ;; expression expansion - '(ruby-match-expression-expansion + ("\\(^\\s *\\|[\[\{\(,]\\s *\\|\\sw\\s +\\)\\(\\(\\sw\\|_\\)+\\):[^:]" + (2 font-lock-constant-face)) + ;; Conversion methods on Kernel. + (,(concat ruby-font-lock-keyword-beg-re + (regexp-opt '("Array" "Complex" "Float" "Hash" + "Integer" "Rational" "String") 'symbols)) + (1 font-lock-builtin-face)) + ;; Expression expansion. + (ruby-match-expression-expansion 2 font-lock-variable-name-face t) - ;; negation char - '("[^[:alnum:]_]\\(!\\)[^=]" + ;; Negation char. + ("[^[:alnum:]_]\\(!\\)[^=]" 1 font-lock-negation-char-face) - ;; character literals - ;; FIXME: Support longer escape sequences. - '("\\_<\\?\\\\?\\S " 0 font-lock-string-face) - ) + ;; Character literals. + ;; FIXME: Support longer escape sequences. + ("\\_<\\?\\\\?\\S " 0 font-lock-string-face) + ) "Additional expressions to highlight in Ruby mode.") (defun ruby-match-expression-expansion (limit) @@ -1884,12 +1973,7 @@ See `font-lock-syntax-table'.") ;;;###autoload (define-derived-mode ruby-mode prog-mode "Ruby" - "Major mode for editing Ruby scripts. -\\[ruby-indent-line] properly indents subexpressions of multi-line -class, module, def, if, while, for, do, and case statements, taking -nesting into account. - -The variable `ruby-indent-level' controls the amount of indentation. + "Major mode for editing Ruby code. \\{ruby-mode-map}" (ruby-mode-variables)