: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
(const :tag "Custom Style" custom))
:group 'ruby)
-(defcustom ruby-custom-encoding-magic-comment-template "# coding: %s"
+(defcustom ruby-custom-encoding-magic-comment-template "# encoding: %s"
"The encoding comment template to be used when
`ruby-encoding-magic-comment-style' is set to `custom'."
:type 'string
("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))
(left ".." "...")
(left "+" "-")
(left "*" "/" "%" "**")
- ;; (left "|") ; FIXME: Conflicts with | after block parameters.
(left "&&" "||")
- (left "^" "&")
+ (left "^" "&" "|")
(nonassoc "<=>")
(nonassoc ">" ">=" "<" "<=")
(nonassoc "==" "===" "!=")
(string-match "\\`\\s." (save-excursion
(ruby-smie--backward-token))))
(and (eq (char-before) ?|)
- (eq (char-before (1- (point))) ?|))
+ (member (save-excursion (ruby-smie--backward-token))
+ '("|" "||")))
(and (eq (car (syntax-after (1- (point)))) 2)
(member (save-excursion (ruby-smie--backward-token))
'("iuwu-mod" "and" "or")))
(or (eq ?\{ (char-before))
(looking-back "\\_<do" (- (point) 2)))))
+(defun ruby-smie--closing-pipe-p ()
+ (save-excursion
+ (if (eq ?| (char-before)) (forward-char -1))
+ (and (re-search-backward "|" (line-beginning-position) t)
+ (ruby-smie--opening-pipe-p))))
+
(defun ruby-smie--args-separator-p (pos)
(and
(< pos (line-end-position))
((string-match-p "\\`|[*&]?\\'" tok)
(forward-char (- 1 (length tok)))
(setq tok "|")
- (if (ruby-smie--opening-pipe-p) "opening-|" tok))
+ (cond
+ ((ruby-smie--opening-pipe-p) "opening-|")
+ ((ruby-smie--closing-pipe-p) "closing-|")
+ (t tok)))
((and (equal tok "") (looking-at "\\\\\n"))
(goto-char (match-end 0)) (ruby-smie--forward-token))
((equal tok "do")
(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))
(if (not (smie-rule-sibling-p)) 0)) ;; ruby-indent-level
(`(:after . ,(or "=" "iuwu-mod" "+" "-" "*" "/" "&&" "||" "%" "**" "^" "&"
"<=>" ">" "<" ">=" "<=" "==" "===" "!=" "<<" ">>"
- "+=" "-=" "*=" "/=" "%=" "**=" "&=" "|=" "^="
+ "+=" "-=" "*=" "/=" "%=" "**=" "&=" "|=" "^=" "|"
"<<=" ">>=" "&&=" "||=" "and" "or"))
(if (smie-rule-parent-p ";" nil) ruby-indent-level))
(`(:before . "begin")
(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
- (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 coding-system)
- "\n")))))
+ (ruby--insert-coding-comment coding-system))))
(when (buffer-modified-p)
(basic-save-buffer-1)))))))
(let ((start (point)) beg end)
(end-of-line)
(unless
- (if (and (re-search-backward "\\({\\)\\|\\_<do\\(\\s \\|$\\||\\)")
+ (if (and (re-search-backward "\\(?:[^#]\\)\\({\\)\\|\\(\\_<do\\_>\\)")
(progn
+ (goto-char (or (match-beginning 1) (match-beginning 2)))
(setq beg (point))
(save-match-data (ruby-forward-sexp))
(setq end (point))
"\\_<\\(?:BEGIN\\|END\\)\\_>\\|^__END__$"
;; Variables.
(,(concat ruby-font-lock-keyword-beg-re
- "\\_<\\(nil\\|self\\|true\\|false\\)\\>")
+ "\\_<\\(nil\\|self\\|true\\|false\\)\\_>")
1 font-lock-variable-name-face)
;; Keywords that evaluate to certain values.
("\\_<__\\(?:LINE\\|ENCODING\\|FILE\\)__\\_>"