mindwords 0.6.1 → 0.6.6

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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 1513378395921df0332fa183e9f1bbbb4de0effebaa125ac9cbdaaf5c2043a53
4
- data.tar.gz: 0fdbe75ed727876a2ba3e62c4d67cf9f21bcd64b61cb252cb795b5ae260d0859
3
+ metadata.gz: ec2890a679fe960fc09d401fc33fa57c735b4e8ba940dfa02834880d2f92320a
4
+ data.tar.gz: 2829b18b62650d5f49986113e67e01127331b89e17aaee698219220f3fae6387
5
5
  SHA512:
6
- metadata.gz: 85b57f0e300b6859f4c98a2263920eb5a65014c74711e021f1c52144d6c32c224df4691d8bef4b90b9a69e7f6a95d67e043ccc1100255ac96c6dfe746a592adb
7
- data.tar.gz: dd2ea283e94912e221dfcc463c1f5270ad751b0e7fc968abb6bb19b7dedfe91d29b93fbe3312c96d3726b6d3067b5a7a4d73ee469bf74fc0311423668755edef
6
+ metadata.gz: cd62b5aa44b6227a0028e990369dfa582d0b5c32bbee93969a37456cdc2e787d6d25108d3f4279e1422bd95ce107c01622b9167ab43407c2aa0627a6d0ec2989
7
+ data.tar.gz: af4672aef859de43270d5a16d422815670e7e093282a19c901358d2770fd95276080c1594125a3215c3b0f1ce9b17d9ed6603b6e91dd6ae05b8b2764fb1484cc
checksums.yaml.gz.sig CHANGED
Binary file
data/lib/mindwords.rb CHANGED
@@ -8,44 +8,89 @@ require 'line-tree'
8
8
 
9
9
  module HashCopy
10
10
  refine Hash do
11
-
11
+
12
12
  def deep_clone()
13
13
  Marshal.load(Marshal.dump(self))
14
14
  end
15
-
15
+
16
16
  end
17
17
  end
18
18
 
19
19
  class MindWords
20
20
  using ColouredText
21
21
  using HashCopy
22
-
22
+
23
23
  attr_accessor :lines, :filepath
24
-
24
+
25
25
  def initialize(raws='', parent: nil, debug: false)
26
26
 
27
27
  @parent, @debug = parent, debug
28
-
28
+
29
+ import(raws) if raws.length > 1
30
+
31
+ end
32
+
33
+ def add(s)
34
+
35
+ @lines.concat s.strip.lines
36
+
37
+ end
38
+
39
+ def breadcrumb()
40
+ @parent.attributes[:breadcrumb].split(/ +\/ +/) if @parent
41
+ end
42
+
43
+ def headings()
44
+ breadcrumb[0..-2]
45
+ end
46
+
47
+
48
+ def element(id)
49
+
50
+ doc = Rexle.new(to_xml())
51
+ e = doc.root.element("//*[@id='#{id}']")
52
+ #e.attributes[:breadcrumb].to_s if e
53
+
54
+ end
55
+
56
+ # If title supplied, searches for a requested title and returns the
57
+ # associated hashtags
58
+ # When no title is supplied, it will return the hashtags for the
59
+ # parent element of a search result object
60
+ #
61
+ def hashtags(title=nil)
62
+
63
+ if title then
64
+ found = search(title)
65
+ found.hashtags() if found
66
+ else
67
+ @parent.attributes[:hashtags].split if @parent
68
+ end
69
+
70
+ end
71
+
72
+ def import(raws)
73
+
29
74
  s, type = RXFHelper.read raws
30
-
75
+
31
76
  @filepath = raws if type == :file or type == :dfs
32
- lines = s.strip.gsub(/^\n/,'').lines
33
- lines.shift if lines.first =~ /<\?mindwords\?>/
34
-
77
+ lines = (s.strip.gsub(/(^\n|\r)/,'') + "\n").lines.uniq
78
+ lines.shift if lines.first =~ /<\?mindwords\?>/
79
+
35
80
  @lines = lines.inject([]) do |r,line|
36
-
81
+
37
82
  # the following does 2 things:
38
83
  # 1. splits words separated by a bar (|) onto their own line
39
- # 2. prefixes a word with an underscore if the word is the
40
- # same as the hashtag. That way it's not removed by the
84
+ # 2. prefixes a word with an underscore if the word is the
85
+ # same as the hashtag. That way it's not removed by the
41
86
  # redundancy checker
42
87
 
43
88
  raw_words, raw_hashtags = line.split(/(?= #)/,2)
44
89
  words = raw_words.split(/ *\| */)
45
90
  hashtags = raw_hashtags.scan(/(?<=#)\w+/)
46
-
47
- words.each do |word|
48
-
91
+
92
+ words.each do |word|
93
+
49
94
  linex = (word + raw_hashtags)
50
95
  r << (hashtags.include?(word) ? linex.sub!(/\b#{word}\b/, '_\0') \
51
96
  : linex)
@@ -53,54 +98,47 @@ class MindWords
53
98
 
54
99
  r
55
100
  end
56
-
57
- end
58
-
59
- def add(line)
60
- @lines << line
61
- end
62
-
63
- def breadcrumb()
64
- @parent.attributes[:breadcrumb].split(/ +\/ +/) if @parent
65
101
  end
66
-
67
- def headings()
68
- breadcrumb[0..-2]
69
- end
70
-
71
-
72
- def element(id)
73
-
74
- doc = Rexle.new(to_xml())
75
- e = doc.root.element("//*[@id='#{id}']")
76
- #e.attributes[:breadcrumb].to_s if e
77
-
102
+
103
+ # helpful when searching for a word itself using autosuggest
104
+ #
105
+ def lookup(s)
106
+ self.to_words.keys.sort.grep /^#{s}/i
78
107
  end
79
-
80
- def hashtags()
81
- @parent.attributes[:hashtags].split if @parent
108
+
109
+ # same as #lines but inludes the breadcrumb path; Helpful to identify
110
+ # which words don't have a breadcrumb path.
111
+ #
112
+ def linesplus()
113
+
114
+ to_a.map do |word, _|
115
+ r = search word
116
+ r ? [word, r.breadcrumb] : [r, nil]
117
+ end
118
+
82
119
  end
83
120
 
84
121
  def save(file=@filepath)
85
-
122
+
86
123
  return if @lines.empty?
87
-
124
+
88
125
  puts 'before save' if @debug
126
+
89
127
  File.write file, to_s()
90
-
128
+
91
129
  end
92
130
 
93
- # Accepts a list of words with the aim of returning a MindWords document
131
+ # Accepts a list of words with the aim of returning a MindWords document
94
132
  # using matched words with hashtags from the existing MindWords document.
95
133
  #
96
134
  def reflect(raws)
97
-
135
+
98
136
  h = to_h
99
-
137
+
100
138
  missing_words = []
101
-
139
+
102
140
  # add the tags from the main list
103
- a = raws.strip.lines.map do |x|
141
+ a = raws.strip.lines.map do |x|
104
142
  if h[x.chomp] then
105
143
  [x.chomp, h[x.chomp]]
106
144
  else
@@ -122,153 +160,162 @@ class MindWords
122
160
  raws3 = a.uniq.map {|s,tags| [s, tags.map {|x| '#' + x }.join(' ')].join(' ') }.join("\n")
123
161
 
124
162
  [MindWords.new(raws3), missing_words]
125
-
163
+
126
164
  end
127
-
165
+
128
166
  def search(keyword, succinct: true)
129
-
167
+
130
168
  a = @lines.grep(/#{keyword}/i).map do |line|
131
-
169
+
132
170
  puts 'line: ' + line.inspect if @debug
133
-
171
+
134
172
  words = line.split
135
173
  r = words.grep /#{keyword}/i
136
174
  i = words.index r[0]
137
-
175
+
138
176
  [line, i]
139
-
177
+
140
178
  end
141
-
179
+
142
180
  return nil if a.empty?
143
181
  #return a[0][0] if a.length < 2
144
182
 
145
183
  a2 = a.sort_by(&:last).map(&:first)
146
184
  puts 'a2: ' + a2.inspect if @debug
147
185
  e = element(keyword.downcase.gsub(/ +/,'-'))
148
-
186
+
149
187
  return MindWords.new(a2.uniq.join, debug: @debug) if e.nil?
150
188
 
151
189
  # find and add any linkage support lines
152
190
  #
153
-
191
+
154
192
  a3 = []
155
193
 
156
194
  a2.each do |line|
157
-
195
+
158
196
  line.chomp.scan(/#[^ ]+/).each do |hashtag|
159
-
197
+
160
198
  puts 'hashtag: ' + hashtag.inspect if @debug
161
199
  r2 = @lines.grep(/^#{hashtag[1..-1]} #/)
162
- a3 << r2.first if r2
163
-
200
+ a3 << r2.first if r2
201
+
164
202
  end
165
203
  end
166
204
 
167
205
  puts 'a2: ' + a2.inspect if @debug
168
206
  a2.concat a3
169
-
207
+
170
208
  if succinct then
171
209
  MindWords.new(a2.uniq.join, parent: e, debug: @debug)
172
210
  else
173
211
  MindWords.new(a2.uniq.join, debug: @debug)
174
212
  end
175
-
213
+
176
214
  end
177
-
215
+
178
216
  def sort()
179
217
  s = @lines.sort.join
180
-
218
+
181
219
  def s.to_s()
182
220
  self.lines.map do |x|
183
221
  title, hashtags = x.split(/(?=#)/,2)
184
222
  title + hashtags.chomp.brown
185
223
  end.join("\n")
186
- end
187
-
224
+ end
225
+
188
226
  return s
189
227
  end
190
-
228
+
191
229
  def sort!()
192
230
  @lines = sort().lines
193
231
  self
194
232
  end
195
-
233
+
196
234
  def tag_sort()
197
-
198
- h = @lines.group_by {|x| x[/#\w+/]}
235
+
236
+ h = @lines.group_by {|x| x[/#\w+/]}
199
237
  s = h.sort.map {|key, value| value.sort }.join
200
-
238
+
201
239
  def s.to_s()
202
240
  self.lines.map do |x|
203
241
  title, hashtags = x.split(/(?=#)/,2)
204
242
  title + hashtags.chomp.brown
205
243
  end.join("\n")
206
244
  end
207
-
245
+
208
246
  return s
209
-
247
+
210
248
  end
211
-
249
+
212
250
  def tag_sort!()
213
251
  @lines = tag_sort().lines
214
252
  self
215
253
  end
216
254
 
217
255
  def to_a()
218
-
219
- @lines.map do |x|
256
+
257
+ @lines.map do |x|
220
258
  s, rawtags = x.split(/(?= #)/,2)
221
259
  [s, rawtags.scan(/(?<=#)\w+/)]
222
260
  end
223
-
261
+
224
262
  end
225
-
263
+
226
264
  def to_h()
227
265
  to_a.to_h
228
266
  end
229
-
267
+
230
268
  def to_hashtags()
231
269
  @hashtags
232
270
  end
233
271
 
234
272
  def to_outline(sort: true)
273
+
235
274
  build()
236
- sort ? a2tree(tree_sort(LineTree.new(@outline).to_a)) : @outline
275
+
276
+ if sort then
277
+ a = LineTree.new(@outline).to_a
278
+ puts ('a: ' + a.inspect).debug if @debug
279
+ a2tree(tree_sort(a))
280
+ else
281
+ @outline
282
+ end
283
+
237
284
  end
238
-
285
+
239
286
  alias to_tree to_outline
240
-
287
+
241
288
  def to_s(colour: false)
242
-
289
+
243
290
  header = "<?mindwords?>\n\n"
244
291
  return header + @lines.map(&:chomp).join("\n") unless colour
245
-
292
+
246
293
  body = @lines.map do |x|
247
294
  title, hashtags = x.split(/(?=#)/,2)
248
295
  title + hashtags.chomp.brown
249
296
  end.join("\n")
250
-
297
+
251
298
  header + body
252
-
253
- end
254
-
299
+
300
+ end
301
+
255
302
  def to_words()
256
-
303
+
257
304
  h = {}
258
-
305
+
259
306
  Rexle.new(to_xml).root.each_recursive do |e|
260
-
307
+
261
308
  h[e.attributes[:title]] = {
262
- breadcrumb: e.attributes[:breadcrumb],
309
+ breadcrumb: e.attributes[:breadcrumb],
263
310
  hashtags: e.attributes[:hashtags]
264
311
  }
265
-
312
+
266
313
  end
267
-
314
+
268
315
  h
269
-
270
- end
271
-
316
+
317
+ end
318
+
272
319
  def to_xml()
273
320
  build() unless @xml
274
321
  @xml
@@ -277,13 +324,13 @@ class MindWords
277
324
  private
278
325
 
279
326
  def build()
280
-
327
+
281
328
  h = {}
282
329
 
283
330
  @lines.each do |line|
284
331
 
285
332
  title, rawtags = line.split(/(?= #)/,2)
286
-
333
+
287
334
  rawtags.scan(/#(\w+)/).flatten(1).each do |rawtag|
288
335
  tag = rawtag.gsub(/ +/, '_')
289
336
  h[tag] ||= []
@@ -291,32 +338,32 @@ class MindWords
291
338
  end
292
339
 
293
340
  end
294
-
341
+
295
342
  @hashtags = h.deep_clone.sort.map {|tag, fields| [tag, fields.sort]}.to_h
296
343
 
297
-
344
+
298
345
  a = rexlize(h)
299
346
  doc = Rexle.new(['root', {}, '', *a])
300
347
 
301
348
  # apply node nesting
302
349
 
303
350
  doc.root.elements.each do |e|
304
-
351
+
305
352
  doc.root.xpath('//' + e.name).each do |e2|
306
-
353
+
307
354
  next if e2 === e
308
-
355
+
309
356
  e2.parent.add e
310
357
  e2.delete
311
-
358
+
312
359
  end
313
-
360
+
314
361
  end
315
362
 
316
-
363
+
317
364
  # remove duplicates which appear in the same branch above the nested node
318
365
  rm_duplicates(doc)
319
-
366
+
320
367
  # remove redundant nodes (outsiders)
321
368
  # a redundant node is where all children exist in existing nested nodes
322
369
 
@@ -330,57 +377,59 @@ class MindWords
330
377
 
331
378
  end
332
379
 
380
+ puts 'redundants: ' + redundants.inspect if @debug
381
+
333
382
  redundants.compact.each {|x| doc.element(x).delete }
334
-
383
+
335
384
  node = if @parent then
336
385
  found = doc.root.element('//' + @parent.name)
337
386
  found ? found.parent : doc.root
338
387
  else
339
388
  doc.root
340
389
  end
341
-
342
- # the following removes any undescore prefix from words which were the
390
+
391
+ # the following removes any undescore prefix from words which were the
343
392
  # same as the hashtag
344
-
393
+
345
394
  node.root.each_recursive do |e|
346
395
 
347
396
  next unless e
348
397
  puts 'e: ' + e.inspect if @debug
349
-
398
+
350
399
  e.attributes[:id] = e.attributes[:id].sub(/^_/,'') if e.attributes[:id]
351
400
  e.attributes[:title] = e.attributes[:title].sub(/^_/,'') if e.attributes[:title]
352
401
  e.value = e.value.sub(/^_/,'')
353
402
  e.name = e.name.sub(/^_/,'')
354
-
355
- end
356
-
403
+
404
+ end
405
+
357
406
  # ----
358
-
407
+
359
408
  @outline = treeize node
360
-
409
+
361
410
  node.root.each_recursive do |e|
362
-
363
- e.attributes[:id] = e.attributes[:title].downcase.gsub(/ +/,'-')
364
-
411
+
412
+ e.attributes[:id] = e.attributes[:title].downcase.gsub(/ +/,'-')
413
+
365
414
  s = e.parent.attributes[:breadcrumb] ? \
366
415
  e.parent.attributes[:breadcrumb].to_s + ' / ' : ''
367
416
  e.attributes[:breadcrumb] = s + e.value.strip
368
-
417
+
369
418
  r = @lines.grep(/^#{e.attributes[:title]} #/i)
370
419
  next unless r.any?
371
420
  e.attributes[:hashtags] = r[0].scan(/(?<=#)\w+/).join(' ')
372
421
 
373
-
422
+
374
423
  end
375
-
424
+
376
425
  @xml = node.xml pretty: true
377
426
 
378
427
  end
379
-
428
+
380
429
  def rexlize(a)
381
-
430
+
382
431
  a.map do |x|
383
-
432
+
384
433
  puts 'x: ' + x.inspect if @debug
385
434
 
386
435
  case x
@@ -388,41 +437,41 @@ class MindWords
388
437
  [x.downcase.gsub(/ +/,''), {title: x}, x]
389
438
  when Hash
390
439
  [
391
- x.keys.first.downcase.gsub(/_/,' '),
392
- {title: x.keys.first},
440
+ x.keys.first.downcase.gsub(/_/,' '),
441
+ {title: x.keys.first},
393
442
  x.keys.first,
394
443
  *rexlize(x.values.first)
395
444
  ]
396
445
  when Array
397
446
  [
398
- x.first.downcase.gsub(/_/,' '),
447
+ x.first.downcase.gsub(/_/,' '),
399
448
  {title: x.first}, x.first, *rexlize(x.last)
400
449
  ]
401
450
  end
402
451
  end
403
452
 
404
453
  end
405
-
454
+
406
455
  def rm_duplicates(doc)
407
-
456
+
408
457
  duplicates = []
409
-
458
+
410
459
  doc.root.each_recursive do |e|
411
460
 
412
461
  rows = e.parent.xpath('//' + e.name)
413
462
  next if rows.length < 2
414
463
 
415
464
  rows[0..-2].each {|e2| duplicates << e.backtrack.to_s }
416
-
465
+
417
466
  end
418
467
 
419
468
  duplicates.each do |path|
420
-
469
+
421
470
  puts 'pathx: ' + path.inspect if @debug
422
471
  e = doc.element(path)
423
472
  e.delete if e
424
-
425
- end
473
+
474
+ end
426
475
 
427
476
  end
428
477
 
@@ -434,13 +483,13 @@ class MindWords
434
483
 
435
484
  puts 'e: ' + e.inspect if @debug
436
485
  if e.is_a? Rexle::Element then
437
- (' ' * indent) + e.value.to_s + "\n" + treeize(e,indent+1)
486
+ (' ' * indent) + e.value.to_s + "\n" + treeize(e,indent+1)
438
487
  end
439
488
  end
440
489
 
441
490
  lines.join
442
491
  end
443
-
492
+
444
493
  def tree_sort(a)
445
494
 
446
495
  if a.first.is_a? Array then
@@ -460,7 +509,7 @@ class MindWords
460
509
  (' ' * indent) + title + "\n" + children
461
510
  end.join
462
511
 
463
- end
512
+ end
464
513
 
465
514
  end
466
515
 
@@ -470,7 +519,7 @@ class MindWordsWidget
470
519
 
471
520
  end
472
521
 
473
-
522
+
474
523
  # can be used for main entries or a words list
475
524
  #
476
525
  def input(content: '', action: 'mwupdate', target: 'icontent')
data.tar.gz.sig CHANGED
Binary file
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: mindwords
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.6.1
4
+ version: 0.6.6
5
5
  platform: ruby
6
6
  authors:
7
7
  - James Robertson
@@ -35,7 +35,7 @@ cert_chain:
35
35
  aWH7D2AmhOpqNwWnPHzWR/yzpigAVTrvpHfRxZleQj6Z/090nIH2KR0RdioMmPFq
36
36
  3+574KQzs/gR9Y5a+iMcvHRN
37
37
  -----END CERTIFICATE-----
38
- date: 2021-04-09 00:00:00.000000000 Z
38
+ date: 2022-01-02 00:00:00.000000000 Z
39
39
  dependencies:
40
40
  - !ruby/object:Gem::Dependency
41
41
  name: line-tree
@@ -46,7 +46,7 @@ dependencies:
46
46
  version: '0.9'
47
47
  - - ">="
48
48
  - !ruby/object:Gem::Version
49
- version: 0.9.2
49
+ version: 0.9.3
50
50
  type: :runtime
51
51
  prerelease: false
52
52
  version_requirements: !ruby/object:Gem::Requirement
@@ -56,7 +56,7 @@ dependencies:
56
56
  version: '0.9'
57
57
  - - ">="
58
58
  - !ruby/object:Gem::Version
59
- version: 0.9.2
59
+ version: 0.9.3
60
60
  - !ruby/object:Gem::Dependency
61
61
  name: rxfhelper
62
62
  requirement: !ruby/object:Gem::Requirement
metadata.gz.sig CHANGED
Binary file