ruby_learner 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (188) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +11 -0
  3. data/.rspec +3 -0
  4. data/.travis.yml +5 -0
  5. data/CODE_OF_CONDUCT.md +74 -0
  6. data/Gemfile +6 -0
  7. data/Gemfile.lock +58 -0
  8. data/LICENSE.txt +21 -0
  9. data/README.md +65 -0
  10. data/Rakefile +6 -0
  11. data/bin/console +14 -0
  12. data/bin/new_terminal +25 -0
  13. data/bin/setup +8 -0
  14. data/docs/happy_ruby/RussOlsen_EloquentRuby_c1.pdf +0 -0
  15. data/docs/happy_ruby/RussOlsen_EloquentRuby_c5.pdf +0 -0
  16. data/docs/happy_ruby/TanoshiiRuby_v3_c23.pdf +0 -0
  17. data/docs/happy_ruby/TanoshiiRuby_v5_c1.pdf +0 -0
  18. data/docs/happy_ruby/TanoshiiRuby_v5_c2-3.pdf +0 -0
  19. data/docs/happy_ruby/c2.ipynb +479 -0
  20. data/docs/happy_ruby/c3_4.ipynb +237 -0
  21. data/docs/seminar/8-1.org +18 -0
  22. data/exe/ruby_learner +5 -0
  23. data/lib/ruby_learner/h.rb +14 -0
  24. data/lib/ruby_learner/methods.rb +131 -0
  25. data/lib/ruby_learner/random_h.rb +16 -0
  26. data/lib/ruby_learner/ruby_learner.rb +43 -0
  27. data/lib/ruby_learner/sequential_h.rb +15 -0
  28. data/lib/ruby_learner/typing_practice.rb +21 -0
  29. data/lib/ruby_learner/version.rb +3 -0
  30. data/questions/random_check/.rspec +1 -0
  31. data/questions/random_check/random_h.rb +16 -0
  32. data/questions/random_check/section_1/.rspec +1 -0
  33. data/questions/random_check/section_1/lib/answer.rb +15 -0
  34. data/questions/random_check/section_1/lib/sentence.org +9 -0
  35. data/questions/random_check/section_1/lib/workplace.rb +5 -0
  36. data/questions/random_check/section_1/spec/spec_helper.rb +100 -0
  37. data/questions/random_check/section_1/spec/workplace_spec.rb +10 -0
  38. data/questions/random_check/section_2/.rspec +1 -0
  39. data/questions/random_check/section_2/lib/answer.rb +17 -0
  40. data/questions/random_check/section_2/lib/sentence.org +12 -0
  41. data/questions/random_check/section_2/lib/workplace.rb +5 -0
  42. data/questions/random_check/section_2/spec/.rspec +1 -0
  43. data/questions/random_check/section_2/spec/spec_helper.rb +100 -0
  44. data/questions/random_check/section_2/spec/workplace_spec.rb +11 -0
  45. data/questions/sequential_check/section_1/part_1/lib/answer.rb +9 -0
  46. data/questions/sequential_check/section_1/part_1/lib/sentence.org +9 -0
  47. data/questions/sequential_check/section_1/part_1/lib/workplace.rb +5 -0
  48. data/questions/sequential_check/section_1/part_1/spec/spec_helper.rb +100 -0
  49. data/questions/sequential_check/section_1/part_1/spec/workplace_spec.rb +10 -0
  50. data/questions/sequential_check/section_1/part_2/lib/answer.rb +16 -0
  51. data/questions/sequential_check/section_1/part_2/lib/sentence.org +12 -0
  52. data/questions/sequential_check/section_1/part_2/lib/workplace.rb +5 -0
  53. data/questions/sequential_check/section_1/part_2/spec/.rspec +1 -0
  54. data/questions/sequential_check/section_1/part_2/spec/spec_helper.rb +100 -0
  55. data/questions/sequential_check/section_1/part_2/spec/workplace_spec.rb +11 -0
  56. data/ruby_learner.gemspec +41 -0
  57. data/takahashi/docs/README.org +139 -0
  58. data/takahashi/docs/drill.html +875 -0
  59. data/takahashi/docs/drill.html~ +877 -0
  60. data/takahashi/docs/drill.org +446 -0
  61. data/takahashi/docs/ruby_for_beginner.html +2642 -0
  62. data/takahashi/docs/ruby_for_beginner.org +1430 -0
  63. data/takahashi/sample_prog/answer/10_1.rb +5 -0
  64. data/takahashi/sample_prog/answer/11_1.rb +5 -0
  65. data/takahashi/sample_prog/answer/11_2.rb +4 -0
  66. data/takahashi/sample_prog/answer/1_1.rb +1 -0
  67. data/takahashi/sample_prog/answer/1_2.rb +1 -0
  68. data/takahashi/sample_prog/answer/1_3.rb +1 -0
  69. data/takahashi/sample_prog/answer/2_1.rb +5 -0
  70. data/takahashi/sample_prog/answer/2_2.rb +12 -0
  71. data/takahashi/sample_prog/answer/3_1.rb +10 -0
  72. data/takahashi/sample_prog/answer/4_1.rb +7 -0
  73. data/takahashi/sample_prog/answer/5_1.rb +6 -0
  74. data/takahashi/sample_prog/answer/5_2.rb +3 -0
  75. data/takahashi/sample_prog/answer/6_1.rb +3 -0
  76. data/takahashi/sample_prog/answer/6_2.rb +5 -0
  77. data/takahashi/sample_prog/answer/6_3.rb +5 -0
  78. data/takahashi/sample_prog/answer/6_4.rb +7 -0
  79. data/takahashi/sample_prog/answer/7_1.rb +3 -0
  80. data/takahashi/sample_prog/answer/7_2.rb +8 -0
  81. data/takahashi/sample_prog/answer/9_1.rb +3 -0
  82. data/takahashi/sample_prog/answer/9_2.rb +5 -0
  83. data/takahashi/sample_prog/answer/9_3.rb +10 -0
  84. data/takahashi/sample_prog/answer/hello.rb +3 -0
  85. data/workshop/.rspec +1 -0
  86. data/workshop/emacs.d/ac-comphist.dat +50 -0
  87. data/workshop/emacs.d/cp5022x.el +156 -0
  88. data/workshop/emacs.d/elpa/archives/gnu/archive-contents +1240 -0
  89. data/workshop/emacs.d/elpa/archives/melpa/archive-contents +2 -0
  90. data/workshop/emacs.d/elpa/auto-complete-20170124.1845/auto-complete-autoloads.el +65 -0
  91. data/workshop/emacs.d/elpa/auto-complete-20170124.1845/auto-complete-config.el +551 -0
  92. data/workshop/emacs.d/elpa/auto-complete-20170124.1845/auto-complete-config.elc +0 -0
  93. data/workshop/emacs.d/elpa/auto-complete-20170124.1845/auto-complete-pkg.el +6 -0
  94. data/workshop/emacs.d/elpa/auto-complete-20170124.1845/auto-complete.el +2164 -0
  95. data/workshop/emacs.d/elpa/auto-complete-20170124.1845/auto-complete.elc +0 -0
  96. data/workshop/emacs.d/elpa/auto-complete-20170124.1845/dict/ada-mode +72 -0
  97. data/workshop/emacs.d/elpa/auto-complete-20170124.1845/dict/c++-mode +99 -0
  98. data/workshop/emacs.d/elpa/auto-complete-20170124.1845/dict/c-mode +55 -0
  99. data/workshop/emacs.d/elpa/auto-complete-20170124.1845/dict/caml-mode +231 -0
  100. data/workshop/emacs.d/elpa/auto-complete-20170124.1845/dict/clojure-mode +580 -0
  101. data/workshop/emacs.d/elpa/auto-complete-20170124.1845/dict/clojurescript-mode +475 -0
  102. data/workshop/emacs.d/elpa/auto-complete-20170124.1845/dict/coq-mode +278 -0
  103. data/workshop/emacs.d/elpa/auto-complete-20170124.1845/dict/css-mode +874 -0
  104. data/workshop/emacs.d/elpa/auto-complete-20170124.1845/dict/erlang-mode +216 -0
  105. data/workshop/emacs.d/elpa/auto-complete-20170124.1845/dict/ess-julia-mode +37 -0
  106. data/workshop/emacs.d/elpa/auto-complete-20170124.1845/dict/go-mode +25 -0
  107. data/workshop/emacs.d/elpa/auto-complete-20170124.1845/dict/haskell-mode +679 -0
  108. data/workshop/emacs.d/elpa/auto-complete-20170124.1845/dict/java-mode +53 -0
  109. data/workshop/emacs.d/elpa/auto-complete-20170124.1845/dict/js-mode +148 -0
  110. data/workshop/emacs.d/elpa/auto-complete-20170124.1845/dict/julia-mode +37 -0
  111. data/workshop/emacs.d/elpa/auto-complete-20170124.1845/dict/lua-mode +21 -0
  112. data/workshop/emacs.d/elpa/auto-complete-20170124.1845/dict/nim-mode +70 -0
  113. data/workshop/emacs.d/elpa/auto-complete-20170124.1845/dict/objc-mode +161 -0
  114. data/workshop/emacs.d/elpa/auto-complete-20170124.1845/dict/octave-mode +46 -0
  115. data/workshop/emacs.d/elpa/auto-complete-20170124.1845/dict/php-mode +6144 -0
  116. data/workshop/emacs.d/elpa/auto-complete-20170124.1845/dict/python-mode +379 -0
  117. data/workshop/emacs.d/elpa/auto-complete-20170124.1845/dict/qml-mode +183 -0
  118. data/workshop/emacs.d/elpa/auto-complete-20170124.1845/dict/ruby-mode +181 -0
  119. data/workshop/emacs.d/elpa/auto-complete-20170124.1845/dict/scala-mode +1347 -0
  120. data/workshop/emacs.d/elpa/auto-complete-20170124.1845/dict/scheme-mode +216 -0
  121. data/workshop/emacs.d/elpa/auto-complete-20170124.1845/dict/sclang-mode +1481 -0
  122. data/workshop/emacs.d/elpa/auto-complete-20170124.1845/dict/sh-mode +182 -0
  123. data/workshop/emacs.d/elpa/auto-complete-20170124.1845/dict/swift-mode +87 -0
  124. data/workshop/emacs.d/elpa/auto-complete-20170124.1845/dict/tcl-mode +172 -0
  125. data/workshop/emacs.d/elpa/auto-complete-20170124.1845/dict/ts-mode +797 -0
  126. data/workshop/emacs.d/elpa/auto-complete-20170124.1845/dict/tuareg-mode +231 -0
  127. data/workshop/emacs.d/elpa/auto-complete-20170124.1845/dict/verilog-mode +313 -0
  128. data/workshop/emacs.d/elpa/better-defaults-20170613.2104/better-defaults-autoloads.el +16 -0
  129. data/workshop/emacs.d/elpa/better-defaults-20170613.2104/better-defaults-pkg.el +2 -0
  130. data/workshop/emacs.d/elpa/better-defaults-20170613.2104/better-defaults.el +90 -0
  131. data/workshop/emacs.d/elpa/better-defaults-20170613.2104/better-defaults.elc +0 -0
  132. data/workshop/emacs.d/elpa/haml-mode-20170923.2153/haml-mode-autoloads.el +26 -0
  133. data/workshop/emacs.d/elpa/haml-mode-20170923.2153/haml-mode-pkg.el +2 -0
  134. data/workshop/emacs.d/elpa/haml-mode-20170923.2153/haml-mode.el +877 -0
  135. data/workshop/emacs.d/elpa/haml-mode-20170923.2153/haml-mode.elc +0 -0
  136. data/workshop/emacs.d/elpa/haml-mode-readme.txt +8 -0
  137. data/workshop/emacs.d/elpa/material-theme-20171123.1040/material-light-theme.el +918 -0
  138. data/workshop/emacs.d/elpa/material-theme-20171123.1040/material-light-theme.elc +0 -0
  139. data/workshop/emacs.d/elpa/material-theme-20171123.1040/material-theme-autoloads.el +32 -0
  140. data/workshop/emacs.d/elpa/material-theme-20171123.1040/material-theme-pkg.el +8 -0
  141. data/workshop/emacs.d/elpa/material-theme-20171123.1040/material-theme.el +912 -0
  142. data/workshop/emacs.d/elpa/material-theme-20171123.1040/material-theme.elc +0 -0
  143. data/workshop/emacs.d/elpa/ox-bibtex-chinese-readme.txt +21 -0
  144. data/workshop/emacs.d/elpa/popup-20160709.729/popup-autoloads.el +15 -0
  145. data/workshop/emacs.d/elpa/popup-20160709.729/popup-pkg.el +2 -0
  146. data/workshop/emacs.d/elpa/popup-20160709.729/popup.el +1432 -0
  147. data/workshop/emacs.d/elpa/popup-20160709.729/popup.elc +0 -0
  148. data/workshop/emacs.d/elpa/yaml-mode-20180212.1556/yaml-mode-autoloads.el +33 -0
  149. data/workshop/emacs.d/elpa/yaml-mode-20180212.1556/yaml-mode-pkg.el +2 -0
  150. data/workshop/emacs.d/elpa/yaml-mode-20180212.1556/yaml-mode.el +470 -0
  151. data/workshop/emacs.d/elpa/yaml-mode-20180212.1556/yaml-mode.elc +0 -0
  152. data/workshop/emacs.d/elpa/yaml-mode-readme.txt +25 -0
  153. data/workshop/emacs.d/haml-mode-master/.gitignore +1 -0
  154. data/workshop/emacs.d/haml-mode-master/.mailmap +2 -0
  155. data/workshop/emacs.d/haml-mode-master/MIT-LICENSE +20 -0
  156. data/workshop/emacs.d/haml-mode-master/README.md +47 -0
  157. data/workshop/emacs.d/haml-mode-master/haml-mode.el +887 -0
  158. data/workshop/emacs.d/iceberg_theme.el +202 -0
  159. data/workshop/emacs.d/init-open-recentf.el +133 -0
  160. data/workshop/emacs.d/init.el +229 -0
  161. data/workshop/emacs.d/inits/line-num.el +264 -0
  162. data/workshop/emacs.d/install-elisp.el +366 -0
  163. data/workshop/emacs.d/markdown-mode/markdown-mode.el +5978 -0
  164. data/workshop/emacs.d/notes +12 -0
  165. data/workshop/emacs.d/processing-mode/processing-mode.el +275 -0
  166. data/workshop/emacs.d/recentf +31 -0
  167. data/workshop/emacs.d/ruby-mode/inf-ruby.el +416 -0
  168. data/workshop/emacs.d/ruby-mode/rdoc-mode.el +130 -0
  169. data/workshop/emacs.d/ruby-mode/ruby-electric.el +205 -0
  170. data/workshop/emacs.d/ruby-mode/ruby-mode.el +1496 -0
  171. data/workshop/emacs.d/ruby-mode/ruby-style.el +78 -0
  172. data/workshop/emacs.d/ruby-mode/rubydb2x.el +104 -0
  173. data/workshop/emacs.d/ruby-mode/rubydb3x.el +115 -0
  174. data/workshop/emacs.d/ruby_learner_init.el +244 -0
  175. data/workshop/emacs.d/themes/dracula-theme.el +431 -0
  176. data/workshop/emacs.d/themes/iceberg-theme.el +205 -0
  177. data/workshop/emacs.d/themes/my-misterioso-theme.el +109 -0
  178. data/workshop/emacs.d/themes/my-wombat-theme.el +121 -0
  179. data/workshop/emacs.d/wiki-mode/wiki.el +976 -0
  180. data/workshop/emacs_help.org +34 -0
  181. data/workshop/lib/answer.rb +1 -0
  182. data/workshop/lib/sentence.org +1 -0
  183. data/workshop/lib/workplace.rb +1 -0
  184. data/workshop/restore/empty.rb +0 -0
  185. data/workshop/spec/spec_helper.rb +100 -0
  186. data/workshop/spec/workplace_spec.rb +1 -0
  187. data/workshop/training_data.txt +3 -0
  188. metadata +343 -0
@@ -0,0 +1,1496 @@
1
+ ;;; ruby-mode.el --- Major mode for editing Ruby files
2
+
3
+ ;; Copyright (C) 1994, 1995, 1996 1997, 1998, 1999, 2000, 2001,
4
+ ;; 2002,2003, 2004, 2005, 2006, 2007, 2008
5
+ ;; Free Software Foundation, Inc.
6
+
7
+ ;; Authors: Yukihiro Matsumoto, Nobuyoshi Nakada
8
+ ;; URL: http://www.emacswiki.org/cgi-bin/wiki/RubyMode
9
+ ;; Created: Fri Feb 4 14:49:13 JST 1994
10
+ ;; Keywords: languages ruby
11
+ ;; Version: 0.9
12
+
13
+ ;; This file is not part of GNU Emacs. However, a newer version of
14
+ ;; ruby-mode is included in recent releases of GNU Emacs (version 23
15
+ ;; and up), but the new version is not guaranteed to be compatible
16
+ ;; with older versions of Emacs or XEmacs. This file is the last
17
+ ;; version that aims to keep this compatibility.
18
+
19
+ ;; You can also get the latest version from the Emacs Lisp Package
20
+ ;; Archive: http://tromey.com/elpa
21
+
22
+ ;; This file is free software: you can redistribute it and/or modify
23
+ ;; it under the terms of the GNU General Public License as published by
24
+ ;; the Free Software Foundation, either version 3 of the License, or
25
+ ;; (at your option) any later version.
26
+
27
+ ;; It is distributed in the hope that it will be useful, but WITHOUT
28
+ ;; ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
29
+ ;; or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
30
+ ;; License for more details.
31
+
32
+ ;; You should have received a copy of the GNU General Public License
33
+ ;; along with it. If not, see <http://www.gnu.org/licenses/>.
34
+
35
+ ;;; Commentary:
36
+
37
+ ;; Provides font-locking, indentation support, and navigation for Ruby code.
38
+ ;;
39
+ ;; If you're installing manually, you should add this to your .emacs
40
+ ;; file after putting it on your load path:
41
+ ;;
42
+ ;; (autoload 'ruby-mode "ruby-mode" "Major mode for ruby files" t)
43
+ ;; (add-to-list 'auto-mode-alist '("\\.rb$" . ruby-mode))
44
+ ;; (add-to-list 'interpreter-mode-alist '("ruby" . ruby-mode))
45
+ ;;
46
+
47
+ ;;; Code:
48
+
49
+ (defconst ruby-mode-revision "$Revision: 33278 $"
50
+ "Ruby mode revision string.")
51
+
52
+ (defconst ruby-mode-version
53
+ (and (string-match "[0-9.]+" ruby-mode-revision)
54
+ (substring ruby-mode-revision (match-beginning 0) (match-end 0)))
55
+ "Ruby mode version number.")
56
+
57
+ (defconst ruby-keyword-end-re
58
+ (if (string-match "\\_>" "ruby")
59
+ "\\_>"
60
+ "\\>"))
61
+
62
+ (defconst ruby-block-beg-keywords
63
+ '("class" "module" "def" "if" "unless" "case" "while" "until" "for" "begin" "do")
64
+ "Keywords at the beginning of blocks.")
65
+
66
+ (defconst ruby-block-beg-re
67
+ (regexp-opt ruby-block-beg-keywords)
68
+ "Regexp to match the beginning of blocks.")
69
+
70
+ (defconst ruby-non-block-do-re
71
+ (concat (regexp-opt '("while" "until" "for" "rescue") t) ruby-keyword-end-re)
72
+ "Regexp to match")
73
+
74
+ (defconst ruby-indent-beg-re
75
+ (concat "\\(\\s *" (regexp-opt '("class" "module" "def") t) "\\)\\|"
76
+ (regexp-opt '("if" "unless" "case" "while" "until" "for" "begin")))
77
+ "Regexp to match where the indentation gets deeper.")
78
+
79
+ (defconst ruby-modifier-beg-keywords
80
+ '("if" "unless" "while" "until")
81
+ "Modifiers that are the same as the beginning of blocks.")
82
+
83
+ (defconst ruby-modifier-beg-re
84
+ (regexp-opt ruby-modifier-beg-keywords)
85
+ "Regexp to match modifiers same as the beginning of blocks.")
86
+
87
+ (defconst ruby-modifier-re
88
+ (regexp-opt (cons "rescue" ruby-modifier-beg-keywords))
89
+ "Regexp to match modifiers.")
90
+
91
+ (defconst ruby-block-mid-keywords
92
+ '("then" "else" "elsif" "when" "rescue" "ensure")
93
+ "Keywords where the indentation gets shallower in middle of block statements.")
94
+
95
+ (defconst ruby-block-mid-re
96
+ (regexp-opt ruby-block-mid-keywords)
97
+ "Regexp to match where the indentation gets shallower in middle of block statements.")
98
+
99
+ (defconst ruby-block-op-keywords
100
+ '("and" "or" "not")
101
+ "Block operators.")
102
+
103
+ (defconst ruby-block-hanging-re
104
+ (regexp-opt (append ruby-modifier-beg-keywords ruby-block-op-keywords))
105
+ "Regexp to match hanging block modifiers.")
106
+
107
+ (defconst ruby-block-end-re "\\<end\\>")
108
+
109
+ (defconst ruby-here-doc-beg-re
110
+ "\\(<\\)<\\(-\\)?\\(\\([a-zA-Z0-9_]+\\)\\|[\"]\\([^\"]+\\)[\"]\\|[']\\([^']+\\)[']\\)")
111
+
112
+ (defconst ruby-here-doc-end-re
113
+ "^\\([ \t]+\\)?\\(.*\\)\\(.\\)$")
114
+
115
+ (defun ruby-here-doc-end-match ()
116
+ (concat "^"
117
+ (if (match-string 2) "[ \t]*" nil)
118
+ (regexp-quote
119
+ (or (match-string 4)
120
+ (match-string 5)
121
+ (match-string 6)))))
122
+
123
+ (defun ruby-here-doc-beg-match ()
124
+ (let ((contents (concat
125
+ (regexp-quote (concat (match-string 2) (match-string 3)))
126
+ (if (string= (match-string 3) "_") "\\B" "\\b"))))
127
+ (concat "<<"
128
+ (let ((match (match-string 1)))
129
+ (if (and match (> (length match) 0))
130
+ (concat "\\(?:-\\([\"']?\\)\\|\\([\"']\\)" (match-string 1) "\\)"
131
+ contents "\\(\\1\\|\\2\\)")
132
+ (concat "-?\\([\"']\\|\\)" contents "\\1"))))))
133
+
134
+ (defconst ruby-delimiter
135
+ (concat "[?$/%(){}#\"'`.:]\\|<<\\|\\[\\|\\]\\|\\<\\("
136
+ ruby-block-beg-re
137
+ "\\)\\>\\|" ruby-block-end-re
138
+ "\\|^=begin\\|" ruby-here-doc-beg-re)
139
+ )
140
+
141
+ (defconst ruby-negative
142
+ (concat "^[ \t]*\\(\\(" ruby-block-mid-re "\\)\\>\\|"
143
+ ruby-block-end-re "\\|}\\|\\]\\)")
144
+ "Regexp to match where the indentation gets shallower.")
145
+
146
+ (defconst ruby-operator-chars "-,.+*/%&|^~=<>:")
147
+ (defconst ruby-operator-re (concat "[" ruby-operator-chars "]"))
148
+
149
+ (defconst ruby-symbol-chars "a-zA-Z0-9_")
150
+ (defconst ruby-symbol-re (concat "[" ruby-symbol-chars "]"))
151
+
152
+ (defvar ruby-mode-abbrev-table nil
153
+ "Abbrev table in use in ruby-mode buffers.")
154
+
155
+ (define-abbrev-table 'ruby-mode-abbrev-table ())
156
+
157
+ (defvar ruby-mode-map nil "Keymap used in ruby mode.")
158
+
159
+ (if ruby-mode-map
160
+ nil
161
+ (setq ruby-mode-map (make-sparse-keymap))
162
+ (define-key ruby-mode-map "{" 'ruby-electric-brace)
163
+ (define-key ruby-mode-map "}" 'ruby-electric-brace)
164
+ (define-key ruby-mode-map "\e\C-a" 'ruby-beginning-of-defun)
165
+ (define-key ruby-mode-map "\e\C-e" 'ruby-end-of-defun)
166
+ (define-key ruby-mode-map "\e\C-b" 'ruby-backward-sexp)
167
+ (define-key ruby-mode-map "\e\C-f" 'ruby-forward-sexp)
168
+ (define-key ruby-mode-map "\e\C-p" 'ruby-beginning-of-block)
169
+ (define-key ruby-mode-map "\e\C-n" 'ruby-end-of-block)
170
+ (define-key ruby-mode-map "\e\C-h" 'ruby-mark-defun)
171
+ (define-key ruby-mode-map "\e\C-q" 'ruby-indent-exp)
172
+ (define-key ruby-mode-map "\t" 'ruby-indent-command)
173
+ (define-key ruby-mode-map "\C-c\C-e" 'ruby-insert-end)
174
+ (define-key ruby-mode-map "\C-j" 'ruby-reindent-then-newline-and-indent)
175
+ (define-key ruby-mode-map "\C-c{" 'ruby-toggle-block)
176
+ (define-key ruby-mode-map "\C-c\C-u" 'uncomment-region))
177
+
178
+ (defvar ruby-mode-syntax-table nil
179
+ "Syntax table in use in ruby-mode buffers.")
180
+
181
+ (if ruby-mode-syntax-table
182
+ ()
183
+ (setq ruby-mode-syntax-table (make-syntax-table))
184
+ (modify-syntax-entry ?\' "\"" ruby-mode-syntax-table)
185
+ (modify-syntax-entry ?\" "\"" ruby-mode-syntax-table)
186
+ (modify-syntax-entry ?\` "\"" ruby-mode-syntax-table)
187
+ (modify-syntax-entry ?# "<" ruby-mode-syntax-table)
188
+ (modify-syntax-entry ?\n ">" ruby-mode-syntax-table)
189
+ (modify-syntax-entry ?\\ "\\" ruby-mode-syntax-table)
190
+ (modify-syntax-entry ?$ "." ruby-mode-syntax-table)
191
+ (modify-syntax-entry ?? "_" ruby-mode-syntax-table)
192
+ (modify-syntax-entry ?_ "_" ruby-mode-syntax-table)
193
+ (modify-syntax-entry ?< "." ruby-mode-syntax-table)
194
+ (modify-syntax-entry ?> "." ruby-mode-syntax-table)
195
+ (modify-syntax-entry ?& "." ruby-mode-syntax-table)
196
+ (modify-syntax-entry ?| "." ruby-mode-syntax-table)
197
+ (modify-syntax-entry ?% "." ruby-mode-syntax-table)
198
+ (modify-syntax-entry ?= "." ruby-mode-syntax-table)
199
+ (modify-syntax-entry ?/ "." ruby-mode-syntax-table)
200
+ (modify-syntax-entry ?+ "." ruby-mode-syntax-table)
201
+ (modify-syntax-entry ?* "." ruby-mode-syntax-table)
202
+ (modify-syntax-entry ?- "." ruby-mode-syntax-table)
203
+ (modify-syntax-entry ?\; "." ruby-mode-syntax-table)
204
+ (modify-syntax-entry ?\( "()" ruby-mode-syntax-table)
205
+ (modify-syntax-entry ?\) ")(" ruby-mode-syntax-table)
206
+ (modify-syntax-entry ?\{ "(}" ruby-mode-syntax-table)
207
+ (modify-syntax-entry ?\} "){" ruby-mode-syntax-table)
208
+ (modify-syntax-entry ?\[ "(]" ruby-mode-syntax-table)
209
+ (modify-syntax-entry ?\] ")[" ruby-mode-syntax-table)
210
+ )
211
+
212
+ (defcustom ruby-indent-tabs-mode nil
213
+ "*Indentation can insert tabs in ruby mode if this is non-nil."
214
+ :type 'boolean :group 'ruby)
215
+ (put 'ruby-indent-tabs-mode 'safe-local-variable 'booleanp)
216
+
217
+ (defcustom ruby-indent-level 2
218
+ "*Indentation of ruby statements."
219
+ :type 'integer :group 'ruby)
220
+ (put 'ruby-indent-level 'safe-local-variable 'integerp)
221
+
222
+ (defcustom ruby-comment-column 32
223
+ "*Indentation column of comments."
224
+ :type 'integer :group 'ruby)
225
+ (put 'ruby-comment-column 'safe-local-variable 'integerp)
226
+
227
+ (defcustom ruby-deep-arglist t
228
+ "*Deep indent lists in parenthesis when non-nil.
229
+ Also ignores spaces after parenthesis when 'space."
230
+ :group 'ruby)
231
+ (put 'ruby-deep-arglist 'safe-local-variable 'booleanp)
232
+
233
+ (defcustom ruby-deep-indent-paren '(?\( ?\[ ?\] t)
234
+ "*Deep indent lists in parenthesis when non-nil. t means continuous line.
235
+ Also ignores spaces after parenthesis when 'space."
236
+ :group 'ruby)
237
+
238
+ (defcustom ruby-deep-indent-paren-style 'space
239
+ "Default deep indent style."
240
+ :options '(t nil space) :group 'ruby)
241
+
242
+ (defcustom ruby-encoding-map '((shift_jis . cp932) (shift-jis . cp932))
243
+ "Alist to map encoding name from emacs to ruby."
244
+ :group 'ruby)
245
+
246
+ (defcustom ruby-use-encoding-map t
247
+ "*Use `ruby-encoding-map' to set encoding magic comment if this is non-nil."
248
+ :type 'boolean :group 'ruby)
249
+
250
+ (defvar ruby-indent-point nil "internal variable")
251
+
252
+ (eval-when-compile (require 'cl))
253
+ (defun ruby-imenu-create-index-in-block (prefix beg end)
254
+ (let ((index-alist '()) (case-fold-search nil)
255
+ name next pos decl sing)
256
+ (goto-char beg)
257
+ (while (re-search-forward "^\\s *\\(\\(class\\s +\\|\\(class\\s *<<\\s *\\)\\|module\\s +\\)\\([^\(<\n ]+\\)\\|\\(def\\|alias\\)\\s +\\([^\(\n ]+\\)\\)" end t)
258
+ (setq sing (match-beginning 3))
259
+ (setq decl (match-string 5))
260
+ (setq next (match-end 0))
261
+ (setq name (or (match-string 4) (match-string 6)))
262
+ (setq pos (match-beginning 0))
263
+ (cond
264
+ ((string= "alias" decl)
265
+ (if prefix (setq name (concat prefix name)))
266
+ (push (cons name pos) index-alist))
267
+ ((string= "def" decl)
268
+ (if prefix
269
+ (setq name
270
+ (cond
271
+ ((string-match "^self\." name)
272
+ (concat (substring prefix 0 -1) (substring name 4)))
273
+ (t (concat prefix name)))))
274
+ (push (cons name pos) index-alist)
275
+ (ruby-accurate-end-of-block end))
276
+ (t
277
+ (if (string= "self" name)
278
+ (if prefix (setq name (substring prefix 0 -1)))
279
+ (if prefix (setq name (concat (substring prefix 0 -1) "::" name)))
280
+ (push (cons name pos) index-alist))
281
+ (ruby-accurate-end-of-block end)
282
+ (setq beg (point))
283
+ (setq index-alist
284
+ (nconc (ruby-imenu-create-index-in-block
285
+ (concat name (if sing "." "#"))
286
+ next beg) index-alist))
287
+ (goto-char beg))))
288
+ index-alist))
289
+
290
+ (defun ruby-imenu-create-index ()
291
+ (nreverse (ruby-imenu-create-index-in-block nil (point-min) nil)))
292
+
293
+ (defun ruby-accurate-end-of-block (&optional end)
294
+ (let (state)
295
+ (or end (setq end (point-max)))
296
+ (while (and (setq state (apply 'ruby-parse-partial end state))
297
+ (>= (nth 2 state) 0) (< (point) end)))))
298
+
299
+ (defun ruby-mode-variables ()
300
+ (set-syntax-table ruby-mode-syntax-table)
301
+ (setq show-trailing-whitespace t)
302
+ (setq local-abbrev-table ruby-mode-abbrev-table)
303
+ (make-local-variable 'indent-line-function)
304
+ (setq indent-line-function 'ruby-indent-line)
305
+ (make-local-variable 'require-final-newline)
306
+ (setq require-final-newline t)
307
+ (make-local-variable 'comment-start)
308
+ (setq comment-start "# ")
309
+ (make-local-variable 'comment-end)
310
+ (setq comment-end "")
311
+ (make-local-variable 'comment-column)
312
+ (setq comment-column ruby-comment-column)
313
+ (make-local-variable 'comment-start-skip)
314
+ (setq comment-start-skip "#+ *")
315
+ (setq indent-tabs-mode ruby-indent-tabs-mode)
316
+ (make-local-variable 'parse-sexp-ignore-comments)
317
+ (setq parse-sexp-ignore-comments t)
318
+ (make-local-variable 'parse-sexp-lookup-properties)
319
+ (setq parse-sexp-lookup-properties t)
320
+ (make-local-variable 'paragraph-start)
321
+ (setq paragraph-start (concat "$\\|" page-delimiter))
322
+ (make-local-variable 'paragraph-separate)
323
+ (setq paragraph-separate paragraph-start)
324
+ (make-local-variable 'paragraph-ignore-fill-prefix)
325
+ (setq paragraph-ignore-fill-prefix t))
326
+
327
+ (defun ruby-mode-set-encoding ()
328
+ (save-excursion
329
+ (widen)
330
+ (goto-char (point-min))
331
+ (when (re-search-forward "[^\0-\177]" nil t)
332
+ (goto-char (point-min))
333
+ (let ((coding-system
334
+ (or coding-system-for-write
335
+ buffer-file-coding-system)))
336
+ (if coding-system
337
+ (setq coding-system
338
+ (or (coding-system-get coding-system 'mime-charset)
339
+ (coding-system-change-eol-conversion coding-system nil))))
340
+ (setq coding-system
341
+ (if coding-system
342
+ (symbol-name
343
+ (or (and ruby-use-encoding-map
344
+ (cdr (assq coding-system ruby-encoding-map)))
345
+ coding-system))
346
+ "ascii-8bit"))
347
+ (if (looking-at "^#!") (beginning-of-line 2))
348
+ (cond ((looking-at "\\s *#.*-\*-\\s *\\(en\\)?coding\\s *:\\s *\\([-a-z0-9_]*\\)\\s *\\(;\\|-\*-\\)")
349
+ (unless (string= (match-string 2) coding-system)
350
+ (goto-char (match-beginning 2))
351
+ (delete-region (point) (match-end 2))
352
+ (and (looking-at "-\*-")
353
+ (let ((n (skip-chars-backward " ")))
354
+ (cond ((= n 0) (insert " ") (backward-char))
355
+ ((= n -1) (insert " "))
356
+ ((forward-char)))))
357
+ (insert coding-system)))
358
+ ((looking-at "\\s *#.*coding\\s *[:=]"))
359
+ (t (insert "# -*- coding: " coding-system " -*-\n"))
360
+ )))))
361
+
362
+ (defun ruby-current-indentation ()
363
+ (save-excursion
364
+ (beginning-of-line)
365
+ (back-to-indentation)
366
+ (current-column)))
367
+
368
+ (defun ruby-indent-line (&optional flag)
369
+ "Correct indentation of the current ruby line."
370
+ (ruby-indent-to (ruby-calculate-indent)))
371
+
372
+ (defun ruby-indent-command ()
373
+ (interactive)
374
+ (ruby-indent-line t))
375
+
376
+ (defun ruby-indent-to (x)
377
+ (if x
378
+ (let (shift top beg)
379
+ (and (< x 0) (error "invalid nest"))
380
+ (setq shift (current-column))
381
+ (beginning-of-line)
382
+ (setq beg (point))
383
+ (back-to-indentation)
384
+ (setq top (current-column))
385
+ (skip-chars-backward " \t")
386
+ (if (>= shift top) (setq shift (- shift top))
387
+ (setq shift 0))
388
+ (if (and (bolp)
389
+ (= x top))
390
+ (move-to-column (+ x shift))
391
+ (move-to-column top)
392
+ (delete-region beg (point))
393
+ (beginning-of-line)
394
+ (indent-to x)
395
+ (move-to-column (+ x shift))))))
396
+
397
+ (defun ruby-special-char-p (&optional pnt)
398
+ (setq pnt (or pnt (point)))
399
+ (let ((c (char-before pnt)) (b (and (< (point-min) pnt) (char-before (1- pnt)))))
400
+ (cond ((or (eq c ??) (eq c ?$)))
401
+ ((and (eq c ?:) (or (not b) (eq (char-syntax b) ? ))))
402
+ ((eq c ?\\) (eq b ??)))))
403
+
404
+ (defun ruby-singleton-class-p ()
405
+ (save-excursion
406
+ (forward-word -1)
407
+ (and (or (bolp) (not (eq (char-before (point)) ?_)))
408
+ (looking-at "class\\s *<<"))))
409
+
410
+ (defun ruby-expr-beg (&optional option)
411
+ (save-excursion
412
+ (store-match-data nil)
413
+ (let ((space (skip-chars-backward " \t"))
414
+ (start (point)))
415
+ (cond
416
+ ((bolp) t)
417
+ ((progn
418
+ (forward-char -1)
419
+ (and (looking-at "\\?")
420
+ (or (eq (char-syntax (char-before (point))) ?w)
421
+ (ruby-special-char-p))))
422
+ nil)
423
+ ((and (eq option 'heredoc) (< space 0))
424
+ (not (progn (goto-char start) (ruby-singleton-class-p))))
425
+ ((or (looking-at ruby-operator-re)
426
+ (looking-at "[\\[({,;]")
427
+ (and (looking-at "[!?]")
428
+ (or (not (eq option 'modifier))
429
+ (bolp)
430
+ (save-excursion (forward-char -1) (looking-at "\\Sw$"))))
431
+ (and (looking-at ruby-symbol-re)
432
+ (skip-chars-backward ruby-symbol-chars)
433
+ (cond
434
+ ((looking-at (regexp-opt
435
+ (append ruby-block-beg-keywords
436
+ ruby-block-op-keywords
437
+ ruby-block-mid-keywords)
438
+ 'words))
439
+ (goto-char (match-end 0))
440
+ (not (looking-at "\\s_\\|[!?:]")))
441
+ ((eq option 'expr-qstr)
442
+ (looking-at "[a-zA-Z][a-zA-z0-9_]* +%[^ \t]"))
443
+ ((eq option 'expr-re)
444
+ (looking-at "[a-zA-Z][a-zA-z0-9_]* +/[^ \t]"))
445
+ (t nil)))))))))
446
+
447
+ (defun ruby-forward-string (term &optional end no-error expand)
448
+ (let ((n 1) (c (string-to-char term))
449
+ (re (if expand
450
+ (concat "[^\\]\\(\\\\\\\\\\)*\\([" term "]\\|\\(#{\\)\\)")
451
+ (concat "[^\\]\\(\\\\\\\\\\)*[" term "]"))))
452
+ (while (and (re-search-forward re end no-error)
453
+ (if (match-beginning 3)
454
+ (ruby-forward-string "}{" end no-error nil)
455
+ (> (setq n (if (eq (char-before (point)) c)
456
+ (1- n) (1+ n))) 0)))
457
+ (forward-char -1))
458
+ (cond ((zerop n))
459
+ (no-error nil)
460
+ ((error "unterminated string")))))
461
+
462
+ (defun ruby-deep-indent-paren-p (c)
463
+ (cond ((listp ruby-deep-indent-paren)
464
+ (let ((deep (assoc c ruby-deep-indent-paren)))
465
+ (cond (deep
466
+ (or (cdr deep) ruby-deep-indent-paren-style))
467
+ ((memq c ruby-deep-indent-paren)
468
+ ruby-deep-indent-paren-style))))
469
+ ((eq c ruby-deep-indent-paren) ruby-deep-indent-paren-style)
470
+ ((eq c ?\( ) ruby-deep-arglist)))
471
+
472
+ (defun ruby-parse-partial (&optional end in-string nest depth pcol indent)
473
+ (or depth (setq depth 0))
474
+ (or indent (setq indent 0))
475
+ (when (re-search-forward ruby-delimiter end 'move)
476
+ (let ((pnt (point)) w re expand)
477
+ (goto-char (match-beginning 0))
478
+ (cond
479
+ ((and (memq (char-before) '(?@ ?$)) (looking-at "\\sw"))
480
+ (goto-char pnt))
481
+ ((looking-at "[\"`]") ;skip string
482
+ (cond
483
+ ((and (not (eobp))
484
+ (ruby-forward-string (buffer-substring (point) (1+ (point))) end t t))
485
+ nil)
486
+ (t
487
+ (setq in-string (point))
488
+ (goto-char end))))
489
+ ((looking-at "'")
490
+ (cond
491
+ ((and (not (eobp))
492
+ (re-search-forward "[^\\]\\(\\\\\\\\\\)*'" end t))
493
+ nil)
494
+ (t
495
+ (setq in-string (point))
496
+ (goto-char end))))
497
+ ((looking-at "/=")
498
+ (goto-char pnt))
499
+ ((looking-at "/")
500
+ (cond
501
+ ((and (not (eobp)) (ruby-expr-beg 'expr-re))
502
+ (if (ruby-forward-string "/" end t t)
503
+ nil
504
+ (setq in-string (point))
505
+ (goto-char end)))
506
+ (t
507
+ (goto-char pnt))))
508
+ ((looking-at "%")
509
+ (cond
510
+ ((and (not (eobp))
511
+ (ruby-expr-beg 'expr-qstr)
512
+ (not (looking-at "%="))
513
+ (looking-at "%[QqrxWw]?\\([^a-zA-Z0-9 \t\n]\\)"))
514
+ (goto-char (match-beginning 1))
515
+ (setq expand (not (memq (char-before) '(?q ?w))))
516
+ (setq w (match-string 1))
517
+ (cond
518
+ ((string= w "[") (setq re "]["))
519
+ ((string= w "{") (setq re "}{"))
520
+ ((string= w "(") (setq re ")("))
521
+ ((string= w "<") (setq re "><"))
522
+ ((and expand (string= w "\\"))
523
+ (setq w (concat "\\" w))))
524
+ (unless (cond (re (ruby-forward-string re end t expand))
525
+ (expand (ruby-forward-string w end t t))
526
+ (t (re-search-forward
527
+ (if (string= w "\\")
528
+ "\\\\[^\\]*\\\\"
529
+ (concat "[^\\]\\(\\\\\\\\\\)*" w))
530
+ end t)))
531
+ (setq in-string (point))
532
+ (goto-char end)))
533
+ (t
534
+ (goto-char pnt))))
535
+ ((looking-at "\\?") ;skip ?char
536
+ (cond
537
+ ((and (ruby-expr-beg)
538
+ (looking-at "?\\(\\\\C-\\|\\\\M-\\)*\\\\?."))
539
+ (goto-char (match-end 0)))
540
+ (t
541
+ (goto-char pnt))))
542
+ ((looking-at "\\$") ;skip $char
543
+ (goto-char pnt)
544
+ (forward-char 1))
545
+ ((looking-at "#") ;skip comment
546
+ (forward-line 1)
547
+ (goto-char (point))
548
+ )
549
+ ((looking-at "[\\[{(]")
550
+ (let ((deep (ruby-deep-indent-paren-p (char-after))))
551
+ (if (and deep (or (not (eq (char-after) ?\{)) (ruby-expr-beg)))
552
+ (progn
553
+ (and (eq deep 'space) (looking-at ".\\s +[^# \t\n]")
554
+ (setq pnt (1- (match-end 0))))
555
+ (setq nest (cons (cons (char-after (point)) pnt) nest))
556
+ (setq pcol (cons (cons pnt depth) pcol))
557
+ (setq depth 0))
558
+ (setq nest (cons (cons (char-after (point)) pnt) nest))
559
+ (setq depth (1+ depth))))
560
+ (goto-char pnt)
561
+ )
562
+ ((looking-at "[])}]")
563
+ (if (ruby-deep-indent-paren-p (matching-paren (char-after)))
564
+ (setq depth (cdr (car pcol)) pcol (cdr pcol))
565
+ (setq depth (1- depth)))
566
+ (setq nest (cdr nest))
567
+ (goto-char pnt))
568
+ ((looking-at ruby-block-end-re)
569
+ (if (or (and (not (bolp))
570
+ (progn
571
+ (forward-char -1)
572
+ (setq w (char-after (point)))
573
+ (or (eq ?_ w)
574
+ (eq ?. w))))
575
+ (progn
576
+ (goto-char pnt)
577
+ (setq w (char-after (point)))
578
+ (or (eq ?_ w)
579
+ (eq ?! w)
580
+ (eq ?? w))))
581
+ nil
582
+ (setq nest (cdr nest))
583
+ (setq depth (1- depth)))
584
+ (goto-char pnt))
585
+ ((looking-at "def\\s +[^(\n;]*")
586
+ (if (or (bolp)
587
+ (progn
588
+ (forward-char -1)
589
+ (not (eq ?_ (char-after (point))))))
590
+ (progn
591
+ (setq nest (cons (cons nil pnt) nest))
592
+ (setq depth (1+ depth))))
593
+ (goto-char (match-end 0)))
594
+ ((looking-at (concat "\\<\\(" ruby-block-beg-re "\\)\\>"))
595
+ (and
596
+ (save-match-data
597
+ (or (not (looking-at (concat "do" ruby-keyword-end-re)))
598
+ (save-excursion
599
+ (back-to-indentation)
600
+ (not (looking-at ruby-non-block-do-re)))))
601
+ (or (bolp)
602
+ (progn
603
+ (forward-char -1)
604
+ (setq w (char-after (point)))
605
+ (not (or (eq ?_ w)
606
+ (eq ?. w)))))
607
+ (goto-char pnt)
608
+ (setq w (char-after (point)))
609
+ (not (eq ?_ w))
610
+ (not (eq ?! w))
611
+ (not (eq ?? w))
612
+ (not (eq ?: w))
613
+ (skip-chars-forward " \t")
614
+ (goto-char (match-beginning 0))
615
+ (or (not (looking-at ruby-modifier-re))
616
+ (ruby-expr-beg 'modifier))
617
+ (goto-char pnt)
618
+ (setq nest (cons (cons nil pnt) nest))
619
+ (setq depth (1+ depth)))
620
+ (goto-char pnt))
621
+ ((looking-at ":\\(['\"]\\)")
622
+ (goto-char (match-beginning 1))
623
+ (ruby-forward-string (buffer-substring (match-beginning 1) (match-end 1)) end))
624
+ ((looking-at ":\\([-,.+*/%&|^~<>]=?\\|===?\\|<=>\\|![~=]?\\)")
625
+ (goto-char (match-end 0)))
626
+ ((looking-at ":\\([a-zA-Z_][a-zA-Z_0-9]*[!?=]?\\)?")
627
+ (goto-char (match-end 0)))
628
+ ((or (looking-at "\\.\\.\\.?")
629
+ (looking-at "\\.[0-9]+")
630
+ (looking-at "\\.[a-zA-Z_0-9]+")
631
+ (looking-at "\\."))
632
+ (goto-char (match-end 0)))
633
+ ((looking-at "^=begin")
634
+ (if (re-search-forward "^=end" end t)
635
+ (forward-line 1)
636
+ (setq in-string (match-end 0))
637
+ (goto-char end)))
638
+ ((looking-at "<<")
639
+ (cond
640
+ ((and (ruby-expr-beg 'heredoc)
641
+ (looking-at "<<\\(-\\)?\\(\\([\"'`]\\)\\([^\n]+?\\)\\3\\|\\(?:\\sw\\|\\s_\\)+\\)"))
642
+ (setq re (regexp-quote (or (match-string 4) (match-string 2))))
643
+ (if (match-beginning 1) (setq re (concat "\\s *" re)))
644
+ (let* ((id-end (goto-char (match-end 0)))
645
+ (line-end-position (save-excursion (end-of-line) (point)))
646
+ (state (list in-string nest depth pcol indent)))
647
+ ;; parse the rest of the line
648
+ (while (and (> line-end-position (point))
649
+ (setq state (apply 'ruby-parse-partial
650
+ line-end-position state))))
651
+ (setq in-string (car state)
652
+ nest (nth 1 state)
653
+ depth (nth 2 state)
654
+ pcol (nth 3 state)
655
+ indent (nth 4 state))
656
+ ;; skip heredoc section
657
+ (if (re-search-forward (concat "^" re "$") end 'move)
658
+ (forward-line 1)
659
+ (setq in-string id-end)
660
+ (goto-char end))))
661
+ (t
662
+ (goto-char pnt))))
663
+ ((looking-at "^__END__$")
664
+ (goto-char pnt))
665
+ ((looking-at ruby-here-doc-beg-re)
666
+ (if (re-search-forward (ruby-here-doc-end-match)
667
+ ruby-indent-point t)
668
+ (forward-line 1)
669
+ (setq in-string (match-end 0))
670
+ (goto-char ruby-indent-point)))
671
+ (t
672
+ (error (format "bad string %s"
673
+ (buffer-substring (point) pnt)
674
+ ))))))
675
+ (list in-string nest depth pcol))
676
+
677
+ (defun ruby-parse-region (start end)
678
+ (let (state)
679
+ (save-excursion
680
+ (if start
681
+ (goto-char start)
682
+ (ruby-beginning-of-indent))
683
+ (save-restriction
684
+ (narrow-to-region (point) end)
685
+ (while (and (> end (point))
686
+ (setq state (apply 'ruby-parse-partial end state))))))
687
+ (list (nth 0 state) ; in-string
688
+ (car (nth 1 state)) ; nest
689
+ (nth 2 state) ; depth
690
+ (car (car (nth 3 state))) ; pcol
691
+ ;(car (nth 5 state)) ; indent
692
+ )))
693
+
694
+ (defun ruby-indent-size (pos nest)
695
+ (+ pos (* (or nest 1) ruby-indent-level)))
696
+
697
+ (defun ruby-calculate-indent (&optional parse-start)
698
+ (save-excursion
699
+ (beginning-of-line)
700
+ (let ((ruby-indent-point (point))
701
+ (case-fold-search nil)
702
+ state bol eol begin op-end
703
+ (paren (progn (skip-syntax-forward " ")
704
+ (and (char-after) (matching-paren (char-after)))))
705
+ (indent 0))
706
+ (if parse-start
707
+ (goto-char parse-start)
708
+ (ruby-beginning-of-indent)
709
+ (setq parse-start (point)))
710
+ (back-to-indentation)
711
+ (setq indent (current-column))
712
+ (setq state (ruby-parse-region parse-start ruby-indent-point))
713
+ (cond
714
+ ((nth 0 state) ; within string
715
+ (setq indent nil)) ; do nothing
716
+ ((car (nth 1 state)) ; in paren
717
+ (goto-char (setq begin (cdr (nth 1 state))))
718
+ (let ((deep (ruby-deep-indent-paren-p (car (nth 1 state)))))
719
+ (if deep
720
+ (cond ((and (eq deep t) (eq (car (nth 1 state)) paren))
721
+ (skip-syntax-backward " ")
722
+ (setq indent (1- (current-column))))
723
+ ((let ((s (ruby-parse-region (point) ruby-indent-point)))
724
+ (and (nth 2 s) (> (nth 2 s) 0)
725
+ (or (goto-char (cdr (nth 1 s))) t)))
726
+ (forward-word -1)
727
+ (setq indent (ruby-indent-size (current-column) (nth 2 state))))
728
+ (t
729
+ (setq indent (current-column))
730
+ (cond ((eq deep 'space))
731
+ (paren (setq indent (1- indent)))
732
+ (t (setq indent (ruby-indent-size (1- indent) 1))))))
733
+ (if (nth 3 state) (goto-char (nth 3 state))
734
+ (goto-char parse-start) (back-to-indentation))
735
+ (setq indent (ruby-indent-size (current-column) (nth 2 state))))
736
+ (and (eq (car (nth 1 state)) paren)
737
+ (ruby-deep-indent-paren-p (matching-paren paren))
738
+ (search-backward (char-to-string paren))
739
+ (setq indent (current-column)))))
740
+ ((and (nth 2 state) (> (nth 2 state) 0)) ; in nest
741
+ (if (null (cdr (nth 1 state)))
742
+ (error "invalid nest"))
743
+ (goto-char (cdr (nth 1 state)))
744
+ (forward-word -1) ; skip back a keyword
745
+ (setq begin (point))
746
+ (cond
747
+ ((looking-at "do\\>[^_]") ; iter block is a special case
748
+ (if (nth 3 state) (goto-char (nth 3 state))
749
+ (goto-char parse-start) (back-to-indentation))
750
+ (setq indent (ruby-indent-size (current-column) (nth 2 state))))
751
+ (t
752
+ (setq indent (+ (current-column) ruby-indent-level)))))
753
+
754
+ ((and (nth 2 state) (< (nth 2 state) 0)) ; in negative nest
755
+ (setq indent (ruby-indent-size (current-column) (nth 2 state)))))
756
+ (when indent
757
+ (goto-char ruby-indent-point)
758
+ (end-of-line)
759
+ (setq eol (point))
760
+ (beginning-of-line)
761
+ (cond
762
+ ((and (not (ruby-deep-indent-paren-p paren))
763
+ (re-search-forward ruby-negative eol t))
764
+ (and (not (eq ?_ (char-after (match-end 0))))
765
+ (setq indent (- indent ruby-indent-level))))
766
+ ((and
767
+ (save-excursion
768
+ (beginning-of-line)
769
+ (not (bobp)))
770
+ (or (ruby-deep-indent-paren-p t)
771
+ (null (car (nth 1 state)))))
772
+ ;; goto beginning of non-empty no-comment line
773
+ (let (end done)
774
+ (while (not done)
775
+ (skip-chars-backward " \t\n")
776
+ (setq end (point))
777
+ (beginning-of-line)
778
+ (if (re-search-forward "^\\s *#" end t)
779
+ (beginning-of-line)
780
+ (setq done t))))
781
+ (setq bol (point))
782
+ (end-of-line)
783
+ ;; skip the comment at the end
784
+ (skip-chars-backward " \t")
785
+ (let (end (pos (point)))
786
+ (beginning-of-line)
787
+ (while (and (re-search-forward "#" pos t)
788
+ (setq end (1- (point)))
789
+ (or (ruby-special-char-p end)
790
+ (and (setq state (ruby-parse-region parse-start end))
791
+ (nth 0 state))))
792
+ (setq end nil))
793
+ (goto-char (or end pos))
794
+ (skip-chars-backward " \t")
795
+ (setq begin (if (and end (nth 0 state)) pos (cdr (nth 1 state))))
796
+ (setq state (ruby-parse-region parse-start (point))))
797
+ (or (bobp) (forward-char -1))
798
+ (and
799
+ (or (and (looking-at ruby-symbol-re)
800
+ (skip-chars-backward ruby-symbol-chars)
801
+ (looking-at (concat "\\<\\(" ruby-block-hanging-re "\\)\\>"))
802
+ (not (eq (point) (nth 3 state)))
803
+ (save-excursion
804
+ (goto-char (match-end 0))
805
+ (not (looking-at "[a-z_]"))))
806
+ (and (looking-at ruby-operator-re)
807
+ (not (ruby-special-char-p))
808
+ ;; operator at the end of line
809
+ (let ((c (char-after (point))))
810
+ (and
811
+ ;; (or (null begin)
812
+ ;; (save-excursion
813
+ ;; (goto-char begin)
814
+ ;; (skip-chars-forward " \t")
815
+ ;; (not (or (eolp) (looking-at "#")
816
+ ;; (and (eq (car (nth 1 state)) ?{)
817
+ ;; (looking-at "|"))))))
818
+ (or (not (eq ?/ c))
819
+ (null (nth 0 (ruby-parse-region (or begin parse-start) (point)))))
820
+ (or (not (eq ?| (char-after (point))))
821
+ (save-excursion
822
+ (or (eolp) (forward-char -1))
823
+ (cond
824
+ ((search-backward "|" nil t)
825
+ (skip-chars-backward " \t\n")
826
+ (and (not (eolp))
827
+ (progn
828
+ (forward-char -1)
829
+ (not (looking-at "{")))
830
+ (progn
831
+ (forward-word -1)
832
+ (not (looking-at "do\\>[^_]")))))
833
+ (t t))))
834
+ (not (eq ?, c))
835
+ (setq op-end t)))))
836
+ (setq indent
837
+ (cond
838
+ ((and
839
+ (null op-end)
840
+ (not (looking-at (concat "\\<\\(" ruby-block-hanging-re "\\)\\>")))
841
+ (eq (ruby-deep-indent-paren-p t) 'space)
842
+ (not (bobp)))
843
+ (widen)
844
+ (goto-char (or begin parse-start))
845
+ (skip-syntax-forward " ")
846
+ (current-column))
847
+ ((car (nth 1 state)) indent)
848
+ (t
849
+ (+ indent ruby-indent-level))))))))
850
+ (goto-char ruby-indent-point)
851
+ (beginning-of-line)
852
+ (skip-syntax-forward " ")
853
+ (if (looking-at "\\.[^.]")
854
+ (+ indent ruby-indent-level)
855
+ indent))))
856
+
857
+ (defun ruby-electric-brace (arg)
858
+ (interactive "P")
859
+ (insert-char last-command-event 1)
860
+ (ruby-indent-line t)
861
+ (delete-char -1)
862
+ (self-insert-command (prefix-numeric-value arg)))
863
+
864
+ (eval-when-compile
865
+ (defmacro defun-region-command (func args &rest body)
866
+ (let ((intr (car body)))
867
+ (when (featurep 'xemacs)
868
+ (if (stringp intr) (setq intr (cadr body)))
869
+ (and (eq (car intr) 'interactive)
870
+ (setq intr (cdr intr))
871
+ (setcar intr (concat "_" (car intr)))))
872
+ (cons 'defun (cons func (cons args body))))))
873
+
874
+ (defun-region-command ruby-beginning-of-defun (&optional arg)
875
+ "Move backward to next beginning-of-defun.
876
+ With argument, do this that many times.
877
+ Returns t unless search stops due to end of buffer."
878
+ (interactive "p")
879
+ (and (re-search-backward (concat "^\\(" ruby-block-beg-re "\\)\\b")
880
+ nil 'move (or arg 1))
881
+ (progn (beginning-of-line) t)))
882
+
883
+ (defun ruby-beginning-of-indent ()
884
+ (and (re-search-backward (concat "^\\(" ruby-indent-beg-re "\\)\\b")
885
+ nil 'move)
886
+ (progn
887
+ (beginning-of-line)
888
+ t)))
889
+
890
+ (defun-region-command ruby-end-of-defun (&optional arg)
891
+ "Move forward to next end of defun.
892
+ An end of a defun is found by moving forward from the beginning of one."
893
+ (interactive "p")
894
+ (and (re-search-forward (concat "^\\(" ruby-block-end-re "\\)\\($\\|\\b[^_]\\)")
895
+ nil 'move (or arg 1))
896
+ (progn (beginning-of-line) t))
897
+ (forward-line 1))
898
+
899
+ (defun ruby-move-to-block (n)
900
+ (let (start pos done down (orig (point)))
901
+ (setq start (ruby-calculate-indent))
902
+ (setq down (looking-at (if (< n 0) ruby-block-end-re
903
+ (concat "\\<\\(" ruby-block-beg-re "\\)\\>"))))
904
+ (while (and (not done) (not (if (< n 0) (bobp) (eobp))))
905
+ (forward-line n)
906
+ (cond
907
+ ((looking-at "^\\s *$"))
908
+ ((looking-at "^\\s *#"))
909
+ ((and (> n 0) (looking-at "^=begin\\>"))
910
+ (re-search-forward "^=end\\>"))
911
+ ((and (< n 0) (looking-at "^=end\\>"))
912
+ (re-search-backward "^=begin\\>"))
913
+ (t
914
+ (setq pos (current-indentation))
915
+ (cond
916
+ ((< start pos)
917
+ (setq down t))
918
+ ((and down (= pos start))
919
+ (setq done t))
920
+ ((> start pos)
921
+ (setq done t)))))
922
+ (if done
923
+ (save-excursion
924
+ (back-to-indentation)
925
+ (if (looking-at (concat "\\<\\(" ruby-block-mid-re "\\)\\>"))
926
+ (setq done nil)))))
927
+ (back-to-indentation)
928
+ (when (< n 0)
929
+ (let ((eol (point-at-eol)) state next)
930
+ (if (< orig eol) (setq eol orig))
931
+ (setq orig (point))
932
+ (while (and (setq next (apply 'ruby-parse-partial eol state))
933
+ (< (point) eol))
934
+ (setq state next))
935
+ (when (cdaadr state)
936
+ (goto-char (cdaadr state)))
937
+ (backward-word)))))
938
+
939
+ (defun-region-command ruby-beginning-of-block (&optional arg)
940
+ "Move backward to next beginning-of-block"
941
+ (interactive "p")
942
+ (ruby-move-to-block (- (or arg 1))))
943
+
944
+ (defun-region-command ruby-end-of-block (&optional arg)
945
+ "Move forward to next beginning-of-block"
946
+ (interactive "p")
947
+ (ruby-move-to-block (or arg 1)))
948
+
949
+ (defun-region-command ruby-forward-sexp (&optional cnt)
950
+ (interactive "p")
951
+ (if (and (numberp cnt) (< cnt 0))
952
+ (ruby-backward-sexp (- cnt))
953
+ (let ((i (or cnt 1)))
954
+ (condition-case nil
955
+ (while (> i 0)
956
+ (skip-syntax-forward " ")
957
+ (if (looking-at ",\\s *") (goto-char (match-end 0)))
958
+ (cond ((looking-at "\\?\\(\\\\[CM]-\\)*\\\\?\\S ")
959
+ (goto-char (match-end 0)))
960
+ ((progn
961
+ (skip-chars-forward ",.:;|&^~=!?\\+\\-\\*")
962
+ (looking-at "\\s("))
963
+ (goto-char (scan-sexps (point) 1)))
964
+ ((and (looking-at (concat "\\<\\(" ruby-block-beg-re "\\)\\>"))
965
+ (not (eq (char-before (point)) ?.))
966
+ (not (eq (char-before (point)) ?:)))
967
+ (ruby-end-of-block)
968
+ (forward-word 1))
969
+ ((looking-at "\\(\\$\\|@@?\\)?\\sw")
970
+ (while (progn
971
+ (while (progn (forward-word 1) (looking-at "_")))
972
+ (cond ((looking-at "::") (forward-char 2) t)
973
+ ((> (skip-chars-forward ".") 0))
974
+ ((looking-at "\\?\\|!\\(=[~=>]\\|[^~=]\\)")
975
+ (forward-char 1) nil)))))
976
+ ((let (state expr)
977
+ (while
978
+ (progn
979
+ (setq expr (or expr (ruby-expr-beg)
980
+ (looking-at "%\\sw?\\Sw\\|[\"'`/]")))
981
+ (nth 1 (setq state (apply 'ruby-parse-partial nil state))))
982
+ (setq expr t)
983
+ (skip-chars-forward "<"))
984
+ (not expr))))
985
+ (setq i (1- i)))
986
+ ((error) (forward-word 1)))
987
+ i)))
988
+
989
+ (defun-region-command ruby-backward-sexp (&optional cnt)
990
+ (interactive "p")
991
+ (if (and (numberp cnt) (< cnt 0))
992
+ (ruby-forward-sexp (- cnt))
993
+ (let ((i (or cnt 1)))
994
+ (condition-case nil
995
+ (while (> i 0)
996
+ (skip-chars-backward " \t\n,.:;|&^~=!?\\+\\-\\*")
997
+ (forward-char -1)
998
+ (cond ((looking-at "\\s)")
999
+ (goto-char (scan-sexps (1+ (point)) -1))
1000
+ (case (char-before)
1001
+ (?% (forward-char -1))
1002
+ ('(?q ?Q ?w ?W ?r ?x)
1003
+ (if (eq (char-before (1- (point))) ?%) (forward-char -2))))
1004
+ nil)
1005
+ ((looking-at "\\s\"\\|\\\\\\S_")
1006
+ (let ((c (char-to-string (char-before (match-end 0)))))
1007
+ (while (and (search-backward c)
1008
+ (oddp (skip-chars-backward "\\")))))
1009
+ nil)
1010
+ ((looking-at "\\s.\\|\\s\\")
1011
+ (if (ruby-special-char-p) (forward-char -1)))
1012
+ ((looking-at "\\s(") nil)
1013
+ (t
1014
+ (forward-char 1)
1015
+ (while (progn (forward-word -1)
1016
+ (case (char-before)
1017
+ (?_ t)
1018
+ (?. (forward-char -1) t)
1019
+ ((?$ ?@)
1020
+ (forward-char -1)
1021
+ (and (eq (char-before) (char-after)) (forward-char -1)))
1022
+ (?:
1023
+ (forward-char -1)
1024
+ (eq (char-before) :)))))
1025
+ (if (looking-at ruby-block-end-re)
1026
+ (ruby-beginning-of-block))
1027
+ nil))
1028
+ (setq i (1- i)))
1029
+ ((error)))
1030
+ i)))
1031
+
1032
+ (defun ruby-reindent-then-newline-and-indent ()
1033
+ (interactive "*")
1034
+ (newline)
1035
+ (save-excursion
1036
+ (end-of-line 0)
1037
+ (indent-according-to-mode)
1038
+ (delete-region (point) (progn (skip-chars-backward " \t") (point))))
1039
+ (indent-according-to-mode))
1040
+
1041
+ (fset 'ruby-encomment-region (symbol-function 'comment-region))
1042
+
1043
+ (defun ruby-decomment-region (beg end)
1044
+ (interactive "r")
1045
+ (save-excursion
1046
+ (goto-char beg)
1047
+ (while (re-search-forward "^\\([ \t]*\\)#" end t)
1048
+ (replace-match "\\1" nil nil)
1049
+ (save-excursion
1050
+ (ruby-indent-line)))))
1051
+
1052
+ (defun ruby-insert-end ()
1053
+ (interactive)
1054
+ (insert "end")
1055
+ (ruby-indent-line t)
1056
+ (end-of-line))
1057
+
1058
+ (defun ruby-mark-defun ()
1059
+ "Put mark at end of this Ruby function, point at beginning."
1060
+ (interactive)
1061
+ (push-mark (point))
1062
+ (ruby-end-of-defun)
1063
+ (push-mark (point) nil t)
1064
+ (ruby-beginning-of-defun)
1065
+ (re-search-backward "^\n" (- (point) 1) t))
1066
+
1067
+ (defun ruby-indent-exp (&optional shutup-p)
1068
+ "Indent each line in the balanced expression following point syntactically.
1069
+ If optional SHUTUP-P is non-nil, no errors are signalled if no
1070
+ balanced expression is found."
1071
+ (interactive "*P")
1072
+ (let ((here (point-marker)) start top column (nest t))
1073
+ (set-marker-insertion-type here t)
1074
+ (unwind-protect
1075
+ (progn
1076
+ (beginning-of-line)
1077
+ (setq start (point) top (current-indentation))
1078
+ (while (and (not (eobp))
1079
+ (progn
1080
+ (setq column (ruby-calculate-indent start))
1081
+ (cond ((> column top)
1082
+ (setq nest t))
1083
+ ((and (= column top) nest)
1084
+ (setq nest nil) t))))
1085
+ (ruby-indent-to column)
1086
+ (beginning-of-line 2)))
1087
+ (goto-char here)
1088
+ (set-marker here nil))))
1089
+
1090
+ (defun ruby-add-log-current-method ()
1091
+ "Return current method string."
1092
+ (condition-case nil
1093
+ (save-excursion
1094
+ (let (mname mlist (indent 0))
1095
+ ;; get current method (or class/module)
1096
+ (if (re-search-backward
1097
+ (concat "^[ \t]*\\(def\\|class\\|module\\)[ \t]+"
1098
+ "\\("
1099
+ ;; \\. and :: for class method
1100
+ "\\([A-Za-z_]" ruby-symbol-re "*\\|\\.\\|::" "\\)"
1101
+ "+\\)")
1102
+ nil t)
1103
+ (progn
1104
+ (setq mname (match-string 2))
1105
+ (unless (string-equal "def" (match-string 1))
1106
+ (setq mlist (list mname) mname nil))
1107
+ (goto-char (match-beginning 1))
1108
+ (setq indent (current-column))
1109
+ (beginning-of-line)))
1110
+ ;; nest class/module
1111
+ (while (and (> indent 0)
1112
+ (re-search-backward
1113
+ (concat
1114
+ "^[ \t]*\\(class\\|module\\)[ \t]+"
1115
+ "\\([A-Z]" ruby-symbol-re "*\\)")
1116
+ nil t))
1117
+ (goto-char (match-beginning 1))
1118
+ (if (< (current-column) indent)
1119
+ (progn
1120
+ (setq mlist (cons (match-string 2) mlist))
1121
+ (setq indent (current-column))
1122
+ (beginning-of-line))))
1123
+ (when mname
1124
+ (let ((mn (split-string mname "\\.\\|::")))
1125
+ (if (cdr mn)
1126
+ (progn
1127
+ (cond
1128
+ ((string-equal "" (car mn))
1129
+ (setq mn (cdr mn) mlist nil))
1130
+ ((string-equal "self" (car mn))
1131
+ (setq mn (cdr mn)))
1132
+ ((let ((ml (nreverse mlist)))
1133
+ (while ml
1134
+ (if (string-equal (car ml) (car mn))
1135
+ (setq mlist (nreverse (cdr ml)) ml nil))
1136
+ (or (setq ml (cdr ml)) (nreverse mlist))))))
1137
+ (if mlist
1138
+ (setcdr (last mlist) mn)
1139
+ (setq mlist mn))
1140
+ (setq mn (last mn 2))
1141
+ (setq mname (concat "." (cadr mn)))
1142
+ (setcdr mn nil))
1143
+ (setq mname (concat "#" mname)))))
1144
+ ;; generate string
1145
+ (if (consp mlist)
1146
+ (setq mlist (mapconcat (function identity) mlist "::")))
1147
+ (if mname
1148
+ (if mlist (concat mlist mname) mname)
1149
+ mlist)))))
1150
+
1151
+ (defun ruby-brace-to-do-end ()
1152
+ (when (looking-at "{")
1153
+ (let ((orig (point)) (end (progn (ruby-forward-sexp) (point))))
1154
+ (when (eq (char-before) ?\})
1155
+ (delete-char -1)
1156
+ (if (eq (char-syntax (char-before)) ?w)
1157
+ (insert " "))
1158
+ (insert "end")
1159
+ (if (eq (char-syntax (char-after)) ?w)
1160
+ (insert " "))
1161
+ (goto-char orig)
1162
+ (delete-char 1)
1163
+ (if (eq (char-syntax (char-before)) ?w)
1164
+ (insert " "))
1165
+ (insert "do")
1166
+ (when (looking-at "\\sw\\||")
1167
+ (insert " ")
1168
+ (backward-char))
1169
+ t))))
1170
+
1171
+ (defun ruby-do-end-to-brace ()
1172
+ (when (and (or (bolp)
1173
+ (not (memq (char-syntax (char-before)) '(?w ?_))))
1174
+ (looking-at "\\<do\\(\\s \\|$\\)"))
1175
+ (let ((orig (point)) (end (progn (ruby-forward-sexp) (point))))
1176
+ (backward-char 3)
1177
+ (when (looking-at ruby-block-end-re)
1178
+ (delete-char 3)
1179
+ (insert "}")
1180
+ (goto-char orig)
1181
+ (delete-char 2)
1182
+ (insert "{")
1183
+ (if (looking-at "\\s +|")
1184
+ (delete-char (- (match-end 0) (match-beginning 0) 1)))
1185
+ t))))
1186
+
1187
+ (defun ruby-toggle-block ()
1188
+ (interactive)
1189
+ (or (ruby-brace-to-do-end)
1190
+ (ruby-do-end-to-brace)))
1191
+
1192
+ (eval-when-compile
1193
+ (if (featurep 'font-lock)
1194
+ (defmacro eval-when-font-lock-available (&rest args) (cons 'progn args))
1195
+ (defmacro eval-when-font-lock-available (&rest args))))
1196
+
1197
+ (eval-when-compile
1198
+ (if (featurep 'hilit19)
1199
+ (defmacro eval-when-hilit19-available (&rest args) (cons 'progn args))
1200
+ (defmacro eval-when-hilit19-available (&rest args))))
1201
+
1202
+ (eval-when-font-lock-available
1203
+ (or (boundp 'font-lock-variable-name-face)
1204
+ (setq font-lock-variable-name-face font-lock-type-face))
1205
+
1206
+ (defconst ruby-font-lock-syntactic-keywords
1207
+ `(
1208
+ ;; #{ }, #$hoge, #@foo are not comments
1209
+ ("\\(#\\)[{$@]" 1 (1 . nil))
1210
+ ;; the last $', $", $` in the respective string is not variable
1211
+ ;; the last ?', ?", ?` in the respective string is not ascii code
1212
+ ("\\(^\\|[\[ \t\n<+\(,=]\\)\\(['\"`]\\)\\(\\\\.\\|\\2\\|[^'\"`\n\\\\]\\)*?\\\\?[?$]\\(\\2\\)"
1213
+ (2 (7 . nil))
1214
+ (4 (7 . nil)))
1215
+ ;; $' $" $` .... are variables
1216
+ ;; ?' ?" ?` are ascii codes
1217
+ ("\\(^\\|[^\\\\]\\)\\(\\\\\\\\\\)*[?$]\\([#\"'`]\\)" 3 (1 . nil))
1218
+ ;; regexps
1219
+ ("\\(^\\|[[=(,~?:;<>]\\|\\(^\\|\\s \\)\\(if\\|elsif\\|unless\\|while\\|until\\|when\\|and\\|or\\|&&\\|||\\)\\|g?sub!?\\|scan\\|split!?\\)\\s *\\(/\\)[^/\n\\\\]*\\(\\\\.[^/\n\\\\]*\\)*\\(/\\)"
1220
+ (4 (7 . ?/))
1221
+ (6 (7 . ?/)))
1222
+ ("^\\(=\\)begin\\(\\s \\|$\\)" 1 (7 . nil))
1223
+ ("^\\(=\\)end\\(\\s \\|$\\)" 1 (7 . nil))
1224
+ (,(concat ruby-here-doc-beg-re ".*\\(\n\\)")
1225
+ ,(+ 1 (regexp-opt-depth ruby-here-doc-beg-re))
1226
+ (ruby-here-doc-beg-syntax))
1227
+ (,ruby-here-doc-end-re 3 (ruby-here-doc-end-syntax))))
1228
+
1229
+ (unless (functionp 'syntax-ppss)
1230
+ (defun syntax-ppss (&optional pos)
1231
+ (parse-partial-sexp (point-min) (or pos (point)))))
1232
+
1233
+ (defun ruby-in-ppss-context-p (context &optional ppss)
1234
+ (let ((ppss (or ppss (syntax-ppss (point)))))
1235
+ (if (cond
1236
+ ((eq context 'anything)
1237
+ (or (nth 3 ppss)
1238
+ (nth 4 ppss)))
1239
+ ((eq context 'string)
1240
+ (nth 3 ppss))
1241
+ ((eq context 'heredoc)
1242
+ (and (nth 3 ppss)
1243
+ ;; If it's generic string, it's a heredoc and we don't care
1244
+ ;; See `parse-partial-sexp'
1245
+ (not (numberp (nth 3 ppss)))))
1246
+ ((eq context 'non-heredoc)
1247
+ (and (ruby-in-ppss-context-p 'anything)
1248
+ (not (ruby-in-ppss-context-p 'heredoc))))
1249
+ ((eq context 'comment)
1250
+ (nth 4 ppss))
1251
+ (t
1252
+ (error (concat
1253
+ "Internal error on `ruby-in-ppss-context-p': "
1254
+ "context name `" (symbol-name context) "' is unknown"))))
1255
+ t)))
1256
+
1257
+ (defun ruby-in-here-doc-p ()
1258
+ (save-excursion
1259
+ (let ((old-point (point)) (case-fold-search nil))
1260
+ (beginning-of-line)
1261
+ (catch 'found-beg
1262
+ (while (and (re-search-backward ruby-here-doc-beg-re nil t)
1263
+ (not (ruby-singleton-class-p)))
1264
+ (if (not (or (ruby-in-ppss-context-p 'anything)
1265
+ (ruby-here-doc-find-end old-point)))
1266
+ (throw 'found-beg t)))))))
1267
+
1268
+ (defun ruby-here-doc-find-end (&optional limit)
1269
+ "Expects the point to be on a line with one or more heredoc
1270
+ openers. Returns the buffer position at which all heredocs on the
1271
+ line are terminated, or nil if they aren't terminated before the
1272
+ buffer position `limit' or the end of the buffer."
1273
+ (save-excursion
1274
+ (beginning-of-line)
1275
+ (catch 'done
1276
+ (let ((eol (save-excursion (end-of-line) (point)))
1277
+ (case-fold-search nil)
1278
+ ;; Fake match data such that (match-end 0) is at eol
1279
+ (end-match-data (progn (looking-at ".*$") (match-data)))
1280
+ beg-match-data end-re)
1281
+ (while (re-search-forward ruby-here-doc-beg-re eol t)
1282
+ (setq beg-match-data (match-data))
1283
+ (setq end-re (ruby-here-doc-end-match))
1284
+
1285
+ (set-match-data end-match-data)
1286
+ (goto-char (match-end 0))
1287
+ (unless (re-search-forward end-re limit t) (throw 'done nil))
1288
+ (setq end-match-data (match-data))
1289
+
1290
+ (set-match-data beg-match-data)
1291
+ (goto-char (match-end 0)))
1292
+ (set-match-data end-match-data)
1293
+ (goto-char (match-end 0))
1294
+ (point)))))
1295
+
1296
+ (defun ruby-here-doc-beg-syntax ()
1297
+ (save-excursion
1298
+ (goto-char (match-beginning 0))
1299
+ (unless (or (ruby-in-ppss-context-p 'non-heredoc)
1300
+ (ruby-in-here-doc-p))
1301
+ (string-to-syntax "|"))))
1302
+
1303
+ (defun ruby-here-doc-end-syntax ()
1304
+ (let ((pss (syntax-ppss)) (case-fold-search nil))
1305
+ (when (ruby-in-ppss-context-p 'heredoc pss)
1306
+ (save-excursion
1307
+ (goto-char (nth 8 pss)) ; Go to the beginning of heredoc.
1308
+ (let ((eol (point)))
1309
+ (beginning-of-line)
1310
+ (if (and (re-search-forward (ruby-here-doc-beg-match) eol t) ; If there is a heredoc that matches this line...
1311
+ (not (ruby-in-ppss-context-p 'anything)) ; And that's not inside a heredoc/string/comment...
1312
+ (progn (goto-char (match-end 0)) ; And it's the last heredoc on its line...
1313
+ (not (re-search-forward ruby-here-doc-beg-re eol t))))
1314
+ (string-to-syntax "|")))))))
1315
+
1316
+ (eval-when-compile
1317
+ (put 'ruby-mode 'font-lock-defaults
1318
+ '((ruby-font-lock-keywords)
1319
+ nil nil nil
1320
+ beginning-of-line
1321
+ (font-lock-syntactic-keywords
1322
+ . ruby-font-lock-syntactic-keywords))))
1323
+
1324
+ (defun ruby-font-lock-docs (limit)
1325
+ (if (re-search-forward "^=begin\\(\\s \\|$\\)" limit t)
1326
+ (let (beg)
1327
+ (beginning-of-line)
1328
+ (setq beg (point))
1329
+ (forward-line 1)
1330
+ (if (re-search-forward "^=end\\(\\s \\|$\\)" limit t)
1331
+ (progn
1332
+ (set-match-data (list beg (point)))
1333
+ t)))))
1334
+
1335
+ (defun ruby-font-lock-maybe-docs (limit)
1336
+ (let (beg)
1337
+ (save-excursion
1338
+ (if (and (re-search-backward "^=\\(begin\\|end\\)\\(\\s \\|$\\)" nil t)
1339
+ (string= (match-string 1) "begin"))
1340
+ (progn
1341
+ (beginning-of-line)
1342
+ (setq beg (point)))))
1343
+ (if (and beg (and (re-search-forward "^=\\(begin\\|end\\)\\(\\s \\|$\\)" nil t)
1344
+ (string= (match-string 1) "end")))
1345
+ (progn
1346
+ (set-match-data (list beg (point)))
1347
+ t)
1348
+ nil)))
1349
+
1350
+ (defvar ruby-font-lock-syntax-table
1351
+ (let* ((tbl (copy-syntax-table ruby-mode-syntax-table)))
1352
+ (modify-syntax-entry ?_ "w" tbl)
1353
+ tbl))
1354
+
1355
+ (defconst ruby-font-lock-keywords
1356
+ (list
1357
+ ;; functions
1358
+ '("^\\s *def\\s +\\([^( \t\n]+\\)"
1359
+ 1 font-lock-function-name-face)
1360
+ ;; keywords
1361
+ (cons (concat
1362
+ "\\(^\\|[^_:.@$]\\|\\.\\.\\)\\b\\(defined\\?\\|"
1363
+ (regexp-opt
1364
+ '("alias"
1365
+ "and"
1366
+ "begin"
1367
+ "break"
1368
+ "case"
1369
+ "catch"
1370
+ "class"
1371
+ "def"
1372
+ "do"
1373
+ "elsif"
1374
+ "else"
1375
+ "fail"
1376
+ "ensure"
1377
+ "for"
1378
+ "end"
1379
+ "if"
1380
+ "in"
1381
+ "module"
1382
+ "next"
1383
+ "not"
1384
+ "or"
1385
+ "raise"
1386
+ "redo"
1387
+ "rescue"
1388
+ "retry"
1389
+ "return"
1390
+ "then"
1391
+ "throw"
1392
+ "super"
1393
+ "unless"
1394
+ "undef"
1395
+ "until"
1396
+ "when"
1397
+ "while"
1398
+ "yield"
1399
+ )
1400
+ t)
1401
+ "\\)"
1402
+ ruby-keyword-end-re)
1403
+ 2)
1404
+ ;; here-doc beginnings
1405
+ (list ruby-here-doc-beg-re 0 'font-lock-string-face)
1406
+ ;; variables
1407
+ '("\\(^\\|[^_:.@$]\\|\\.\\.\\)\\b\\(nil\\|self\\|true\\|false\\)\\>"
1408
+ 2 font-lock-variable-name-face)
1409
+ ;; variables
1410
+ '("\\(\\$\\([^a-zA-Z0-9 \n]\\|[0-9]\\)\\)\\W"
1411
+ 1 font-lock-variable-name-face)
1412
+ '("\\(\\$\\|@\\|@@\\)\\(\\w\\|_\\)+"
1413
+ 0 font-lock-variable-name-face)
1414
+ ;; embedded document
1415
+ '(ruby-font-lock-docs
1416
+ 0 font-lock-comment-face t)
1417
+ '(ruby-font-lock-maybe-docs
1418
+ 0 font-lock-comment-face t)
1419
+ ;; general delimited string
1420
+ '("\\(^\\|[[ \t\n<+(,=]\\)\\(%[xrqQwW]?\\([^<[{(a-zA-Z0-9 \n]\\)[^\n\\\\]*\\(\\\\.[^\n\\\\]*\\)*\\(\\3\\)\\)"
1421
+ (2 font-lock-string-face))
1422
+ ;; constants
1423
+ '("\\(^\\|[^_]\\)\\b\\([A-Z]+\\(\\w\\|_\\)*\\)"
1424
+ 2 font-lock-type-face)
1425
+ ;; symbols
1426
+ '("\\(^\\|[^:]\\)\\(:\\([-+~]@?\\|[/%&|^`]\\|\\*\\*?\\|<\\(<\\|=>?\\)?\\|>[>=]?\\|===?\\|=~\\|![~=]?\\|\\[\\]=?\\|\\(\\w\\|_\\)+\\([!?=]\\|\\b_*\\)\\|#{[^}\n\\\\]*\\(\\\\.[^}\n\\\\]*\\)*}\\)\\)"
1427
+ 2 font-lock-reference-face)
1428
+ '("\\(^\\s *\\|[\[\{\(,]\\s *\\|\\sw\\s +\\)\\(\\(\\sw\\|_\\)+\\):[^:]" 2 font-lock-reference-face)
1429
+ ;; expression expansion
1430
+ '("#\\({[^}\n\\\\]*\\(\\\\.[^}\n\\\\]*\\)*}\\|\\(\\$\\|@\\|@@\\)\\(\\w\\|_\\)+\\)"
1431
+ 0 font-lock-variable-name-face t)
1432
+ ;; warn lower camel case
1433
+ ;'("\\<[a-z]+[a-z0-9]*[A-Z][A-Za-z0-9]*\\([!?]?\\|\\>\\)"
1434
+ ; 0 font-lock-warning-face)
1435
+ )
1436
+ "*Additional expressions to highlight in ruby mode."))
1437
+
1438
+ (eval-when-hilit19-available
1439
+ (hilit-set-mode-patterns
1440
+ 'ruby-mode
1441
+ '(("[^$\\?]\\(\"[^\\\"]*\\(\\\\\\(.\\|\n\\)[^\\\"]*\\)*\"\\)" 1 string)
1442
+ ("[^$\\?]\\('[^\\']*\\(\\\\\\(.\\|\n\\)[^\\']*\\)*'\\)" 1 string)
1443
+ ("[^$\\?]\\(`[^\\`]*\\(\\\\\\(.\\|\n\\)[^\\`]*\\)*`\\)" 1 string)
1444
+ ("^\\s *#.*$" nil comment)
1445
+ ("[^$@?\\]\\(#[^$@{\n].*$\\)" 1 comment)
1446
+ ("[^a-zA-Z_]\\(\\?\\(\\\\[CM]-\\)*.\\)" 1 string)
1447
+ ("^\\s *\\(require\\|load\\).*$" nil include)
1448
+ ("^\\s *\\(include\\|alias\\|undef\\).*$" nil decl)
1449
+ ("^\\s *\\<\\(class\\|def\\|module\\)\\>" "[)\n;]" defun)
1450
+ ("[^_]\\<\\(begin\\|case\\|else\\|elsif\\|end\\|ensure\\|for\\|if\\|unless\\|rescue\\|then\\|when\\|while\\|until\\|do\\|yield\\)\\>\\([^_]\\|$\\)" 1 defun)
1451
+ ("[^_]\\<\\(and\\|break\\|next\\|raise\\|fail\\|in\\|not\\|or\\|redo\\|retry\\|return\\|super\\|yield\\|catch\\|throw\\|self\\|nil\\)\\>\\([^_]\\|$\\)" 1 keyword)
1452
+ ("\\$\\(.\\|\\sw+\\)" nil type)
1453
+ ("[$@].[a-zA-Z_0-9]*" nil struct)
1454
+ ("^__END__" nil label))))
1455
+
1456
+
1457
+ ;;;###autoload
1458
+ (defun ruby-mode ()
1459
+ "Major mode for editing ruby scripts.
1460
+ \\[ruby-indent-command] properly indents subexpressions of multi-line
1461
+ class, module, def, if, while, for, do, and case statements, taking
1462
+ nesting into account.
1463
+
1464
+ The variable ruby-indent-level controls the amount of indentation.
1465
+ \\{ruby-mode-map}"
1466
+ (interactive)
1467
+ (kill-all-local-variables)
1468
+ (use-local-map ruby-mode-map)
1469
+ (setq mode-name "Ruby")
1470
+ (setq major-mode 'ruby-mode)
1471
+ (ruby-mode-variables)
1472
+
1473
+ (make-local-variable 'imenu-create-index-function)
1474
+ (setq imenu-create-index-function 'ruby-imenu-create-index)
1475
+
1476
+ (make-local-variable 'add-log-current-defun-function)
1477
+ (setq add-log-current-defun-function 'ruby-add-log-current-method)
1478
+
1479
+ (add-hook
1480
+ (cond ((boundp 'before-save-hook)
1481
+ (make-local-variable 'before-save-hook)
1482
+ 'before-save-hook)
1483
+ ((boundp 'write-contents-functions) 'write-contents-functions)
1484
+ ((boundp 'write-contents-hooks) 'write-contents-hooks))
1485
+ 'ruby-mode-set-encoding)
1486
+
1487
+ (set (make-local-variable 'font-lock-defaults) '((ruby-font-lock-keywords) nil nil))
1488
+ (set (make-local-variable 'font-lock-keywords) ruby-font-lock-keywords)
1489
+ (set (make-local-variable 'font-lock-syntax-table) ruby-font-lock-syntax-table)
1490
+ (set (make-local-variable 'font-lock-syntactic-keywords) ruby-font-lock-syntactic-keywords)
1491
+
1492
+ (if (fboundp 'run-mode-hooks)
1493
+ (run-mode-hooks 'ruby-mode-hook)
1494
+ (run-hooks 'ruby-mode-hook)))
1495
+
1496
+ (provide 'ruby-mode)