doing 2.1.25 → 2.1.29
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.
- checksums.yaml +4 -4
- data/.yardoc/checksums +15 -20
- data/.yardoc/object_types +0 -0
- data/.yardoc/objects/root.dat +0 -0
- data/CHANGELOG.md +322 -108
- data/Dockerfile +5 -5
- data/Dockerfile-2.6 +5 -5
- data/Dockerfile-2.7 +5 -4
- data/Dockerfile-3.0 +5 -4
- data/Gemfile.lock +1 -1
- data/README.md +1 -1
- data/Rakefile +2 -3
- data/bin/commands/add_section.rb +15 -0
- data/bin/commands/again.rb +57 -0
- data/bin/commands/archive.rb +55 -0
- data/bin/commands/cancel.rb +60 -0
- data/bin/commands/changes.rb +83 -0
- data/bin/commands/choose.rb +9 -0
- data/bin/commands/colors.rb +21 -0
- data/bin/commands/commands.rb +89 -0
- data/bin/commands/commands_accepting.rb +76 -0
- data/bin/commands/completion.rb +27 -0
- data/bin/commands/config.rb +245 -0
- data/bin/commands/done.rb +235 -0
- data/bin/commands/finish.rb +126 -0
- data/bin/commands/flag.rb +90 -0
- data/bin/commands/grep.rb +108 -0
- data/bin/commands/import.rb +71 -0
- data/bin/commands/install_fzf.rb +17 -0
- data/bin/commands/last.rb +81 -0
- data/bin/commands/meanwhile.rb +76 -0
- data/bin/commands/note.rb +91 -0
- data/bin/commands/now.rb +145 -0
- data/bin/commands/on.rb +65 -0
- data/bin/commands/open.rb +53 -0
- data/bin/commands/plugins.rb +23 -0
- data/bin/commands/recent.rb +77 -0
- data/bin/commands/redo.rb +26 -0
- data/bin/commands/reset.rb +73 -0
- data/bin/commands/rotate.rb +42 -0
- data/bin/commands/sections.rb +11 -0
- data/bin/commands/select.rb +105 -0
- data/bin/commands/show.rb +185 -0
- data/bin/commands/since.rb +63 -0
- data/bin/commands/tag.rb +149 -0
- data/bin/commands/tag_dir.rb +29 -0
- data/bin/commands/tags.rb +66 -0
- data/bin/commands/template.rb +61 -0
- data/bin/commands/today.rb +64 -0
- data/bin/commands/undo.rb +49 -0
- data/bin/commands/view.rb +201 -0
- data/bin/commands/views.rb +11 -0
- data/bin/commands/yesterday.rb +72 -0
- data/bin/doing +241 -3706
- data/docs/doc/Array.html +3 -502
- 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 +62 -56
- data/docs/doc/Doing/Completion.html +1 -1
- data/docs/doc/Doing/Configuration.html +36 -1
- 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 +1 -1
- data/docs/doc/Doing/Items.html +2 -2
- data/docs/doc/Doing/LogAdapter.html +1 -1
- data/docs/doc/Doing/Note.html +2 -2
- data/docs/doc/Doing/Pager.html +1 -1
- data/docs/doc/Doing/Plugins.html +1 -1
- data/docs/doc/Doing/Prompt.html +46 -1
- data/docs/doc/Doing/Section.html +1 -1
- data/docs/doc/Doing/TemplateString.html +2 -2
- data/docs/doc/Doing/Types.html +41 -1
- data/docs/doc/Doing/Util/Backup.html +1 -1
- data/docs/doc/Doing/Util.html +1 -1
- data/docs/doc/Doing/WWID.html +10 -10
- data/docs/doc/Doing.html +3 -3
- data/docs/doc/FalseClass.html +235 -0
- 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/Numeric.html +1 -1
- data/docs/doc/Object.html +203 -0
- 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 +287 -3155
- data/docs/doc/Symbol.html +40 -6
- data/docs/doc/Time.html +1 -1
- data/docs/doc/TrueClass.html +235 -0
- data/docs/doc/_index.html +5 -10
- data/docs/doc/class_list.html +1 -1
- data/docs/doc/file.README.html +2 -2
- data/docs/doc/index.html +2 -2
- data/docs/doc/method_list.html +289 -681
- data/docs/doc/top-level-namespace.html +2 -2
- data/doing.rdoc +306 -205
- data/lib/completion/_doing.zsh +35 -35
- data/lib/completion/doing.bash +30 -30
- data/lib/completion/doing.fish +88 -78
- data/lib/doing/array/array.rb +4 -0
- data/lib/doing/array/nested_hash.rb +17 -0
- data/lib/doing/{array.rb → array/tags.rb} +7 -25
- data/lib/doing/changelog/change.rb +26 -11
- data/lib/doing/changelog/changes.rb +31 -4
- data/lib/doing/{array_chronify.rb → chronify/array.rb} +0 -0
- data/lib/doing/chronify/chronify.rb +5 -0
- data/lib/doing/{numeric_chronify.rb → chronify/numeric.rb} +0 -0
- data/lib/doing/{string_chronify.rb → chronify/string.rb} +0 -0
- data/lib/doing/colors.rb +115 -54
- data/lib/doing/configuration.rb +5 -0
- data/lib/doing/good.rb +8 -0
- data/lib/doing/help_monkey_patch.rb +6 -5
- data/lib/doing/item.rb +5 -5
- data/lib/doing/items.rb +2 -2
- data/lib/doing/log_adapter.rb +35 -2
- data/lib/doing/normalize.rb +188 -0
- data/lib/doing/pager.rb +1 -0
- data/lib/doing/plugins/export/dayone_export.rb +1 -1
- data/lib/doing/plugins/export/html_export.rb +1 -1
- data/lib/doing/plugins/export/json_export.rb +1 -1
- data/lib/doing/plugins/export/markdown_export.rb +1 -1
- data/lib/doing/plugins/export/template_export.rb +3 -1
- data/lib/doing/prompt.rb +9 -3
- data/lib/doing/string/highlight.rb +95 -0
- data/lib/doing/string/query.rb +129 -0
- data/lib/doing/string/string.rb +12 -0
- data/lib/doing/string/tags.rb +164 -0
- data/lib/doing/string/transform.rb +168 -0
- data/lib/doing/string/truncate.rb +75 -0
- data/lib/doing/string/url.rb +82 -0
- data/lib/doing/template_string.rb +0 -22
- data/lib/doing/types.rb +8 -0
- data/lib/doing/util.rb +13 -9
- data/lib/doing/version.rb +1 -1
- data/lib/doing/wwid.rb +53 -35
- data/lib/doing.rb +4 -6
- data/lib/examples/commands/wiki.rb +6 -7
- data/lib/examples/plugins/wiki_export/wiki_export.rb +1 -1
- data/lib/helpers/threaded_tests.rb +39 -20
- data/scripts/deploy.rb +107 -0
- data/scripts/runtests.sh +4 -0
- metadata +63 -8
- data/lib/doing/string.rb +0 -765
- data/lib/doing/symbol.rb +0 -28
data/Dockerfile
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
FROM ruby:3.0.1
|
|
2
|
-
RUN curl -sS https://dl.yarnpkg.com/debian/pubkey.gpg | apt-key add -
|
|
2
|
+
# RUN curl -sS https://dl.yarnpkg.com/debian/pubkey.gpg | apt-key add -
|
|
3
3
|
RUN mkdir /doing
|
|
4
4
|
WORKDIR /doing
|
|
5
|
-
COPY ./ /doing/
|
|
5
|
+
# COPY ./ /doing/
|
|
6
6
|
RUN gem install bundler:2.2.17
|
|
7
|
-
|
|
8
|
-
RUN
|
|
9
|
-
CMD ["
|
|
7
|
+
RUN apt-get update -y
|
|
8
|
+
RUN apt-get install -y less
|
|
9
|
+
CMD ["scripts/runtests.sh"]
|
data/Dockerfile-2.6
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
FROM ruby:2.6
|
|
2
|
+
# RUN curl -sS https://dl.yarnpkg.com/debian/pubkey.gpg | apt-key add -
|
|
2
3
|
RUN mkdir /doing
|
|
3
4
|
WORKDIR /doing
|
|
4
|
-
COPY ./ /doing/
|
|
5
|
+
# COPY ./ /doing/
|
|
5
6
|
RUN gem install bundler:2.2.17
|
|
6
|
-
|
|
7
|
-
RUN
|
|
8
|
-
|
|
9
|
-
CMD ["rake", "parallel:test"]
|
|
7
|
+
RUN apt-get update -y
|
|
8
|
+
RUN apt-get install -y less
|
|
9
|
+
CMD ["scripts/runtests.sh"]
|
data/Dockerfile-2.7
CHANGED
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
FROM ruby:2.7
|
|
2
|
+
RUN curl -sS https://dl.yarnpkg.com/debian/pubkey.gpg | apt-key add -
|
|
2
3
|
RUN mkdir /doing
|
|
3
4
|
WORKDIR /doing
|
|
4
|
-
COPY ./ /doing/
|
|
5
|
+
# COPY ./ /doing/
|
|
5
6
|
RUN gem install bundler:2.2.17
|
|
6
|
-
|
|
7
|
-
RUN
|
|
8
|
-
CMD ["
|
|
7
|
+
RUN apt-get update -y
|
|
8
|
+
RUN apt-get install -y less
|
|
9
|
+
CMD ["scripts/runtests.sh"]
|
data/Dockerfile-3.0
CHANGED
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
FROM ruby:3.0.0
|
|
2
|
+
# RUN curl -sS https://dl.yarnpkg.com/debian/pubkey.gpg | apt-key add -
|
|
2
3
|
RUN mkdir /doing
|
|
3
4
|
WORKDIR /doing
|
|
4
|
-
COPY ./ /doing/
|
|
5
|
+
# COPY ./ /doing/
|
|
5
6
|
RUN gem install bundler:2.2.17
|
|
6
|
-
|
|
7
|
-
RUN
|
|
8
|
-
CMD ["
|
|
7
|
+
RUN apt-get update -y
|
|
8
|
+
RUN apt-get install -y less
|
|
9
|
+
CMD ["scripts/runtests.sh"]
|
data/Gemfile.lock
CHANGED
data/README.md
CHANGED
|
@@ -8,7 +8,7 @@ _If you're one of the rare people like me who find this useful, feel free to
|
|
|
8
8
|
|
|
9
9
|
<!--README-->
|
|
10
10
|
|
|
11
|
-
The current version of `doing` is <!--VER-->2.1.
|
|
11
|
+
The current version of `doing` is <!--VER-->2.1.28<!--END VER-->.
|
|
12
12
|
|
|
13
13
|
Find all of the documentation in the [doing wiki][wiki].
|
|
14
14
|
|
data/Rakefile
CHANGED
|
@@ -77,15 +77,14 @@ task :dockertest, :version, :login do |_, args|
|
|
|
77
77
|
file = 'Dockerfile'
|
|
78
78
|
end
|
|
79
79
|
|
|
80
|
-
|
|
81
80
|
puts `docker build . --file #{file} -t #{img}`
|
|
82
81
|
|
|
83
|
-
exec "docker run -it #{img} /bin/bash -l" if args[:login]
|
|
82
|
+
exec "docker run -v #{File.dirname(__FILE__)}:/doing -it #{img} /bin/bash -l" if args[:login]
|
|
84
83
|
|
|
85
84
|
spinner = TTY::Spinner.new('[:spinner] Running tests ...', hide_cursor: true)
|
|
86
85
|
|
|
87
86
|
spinner.auto_spin
|
|
88
|
-
res = `docker run --rm -it #{img}`
|
|
87
|
+
res = `docker run --rm -v #{File.dirname(__FILE__)}:/doing -it #{img}`
|
|
89
88
|
# commit = puts `bash -c "docker commit $(docker ps -a|grep #{img}|awk '{print $1}'|head -n 1) #{img}"`.strip
|
|
90
89
|
spinner.success
|
|
91
90
|
spinner.stop
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
# @@add_section
|
|
4
|
+
desc 'Add a new section to the "doing" file'
|
|
5
|
+
arg_name 'SECTION_NAME'
|
|
6
|
+
command :add_section do |c|
|
|
7
|
+
c.example 'doing add_section Ideas', desc: 'Add a section called Ideas to the doing file'
|
|
8
|
+
|
|
9
|
+
c.action do |_global_options, _options, args|
|
|
10
|
+
raise InvalidArgument, "Section #{args[0]} already exists" if @wwid.sections.include?(args[0])
|
|
11
|
+
|
|
12
|
+
@wwid.content.add_section(args.join(' ').cap_first, log: true)
|
|
13
|
+
@wwid.write(@wwid.doing_file)
|
|
14
|
+
end
|
|
15
|
+
end
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
# @@again @@resume
|
|
4
|
+
desc 'Repeat last entry as new entry'
|
|
5
|
+
long_desc 'This command is designed to allow multiple time intervals to be created
|
|
6
|
+
for an entry by duplicating it with a new start (and end, eventually) time'
|
|
7
|
+
command %i[again resume] do |c|
|
|
8
|
+
c.example 'doing resume',
|
|
9
|
+
desc: 'Duplicate the most recent entry with a new start time, removing any @done tag'
|
|
10
|
+
c.example 'doing again',
|
|
11
|
+
desc: 'again is an alias for resume'
|
|
12
|
+
c.example 'doing resume --editor',
|
|
13
|
+
desc: 'Repeat the last entry, opening the new entry in the default editor'
|
|
14
|
+
c.example 'doing resume --tag project1 --in Projects',
|
|
15
|
+
desc: 'Repeat the last entry tagged @project1, creating the new entry in the Projects section'
|
|
16
|
+
c.example 'doing resume --interactive', desc: 'Select the entry to repeat from a menu'
|
|
17
|
+
|
|
18
|
+
c.desc 'Get last entry from a specific section'
|
|
19
|
+
c.arg_name 'NAME'
|
|
20
|
+
c.flag %i[s section], default_value: 'All'
|
|
21
|
+
|
|
22
|
+
c.desc 'Add new entry to section (default: same section as repeated entry)'
|
|
23
|
+
c.arg_name 'SECTION_NAME'
|
|
24
|
+
c.flag [:in]
|
|
25
|
+
|
|
26
|
+
c.desc 'Select item to resume from a menu of matching entries'
|
|
27
|
+
c.switch %i[i interactive], negatable: false, default_value: false
|
|
28
|
+
|
|
29
|
+
add_options(:add_entry, c)
|
|
30
|
+
add_options(:search, c)
|
|
31
|
+
add_options(:tag_filter, c)
|
|
32
|
+
|
|
33
|
+
c.action do |_global_options, options, _args|
|
|
34
|
+
options[:fuzzy] = false
|
|
35
|
+
|
|
36
|
+
if options[:search]
|
|
37
|
+
options[:search] = options[:exact] ? options[:search].sub(/^'?/, "'") : options[:search]
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
if options[:back]
|
|
41
|
+
options[:date] = options[:back]
|
|
42
|
+
raise InvalidTimeExpression, 'Unable to parse date string for --back' if date.nil?
|
|
43
|
+
|
|
44
|
+
else
|
|
45
|
+
options[:date] = Time.now
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
note = Doing::Note.new(options[:note])
|
|
49
|
+
note.add(Doing::Prompt.read_lines(prompt: 'Add a note')) if options[:ask]
|
|
50
|
+
|
|
51
|
+
options[:note] = note
|
|
52
|
+
options[:tag] ||= []
|
|
53
|
+
options[:tag_bool] = options[:bool]
|
|
54
|
+
|
|
55
|
+
@wwid.repeat_last(options)
|
|
56
|
+
end
|
|
57
|
+
end
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
# @@archive @@move
|
|
4
|
+
desc 'Move entries between sections'
|
|
5
|
+
long_desc %(Argument can be a section name to move all entries from a section,
|
|
6
|
+
or start with an "@" to move entries matching a tag.
|
|
7
|
+
|
|
8
|
+
Default with no argument moves items from the "#{@settings['current_section']}" section to Archive.)
|
|
9
|
+
arg_name 'SECTION_OR_TAG'
|
|
10
|
+
default_value @settings['current_section']
|
|
11
|
+
command %i[archive move] do |c|
|
|
12
|
+
c.example 'doing archive Currently', desc: 'Move all entries in the Currently section to Archive section'
|
|
13
|
+
c.example 'doing archive @done', desc: 'Move all entries tagged @done to Archive'
|
|
14
|
+
c.example 'doing archive --to Later @project1', desc: 'Move all entries tagged @project1 to Later section'
|
|
15
|
+
c.example 'doing move Later --tag project1 --to Currently',
|
|
16
|
+
desc: 'Move entries in Later tagged @project1 to Currently (move is an alias for archive)'
|
|
17
|
+
|
|
18
|
+
c.desc 'How many items to keep (ignored if archiving by tag or search)'
|
|
19
|
+
c.arg_name 'X'
|
|
20
|
+
c.flag %i[k keep], must_match: /^\d+$/, type: Integer
|
|
21
|
+
|
|
22
|
+
c.desc 'Move entries to'
|
|
23
|
+
c.arg_name 'SECTION_NAME'
|
|
24
|
+
c.flag %i[t to], default_value: 'Archive'
|
|
25
|
+
|
|
26
|
+
c.desc 'Label moved items with @from(SECTION_NAME)'
|
|
27
|
+
c.switch [:label], default_value: true, negatable: true
|
|
28
|
+
|
|
29
|
+
add_options(:search, c)
|
|
30
|
+
add_options(:tag_filter, c)
|
|
31
|
+
add_options(:date_filter, c)
|
|
32
|
+
|
|
33
|
+
c.action do |_global_options, options, args|
|
|
34
|
+
options[:fuzzy] = false
|
|
35
|
+
section, tags = if args.empty?
|
|
36
|
+
[@settings['current_section'], []]
|
|
37
|
+
elsif args[0] =~ /^all/i
|
|
38
|
+
['all', []]
|
|
39
|
+
elsif args[0] =~ /^@\S+/
|
|
40
|
+
['all', args.tags_to_array]
|
|
41
|
+
else
|
|
42
|
+
[args.shift.cap_first, args.tags_to_array]
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
raise InvalidArgument, '--keep and --count can not be used together' if options[:keep] && options[:count]
|
|
46
|
+
|
|
47
|
+
tags.concat(options[:tag]) if options[:tag]
|
|
48
|
+
|
|
49
|
+
options[:search] = options[:search].sub(/^'?/, "'") if options[:search] && options[:exact]
|
|
50
|
+
options[:destination] = options[:to]
|
|
51
|
+
options[:tags] = tags
|
|
52
|
+
|
|
53
|
+
@wwid.archive(section, options)
|
|
54
|
+
end
|
|
55
|
+
end
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
# @@cancel
|
|
4
|
+
desc 'End last X entries with no time tracked'
|
|
5
|
+
long_desc 'Adds @done tag without datestamp so no elapsed time is recorded.
|
|
6
|
+
Alias for `doing finish --no-date`'
|
|
7
|
+
arg_name 'COUNT'
|
|
8
|
+
command :cancel do |c|
|
|
9
|
+
c.example 'doing cancel', desc: 'Cancel the last entry'
|
|
10
|
+
c.example 'doing cancel --tag project1 -u 5', desc: 'Cancel the last 5 unfinished entries containing @project1'
|
|
11
|
+
|
|
12
|
+
c.desc 'Archive entries'
|
|
13
|
+
c.switch %i[a archive], negatable: false, default_value: false
|
|
14
|
+
|
|
15
|
+
c.desc 'Section'
|
|
16
|
+
c.arg_name 'NAME'
|
|
17
|
+
c.flag %i[s section]
|
|
18
|
+
|
|
19
|
+
c.desc 'Cancel last entry (or entries) not already marked @done'
|
|
20
|
+
c.switch %i[u unfinished], negatable: false, default_value: false
|
|
21
|
+
|
|
22
|
+
c.desc 'Select item(s) to cancel from a menu of matching entries'
|
|
23
|
+
c.switch %i[i interactive], negatable: false, default_value: false
|
|
24
|
+
|
|
25
|
+
add_options(:search, c)
|
|
26
|
+
add_options(:tag_filter, c)
|
|
27
|
+
|
|
28
|
+
c.action do |_global_options, options, args|
|
|
29
|
+
options[:fuzzy] = false
|
|
30
|
+
options[:section] = if options[:section]
|
|
31
|
+
@wwid.guess_section(options[:section]) || options[:section].cap_first
|
|
32
|
+
else
|
|
33
|
+
@settings['current_section']
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
raise InvalidArgument, 'Only one argument allowed' if args.length > 1
|
|
37
|
+
|
|
38
|
+
unless args.empty? || args[0] =~ /\d+/
|
|
39
|
+
raise InvalidArgument, 'Invalid argument (specify number of recent items to mark @done)'
|
|
40
|
+
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
options[:count] = if options[:interactive]
|
|
44
|
+
0
|
|
45
|
+
else
|
|
46
|
+
args[0] ? args[0].to_i : 1
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
options[:search] = options[:search].sub(/^'?/, "'") if options[:search] && options[:exact]
|
|
50
|
+
|
|
51
|
+
options[:case] = options[:case].normalize_case
|
|
52
|
+
options[:date] = false
|
|
53
|
+
options[:sequential] = false
|
|
54
|
+
options[:tag] ||= []
|
|
55
|
+
options[:tag_bool] = options[:bool].normalize_bool
|
|
56
|
+
options[:tags] = ['done']
|
|
57
|
+
|
|
58
|
+
@wwid.tag_last(options)
|
|
59
|
+
end
|
|
60
|
+
end
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
# @@changelog @@changes
|
|
2
|
+
|
|
3
|
+
MARKDOWN_THEME = {
|
|
4
|
+
em: %i[white dark],
|
|
5
|
+
header: %i[cyan bold],
|
|
6
|
+
hr: :yellow,
|
|
7
|
+
link: %i[bright_cyan underline],
|
|
8
|
+
list: :yellow,
|
|
9
|
+
strong: %i[yellow bold],
|
|
10
|
+
table: :yellow,
|
|
11
|
+
quote: :yellow,
|
|
12
|
+
image: :bright_black,
|
|
13
|
+
note: :yellow,
|
|
14
|
+
comment: :bright_black
|
|
15
|
+
}.deep_freeze
|
|
16
|
+
|
|
17
|
+
CHANGE_RX = /^(?:(?:(?:[<>=]|p(?:rior)|b(?:efore)|o(?:lder)|s(?:ince)|a(?:fter)|n(?:ewer))? *[\d.*?]+ *)+|(?:[\d.]+ *-+ *[\d.]+))$/
|
|
18
|
+
|
|
19
|
+
desc 'List recent changes in Doing'
|
|
20
|
+
long_desc %(Display a formatted list of changes in recent versions.
|
|
21
|
+
|
|
22
|
+
Without flags, displays only the most recent version.
|
|
23
|
+
Use --lookup or --all for history.)
|
|
24
|
+
command %i[changes changelog] do |c|
|
|
25
|
+
c.desc 'Display all versions'
|
|
26
|
+
c.switch %i[a all], default_value: false, negatable: false
|
|
27
|
+
|
|
28
|
+
c.desc %(Look up a specific version. Specify versions as "MAJ.MIN.PATCH", MIN
|
|
29
|
+
and PATCH are optional. Use > or < to see all changes since or prior
|
|
30
|
+
to a version.)
|
|
31
|
+
c.arg_name 'VERSION'
|
|
32
|
+
c.flag %i[l lookup], must_match: CHANGE_RX
|
|
33
|
+
|
|
34
|
+
c.desc %(Show changelogs matching search terms (uses pattern-based searching).
|
|
35
|
+
Add slashes to search with regular expressions, e.g. `--search "/output.*flag/"`)
|
|
36
|
+
c.flag %i[s search]
|
|
37
|
+
|
|
38
|
+
c.desc 'Sort order (asc/desc)'
|
|
39
|
+
c.arg_name 'ORDER'
|
|
40
|
+
c.flag %i[sort], must_match: REGEX_SORT_ORDER, default_value: :desc, type: OrderSymbol
|
|
41
|
+
|
|
42
|
+
c.desc 'Only output changes, no version numbers, headers, or dates'
|
|
43
|
+
c.switch %i[C changes], default_value: false, negatable: false
|
|
44
|
+
|
|
45
|
+
c.desc 'Output raw Markdown'
|
|
46
|
+
c.switch %i[m md markdown], default_value: false, negatable: false
|
|
47
|
+
|
|
48
|
+
c.desc 'Force rendered output'
|
|
49
|
+
c.switch %i[render], default_value: false, negatable: false
|
|
50
|
+
|
|
51
|
+
c.desc 'Open changelog in interactive viewer'
|
|
52
|
+
c.switch %i[i interactive], default_value: false, negatable: false
|
|
53
|
+
|
|
54
|
+
c.example 'doing changes', desc: 'View changes in the current version'
|
|
55
|
+
c.example 'doing changes --all', desc: 'See the entire changelog'
|
|
56
|
+
c.example 'doing changes --lookup 2.0.21', desc: 'See changes from version 2.0.21'
|
|
57
|
+
c.example 'doing changes --lookup "> 2.1"', desc: 'See all changes since 2.1.0'
|
|
58
|
+
c.example 'doing changes --search "tags +bool"', desc: 'See all changes containing "tags" and "bool"'
|
|
59
|
+
c.example 'doing changes -l "> 2.1" -s "pattern"', desc: 'Lookup and search can be combined'
|
|
60
|
+
|
|
61
|
+
c.action do |_global_options, options, _args|
|
|
62
|
+
cl = Doing::Changes.new(lookup: options[:lookup], search: options[:search], changes: options[:changes], sort: options[:sort])
|
|
63
|
+
|
|
64
|
+
if options[:interactive]
|
|
65
|
+
cl.interactive
|
|
66
|
+
else
|
|
67
|
+
content = if options[:all] || options[:search] || options[:lookup]
|
|
68
|
+
cl.to_s
|
|
69
|
+
else
|
|
70
|
+
cl.latest
|
|
71
|
+
end
|
|
72
|
+
|
|
73
|
+
parsed = if (options[:markdown] || !$stdout.isatty) && !options[:render]
|
|
74
|
+
content
|
|
75
|
+
else
|
|
76
|
+
TTY::Markdown.parse(content, width: 80, theme: MARKDOWN_THEME, symbols: { override: { bullet: '•' } })
|
|
77
|
+
end
|
|
78
|
+
|
|
79
|
+
Doing::Pager.paginate = true
|
|
80
|
+
Doing::Pager.page parsed
|
|
81
|
+
end
|
|
82
|
+
end
|
|
83
|
+
end
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
# @@choose
|
|
2
|
+
desc 'Select a section to display from a menu'
|
|
3
|
+
command :choose do |c|
|
|
4
|
+
c.action do |_global_options, _options, _args|
|
|
5
|
+
section = @wwid.choose_section
|
|
6
|
+
|
|
7
|
+
Doing::Pager.page @wwid.list_section({ section: section.cap_first, count: 0 }) if section
|
|
8
|
+
end
|
|
9
|
+
end
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
# @@colors
|
|
2
|
+
desc 'List available color variables for configuration templates and views'
|
|
3
|
+
command :colors do |c|
|
|
4
|
+
c.action do |_global_options, _options, _args|
|
|
5
|
+
bgs = []
|
|
6
|
+
fgs = []
|
|
7
|
+
@colors::attributes.each do |color|
|
|
8
|
+
colname = color.to_s
|
|
9
|
+
colname << " (#{color.to_s.sub(/bold/, 'bright')})" if colname =~ /bold/
|
|
10
|
+
if color.to_s =~ /bg/
|
|
11
|
+
bgs.push("#{@colors.send(color, " ")}#{@colors.default} <-- #{colname}")
|
|
12
|
+
else
|
|
13
|
+
fgs.push("#{@colors.send(color, "XXXX")}#{@colors.default} <-- #{colname}")
|
|
14
|
+
end
|
|
15
|
+
end
|
|
16
|
+
out = []
|
|
17
|
+
out << fgs.join("\n")
|
|
18
|
+
out << bgs.join("\n")
|
|
19
|
+
Doing::Pager.page out.join("\n")
|
|
20
|
+
end
|
|
21
|
+
end
|
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
# @@commands
|
|
4
|
+
desc 'Enable and disable Doing commands'
|
|
5
|
+
command :commands do |c|
|
|
6
|
+
c.example 'doing commands add', desc: 'Get a menu of available commands'
|
|
7
|
+
c.example 'doing commands add COMMAND', desc: 'Specify a command to enable'
|
|
8
|
+
c.example 'doing commands remove COMMAND', desc: 'Specify a command to disable'
|
|
9
|
+
|
|
10
|
+
c.default_command :add
|
|
11
|
+
|
|
12
|
+
# @@commands.enable
|
|
13
|
+
c.desc 'Enable Doing commands'
|
|
14
|
+
c.long_desc 'Run without arguments to select commands from a list.'
|
|
15
|
+
c.arg_name 'COMMAND [COMMAND...]'
|
|
16
|
+
c.command %i[add enable] do |add|
|
|
17
|
+
add.action do |_global, _options, args|
|
|
18
|
+
cfg = @settings
|
|
19
|
+
custom_dir = @settings.dig('plugins', 'command_path')
|
|
20
|
+
|
|
21
|
+
available = cfg['disabled_commands']
|
|
22
|
+
raise UserCancelled, 'No commands available to enable' unless args.good? || available.good?
|
|
23
|
+
|
|
24
|
+
to_enable = if args.good?
|
|
25
|
+
args
|
|
26
|
+
else
|
|
27
|
+
Doing::Prompt.choose_from(available,
|
|
28
|
+
prompt: 'Select commands to enable',
|
|
29
|
+
multiple: true,
|
|
30
|
+
sorted: true)
|
|
31
|
+
end
|
|
32
|
+
raise UserCancelled unless to_enable
|
|
33
|
+
|
|
34
|
+
to_enable.strip.split("\n").each do |cmd|
|
|
35
|
+
default_command = File.join(File.dirname(__FILE__), "#{cmd}.rb")
|
|
36
|
+
custom_command = File.join(File.expand_path(custom_dir), "#{cmd}.rb")
|
|
37
|
+
unless File.exist?(default_command) || File.exist?(custom_command)
|
|
38
|
+
raise InvalidArgument, "Command #{cmd} not found"
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
raise InvalidArgument, "Command #{cmd} is not disabled" unless available.include?(cmd)
|
|
42
|
+
|
|
43
|
+
available.delete(cmd)
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
cfg.deep_set(['disabled_commands'], available)
|
|
47
|
+
|
|
48
|
+
Doing::Util.write_to_file(@config.config_file, YAML.dump(cfg), backup: true)
|
|
49
|
+
Doing.logger.warn('Config:', "#{@config.config_file} updated")
|
|
50
|
+
end
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
# @@commands.disable
|
|
54
|
+
c.desc 'Disable Doing commands'
|
|
55
|
+
c.command %i[remove disable] do |remove|
|
|
56
|
+
remove.action do |_global, _options, args|
|
|
57
|
+
available = Dir.glob(File.join(File.dirname(__FILE__), '*.rb')).map { |cmd| File.basename(cmd, '.rb') }
|
|
58
|
+
cfg = @settings
|
|
59
|
+
custom_dir = @settings.dig('plugins', 'command_path')
|
|
60
|
+
custom_commands = Dir.glob(File.join(File.expand_path(custom_dir), '*.rb'))
|
|
61
|
+
available.concat(custom_commands.map { |cmd| File.basename(cmd, '.rb') })
|
|
62
|
+
disabled = cfg['disabled_commands']
|
|
63
|
+
disabled.each { |cmd| available.delete(cmd) }
|
|
64
|
+
to_disable = if args.good?
|
|
65
|
+
args
|
|
66
|
+
else
|
|
67
|
+
Doing::Prompt.choose_from(available,
|
|
68
|
+
prompt: 'Select commands to enable',
|
|
69
|
+
multiple: true,
|
|
70
|
+
sorted: true).strip.split("\n")
|
|
71
|
+
end
|
|
72
|
+
to_disable.each do |cmd|
|
|
73
|
+
default_command = File.join(File.dirname(__FILE__), "#{cmd}.rb")
|
|
74
|
+
custom_command = File.join(File.expand_path(custom_dir), "#{cmd}.rb")
|
|
75
|
+
unless File.exist?(default_command) || File.exist?(custom_command)
|
|
76
|
+
raise InvalidArgument, "Command #{cmd} not found"
|
|
77
|
+
|
|
78
|
+
end
|
|
79
|
+
|
|
80
|
+
raise InvalidArgument, "Command #{cmd} is not enabled" unless available.include?(cmd)
|
|
81
|
+
end
|
|
82
|
+
|
|
83
|
+
cfg.deep_set(['disabled_commands'], disabled.concat(to_disable))
|
|
84
|
+
|
|
85
|
+
Doing::Util.write_to_file(@config.config_file, YAML.dump(cfg), backup: true)
|
|
86
|
+
Doing.logger.warn('Config:', "#{@config.config_file} updated")
|
|
87
|
+
end
|
|
88
|
+
end
|
|
89
|
+
end
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
# @@commands_accepting
|
|
4
|
+
arg_name 'OPTION'
|
|
5
|
+
command :commands_accepting do |c|
|
|
6
|
+
c.desc 'Output in single column for completion'
|
|
7
|
+
c.switch %i[c column]
|
|
8
|
+
|
|
9
|
+
c.desc 'Join multiple arguments using boolean (AND|OR|NOT)'
|
|
10
|
+
c.flag [:bool], must_match: REGEX_BOOL,
|
|
11
|
+
default_value: :and,
|
|
12
|
+
type: BooleanSymbol
|
|
13
|
+
|
|
14
|
+
c.action do |g, o, a|
|
|
15
|
+
cmds = []
|
|
16
|
+
commands.each { |cmd, v| cmds.push(cmd) if has_flags?(v, a, o[:bool]) }
|
|
17
|
+
|
|
18
|
+
if o[:column]
|
|
19
|
+
puts cmds.sort
|
|
20
|
+
else
|
|
21
|
+
description = "Commands "
|
|
22
|
+
description += "not " if o[:bool] == :not
|
|
23
|
+
description += "accepting "
|
|
24
|
+
description += a.map { |arg| "--#{arg}" }.join(o[:bool] == :and ? ' and ' : ' or ')
|
|
25
|
+
puts "#{description}: #{cmds.sort.join(', ')}"
|
|
26
|
+
end
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
def has_flags?(options, args, bool)
|
|
30
|
+
case bool
|
|
31
|
+
when :and
|
|
32
|
+
all_flags?(options, args)
|
|
33
|
+
when :not
|
|
34
|
+
no_flags?(options, args)
|
|
35
|
+
else
|
|
36
|
+
any_flags?(options, args)
|
|
37
|
+
end
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
def all_flags?(options, args)
|
|
41
|
+
args.each do |arg|
|
|
42
|
+
has_flag = false
|
|
43
|
+
options.flags.merge(options.switches).each do |_, flag|
|
|
44
|
+
if flag.name == arg.to_sym || flag.aliases&.include?(arg.to_sym)
|
|
45
|
+
has_flag = true
|
|
46
|
+
break
|
|
47
|
+
end
|
|
48
|
+
end
|
|
49
|
+
return false unless has_flag
|
|
50
|
+
end
|
|
51
|
+
|
|
52
|
+
true
|
|
53
|
+
end
|
|
54
|
+
|
|
55
|
+
def any_flags?(options, args)
|
|
56
|
+
args.each do |option|
|
|
57
|
+
options.flags.merge(options.switches).each do |_, flag|
|
|
58
|
+
return true if flag.name == option.to_sym || flag.aliases&.include?(option.to_sym)
|
|
59
|
+
end
|
|
60
|
+
end
|
|
61
|
+
|
|
62
|
+
false
|
|
63
|
+
end
|
|
64
|
+
|
|
65
|
+
def no_flags?(options, args)
|
|
66
|
+
args.each do |option|
|
|
67
|
+
options.flags.merge(options.switches).each do |_, flag|
|
|
68
|
+
return false if flag.name == option.to_sym || flag.aliases&.include?(option.to_sym)
|
|
69
|
+
end
|
|
70
|
+
end
|
|
71
|
+
|
|
72
|
+
true
|
|
73
|
+
end
|
|
74
|
+
end
|
|
75
|
+
|
|
76
|
+
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
# @@completion
|
|
4
|
+
desc 'Generate shell completion scripts'
|
|
5
|
+
long_desc 'Generates the necessary scripts to add command line completion to various shells,
|
|
6
|
+
so typing \'doing\' and hitting tab will offer completions of subcommands and their options.'
|
|
7
|
+
command :completion do |c|
|
|
8
|
+
c.example 'doing completion', desc: 'Output zsh (default) to STDOUT'
|
|
9
|
+
c.example 'doing completion --type zsh --file ~/.zsh-completions/_doing.zsh',
|
|
10
|
+
desc: 'Output zsh completions to file'
|
|
11
|
+
c.example 'doing completion --type fish --file ~/.config/fish/completions/doing.fish',
|
|
12
|
+
desc: 'Output fish completions to file'
|
|
13
|
+
c.example 'doing completion --type bash --file ~/.bash_it/completion/enabled/doing.bash',
|
|
14
|
+
desc: 'Output bash completions to file'
|
|
15
|
+
|
|
16
|
+
c.desc 'Shell to generate for (bash, zsh, fish)'
|
|
17
|
+
c.arg_name 'SHELL'
|
|
18
|
+
c.flag %i[t type], must_match: /^(?:[bzf](?:[ai]?sh)?|all)$/i, default_value: 'zsh'
|
|
19
|
+
|
|
20
|
+
c.desc 'File to write output to'
|
|
21
|
+
c.arg_name 'PATH'
|
|
22
|
+
c.flag %i[f file], default_value: 'STDOUT'
|
|
23
|
+
|
|
24
|
+
c.action do |_global_options, options, _args|
|
|
25
|
+
Doing::Completion.generate_completion(type: options[:type], file: options[:file])
|
|
26
|
+
end
|
|
27
|
+
end
|