montoc 0.0.1

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.
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 22d841de97a5b5b8e39b3e5827693fe6fb81a3c5
4
+ data.tar.gz: f478d0705f8ddc55f14f1621caa08071f7bc057b
5
+ SHA512:
6
+ metadata.gz: 91687e0f2ea29d6e5933047eba244f5a862bec15ef9d982d6bd29eb3f4aefaf73d7168d60e7c37b8eb892264b3bc51d11a678942ba56afa9be1b02e6106e025e
7
+ data.tar.gz: 3337e1f3fbde5af5675274d94dc1a3624962cba774bb65ce1244c6930adb59659fac250953a88bddc8ed00e1a194b4b5378b92783aafe74bf0b9cf6ae2e18e2e
@@ -0,0 +1,14 @@
1
+ /.bundle/
2
+ /.yardoc
3
+ /Gemfile.lock
4
+ /_yardoc/
5
+ /coverage/
6
+ /doc/
7
+ /pkg/
8
+ /spec/reports/
9
+ /tmp/
10
+ *.bundle
11
+ *.so
12
+ *.o
13
+ *.a
14
+ mkmf.log
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in montoc.gemspec
4
+ gemspec
@@ -0,0 +1,15 @@
1
+ Montoc (Monospace Text Document), a library to modify/format plain text.
2
+ Copyright (C) 2014 Adrian Setyadi
3
+
4
+ This program is free software: you can redistribute it and/or modify it
5
+ under the terms of the GNU General Public License as published by the
6
+ Free Software Foundation, either version 3 of the License, or (at your
7
+ option) any later version.
8
+
9
+ This program is distributed in the hope that it will be useful, but
10
+ WITHOUT ANY WARRANTY; without even the implied warranty of
11
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
12
+ Public License for more details.
13
+
14
+ You should have received a copy of the GNU General Public License along
15
+ with this program. If not, see <http://www.gnu.org/licenses/>.
@@ -0,0 +1,35 @@
1
+ # Montoc
2
+
3
+ Monospace Text Document: convert any plain text to rectangularize text
4
+ (same number of characters per line) or text matrix (two dimensional
5
+ Array of chars) by adding spaces in between the text. Set alignment to
6
+ left, right, center, and justify. You can also reflow the text to the
7
+ specified columns, and many other features.
8
+
9
+ ## Installation
10
+
11
+ Add this line to your application's Gemfile:
12
+
13
+ ```ruby
14
+ gem 'montoc'
15
+ ```
16
+
17
+ And then execute:
18
+
19
+ $ bundle
20
+
21
+ Or install it yourself as:
22
+
23
+ $ gem install montoc
24
+
25
+ ## Usage
26
+
27
+ require 'montoc'
28
+
29
+ ## Contributing
30
+
31
+ 1. Fork it ( https://github.com/styd/montoc/fork )
32
+ 2. Create your feature branch (`git checkout -b my-new-feature`)
33
+ 3. Commit your changes (`git commit -am 'Add some feature'`)
34
+ 4. Push to the branch (`git push origin my-new-feature`)
35
+ 5. Create a new Pull Request
@@ -0,0 +1,2 @@
1
+ require "bundler/gem_tasks"
2
+
@@ -0,0 +1,336 @@
1
+ require "montoc/version"
2
+
3
+ module Montoc
4
+ class TextMatrix
5
+ attr_reader :text, :format
6
+
7
+ def initialize text = ""
8
+ @text = text
9
+ @rows = rows
10
+ @columns = columns
11
+ @format = :virgin
12
+ yield self if block_given?
13
+ end
14
+
15
+ def to_s
16
+ return @text
17
+ end
18
+
19
+ def + string
20
+ @text = squeeze_space
21
+ @text << string.to_s
22
+ @format = :left if @format == :virgin
23
+ method(@format.id2name + "!").call
24
+ return self
25
+ end
26
+
27
+ def text= string
28
+ @original = string
29
+ @text = string
30
+ end
31
+
32
+ # Find the longest lines in text and return the first match.
33
+ # to_s is called from the longest_line to avoid chomp being called
34
+ # from nil, in the case of text = ""
35
+ def longest_line remove_new_line_char = true
36
+ longest_line = squeeze_space.lines.max_by(&:length)
37
+ longest_line = longest_line.to_s.chomp if remove_new_line_char
38
+ return longest_line
39
+ end
40
+
41
+ def rows
42
+ return @text.lines.length
43
+ end
44
+
45
+ def row row_no = 1
46
+ raise ArgumentError, "Row number cannot be lower than 1." \
47
+ if row_no < 1
48
+ matricize
49
+ row_text = text.lines[row_no-1]
50
+ return row_text
51
+ end
52
+
53
+ def columns
54
+ return longest_line.length
55
+ end
56
+
57
+ def column col_no = 1
58
+ raise ArgumentError, "Column number cannot be lower than 1." \
59
+ if col_no < 1
60
+ matricize
61
+ if col_no > columns
62
+ return nil
63
+ end
64
+ column_text = ""
65
+ @text.each_line do |line|
66
+ column_text << line.to_s.chomp[col_no-1]
67
+ end
68
+ return column_text
69
+ end
70
+
71
+ def matricize align = :left, columns = 80
72
+ if !matrix?
73
+ reflow! columns
74
+ method(align.id2name + "!").call
75
+ end
76
+ end
77
+
78
+ def matricize! align = :left, columns = 80
79
+ squeeze_space!
80
+ matricize align, columns
81
+ end
82
+
83
+ def matrix?
84
+ @text.each_line do |line|
85
+ return false if line.to_s.chomp.length != columns
86
+ end
87
+ return true
88
+ end
89
+
90
+ def virginize
91
+ @format = :virgin
92
+ @text = @original
93
+ return self
94
+ end
95
+
96
+ def virgin?
97
+ return true if @format == :virgin
98
+ return false
99
+ end
100
+
101
+ def left
102
+ new_text = squeeze_space.split("\n").map do |line|
103
+ line = line.to_s.ljust columns
104
+ end .join "\n"
105
+ return self.class.new(new_text)
106
+ end
107
+
108
+ def left!
109
+ @text = left.text
110
+ @format = :left
111
+ return self
112
+ end
113
+
114
+ def right
115
+ new_text = squeeze_space.split("\n").map do |line|
116
+ line = line.chomp.strip.rjust columns
117
+ end .join "\n"
118
+ return self.class.new(new_text)
119
+ end
120
+
121
+ def right!
122
+ @text = right.text
123
+ @format = :right
124
+ return self
125
+ end
126
+
127
+ def center
128
+ new_text = squeeze_space.split("\n").map do |line|
129
+ line = line.chomp.strip.rjust columns-(columns-line.length)/2
130
+ line = line.ljust columns
131
+ end .join "\n"
132
+ return self.class.new(new_text)
133
+ end
134
+
135
+ def center!
136
+ @text = center.text
137
+ @format = :center
138
+ return self
139
+ end
140
+
141
+ def squeeze_space
142
+ inter_text = @text
143
+ new_text = "".to_s
144
+ # strip extra space between non-space characters
145
+ inter_text.each_line do |line|
146
+ new_text << line.strip.squeeze(" ") + "\n"
147
+ end
148
+
149
+ return new_text
150
+ end
151
+
152
+ def squeeze_space!
153
+ @text = squeeze_space
154
+ end
155
+
156
+ def space_weight
157
+ # Initialize space position at line 0 as 0
158
+ space_weight = {0=>0}
159
+
160
+ i = 0
161
+ squeeze_space.each_line do |line|
162
+ # Initialize weight carried by a space at space position 0 as 0
163
+ weight = {0=>0}
164
+
165
+ # Space position index in each line starting from 0
166
+ j = 0
167
+
168
+ # Capture weight carried by each space in each line
169
+ # Weight means the total number of characters to the left and right
170
+ # of a space.
171
+ line.tr("\n","").split.each_cons(2) do |left_word, right_word|
172
+ weight[j] = left_word.length + right_word.length if left_word
173
+
174
+ # Move index to next space position
175
+ j += 1
176
+ end
177
+
178
+ # Copy space weight per line to overall space weight hash
179
+ space_weight[i] = weight
180
+ i +=1
181
+ end
182
+
183
+ return space_weight
184
+ # Return format:
185
+ # {line number => {space number => weight, next space number => weight, ...},
186
+ # next line number => {space number => weight, ...},
187
+ # ...}
188
+ # Return example:
189
+ # {0=>{0=>6, 1=>3, 2=>8}, 1=>{0=>4, 1=>8}, 2=>{0=>0}, 3=>{0=>8, 1=>8, 2=>9}}
190
+ # Meaning:
191
+ # Line 0 has 3 spaces with the first and the last space has weight of 6 and
192
+ # 8, respectively. Line 2 is an empty line.
193
+ end
194
+
195
+ def justify left_align_EOP = true
196
+ spacing_priority = {}
197
+ space_weight.each do |line, weights|
198
+ spacing_priority[line] = weights.sort_by do |position, weight|
199
+ weight
200
+ end .reverse.to_h.map do |position, weight|
201
+ position
202
+ end
203
+ end
204
+ # Result example:
205
+ # {0=>[2, 0, 1], 1=>[1, 0], 2=>[0], 3=>[2, 1, 0], 4=>[0]}
206
+
207
+ squeezed_text = squeeze_space
208
+ end_of_para = []
209
+ # Get lines that end paragraphs
210
+ squeezed_text.each_line.with_index do |line, line_index|
211
+ if line =~ /^\s*$/ && line_index != 0
212
+ end_of_para.push(line_index - 1)
213
+ end
214
+ end
215
+
216
+ inter_text = ""
217
+ squeezed_text.each_line.with_index do |line, line_index|
218
+ words_arr = line.split
219
+ words_arr_length = words_arr.length < 2 ? 1 : words_arr.length-1
220
+ spaces_arr = (" ,"*words_arr_length).split(",")
221
+ space_needed = columns-line.tr("\n", "").length
222
+ (0...space_needed).each do |i|
223
+ spaces_arr.length == 0 ? index = i : index = i % spaces_arr.length
224
+ spaces_arr[spacing_priority[line_index][index]] += " "
225
+ end
226
+
227
+ (0...words_arr.length).each do |j|
228
+ inter_text << words_arr[j]
229
+ inter_text << spaces_arr[j] unless j == words_arr.length - 1
230
+ end
231
+
232
+ inter_text << "\n"
233
+ end
234
+
235
+ if left_align_EOP == true
236
+ text_arr = inter_text.split("\n")
237
+ inter_text.each_line.with_index do |line, line_index|
238
+ if end_of_para.include?(line_index) || line == inter_text.lines[-1]
239
+ text_arr[line_index] = line.strip.squeeze(" ").ljust(columns)
240
+ end
241
+ end
242
+ inter_text = text_arr.join("\n")
243
+ end
244
+
245
+ new_text = ""
246
+ inter_text.each_line do |line|
247
+ line = line.tr("\n","")
248
+ line = " ".ljust(columns) if line =~ /^\s*$/
249
+ new_text << line + "\n"
250
+ end
251
+
252
+ # In case line contains only one word, this will add trailing spaces
253
+ newer_text = ""
254
+ new_text.each_line do |line|
255
+ newer_text << line.strip.ljust(columns) + "\n"
256
+ end
257
+ newer_text.chomp!
258
+
259
+ # return new object with new text
260
+ return self.class.new(newer_text)
261
+ end
262
+
263
+ def justify! left_align_EOP = true
264
+ @text = justify(left_align_EOP).text
265
+ @format = :justify
266
+ return self
267
+ end
268
+
269
+ def longest_word
270
+ longest_word = squeeze_space.split.max_by(&:length)
271
+ return longest_word
272
+ end
273
+
274
+ def reflow column_width = `echo $COLUMNS`.to_i
275
+ raise ArgumentError, "Columns cannot be shorter than the longest word." \
276
+ if columns < longest_word.length
277
+ new_text = ""
278
+ text_arr = @text.split(/\n\s*\n/)
279
+ new_paragraph = []
280
+ text_arr.each do |paragraph|
281
+ para = []
282
+ para_arr = paragraph.split(" ")
283
+ while para_arr.length > 0
284
+ line_arr = []
285
+ para_arr.take_while do |word|
286
+ line_arr.push(word)
287
+ line_arr.join(" ").length <= column_width
288
+ end
289
+ line_arr.pop if line_arr.join(" ").length > column_width
290
+ len = line_arr.length
291
+ para_arr.shift(len)
292
+ line = line_arr.join(" ")
293
+ para << line + " \n"
294
+ end
295
+ new_paragraph << para.join
296
+ end
297
+ new_text = new_paragraph.join("\n")
298
+
299
+ unless @format == :virgin
300
+ new_text = self.class.new(new_text).method(@format).call.text
301
+ else
302
+ return self.class.new(new_text).left # default alignment
303
+ end
304
+
305
+ return self.class.new(new_text)
306
+ end
307
+
308
+ def reflow! column_width = `echo $COLUMNS`.to_i
309
+ obj = reflow(column_width)
310
+ @text = obj.text
311
+ @format = obj.format
312
+ return self
313
+ end
314
+
315
+ # Define alias methods
316
+ method_aliases = %w{col column line row cols columns unmatricize
317
+ squeeze_space! unmat squeeze_space! restore
318
+ virginize}
319
+ method_aliases.each_slice(2) do |new_method, ori_method|
320
+ alias_method new_method, ori_method
321
+ end
322
+
323
+ end
324
+ end
325
+
326
+ class String
327
+ def +(other)
328
+ if other.kind_of? Montoc::TextMatrix
329
+ new_text = self + other.text
330
+ return new_text
331
+ end
332
+ result = self.dup
333
+ result << other.to_s
334
+ return result
335
+ end
336
+ end
@@ -0,0 +1,3 @@
1
+ module Montoc
2
+ VERSION = "0.0.1"
3
+ end
@@ -0,0 +1,27 @@
1
+ # coding: utf-8
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'montoc/version'
5
+
6
+ Gem::Specification.new do |spec|
7
+ spec.name = "montoc"
8
+ spec.version = Montoc::VERSION
9
+ spec.authors = ["Adrian Setyadi"]
10
+ spec.email = ["a.styd@yahoo.com"]
11
+ spec.summary = %q{Monospace Text Document}
12
+ spec.description = %q{Monospace Text Document: convert any plain text to rectangularized text
13
+ (same number of characters per line) or text matrix (two dimensional
14
+ Array of chars of the text) by adding spaces in between the text.
15
+ Set alignment to left, right, center, and justify. You can also reflow
16
+ the text to the specified columns, and many other features.}
17
+ spec.homepage = "https://github.com/styd/montoc/"
18
+ spec.license = "GPLv3"
19
+
20
+ spec.files = `git ls-files -z`.split("\x0")
21
+ spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
22
+ spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
23
+ spec.require_paths = ["lib"]
24
+
25
+ spec.add_development_dependency "bundler", "~> 1.6"
26
+ spec.add_development_dependency "rake", "~> 10.0"
27
+ end
metadata ADDED
@@ -0,0 +1,84 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: montoc
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ platform: ruby
6
+ authors:
7
+ - Adrian Setyadi
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2014-08-11 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: bundler
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: '1.6'
20
+ type: :development
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: '1.6'
27
+ - !ruby/object:Gem::Dependency
28
+ name: rake
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - "~>"
32
+ - !ruby/object:Gem::Version
33
+ version: '10.0'
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - "~>"
39
+ - !ruby/object:Gem::Version
40
+ version: '10.0'
41
+ description: "Monospace Text Document: convert any plain text to rectangularized text
42
+ \n(same number of characters per line) or text matrix (two dimensional\nArray of
43
+ chars of the text) by adding spaces in between the text.\nSet alignment to left,
44
+ right, center, and justify. You can also reflow\nthe text to the specified columns,
45
+ and many other features."
46
+ email:
47
+ - a.styd@yahoo.com
48
+ executables: []
49
+ extensions: []
50
+ extra_rdoc_files: []
51
+ files:
52
+ - ".gitignore"
53
+ - Gemfile
54
+ - LICENSE.txt
55
+ - README.md
56
+ - Rakefile
57
+ - lib/montoc.rb
58
+ - lib/montoc/version.rb
59
+ - montoc.gemspec
60
+ homepage: https://github.com/styd/montoc/
61
+ licenses:
62
+ - GPLv3
63
+ metadata: {}
64
+ post_install_message:
65
+ rdoc_options: []
66
+ require_paths:
67
+ - lib
68
+ required_ruby_version: !ruby/object:Gem::Requirement
69
+ requirements:
70
+ - - ">="
71
+ - !ruby/object:Gem::Version
72
+ version: '0'
73
+ required_rubygems_version: !ruby/object:Gem::Requirement
74
+ requirements:
75
+ - - ">="
76
+ - !ruby/object:Gem::Version
77
+ version: '0'
78
+ requirements: []
79
+ rubyforge_project:
80
+ rubygems_version: 2.4.1
81
+ signing_key:
82
+ specification_version: 4
83
+ summary: Monospace Text Document
84
+ test_files: []