diff options
| author | Joakim Verona | 2012-09-10 16:03:53 +0200 |
|---|---|---|
| committer | Joakim Verona | 2012-09-10 16:03:53 +0200 |
| commit | b035a30e5cd2f34fedc04c253eeb5a11afed8145 (patch) | |
| tree | b9350cce389602f4967bdc1beed745929155ad5d /lisp/progmodes/ruby-mode.el | |
| parent | 4a37733c693d59a9b83a3fb2d0c7f9461d149f60 (diff) | |
| parent | a31a4cdacb196cc96dcb9bd229edb1d635e01344 (diff) | |
| download | emacs-b035a30e5cd2f34fedc04c253eeb5a11afed8145.tar.gz emacs-b035a30e5cd2f34fedc04c253eeb5a11afed8145.zip | |
upstream
Diffstat (limited to 'lisp/progmodes/ruby-mode.el')
| -rw-r--r-- | lisp/progmodes/ruby-mode.el | 173 |
1 files changed, 89 insertions, 84 deletions
diff --git a/lisp/progmodes/ruby-mode.el b/lisp/progmodes/ruby-mode.el index 457c7fee36c..77ec8084ea2 100644 --- a/lisp/progmodes/ruby-mode.el +++ b/lisp/progmodes/ruby-mode.el | |||
| @@ -64,8 +64,8 @@ | |||
| 64 | "Regexp to match keywords that nest without blocks.") | 64 | "Regexp to match keywords that nest without blocks.") |
| 65 | 65 | ||
| 66 | (defconst ruby-indent-beg-re | 66 | (defconst ruby-indent-beg-re |
| 67 | (concat "\\(\\s *" (regexp-opt '("class" "module" "def") t) "\\)\\|" | 67 | (concat "^\\s *" (regexp-opt '("class" "module" "def" "if" "unless" "case" |
| 68 | (regexp-opt '("if" "unless" "case" "while" "until" "for" "begin"))) | 68 | "while" "until" "for" "begin")) "\\_>") |
| 69 | "Regexp to match where the indentation gets deeper.") | 69 | "Regexp to match where the indentation gets deeper.") |
| 70 | 70 | ||
| 71 | (defconst ruby-modifier-beg-keywords | 71 | (defconst ruby-modifier-beg-keywords |
| @@ -98,6 +98,10 @@ | |||
| 98 | 98 | ||
| 99 | (defconst ruby-block-end-re "\\_<end\\_>") | 99 | (defconst ruby-block-end-re "\\_<end\\_>") |
| 100 | 100 | ||
| 101 | (defconst ruby-defun-beg-re | ||
| 102 | '"\\(def\\|class\\|module\\)" | ||
| 103 | "Regexp to match the beginning of a defun, in the general sense.") | ||
| 104 | |||
| 101 | (eval-and-compile | 105 | (eval-and-compile |
| 102 | (defconst ruby-here-doc-beg-re | 106 | (defconst ruby-here-doc-beg-re |
| 103 | "\\(<\\)<\\(-\\)?\\(\\([a-zA-Z0-9_]+\\)\\|[\"]\\([^\"]+\\)[\"]\\|[']\\([^']+\\)[']\\)" | 107 | "\\(<\\)<\\(-\\)?\\(\\([a-zA-Z0-9_]+\\)\\|[\"]\\([^\"]+\\)[\"]\\|[']\\([^']+\\)[']\\)" |
| @@ -138,18 +142,11 @@ This should only be called after matching against `ruby-here-doc-beg-re'." | |||
| 138 | 142 | ||
| 139 | (defvar ruby-mode-map | 143 | (defvar ruby-mode-map |
| 140 | (let ((map (make-sparse-keymap))) | 144 | (let ((map (make-sparse-keymap))) |
| 141 | (define-key map "{" 'ruby-electric-brace) | ||
| 142 | (define-key map "}" 'ruby-electric-brace) | ||
| 143 | (define-key map (kbd "M-C-a") 'ruby-beginning-of-defun) | ||
| 144 | (define-key map (kbd "M-C-e") 'ruby-end-of-defun) | ||
| 145 | (define-key map (kbd "M-C-b") 'ruby-backward-sexp) | 145 | (define-key map (kbd "M-C-b") 'ruby-backward-sexp) |
| 146 | (define-key map (kbd "M-C-f") 'ruby-forward-sexp) | 146 | (define-key map (kbd "M-C-f") 'ruby-forward-sexp) |
| 147 | (define-key map (kbd "M-C-p") 'ruby-beginning-of-block) | 147 | (define-key map (kbd "M-C-p") 'ruby-beginning-of-block) |
| 148 | (define-key map (kbd "M-C-n") 'ruby-end-of-block) | 148 | (define-key map (kbd "M-C-n") 'ruby-end-of-block) |
| 149 | (define-key map (kbd "M-C-h") 'ruby-mark-defun) | ||
| 150 | (define-key map (kbd "M-C-q") 'ruby-indent-exp) | 149 | (define-key map (kbd "M-C-q") 'ruby-indent-exp) |
| 151 | (define-key map (kbd "C-M-h") 'backward-kill-word) | ||
| 152 | (define-key map (kbd "C-j") 'reindent-then-newline-and-indent) | ||
| 153 | (define-key map (kbd "C-c {") 'ruby-toggle-block) | 150 | (define-key map (kbd "C-c {") 'ruby-toggle-block) |
| 154 | map) | 151 | map) |
| 155 | "Keymap used in Ruby mode.") | 152 | "Keymap used in Ruby mode.") |
| @@ -840,20 +837,13 @@ and `\\' when preceded by `?'." | |||
| 840 | (+ indent ruby-indent-level) | 837 | (+ indent ruby-indent-level) |
| 841 | indent)))) | 838 | indent)))) |
| 842 | 839 | ||
| 843 | (defun ruby-electric-brace (arg) | ||
| 844 | "Insert a brace and re-indent the current line." | ||
| 845 | (interactive "P") | ||
| 846 | (self-insert-command (prefix-numeric-value arg)) | ||
| 847 | (ruby-indent-line t)) | ||
| 848 | |||
| 849 | ;; TODO: Why isn't one ruby-*-of-defun written in terms of the other? | ||
| 850 | (defun ruby-beginning-of-defun (&optional arg) | 840 | (defun ruby-beginning-of-defun (&optional arg) |
| 851 | "Move backward to the beginning of the current top-level defun. | 841 | "Move backward to the beginning of the current top-level defun. |
| 852 | With ARG, move backward multiple defuns. Negative ARG means | 842 | With ARG, move backward multiple defuns. Negative ARG means |
| 853 | move forward." | 843 | move forward." |
| 854 | (interactive "p") | 844 | (interactive "p") |
| 855 | (and (re-search-backward (concat "^\\(" ruby-block-beg-re "\\)\\b") | 845 | (and (re-search-backward (concat "^\\s *" ruby-defun-beg-re "\\_>") |
| 856 | nil 'move (or arg 1)) | 846 | nil t (or arg 1)) |
| 857 | (beginning-of-line))) | 847 | (beginning-of-line))) |
| 858 | 848 | ||
| 859 | (defun ruby-end-of-defun (&optional arg) | 849 | (defun ruby-end-of-defun (&optional arg) |
| @@ -861,19 +851,18 @@ move forward." | |||
| 861 | With ARG, move forward multiple defuns. Negative ARG means | 851 | With ARG, move forward multiple defuns. Negative ARG means |
| 862 | move backward." | 852 | move backward." |
| 863 | (interactive "p") | 853 | (interactive "p") |
| 864 | (and (re-search-forward (concat "^\\(" ruby-block-end-re "\\)\\($\\|\\b[^_]\\)") | 854 | (ruby-forward-sexp) |
| 865 | nil 'move (or arg 1)) | 855 | (when (looking-back (concat "^\\s *" ruby-block-end-re)) |
| 866 | (beginning-of-line)) | 856 | (forward-line 1))) |
| 867 | (forward-line 1)) | ||
| 868 | 857 | ||
| 869 | (defun ruby-beginning-of-indent () | 858 | (defun ruby-beginning-of-indent () |
| 870 | "TODO: document" | 859 | "Backtrack to a line which can be used as a reference for |
| 871 | ;; I don't understand this function. | 860 | calculating indentation on the lines after it." |
| 872 | ;; It seems like it should move to the line where indentation should deepen, | 861 | (while (and (re-search-backward ruby-indent-beg-re nil 'move) |
| 873 | ;; but ruby-indent-beg-re only accounts for whitespace before class, module and def, | 862 | (if (ruby-in-ppss-context-p 'anything) |
| 874 | ;; so this will only match other block beginners at the beginning of the line. | 863 | t |
| 875 | (and (re-search-backward (concat "^\\(" ruby-indent-beg-re "\\)\\_>") nil 'move) | 864 | ;; We can stop, then. |
| 876 | (beginning-of-line))) | 865 | (beginning-of-line))))) |
| 877 | 866 | ||
| 878 | (defun ruby-move-to-block (n) | 867 | (defun ruby-move-to-block (n) |
| 879 | "Move to the beginning (N < 0) or the end (N > 0) of the current block | 868 | "Move to the beginning (N < 0) or the end (N > 0) of the current block |
| @@ -1024,15 +1013,6 @@ With ARG, do it many times. Negative ARG means move forward." | |||
| 1024 | ((error))) | 1013 | ((error))) |
| 1025 | i))) | 1014 | i))) |
| 1026 | 1015 | ||
| 1027 | (defun ruby-mark-defun () | ||
| 1028 | "Put mark at end of this Ruby function, point at beginning." | ||
| 1029 | (interactive) | ||
| 1030 | (push-mark (point)) | ||
| 1031 | (ruby-end-of-defun) | ||
| 1032 | (push-mark (point) nil t) | ||
| 1033 | (ruby-beginning-of-defun) | ||
| 1034 | (re-search-backward "^\n" (- (point) 1) t)) | ||
| 1035 | |||
| 1036 | (defun ruby-indent-exp (&optional ignored) | 1016 | (defun ruby-indent-exp (&optional ignored) |
| 1037 | "Indent each line in the balanced expression following the point." | 1017 | "Indent each line in the balanced expression following the point." |
| 1038 | (interactive "*P") | 1018 | (interactive "*P") |
| @@ -1073,7 +1053,7 @@ See `add-log-current-defun-function'." | |||
| 1073 | (let (mname mlist (indent 0)) | 1053 | (let (mname mlist (indent 0)) |
| 1074 | ;; get current method (or class/module) | 1054 | ;; get current method (or class/module) |
| 1075 | (if (re-search-backward | 1055 | (if (re-search-backward |
| 1076 | (concat "^[ \t]*\\(def\\|class\\|module\\)[ \t]+" | 1056 | (concat "^[ \t]*" ruby-defun-beg-re "[ \t]+" |
| 1077 | "\\(" | 1057 | "\\(" |
| 1078 | ;; \\. and :: for class method | 1058 | ;; \\. and :: for class method |
| 1079 | "\\([A-Za-z_]" ruby-symbol-re "*\\|\\.\\|::" "\\)" | 1059 | "\\([A-Za-z_]" ruby-symbol-re "*\\|\\.\\|::" "\\)" |
| @@ -1127,46 +1107,65 @@ See `add-log-current-defun-function'." | |||
| 1127 | (if mlist (concat mlist mname) mname) | 1107 | (if mlist (concat mlist mname) mname) |
| 1128 | mlist))))) | 1108 | mlist))))) |
| 1129 | 1109 | ||
| 1130 | (defun ruby-brace-to-do-end () | 1110 | (defun ruby-brace-to-do-end (orig end) |
| 1131 | (when (looking-at "{") | 1111 | (let (beg-marker end-marker) |
| 1132 | (let ((orig (point)) (end (progn (ruby-forward-sexp) (point)))) | 1112 | (goto-char end) |
| 1133 | (when (eq (char-before) ?\}) | 1113 | (when (eq (char-before) ?\}) |
| 1134 | (delete-char -1) | 1114 | (delete-char -1) |
| 1135 | (if (eq (char-syntax (char-before)) ?w) | 1115 | (skip-chars-backward " \t") |
| 1136 | (insert " ")) | 1116 | (when (not (bolp)) |
| 1137 | (insert "end") | 1117 | (insert "\n")) |
| 1138 | (if (eq (char-syntax (char-after)) ?w) | 1118 | (insert "end") |
| 1139 | (insert " ")) | 1119 | (setq end-marker (point-marker)) |
| 1140 | (goto-char orig) | 1120 | (when (and (not (eobp)) (eq (char-syntax (char-after)) ?w)) |
| 1141 | (delete-char 1) | 1121 | (insert " ")) |
| 1142 | (if (eq (char-syntax (char-before)) ?w) | 1122 | (goto-char orig) |
| 1143 | (insert " ")) | 1123 | (delete-char 1) |
| 1144 | (insert "do") | 1124 | (when (eq (char-syntax (char-before)) ?w) |
| 1145 | (when (looking-at "\\sw\\||") | 1125 | (insert " ")) |
| 1146 | (insert " ") | 1126 | (insert "do") |
| 1147 | (backward-char)) | 1127 | (setq beg-marker (point-marker)) |
| 1148 | t)))) | 1128 | (when (looking-at "\\(\\s \\)*|") |
| 1149 | 1129 | (unless (match-beginning 1) | |
| 1150 | (defun ruby-do-end-to-brace () | 1130 | (insert " ")) |
| 1151 | (when (and (or (bolp) | 1131 | (goto-char (1+ (match-end 0))) |
| 1152 | (not (memq (char-syntax (char-before)) '(?w ?_)))) | 1132 | (search-forward "|")) |
| 1153 | (looking-at "\\<do\\(\\s \\|$\\)")) | 1133 | (unless (looking-at "\\s *$") |
| 1154 | (let ((orig (point)) (end (progn (ruby-forward-sexp) (point)))) | 1134 | (insert "\n")) |
| 1155 | (backward-char 3) | 1135 | (indent-region beg-marker end-marker) |
| 1156 | (when (looking-at ruby-block-end-re) | 1136 | (goto-char beg-marker) |
| 1157 | (delete-char 3) | 1137 | t))) |
| 1158 | (insert "}") | 1138 | |
| 1159 | (goto-char orig) | 1139 | (defun ruby-do-end-to-brace (orig end) |
| 1160 | (delete-char 2) | 1140 | (goto-char (- end 3)) |
| 1161 | (insert "{") | 1141 | (when (looking-at ruby-block-end-re) |
| 1162 | (if (looking-at "\\s +|") | 1142 | (delete-char 3) |
| 1163 | (delete-char (- (match-end 0) (match-beginning 0) 1))) | 1143 | (insert "}") |
| 1164 | t)))) | 1144 | (goto-char orig) |
| 1145 | (delete-char 2) | ||
| 1146 | (insert "{") | ||
| 1147 | (if (looking-at "\\s +|") | ||
| 1148 | (delete-char (- (match-end 0) (match-beginning 0) 1))) | ||
| 1149 | t)) | ||
| 1165 | 1150 | ||
| 1166 | (defun ruby-toggle-block () | 1151 | (defun ruby-toggle-block () |
| 1152 | "Toggle block type from do-end to braces or back. | ||
| 1153 | The block must begin on the current line or above it and end after the point. | ||
| 1154 | If the result is do-end block, it will always be multiline." | ||
| 1167 | (interactive) | 1155 | (interactive) |
| 1168 | (or (ruby-brace-to-do-end) | 1156 | (let ((start (point)) beg end) |
| 1169 | (ruby-do-end-to-brace))) | 1157 | (end-of-line) |
| 1158 | (unless | ||
| 1159 | (if (and (re-search-backward "\\({\\)\\|\\_<do\\(\\s \\|$\\||\\)") | ||
| 1160 | (progn | ||
| 1161 | (setq beg (point)) | ||
| 1162 | (save-match-data (ruby-forward-sexp)) | ||
| 1163 | (setq end (point)) | ||
| 1164 | (> end start))) | ||
| 1165 | (if (match-beginning 1) | ||
| 1166 | (ruby-brace-to-do-end beg end) | ||
| 1167 | (ruby-do-end-to-brace beg end))) | ||
| 1168 | (goto-char start)))) | ||
| 1170 | 1169 | ||
| 1171 | (declare-function ruby-syntax-propertize-heredoc "ruby-mode" (limit)) | 1170 | (declare-function ruby-syntax-propertize-heredoc "ruby-mode" (limit)) |
| 1172 | (declare-function ruby-syntax-enclosing-percent-literal "ruby-mode" (limit)) | 1171 | (declare-function ruby-syntax-enclosing-percent-literal "ruby-mode" (limit)) |
| @@ -1193,8 +1192,6 @@ It will be properly highlighted even when the call omits parens.")) | |||
| 1193 | (ruby-syntax-enclosing-percent-literal end) | 1192 | (ruby-syntax-enclosing-percent-literal end) |
| 1194 | (funcall | 1193 | (funcall |
| 1195 | (syntax-propertize-rules | 1194 | (syntax-propertize-rules |
| 1196 | ;; #{ }, #$hoge, #@foo are not comments. | ||
| 1197 | ("\\(#\\)[{$@]" (1 ".")) | ||
| 1198 | ;; $' $" $` .... are variables. | 1195 | ;; $' $" $` .... are variables. |
| 1199 | ;; ?' ?" ?` are ascii codes. | 1196 | ;; ?' ?" ?` are ascii codes. |
| 1200 | ("\\([?$]\\)[#\"'`]" | 1197 | ("\\([?$]\\)[#\"'`]" |
| @@ -1326,8 +1323,7 @@ This should only be called after matching against `ruby-here-doc-end-re'." | |||
| 1326 | (concat "-?\\([\"']\\|\\)" contents "\\1")))))) | 1323 | (concat "-?\\([\"']\\|\\)" contents "\\1")))))) |
| 1327 | 1324 | ||
| 1328 | (defconst ruby-font-lock-syntactic-keywords | 1325 | (defconst ruby-font-lock-syntactic-keywords |
| 1329 | `( ;; #{ }, #$hoge, #@foo are not comments | 1326 | `( |
| 1330 | ("\\(#\\)[{$@]" 1 (1 . nil)) | ||
| 1331 | ;; the last $', $", $` in the respective string is not variable | 1327 | ;; the last $', $", $` in the respective string is not variable |
| 1332 | ;; the last ?', ?", ?` in the respective string is not ascii code | 1328 | ;; the last ?', ?", ?` in the respective string is not ascii code |
| 1333 | ("\\(^\\|[\[ \t\n<+\(,=]\\)\\(['\"`]\\)\\(\\\\.\\|\\2\\|[^'\"`\n\\\\]\\)*?\\\\?[?$]\\(\\2\\)" | 1329 | ("\\(^\\|[\[ \t\n<+\(,=]\\)\\(['\"`]\\)\\(\\\\.\\|\\2\\|[^'\"`\n\\\\]\\)*?\\\\?[?$]\\(\\2\\)" |
| @@ -1549,6 +1545,9 @@ See `font-lock-syntax-table'.") | |||
| 1549 | ;; variables | 1545 | ;; variables |
| 1550 | '("\\(^\\|[^_:.@$]\\|\\.\\.\\)\\b\\(nil\\|self\\|true\\|false\\)\\>" | 1546 | '("\\(^\\|[^_:.@$]\\|\\.\\.\\)\\b\\(nil\\|self\\|true\\|false\\)\\>" |
| 1551 | 2 font-lock-variable-name-face) | 1547 | 2 font-lock-variable-name-face) |
| 1548 | ;; symbols | ||
| 1549 | '("\\(^\\|[^:]\\)\\(:\\([-+~]@?\\|[/%&|^`]\\|\\*\\*?\\|<\\(<\\|=>?\\)?\\|>[>=]?\\|===?\\|=~\\|![~=]?\\|\\[\\]=?\\|@?\\(\\w\\|_\\)+\\([!?=]\\|\\b_*\\)\\|#{[^}\n\\\\]*\\(\\\\.[^}\n\\\\]*\\)*}\\)\\)" | ||
| 1550 | 2 font-lock-reference-face) | ||
| 1552 | ;; variables | 1551 | ;; variables |
| 1553 | '("\\(\\$\\([^a-zA-Z0-9 \n]\\|[0-9]\\)\\)\\W" | 1552 | '("\\(\\$\\([^a-zA-Z0-9 \n]\\|[0-9]\\)\\)\\W" |
| 1554 | 1 font-lock-variable-name-face) | 1553 | 1 font-lock-variable-name-face) |
| @@ -1557,12 +1556,9 @@ See `font-lock-syntax-table'.") | |||
| 1557 | ;; constants | 1556 | ;; constants |
| 1558 | '("\\(^\\|[^_]\\)\\b\\([A-Z]+\\(\\w\\|_\\)*\\)" | 1557 | '("\\(^\\|[^_]\\)\\b\\([A-Z]+\\(\\w\\|_\\)*\\)" |
| 1559 | 2 font-lock-type-face) | 1558 | 2 font-lock-type-face) |
| 1560 | ;; symbols | ||
| 1561 | '("\\(^\\|[^:]\\)\\(:\\([-+~]@?\\|[/%&|^`]\\|\\*\\*?\\|<\\(<\\|=>?\\)?\\|>[>=]?\\|===?\\|=~\\|![~=]?\\|\\[\\]=?\\|\\(\\w\\|_\\)+\\([!?=]\\|\\b_*\\)\\|#{[^}\n\\\\]*\\(\\\\.[^}\n\\\\]*\\)*}\\)\\)" | ||
| 1562 | 2 font-lock-reference-face) | ||
| 1563 | '("\\(^\\s *\\|[\[\{\(,]\\s *\\|\\sw\\s +\\)\\(\\(\\sw\\|_\\)+\\):[^:]" 2 font-lock-reference-face) | 1559 | '("\\(^\\s *\\|[\[\{\(,]\\s *\\|\\sw\\s +\\)\\(\\(\\sw\\|_\\)+\\):[^:]" 2 font-lock-reference-face) |
| 1564 | ;; expression expansion | 1560 | ;; expression expansion |
| 1565 | '("#\\({[^}\n\\\\]*\\(\\\\.[^}\n\\\\]*\\)*}\\|\\(\\$\\|@\\|@@\\)\\(\\w\\|_\\)+\\)" | 1561 | '(ruby-match-expression-expansion |
| 1566 | 0 font-lock-variable-name-face t) | 1562 | 0 font-lock-variable-name-face t) |
| 1567 | ;; warn lower camel case | 1563 | ;; warn lower camel case |
| 1568 | ;'("\\<[a-z]+[a-z0-9]*[A-Z][A-Za-z0-9]*\\([!?]?\\|\\>\\)" | 1564 | ;'("\\<[a-z]+[a-z0-9]*[A-Z][A-Za-z0-9]*\\([!?]?\\|\\>\\)" |
| @@ -1570,6 +1566,11 @@ See `font-lock-syntax-table'.") | |||
| 1570 | ) | 1566 | ) |
| 1571 | "Additional expressions to highlight in Ruby mode.") | 1567 | "Additional expressions to highlight in Ruby mode.") |
| 1572 | 1568 | ||
| 1569 | (defun ruby-match-expression-expansion (limit) | ||
| 1570 | (when (re-search-forward "[^\\]\\(\\\\\\\\\\)*\\(#\\({[^}\n\\\\]*\\(\\\\.[^}\n\\\\]*\\)*}\\|\\(\\$\\|@\\|@@\\)\\(\\w\\|_\\)+\\)\\)" limit 'move) | ||
| 1571 | (or (ruby-in-ppss-context-p 'string) | ||
| 1572 | (ruby-match-expression-expansion limit)))) | ||
| 1573 | |||
| 1573 | ;;;###autoload | 1574 | ;;;###autoload |
| 1574 | (define-derived-mode ruby-mode prog-mode "Ruby" | 1575 | (define-derived-mode ruby-mode prog-mode "Ruby" |
| 1575 | "Major mode for editing Ruby scripts. | 1576 | "Major mode for editing Ruby scripts. |
| @@ -1586,6 +1587,10 @@ The variable `ruby-indent-level' controls the amount of indentation. | |||
| 1586 | 'ruby-imenu-create-index) | 1587 | 'ruby-imenu-create-index) |
| 1587 | (set (make-local-variable 'add-log-current-defun-function) | 1588 | (set (make-local-variable 'add-log-current-defun-function) |
| 1588 | 'ruby-add-log-current-method) | 1589 | 'ruby-add-log-current-method) |
| 1590 | (set (make-local-variable 'beginning-of-defun-function) | ||
| 1591 | 'ruby-beginning-of-defun) | ||
| 1592 | (set (make-local-variable 'end-of-defun-function) | ||
| 1593 | 'ruby-end-of-defun) | ||
| 1589 | 1594 | ||
| 1590 | (add-hook | 1595 | (add-hook |
| 1591 | (cond ((boundp 'before-save-hook) 'before-save-hook) | 1596 | (cond ((boundp 'before-save-hook) 'before-save-hook) |