diff options
Diffstat (limited to 'lisp/progmodes/ruby-mode.el')
-rw-r--r-- | lisp/progmodes/ruby-mode.el | 215 |
1 files changed, 103 insertions, 112 deletions
diff --git a/lisp/progmodes/ruby-mode.el b/lisp/progmodes/ruby-mode.el index 534eeb16a67..999fbebfb08 100644 --- a/lisp/progmodes/ruby-mode.el +++ b/lisp/progmodes/ruby-mode.el @@ -516,7 +516,9 @@ 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) + :type '(choice (const :tag "Don't insert" nil) + (const :tag "Insert utf-8 comment always" always-utf8) + (const :tag "Insert only when required" t))) (defcustom ruby-encoding-magic-comment-style 'ruby "The style of the magic encoding comment to use." @@ -1850,93 +1852,92 @@ For example: File.open See `add-log-current-defun-function'." - (condition-case nil - (save-excursion - (let* ((indent (ruby--add-log-current-indent)) - mname mlist - (start (point)) - (make-definition-re - (lambda (re &optional method-name?) - (concat "^[ \t]*" re "[ \t]+" - "\\(" - ;; \\. and :: for class methods - "\\([A-Za-z_]" ruby-symbol-re "*[?!]?" - "\\|" - (if method-name? ruby-operator-re "\\.") - "\\|::" "\\)" - "+\\)"))) - (definition-re (funcall make-definition-re ruby-defun-beg-re t)) - (module-re (funcall make-definition-re "\\(class\\|module\\)"))) - ;; Get the current method definition (or class/module). - (when (catch 'found - (while (and (re-search-backward definition-re nil t) - (if (if (string-equal "def" (match-string 1)) - ;; We're inside a method. - (if (ruby-block-contains-point (1- start)) - t - ;; Try to match a method only once. - (setq definition-re module-re) - nil) - ;; Class/module. For performance, - ;; comparing indentation. - (or (not (numberp indent)) - (> indent (current-indentation)))) - (throw 'found t) - t)))) - (goto-char (match-beginning 1)) - (if (not (string-equal "def" (match-string 1))) - (setq mlist (list (match-string 2))) - (setq mname (match-string 2))) - (setq indent (current-column)) - (beginning-of-line)) - ;; Walk up the class/module nesting. - (while (and indent - (> indent 0) - (re-search-backward module-re nil t)) - (goto-char (match-beginning 1)) - (when (< (current-column) indent) - (setq mlist (cons (match-string 2) mlist)) - (setq indent (current-column)) - (beginning-of-line))) - ;; Process the method name. - (when mname - (let ((mn (split-string mname "\\.\\|::"))) - (if (cdr mn) - (progn - (unless (string-equal "self" (car mn)) ; def self.foo - ;; def C.foo - (let ((ml (reverse mlist))) - ;; If the method name references one of the - ;; containing modules, drop the more nested ones. - (while ml - (if (string-equal (car ml) (car mn)) - (setq mlist (nreverse (cdr ml)) ml nil)) - (setq ml (cdr ml)))) - (if mlist - (setcdr (last mlist) (butlast mn)) - (setq mlist (butlast mn)))) - (setq mname (concat "." (car (last mn))))) - ;; See if the method is in singleton class context. - (let ((in-singleton-class - (when (re-search-forward ruby-singleton-class-re start t) - (goto-char (match-beginning 0)) - ;; FIXME: Optimize it out, too? - ;; This can be slow in a large file, but - ;; unlike class/module declaration - ;; indentations, method definitions can be - ;; intermixed with these, and may or may not - ;; be additionally indented after visibility - ;; keywords. - (ruby-block-contains-point start)))) - (setq mname (concat - (if in-singleton-class "." "#") - mname)))))) - ;; Generate the string. - (if (consp mlist) - (setq mlist (mapconcat (function identity) mlist "::"))) - (if mname - (if mlist (concat mlist mname) mname) - mlist))))) + (save-excursion + (let* ((indent (ruby--add-log-current-indent)) + mname mlist + (start (point)) + (make-definition-re + (lambda (re &optional method-name?) + (concat "^[ \t]*" re "[ \t]+" + "\\(" + ;; \\. and :: for class methods + "\\([A-Za-z_]" ruby-symbol-re "*[?!]?" + "\\|" + (if method-name? ruby-operator-re "\\.") + "\\|::" "\\)" + "+\\)"))) + (definition-re (funcall make-definition-re ruby-defun-beg-re t)) + (module-re (funcall make-definition-re "\\(class\\|module\\)"))) + ;; Get the current method definition (or class/module). + (when (catch 'found + (while (and (re-search-backward definition-re nil t) + (if (if (string-equal "def" (match-string 1)) + ;; We're inside a method. + (if (ruby-block-contains-point (1- start)) + t + ;; Try to match a method only once. + (setq definition-re module-re) + nil) + ;; Class/module. For performance, + ;; comparing indentation. + (or (not (numberp indent)) + (> indent (current-indentation)))) + (throw 'found t) + t)))) + (goto-char (match-beginning 1)) + (if (not (string-equal "def" (match-string 1))) + (setq mlist (list (match-string 2))) + (setq mname (match-string 2))) + (setq indent (current-column)) + (beginning-of-line)) + ;; Walk up the class/module nesting. + (while (and indent + (> indent 0) + (re-search-backward module-re nil t)) + (goto-char (match-beginning 1)) + (when (< (current-column) indent) + (setq mlist (cons (match-string 2) mlist)) + (setq indent (current-column)) + (beginning-of-line))) + ;; Process the method name. + (when mname + (let ((mn (split-string mname "\\.\\|::"))) + (if (cdr mn) + (progn + (unless (string-equal "self" (car mn)) ; def self.foo + ;; def C.foo + (let ((ml (reverse mlist))) + ;; If the method name references one of the + ;; containing modules, drop the more nested ones. + (while ml + (if (string-equal (car ml) (car mn)) + (setq mlist (nreverse (cdr ml)) ml nil)) + (setq ml (cdr ml)))) + (if mlist + (setcdr (last mlist) (butlast mn)) + (setq mlist (butlast mn)))) + (setq mname (concat "." (car (last mn))))) + ;; See if the method is in singleton class context. + (let ((in-singleton-class + (when (re-search-forward ruby-singleton-class-re start t) + (goto-char (match-beginning 0)) + ;; FIXME: Optimize it out, too? + ;; This can be slow in a large file, but + ;; unlike class/module declaration + ;; indentations, method definitions can be + ;; intermixed with these, and may or may not + ;; be additionally indented after visibility + ;; keywords. + (ruby-block-contains-point start)))) + (setq mname (concat + (if in-singleton-class "." "#") + mname)))))) + ;; Generate the string. + (if (consp mlist) + (setq mlist (mapconcat (function identity) mlist "::"))) + (if mname + (if mlist (concat mlist mname) mname) + mlist)))) (defun ruby-block-contains-point (pt) (save-excursion @@ -2105,12 +2106,6 @@ or `gem' statement around point." "\\(%\\)[qQrswWxIi]?\\([[:punct:]]\\)" "Regexp to match the beginning of percent literal.") - (defconst ruby-syntax-methods-before-regexp - '("gsub" "gsub!" "sub" "sub!" "scan" "split" "split!" "index" "match" - "assert_match" "Given" "Then" "When") - "Methods that can take regexp as the first argument. -It will be properly highlighted even when the call omits parens.") - (defvar ruby-syntax-before-regexp-re (concat ;; Special tokens that can't be followed by a division operator. @@ -2122,11 +2117,9 @@ It will be properly highlighted even when the call omits parens.") "\\|\\(?:^\\|\\s \\)" (regexp-opt '("if" "elsif" "unless" "while" "until" "when" "and" "or" "not" "&&" "||")) - ;; Method name from the list. - "\\|\\_<" - (regexp-opt ruby-syntax-methods-before-regexp t) "\\)\\s *") - "Regexp to match text that can be followed by a regular expression.")) + "Regexp to match text that disambiguates a regular expression. +A slash character after any of these should begin a regexp.")) (defun ruby-syntax-propertize (start end) "Syntactic keywords for Ruby mode. See `syntax-propertize-function'." @@ -2182,20 +2175,18 @@ It will be properly highlighted even when the call omits parens.") (when (save-excursion (forward-char -1) (cl-evenp (skip-chars-backward "\\\\"))) - (let ((state (save-excursion (syntax-ppss (match-beginning 1)))) - division-like) + (let ((state (save-excursion (syntax-ppss (match-beginning 1))))) (when (or ;; Beginning of a regexp. (and (null (nth 8 state)) - (save-excursion - (setq division-like - (or (eql (char-after) ?\s) - (not (eql (char-before (1- (point))) ?\s)))) - (forward-char -1) - (looking-back ruby-syntax-before-regexp-re - (line-beginning-position))) - (not (and division-like - (match-beginning 2)))) + (or (not + ;; Looks like division. + (or (eql (char-after) ?\s) + (not (eql (char-before (1- (point))) ?\s)))) + (save-excursion + (forward-char -1) + (looking-back ruby-syntax-before-regexp-re + (line-beginning-position))))) ;; End of regexp. We don't match the whole ;; regexp at once because it can have ;; string interpolation inside, or span @@ -2704,18 +2695,18 @@ Currently there are `ruby-mode' and `ruby-ts-mode'." ;;;###autoload (add-to-list 'auto-mode-alist (cons (purecopy (concat "\\(?:\\.\\(?:" - "rbw?\\|ru\\|rake\\|thor" + "rbw?\\|ru\\|rake\\|thor\\|axlsx" "\\|jbuilder\\|rabl\\|gemspec\\|podspec" "\\)" "\\|/" "\\(?:Gem\\|Rake\\|Cap\\|Thor" - "\\|Puppet\\|Berks\\|Brew" + "\\|Puppet\\|Berks\\|Brew\\|Fast" "\\|Vagrant\\|Guard\\|Pod\\)file" "\\)\\'")) 'ruby-mode)) ;;;###autoload -(dolist (name (list "ruby" "rbx" "jruby" "ruby1.9" "ruby1.8")) +(dolist (name (list "ruby" "rbx" "jruby" "j?ruby\\(?:[0-9.]+\\)")) (add-to-list 'interpreter-mode-alist (cons (purecopy name) 'ruby-mode))) (provide 'ruby-mode) |