ruby_learner 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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)