mr_poole 0.1.0 → 0.2.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.
data/spec/command_spec.rb CHANGED
@@ -1,290 +1,348 @@
1
1
  require 'spec_helper'
2
-
3
2
  require 'mr_poole'
4
3
 
5
4
  module MrPoole
6
5
  describe Commands do
7
6
 
8
- before :all do
9
- @date_regex = %r{\d{4}-\d{2}-\d{2}}
10
- end
11
-
12
- before :each do
13
- @c = Commands.new
14
- @olddir, @tmpdir = make_jekyll_dir
15
- end
16
-
17
- after :each do
18
- clean_tmp_files(@tmpdir, @olddir)
19
- end
7
+ let(:date_regex) { %r{\d{4}-\d{2}-\d{2}} }
8
+ let(:c) { Commands.new }
9
+ before(:each) { @olddir, @tmpdir = make_jekyll_dir }
10
+ after(:each) { clean_tmp_files(@tmpdir, @olddir) }
20
11
 
21
12
  describe "#post" do
22
13
  context 'title only' do
23
-
24
14
  it "should create a new post in the _posts directory" do
25
- @c.post("test_post")
26
- Dir.glob("_posts/*.md").length.should == 1
27
- end
28
-
29
- it "should create a timestamped post in the _posts directory" do
30
- @c.post("test_post")
31
- fn = Dir.glob("_posts/*.md").first
32
- fn.should match(/#{@date_regex}-test_post[.]md$/)
15
+ fn = c.post({title: "test_post"})
16
+ expect(File.exists?(fn)).to be_true
33
17
  end
34
18
 
35
19
  it "should return path to the newly created post" do
36
- returned = @c.post("test_post")
20
+ returned = c.post({title: "test_post"})
37
21
  determined = Dir.glob("_posts/*.md").first
38
- returned.should == determined
22
+ expect(returned).to eq(determined)
23
+ end
24
+
25
+ it "should create a timestamped post in the _posts directory" do
26
+ fn = c.post({title: "test_post" })
27
+ expect(fn).to match(/#{date_regex}-test_post[.]md$/)
39
28
  end
40
29
 
41
30
  it "should downcase a title" do
42
- @c.post("Test_Post_With_Uppercase")
43
- fn = Dir.glob("_posts/*.md").first
44
- fn.should match(/#{@date_regex}-test_post_with_uppercase[.]md/)
31
+ fn = c.post({title: "Test_Post_With_Uppercase"})
32
+ expect(fn).to match(/#{date_regex}-test_post_with_uppercase[.]md/)
45
33
  end
46
34
 
47
35
  it "should sub underscores for spaces in title" do
48
- @c.post("Test Post with Spaces")
49
- fn = Dir.glob("_posts/*.md").first
50
- fn.should match(/#{@date_regex}-test_post_with_spaces[.]md/)
36
+ fn = c.post({title: "Test Post with Spaces"})
37
+ expect(fn).to match(/#{date_regex}-test_post_with_spaces[.]md/)
51
38
  end
52
39
 
53
40
  it "should remove non-word characters for slug" do
54
- @c.post("On (function() {}()) in JavaScript")
55
- fn = Dir.glob("_posts/*.md").first
56
- fn.should match(/#{@date_regex}-on_function_in_javascript[.]md/)
41
+ fn = c.post({title: "On (function() {}()) in JavaScript"})
42
+ expect(fn).to match(/#{date_regex}-on_function_in_javascript[.]md/)
57
43
  end
58
44
 
59
45
  it "should update the title in the file itself" do
60
- @c.post("Testing Post {}")
61
- fn = Dir.glob("_posts/*.md").first
46
+ fn = c.post({title: "Testing Post {}"})
62
47
  content = File.open(fn, 'r').read
63
- content.should match(/title: Testing Post {}/)
48
+ expect(content).to match(/title: Testing Post {}/)
64
49
  end
65
50
 
66
51
  it "should update the date in the file itself" do
67
- @c.post("Date test post")
68
- fn = Dir.glob("_posts/*.md").first
52
+ fn = c.post({title: "Date test post"})
69
53
 
70
54
  # date in filename should match date in file itself
71
- date = fn.match(/(#{@date_regex})-date_test_post[.]md/)[1]
55
+ date = fn.match(/(#{date_regex})-date_test_post[.]md/)[1]
72
56
  content = File.open(fn, 'r').read
73
- content.should match(/date: #{date}/)
57
+ expect(content).to match(/date: #{date}/)
74
58
  end
75
-
76
59
  end # end context title only
77
60
 
78
61
  context 'title and slug' do
79
-
80
62
  it "should create a post named for slug" do
81
- @c.post("Test Post", 'unique_slug')
82
- fn = Dir.glob("_posts/*.md").first
83
- fn.should match(/#{@date_regex}-unique_slug[.]md$/)
63
+ fn = c.post({title: "Test Post", slug: 'unique_slug'})
64
+ expect(fn).to match(/#{date_regex}-unique_slug[.]md$/)
84
65
  end
85
66
 
86
67
  it "should sub any weird characters in slug" do
87
- @c.post("Test Post with Spaces", "(stupid] {slüg/")
88
- fn = Dir.glob("_posts/*.md").first
89
- fn.should match(/#{@date_regex}-stupid_slg[.]md/)
68
+ fn = c.post({title: "Test Post with Spaces", slug: "(stupid] {slüg/"})
69
+ expect(fn).to match(/#{date_regex}-stupid_slg[.]md/)
90
70
  end
91
71
 
92
72
  it "should update the title in the file itself" do
93
- @c.post("Testing Post {}", 'shouldnt_be_in_title')
94
- fn = Dir.glob("_posts/*.md").first
73
+ fn = c.post({title: "Testing Post {}", slug: 'shouldnt_be_in_title'})
95
74
  content = File.open(fn, 'r').read
96
- content.should match(/title: Testing Post {}/)
75
+ expect(content).to match(/title: Testing Post {}/)
97
76
  end
98
-
99
77
  end # end context title & slug
100
78
 
79
+ context 'with custom layout' do
80
+ let(:layout_path) { write_custom_layout }
81
+
82
+ it "should exit if layout path doesn't exist" do
83
+ expect {
84
+ capture_stdout do
85
+ c.post({title: 'test_post', layout: 'bogus_path.md'})
86
+ end
87
+ }.to raise_error(SystemExit)
88
+ end
89
+
90
+ it 'should not use the default layout' do
91
+ fn = c.post({title: 'test_post', layout: layout_path})
92
+ content = File.open(fn, 'r').read
93
+ expect(content).not_to match(/layout: post/)
94
+ end
95
+
96
+ it 'should use the custom layout' do
97
+ fn = c.post({title: 'test_post', layout: layout_path})
98
+ content = File.open(fn, 'r').read
99
+ expect(content).to match(/tags: testing/)
100
+ end
101
+ end # context custom layout
101
102
  end # end describe post
102
103
 
103
104
  describe "#draft" do
104
105
  context 'title only' do
105
-
106
106
  it "should create a _drafts directory" do
107
- @c.draft('draft post')
108
- Dir.exists?('_drafts').should be_true
109
- end
110
-
111
- it "should create a new draft in the _drafts directory" do
112
- @c.draft('draft post')
113
- Dir.glob("_drafts/*.md").length.should == 1
107
+ c.draft({title: 'draft post'})
108
+ expect(Dir.exists?('_drafts')).to be_true
114
109
  end
115
110
 
116
111
  it "should return path to the newly created draft" do
117
- returned = @c.draft("test_draft")
112
+ returned = c.draft({title: "test_draft"})
118
113
  determined = Dir.glob("_drafts/*.md").first
119
- returned.should == determined
114
+ expect(returned).to eq(determined)
115
+ end
116
+
117
+ it "should create a new draft in the _drafts directory" do
118
+ fn = c.draft({title: 'draft post'})
119
+ expect(File.exists?(fn)).to be_true
120
120
  end
121
121
 
122
122
  it "should create a non-timestamped draft" do
123
- @c.draft('draft post')
124
- fn = Dir.glob("_drafts/*.md").first
125
- fn.should_not match(/#{@date_regex}/)
123
+ fn = c.draft({title: 'draft post'})
124
+ expect(fn).not_to match(/#{date_regex}/)
126
125
  end
127
126
 
128
127
  it "should downcase and underscore title for slug" do
129
- @c.draft("Test Post with Spaces")
130
- fn = Dir.glob("_drafts/*.md").first
131
- fn.should match(/test_post_with_spaces[.]md/)
128
+ fn = c.draft({title: "Test Post with Spaces"})
129
+ expect(fn).to match(/test_post_with_spaces[.]md/)
132
130
  end
133
131
 
134
132
  it "should remove non-word characters for slug" do
135
- @c.draft("On (function() {}()) in JavaScript")
136
- fn = Dir.glob("_drafts/*.md").first
137
- fn.should match(/on_function_in_javascript[.]md/)
133
+ fn = c.draft({title: "On (function() {}()) in JavaScript"})
134
+ expect(fn).to match(/on_function_in_javascript[.]md/)
138
135
  end
139
136
 
140
137
  it "should update the title in the file itself" do
141
- @c.draft("Testing Draft {}")
142
- fn = Dir.glob("_drafts/*.md").first
138
+ fn = c.draft({title: "Testing Draft {}"})
143
139
  content = File.open(fn, 'r').read
144
- content.should match(/title: Testing Draft {}/)
140
+ expect(content).to match(/title: Testing Draft {}/)
145
141
  end
146
142
 
147
143
  it "should not update the date in the file itself" do
148
- @c.draft("Date test post")
149
- fn = Dir.glob("_drafts/*.md").first
150
-
151
- # date in filename should match date in file itself
144
+ fn = c.draft({title: "Date test post"})
152
145
  content = File.open(fn, 'r').read
153
- content.should match(/date:\s*\n/)
146
+ expect(content).to match(/date:\s*\n/)
154
147
  end
155
-
156
148
  end # end context title only
157
149
 
158
150
  context 'title and slug' do
159
-
160
151
  it "should create a draft named for slug" do
161
- @c.draft("Test Draft", 'unique_slug')
162
- fn = Dir.glob("_drafts/*.md").first
163
- fn.should match(/unique_slug[.]md$/)
152
+ fn = c.draft({title: "Test Draft", slug: 'unique_slug'})
153
+ expect(fn).to match(/unique_slug[.]md$/)
164
154
  end
165
155
 
166
156
  it "should sub any weird characters in slug" do
167
- @c.draft("Test Post with Spaces", "(stupid] {slüg/")
168
- fn = Dir.glob("_drafts/*.md").first
169
- fn.should match(/stupid_slg[.]md/)
157
+ fn = c.draft({title: "Test Post with Spaces", slug: "(stupid] {slüg/"})
158
+ expect(fn).to match(/stupid_slg[.]md/)
170
159
  end
171
160
 
172
161
  it "should update the title in the file itself" do
173
- @c.draft("Testing Post {}", 'shouldnt_be_in_title')
174
- fn = Dir.glob("_drafts/*.md").first
162
+ fn = c.draft({title: "Testing Post {}", slug: 'shouldnt_be_in_title'})
175
163
  content = File.open(fn, 'r').read
176
- content.should match(/title: Testing Post {}/)
164
+ expect(content).to match(/title: Testing Post {}/)
177
165
  end
166
+ end # context title & slug
178
167
 
179
- end # end context title & slug
168
+ context 'with custom layout' do
169
+ let(:layout_path) { write_custom_layout }
170
+
171
+ it "should exit if layout path doesn't exist" do
172
+ expect {
173
+ capture_stdout do
174
+ c.draft({title: 'test_post', layout: 'bogus_path.md'})
175
+ end
176
+ }.to raise_error(SystemExit)
177
+ end
178
+
179
+ it 'should not use the default layout' do
180
+ fn = c.draft({title: 'test_post', layout: layout_path})
181
+ content = File.open(fn, 'r').read
182
+ expect(content).not_to match(/layout: post/)
183
+ end
180
184
 
185
+ it 'should use the custom layout' do
186
+ fn = c.draft({title: 'test_post', layout: layout_path})
187
+ content = File.open(fn, 'r').read
188
+ expect(content).to match(/tags: testing/)
189
+ end
190
+ end # context custom layout
181
191
  end # end describe draft
182
192
 
183
193
  describe "#publish" do
194
+ let(:d_path) { c.draft({title: 'test_draft'}) }
184
195
 
185
- before :each do
186
- @d_path = @c.draft('test_draft')
196
+ it 'should return path to newly created post' do
197
+ returned = c.publish(d_path)
198
+ determined = Dir.glob("_posts/*.md").first
199
+ expect(returned).to eq(determined)
187
200
  end
188
201
 
189
202
  it 'should create a timestamped post in the _posts folder' do
190
- @c.publish(@d_path)
191
- fn = Dir.glob("_posts/*.md").first
192
- fn.should match(/#{@date_regex}-test_draft[.]md$/)
203
+ fn = c.publish(d_path)
204
+ expect(fn).to match(/#{date_regex}-test_draft[.]md$/)
193
205
  end
194
206
 
195
207
  it 'should remove file in the _drafts folder' do
196
- @c.publish(@d_path)
197
- File.exist?(@d_path).should be_false
198
- end
199
-
200
- it 'should return path to newly created post' do
201
- returned = @c.publish(@d_path)
202
- determined = Dir.glob("_posts/*.md").first
203
- returned.should == determined
208
+ c.publish(d_path)
209
+ expect(File.exist?(d_path)).to be_false
204
210
  end
205
211
 
206
212
  it 'should create post with matching slug' do
207
- post = @c.publish(@d_path)
208
-
209
- draft_slug = File.basename(@d_path, '.md')
210
- post_slug = post.match(/#{@date_regex}-(.*)[.]md/)[1]
211
-
212
- post_slug.should == draft_slug
213
+ post = c.publish(d_path)
214
+ draft_slug = File.basename(d_path, '.md')
215
+ post_slug = post.match(/#{date_regex}-(.*)[.]md/)[1]
216
+ expect(post_slug).to eq(draft_slug)
213
217
  end
214
218
 
215
219
  it 'should update timestamp in actual file' do
216
- post = @c.publish(@d_path)
220
+ post = c.publish(d_path)
217
221
  content = File.open(post, 'r').read
218
- content.should match(/date: #{@date_regex} \d{2}:\d{2}\n/)
222
+ expect(content).to match(/date: #{date_regex} \d{2}:\d{2}\n/)
219
223
  end
220
224
 
221
225
  it 'should copy contents of draft into post' do
222
226
  # first add some content to the draft
223
- f = File.open(@d_path, 'a')
227
+ f = File.open(d_path, 'a')
224
228
  f.write("Some new content for my blog\n")
225
229
  f.close
226
230
 
227
- post = @c.publish(@d_path)
231
+ post = c.publish(d_path)
228
232
  content = File.open(post, 'r').read
229
- content.should match(/Some new content for my blog/)
233
+ expect(content).to match(/Some new content for my blog/)
230
234
  end
231
-
232
235
  end # end describe publish
233
236
 
234
237
  describe "#unpublish" do
238
+ let(:p_path) { c.post({title: 'test_post'}) }
235
239
 
236
- before :each do
237
- @p_path = @c.post('test_post')
240
+ it 'should return path to newly created draft' do
241
+ returned = c.unpublish(p_path)
242
+ determined = Dir.glob("_drafts/*.md").first
243
+ expect(returned).to eq(determined)
238
244
  end
239
245
 
240
246
  it 'should create a _drafts directory' do
241
- @c.unpublish(@p_path)
242
- Dir.exists?('_drafts').should be_true
247
+ c.unpublish(p_path)
248
+ expect(Dir.exists?('_drafts')).to be_true
243
249
  end
244
250
 
245
251
  it 'should create an untimestamped draft in the _drafts folder' do
246
- @c.unpublish(@p_path)
247
- fn = Dir.glob("_drafts/*.md").first
248
- fn.should_not match(/#{@date_regex}/)
252
+ fn = c.unpublish(p_path)
253
+ expect(fn).not_to match(/#{date_regex}/)
249
254
  end
250
255
 
251
256
  it 'should remove file in the _posts folder' do
252
- @c.unpublish(@p_path)
253
- File.exist?(@p_path).should be_false
254
- end
255
-
256
- it 'should return path to newly created draft' do
257
- returned = @c.unpublish(@p_path)
258
- determined = Dir.glob("_drafts/*.md").first
259
- returned.should == determined
257
+ c.unpublish(p_path)
258
+ expect(File.exist?(p_path)).to be_false
260
259
  end
261
260
 
262
261
  it 'should create draft with matching slug' do
263
- draft = @c.unpublish(@p_path)
264
-
265
- post_slug = @p_path.match(/#{@date_regex}-(.*)[.]md$/)[1]
262
+ draft = c.unpublish(p_path)
263
+ post_slug = p_path.match(/#{date_regex}-(.*)[.]md$/)[1]
266
264
  draft_slug = File.basename(draft, '.md')
267
-
268
- draft_slug.should == post_slug
265
+ expect(draft_slug).to eq(post_slug)
269
266
  end
270
267
 
271
268
  it 'should delete timestamp in actual file' do
272
- draft = @c.unpublish(@p_path)
269
+ draft = c.unpublish(p_path)
273
270
  content = File.open(draft, 'r').read
274
- content.should match(/date:\s*\n/)
271
+ expect(content).to match(/date:\s*\n/)
275
272
  end
276
273
 
277
274
  it 'should copy contents of post into draft' do
278
275
  # first add some content to the draft
279
- f = File.open(@p_path, 'a')
276
+ f = File.open(p_path, 'a')
280
277
  f.write("Some new content for my blog\n")
281
278
  f.close
282
279
 
283
- draft = @c.unpublish(@p_path)
280
+ draft = c.unpublish(p_path)
284
281
  content = File.open(draft, 'r').read
285
- content.should match(/Some new content for my blog/)
282
+ expect(content).to match(/Some new content for my blog/)
286
283
  end
287
284
 
288
285
  end # end describe unpublish
286
+
287
+ context 'with custom extension' do
288
+ let(:commands) { Commands.new('textile') }
289
+
290
+ it 'post should use custom extension' do
291
+ fn = commands.post({title: 'post title'})
292
+ expect(fn).to match(/textile$/)
293
+ end
294
+
295
+ it 'draft should use custom extension' do
296
+ fn = commands.draft({title: 'post title'})
297
+ expect(fn).to match(/textile$/)
298
+ end
299
+
300
+ it 'publish should use custom extension' do
301
+ draft_path = commands.draft({title: 'post title'})
302
+ fn = commands.publish(draft_path)
303
+ expect(fn).to match(/textile$/)
304
+ end
305
+
306
+ it 'unpublish should use custom extension' do
307
+ post_path = commands.post({title: 'post title'})
308
+ fn = commands.unpublish(post_path)
309
+ expect(fn).to match(/textile$/)
310
+ end
311
+
312
+ end
313
+
314
+ context 'with layout override' do
315
+
316
+ it "post should inherit layout's file extension" do
317
+ layout_path = write_custom_layout_textile
318
+ fn = c.post({title: 'post title', layout: layout_path})
319
+ expect(fn).not_to match(/md/)
320
+ expect(fn).to match(/textile$/)
321
+ end
322
+
323
+ it "draft should inherit layout's file extension" do
324
+ layout_path = write_custom_layout_textile
325
+ fn = c.draft({title: 'post title', layout: layout_path})
326
+ expect(fn).not_to match(/md/)
327
+ expect(fn).to match(/textile$/)
328
+ end
329
+
330
+ it "publish should inherit draft's extension" do
331
+ layout_path = write_custom_layout_textile
332
+ draft_path = c.draft({title: 'post title', layout: layout_path})
333
+ fn = c.publish(draft_path)
334
+ expect(fn).not_to match(/md/)
335
+ expect(fn).to match(/textile$/)
336
+ end
337
+
338
+ it "unpublish should inherit post's extension" do
339
+ layout_path = write_custom_layout_textile
340
+ post_path = c.post({title: 'post title', layout: layout_path})
341
+ fn = c.publish(post_path)
342
+ expect(fn).not_to match(/md/)
343
+ expect(fn).to match(/textile$/)
344
+ end
345
+
346
+ end
289
347
  end
290
348
  end
@@ -0,0 +1,58 @@
1
+ require 'spec_helper'
2
+ require 'mr_poole'
3
+
4
+ def write_config_file
5
+ f = File.open('_config.yml', 'w')
6
+ f.puts 'poole:'
7
+ f.puts ' default_layout: _layouts/poole.md'
8
+ f.puts ' default_extension: md'
9
+ f.close
10
+ end
11
+
12
+ def write_config_file_no_poole
13
+ f = File.open('_config.yml', 'w')
14
+ f.puts 'name: Douglas N. Adams'
15
+ f.puts 'description: Life, the universe, and everything'
16
+ f.close
17
+ end
18
+
19
+ module MrPoole
20
+ describe Config do
21
+ before(:each) { @olddir, @tmpdir = make_jekyll_dir }
22
+ after(:each) { clean_tmp_files(@tmpdir, @olddir) }
23
+
24
+ describe '::initialize' do
25
+ it 'is empty with no config file' do
26
+ config = Config.new
27
+ expect(config).to be_empty
28
+ end
29
+
30
+ it "is empty with no 'poole' key in config file" do
31
+ write_config_file_no_poole
32
+ config = Config.new
33
+ expect(config).to be_empty
34
+ end
35
+
36
+ it "is not empty with 'poole' key in config file" do
37
+ write_config_file
38
+ config = Config.new
39
+ expect(config).not_to be_empty
40
+ end
41
+
42
+ end
43
+
44
+ describe '#method_missing' do
45
+ before(:each) { write_config_file }
46
+ let(:config) { Config.new }
47
+
48
+ it 'allows access to defined members' do
49
+ expect(config.default_extension).to eq('md')
50
+ end
51
+
52
+ it 'returns nil for unknown key' do
53
+ expect(config.bogus_key).to be_nil
54
+ end
55
+ end
56
+
57
+ end
58
+ end
data/spec/spec_helper.rb CHANGED
@@ -38,7 +38,7 @@ def clean_tmp_files(tmpdir, restoredir)
38
38
  FileUtils.rm_rf(tmpdir)
39
39
  end
40
40
 
41
- def poole_with_args(argv)
41
+ def poole(argv)
42
42
  return Proc.new do
43
43
  action = argv.shift
44
44
  cli = MrPoole::CLI.new(argv)
@@ -46,7 +46,7 @@ def poole_with_args(argv)
46
46
  end
47
47
  end
48
48
 
49
- def poole_with_args_no_stdout(argv)
49
+ def poole_no_stdout(argv)
50
50
  return Proc.new do
51
51
  capture_stdout do
52
52
  action = argv.shift
@@ -55,3 +55,73 @@ def poole_with_args_no_stdout(argv)
55
55
  end
56
56
  end
57
57
  end
58
+
59
+ # This captures SystemExit exceptions and returns stdout
60
+ def aborted_poole_output(argv)
61
+ return Proc.new do
62
+ output = capture_stdout do
63
+ begin
64
+ action = argv.shift
65
+ cli = MrPoole::CLI.new(argv)
66
+ cli.execute(action)
67
+ rescue SystemExit
68
+ end
69
+ end
70
+ output
71
+ end
72
+ end
73
+
74
+ def write_custom_layout
75
+ filename = 'custom_layout.md'
76
+ f = File.open(filename, 'w')
77
+ f.puts '---'
78
+ f.puts 'title:'
79
+ f.puts 'date:'
80
+ f.puts 'tags: testing'
81
+ f.puts '---'
82
+ f.puts ''
83
+ f.close
84
+
85
+ filename
86
+ end
87
+
88
+ def write_custom_layout_textile
89
+ filename = 'custom_layout.textile'
90
+ f = File.open(filename, 'w')
91
+ f.puts '---'
92
+ f.puts 'title:'
93
+ f.puts 'date:'
94
+ f.puts 'tags: testing'
95
+ f.puts '---'
96
+ f.puts ''
97
+ f.close
98
+
99
+ filename
100
+ end
101
+
102
+ def write_config_file_custom_layout
103
+ filename = 'default_layout.md'
104
+
105
+ l = File.open(filename, 'w')
106
+ l.puts '---'
107
+ l.puts 'title:'
108
+ l.puts 'date:'
109
+ l.puts 'tags: from_config'
110
+ l.puts '---'
111
+ l.puts ''
112
+ l.close
113
+
114
+ c = File.open('_config.yml', 'w')
115
+ c.puts 'poole:'
116
+ c.puts " default_layout: #{filename}"
117
+ c.close
118
+
119
+ filename
120
+ end
121
+
122
+ def write_config_file_custom_extension
123
+ c = File.open('_config.yml', 'w')
124
+ c.puts 'poole:'
125
+ c.puts " default_extension: textile"
126
+ c.close
127
+ end