doing 2.1.10 → 2.1.11
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +20 -0
- data/Dockerfile +9 -0
- data/Dockerfile-2.6 +9 -0
- data/Dockerfile-2.7 +8 -0
- data/Dockerfile-3.0 +8 -0
- data/Gemfile.lock +1 -1
- data/README.md +1 -1
- data/Rakefile +39 -5
- data/bin/doing +2106 -1979
- data/lib/doing/configuration.rb +18 -8
- data/lib/doing/hooks.rb +10 -5
- data/lib/doing/items.rb +16 -1
- data/lib/doing/pager.rb +2 -20
- data/lib/doing/plugins/import/calendar_import.rb +5 -0
- data/lib/doing/plugins/import/doing_import.rb +2 -0
- data/lib/doing/plugins/import/timing_import.rb +5 -0
- data/lib/doing/util_backup.rb +16 -5
- data/lib/doing/version.rb +1 -1
- data/lib/doing/wwid.rb +147 -66
- data/lib/doing.rb +1 -0
- data/lib/examples/plugins/hooks.rb +31 -0
- data/scripts/sort_commands.rb +59 -0
- metadata +7 -2
data/lib/doing/wwid.rb
CHANGED
@@ -114,6 +114,8 @@ module Doing
|
|
114
114
|
filename = @doing_file if filename.nil?
|
115
115
|
return if File.exist?(filename) && File.stat(filename).size.positive?
|
116
116
|
|
117
|
+
FileUtils.mkdir_p(File.dirname(filename)) unless File.directory?(File.dirname(filename))
|
118
|
+
|
117
119
|
File.open(filename, 'w+') do |f|
|
118
120
|
f.puts "#{@config['current_section']}:"
|
119
121
|
end
|
@@ -372,9 +374,13 @@ module Doing
|
|
372
374
|
end
|
373
375
|
end
|
374
376
|
|
377
|
+
Hooks.trigger :pre_entry_add, self, entry
|
378
|
+
|
375
379
|
@content.push(entry)
|
376
380
|
# logger.count(:added, level: :debug)
|
377
381
|
logger.info('New entry:', %(added "#{entry.title}" to #{section}))
|
382
|
+
|
383
|
+
Hooks.trigger :post_entry_added, self, entry.dup
|
378
384
|
end
|
379
385
|
|
380
386
|
##
|
@@ -471,6 +477,7 @@ module Doing
|
|
471
477
|
else
|
472
478
|
item.title.tag!('done')
|
473
479
|
end
|
480
|
+
Hooks.trigger :post_entry_updated, self, item
|
474
481
|
end
|
475
482
|
|
476
483
|
# Remove @done tag
|
@@ -798,6 +805,65 @@ module Doing
|
|
798
805
|
output
|
799
806
|
end
|
800
807
|
|
808
|
+
def delete_items(items, force: false)
|
809
|
+
res = force ? true : Prompt.yn("Delete #{items.size} #{items.size == 1 ? 'item' : 'items'}?", default_response: 'y')
|
810
|
+
if res
|
811
|
+
items.each do |i|
|
812
|
+
deleted = @content.delete_item(i, single: items.count == 1)
|
813
|
+
Hooks.trigger :post_entry_removed, self, deleted
|
814
|
+
end
|
815
|
+
write(@doing_file)
|
816
|
+
end
|
817
|
+
end
|
818
|
+
|
819
|
+
def edit_items(items)
|
820
|
+
editable_items = []
|
821
|
+
|
822
|
+
items.each do |i|
|
823
|
+
editable = "#{i.date.strftime('%F %R')} | #{i.title}"
|
824
|
+
old_note = i.note ? i.note.strip_lines.join("\n") : nil
|
825
|
+
editable += "\n#{old_note}" unless old_note.nil?
|
826
|
+
editable_items << editable
|
827
|
+
end
|
828
|
+
divider = "\n-----------\n"
|
829
|
+
notice =<<~EONOTICE
|
830
|
+
# - You may delete entries, but leave all divider lines (---) in place.
|
831
|
+
# - Start and @done dates replaced with a time string (yesterday 3pm) will
|
832
|
+
# be parsed automatically. Do not delete the pipe (|) between start date
|
833
|
+
# and entry title.
|
834
|
+
EONOTICE
|
835
|
+
input = "#{editable_items.map(&:strip).join(divider)}\n\n#{notice}"
|
836
|
+
|
837
|
+
new_items = fork_editor(input).split(/#{divider}/)
|
838
|
+
|
839
|
+
new_items.each_with_index do |new_item, i|
|
840
|
+
input_lines = new_item.split(/[\n\r]+/).delete_if(&:ignore?)
|
841
|
+
first_line = input_lines[0]&.strip
|
842
|
+
|
843
|
+
if first_line.nil? || first_line =~ /^#{divider.strip}$/ || first_line.strip.empty?
|
844
|
+
deleted = @content.delete_item(items[i], single: new_items.count == 1)
|
845
|
+
Hooks.trigger :post_entry_removed, self, deleted
|
846
|
+
Doing.logger.count(:deleted)
|
847
|
+
else
|
848
|
+
date, title, note = format_input(new_item)
|
849
|
+
|
850
|
+
note.map!(&:strip)
|
851
|
+
note.delete_if(&:ignore?)
|
852
|
+
item = items[i]
|
853
|
+
old_item = item.dup
|
854
|
+
item.date = date || items[i].date
|
855
|
+
item.title = title
|
856
|
+
item.note = note
|
857
|
+
if (item.equal?(old_item))
|
858
|
+
Doing.logger.count(:skipped, level: :debug)
|
859
|
+
else
|
860
|
+
Doing.logger.count(:updated)
|
861
|
+
Hooks.trigger :post_entry_updated, self, item
|
862
|
+
end
|
863
|
+
end
|
864
|
+
end
|
865
|
+
end
|
866
|
+
|
801
867
|
##
|
802
868
|
## Display an interactive menu of entries
|
803
869
|
##
|
@@ -958,7 +1024,7 @@ module Doing
|
|
958
1024
|
|
959
1025
|
item = items[0]
|
960
1026
|
if opt[:resume] && !opt[:reset]
|
961
|
-
repeat_item(item, { editor: opt[:editor] })
|
1027
|
+
repeat_item(item, { editor: opt[:editor] }) # hooked
|
962
1028
|
elsif opt[:reset]
|
963
1029
|
res = Prompt.enter_text('Start date (blank for current time)', default_response: '')
|
964
1030
|
if res =~ /^ *$/
|
@@ -972,7 +1038,9 @@ module Doing
|
|
972
1038
|
else
|
973
1039
|
opt[:resume]
|
974
1040
|
end
|
975
|
-
|
1041
|
+
new_entry = reset_item(item, date: date, resume: res)
|
1042
|
+
@content.update_item(item, new_entry)
|
1043
|
+
Hooks.trigger :post_entry_updated, self, new_entry
|
976
1044
|
end
|
977
1045
|
write(@doing_file)
|
978
1046
|
|
@@ -980,11 +1048,7 @@ module Doing
|
|
980
1048
|
end
|
981
1049
|
|
982
1050
|
if opt[:delete]
|
983
|
-
|
984
|
-
if res
|
985
|
-
items.each { |i| @content.delete_item(i, single: items.count == 1) }
|
986
|
-
write(@doing_file)
|
987
|
-
end
|
1051
|
+
delete_items(items, force: opt[:force]) # hooked
|
988
1052
|
return
|
989
1053
|
end
|
990
1054
|
|
@@ -992,6 +1056,7 @@ module Doing
|
|
992
1056
|
tag = @config['marker_tag'] || 'flagged'
|
993
1057
|
items.map! do |i|
|
994
1058
|
i.tag(tag, date: false, remove: opt[:remove], single: single)
|
1059
|
+
Hooks.trigger :post_entry_updated, self, i
|
995
1060
|
end
|
996
1061
|
end
|
997
1062
|
|
@@ -1001,6 +1066,7 @@ module Doing
|
|
1001
1066
|
if i.should_finish?
|
1002
1067
|
should_date = !opt[:cancel] && i.should_time?
|
1003
1068
|
i.tag(tag, date: should_date, remove: opt[:remove], single: single)
|
1069
|
+
Hooks.trigger :post_entry_updated, self, i
|
1004
1070
|
end
|
1005
1071
|
end
|
1006
1072
|
end
|
@@ -1009,61 +1075,22 @@ module Doing
|
|
1009
1075
|
tag = opt[:tag]
|
1010
1076
|
items.map! do |i|
|
1011
1077
|
i.tag(tag, date: false, remove: opt[:remove], single: single)
|
1078
|
+
Hooks.trigger :post_entry_updated, self, i
|
1012
1079
|
end
|
1013
1080
|
end
|
1014
1081
|
|
1015
1082
|
if opt[:archive] || opt[:move]
|
1016
1083
|
section = opt[:archive] ? 'Archive' : guess_section(opt[:move])
|
1017
|
-
items.map!
|
1084
|
+
items.map! do |i|
|
1085
|
+
i.move_to(section, label: true)
|
1086
|
+
Hooks.trigger :post_entry_updated, self, i
|
1087
|
+
end
|
1018
1088
|
end
|
1019
1089
|
|
1020
1090
|
write(@doing_file)
|
1021
1091
|
|
1022
1092
|
if opt[:editor]
|
1023
|
-
|
1024
|
-
editable_items = []
|
1025
|
-
|
1026
|
-
items.each do |i|
|
1027
|
-
editable = "#{i.date.strftime('%F %R')} | #{i.title}"
|
1028
|
-
old_note = i.note ? i.note.strip_lines.join("\n") : nil
|
1029
|
-
editable += "\n#{old_note}" unless old_note.nil?
|
1030
|
-
editable_items << editable
|
1031
|
-
end
|
1032
|
-
divider = "\n-----------\n"
|
1033
|
-
notice =<<~EONOTICE
|
1034
|
-
# - You may delete entries, but leave all divider lines (---) in place.
|
1035
|
-
# - Start and @done dates replaced with a time string (yesterday 3pm) will
|
1036
|
-
# be parsed automatically. Do not delete the pipe (|) between start date
|
1037
|
-
# and entry title.
|
1038
|
-
EONOTICE
|
1039
|
-
input = "#{editable_items.map(&:strip).join(divider)}\n\n#{notice}"
|
1040
|
-
|
1041
|
-
new_items = fork_editor(input).split(/#{divider}/)
|
1042
|
-
|
1043
|
-
new_items.each_with_index do |new_item, i|
|
1044
|
-
input_lines = new_item.split(/[\n\r]+/).delete_if(&:ignore?)
|
1045
|
-
first_line = input_lines[0]&.strip
|
1046
|
-
|
1047
|
-
if first_line.nil? || first_line =~ /^#{divider.strip}$/ || first_line.strip.empty?
|
1048
|
-
@content.delete_item(items[i], single: new_items.count == 1)
|
1049
|
-
Doing.logger.count(:deleted)
|
1050
|
-
else
|
1051
|
-
date, title, note = format_input(new_item)
|
1052
|
-
|
1053
|
-
note.map!(&:strip)
|
1054
|
-
note.delete_if(&:ignore?)
|
1055
|
-
item = items[i]
|
1056
|
-
old_item = item.dup
|
1057
|
-
item.date = date || items[i].date
|
1058
|
-
item.title = title
|
1059
|
-
item.note = note
|
1060
|
-
if (item.equal?(old_item))
|
1061
|
-
Doing.logger.count(:skipped, level: :debug)
|
1062
|
-
else
|
1063
|
-
Doing.logger.count(:updated)
|
1064
|
-
end
|
1065
|
-
end
|
1066
|
-
end
|
1093
|
+
edit_items(items) # hooked
|
1067
1094
|
|
1068
1095
|
write(@doing_file)
|
1069
1096
|
end
|
@@ -1088,7 +1115,7 @@ module Doing
|
|
1088
1115
|
options[:template] = opt[:template] || nil
|
1089
1116
|
end
|
1090
1117
|
|
1091
|
-
output = list_section(options)
|
1118
|
+
output = list_section(options) # hooked
|
1092
1119
|
|
1093
1120
|
if opt[:save_to]
|
1094
1121
|
file = File.expand_path(opt[:save_to])
|
@@ -1116,7 +1143,7 @@ module Doing
|
|
1116
1143
|
##
|
1117
1144
|
## @see #filter_items
|
1118
1145
|
##
|
1119
|
-
def tag_last(opt)
|
1146
|
+
def tag_last(opt) # hooked
|
1120
1147
|
opt ||= {}
|
1121
1148
|
opt[:count] ||= 1
|
1122
1149
|
opt[:archive] ||= false
|
@@ -1227,6 +1254,8 @@ module Doing
|
|
1227
1254
|
elsif opt[:archive] && opt[:count].zero?
|
1228
1255
|
logger.warn('Skipped:', 'Archiving is skipped when operating on all entries')
|
1229
1256
|
end
|
1257
|
+
|
1258
|
+
Hooks.trigger :post_entry_updated, self, item
|
1230
1259
|
end
|
1231
1260
|
|
1232
1261
|
write(@doing_file)
|
@@ -1280,6 +1309,7 @@ module Doing
|
|
1280
1309
|
item.title = title
|
1281
1310
|
item.note.add(note, replace: true)
|
1282
1311
|
logger.info('Edited:', item.title)
|
1312
|
+
Hooks.trigger :post_entry_updated, self, item.dup
|
1283
1313
|
|
1284
1314
|
write(@doing_file)
|
1285
1315
|
end
|
@@ -1334,8 +1364,10 @@ module Doing
|
|
1334
1364
|
logger.count(:completed)
|
1335
1365
|
logger.info('Completed:', item.title)
|
1336
1366
|
end
|
1367
|
+
Hooks.trigger :post_entry_updated, self, item
|
1337
1368
|
end
|
1338
1369
|
|
1370
|
+
|
1339
1371
|
logger.debug('Skipped:', "No active @#{tag} tasks found.") if found_items.zero?
|
1340
1372
|
|
1341
1373
|
if opt[:new_item]
|
@@ -1393,6 +1425,7 @@ module Doing
|
|
1393
1425
|
|
1394
1426
|
unless ((!tags.empty? && !item.tags?(tags, bool)) || (opt[:search] && !item.search(opt[:search].to_s)) || (opt[:before] && item.date >= cutoff))
|
1395
1427
|
new_item = @content.delete(item)
|
1428
|
+
Hooks.trigger :post_entry_removed, self, item.dup
|
1396
1429
|
raise DoingRuntimeError, "Error deleting item: #{item}" if new_item.nil?
|
1397
1430
|
|
1398
1431
|
new_content.add_section(new_item.section, log: false)
|
@@ -1503,7 +1536,7 @@ module Doing
|
|
1503
1536
|
tpl_cfg = @config.dig('templates', opt[:config_template])
|
1504
1537
|
|
1505
1538
|
cfg = if opt[:view_template]
|
1506
|
-
@config.dig('views', opt[:view_template]).deep_merge(tpl_cfg)
|
1539
|
+
@config.dig('views', opt[:view_template]).deep_merge(tpl_cfg, { extend_existing_arrays: true, sort_merged_arrays: true })
|
1507
1540
|
else
|
1508
1541
|
tpl_cfg
|
1509
1542
|
end
|
@@ -1515,7 +1548,7 @@ module Doing
|
|
1515
1548
|
'tags_color' => @config['tags_color'],
|
1516
1549
|
'duration' => @config['duration'],
|
1517
1550
|
'interval_format' => @config['interval_format']
|
1518
|
-
})
|
1551
|
+
}, { extend_existing_arrays: true, sort_merged_arrays: true })
|
1519
1552
|
opt[:duration] ||= cfg['duration'] || false
|
1520
1553
|
opt[:interval_format] ||= cfg['interval_format'] || 'text'
|
1521
1554
|
opt[:count] ||= 0
|
@@ -1551,7 +1584,13 @@ module Doing
|
|
1551
1584
|
|
1552
1585
|
items.reverse! unless opt[:order] =~ /^d/i
|
1553
1586
|
|
1554
|
-
if opt[:
|
1587
|
+
if opt[:delete]
|
1588
|
+
delete_items(items, force: opt[:force])
|
1589
|
+
return
|
1590
|
+
elsif opt[:editor]
|
1591
|
+
edit_items(items)
|
1592
|
+
return
|
1593
|
+
elsif opt[:interactive]
|
1555
1594
|
opt[:menu] = !opt[:force]
|
1556
1595
|
opt[:query] = '' # opt[:search]
|
1557
1596
|
opt[:multiple] = true
|
@@ -1611,14 +1650,14 @@ module Doing
|
|
1611
1650
|
opt[:totals] ||= false
|
1612
1651
|
opt[:sort_tags] ||= false
|
1613
1652
|
|
1614
|
-
cfg = @config['templates']['today'].deep_merge(@config['templates']['default']).deep_merge({
|
1653
|
+
cfg = @config['templates']['today'].deep_merge(@config['templates']['default'], { extend_existing_arrays: true, sort_merged_arrays: true }).deep_merge({
|
1615
1654
|
'wrap_width' => @config['wrap_width'] || 0,
|
1616
1655
|
'date_format' => @config['default_date_format'],
|
1617
1656
|
'order' => @config['order'] || 'asc',
|
1618
1657
|
'tags_color' => @config['tags_color'],
|
1619
1658
|
'duration' => @config['duration'],
|
1620
1659
|
'interval_format' => @config['interval_format']
|
1621
|
-
})
|
1660
|
+
}, { extend_existing_arrays: true, sort_merged_arrays: true })
|
1622
1661
|
|
1623
1662
|
opt[:duration] ||= cfg['duration'] || false
|
1624
1663
|
opt[:interval_format] ||= cfg['interval_format'] || 'text'
|
@@ -1727,14 +1766,14 @@ module Doing
|
|
1727
1766
|
opt[:totals] ||= false
|
1728
1767
|
opt[:sort_tags] ||= false
|
1729
1768
|
|
1730
|
-
cfg = @config['templates']['recent'].deep_merge(@config['templates']['default']).deep_merge({
|
1769
|
+
cfg = @config['templates']['recent'].deep_merge(@config['templates']['default'], { extend_existing_arrays: true, sort_merged_arrays: true }).deep_merge({
|
1731
1770
|
'wrap_width' => @config['wrap_width'] || 0,
|
1732
1771
|
'date_format' => @config['default_date_format'],
|
1733
1772
|
'order' => @config['order'] || 'asc',
|
1734
1773
|
'tags_color' => @config['tags_color'],
|
1735
1774
|
'duration' => @config['duration'],
|
1736
1775
|
'interval_format' => @config['interval_format']
|
1737
|
-
})
|
1776
|
+
}, { extend_existing_arrays: true, sort_merged_arrays: true })
|
1738
1777
|
opt[:duration] ||= cfg['duration'] || false
|
1739
1778
|
opt[:interval_format] ||= cfg['interval_format'] || 'text'
|
1740
1779
|
|
@@ -1761,14 +1800,14 @@ module Doing
|
|
1761
1800
|
##
|
1762
1801
|
def last(times: true, section: nil, options: {})
|
1763
1802
|
section = section.nil? || section =~ /all/i ? 'All' : guess_section(section)
|
1764
|
-
cfg = @config['templates']['last'].deep_merge(@config['templates']['default']).deep_merge({
|
1803
|
+
cfg = @config['templates']['last'].deep_merge(@config['templates']['default'], { extend_existing_arrays: true, sort_merged_arrays: true }).deep_merge({
|
1765
1804
|
'wrap_width' => @config['wrap_width'] || 0,
|
1766
1805
|
'date_format' => @config['default_date_format'],
|
1767
1806
|
'order' => @config['order'] || 'asc',
|
1768
1807
|
'tags_color' => @config['tags_color'],
|
1769
1808
|
'duration' => @config['duration'],
|
1770
1809
|
'interval_format' => @config['interval_format']
|
1771
|
-
})
|
1810
|
+
}, { extend_existing_arrays: true, sort_merged_arrays: true })
|
1772
1811
|
options[:duration] ||= cfg['duration'] || false
|
1773
1812
|
options[:interval_format] ||= cfg['interval_format'] || 'text'
|
1774
1813
|
|
@@ -1783,7 +1822,8 @@ module Doing
|
|
1783
1822
|
interval_format: options[:interval_format],
|
1784
1823
|
case: options[:case],
|
1785
1824
|
not: options[:negate],
|
1786
|
-
config_template: 'last'
|
1825
|
+
config_template: 'last',
|
1826
|
+
delete: options[:delete]
|
1787
1827
|
}
|
1788
1828
|
|
1789
1829
|
if options[:tag]
|
@@ -1832,6 +1872,7 @@ module Doing
|
|
1832
1872
|
|
1833
1873
|
@config['autotag']['synonyms'].each do |tag, v|
|
1834
1874
|
v.each do |word|
|
1875
|
+
word = word.wildcard_to_rx
|
1835
1876
|
next unless text =~ /\b#{word}\b/i
|
1836
1877
|
|
1837
1878
|
unless current_tags.include?(tag) || tagged[:whitelisted].include?(tag)
|
@@ -1845,7 +1886,12 @@ module Doing
|
|
1845
1886
|
@config['autotag']['transform'].each do |tag|
|
1846
1887
|
next unless tag =~ /\S+:\S+/
|
1847
1888
|
|
1848
|
-
|
1889
|
+
if tag =~ /::/
|
1890
|
+
rx, r = tag.split(/::/)
|
1891
|
+
else
|
1892
|
+
rx, r = tag.split(/:/)
|
1893
|
+
end
|
1894
|
+
|
1849
1895
|
flag_rx = %r{/([r]+)$}
|
1850
1896
|
if r =~ flag_rx
|
1851
1897
|
flags = r.match(flag_rx)[1].split(//)
|
@@ -2087,6 +2133,36 @@ EOS
|
|
2087
2133
|
end
|
2088
2134
|
end
|
2089
2135
|
|
2136
|
+
def configure(filename = nil)
|
2137
|
+
if filename
|
2138
|
+
Doing.config_with(filename, { ignore_local: true })
|
2139
|
+
elsif ENV['DOING_CONFIG']
|
2140
|
+
Doing.config_with(ENV['DOING_CONFIG'], { ignore_local: true })
|
2141
|
+
end
|
2142
|
+
|
2143
|
+
Doing.logger.benchmark(:configure, :start)
|
2144
|
+
config = Doing.config
|
2145
|
+
Doing.logger.benchmark(:configure, :finish)
|
2146
|
+
|
2147
|
+
config.settings['backup_dir'] = ENV['DOING_BACKUP_DIR'] if ENV['DOING_BACKUP_DIR']
|
2148
|
+
@config = config.settings
|
2149
|
+
end
|
2150
|
+
|
2151
|
+
def get_diff(filename = nil)
|
2152
|
+
configure if @config.nil?
|
2153
|
+
|
2154
|
+
filename ||= @config['doing_file']
|
2155
|
+
init_doing_file(filename)
|
2156
|
+
current_content = @content.dup
|
2157
|
+
backup_file = Util::Backup.last_backup(filename, count: 1)
|
2158
|
+
raise DoingRuntimeError, 'No undo history to diff' if backup_file.nil?
|
2159
|
+
|
2160
|
+
backup = WWID.new
|
2161
|
+
backup.config = @config
|
2162
|
+
backup.init_doing_file(backup_file)
|
2163
|
+
current_content.diff(backup.content)
|
2164
|
+
end
|
2165
|
+
|
2090
2166
|
private
|
2091
2167
|
|
2092
2168
|
##
|
@@ -2127,6 +2203,8 @@ EOS
|
|
2127
2203
|
|
2128
2204
|
export_options = { page_title: title, is_single: is_single, options: opt }
|
2129
2205
|
|
2206
|
+
Hooks.trigger :pre_export, self, opt[:output], items
|
2207
|
+
|
2130
2208
|
Plugins.plugins[:export].each do |_, options|
|
2131
2209
|
next unless opt[:output] =~ /^(#{options[:trigger].normalize_trigger})$/i
|
2132
2210
|
|
@@ -2176,10 +2254,11 @@ EOS
|
|
2176
2254
|
|
2177
2255
|
section_items = @content.in_section(section)
|
2178
2256
|
max = section_items.count - count.to_i
|
2257
|
+
moved_items = []
|
2179
2258
|
|
2180
2259
|
counter = 0
|
2181
2260
|
|
2182
|
-
@content.map
|
2261
|
+
@content.map do |item|
|
2183
2262
|
break if counter >= max
|
2184
2263
|
if opt[:before]
|
2185
2264
|
time_string = opt[:before]
|
@@ -2193,6 +2272,8 @@ EOS
|
|
2193
2272
|
else
|
2194
2273
|
counter += 1
|
2195
2274
|
item.move_to(destination, label: label, log: false)
|
2275
|
+
Hooks.trigger :post_entry_updated, self, item.dup
|
2276
|
+
item
|
2196
2277
|
end
|
2197
2278
|
end
|
2198
2279
|
|
data/lib/doing.rb
CHANGED
@@ -18,5 +18,36 @@ module Doing
|
|
18
18
|
Hooks.register :post_write do |filename|
|
19
19
|
res = `/bin/bash /Users/ttscoff/scripts/after_doing.sh`.strip
|
20
20
|
Doing.logger.debug('Hooks:', res) unless res =~ /^\.\.\.$/
|
21
|
+
|
22
|
+
wwid = WWID.new
|
23
|
+
wwid.configure
|
24
|
+
if filename == wwid.config['doing_file']
|
25
|
+
diff = wwid.get_diff(filename)
|
26
|
+
puts diff
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
Hooks.register :post_entry_added do |wwid, entry|
|
31
|
+
if wwid.config.key?('day_one_trigger') && entry.tags?(wwid.config['day_one_trigger'], :and)
|
32
|
+
|
33
|
+
logger.info('New entry:', 'Adding to Day One')
|
34
|
+
add_to_day_one(entry, wwid.config)
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
##
|
39
|
+
## Add the entry to Day One using the CLI
|
40
|
+
##
|
41
|
+
## @param entry The entry to add
|
42
|
+
##
|
43
|
+
def self.add_to_day_one(entry, config)
|
44
|
+
dayone = TTY::Which.which('dayone2')
|
45
|
+
flagged = entry.tags?('flagged') ? ' -s' : ''
|
46
|
+
tags = entry.tags.map { |t| Shellwords.escape(t) }.join(' ')
|
47
|
+
tags = tags.length.positive? ? " -t #{tags}" : ''
|
48
|
+
date = " -d '#{entry.date.strftime('%Y-%m-%d %H:%M:%S')}'"
|
49
|
+
title = entry.title.tag(config['day_one_trigger'], remove: true)
|
50
|
+
title += "\n#{entry.note}" unless entry.note.empty?
|
51
|
+
`echo #{Shellwords.escape(title)} | #{dayone} new#{flagged}#{date}#{tags}`
|
21
52
|
end
|
22
53
|
end
|
@@ -0,0 +1,59 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
require 'awesome_print'
|
3
|
+
|
4
|
+
input = STDIN.read.force_encoding('utf-8')
|
5
|
+
|
6
|
+
commands = input.split(/^# @@/).delete_if(&:empty?).sort
|
7
|
+
# commands.each do |cmd|
|
8
|
+
# puts cmd.split(/^(\w+)(.*)$/m)[1]
|
9
|
+
# end
|
10
|
+
indexes = %w[
|
11
|
+
again
|
12
|
+
cancel
|
13
|
+
done
|
14
|
+
finish
|
15
|
+
later
|
16
|
+
mark
|
17
|
+
meanwhile
|
18
|
+
note
|
19
|
+
now
|
20
|
+
reset
|
21
|
+
select
|
22
|
+
tag
|
23
|
+
choose
|
24
|
+
grep
|
25
|
+
last
|
26
|
+
recent
|
27
|
+
show
|
28
|
+
tags
|
29
|
+
today
|
30
|
+
view
|
31
|
+
yesterday
|
32
|
+
open
|
33
|
+
config
|
34
|
+
archive
|
35
|
+
import
|
36
|
+
rotate
|
37
|
+
colors
|
38
|
+
completion
|
39
|
+
plugins
|
40
|
+
sections
|
41
|
+
template
|
42
|
+
views
|
43
|
+
undo
|
44
|
+
redo
|
45
|
+
add_section
|
46
|
+
tag_dir
|
47
|
+
changelog
|
48
|
+
]
|
49
|
+
|
50
|
+
result = Array.new(indexes.count)
|
51
|
+
|
52
|
+
commands.each do |cmd|
|
53
|
+
key = cmd.match(/^(\w+)/)[1]
|
54
|
+
idx = indexes.index(key)
|
55
|
+
result[idx] = "#@@#{cmd}"
|
56
|
+
# puts commands.join('# @@')
|
57
|
+
end
|
58
|
+
|
59
|
+
puts result.join('')
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: doing
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 2.1.
|
4
|
+
version: 2.1.11
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Brett Terpstra
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2022-01-12 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: safe_yaml
|
@@ -405,6 +405,10 @@ files:
|
|
405
405
|
- AUTHORS
|
406
406
|
- CHANGELOG.md
|
407
407
|
- COMMANDS.md
|
408
|
+
- Dockerfile
|
409
|
+
- Dockerfile-2.6
|
410
|
+
- Dockerfile-2.7
|
411
|
+
- Dockerfile-3.0
|
408
412
|
- Gemfile
|
409
413
|
- Gemfile.lock
|
410
414
|
- LICENSE
|
@@ -642,6 +646,7 @@ files:
|
|
642
646
|
- scripts/generate_bash_completions.rb
|
643
647
|
- scripts/generate_fish_completions.rb
|
644
648
|
- scripts/generate_zsh_completions.rb
|
649
|
+
- scripts/sort_commands.rb
|
645
650
|
- yard_templates/default/method_details/setup.rb
|
646
651
|
homepage: http://brettterpstra.com/project/doing/
|
647
652
|
licenses:
|