mindwords 0.6.4 → 0.6.5

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