bin/commands/now.rb in doing-2.1.41 vs bin/commands/now.rb in doing-2.1.42
- old
+ new
@@ -1,142 +1,186 @@
# @@now @@next
-desc 'Add an entry'
-long_desc %(Record what you're starting now, or backdate the start time using natural language.
-A parenthetical at the end of the entry will be converted to a note.
+module Doing
+ # Methods for the now command
+ class NowCommand
+ def initialize(wwid)
+ @wwid = wwid
+ end
-Run without arguments to create a new entry interactively.
+ def setup(cmd)
+ add_examples(cmd)
+ add_options(cmd)
+ end
-Run with --editor to create a new entry using #{Doing::Util.default_editor}.)
-arg_name 'ENTRY'
-command %i[now next] do |c|
- c.example 'doing now', desc: 'Create a new entry with interactive prompts'
- c.example 'doing now -e', desc: "Open #{Doing::Util.default_editor} to input an entry and optional note"
- c.example 'doing now working on a new project', desc: 'Add a new entry at the current time'
- c.example 'doing now debugging @project2', desc: 'Add an entry with a tag'
- c.example 'doing now adding an entry (with a note)', desc: 'Parenthetical at end is converted to note'
- c.example 'doing now --back 2pm A thing I started at 2:00 and am still doing...', desc: 'Backdate an entry'
+ def process_now_options(options)
+ raise InvalidArgument, '--back and --from cannot be used together' if options[:back] && options[:from]
- c.desc 'Section'
- c.arg_name 'NAME'
- c.flag %i[s section]
+ if options[:back]
+ options[:date] = options[:back]
+ elsif options[:from]
+ options[:date], finish_date = options[:from]
+ options[:done] = finish_date
+ else
+ options[:date] = Time.now
+ end
+ raise InvalidTimeExpression.new('unable to parse date string', topic: 'Parser:') if options[:date].nil?
- c.desc %(
- Set a start and optionally end time as a date range ("from 1pm to 2:30pm").
- If an end time is provided, a dated @done tag will be added
- )
- c.arg_name 'TIME_RANGE'
- c.flag [:from], type: DateRangeString
+ options[:section] = if options[:section]
+ @wwid.guess_section(options[:section]) || options[:section].cap_first
+ else
+ Doing.setting('current_section')
+ end
- c.desc 'Timed entry, marks last entry in section as @done'
- c.switch %i[f finish_last], negatable: false, default_value: false
+ options[:ask_note] = if options[:ask] && !options[:editor] && options[:has_args]
+ Doing::Prompt.read_lines(prompt: 'Add a note')
+ else
+ ''
+ end
- add_options(:add_entry, c)
-
- # c.desc "Edit entry with specified app"
- # c.arg_name 'editor_app'
- # # c.flag [:a, :app]
-
- c.action do |global_options, options, args|
- Doing.auto_tag = !options[:noauto]
-
- raise InvalidArgument, '--back and --from cannot be used together' if options[:back] && options[:from]
-
- if options[:back]
- date = options[:back]
- elsif options[:from]
- date, finish_date = options[:from]
- options[:done] = finish_date
- else
- date = Time.now
+ options
end
- raise InvalidTimeExpression.new('unable to parse date string', topic: 'Parser:') if date.nil?
- section = if options[:section]
- @wwid.guess_section(options[:section]) || options[:section].cap_first
- else
- Doing.setting('current_section')
- end
-
- ask_note = if options[:ask] && !options[:editor] && args.count.positive?
- Doing::Prompt.read_lines(prompt: 'Add a note')
- else
- ''
- end
-
- if options[:editor]
+ def now_with_editor(options, args)
raise MissingEditor, 'No EDITOR variable defined in environment' if Doing::Util.default_editor.nil?
- input = date.strftime('%F %R | ')
+ input = options[:date].strftime('%F %R | ')
input += args.join(' ') unless args.empty?
input += " @done(#{options[:done].strftime('%F %R')})" if options[:done]
input += "\n#{options[:note]}" if options[:note]
- input += "\n#{ask_note}" if ask_note.good?
+ input += "\n#{options[:ask_note]}" if options[:ask_note].good?
input = @wwid.fork_editor(input).strip
d, title, note = @wwid.format_input(input)
raise EmptyInput, 'No content' unless title.good?
- if ask_note.empty? && options[:ask]
- ask_note = Doing::Prompt.read_lines(prompt: 'Add a note')
- note.add(ask_note) if ask_note.good?
- end
+ note = ask_note(options, note, prompt: false)
- date = d.nil? ? date : d
- @wwid.add_item(title.cap_first, section, { note: note, back: date, timed: options[:finish_last] })
- elsif args.length.positive?
+ options[:date] = d.nil? ? options[:date] : d
+ opts = { note: note, back: options[:date], timed: options[:finish_last] }
+ @wwid.add_item(title.cap_first, options[:section], opts)
+ end
+
+ def now_with_args(options, args)
d, title, note = @wwid.format_input(args.join(' '))
- date = d.nil? ? date : d
- note.add(options[:note]) if options[:note]
- note.add(ask_note) if ask_note.good?
- entry = @wwid.add_item(title.cap_first, section, { note: note, back: date, timed: options[:finish_last] })
- if options[:done] && entry.should_finish?
- if entry.should_time?
- entry.tag('done', value: options[:done])
- else
- entry.tag('done')
- end
- end
- elsif global_options[:stdin]
- input = global_options[:stdin]
- d, title, note = @wwid.format_input(input)
+ options[:date] = d.nil? ? options[:date] : d
+
+ note = ask_note(options, note, prompt: false)
+
+ opts = { note: note, back: options[:date], timed: options[:finish_last] }
+ entry = @wwid.add_item(title.cap_first, options[:section], opts)
+ return unless options[:done] && entry.should_finish?
+
+ entry.should_time? ? entry.tag('done', value: options[:done]) : entry.tag('done')
+ end
+
+ def now_with_stdin(global_options, options, _args)
+ d, title, note = @wwid.format_input(global_options[:stdin])
+
unless d.nil?
Doing.logger.debug('Parser:', 'Date detected in input, overriding command line values')
- date = d
+ options[:date] = d
end
- note.add(options[:note]) if options[:note]
- if ask_note.empty? && options[:ask]
- ask_note = Doing::Prompt.read_lines(prompt: 'Add a note')
- note.add(ask_note) if ask_note.good?
- end
- entry = @wwid.add_item(title.cap_first, section, { note: note, back: date, timed: options[:finish_last] })
- if options[:done] && entry.should_finish?
- if entry.should_time?
- entry.tag('done', value: options[:done])
- else
- entry.tag('done')
- end
- end
- else
+
+ note = ask_note(options, note, prompt: false)
+
+ opts = { note: note, back: options[:date], timed: options[:finish_last] }
+ entry = @wwid.add_item(title.cap_first, options[:section], opts)
+ return unless options[:done] && entry.should_finish?
+
+ entry.should_time? ? entry.tag('done', value: options[:done]) : entry.tag('done')
+ end
+
+ def interactive_now(options, _args)
tags = @wwid.all_tags(@wwid.content)
- $stderr.puts Doing::Color.boldgreen("Add a new entry. Tab will autocomplete known tags. Ctrl-c to cancel.")
+ puts Doing::Color.boldgreen('Add a new entry. Tab will autocomplete known tags. Ctrl-c to cancel.')
title = Doing::Prompt.read_line(prompt: 'Entry content', completions: tags)
raise EmptyInput, 'You must provide content when creating a new entry' unless title.good?
- note = Doing::Note.new
+ note = ask_note(options, prompt: true)
+
+ opts = { note: note, back: options[:date], timed: options[:finish_last] }
+ entry = @wwid.add_item(title.cap_first, options[:section], opts)
+ return unless options[:done] && entry.should_finish?
+
+ if entry.should_time?
+ entry.tag('done', value: options[:done])
+ else
+ entry.tag('done')
+ end
+ end
+
+ private
+
+ def ask_note(options, note = nil, prompt: false)
+ note ||= Doing::Note.new
note.add(options[:note]) if options[:note]
- res = Doing::Prompt.yn('Add a note', default_response: false)
- ask_note = res ? Doing::Prompt.read_lines(prompt: 'Enter note') : []
- note.add(ask_note)
- entry = @wwid.add_item(title.cap_first, section, { note: note, back: date, timed: options[:finish_last] })
- if options[:done] && entry.should_finish?
- if entry.should_time?
- entry.tag('done', value: options[:done])
- else
- entry.tag('done')
- end
+ res = prompt ? Doing::Prompt.yn('Add a note', default_response: false) : false
+
+ if options[:ask_note].empty? && (res || options[:ask])
+ options[:ask_note] = Doing::Prompt.read_lines(prompt: 'Enter note')
end
+
+ note.add(options[:ask_note]) if options[:ask_note].good?
+ note
+ end
+
+ def add_examples(cmd)
+ cmd.example 'doing now', desc: 'Create a new entry with interactive prompts'
+ cmd.example 'doing now -e', desc: "Open #{Doing::Util.default_editor} to input an entry and optional note"
+ cmd.example 'doing now working on a new project', desc: 'Add a new entry at the current time'
+ cmd.example 'doing now debugging @project2', desc: 'Add an entry with a tag'
+ cmd.example 'doing now adding an entry (with a note)', desc: 'Parenthetical at end is converted to note'
+ cmd.example 'doing now --back 2pm A thing I started at 2:00 and am still doing...', desc: 'Backdate an entry'
+ end
+
+ def add_options(cmd)
+ cmd.desc 'Section'
+ cmd.arg_name 'NAME'
+ cmd.flag %i[s section]
+
+ cmd.desc %(Set a start and optionally end time as a date range ("from 1pm to 2:30pm").
+ If an end time is provided, a dated @done tag will be added)
+ cmd.arg_name 'TIME_RANGE'
+ cmd.flag [:from], type: DateRangeString
+
+ cmd.desc 'Timed entry, marks last entry in section as @done'
+ cmd.switch %i[f finish_last], negatable: false, default_value: false
+ end
+ end
+end
+
+desc 'Add an entry'
+long_desc %(Record what you're starting now, or backdate the start time using natural language.
+
+A parenthetical at the end of the entry will be converted to a note.
+
+Run without arguments to create a new entry interactively.
+
+Run with --editor to create a new entry using #{Doing::Util.default_editor}.)
+arg_name 'ENTRY'
+command %i[now next] do |c|
+ cmd = Doing::NowCommand.new(@wwid)
+ cmd.setup(c)
+ add_options(:add_entry, c)
+
+ # c.desc "Edit entry with specified app"
+ # c.arg_name 'editor_app'
+ # # c.flag [:a, :app]
+ c.action do |global_options, options, args|
+ Doing.auto_tag = !options[:noauto]
+ options[:has_args] = args.count.positive?
+ options = cmd.process_now_options(options)
+
+ if options[:editor]
+ cmd.now_with_editor(options, args)
+ elsif args.length.positive?
+ cmd.now_with_args(options, args)
+ elsif global_options[:stdin]
+ cmd.now_with_stdin(global_options, options, args)
+ else
+ cmd.interactive_now(options, args)
end
@wwid.write(@wwid.doing_file)
end
end