text_editor 0.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (67) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +3 -0
  3. data/.rspec +2 -0
  4. data/.rubocop.yml +33 -0
  5. data/.ruby-version +1 -0
  6. data/.text_editor.rb +9 -0
  7. data/Gemfile +6 -0
  8. data/Gemfile.lock +58 -0
  9. data/LICENSE +20 -0
  10. data/README.org +29 -0
  11. data/bin/console +9 -0
  12. data/bin/te +3 -0
  13. data/lib/core_ext/hash.rb +12 -0
  14. data/lib/core_ext/pathname.rb +9 -0
  15. data/lib/text_editor/buffer.rb +85 -0
  16. data/lib/text_editor/clipboard/cygwin.rb +20 -0
  17. data/lib/text_editor/clipboard/linux.rb +17 -0
  18. data/lib/text_editor/clipboard/mac.rb +18 -0
  19. data/lib/text_editor/clipboard/unknown.rb +17 -0
  20. data/lib/text_editor/clipboard/windows.rb +17 -0
  21. data/lib/text_editor/clipboard.rb +18 -0
  22. data/lib/text_editor/command/backspace.rb +26 -0
  23. data/lib/text_editor/command/cursor_down.rb +14 -0
  24. data/lib/text_editor/command/cursor_end.rb +10 -0
  25. data/lib/text_editor/command/cursor_left.rb +16 -0
  26. data/lib/text_editor/command/cursor_right.rb +19 -0
  27. data/lib/text_editor/command/cursor_start.rb +10 -0
  28. data/lib/text_editor/command/cursor_up.rb +13 -0
  29. data/lib/text_editor/command/insert_char.rb +11 -0
  30. data/lib/text_editor/command/insert_line.rb +16 -0
  31. data/lib/text_editor/command/insert_tab.rb +9 -0
  32. data/lib/text_editor/command/quit.rb +9 -0
  33. data/lib/text_editor/command/resolver.rb +36 -0
  34. data/lib/text_editor/command/write_file.rb +13 -0
  35. data/lib/text_editor/command.rb +26 -0
  36. data/lib/text_editor/component.rb +13 -0
  37. data/lib/text_editor/configuration/bootstrap.rb +43 -0
  38. data/lib/text_editor/configuration/dsl.rb +11 -0
  39. data/lib/text_editor/configuration/resolver.rb +45 -0
  40. data/lib/text_editor/configuration.rb +15 -0
  41. data/lib/text_editor/cursor.rb +42 -0
  42. data/lib/text_editor/keyboard.rb +54 -0
  43. data/lib/text_editor/mode/nano.rb +30 -0
  44. data/lib/text_editor/mode.rb +23 -0
  45. data/lib/text_editor/operating_system.rb +19 -0
  46. data/lib/text_editor/reactor.rb +38 -0
  47. data/lib/text_editor/state.rb +10 -0
  48. data/lib/text_editor/terminal.rb +57 -0
  49. data/lib/text_editor/window.rb +44 -0
  50. data/lib/text_editor.rb +121 -0
  51. data/log/.keep +0 -0
  52. data/spec/core_ext/hash_spec.rb +15 -0
  53. data/spec/core_ext/pathname_spec.rb +26 -0
  54. data/spec/spec_helper.rb +15 -0
  55. data/spec/text_editor/buffer_spec.rb +181 -0
  56. data/spec/text_editor/clipboard_spec.rb +28 -0
  57. data/spec/text_editor/command/quit_spec.rb +14 -0
  58. data/spec/text_editor/command/resolver_spec.rb +56 -0
  59. data/spec/text_editor/command_spec.rb +85 -0
  60. data/spec/text_editor/component_spec.rb +40 -0
  61. data/spec/text_editor/configuration_spec.rb +25 -0
  62. data/spec/text_editor/cursor_spec.rb +93 -0
  63. data/spec/text_editor/operating_system_spec.rb +55 -0
  64. data/spec/text_editor/reactor_spec.rb +34 -0
  65. data/spec/text_editor/state_spec.rb +20 -0
  66. data/text_editor.gemspec +18 -0
  67. metadata +143 -0
@@ -0,0 +1,181 @@
1
+ require "spec_helper"
2
+
3
+ RSpec.describe TextEditor::Buffer do
4
+ subject { described_class.new(lines) }
5
+
6
+ let(:lines) { %w(one two) }
7
+
8
+ describe "#delete_char" do
9
+ it "deletes char at line and column" do
10
+ actual = subject.delete_char(0, 0)
11
+ expect(actual.to_s).to eq("ne\ntwo")
12
+
13
+ actual = subject.delete_char(0, 1)
14
+ expect(actual.to_s).to eq("oe\ntwo")
15
+
16
+ actual = subject.delete_char(1, 0)
17
+ expect(actual.to_s).to eq("one\nwo")
18
+
19
+ actual = subject.delete_char(1, 1)
20
+ expect(actual.to_s).to eq("one\nto")
21
+ end
22
+
23
+ it "ignores columns out of bounds" do
24
+ actual = subject.delete_char(0, 10)
25
+ expect(actual.to_s).to eq("one\ntwo")
26
+ end
27
+
28
+ it "raises IndexError when line is out of bounds" do
29
+ expect { subject.delete_char(10, 0) }.to raise_error(IndexError)
30
+ end
31
+ end
32
+
33
+ describe "#delete_line" do
34
+ it "deletes line at index" do
35
+ actual = subject.delete_line(0)
36
+ expect(actual.to_s).to eq("two")
37
+
38
+ actual = subject.delete_line(1)
39
+ expect(actual.to_s).to eq("one")
40
+ end
41
+
42
+ it "ignores out of bound indexes" do
43
+ actual = subject.delete_line(3)
44
+ expect(actual.to_s).to eq("one\ntwo")
45
+ end
46
+
47
+ it "does not mutate the original buffer" do
48
+ subject.delete_line(0)
49
+ expect(subject.to_s).to eq("one\ntwo")
50
+ end
51
+ end
52
+
53
+ describe "#each_line" do
54
+ it "delegates to lines" do
55
+ expect(lines).to receive(:each)
56
+ subject.each_line { |line| line }
57
+ end
58
+ end
59
+
60
+ describe "#insert_char" do
61
+ it "inserts char at index" do
62
+ actual = subject.insert_char(0, 0, "x")
63
+ expect(actual.to_s).to eq("xone\ntwo")
64
+
65
+ actual = subject.insert_char(0, 1, "x")
66
+ expect(actual.to_s).to eq("oxne\ntwo")
67
+
68
+ actual = subject.insert_char(1, 0, "x")
69
+ expect(actual.to_s).to eq("one\nxtwo")
70
+
71
+ actual = subject.insert_char(1, 1, "x")
72
+ expect(actual.to_s).to eq("one\ntxwo")
73
+ end
74
+
75
+ it "raises IndexError when line is out of bounds" do
76
+ expect { subject.insert_char(10, 0, "x") }.to raise_error(IndexError)
77
+ end
78
+
79
+ it "raises IndexError when column is out of bounds" do
80
+ expect { subject.insert_char(0, 10, "x") }.to raise_error(IndexError)
81
+ end
82
+ end
83
+
84
+ describe "#insert_line" do
85
+ it "inserts line at index" do
86
+ actual = subject.insert_line(0)
87
+ expect(actual.to_s).to eq("\none\ntwo")
88
+
89
+ actual = subject.insert_line(1)
90
+ expect(actual.to_s).to eq("one\n\ntwo")
91
+
92
+ actual = subject.insert_line(2)
93
+ expect(actual.to_s).to eq("one\ntwo\n")
94
+ end
95
+
96
+ it "optionally accepts content" do
97
+ actual = subject.insert_line(1, "test")
98
+ expect(actual.to_s).to eq("one\ntest\ntwo")
99
+ end
100
+
101
+ it "inserts at tail when index is out of bounds" do
102
+ actual = subject.insert_line(5)
103
+ expect(actual.to_s).to eq("one\ntwo\n")
104
+ end
105
+ end
106
+
107
+ describe "#line" do
108
+ it "returns line by index" do
109
+ actual = subject.line(0)
110
+ expect(actual).to eq("one")
111
+
112
+ actual = subject.line(1)
113
+ expect(actual).to eq("two")
114
+ end
115
+
116
+ it "returns empty string otherwise" do
117
+ actual = subject.line(2)
118
+ expect(actual).to eq("")
119
+ end
120
+
121
+ it "returns a copy of the line" do
122
+ first_id = subject.line(0).object_id
123
+ second_id = subject.line(0).object_id
124
+ expect(first_id).not_to eq(second_id)
125
+ end
126
+ end
127
+
128
+ context "#replace_char" do
129
+ it "replace char at index" do
130
+ actual = subject.replace_char(0, 0, "x")
131
+ expect(actual.to_s).to eq("xne\ntwo")
132
+
133
+ actual = subject.replace_char(0, 1, "x")
134
+ expect(actual.to_s).to eq("oxe\ntwo")
135
+
136
+ actual = subject.replace_char(1, 0, "x")
137
+ expect(actual.to_s).to eq("one\nxwo")
138
+
139
+ actual = subject.replace_char(1, 1, "x")
140
+ expect(actual.to_s).to eq("one\ntxo")
141
+ end
142
+
143
+ it "raises IndexError when line is out of bounds" do
144
+ expect { subject.replace_char(10, 0, "x") }.to raise_error(IndexError)
145
+ end
146
+
147
+ it "raises IndexError when column is out of bounds" do
148
+ expect { subject.replace_char(0, 10, "x") }.to raise_error(IndexError)
149
+ end
150
+ end
151
+
152
+ context "#replace_line" do
153
+ it "replaces line at index" do
154
+ actual = subject.replace_line(0, "test")
155
+ expect(actual.to_s).to eq("test\ntwo")
156
+
157
+ actual = subject.replace_line(1, "test")
158
+ expect(actual.to_s).to eq("one\ntest")
159
+ end
160
+
161
+ it "replaces line with empty string by default" do
162
+ actual = subject.replace_line(0)
163
+ expect(actual.to_s).to eq("\ntwo")
164
+ end
165
+
166
+ it "raises IndexError when line is out of bounds" do
167
+ expect { subject.replace_line(10, "test") }.to raise_error(IndexError)
168
+ end
169
+ end
170
+
171
+ describe "#to_s" do
172
+ it "joins lines with a newline" do
173
+ expect(subject.to_s).to eq("one\ntwo")
174
+ end
175
+
176
+ it "returns an empty string if lines are empty" do
177
+ lines.clear
178
+ expect(subject.to_s).to eq("")
179
+ end
180
+ end
181
+ end
@@ -0,0 +1,28 @@
1
+ require "spec_helper"
2
+
3
+ RSpec.describe TextEditor::Clipboard do
4
+ subject { described_class.new(editor) }
5
+
6
+ let(:editor) { double("editor") }
7
+
8
+ describe "#clear" do
9
+ it "delegates to adapter.clear" do
10
+ expect(subject).to receive_message_chain(:adapter, :clear)
11
+ subject.clear
12
+ end
13
+ end
14
+
15
+ describe "#copy" do
16
+ it "delegates to adapter.copy" do
17
+ expect(subject).to receive_message_chain(:adapter, :copy)
18
+ subject.copy
19
+ end
20
+ end
21
+
22
+ describe "#paste" do
23
+ it "delegates to adapter.paste" do
24
+ expect(subject).to receive_message_chain(:adapter, :paste)
25
+ subject.paste
26
+ end
27
+ end
28
+ end
@@ -0,0 +1,14 @@
1
+ require "spec_helper"
2
+
3
+ RSpec.describe TextEditor::Command::Quit do
4
+ subject { described_class.new(editor) }
5
+
6
+ let(:editor) { double("editor") }
7
+
8
+ describe "#run" do
9
+ it "delegates to editor.reactor.stop" do
10
+ expect(subject).to receive_message_chain(:editor, :reactor, :stop)
11
+ subject.run
12
+ end
13
+ end
14
+ end
@@ -0,0 +1,56 @@
1
+ require "spec_helper"
2
+
3
+ RSpec.describe TextEditor::Command::Resolver do
4
+ subject { described_class.new(editor) }
5
+
6
+ let(:editor) { double("editor") }
7
+ let(:fake) { Class.new(namespace) }
8
+ let(:namespace) { TextEditor::Command }
9
+
10
+ before { namespace.const_set(:FakeCommand, fake) }
11
+ after { namespace.send(:remove_const, :FakeCommand) }
12
+
13
+ describe "#method_missing" do
14
+ it "runs a command instance" do
15
+ expect { subject.fake_command }.to raise_error(NotImplementedError)
16
+ end
17
+
18
+ it "returns self" do
19
+ fake.send(:define_method, :run) { true }
20
+ expect(subject.fake_command).to eq(subject)
21
+ end
22
+
23
+ it "raises NoMethodError for invalid commands" do
24
+ expect { subject.invalid_command }.to raise_error(NoMethodError)
25
+ expect { subject.invalid_command! }.to raise_error(NoMethodError)
26
+ expect { subject.invalid_command? }.to raise_error(NoMethodError)
27
+ end
28
+ end
29
+
30
+ describe "#resolve" do
31
+ it "finds existing string commands" do
32
+ actual = subject.resolve("fake_command")
33
+ expect(actual).to be_a(fake)
34
+ end
35
+
36
+ it "finds existing symbol commands" do
37
+ actual = subject.resolve(:fake_command)
38
+ expect(actual).to be_a(fake)
39
+ end
40
+
41
+ it "returns nil for missing commands" do
42
+ actual = subject.resolve(:invalid)
43
+ expect(actual).to be_nil
44
+ end
45
+ end
46
+
47
+ describe "#respond_to?" do
48
+ it "only returns true for defined commands" do
49
+ actual = subject.respond_to?(:fake_command)
50
+ expect(actual).to eq(true)
51
+
52
+ actual = subject.respond_to?(:invalid_command)
53
+ expect(actual).to eq(false)
54
+ end
55
+ end
56
+ end
@@ -0,0 +1,85 @@
1
+ require "spec_helper"
2
+
3
+ RSpec.describe TextEditor::Command do
4
+ subject { described_class.new(editor) }
5
+
6
+ let(:editor) { double("editor") }
7
+
8
+ describe ".call" do
9
+ it "delegates to new instance" do
10
+ args = [1, 2, 3]
11
+ block = proc { true }
12
+ command = double("command")
13
+ expect(command).to receive(:run).with(*args, &block)
14
+ expect(described_class).to receive(:new).with(editor).and_return(command)
15
+ described_class.call(editor, *args, &block)
16
+ end
17
+ end
18
+
19
+ describe "#buffer" do
20
+ it "delegates to editor.window" do
21
+ expect(editor).to receive_message_chain(:window, :buffer)
22
+ subject.buffer
23
+ end
24
+ end
25
+
26
+ describe "#column" do
27
+ it "delegates to editor.window.cursor" do
28
+ expect(editor).to receive_message_chain(:window, :cursor, :column)
29
+ subject.column
30
+ end
31
+ end
32
+
33
+ describe "#command" do
34
+ let(:resolver) { described_class::Resolver }
35
+
36
+ it "returns a command resolver" do
37
+ expect(subject.command).to be_a(resolver)
38
+ end
39
+ end
40
+
41
+ describe "#content" do
42
+ it "returns buffer content for the current line" do
43
+ line = "test"
44
+ buffer = double("buffer")
45
+ expect(buffer).to receive(:line).with(line)
46
+ expect(subject).to receive(:line).and_return(line)
47
+ expect(subject).to receive(:buffer).and_return(buffer)
48
+ subject.content
49
+ end
50
+ end
51
+
52
+ describe "#cursor" do
53
+ it "delegates to editor.window" do
54
+ expect(editor).to receive_message_chain(:window, :cursor)
55
+ subject.cursor
56
+ end
57
+ end
58
+
59
+ describe "#line" do
60
+ it "delegates to editor.window.line" do
61
+ expect(editor).to receive_message_chain(:window, :cursor, :line)
62
+ subject.line
63
+ end
64
+ end
65
+
66
+ describe "#run" do
67
+ it "must be implemented" do
68
+ expect { subject.run }.to raise_error(NotImplementedError)
69
+ end
70
+ end
71
+
72
+ describe "#state" do
73
+ it "delegates to editor.window" do
74
+ expect(editor).to receive_message_chain(:window, :state)
75
+ subject.state
76
+ end
77
+ end
78
+
79
+ describe "#window" do
80
+ it "delegates to editor" do
81
+ expect(editor).to receive(:window)
82
+ subject.window
83
+ end
84
+ end
85
+ end
@@ -0,0 +1,40 @@
1
+ require "spec_helper"
2
+
3
+ RSpec.describe TextEditor::Component do
4
+ subject { constant.new(editor) }
5
+
6
+ let(:editor) { double("editor") }
7
+
8
+ let(:constant) do
9
+ Class.new.instance_exec(described_class) do |mod|
10
+ include mod
11
+ end
12
+ end
13
+
14
+ describe "#config" do
15
+ it "delegates to editor.config" do
16
+ expect(subject).to receive_message_chain(:editor, :config)
17
+ subject.config
18
+ end
19
+ end
20
+
21
+ describe "#editor" do
22
+ it "returns initialized editor" do
23
+ expect(subject.editor).to eq(editor)
24
+ end
25
+ end
26
+
27
+ describe "#logger" do
28
+ it "delegates to editor.logger" do
29
+ expect(subject).to receive_message_chain(:editor, :logger)
30
+ subject.logger
31
+ end
32
+ end
33
+
34
+ describe "#terminal" do
35
+ it "delegates to editor.terminal" do
36
+ expect(subject).to receive_message_chain(:editor, :terminal)
37
+ subject.terminal
38
+ end
39
+ end
40
+ end
@@ -0,0 +1,25 @@
1
+ require "spec_helper"
2
+
3
+ RSpec.describe TextEditor::Configuration do
4
+ subject { described_class.new(editor) }
5
+
6
+ let(:editor) { double("editor") }
7
+
8
+ describe "#files" do
9
+ it "is an accessor" do
10
+ expect(subject.files).to be_nil
11
+
12
+ subject.files = "test"
13
+ expect(subject.files).to eq("test")
14
+ end
15
+ end
16
+
17
+ describe "#log" do
18
+ it "is an accessor" do
19
+ expect(subject.log).to be_nil
20
+
21
+ subject.log = "test"
22
+ expect(subject.log).to eq("test")
23
+ end
24
+ end
25
+ end
@@ -0,0 +1,93 @@
1
+ require "spec_helper"
2
+
3
+ RSpec.describe TextEditor::Cursor do
4
+ subject { described_class.new(line, column) }
5
+
6
+ let(:line) { 1 }
7
+ let(:column) { 2 }
8
+
9
+ describe "#column" do
10
+ it "returns current column" do
11
+ expect(subject.column).to eq(2)
12
+ end
13
+ end
14
+
15
+ describe "#down" do
16
+ it "moves cursor down" do
17
+ actual = subject.down
18
+ expect(actual.position).to eq([2, 2])
19
+
20
+ actual = subject.down(2)
21
+ expect(actual.position).to eq([3, 2])
22
+ end
23
+ end
24
+
25
+ describe "#initialize" do
26
+ it "sets line and column to 0 by default" do
27
+ expect(described_class.new.position).to eq([0, 0])
28
+ end
29
+ end
30
+
31
+ describe "#left" do
32
+ it "moves cursor left" do
33
+ actual = subject.left
34
+ expect(actual.position).to eq([1, 1])
35
+
36
+ actual = subject.left(2)
37
+ expect(actual.position).to eq([1, 0])
38
+
39
+ actual = subject.left(3)
40
+ expect(actual.position).to eq([1, 0])
41
+ end
42
+ end
43
+
44
+ describe "#line" do
45
+ it "returns current line" do
46
+ expect(subject.line).to eq(1)
47
+ end
48
+ end
49
+
50
+ describe "#move" do
51
+ it "moves cursor" do
52
+ actual = subject.move(4, 5)
53
+ expect(actual.position).to eq([4, 5])
54
+ end
55
+
56
+ it "does not allow negative values" do
57
+ actual = subject.move(-4, 5)
58
+ expect(actual.position).to eq([0, 5])
59
+
60
+ actual = subject.move(5, -4)
61
+ expect(actual.position).to eq([5, 0])
62
+ end
63
+ end
64
+
65
+ describe "#position" do
66
+ let(:line) { 1 }
67
+ let(:column) { 2 }
68
+
69
+ it "returns an array with the line and column" do
70
+ expect(subject.position).to eq([1, 2])
71
+ end
72
+ end
73
+
74
+ describe "#right" do
75
+ it "moves cursor right" do
76
+ actual = subject.right
77
+ expect(actual.position).to eq([1, 3])
78
+
79
+ actual = subject.right(2)
80
+ expect(actual.position).to eq([1, 4])
81
+ end
82
+ end
83
+
84
+ describe "#up" do
85
+ it "moves cursor up" do
86
+ actual = subject.up
87
+ expect(actual.position).to eq([0, 2])
88
+
89
+ actual = subject.up(2)
90
+ expect(actual.position).to eq([0, 2])
91
+ end
92
+ end
93
+ end
@@ -0,0 +1,55 @@
1
+ require "spec_helper"
2
+
3
+ RSpec.describe TextEditor::OperatingSystem do
4
+ subject { described_class.new(version) }
5
+
6
+ describe "#type" do
7
+ context "cygwin" do
8
+ let(:version) { "some-cygwin-version" }
9
+
10
+ it "parses correct type" do
11
+ expect(subject.type).to eq(:Cygwin)
12
+ end
13
+ end
14
+
15
+ context "linux" do
16
+ let(:version) { "i686-linux" }
17
+
18
+ it "parses correct type" do
19
+ expect(subject.type).to eq(:Linux)
20
+ end
21
+ end
22
+
23
+ context "mac" do
24
+ let(:version) { "x86_64-darwin14" }
25
+
26
+ it "parses correct type" do
27
+ expect(subject.type).to eq(:Mac)
28
+ end
29
+ end
30
+
31
+ context "unknown" do
32
+ let(:version) { "some-other-version" }
33
+
34
+ it "parses correct type" do
35
+ expect(subject.type).to eq(:Unknown)
36
+ end
37
+ end
38
+
39
+ context "windows" do
40
+ let(:version) { "some-mswin-version" }
41
+
42
+ it "parses correct type" do
43
+ expect(subject.type).to eq(:Windows)
44
+ end
45
+ end
46
+ end
47
+
48
+ describe "#version" do
49
+ let(:version) { "example" }
50
+
51
+ it "returns initialized version" do
52
+ expect(subject.version).to eq(version)
53
+ end
54
+ end
55
+ end
@@ -0,0 +1,34 @@
1
+ require "spec_helper"
2
+
3
+ RSpec.describe TextEditor::Reactor do
4
+ subject { described_class.new(editor) }
5
+
6
+ let(:editor) { double("editor") }
7
+
8
+ describe "#start" do
9
+ it "starts running" do
10
+ expect(subject).to receive(:render)
11
+ expect(subject).to receive(:listen)
12
+
13
+ expect(subject).not_to be_running
14
+ subject.start
15
+ expect(subject).to be_running
16
+ end
17
+ end
18
+
19
+ describe "#stop" do
20
+ it "stops running" do
21
+ subject.instance_variable_set("@running", true)
22
+ expect(subject).to be_running
23
+
24
+ subject.stop
25
+ expect(subject).not_to be_running
26
+ end
27
+ end
28
+
29
+ describe "#running?" do
30
+ it "is not running by default" do
31
+ expect(subject).not_to be_running
32
+ end
33
+ end
34
+ end
@@ -0,0 +1,20 @@
1
+ require "spec_helper"
2
+
3
+ RSpec.describe TextEditor::State do
4
+ subject { described_class.new(buffer, cursor) }
5
+
6
+ let(:buffer) { double("buffer") }
7
+ let(:cursor) { double("cursor") }
8
+
9
+ describe "#buffer" do
10
+ it "returns initialized buffer" do
11
+ expect(subject.buffer).to eq(buffer)
12
+ end
13
+ end
14
+
15
+ describe "#cursor" do
16
+ it "returns initialized cursor" do
17
+ expect(subject.cursor).to eq(cursor)
18
+ end
19
+ end
20
+ end
@@ -0,0 +1,18 @@
1
+ Gem::Specification.new do |s|
2
+ s.authors = "Sean Huber"
3
+ s.email = "sean@shuber.io"
4
+ s.extra_rdoc_files = %w(LICENSE)
5
+ s.files = `git ls-files`.split("\n")
6
+ s.homepage = "https://github.com/shuber/text_editor"
7
+ s.license = "MIT"
8
+ s.name = "text_editor"
9
+ s.required_ruby_version = ">= 2.0.0"
10
+ s.rdoc_options = %w(--charset=UTF-8 --inline-source --line-numbers --main README.org)
11
+ s.summary = "Text editor"
12
+ s.test_files = `git ls-files -- spec/*`.split("\n")
13
+ s.version = "0.0.0"
14
+
15
+ s.executables << "te"
16
+
17
+ s.add_dependency "curses", "1.0.2"
18
+ end