1# frozen_string_literal: false
2require 'test/unit'
3require 'tempfile'
4
5class TestRubyMode < Test::Unit::TestCase
6  MISCDIR = File.expand_path("../../../misc", __FILE__)
7  e = ENV["EMACS"] || "emacs"
8  emacs = %W"#{e} -q --no-site-file --batch --load #{MISCDIR}/ruby-mode.el"
9  begin
10    raise if IO.popen([e, "--version", :err=>[:child, :out]]) {|f| f.read}[/[0-9]+/].to_i < 23
11    IO.popen([*emacs, :err=>[:child, :out]]) {|f| f.read}
12  rescue
13    EMACS = nil
14  else
15    EMACS = (emacs if $? and $?.success?)
16  end
17end
18
19class TestRubyMode
20  EVAL_OPT = "--eval"
21  EXPR_SAVE = "(save-buffer 0)"
22  finish_mark = "ok-#{$$}"
23  FINISH_MARK = /^#{finish_mark}$/
24  EXPR_FINISH = "(print \'#{finish_mark})"
25  EXPR_RUBYMODE = "(ruby-mode)"
26
27  def run_emacs(src, *exprs)
28    tmp = Tempfile.new(%w"ruby-mode.test. .rb")
29    tmp.puts(src)
30    tmp.close
31    exprs = exprs.map {|expr| [EVAL_OPT, expr]}.flatten
32    exprs.unshift(EVAL_OPT, EXPR_RUBYMODE)
33    exprs.push(EVAL_OPT, EXPR_SAVE)
34    exprs.push(EVAL_OPT, EXPR_FINISH)
35    output = IO.popen([*EMACS, tmp.path, *exprs, err:[:child, :out]], "r") {|e| e.read}
36    tmp.open
37    result = tmp.read
38    return result, output
39  ensure
40    tmp.close!
41  end
42
43  class TestIndent < self
44    EXPR_INDENT = "(indent-region (point-min) (point-max))"
45
46    def assert_indent(expected, source, *message)
47      if space = expected[/\A\n?(\s*\|)/, 1]
48        space = /^#{Regexp.quote(space)}/m
49        expected.gsub!(space, '')
50        source.gsub!(space, '')
51      end
52      result, output = run_emacs(source, EXPR_INDENT)
53      assert_match(FINISH_MARK, output)
54      assert_equal(expected, result, message(*message) {diff expected, result})
55    end
56
57    def test_simple
58      assert_indent('
59      |if foo
60      |  bar
61      |end
62      |zot
63      |', '
64      |if foo
65      |bar
66      |  end
67      |    zot
68      |')
69    end
70
71    def test_keyword_label
72      assert_indent('
73      |bar(class: XXX) do
74      |  foo
75      |end
76      |bar
77      |', '
78      |bar(class: XXX) do
79      |     foo
80      |  end
81      |    bar
82      |')
83    end
84
85    def test_method_with_question_mark
86      assert_indent('
87      |if x.is_a?(XXX)
88      |  foo
89      |end
90      |', '
91      |if x.is_a?(XXX)
92      | foo
93      |   end
94      |')
95    end
96
97    def test_expr_in_regexp
98      assert_indent('
99      |if /#{foo}/ =~ s
100      |  x = 1
101      |end
102      |', '
103      |if /#{foo}/ =~ s
104      | x = 1
105      |  end
106      |')
107    end
108
109    def test_singleton_class
110      skip("pending")
111      assert_indent('
112      |class<<bar
113      |  foo
114      |end
115      |', '
116      |class<<bar
117      |foo
118      |   end
119      |')
120    end
121
122    def test_array_literal
123      assert_indent('
124      |foo = [
125      |  bar
126      |]
127      |', '
128      |foo = [
129      | bar
130      |  ]
131      |')
132      assert_indent('
133      |foo do
134      |  [bar]
135      |end
136      |', '
137      |foo do
138      |[bar]
139      |  end
140      |')
141    end
142
143    def test_begin_end
144      assert_indent('
145      |begin
146      |  a[b]
147      |end
148      |', '
149      |begin
150      | a[b]
151      |  end
152      |')
153    end
154
155    def test_array_after_paren_and_space
156      assert_indent('
157      |class A
158      |  def foo
159      |    foo( [])
160      |  end
161      |end
162      |', '
163      |class A
164      | def foo
165      |foo( [])
166      |end
167      |  end
168      |')
169    end
170
171    def test_spread_arguments
172      assert_indent('
173      |foo(1,
174      |    2,
175      |    3)
176      |', '
177      |foo(1,
178      | 2,
179      |  3)
180      |')
181    end
182  end
183end if TestRubyMode::EMACS
184