doing 2.0.22 → 2.1.0pre

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.
Files changed (88) hide show
  1. checksums.yaml +4 -4
  2. data/.yardoc/checksums +18 -15
  3. data/.yardoc/object_types +0 -0
  4. data/.yardoc/objects/root.dat +0 -0
  5. data/CHANGELOG.md +36 -1
  6. data/Gemfile.lock +8 -1
  7. data/README.md +7 -1
  8. data/Rakefile +23 -4
  9. data/bin/doing +323 -173
  10. data/doc/Array.html +354 -1
  11. data/doc/Doing/Color.html +104 -92
  12. data/doc/Doing/Completion.html +216 -0
  13. data/doc/Doing/Configuration.html +340 -5
  14. data/doc/Doing/Content.html +229 -0
  15. data/doc/Doing/Errors/DoingNoTraceError.html +1 -1
  16. data/doc/Doing/Errors/DoingRuntimeError.html +1 -1
  17. data/doc/Doing/Errors/DoingStandardError.html +1 -1
  18. data/doc/Doing/Errors/EmptyInput.html +1 -1
  19. data/doc/Doing/Errors/NoResults.html +1 -1
  20. data/doc/Doing/Errors/PluginException.html +1 -1
  21. data/doc/Doing/Errors/UserCancelled.html +1 -1
  22. data/doc/Doing/Errors/WrongCommand.html +1 -1
  23. data/doc/Doing/Errors.html +1 -1
  24. data/doc/Doing/Hooks.html +1 -1
  25. data/doc/Doing/Item.html +337 -49
  26. data/doc/Doing/Items.html +444 -35
  27. data/doc/Doing/LogAdapter.html +139 -51
  28. data/doc/Doing/Note.html +253 -22
  29. data/doc/Doing/Pager.html +74 -36
  30. data/doc/Doing/Plugins.html +1 -1
  31. data/doc/Doing/Prompt.html +674 -0
  32. data/doc/Doing/Section.html +354 -0
  33. data/doc/Doing/Util.html +57 -1
  34. data/doc/Doing/WWID.html +477 -670
  35. data/doc/Doing/WWIDFile.html +398 -0
  36. data/doc/Doing.html +5 -5
  37. data/doc/GLI/Commands/MarkdownDocumentListener.html +1 -1
  38. data/doc/GLI/Commands.html +1 -1
  39. data/doc/GLI.html +1 -1
  40. data/doc/Hash.html +97 -1
  41. data/doc/Status.html +37 -3
  42. data/doc/String.html +599 -23
  43. data/doc/Symbol.html +3 -3
  44. data/doc/Time.html +1 -1
  45. data/doc/_index.html +22 -1
  46. data/doc/class_list.html +1 -1
  47. data/doc/file.README.html +8 -2
  48. data/doc/index.html +8 -2
  49. data/doc/method_list.html +453 -173
  50. data/doc/top-level-namespace.html +1 -1
  51. data/doing.gemspec +3 -0
  52. data/doing.rdoc +79 -27
  53. data/example_plugin.rb +5 -5
  54. data/lib/completion/_doing.zsh +42 -42
  55. data/lib/completion/doing.bash +10 -10
  56. data/lib/completion/doing.fish +1 -280
  57. data/lib/doing/array.rb +36 -0
  58. data/lib/doing/colors.rb +70 -66
  59. data/lib/doing/completion/bash_completion.rb +1 -2
  60. data/lib/doing/completion/fish_completion.rb +1 -1
  61. data/lib/doing/completion/zsh_completion.rb +1 -1
  62. data/lib/doing/completion.rb +6 -0
  63. data/lib/doing/configuration.rb +134 -23
  64. data/lib/doing/hash.rb +37 -0
  65. data/lib/doing/item.rb +77 -12
  66. data/lib/doing/items.rb +125 -0
  67. data/lib/doing/log_adapter.rb +58 -4
  68. data/lib/doing/note.rb +53 -1
  69. data/lib/doing/pager.rb +49 -38
  70. data/lib/doing/plugins/export/markdown_export.rb +4 -4
  71. data/lib/doing/plugins/export/template_export.rb +2 -2
  72. data/lib/doing/plugins/import/calendar_import.rb +4 -4
  73. data/lib/doing/plugins/import/doing_import.rb +5 -7
  74. data/lib/doing/plugins/import/timing_import.rb +3 -3
  75. data/lib/doing/prompt.rb +206 -0
  76. data/lib/doing/section.rb +30 -0
  77. data/lib/doing/string.rb +123 -35
  78. data/lib/doing/util.rb +14 -6
  79. data/lib/doing/version.rb +1 -1
  80. data/lib/doing/wwid.rb +307 -614
  81. data/lib/doing.rb +6 -2
  82. data/lib/examples/plugins/capture_thing_import.rb +162 -0
  83. data/rdoc_to_mmd.rb +14 -8
  84. data/scripts/generate_bash_completions.rb +1 -1
  85. data/scripts/generate_fish_completions.rb +1 -1
  86. data/scripts/generate_zsh_completions.rb +1 -1
  87. metadata +73 -5
  88. data/lib/doing/wwidfile.rb +0 -117
data/lib/doing/string.rb CHANGED
@@ -20,8 +20,7 @@ module Doing
20
20
  ## can be separated by up to *distance* characters in
21
21
  ## haystack, spaces indicate unlimited distance.
22
22
  ##
23
- ## @example "this word".to_rx(2) =>
24
- ## /t.{0,3}h.{0,3}i.{0,3}s.{0,3}.*?w.{0,3}o.{0,3}r.{0,3}d/
23
+ ## @example `"this word".to_rx(2) => /t.{0,3}h.{0,3}i.{0,3}s.{0,3}.*?w.{0,3}o.{0,3}r.{0,3}d/`
25
24
  ##
26
25
  ## @param distance [Integer] Allowed distance
27
26
  ## between characters
@@ -63,6 +62,15 @@ module Doing
63
62
  end
64
63
  end
65
64
 
65
+ # Compress multiple spaces to single space
66
+ def compress
67
+ gsub(/ +/, ' ').strip
68
+ end
69
+
70
+ def compress!
71
+ replace compress
72
+ end
73
+
66
74
  ## @param (see #highlight_tags)
67
75
  def highlight_tags!(color = 'yellow')
68
76
  replace highlight_tags(color)
@@ -289,11 +297,29 @@ module Doing
289
297
  title
290
298
  end
291
299
 
292
- def tag!(tag, value: nil, remove: false, rename_to: nil, regex: false, single: false)
293
- replace tag(tag, value: value, remove: remove, rename_to: rename_to, regex: regex, single: single)
300
+ ##
301
+ ## Add, rename, or remove a tag in place
302
+ ##
303
+ ## @see #tag
304
+ ##
305
+ def tag!(tag, **options)
306
+ replace tag(tag, **options)
294
307
  end
295
308
 
296
- def tag(tag, value: nil, remove: false, rename_to: nil, regex: false, single: false)
309
+ ##
310
+ ## Add, rename, or remove a tag
311
+ ##
312
+ ## @param tag The tag
313
+ ## @param value [String] Value for tag (@tag(value))
314
+ ## @param remove [Boolean] Remove the tag instead of adding
315
+ ## @param rename_to [String] Replace tag with this tag
316
+ ## @param regex [Boolean] Tag is regular expression
317
+ ## @param single [Boolean] Operating on a single item (for logging)
318
+ ## @param force [Boolean] With rename_to, add tag if it doesn't exist
319
+ ##
320
+ ## @return [String] The string with modified tags
321
+ ##
322
+ def tag(tag, value: nil, remove: false, rename_to: nil, regex: false, single: false, force: false)
297
323
  log_level = single ? :info : :debug
298
324
  title = dup
299
325
  title.chomp!
@@ -307,13 +333,14 @@ module Doing
307
333
  end
308
334
 
309
335
  if remove || rename_to
310
- return title unless title =~ /#{rx_tag}(?=[ (]|$)/
336
+ rx = Regexp.new("(?<=^| )@#{rx_tag}(?<parens>\\((?<value>[^)]*)\\))?(?= |$)", case_sensitive)
337
+ m = title.match(rx)
311
338
 
312
- rx = Regexp.new("(^| )@#{rx_tag}(\\([^)]*\\))?(?= |$)", case_sensitive)
313
- if title =~ rx
339
+ if m.nil? && rename_to && force
340
+ title.tag!(rename_to, value: value, single: single)
341
+ elsif m
314
342
  title.gsub!(rx) do
315
- m = Regexp.last_match
316
- rename_to ? "#{m[1]}@#{rename_to}#{m[2]}" : m[1]
343
+ rename_to ? "@#{rename_to}#{value.nil? ? m['parens'] : "(#{value})"}" : ''
317
344
  end
318
345
 
319
346
  title.dedup_tags!
@@ -373,9 +400,16 @@ module Doing
373
400
  title
374
401
  end
375
402
 
376
- # Returns the last escape sequence from a string
403
+ # Returns the last escape sequence from a string.
404
+ #
405
+ # Actually returns all escape codes, with the assumption
406
+ # that the result of inserting them will generate the
407
+ # same color as was set at the end of the string.
408
+ # Because you can send modifiers like dark and bold
409
+ # separate from color codes, only using the last code
410
+ # may not render the same style.
377
411
  #
378
- # @param string The string to examine
412
+ # @return [String] All escape codes in string
379
413
  #
380
414
  def last_color
381
415
  scan(/\e\[[\d;]+m/).join('')
@@ -386,42 +420,62 @@ module Doing
386
420
  ##
387
421
  ## @param opt [Hash] Additional Options
388
422
  ##
389
- def link_urls!(opt = {})
390
- replace link_urls(opt)
423
+ def link_urls!(**opt)
424
+ fmt = opt.fetch(:format, :html)
425
+ replace link_urls(format: fmt)
391
426
  end
392
427
 
393
- def link_urls(opt = {})
394
- opt[:format] ||= :html
395
- str = self.dup
428
+ def link_urls(**opt)
429
+ fmt = opt.fetch(:format, :html)
430
+ return self unless fmt
396
431
 
397
- if :format == :markdown
398
- # Remove <self-linked> formatting
399
- str.gsub!(/<(.*?)>/) do |match|
400
- m = Regexp.last_match
401
- if m[1] =~ /^https?:/
402
- m[1]
403
- else
404
- match
405
- end
432
+ str = dup
433
+
434
+ str = str.remove_self_links if fmt == :markdown
435
+
436
+ str.replace_qualified_urls(format: fmt).clean_unlinked_urls
437
+ end
438
+
439
+ # Remove <self-linked> formatting
440
+ def remove_self_links
441
+ gsub(/<(.*?)>/) do |match|
442
+ m = Regexp.last_match
443
+ if m[1] =~ /^https?:/
444
+ m[1]
445
+ else
446
+ match
406
447
  end
407
448
  end
449
+ end
408
450
 
409
- # Replace qualified urls
410
- str.gsub!(%r{(?mi)(?<!["'\[(\\])((http|https)://)([\w\-_]+(\.[\w\-_]+)+)([\w\-.,@?^=%&amp;:/~+#]*[\w\-@^=%&amp;/~+#])?}) do |_match|
451
+ # Replace qualified urls
452
+ def replace_qualified_urls(**options)
453
+ fmt = options.fetch(:format, :html)
454
+ gsub(%r{(?mi)(?x:
455
+ (?<!["'\[(\\])
456
+ (?<protocol>(?:http|https)://)
457
+ (?<domain>[\w\-]+(?:\.[\w\-]+)+)
458
+ (?<path>[\w\-.,@?^=%&;:/~+#]*[\w\-@^=%&;/~+#])?
459
+ )}) do |_match|
411
460
  m = Regexp.last_match
412
- proto = m[1].nil? ? 'http://' : ''
413
- case opt[:format]
461
+ url = "#{m['domain']}#{m['path']}"
462
+ proto = m['protocol'].nil? ? 'http://' : m['protocol']
463
+ case fmt
464
+ when :terminal
465
+ TTY::Link.link_to("#{proto}#{url}", "#{proto}#{url}")
414
466
  when :html
415
- %(<a href="#{proto}#{m[0]}" title="Link to #{m[0].sub(/^https?:\/\//, '')}">[#{m[3]}]</a>)
467
+ %(<a href="#{proto}#{url}" title="Link to #{m['domain']}">[#{url}]</a>)
416
468
  when :markdown
417
- "[#{m[0]}](#{proto}#{m[0]})"
469
+ "[#{url}](#{proto}#{url})"
418
470
  else
419
471
  m[0]
420
472
  end
421
473
  end
474
+ end
422
475
 
423
- # Clean up unlinked <urls>
424
- str.gsub!(/<(\w+:.*?)>/) do |match|
476
+ # Clean up unlinked <urls>
477
+ def clean_unlinked_urls
478
+ gsub(/<(\w+:.*?)>/) do |match|
425
479
  m = Regexp.last_match
426
480
  if m[1] =~ /<a href/
427
481
  match
@@ -429,8 +483,42 @@ module Doing
429
483
  %(<a href="#{m[1]}" title="Link to #{m[1]}">[link]</a>)
430
484
  end
431
485
  end
486
+ end
432
487
 
433
- str
488
+ def set_type(kind = nil)
489
+ if kind
490
+ case kind.to_s
491
+ when /^a/i
492
+ gsub(/^\[ *| *\]$/, '').split(/ *, */)
493
+ when /^i/i
494
+ to_i
495
+ when /^f/i
496
+ to_f
497
+ when /^sy/i
498
+ sub(/^:/, '').to_sym
499
+ when /^b/i
500
+ self =~ /^(true|yes)$/ ? true : false
501
+ else
502
+ to_s
503
+ end
504
+ else
505
+ case self
506
+ when / *, */
507
+ gsub(/^\[ *| *\]$/, '').split(/ *, */)
508
+ when /^[0-9]+$/
509
+ to_i
510
+ when /^[0-9]+\.[0-9]+$/
511
+ to_f
512
+ when /^:\w+/
513
+ sub(/^:/, '').to_sym
514
+ when /^(true|yes)$/i
515
+ true
516
+ when /^(false|no)$/i
517
+ false
518
+ else
519
+ to_s
520
+ end
521
+ end
434
522
  end
435
523
  end
436
524
  end
data/lib/doing/util.rb CHANGED
@@ -21,11 +21,17 @@ module Doing
21
21
  def exec_available(cli)
22
22
  return false if cli.nil?
23
23
 
24
- if File.exist?(File.expand_path(cli))
25
- File.executable?(File.expand_path(cli))
26
- else
27
- system "which #{cli}", out: File::NULL, err: File::NULL
28
- end
24
+ !TTY::Which.which(cli).nil?
25
+ end
26
+
27
+ ##
28
+ ## Return the first valid executable from a list of commands
29
+ ##
30
+ ## @example `Doing::Util.first_available_exec('bat', 'less -Xr', 'more -r', 'cat')`
31
+ ##
32
+ def first_available_exec(*commands)
33
+ commands.compact.map(&:strip).reject(&:empty?).uniq
34
+ .find { |cmd| exec_available(cmd.split.first) }
29
35
  end
30
36
 
31
37
  def merge_default_proc(target, overwrite)
@@ -116,6 +122,7 @@ module Doing
116
122
 
117
123
  File.open(file, 'w+') do |f|
118
124
  f.puts content
125
+ Doing.logger.debug('Write:', "File written: #{file}")
119
126
  end
120
127
 
121
128
  Hooks.trigger :post_write, file
@@ -183,7 +190,8 @@ module Doing
183
190
  Doing.logger.debug('ENV:', 'No EDITOR environment variable, testing available editors')
184
191
  editors = %w[vim vi code subl mate mvim nano emacs]
185
192
  editors.each do |ed|
186
- return ed if exec_available(ed)
193
+ return TTY::Which.which(ed) if TTY::Which.which(ed)
194
+
187
195
  Doing.logger.debug('ENV:', "#{ed} not available")
188
196
  end
189
197
 
data/lib/doing/version.rb CHANGED
@@ -1,3 +1,3 @@
1
1
  module Doing
2
- VERSION = '2.0.22'
2
+ VERSION = '2.1.0pre'
3
3
  end