doing 1.0.93 → 2.0.6.pre
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/AUTHORS +19 -0
- data/CHANGELOG.md +616 -0
- data/COMMANDS.md +1181 -0
- data/Gemfile +2 -0
- data/Gemfile.lock +110 -0
- data/LICENSE +23 -0
- data/README.md +15 -699
- data/Rakefile +79 -0
- data/_config.yml +1 -0
- data/bin/doing +1055 -494
- data/doing.gemspec +34 -0
- data/doing.rdoc +1839 -0
- data/example_plugin.rb +209 -0
- data/generate_completions.sh +5 -0
- data/img/doing-colors.jpg +0 -0
- data/img/doing-printf-wrap-800.jpg +0 -0
- data/img/doing-show-note-formatting-800.jpg +0 -0
- data/lib/completion/_doing.zsh +203 -0
- data/lib/completion/doing.bash +449 -0
- data/lib/completion/doing.fish +329 -0
- data/lib/doing/array.rb +8 -0
- data/lib/doing/cli_status.rb +70 -0
- data/lib/doing/colors.rb +136 -0
- data/lib/doing/configuration.rb +312 -0
- data/lib/doing/errors.rb +109 -0
- data/lib/doing/hash.rb +31 -0
- data/lib/doing/hooks.rb +59 -0
- data/lib/doing/item.rb +155 -0
- data/lib/doing/log_adapter.rb +344 -0
- data/lib/doing/markdown_document_listener.rb +174 -0
- data/lib/doing/note.rb +59 -0
- data/lib/doing/pager.rb +95 -0
- data/lib/doing/plugin_manager.rb +208 -0
- data/lib/doing/plugins/export/csv_export.rb +48 -0
- data/lib/doing/plugins/export/html_export.rb +83 -0
- data/lib/doing/plugins/export/json_export.rb +140 -0
- data/lib/doing/plugins/export/markdown_export.rb +85 -0
- data/lib/doing/plugins/export/taskpaper_export.rb +34 -0
- data/lib/doing/plugins/export/template_export.rb +141 -0
- data/lib/doing/plugins/import/cal_to_json.scpt +0 -0
- data/lib/doing/plugins/import/calendar_import.rb +76 -0
- data/lib/doing/plugins/import/doing_import.rb +144 -0
- data/lib/doing/plugins/import/timing_import.rb +78 -0
- data/lib/doing/string.rb +348 -0
- data/lib/doing/symbol.rb +16 -0
- data/lib/doing/time.rb +18 -0
- data/lib/doing/util.rb +186 -0
- data/lib/doing/version.rb +1 -1
- data/lib/doing/wwid.rb +1868 -2349
- data/lib/doing/wwidfile.rb +117 -0
- data/lib/doing.rb +43 -3
- data/lib/examples/commands/autotag.rb +63 -0
- data/lib/examples/commands/wiki.rb +81 -0
- data/lib/examples/plugins/hooks.rb +22 -0
- data/lib/examples/plugins/say_export.rb +202 -0
- data/lib/examples/plugins/templates/wiki.css +169 -0
- data/lib/examples/plugins/templates/wiki.haml +27 -0
- data/lib/examples/plugins/templates/wiki_index.haml +18 -0
- data/lib/examples/plugins/wiki_export.rb +87 -0
- data/lib/templates/doing-markdown.erb +5 -0
- data/man/doing.1 +964 -0
- data/man/doing.1.html +711 -0
- data/man/doing.1.ronn +600 -0
- data/package-lock.json +3 -0
- data/rdoc_to_mmd.rb +42 -0
- data/rdocfixer.rb +13 -0
- data/scripts/generate_bash_completions.rb +211 -0
- data/scripts/generate_fish_completions.rb +204 -0
- data/scripts/generate_zsh_completions.rb +168 -0
- metadata +82 -7
- data/lib/doing/helpers.rb +0 -191
- data/lib/doing/markdown_export.rb +0 -16
@@ -0,0 +1,211 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
$LOAD_PATH.unshift File.join(__dir__, '..', 'lib')
|
3
|
+
require 'doing/cli_status'
|
4
|
+
|
5
|
+
require 'shellwords'
|
6
|
+
|
7
|
+
class ::String
|
8
|
+
def short_desc
|
9
|
+
split(/[,.]/)[0].sub(/ \(.*?\)?$/, '').strip
|
10
|
+
end
|
11
|
+
|
12
|
+
def ltrunc(max)
|
13
|
+
if length > max
|
14
|
+
sub(/^.*?(.{#{max - 3}})$/, '...\1')
|
15
|
+
else
|
16
|
+
self
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
def ltrunc!(max)
|
21
|
+
replace ltrunc(max)
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
class BashCompletions
|
26
|
+
include Status
|
27
|
+
|
28
|
+
attr_accessor :commands, :global_options
|
29
|
+
|
30
|
+
def main_function
|
31
|
+
first = true
|
32
|
+
out = []
|
33
|
+
logic = []
|
34
|
+
need_export = []
|
35
|
+
# processing = []
|
36
|
+
|
37
|
+
@commands.each_with_index do |cmd, i|
|
38
|
+
# processing << cmd[:commands].first
|
39
|
+
processing = cmd[:commands]
|
40
|
+
progress('Processing subcommand options', i, @commands.count, processing)
|
41
|
+
|
42
|
+
data = get_help_sections(cmd[:commands].first)
|
43
|
+
|
44
|
+
arg = data[:synopsis].join(' ').strip.split(/ /).last
|
45
|
+
case arg
|
46
|
+
when /(path|file)/i
|
47
|
+
type = :file
|
48
|
+
when /sect/i
|
49
|
+
type = 'sections'
|
50
|
+
when /view/i
|
51
|
+
type = 'views'
|
52
|
+
else
|
53
|
+
type = nil
|
54
|
+
end
|
55
|
+
|
56
|
+
if data[:command_options]
|
57
|
+
options = parse_options(data[:command_options])
|
58
|
+
out << command_function(cmd[:commands].first, options, type)
|
59
|
+
|
60
|
+
if first
|
61
|
+
op = 'if'
|
62
|
+
first = false
|
63
|
+
else
|
64
|
+
op = 'elif'
|
65
|
+
end
|
66
|
+
logic << %(#{op} [[ $last =~ (#{cmd[:commands].join('|')}) ]]; then _doing_#{cmd[:commands].first})
|
67
|
+
end
|
68
|
+
end
|
69
|
+
|
70
|
+
out << <<~EOFUNC
|
71
|
+
_doing()
|
72
|
+
{
|
73
|
+
local last="${@: -1}"
|
74
|
+
local token=${COMP_WORDS[$COMP_CWORD]}
|
75
|
+
|
76
|
+
#{logic.join("\n ")}
|
77
|
+
else
|
78
|
+
OLD_IFS="$IFS"
|
79
|
+
IFS=$'\n'
|
80
|
+
COMPREPLY=( $(compgen -W "$(doing help -c)" -- $token) )
|
81
|
+
IFS="$OLD_IFS"
|
82
|
+
fi
|
83
|
+
}
|
84
|
+
EOFUNC
|
85
|
+
clear
|
86
|
+
out.join("\n")
|
87
|
+
end
|
88
|
+
|
89
|
+
def command_function(command, options, type)
|
90
|
+
long_options = []
|
91
|
+
short_options = []
|
92
|
+
|
93
|
+
options.each do |o|
|
94
|
+
next if o.nil?
|
95
|
+
|
96
|
+
long_options << o[:long] if o[:long]
|
97
|
+
short_options << o[:short] if o[:short]
|
98
|
+
end
|
99
|
+
|
100
|
+
long = long_options.map! {|o| "--#{o}"}.join(' ')
|
101
|
+
short = short_options.map! {|o| "-#{o}"}.join(' ')
|
102
|
+
words = ''
|
103
|
+
logic = ''
|
104
|
+
words, logic = get_words(type) if type && type.is_a?(String)
|
105
|
+
|
106
|
+
func = <<~ENDFUNC
|
107
|
+
_doing_#{command}() {
|
108
|
+
#{words}
|
109
|
+
if [[ "$token" == --* ]]; then
|
110
|
+
COMPREPLY=( $( compgen -W '#{long}' -- $token ) )
|
111
|
+
elif [[ "$token" == -* ]]; then
|
112
|
+
COMPREPLY=( $( compgen -W '#{short} #{long}' -- $token ) )
|
113
|
+
#{logic}
|
114
|
+
fi
|
115
|
+
}
|
116
|
+
ENDFUNC
|
117
|
+
|
118
|
+
func
|
119
|
+
end
|
120
|
+
|
121
|
+
def get_words(type)
|
122
|
+
func = <<~EOFUNC
|
123
|
+
OLD_IFS="$IFS"
|
124
|
+
local token=${COMP_WORDS[$COMP_CWORD]}
|
125
|
+
IFS=$'\t'
|
126
|
+
local words=$(doing #{type})
|
127
|
+
IFS="$OLD_IFS"
|
128
|
+
EOFUNC
|
129
|
+
|
130
|
+
logic = <<~EOLOGIC
|
131
|
+
else
|
132
|
+
local nocasematchWasOff=0
|
133
|
+
shopt nocasematch >/dev/null || nocasematchWasOff=1
|
134
|
+
(( nocasematchWasOff )) && shopt -s nocasematch
|
135
|
+
local w matches=()
|
136
|
+
OLD_IFS="$IFS"
|
137
|
+
IFS=$'\t'‰
|
138
|
+
for w in $words; do
|
139
|
+
if [[ "$w" == "$token"* ]]; then
|
140
|
+
matches+=("${w// /\ }")
|
141
|
+
fi
|
142
|
+
done
|
143
|
+
IFS="$OLD_IFS"
|
144
|
+
(( nocasematchWasOff )) && shopt -u nocasematch
|
145
|
+
COMPREPLY=("${matches[@]}")
|
146
|
+
EOLOGIC
|
147
|
+
|
148
|
+
[func, logic]
|
149
|
+
end
|
150
|
+
|
151
|
+
|
152
|
+
|
153
|
+
def get_help_sections(command = '')
|
154
|
+
res = `doing help #{command}`.strip
|
155
|
+
scanned = res.scan(/(?m-i)^([A-Z ]+)\n([\s\S]*?)(?=\n+[A-Z]+|\Z)/)
|
156
|
+
sections = {}
|
157
|
+
scanned.each do |sect|
|
158
|
+
title = sect[0].downcase.strip.gsub(/ +/, '_').to_sym
|
159
|
+
content = sect[1].split(/\n/).map(&:strip).delete_if(&:empty?)
|
160
|
+
sections[title] = content
|
161
|
+
end
|
162
|
+
sections
|
163
|
+
end
|
164
|
+
|
165
|
+
def parse_option(option)
|
166
|
+
res = option.match(/(?:-(?<short>\w), )?(?:--(?:\[no-\])?(?<long>[\w_]+)(?:=(?<arg>\w+))?)\s+- (?<desc>.*?)$/)
|
167
|
+
return nil unless res
|
168
|
+
{
|
169
|
+
short: res['short'],
|
170
|
+
long: res['long'],
|
171
|
+
arg: res[:arg],
|
172
|
+
description: res['desc'].short_desc
|
173
|
+
}
|
174
|
+
end
|
175
|
+
|
176
|
+
def parse_options(options)
|
177
|
+
options.map { |opt| parse_option(opt) }
|
178
|
+
end
|
179
|
+
|
180
|
+
def parse_command(command)
|
181
|
+
res = command.match(/^(?<cmd>[^, \t]+)(?<alias>(?:, [^, \t]+)*)?\s+- (?<desc>.*?)$/)
|
182
|
+
commands = [res['cmd']]
|
183
|
+
commands.concat(res['alias'].split(/, /).delete_if(&:empty?)) if res['alias']
|
184
|
+
|
185
|
+
{
|
186
|
+
commands: commands,
|
187
|
+
description: res['desc'].short_desc
|
188
|
+
}
|
189
|
+
end
|
190
|
+
|
191
|
+
def parse_commands(commands)
|
192
|
+
commands.map { |cmd| parse_command(cmd) }
|
193
|
+
end
|
194
|
+
|
195
|
+
def initialize
|
196
|
+
status('Generating Bash completions', reset: false)
|
197
|
+
data = get_help_sections
|
198
|
+
@global_options = parse_options(data[:global_options])
|
199
|
+
@commands = parse_commands(data[:commands])
|
200
|
+
end
|
201
|
+
|
202
|
+
def generate_completions
|
203
|
+
out = []
|
204
|
+
out << main_function
|
205
|
+
out << 'complete -F _doing doing'
|
206
|
+
status('Complete', reset: false)
|
207
|
+
out.join("\n")
|
208
|
+
end
|
209
|
+
end
|
210
|
+
|
211
|
+
puts BashCompletions.new.generate_completions
|
@@ -0,0 +1,204 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
$LOAD_PATH.unshift File.join(__dir__, '..', 'lib')
|
3
|
+
require 'doing/cli_status'
|
4
|
+
|
5
|
+
require 'shellwords'
|
6
|
+
|
7
|
+
class ::String
|
8
|
+
def short_desc
|
9
|
+
split(/[,.]/)[0].sub(/ \(.*?\)?$/, '').strip
|
10
|
+
end
|
11
|
+
|
12
|
+
def ltrunc(max)
|
13
|
+
if length > max
|
14
|
+
sub(/^.*?(.{#{max - 3}})$/, '...\1')
|
15
|
+
else
|
16
|
+
self
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
def ltrunc!(max)
|
21
|
+
replace ltrunc(max)
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
class FishCompletions
|
26
|
+
include Status
|
27
|
+
|
28
|
+
attr_accessor :commands, :global_options
|
29
|
+
|
30
|
+
def generate_helpers
|
31
|
+
<<~EOFUNCTIONS
|
32
|
+
function __fish_doing_needs_command
|
33
|
+
# Figure out if the current invocation already has a command.
|
34
|
+
|
35
|
+
set -l opts h-help config_file= f-doing_file= n-notes v-version stdout d-debug default x-noauto
|
36
|
+
set cmd (commandline -opc)
|
37
|
+
set -e cmd[1]
|
38
|
+
argparse -s $opts -- $cmd 2>/dev/null
|
39
|
+
or return 0
|
40
|
+
# These flags function as commands, effectively.
|
41
|
+
if set -q argv[1]
|
42
|
+
# Also print the command, so this can be used to figure out what it is.
|
43
|
+
echo $argv[1]
|
44
|
+
return 1
|
45
|
+
end
|
46
|
+
return 0
|
47
|
+
end
|
48
|
+
|
49
|
+
function __fish_doing_using_command
|
50
|
+
set -l cmd (__fish_doing_needs_command)
|
51
|
+
test -z "$cmd"
|
52
|
+
and return 1
|
53
|
+
contains -- $cmd $argv
|
54
|
+
and return 0
|
55
|
+
end
|
56
|
+
|
57
|
+
function __fish_doing_complete_sections
|
58
|
+
doing sections -c
|
59
|
+
end
|
60
|
+
|
61
|
+
function __fish_doing_complete_views
|
62
|
+
doing views -c
|
63
|
+
end
|
64
|
+
|
65
|
+
function __fish_doing_subcommands
|
66
|
+
doing help -c
|
67
|
+
end
|
68
|
+
|
69
|
+
function __fish_doing_export_plugins
|
70
|
+
doing plugins --type export -c
|
71
|
+
end
|
72
|
+
|
73
|
+
function __fish_doing_import_plugins
|
74
|
+
doing plugins --type import -c
|
75
|
+
end
|
76
|
+
|
77
|
+
function __fish_doing_complete_templates
|
78
|
+
doing template -c
|
79
|
+
end
|
80
|
+
|
81
|
+
complete -c doing -f
|
82
|
+
complete -xc doing -n '__fish_doing_needs_command' -a '(__fish_doing_subcommands)'
|
83
|
+
|
84
|
+
complete -f -c doing -n '__fish_doing_using_command show' -a '(__fish_doing_complete_sections)'
|
85
|
+
complete -f -c doing -n '__fish_doing_using_command view' -a '(__fish_doing_complete_views)'
|
86
|
+
complete -f -c doing -n '__fish_doing_using_command template' -a '(__fish_doing_complete_templates)'
|
87
|
+
complete -f -c doing -s t -l type -x -n '__fish_doing_using_command import' -a '(__fish_doing_import_plugins)'
|
88
|
+
|
89
|
+
complete -xc doing -n '__fish_seen_subcommand_from help; and not __fish_seen_subcommand_from (doing help -c)' -a "(doing help -c)"
|
90
|
+
EOFUNCTIONS
|
91
|
+
end
|
92
|
+
|
93
|
+
def get_help_sections(command = '')
|
94
|
+
res = `doing help #{command}`.strip
|
95
|
+
scanned = res.scan(/(?m-i)^([A-Z ]+)\n([\s\S]*?)(?=\n+[A-Z]+|\Z)/)
|
96
|
+
sections = {}
|
97
|
+
scanned.each do |sect|
|
98
|
+
title = sect[0].downcase.strip.gsub(/ +/, '_').to_sym
|
99
|
+
content = sect[1].split(/\n/).map(&:strip).delete_if(&:empty?)
|
100
|
+
sections[title] = content
|
101
|
+
end
|
102
|
+
sections
|
103
|
+
end
|
104
|
+
|
105
|
+
def parse_option(option)
|
106
|
+
res = option.match(/(?:-(?<short>\w), )?(?:--(?:\[no-\])?(?<long>[\w_]+)(?:=(?<arg>\w+))?)\s+- (?<desc>.*?)$/)
|
107
|
+
return nil unless res
|
108
|
+
{
|
109
|
+
short: res['short'],
|
110
|
+
long: res['long'],
|
111
|
+
arg: res[:arg],
|
112
|
+
description: res['desc'].short_desc
|
113
|
+
}
|
114
|
+
end
|
115
|
+
|
116
|
+
def parse_options(options)
|
117
|
+
options.map { |opt| parse_option(opt) }
|
118
|
+
end
|
119
|
+
|
120
|
+
def parse_command(command)
|
121
|
+
res = command.match(/^(?<cmd>[^, \t]+)(?<alias>(?:, [^, \t]+)*)?\s+- (?<desc>.*?)$/)
|
122
|
+
commands = [res['cmd']]
|
123
|
+
commands.concat(res['alias'].split(/, /).delete_if(&:empty?)) if res['alias']
|
124
|
+
|
125
|
+
{
|
126
|
+
commands: commands,
|
127
|
+
description: res['desc'].short_desc
|
128
|
+
}
|
129
|
+
end
|
130
|
+
|
131
|
+
def parse_commands(commands)
|
132
|
+
commands.map { |cmd| parse_command(cmd) }
|
133
|
+
end
|
134
|
+
|
135
|
+
def generate_subcommand_completions
|
136
|
+
out = []
|
137
|
+
# processing = []
|
138
|
+
@commands.each_with_index do |cmd, i|
|
139
|
+
# processing << cmd[:commands].first
|
140
|
+
processing = cmd[:commands]
|
141
|
+
progress('Processing subcommands', i, @commands.count, processing)
|
142
|
+
out << "complete -xc doing -n '__fish_doing_needs_command' -a '#{cmd[:commands].join(' ')}' -d #{Shellwords.escape(cmd[:description])}"
|
143
|
+
end
|
144
|
+
|
145
|
+
out.join("\n")
|
146
|
+
end
|
147
|
+
|
148
|
+
def generate_subcommand_option_completions
|
149
|
+
|
150
|
+
out = []
|
151
|
+
need_export = []
|
152
|
+
# processing = []
|
153
|
+
|
154
|
+
@commands.each_with_index do |cmd, i|
|
155
|
+
# processing << cmd[:commands].first
|
156
|
+
processing = cmd[:commands]
|
157
|
+
progress('Processing subcommand options', i, @commands.count, processing)
|
158
|
+
|
159
|
+
data = get_help_sections(cmd[:commands].first)
|
160
|
+
|
161
|
+
if data[:synopsis].join(' ').strip.split(/ /).last =~ /(path|file)/i
|
162
|
+
out << "complete -c doing -F -n '__fish_doing_using_command #{cmd[:commands].join(" ")}'"
|
163
|
+
end
|
164
|
+
|
165
|
+
if data[:command_options]
|
166
|
+
parse_options(data[:command_options]).each do |option|
|
167
|
+
next if option.nil?
|
168
|
+
|
169
|
+
arg = option[:arg] ? '-r' : ''
|
170
|
+
short = option[:short] ? "-s #{option[:short]}" : ''
|
171
|
+
long = option[:long] ? "-l #{option[:long]}" : ''
|
172
|
+
out << "complete -c doing #{long} #{short} -f #{arg} -n '__fish_doing_using_command #{cmd[:commands].join(' ')}' -d #{Shellwords.escape(option[:description])}"
|
173
|
+
|
174
|
+
need_export.concat(cmd[:commands]) if option[:long] == 'output'
|
175
|
+
end
|
176
|
+
end
|
177
|
+
end
|
178
|
+
|
179
|
+
unless need_export.empty?
|
180
|
+
out << "complete -f -c doing -s o -l output -x -n '__fish_doing_using_command #{need_export.join(' ')}' -a '(__fish_doing_export_plugins)'"
|
181
|
+
end
|
182
|
+
|
183
|
+
clear
|
184
|
+
out.join("\n")
|
185
|
+
end
|
186
|
+
|
187
|
+
def initialize
|
188
|
+
status('Generating Fish completions', reset: false)
|
189
|
+
data = get_help_sections
|
190
|
+
@global_options = parse_options(data[:global_options])
|
191
|
+
@commands = parse_commands(data[:commands])
|
192
|
+
end
|
193
|
+
|
194
|
+
def generate_completions
|
195
|
+
out = []
|
196
|
+
out << generate_helpers
|
197
|
+
out << generate_subcommand_completions
|
198
|
+
out << generate_subcommand_option_completions
|
199
|
+
status('Complete', reset: false)
|
200
|
+
out.join("\n")
|
201
|
+
end
|
202
|
+
end
|
203
|
+
|
204
|
+
puts FishCompletions.new.generate_completions
|
@@ -0,0 +1,168 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
$LOAD_PATH.unshift File.join(__dir__, '..', 'lib')
|
3
|
+
require 'doing/cli_status'
|
4
|
+
|
5
|
+
require 'shellwords'
|
6
|
+
|
7
|
+
class ::String
|
8
|
+
def short_desc
|
9
|
+
split(/[,.]/)[0].sub(/ \(.*?\)?$/, '').strip
|
10
|
+
end
|
11
|
+
|
12
|
+
def ltrunc(max)
|
13
|
+
if length > max
|
14
|
+
sub(/^.*?(.{#{max - 3}})$/, '...\1')
|
15
|
+
else
|
16
|
+
self
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
def ltrunc!(max)
|
21
|
+
replace ltrunc(max)
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
class ZshCompletions
|
26
|
+
include Status
|
27
|
+
|
28
|
+
attr_accessor :commands, :global_options
|
29
|
+
|
30
|
+
def generate_helpers
|
31
|
+
<<~EOFUNCTIONS
|
32
|
+
compdef _doing doing
|
33
|
+
|
34
|
+
function _doing() {
|
35
|
+
local line state
|
36
|
+
|
37
|
+
function _commands {
|
38
|
+
local -a commands
|
39
|
+
|
40
|
+
commands=(
|
41
|
+
#{generate_subcommand_completions.join("\n ")}
|
42
|
+
)
|
43
|
+
_describe 'command' commands
|
44
|
+
}
|
45
|
+
|
46
|
+
_arguments -C \
|
47
|
+
"1: :_commands" \
|
48
|
+
"*::arg:->args"
|
49
|
+
|
50
|
+
|
51
|
+
|
52
|
+
case $line[1] in
|
53
|
+
#{generate_subcommand_option_completions(indent: ' ').join("\n ")}
|
54
|
+
esac
|
55
|
+
|
56
|
+
_arguments -s $args
|
57
|
+
}
|
58
|
+
|
59
|
+
EOFUNCTIONS
|
60
|
+
end
|
61
|
+
|
62
|
+
def get_help_sections(command = '')
|
63
|
+
res = `doing help #{command}`.strip
|
64
|
+
scanned = res.scan(/(?m-i)^([A-Z ]+)\n([\s\S]*?)(?=\n+[A-Z]+|\Z)/)
|
65
|
+
sections = {}
|
66
|
+
scanned.each do |sect|
|
67
|
+
title = sect[0].downcase.strip.gsub(/ +/, '_').to_sym
|
68
|
+
content = sect[1].split(/\n/).map(&:strip).delete_if(&:empty?)
|
69
|
+
sections[title] = content
|
70
|
+
end
|
71
|
+
sections
|
72
|
+
end
|
73
|
+
|
74
|
+
def parse_option(option)
|
75
|
+
res = option.match(/(?:-(?<short>\w), )?(?:--(?:\[no-\])?(?<long>[\w_]+)(?:=(?<arg>\w+))?)\s+- (?<desc>.*?)$/)
|
76
|
+
return nil unless res
|
77
|
+
|
78
|
+
{
|
79
|
+
short: res['short'],
|
80
|
+
long: res['long'],
|
81
|
+
arg: res[:arg],
|
82
|
+
description: res['desc'].short_desc
|
83
|
+
}
|
84
|
+
end
|
85
|
+
|
86
|
+
def parse_options(options)
|
87
|
+
options.map { |opt| parse_option(opt) }
|
88
|
+
end
|
89
|
+
|
90
|
+
def parse_command(command)
|
91
|
+
res = command.match(/^(?<cmd>[^, \t]+)(?<alias>(?:, [^, \t]+)*)?\s+- (?<desc>.*?)$/)
|
92
|
+
commands = [res['cmd']]
|
93
|
+
commands.concat(res['alias'].split(/, /).delete_if(&:empty?)) if res['alias']
|
94
|
+
|
95
|
+
{
|
96
|
+
commands: commands,
|
97
|
+
description: res['desc'].short_desc
|
98
|
+
}
|
99
|
+
end
|
100
|
+
|
101
|
+
def parse_commands(commands)
|
102
|
+
commands.map { |cmd| parse_command(cmd) }
|
103
|
+
end
|
104
|
+
|
105
|
+
def generate_subcommand_completions
|
106
|
+
out = []
|
107
|
+
# processing = []
|
108
|
+
@commands.each_with_index do |cmd, i|
|
109
|
+
# processing << cmd[:commands].first
|
110
|
+
processing = cmd[:commands]
|
111
|
+
progress('Processing subcommands', i, @commands.count, processing)
|
112
|
+
cmd[:commands].each do |c|
|
113
|
+
out << "'#{c}:#{cmd[:description].gsub(/'/, '\\\'')}'"
|
114
|
+
end
|
115
|
+
end
|
116
|
+
clear
|
117
|
+
out
|
118
|
+
end
|
119
|
+
|
120
|
+
def generate_subcommand_option_completions(indent: ' ')
|
121
|
+
|
122
|
+
out = []
|
123
|
+
# processing = []
|
124
|
+
|
125
|
+
@commands.each_with_index do |cmd, i|
|
126
|
+
# processing << cmd[:commands].first
|
127
|
+
processing = cmd[:commands]
|
128
|
+
progress('Processing subcommand options', i, @commands.count, processing)
|
129
|
+
|
130
|
+
data = get_help_sections(cmd[:commands].first)
|
131
|
+
option_arr = []
|
132
|
+
|
133
|
+
if data[:command_options]
|
134
|
+
parse_options(data[:command_options]).each do |option|
|
135
|
+
next if option.nil?
|
136
|
+
|
137
|
+
arg = option[:arg] ? '=' : ''
|
138
|
+
|
139
|
+
option_arr << if option[:short]
|
140
|
+
%({-#{option[:short]},--#{option[:long]}#{arg}}"[#{option[:description].gsub(/'/, '\\\'')}]")
|
141
|
+
else
|
142
|
+
%("(--#{option[:long]}#{arg})--#{option[:long]}#{arg}}[#{option[:description].gsub(/'/, '\\\'')}]")
|
143
|
+
end
|
144
|
+
end
|
145
|
+
end
|
146
|
+
|
147
|
+
cmd[:commands].each do |c|
|
148
|
+
out << "#{c}) \n#{indent} args=( #{option_arr.join(' ')} )\n#{indent};;"
|
149
|
+
end
|
150
|
+
end
|
151
|
+
|
152
|
+
out
|
153
|
+
end
|
154
|
+
|
155
|
+
def initialize
|
156
|
+
status('Generating Zsh completions', reset: false)
|
157
|
+
data = get_help_sections
|
158
|
+
@global_options = parse_options(data[:global_options])
|
159
|
+
@commands = parse_commands(data[:commands])
|
160
|
+
end
|
161
|
+
|
162
|
+
def generate_completions
|
163
|
+
generate_helpers
|
164
|
+
status('Complete', reset: false)
|
165
|
+
end
|
166
|
+
end
|
167
|
+
|
168
|
+
puts ZshCompletions.new.generate_completions
|
metadata
CHANGED
@@ -1,15 +1,29 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: doing
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version:
|
4
|
+
version: 2.0.6.pre
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Brett Terpstra
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2021-
|
11
|
+
date: 2021-11-18 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: safe_yaml
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - "~>"
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '1.0'
|
20
|
+
type: :runtime
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - "~>"
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '1.0'
|
13
27
|
- !ruby/object:Gem::Dependency
|
14
28
|
name: rake
|
15
29
|
requirement: !ruby/object:Gem::Requirement
|
@@ -162,16 +176,78 @@ extensions: []
|
|
162
176
|
extra_rdoc_files:
|
163
177
|
- README.md
|
164
178
|
files:
|
179
|
+
- AUTHORS
|
180
|
+
- CHANGELOG.md
|
181
|
+
- COMMANDS.md
|
182
|
+
- Gemfile
|
183
|
+
- Gemfile.lock
|
184
|
+
- LICENSE
|
165
185
|
- README.md
|
186
|
+
- Rakefile
|
187
|
+
- _config.yml
|
166
188
|
- bin/doing
|
189
|
+
- doing.gemspec
|
190
|
+
- doing.rdoc
|
191
|
+
- example_plugin.rb
|
192
|
+
- generate_completions.sh
|
193
|
+
- img/doing-colors.jpg
|
194
|
+
- img/doing-printf-wrap-800.jpg
|
195
|
+
- img/doing-show-note-formatting-800.jpg
|
196
|
+
- lib/completion/_doing.zsh
|
197
|
+
- lib/completion/doing.bash
|
198
|
+
- lib/completion/doing.fish
|
167
199
|
- lib/doing.rb
|
168
|
-
- lib/doing/
|
169
|
-
- lib/doing/
|
200
|
+
- lib/doing/array.rb
|
201
|
+
- lib/doing/cli_status.rb
|
202
|
+
- lib/doing/colors.rb
|
203
|
+
- lib/doing/configuration.rb
|
204
|
+
- lib/doing/errors.rb
|
205
|
+
- lib/doing/hash.rb
|
206
|
+
- lib/doing/hooks.rb
|
207
|
+
- lib/doing/item.rb
|
208
|
+
- lib/doing/log_adapter.rb
|
209
|
+
- lib/doing/markdown_document_listener.rb
|
210
|
+
- lib/doing/note.rb
|
211
|
+
- lib/doing/pager.rb
|
212
|
+
- lib/doing/plugin_manager.rb
|
213
|
+
- lib/doing/plugins/export/csv_export.rb
|
214
|
+
- lib/doing/plugins/export/html_export.rb
|
215
|
+
- lib/doing/plugins/export/json_export.rb
|
216
|
+
- lib/doing/plugins/export/markdown_export.rb
|
217
|
+
- lib/doing/plugins/export/taskpaper_export.rb
|
218
|
+
- lib/doing/plugins/export/template_export.rb
|
219
|
+
- lib/doing/plugins/import/cal_to_json.scpt
|
220
|
+
- lib/doing/plugins/import/calendar_import.rb
|
221
|
+
- lib/doing/plugins/import/doing_import.rb
|
222
|
+
- lib/doing/plugins/import/timing_import.rb
|
223
|
+
- lib/doing/string.rb
|
224
|
+
- lib/doing/symbol.rb
|
225
|
+
- lib/doing/time.rb
|
226
|
+
- lib/doing/util.rb
|
170
227
|
- lib/doing/version.rb
|
171
228
|
- lib/doing/wwid.rb
|
229
|
+
- lib/doing/wwidfile.rb
|
230
|
+
- lib/examples/commands/autotag.rb
|
231
|
+
- lib/examples/commands/wiki.rb
|
232
|
+
- lib/examples/plugins/hooks.rb
|
233
|
+
- lib/examples/plugins/say_export.rb
|
234
|
+
- lib/examples/plugins/templates/wiki.css
|
235
|
+
- lib/examples/plugins/templates/wiki.haml
|
236
|
+
- lib/examples/plugins/templates/wiki_index.haml
|
237
|
+
- lib/examples/plugins/wiki_export.rb
|
172
238
|
- lib/helpers/fuzzyfilefinder
|
239
|
+
- lib/templates/doing-markdown.erb
|
173
240
|
- lib/templates/doing.css
|
174
241
|
- lib/templates/doing.haml
|
242
|
+
- man/doing.1
|
243
|
+
- man/doing.1.html
|
244
|
+
- man/doing.1.ronn
|
245
|
+
- package-lock.json
|
246
|
+
- rdoc_to_mmd.rb
|
247
|
+
- rdocfixer.rb
|
248
|
+
- scripts/generate_bash_completions.rb
|
249
|
+
- scripts/generate_fish_completions.rb
|
250
|
+
- scripts/generate_zsh_completions.rb
|
175
251
|
homepage: http://brettterpstra.com/project/doing/
|
176
252
|
licenses:
|
177
253
|
- MIT
|
@@ -184,7 +260,6 @@ rdoc_options:
|
|
184
260
|
- README.md
|
185
261
|
- "--markup"
|
186
262
|
- markdown
|
187
|
-
- "-ri"
|
188
263
|
require_paths:
|
189
264
|
- lib
|
190
265
|
- lib
|
@@ -195,9 +270,9 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
195
270
|
version: '0'
|
196
271
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
197
272
|
requirements:
|
198
|
-
- - "
|
273
|
+
- - ">"
|
199
274
|
- !ruby/object:Gem::Version
|
200
|
-
version:
|
275
|
+
version: 1.3.1
|
201
276
|
requirements: []
|
202
277
|
rubygems_version: 3.2.16
|
203
278
|
signing_key:
|