mindwords 0.6.0 → 0.6.5

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