doing 2.1.29 → 2.1.33
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.irbrc +1 -0
- data/CHANGELOG.md +4962 -0
- data/Dockerfile-2.6 +3 -1
- data/Dockerfile-2.7 +4 -2
- data/Dockerfile-3.0 +3 -1
- data/Gemfile.lock +2 -67
- data/README.md +1 -1
- data/bash_profile +13 -0
- data/bin/commands/again.rb +1 -1
- data/bin/commands/archive.rb +3 -3
- data/bin/commands/cancel.rb +1 -1
- data/bin/commands/changes.rb +2 -2
- data/bin/commands/commands.rb +8 -8
- data/bin/commands/completion.rb +61 -19
- data/bin/commands/config.rb +20 -17
- data/bin/commands/done.rb +1 -1
- data/bin/commands/flag.rb +1 -1
- data/bin/commands/grep.rb +5 -5
- data/bin/commands/last.rb +1 -1
- data/bin/commands/meanwhile.rb +1 -1
- data/bin/commands/now.rb +1 -1
- data/bin/commands/on.rb +1 -1
- data/bin/commands/open.rb +4 -4
- data/bin/commands/recent.rb +4 -4
- data/bin/commands/show.rb +8 -8
- data/bin/commands/since.rb +1 -1
- data/bin/commands/tag_dir.rb +27 -3
- data/bin/commands/today.rb +1 -1
- data/bin/commands/view.rb +3 -3
- data/bin/commands/yesterday.rb +2 -2
- data/bin/doing +26 -135
- data/docs/doc/Array.html +1 -1
- data/docs/doc/BooleanTermParser/Clause.html +1 -1
- data/docs/doc/BooleanTermParser/Operator.html +1 -1
- data/docs/doc/BooleanTermParser/Query.html +1 -1
- data/docs/doc/BooleanTermParser/QueryParser.html +1 -1
- data/docs/doc/BooleanTermParser/QueryTransformer.html +1 -1
- data/docs/doc/BooleanTermParser.html +1 -1
- data/docs/doc/Doing/Color.html +1 -1
- data/docs/doc/Doing/Completion.html +324 -4
- data/docs/doc/Doing/Configuration.html +3 -3
- data/docs/doc/Doing/Errors/DoingNoTraceError.html +1 -1
- data/docs/doc/Doing/Errors/DoingRuntimeError.html +1 -1
- data/docs/doc/Doing/Errors/DoingStandardError.html +1 -1
- data/docs/doc/Doing/Errors/EmptyInput.html +1 -1
- data/docs/doc/Doing/Errors/NoResults.html +1 -1
- data/docs/doc/Doing/Errors/PluginException.html +1 -1
- data/docs/doc/Doing/Errors/UserCancelled.html +1 -1
- data/docs/doc/Doing/Errors/WrongCommand.html +1 -1
- data/docs/doc/Doing/Errors.html +1 -1
- data/docs/doc/Doing/Hooks.html +1 -1
- data/docs/doc/Doing/Item.html +125 -1
- data/docs/doc/Doing/Items.html +1 -1
- data/docs/doc/Doing/LogAdapter.html +1 -1
- data/docs/doc/Doing/Note.html +109 -3
- data/docs/doc/Doing/Pager.html +1 -1
- data/docs/doc/Doing/Plugins.html +1 -1
- data/docs/doc/Doing/Prompt.html +1 -1
- data/docs/doc/Doing/Section.html +1 -1
- data/docs/doc/Doing/TemplateString.html +1 -1
- data/docs/doc/Doing/Types.html +2 -2
- data/docs/doc/Doing/Util/Backup.html +1 -1
- data/docs/doc/Doing/Util.html +1 -1
- data/docs/doc/Doing/WWID.html +6 -6
- data/docs/doc/Doing.html +2 -2
- data/docs/doc/FalseClass.html +1 -1
- data/docs/doc/GLI/Commands/Help.html +1 -1
- data/docs/doc/GLI/Commands/MarkdownDocumentListener.html +1 -1
- data/docs/doc/GLI/Commands.html +1 -1
- data/docs/doc/GLI.html +1 -1
- data/docs/doc/Hash.html +1 -1
- data/docs/doc/Object.html +1 -1
- data/docs/doc/PhraseParser/Operator.html +1 -1
- data/docs/doc/PhraseParser/PhraseClause.html +1 -1
- data/docs/doc/PhraseParser/Query.html +1 -1
- data/docs/doc/PhraseParser/QueryParser.html +1 -1
- data/docs/doc/PhraseParser/QueryTransformer.html +1 -1
- data/docs/doc/PhraseParser/TermClause.html +1 -1
- data/docs/doc/PhraseParser.html +1 -1
- data/docs/doc/Status.html +1 -1
- data/docs/doc/String.html +1 -1
- data/docs/doc/Symbol.html +1 -1
- data/docs/doc/Time.html +1 -1
- data/docs/doc/TrueClass.html +1 -1
- data/docs/doc/_index.html +3 -1
- data/docs/doc/file.README.html +2 -2
- data/docs/doc/index.html +2 -2
- data/docs/doc/method_list.html +337 -241
- data/docs/doc/top-level-namespace.html +105 -1
- data/docs/index.md +1 -1
- data/doing.gemspec +24 -23
- data/doing.rdoc +34 -13
- data/example_plugin.rb +7 -5
- data/inputrc +57 -0
- data/lib/completion/_doing.zsh +46 -46
- data/lib/completion/doing.bash +2 -2
- data/lib/completion/doing.fish +4 -4
- data/lib/doing/add_options.rb +117 -0
- data/lib/doing/array/array.rb +16 -0
- data/lib/doing/changelog/changes.rb +8 -6
- data/lib/doing/changelog/version.rb +11 -3
- data/lib/doing/completion/bash_completion.rb +12 -51
- data/lib/doing/completion/fish_completion.rb +17 -53
- data/lib/doing/completion/zsh_completion.rb +21 -54
- data/lib/doing/completion.rb +203 -17
- data/lib/doing/configuration.rb +12 -6
- data/lib/doing/item.rb +21 -3
- data/lib/doing/items.rb +5 -5
- data/lib/doing/note.rb +24 -8
- data/lib/doing/plugins/export/dayone_export.rb +8 -6
- data/lib/doing/plugins/export/html_export.rb +4 -4
- data/lib/doing/plugins/export/json_export.rb +19 -20
- data/lib/doing/plugins/export/markdown_export.rb +2 -2
- data/lib/doing/plugins/export/template_export.rb +4 -4
- data/lib/doing/plugins/import/calendar_import.rb +1 -1
- data/lib/doing/plugins/import/doing_import.rb +1 -1
- data/lib/doing/plugins/import/timing_import.rb +1 -1
- data/lib/doing/section.rb +1 -1
- data/lib/doing/string/highlight.rb +3 -4
- data/lib/doing/string/string.rb +8 -0
- data/lib/doing/types.rb +1 -1
- data/lib/doing/util.rb +1 -1
- data/lib/doing/util_backup.rb +12 -12
- data/lib/doing/version.rb +1 -1
- data/lib/doing/wwid.rb +75 -76
- data/lib/doing.rb +58 -0
- data/lib/examples/commands/wiki.rb +27 -19
- data/lib/helpers/threaded_tests.rb +2 -0
- data/scripts/setting_replace.rb +11 -0
- metadata +107 -102
- data/.yardoc/checksums +0 -29
- data/.yardoc/complete +0 -0
- data/.yardoc/object_types +0 -0
- data/.yardoc/objects/root.dat +0 -0
- data/.yardoc/proxy_types +0 -0
data/lib/doing/item.rb
CHANGED
@@ -272,7 +272,7 @@ module Doing
|
|
272
272
|
end
|
273
273
|
|
274
274
|
def highlight_search(search, distance: nil, negate: false, case_type: nil)
|
275
|
-
prefs = Doing.
|
275
|
+
prefs = Doing.setting('search', {})
|
276
276
|
matching = prefs.fetch('matching', 'pattern').normalize_matching
|
277
277
|
distance ||= prefs.fetch('distance', 3).to_i
|
278
278
|
case_type ||= prefs.fetch('case', 'smart').normalize_case
|
@@ -311,7 +311,7 @@ module Doing
|
|
311
311
|
## @return [Boolean] matches search criteria
|
312
312
|
##
|
313
313
|
def search(search, distance: nil, negate: false, case_type: nil)
|
314
|
-
prefs = Doing.
|
314
|
+
prefs = Doing.setting('search', {})
|
315
315
|
matching = prefs.fetch('matching', 'pattern').normalize_matching
|
316
316
|
distance ||= prefs.fetch('distance', 3).to_i
|
317
317
|
case_type ||= prefs.fetch('case', 'smart').normalize_case
|
@@ -354,6 +354,24 @@ module Doing
|
|
354
354
|
negate ? !matches : matches
|
355
355
|
end
|
356
356
|
|
357
|
+
##
|
358
|
+
## Test if item has a @done tag
|
359
|
+
##
|
360
|
+
## @return [Boolean] true item has @done tag
|
361
|
+
##
|
362
|
+
def finished?
|
363
|
+
tags?('done')
|
364
|
+
end
|
365
|
+
|
366
|
+
##
|
367
|
+
## Test if item does not contain @done tag
|
368
|
+
##
|
369
|
+
## @return [Boolean] true if item is missing @done tag
|
370
|
+
##
|
371
|
+
def unfinished?
|
372
|
+
tags?('done', negate: true)
|
373
|
+
end
|
374
|
+
|
357
375
|
##
|
358
376
|
## Test if item is included in never_finish config and
|
359
377
|
## thus should not receive a @done tag
|
@@ -436,7 +454,7 @@ module Doing
|
|
436
454
|
private
|
437
455
|
|
438
456
|
def should?(key)
|
439
|
-
config = Doing.
|
457
|
+
config = Doing.settings
|
440
458
|
return true unless config[key].is_a?(Array)
|
441
459
|
|
442
460
|
config[key].each do |tag|
|
data/lib/doing/items.rb
CHANGED
@@ -131,9 +131,9 @@ module Doing
|
|
131
131
|
out = []
|
132
132
|
@sections.each do |section|
|
133
133
|
out.push(section.original)
|
134
|
-
items = in_section(section.title).sort_by
|
135
|
-
items.reverse! if Doing.
|
136
|
-
items.each { |item| out.push(item.to_s)}
|
134
|
+
items = in_section(section.title).sort_by(&:date)
|
135
|
+
items.reverse! if Doing.setting('doing_file_sort').normalize_order == :desc
|
136
|
+
items.each { |item| out.push(item.to_s) }
|
137
137
|
end
|
138
138
|
|
139
139
|
out.join("\n")
|
@@ -141,8 +141,8 @@ module Doing
|
|
141
141
|
|
142
142
|
# @private
|
143
143
|
def inspect
|
144
|
-
|
144
|
+
sections = @sections.map { |s| "<Section:#{s.title} #{in_section(s.title).count} items>" }.join(', ')
|
145
|
+
"#<Doing::Items #{count} items, #{@sections.count} sections: #{sections}>"
|
145
146
|
end
|
146
|
-
|
147
147
|
end
|
148
148
|
end
|
data/lib/doing/note.rb
CHANGED
@@ -5,7 +5,6 @@ module Doing
|
|
5
5
|
## This class describes an item note.
|
6
6
|
##
|
7
7
|
class Note < Array
|
8
|
-
|
9
8
|
##
|
10
9
|
## Initializes a new note
|
11
10
|
##
|
@@ -28,9 +27,10 @@ module Doing
|
|
28
27
|
##
|
29
28
|
def add(note, replace: false)
|
30
29
|
clear if replace
|
31
|
-
|
30
|
+
case note
|
31
|
+
when String
|
32
32
|
append_string(note)
|
33
|
-
|
33
|
+
when Array
|
34
34
|
append(note)
|
35
35
|
end
|
36
36
|
end
|
@@ -55,7 +55,7 @@ module Doing
|
|
55
55
|
## @return [Array] Stripped note
|
56
56
|
##
|
57
57
|
def strip_lines
|
58
|
-
map(&:strip)
|
58
|
+
Note.new(map(&:strip))
|
59
59
|
end
|
60
60
|
|
61
61
|
def strip_lines!
|
@@ -64,8 +64,24 @@ module Doing
|
|
64
64
|
|
65
65
|
##
|
66
66
|
## Note as multi-line string
|
67
|
-
|
68
|
-
|
67
|
+
##
|
68
|
+
## @param prefix [String] prefix for each line (default two tabs, TaskPaper format)
|
69
|
+
##
|
70
|
+
def to_s(prefix: "\t\t")
|
71
|
+
compress.strip_lines.map { |l| "#{prefix}#{l}" }.join("\n")
|
72
|
+
end
|
73
|
+
|
74
|
+
##
|
75
|
+
## Returns note as a single line, newlines separated by
|
76
|
+
## space
|
77
|
+
##
|
78
|
+
## @return [String] Line representation of the Note.
|
79
|
+
##
|
80
|
+
## @param separator The separator with which to
|
81
|
+
## join multiple lines
|
82
|
+
##
|
83
|
+
def to_line(separator: ' ')
|
84
|
+
compress.strip_lines.join(separator)
|
69
85
|
end
|
70
86
|
|
71
87
|
# @private
|
@@ -94,7 +110,7 @@ module Doing
|
|
94
110
|
## @param lines [Array] Array of strings
|
95
111
|
##
|
96
112
|
def append(lines)
|
97
|
-
concat(lines)
|
113
|
+
concat(lines.utf8)
|
98
114
|
replace compress
|
99
115
|
end
|
100
116
|
|
@@ -105,7 +121,7 @@ module Doing
|
|
105
121
|
## newlines will be split
|
106
122
|
##
|
107
123
|
def append_string(input)
|
108
|
-
concat(input.split(/\n/).map(&:strip))
|
124
|
+
concat(input.utf8.split(/\n/).map(&:strip))
|
109
125
|
replace compress
|
110
126
|
end
|
111
127
|
end
|
@@ -45,7 +45,9 @@ module Doing
|
|
45
45
|
|
46
46
|
def self.render(wwid, items, variables: {})
|
47
47
|
|
48
|
-
return
|
48
|
+
return unless items.good?
|
49
|
+
|
50
|
+
config = Doing.settings
|
49
51
|
|
50
52
|
opt = variables[:options]
|
51
53
|
trigger = opt[:output]
|
@@ -78,7 +80,7 @@ module Doing
|
|
78
80
|
title = "#{title} @section(#{i.section})" unless variables[:is_single]
|
79
81
|
|
80
82
|
tags.concat(i.tag_array).sort!.uniq!
|
81
|
-
flagged = day_flagged = true if i.tags?(
|
83
|
+
flagged = day_flagged = true if i.tags?(config['marker_tag'])
|
82
84
|
|
83
85
|
interval = wwid.get_interval(i, record: true) if i.title =~ /@done\((\d{4}-\d\d-\d\d \d\d:\d\d.*?)\)/ && opt[:times]
|
84
86
|
interval ||= false
|
@@ -123,8 +125,8 @@ module Doing
|
|
123
125
|
end
|
124
126
|
|
125
127
|
|
126
|
-
template = if
|
127
|
-
IO.read(File.expand_path(
|
128
|
+
template = if config['export_templates']['dayone'] && File.exist?(File.expand_path(config['export_templates']['dayone']))
|
129
|
+
IO.read(File.expand_path(config['export_templates']['dayone']))
|
128
130
|
else
|
129
131
|
self.template('dayone')
|
130
132
|
end
|
@@ -144,8 +146,8 @@ module Doing
|
|
144
146
|
starred: hsh[:starred])
|
145
147
|
end
|
146
148
|
when :entries
|
147
|
-
entry_template = if
|
148
|
-
IO.read(File.expand_path(
|
149
|
+
entry_template = if config['export_templates']['dayone_entry'] && File.exist?(File.expand_path(config['export_templates']['dayone_entry']))
|
150
|
+
IO.read(File.expand_path(config['export_templates']['dayone_entry']))
|
149
151
|
else
|
150
152
|
self.template('dayone-entry')
|
151
153
|
end
|
@@ -58,14 +58,14 @@ module Doing
|
|
58
58
|
}
|
59
59
|
end
|
60
60
|
|
61
|
-
template = if
|
62
|
-
IO.read(File.expand_path(
|
61
|
+
template = if Doing.setting('export_templates.haml') && File.exist?(File.expand_path(Doing.setting('export_templates.haml')))
|
62
|
+
IO.read(File.expand_path(Doing.setting('export_templates.haml')))
|
63
63
|
else
|
64
64
|
self.template('html')
|
65
65
|
end
|
66
66
|
|
67
|
-
style = if
|
68
|
-
IO.read(File.expand_path(
|
67
|
+
style = if Doing.setting('export_templates.css') && File.exist?(File.expand_path(Doing.setting('export_templates.css')))
|
68
|
+
IO.read(File.expand_path(Doing.setting('export_templates.css')))
|
69
69
|
else
|
70
70
|
self.template('css')
|
71
71
|
end
|
@@ -29,16 +29,12 @@ module Doing
|
|
29
29
|
max = last_date.strftime('%F')
|
30
30
|
min = items[0].date.strftime('%F')
|
31
31
|
items.each_with_index do |i, index|
|
32
|
-
|
33
|
-
|
34
|
-
note = i.note.map { |line| line.force_encoding('utf-8').strip } if i.note
|
35
|
-
else
|
36
|
-
title = i.title
|
37
|
-
note = i.note.map { |line| line.strip } if i.note
|
38
|
-
end
|
32
|
+
title = i.title.utf8
|
33
|
+
note = i.note.utf8
|
39
34
|
|
40
35
|
end_date = i.end_date || ''
|
41
36
|
interval = wwid.get_interval(i, formatted: false) || 0
|
37
|
+
duration = i.duration || 0
|
42
38
|
note ||= ''
|
43
39
|
|
44
40
|
tags = []
|
@@ -49,14 +45,15 @@ module Doing
|
|
49
45
|
attributes[tag[0]] = tag[1] if tag[1]
|
50
46
|
end
|
51
47
|
|
52
|
-
|
53
|
-
|
48
|
+
case opt[:output]
|
49
|
+
when 'json'
|
54
50
|
i = {
|
55
51
|
date: i.date,
|
56
52
|
end_date: end_date,
|
57
53
|
title: title.strip, #+ " #{note}"
|
58
|
-
note: note.
|
54
|
+
note: note.to_s(prefix: ''),
|
59
55
|
time: interval.time_string(format: :clock),
|
56
|
+
duration: duration.time_string(format: :clock),
|
60
57
|
tags: tags
|
61
58
|
}
|
62
59
|
|
@@ -64,7 +61,7 @@ module Doing
|
|
64
61
|
|
65
62
|
items_out << i
|
66
63
|
|
67
|
-
|
64
|
+
when 'timeline'
|
68
65
|
new_item = {
|
69
66
|
'id' => index + 1,
|
70
67
|
'content' => title.strip, #+ " #{note}"
|
@@ -74,26 +71,28 @@ module Doing
|
|
74
71
|
'style' => 'color:#4c566b;background-color:#d8dee9;'
|
75
72
|
}
|
76
73
|
|
77
|
-
|
78
|
-
if interval && interval.to_i > 0
|
74
|
+
if interval.to_i&.positive?
|
79
75
|
new_item['end'] = end_date.strftime('%F %T')
|
80
76
|
if interval.to_i > 3600
|
81
77
|
new_item['type'] = 'range'
|
82
78
|
new_item['style'] = 'color:white;background-color:#a2bf8a;'
|
83
79
|
end
|
84
80
|
end
|
85
|
-
new_item['style'] = 'color:white;background-color:#f7921e;' if i.tags?(
|
81
|
+
new_item['style'] = 'color:white;background-color:#f7921e;' if i.tags?(Doing.setting('marker_tag'))
|
86
82
|
items_out.push(new_item)
|
87
83
|
end
|
88
84
|
end
|
89
|
-
|
85
|
+
case opt[:output]
|
86
|
+
when 'json'
|
90
87
|
Doing.logger.debug('JSON Export:', "#{items_out.count} items output to JSON")
|
91
88
|
JSON.pretty_generate({
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
89
|
+
'section' => variables[:page_title],
|
90
|
+
'items' => items_out,
|
91
|
+
'timers' => wwid.tag_times(format: :json,
|
92
|
+
sort_by: opt[:sort_tags],
|
93
|
+
sort_order: opt[:tag_order])
|
94
|
+
})
|
95
|
+
when 'timeline'
|
97
96
|
template = <<~EOTEMPLATE
|
98
97
|
<!doctype html>
|
99
98
|
<html>
|
@@ -66,8 +66,8 @@ module Doing
|
|
66
66
|
}
|
67
67
|
end
|
68
68
|
|
69
|
-
template = if
|
70
|
-
IO.read(File.expand_path(
|
69
|
+
template = if Doing.setting('export_templates.markdown') && File.exist?(File.expand_path(Doing.setting('export_templates.markdown')))
|
70
|
+
IO.read(File.expand_path(Doing.setting('export_templates.markdown')))
|
71
71
|
else
|
72
72
|
self.template(nil)
|
73
73
|
end
|
@@ -24,8 +24,8 @@ module Doing
|
|
24
24
|
|
25
25
|
out = ''
|
26
26
|
items.each do |item|
|
27
|
-
if opt[:highlight] && item.title =~ /@#{
|
28
|
-
flag = Doing::Color.send(
|
27
|
+
if opt[:highlight] && item.title =~ /@#{Doing.setting('marker_tag')}\b/i
|
28
|
+
flag = Doing::Color.send(Doing.setting('marker_color'))
|
29
29
|
reset = Doing::Color.reset + Doing::Color.default
|
30
30
|
else
|
31
31
|
flag = ''
|
@@ -34,7 +34,7 @@ module Doing
|
|
34
34
|
|
35
35
|
placeholders = {}
|
36
36
|
|
37
|
-
if !item.note.empty? &&
|
37
|
+
if !item.note.empty? && Doing.setting('include_notes')
|
38
38
|
note = item.note.map(&:strip).delete_if(&:empty?)
|
39
39
|
note.map! { |line| "#{line.sub(/^\t*/, '')} " }
|
40
40
|
|
@@ -133,7 +133,7 @@ module Doing
|
|
133
133
|
|
134
134
|
# Doing.logger.debug('Template Export:', "#{items.count} items output to template #{opt[:template]}")
|
135
135
|
if opt[:totals]
|
136
|
-
out += wwid.tag_times(format:
|
136
|
+
out += wwid.tag_times(format: Doing.setting('timer_format').to_sym,
|
137
137
|
sort_by: opt[:sort_tags],
|
138
138
|
sort_order: opt[:tag_order])
|
139
139
|
end
|
@@ -23,7 +23,7 @@ module Doing
|
|
23
23
|
limit_start = options[:start].to_i
|
24
24
|
limit_end = options[:end].to_i
|
25
25
|
|
26
|
-
section = options[:section] ||
|
26
|
+
section = options[:section] || Doing.setting('current_section')
|
27
27
|
options[:no_overlap] ||= false
|
28
28
|
options[:autotag] ||= wwid.auto_tag
|
29
29
|
|
@@ -63,7 +63,7 @@ module Doing
|
|
63
63
|
title.gsub!(/ +/, ' ')
|
64
64
|
title.strip!
|
65
65
|
section = options[:section] || item.section
|
66
|
-
section ||=
|
66
|
+
section ||= Doing.setting('current_section')
|
67
67
|
|
68
68
|
new_item = Item.new(item.date, title, section)
|
69
69
|
new_item.note = item.note
|
@@ -24,7 +24,7 @@ module Doing
|
|
24
24
|
##
|
25
25
|
def self.import(wwid, path, options: {})
|
26
26
|
exit_now! 'Path to JSON report required' if path.nil?
|
27
|
-
section = options[:section] ||
|
27
|
+
section = options[:section] || Doing.setting('current_section')
|
28
28
|
options[:no_overlap] ||= false
|
29
29
|
options[:autotag] ||= wwid.auto_tag
|
30
30
|
wwid.content.add_section(section) unless wwid.content.section?(section)
|
data/lib/doing/section.rb
CHANGED
@@ -35,10 +35,9 @@ module Doing
|
|
35
35
|
|
36
36
|
def highlight_search(search, distance: nil, negate: false, case_type: nil)
|
37
37
|
out = dup
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
case_type ||= prefs.fetch('case', 'smart').normalize_case
|
38
|
+
matching = Doing.setting('search.matching', 'pattern').normalize_matching
|
39
|
+
distance ||= Doing.setting('search.distance', 3).to_i
|
40
|
+
case_type ||= Doing.setting('search.case', 'smart').normalize_case
|
42
41
|
|
43
42
|
if search.rx? || matching == :fuzzy
|
44
43
|
rx = search.to_rx(distance: distance, case_type: case_type)
|
data/lib/doing/string/string.rb
CHANGED
data/lib/doing/types.rb
CHANGED
@@ -11,7 +11,7 @@ module Doing
|
|
11
11
|
REGEX_TIME = /^#{REGEX_CLOCK}$/i.freeze
|
12
12
|
REGEX_DAY = /^(mon|tue|wed|thur?|fri|sat|sun)(\w+(day)?)?$/i.freeze
|
13
13
|
REGEX_RANGE_INDICATOR = ' +(?:to|through|thru|(?:un)?til|-+) +'
|
14
|
-
REGEX_RANGE = /^\S
|
14
|
+
REGEX_RANGE = /^\S+.*?#{REGEX_RANGE_INDICATOR}\S+.*?$/i.freeze
|
15
15
|
REGEX_TIME_RANGE = /^#{REGEX_CLOCK}#{REGEX_RANGE_INDICATOR}#{REGEX_CLOCK}$/i.freeze
|
16
16
|
|
17
17
|
InvalidExportType = Class.new(RuntimeError)
|
data/lib/doing/util.rb
CHANGED
@@ -159,7 +159,7 @@ module Doing
|
|
159
159
|
|
160
160
|
return ENV['EDITOR'] if ENV['DOING_EDITOR_TEST']
|
161
161
|
|
162
|
-
editor_config = Doing.
|
162
|
+
editor_config = Doing.setting('editors')
|
163
163
|
|
164
164
|
if editor_config.is_a?(String)
|
165
165
|
msg = "Please update your configuration, 'editors' should be a mapping."
|
data/lib/doing/util_backup.rb
CHANGED
@@ -30,7 +30,7 @@ module Doing
|
|
30
30
|
## @param limit Maximum number of backups to retain
|
31
31
|
##
|
32
32
|
def clear_redo(filename)
|
33
|
-
filename ||= Doing.
|
33
|
+
filename ||= Doing.setting('doing_file')
|
34
34
|
backups = Dir.glob("undone*___#{File.basename(filename)}", base: backup_dir).sort.reverse
|
35
35
|
backups.each do |file|
|
36
36
|
FileUtils.rm(File.join(backup_dir, file))
|
@@ -44,7 +44,7 @@ module Doing
|
|
44
44
|
## @return [String] filename
|
45
45
|
##
|
46
46
|
def last_backup(filename = nil, count: 1)
|
47
|
-
filename ||= Doing.
|
47
|
+
filename ||= Doing.setting('doing_file')
|
48
48
|
|
49
49
|
backup = get_backups(filename).slice(count - 1)
|
50
50
|
backup.nil? ? nil : File.join(backup_dir, backup)
|
@@ -59,7 +59,7 @@ module Doing
|
|
59
59
|
##
|
60
60
|
def restore_last_backup(filename = nil, count: 1)
|
61
61
|
Doing.logger.benchmark(:restore_backup, :start)
|
62
|
-
filename ||= Doing.
|
62
|
+
filename ||= Doing.setting('doing_file')
|
63
63
|
|
64
64
|
backup_file = last_backup(filename, count: count)
|
65
65
|
raise DoingRuntimeError, 'End of undo history' if backup_file.nil?
|
@@ -77,7 +77,7 @@ module Doing
|
|
77
77
|
## @param filename The filename
|
78
78
|
##
|
79
79
|
def redo_backup(filename = nil, count: 1)
|
80
|
-
filename ||= Doing.
|
80
|
+
filename ||= Doing.setting('doing_file')
|
81
81
|
# redo_file = File.join(backup_dir, "undone___#{File.basename(filename)}")
|
82
82
|
undones = Dir.glob("undone*#{File.basename(filename)}", base: backup_dir).sort.reverse
|
83
83
|
total = undones.count
|
@@ -101,7 +101,7 @@ module Doing
|
|
101
101
|
end
|
102
102
|
|
103
103
|
def clear_undone(filename = nil)
|
104
|
-
filename ||= Doing.
|
104
|
+
filename ||= Doing.setting('doing_file')
|
105
105
|
# redo_file = File.join(backup_dir, "undone___#{File.basename(filename)}")
|
106
106
|
Dir.glob("undone*#{File.basename(filename)}", base: backup_dir).each do |f|
|
107
107
|
FileUtils.rm(File.join(backup_dir, f))
|
@@ -115,7 +115,7 @@ module Doing
|
|
115
115
|
## @param filename The filename to restore
|
116
116
|
##
|
117
117
|
def select_redo(filename = nil)
|
118
|
-
filename ||= Doing.
|
118
|
+
filename ||= Doing.setting('doing_file')
|
119
119
|
|
120
120
|
undones = Dir.glob("undone*#{File.basename(filename)}", base: backup_dir).sort
|
121
121
|
|
@@ -155,7 +155,7 @@ module Doing
|
|
155
155
|
## @param filename The filename to restore
|
156
156
|
##
|
157
157
|
def select_backup(filename = nil)
|
158
|
-
filename ||= Doing.
|
158
|
+
filename ||= Doing.setting('doing_file')
|
159
159
|
|
160
160
|
options = get_backups(filename).each_with_object([]) do |file, arr|
|
161
161
|
d, _base = date_of_backup(file)
|
@@ -219,7 +219,7 @@ module Doing
|
|
219
219
|
##
|
220
220
|
def write_backup(filename = nil)
|
221
221
|
Doing.logger.benchmark(:_write_backup, :start)
|
222
|
-
filename ||= Doing.
|
222
|
+
filename ||= Doing.setting('doing_file')
|
223
223
|
|
224
224
|
unless File.exist?(filename)
|
225
225
|
Doing.logger.debug('Backup:', "original file doesn't exist (#{filename})")
|
@@ -234,7 +234,7 @@ module Doing
|
|
234
234
|
|
235
235
|
FileUtils.cp(filename, backup_file)
|
236
236
|
|
237
|
-
prune_backups(filename, Doing.
|
237
|
+
prune_backups(filename, Doing.setting('history_size').to_i)
|
238
238
|
clear_undone(filename)
|
239
239
|
Doing.logger.benchmark(:_write_backup, :finish)
|
240
240
|
end
|
@@ -246,13 +246,13 @@ module Doing
|
|
246
246
|
end
|
247
247
|
|
248
248
|
def get_backups(filename = nil, include_forward: false)
|
249
|
-
filename ||= Doing.
|
249
|
+
filename ||= Doing.setting('doing_file')
|
250
250
|
backups = Dir.glob("*___#{File.basename(filename)}", base: backup_dir).sort.reverse
|
251
251
|
backups.delete_if { |f| f =~ /^undone/ } unless include_forward
|
252
252
|
end
|
253
253
|
|
254
254
|
def save_undone(filename = nil)
|
255
|
-
filename ||= Doing.
|
255
|
+
filename ||= Doing.setting('doing_file')
|
256
256
|
undone_file = File.join(backup_dir, "undone#{timestamp_filename}___#{File.basename(filename)}")
|
257
257
|
FileUtils.cp(filename, undone_file)
|
258
258
|
end
|
@@ -279,7 +279,7 @@ module Doing
|
|
279
279
|
end
|
280
280
|
|
281
281
|
def create_backup_dir
|
282
|
-
dir = File.expand_path(Doing.
|
282
|
+
dir = File.expand_path(Doing.setting('backup_dir')) || File.join(user_home, '.doing_backup')
|
283
283
|
if File.exist?(dir) && !File.directory?(dir)
|
284
284
|
raise DoingRuntimeError, "Backup error: #{dir} is not a directory"
|
285
285
|
|
data/lib/doing/version.rb
CHANGED