X-Git-Url: https://code.delx.au/gnu-emacs/blobdiff_plain/43c75c8eae588a358af95c942742213040240b67..7e09ef09a479731d01b1ca46e94ddadd73ac98e3:/lisp/progmodes/ruby-mode.el diff --git a/lisp/progmodes/ruby-mode.el b/lisp/progmodes/ruby-mode.el index e05aef80e8..d1e42ca344 100644 --- a/lisp/progmodes/ruby-mode.el +++ b/lisp/progmodes/ruby-mode.el @@ -1,6 +1,6 @@ ;;; ruby-mode.el --- Major mode for editing Ruby files -;; Copyright (C) 1994-2014 Free Software Foundation, Inc. +;; Copyright (C) 1994-2015 Free Software Foundation, Inc. ;; Authors: Yukihiro Matsumoto ;; Nobuyoshi Nakada @@ -106,7 +106,7 @@ "Regexp to match the beginning of a heredoc.") (defconst ruby-expression-expansion-re - "\\(?:[^\\]\\|\\=\\)\\(\\\\\\\\\\)*\\(#\\({[^}\n\\\\]*\\(\\\\.[^}\n\\\\]*\\)*}\\|\\(\\$\\|@\\|@@\\)\\(\\w\\|_\\)+\\)\\)")) + "\\(?:[^\\]\\|\\=\\)\\(\\\\\\\\\\)*\\(#\\({[^}\n\\\\]*\\(\\\\.[^}\n\\\\]*\\)*}\\|\\(\\$\\|@\\|@@\\)\\(\\w\\|_\\)+\\|\\$[^a-zA-Z \n]\\)\\)")) (defun ruby-here-doc-end-match () "Return a regexp to find the end of a heredoc. @@ -152,6 +152,7 @@ This should only be called after matching against `ruby-here-doc-beg-re'." (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 "C-c {") 'ruby-toggle-block) + (define-key map (kbd "C-c '") 'ruby-toggle-string-quotes) map) "Keymap used in Ruby mode.") @@ -164,6 +165,8 @@ This should only be called after matching against `ruby-here-doc-beg-re'." ["End of Block" ruby-end-of-block t] ["Toggle Block" ruby-toggle-block t] "--" + ["Toggle String Quotes" ruby-toggle-string-quotes t] + "--" ["Backward Sexp" ruby-backward-sexp :visible (not ruby-use-smie)] ["Backward Sexp" backward-sexp @@ -749,7 +752,6 @@ It is used when `ruby-encoding-magic-comment-style' is set to `custom'." :forward-token #'ruby-smie--forward-token :backward-token #'ruby-smie--backward-token) (setq-local indent-line-function 'ruby-indent-line)) - (setq-local require-final-newline t) (setq-local comment-start "# ") (setq-local comment-end "") (setq-local comment-column ruby-comment-column) @@ -1764,6 +1766,43 @@ If the result is do-end block, it will always be multiline." (ruby-do-end-to-brace beg end))) (goto-char start)))) +(defun ruby--string-region () + "Return region for string at point." + (let ((state (syntax-ppss))) + (when (memq (nth 3 state) '(?' ?\")) + (save-excursion + (goto-char (nth 8 state)) + (forward-sexp) + (list (nth 8 state) (point)))))) + +(defun ruby-string-at-point-p () + "Check if cursor is at a string or not." + (ruby--string-region)) + +(defun ruby--inverse-string-quote (string-quote) + "Get the inverse string quoting for STRING-QUOTE." + (if (equal string-quote "\"") "'" "\"")) + +(defun ruby-toggle-string-quotes () + "Toggle string literal quoting between single and double." + (interactive) + (when (ruby-string-at-point-p) + (let* ((region (ruby--string-region)) + (min (nth 0 region)) + (max (nth 1 region)) + (string-quote (ruby--inverse-string-quote (buffer-substring-no-properties min (1+ min)))) + (content + (buffer-substring-no-properties (1+ min) (1- max)))) + (setq content + (if (equal string-quote "\"") + (replace-regexp-in-string "\\\\\"" "\"" (replace-regexp-in-string "\\([^\\\\]\\)'" "\\1\\\\'" content)) + (replace-regexp-in-string "\\\\\'" "'" (replace-regexp-in-string "\\([^\\\\]\\)\"" "\\1\\\\\"" content)))) + (let ((orig-point (point))) + (delete-region min max) + (insert + (format "%s%s%s" string-quote content string-quote)) + (goto-char orig-point))))) + (eval-and-compile (defconst ruby-percent-literal-beg-re "\\(%\\)[qQrswWxIi]?\\([[:punct:]]\\)" @@ -1804,14 +1843,16 @@ It will be properly highlighted even when the call omits parens.") ;; $' $" $` .... are variables. ;; ?' ?" ?` are character literals (one-char strings in 1.9+). ("\\([?$]\\)[#\"'`]" - (1 (unless (save-excursion - ;; Not within a string. - (nth 3 (syntax-ppss (match-beginning 0)))) + (1 (if (save-excursion + (nth 3 (syntax-ppss (match-beginning 0)))) + ;; Within a string, skip. + (goto-char (match-end 1)) (string-to-syntax "\\")))) ;; Part of symbol when at the end of a method name. ("[!?]" (0 (unless (save-excursion (or (nth 8 (syntax-ppss (match-beginning 0))) + (eq (char-before) ?:) (let (parse-sexp-lookup-properties) (zerop (skip-syntax-backward "w_"))) (memq (preceding-char) '(?@ ?$)))) @@ -2064,6 +2105,10 @@ See `font-lock-syntax-table'.") "include" "module_function" "prepend" + "private_class_method" + "private_constant" + "public_class_method" + "public_constant" "refine" "using") 'symbols)) @@ -2108,13 +2153,28 @@ See `font-lock-syntax-table'.") 1 font-lock-variable-name-face) ;; Keywords that evaluate to certain values. ("\\_<__\\(?:LINE\\|ENCODING\\|FILE\\)__\\_>" - (0 font-lock-variable-name-face)) + (0 font-lock-builtin-face)) ;; Symbols. ("\\(^\\|[^:]\\)\\(:\\([-+~]@?\\|[/%&|^`]\\|\\*\\*?\\|<\\(<\\|=>?\\)?\\|>[>=]?\\|===?\\|=~\\|![~=]?\\|\\[\\]=?\\|@?\\(\\w\\|_\\)+\\([!?=]\\|\\b_*\\)\\|#{[^}\n\\\\]*\\(\\\\.[^}\n\\\\]*\\)*}\\)\\)" 2 font-lock-constant-face) - ;; Variables. - ("\\(\\$\\([^a-zA-Z0-9 \n]\\|[0-9]\\)\\)\\W" - 1 font-lock-variable-name-face) + ;; Special globals. + (,(concat "\\$\\(?:[:\"!@;,/\\._><\\$?~=*&`'+0-9]\\|-[0adFiIlpvw]\\|" + (regexp-opt '("LOAD_PATH" "LOADED_FEATURES" "PROGRAM_NAME" + "ERROR_INFO" "ERROR_POSITION" + "FS" "FIELD_SEPARATOR" + "OFS" "OUTPUT_FIELD_SEPARATOR" + "RS" "INPUT_RECORD_SEPARATOR" + "ORS" "OUTPUT_RECORD_SEPARATOR" + "NR" "INPUT_LINE_NUMBER" + "LAST_READ_LINE" "DEFAULT_OUTPUT" "DEFAULT_INPUT" + "PID" "PROCESS_ID" "CHILD_STATUS" + "LAST_MATCH_INFO" "IGNORECASE" + "ARGV" "MATCH" "PREMATCH" "POSTMATCH" + "LAST_PAREN_MATCH" "stdin" "stdout" "stderr" + "DEBUG" "FILENAME" "VERBOSE" "SAFE" "CLASSPATH" + "JRUBY_VERSION" "JRUBY_REVISION" "ENV_JAVA")) + "\\_>\\)") + 0 font-lock-builtin-face) ("\\(\\$\\|@\\|@@\\)\\(\\w\\|_\\)+" 0 font-lock-variable-name-face) ;; Constants. @@ -2131,7 +2191,7 @@ See `font-lock-syntax-table'.") (ruby-match-expression-expansion 2 font-lock-variable-name-face t) ;; Negation char. - ("\\(?:^\\|[^[:alnum:]_]\\)\\(!+\\)[^=]" + ("\\(?:^\\|[^[:alnum:]_]\\)\\(!+\\)[^=~]" 1 font-lock-negation-char-face) ;; Character literals. ;; FIXME: Support longer escape sequences. @@ -2186,9 +2246,10 @@ See `font-lock-syntax-table'.") (add-to-list 'auto-mode-alist (cons (purecopy (concat "\\(?:\\." "rb\\|ru\\|rake\\|thor" - "\\|jbuilder\\|gemspec\\|podspec" + "\\|jbuilder\\|rabl\\|gemspec\\|podspec" "\\|/" "\\(?:Gem\\|Rake\\|Cap\\|Thor" + "\\|Puppet\\|Berks" "\\|Vagrant\\|Guard\\|Pod\\)file" "\\)\\'")) 'ruby-mode))