From e2fbaf3935c3a66232fe864da3175b9e1bf48c89 Mon Sep 17 00:00:00 2001 From: Brett Terpstra Date: Sun, 1 Aug 2021 15:01:58 -0500 Subject: [PATCH] release prep --- CHANGELOG.md | 4 ++++ README.md | 3 ++- bin/doing | 28 ++++++++++++++++++++++++---- lib/doing/helpers.rb | 1 + lib/doing/version.rb | 2 +- lib/doing/wwid.rb | 4 +++- test/doing_done_test.rb | 7 +++++++ 7 files changed, 42 insertions(+), 7 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index abfaf75c..22e2c5fc 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,7 @@ +### 1.0.69 + +- Add `--unfinished` option to finish and cancel commands + ### 1.0.68 - Fix error in `doing show --sort` argument parsing diff --git a/README.md b/README.md index 8e16135b..8a9121c8 100644 --- a/README.md +++ b/README.md @@ -29,7 +29,7 @@ _Side note:_ I actually use the library behind this utility as part of another s ## Installation -The current version of `doing` is 1.0.67. +The current version of `doing` is 1.0.68. $ [sudo] gem install doing @@ -464,6 +464,7 @@ You can also include a `--no-date` switch to add `@done` without a finish date, By default `doing finish` works on a single entry, the last entry or the most recent entry matching a `--tag` or `--search` query. Specifying `doing finish 10` would finish any unfinished entries within the last 10 entries. In the case of `--tag` or `--search` queries, the count serves as the maximum number of matches doing will act on, sorted in reverse date order (most recent first). A count of 0 will disable the limit entirely, acting on all matching entries. +Both `finish` and `cancel` accept `--unfinished` as an argument. This causes them to act on the last entry not already marked @done, no matter how far back it's dated or how many @done entries come after it. You can use `doing finish --unfinished X -s SECTION` to finish the last X unfinished entries in SECTION. ##### Tagging and Autotagging diff --git a/bin/doing b/bin/doing index e9f868d2..16ec5633 100755 --- a/bin/doing +++ b/bin/doing @@ -446,6 +446,9 @@ command :cancel do |c| c.arg_name 'BOOLEAN' c.flag [:bool], must_match: /(?:and|all|any|or|not|none)/i, default_value: 'AND' + c.desc 'Cancel last entry (or entries) not already marked @done' + c.switch %i[u unfinished], negatable: false, default_value: false + c.action do |_global_options, options, args| section = wwid.guess_section(options[:s]) || options[:s].cap_first @@ -478,7 +481,8 @@ command :cancel do |c| sequential: false, tag: tags, tag_bool: options[:bool], - tags: ['done'] + tags: ['done'], + unfinished: options[:unfinished] } wwid.tag_last(opts) end @@ -512,6 +516,9 @@ command :finish do |c| c.arg_name 'BOOLEAN' c.flag [:bool], must_match: /(?:and|all|any|or|not|none)/i, default_value: 'AND' + c.desc 'Finish last entry (or entries) not already marked @done' + c.switch %i[u unfinished], negatable: false, default_value: false + c.desc %(Auto-generate finish dates from next entry's start time. Automatically generate completion dates 1 minute before next start date. --auto overrides the --date and --back parameters.) @@ -574,7 +581,8 @@ command :finish do |c| sequential: options[:auto], tag: tags, tag_bool: options[:bool], - tags: ['done'] + tags: ['done'], + unfinished: options[:unfinished] } wwid.tag_last(opts) end @@ -648,6 +656,9 @@ command :tag do |c| c.desc 'Remove given tag(s)' c.switch %i[r remove], negatable: false, default_value: false + c.desc 'Tag last entry (or entries) not marked @done' + c.switch %i[u unfinished], negatable: false, default_value: false + c.desc 'Autotag entries based on autotag configuration in ~/.doingrc' c.switch %i[a autotag], negatable: false, default_value: false @@ -691,7 +702,8 @@ command :tag do |c| date: options[:date], remove: options[:r], section: section, - tags: tags + tags: tags, + unfinished: options[:unfinished] } wwid.tag_last(opts) end @@ -706,9 +718,17 @@ command [:mark, :flag] do |c| c.desc 'Remove mark' c.switch %i[r remove], negatable: false, default_value: false + c.desc 'Mark last entry not marked @done' + c.switch %i[u unfinished], negatable: false, default_value: false + c.action do |_global_options, options, _args| mark = wwid.config['marker_tag'] || 'flagged' - wwid.tag_last({ tags: [mark], section: options[:s], remove: options[:r] }) + wwid.tag_last({ + remove: options[:r], + section: options[:s], + tags: [mark], + unfinished: options[:unfinished] + }) end end diff --git a/lib/doing/helpers.rb b/lib/doing/helpers.rb index a3c1585f..885bb41f 100644 --- a/lib/doing/helpers.rb +++ b/lib/doing/helpers.rb @@ -6,6 +6,7 @@ def has_tags?(tags, bool = :and) tags = tags.split(/ *, */) if tags.is_a? String bool = bool.normalize_bool if bool.is_a? String item = self + tags.map! {|t| t.strip.sub(/^@/, '')} case bool when :and result = true diff --git a/lib/doing/version.rb b/lib/doing/version.rb index c691fad2..b361fe9b 100644 --- a/lib/doing/version.rb +++ b/lib/doing/version.rb @@ -1,3 +1,3 @@ module Doing - VERSION = '1.0.68' + VERSION = '1.0.69' end diff --git a/lib/doing/wwid.rb b/lib/doing/wwid.rb index 5f825e31..9d2dd8b4 100755 --- a/lib/doing/wwid.rb +++ b/lib/doing/wwid.rb @@ -781,6 +781,7 @@ def tag_last(opt = {}) opt[:autotag] ||= false opt[:back] ||= false opt[:took] ||= nil + opt[:unfinished] ||= false sec_arr = [] @@ -816,10 +817,11 @@ def tag_last(opt = {}) items.map! do |item| break if idx == count + finished = opt[:unfinished] && item.has_tags?('done', :and) tag_match = opt[:tag].nil? || opt[:tag].empty? ? true : item.has_tags?(opt[:tag], opt[:tag_bool]) search_match = opt[:search].nil? || opt[:search].empty? ? true : item.matches_search?(opt[:search]) - if tag_match && search_match + if tag_match && search_match && !finished if opt[:autotag] new_title = autotag(item['title']) if @auto_tag if new_title == item['title'] diff --git a/test/doing_done_test.rb b/test/doing_done_test.rb index 4b941a5b..0f4abbb0 100644 --- a/test/doing_done_test.rb +++ b/test/doing_done_test.rb @@ -45,6 +45,13 @@ def test_finish_tag assert_no_match(ENTRY_DONE_REGEX, t2, "@tag2 entry should not have @done timestamp") end + def test_finish_unfinished + doing('now', '--back=15m', 'Adding an unfinished entry') + doing('done', 'Adding a finished entry') + result = doing('--stdout', 'finish', '--unfinished') + assert_match(/Added @done: "Adding an unfinished entry/, result, "Earlier unfinished task should be marked @done") + end + def test_finish_took subject = 'Test new entry @tag1' doing('now', subject)