doing 1.0.91 → 2.0.3.pre
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/AUTHORS +19 -0
- data/CHANGELOG.md +590 -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 +1012 -486
- data/doing.fish +278 -0
- data/doing.gemspec +34 -0
- data/doing.rdoc +1759 -0
- data/example_plugin.rb +209 -0
- data/generate_completions.sh +4 -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 +151 -0
- data/lib/completion/doing.bash +416 -0
- data/lib/completion/doing.fish +278 -0
- data/lib/doing/array.rb +8 -0
- data/lib/doing/cli_status.rb +66 -0
- data/lib/doing/colors.rb +136 -0
- data/lib/doing/configuration.rb +310 -0
- data/lib/doing/errors.rb +102 -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 +342 -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 +346 -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 +1831 -2358
- data/lib/doing/wwidfile.rb +117 -0
- data/lib/doing.rb +44 -4
- data/lib/examples/commands/wiki.rb +80 -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 +210 -0
- data/scripts/generate_fish_completions.rb +201 -0
- data/scripts/generate_zsh_completions.rb +164 -0
- metadata +82 -6
- data/lib/doing/helpers.rb +0 -191
@@ -0,0 +1,210 @@
|
|
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
|
+
|
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 = `bundle exec bin/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
|
+
out.join("\n")
|
207
|
+
end
|
208
|
+
end
|
209
|
+
|
210
|
+
puts BashCompletions.new.generate_completions
|
@@ -0,0 +1,201 @@
|
|
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
|
+
EOFUNCTIONS
|
90
|
+
end
|
91
|
+
|
92
|
+
def get_help_sections(command = '')
|
93
|
+
res = `bundle exec bin/doing help #{command}`.strip
|
94
|
+
scanned = res.scan(/(?m-i)^([A-Z ]+)\n([\s\S]*?)(?=\n+[A-Z]+|\Z)/)
|
95
|
+
sections = {}
|
96
|
+
scanned.each do |sect|
|
97
|
+
title = sect[0].downcase.strip.gsub(/ +/, '_').to_sym
|
98
|
+
content = sect[1].split(/\n/).map(&:strip).delete_if(&:empty?)
|
99
|
+
sections[title] = content
|
100
|
+
end
|
101
|
+
sections
|
102
|
+
end
|
103
|
+
|
104
|
+
def parse_option(option)
|
105
|
+
res = option.match(/(?:-(?<short>\w), )?(?:--(?:\[no-\])?(?<long>[\w_]+)(?:=(?<arg>\w+))?)\s+- (?<desc>.*?)$/)
|
106
|
+
return nil unless res
|
107
|
+
{
|
108
|
+
short: res['short'],
|
109
|
+
long: res['long'],
|
110
|
+
arg: res[:arg],
|
111
|
+
description: res['desc'].short_desc
|
112
|
+
}
|
113
|
+
end
|
114
|
+
|
115
|
+
def parse_options(options)
|
116
|
+
options.map { |opt| parse_option(opt) }
|
117
|
+
end
|
118
|
+
|
119
|
+
def parse_command(command)
|
120
|
+
res = command.match(/^(?<cmd>[^, \t]+)(?<alias>(?:, [^, \t]+)*)?\s+- (?<desc>.*?)$/)
|
121
|
+
commands = [res['cmd']]
|
122
|
+
commands.concat(res['alias'].split(/, /).delete_if(&:empty?)) if res['alias']
|
123
|
+
|
124
|
+
{
|
125
|
+
commands: commands,
|
126
|
+
description: res['desc'].short_desc
|
127
|
+
}
|
128
|
+
end
|
129
|
+
|
130
|
+
def parse_commands(commands)
|
131
|
+
commands.map { |cmd| parse_command(cmd) }
|
132
|
+
end
|
133
|
+
|
134
|
+
def generate_subcommand_completions
|
135
|
+
out = []
|
136
|
+
# processing = []
|
137
|
+
@commands.each_with_index do |cmd, i|
|
138
|
+
# processing << cmd[:commands].first
|
139
|
+
processing = cmd[:commands]
|
140
|
+
progress('Processing subcommands', i, @commands.count, processing)
|
141
|
+
out << "complete -xc doing -n '__fish_doing_needs_command' -a '#{cmd[:commands].join(' ')}' -d #{Shellwords.escape(cmd[:description])}"
|
142
|
+
end
|
143
|
+
|
144
|
+
out.join("\n")
|
145
|
+
end
|
146
|
+
|
147
|
+
def generate_subcommand_option_completions
|
148
|
+
|
149
|
+
out = []
|
150
|
+
need_export = []
|
151
|
+
# processing = []
|
152
|
+
|
153
|
+
@commands.each_with_index do |cmd, i|
|
154
|
+
# processing << cmd[:commands].first
|
155
|
+
processing = cmd[:commands]
|
156
|
+
progress('Processing subcommand options', i, @commands.count, processing)
|
157
|
+
|
158
|
+
data = get_help_sections(cmd[:commands].first)
|
159
|
+
|
160
|
+
if data[:synopsis].join(' ').strip.split(/ /).last =~ /(path|file)/i
|
161
|
+
out << "complete -c doing -F -n '__fish_doing_using_command #{cmd[:commands].join(" ")}'"
|
162
|
+
end
|
163
|
+
|
164
|
+
if data[:command_options]
|
165
|
+
parse_options(data[:command_options]).each do |option|
|
166
|
+
next if option.nil?
|
167
|
+
|
168
|
+
arg = option[:arg] ? '-r' : ''
|
169
|
+
short = option[:short] ? "-s #{option[:short]}" : ''
|
170
|
+
long = option[:long] ? "-l #{option[:long]}" : ''
|
171
|
+
out << "complete -c doing #{long} #{short} -f #{arg} -n '__fish_doing_using_command #{cmd[:commands].join(' ')}' -d #{Shellwords.escape(option[:description])}"
|
172
|
+
|
173
|
+
need_export.concat(cmd[:commands]) if option[:long] == 'output'
|
174
|
+
end
|
175
|
+
end
|
176
|
+
end
|
177
|
+
|
178
|
+
unless need_export.empty?
|
179
|
+
out << "complete -f -c doing -s o -l output -x -n '__fish_doing_using_command #{need_export.join(' ')}' -a '(__fish_doing_export_plugins)'"
|
180
|
+
end
|
181
|
+
|
182
|
+
out.join("\n")
|
183
|
+
end
|
184
|
+
|
185
|
+
def initialize
|
186
|
+
status('Generating Fish completions', reset: false)
|
187
|
+
data = get_help_sections
|
188
|
+
@global_options = parse_options(data[:global_options])
|
189
|
+
@commands = parse_commands(data[:commands])
|
190
|
+
end
|
191
|
+
|
192
|
+
def generate_completions
|
193
|
+
out = []
|
194
|
+
out << generate_helpers
|
195
|
+
out << generate_subcommand_completions
|
196
|
+
out << generate_subcommand_option_completions
|
197
|
+
out.join("\n")
|
198
|
+
end
|
199
|
+
end
|
200
|
+
|
201
|
+
puts FishCompletions.new.generate_completions
|
@@ -0,0 +1,164 @@
|
|
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
|
+
#compdef doing
|
33
|
+
|
34
|
+
local ret=1 state
|
35
|
+
|
36
|
+
_arguments \\
|
37
|
+
':subcommand:->subcommand' \\
|
38
|
+
'*::options:->options' && ret=0
|
39
|
+
|
40
|
+
case $state in
|
41
|
+
subcommand)
|
42
|
+
local -a subcommands
|
43
|
+
subcommands=(
|
44
|
+
#{generate_subcommand_completions.join("\n ")}
|
45
|
+
)
|
46
|
+
_describe -t subcommands 'doing subcommand' subcommands && ret=0
|
47
|
+
;;
|
48
|
+
options)
|
49
|
+
case $words[1] in
|
50
|
+
#{generate_subcommand_option_completions(indent: ' ').join("\n ")}
|
51
|
+
esac
|
52
|
+
|
53
|
+
_arguments $args && ret=0
|
54
|
+
;;
|
55
|
+
esac
|
56
|
+
|
57
|
+
return ret
|
58
|
+
EOFUNCTIONS
|
59
|
+
end
|
60
|
+
|
61
|
+
def get_help_sections(command = '')
|
62
|
+
res = `bundle exec bin/doing help #{command}`.strip
|
63
|
+
scanned = res.scan(/(?m-i)^([A-Z ]+)\n([\s\S]*?)(?=\n+[A-Z]+|\Z)/)
|
64
|
+
sections = {}
|
65
|
+
scanned.each do |sect|
|
66
|
+
title = sect[0].downcase.strip.gsub(/ +/, '_').to_sym
|
67
|
+
content = sect[1].split(/\n/).map(&:strip).delete_if(&:empty?)
|
68
|
+
sections[title] = content
|
69
|
+
end
|
70
|
+
sections
|
71
|
+
end
|
72
|
+
|
73
|
+
def parse_option(option)
|
74
|
+
res = option.match(/(?:-(?<short>\w), )?(?:--(?:\[no-\])?(?<long>[\w_]+)(?:=(?<arg>\w+))?)\s+- (?<desc>.*?)$/)
|
75
|
+
return nil unless res
|
76
|
+
{
|
77
|
+
short: res['short'],
|
78
|
+
long: res['long'],
|
79
|
+
arg: res[:arg],
|
80
|
+
description: res['desc'].short_desc
|
81
|
+
}
|
82
|
+
end
|
83
|
+
|
84
|
+
def parse_options(options)
|
85
|
+
options.map { |opt| parse_option(opt) }
|
86
|
+
end
|
87
|
+
|
88
|
+
def parse_command(command)
|
89
|
+
res = command.match(/^(?<cmd>[^, \t]+)(?<alias>(?:, [^, \t]+)*)?\s+- (?<desc>.*?)$/)
|
90
|
+
commands = [res['cmd']]
|
91
|
+
commands.concat(res['alias'].split(/, /).delete_if(&:empty?)) if res['alias']
|
92
|
+
|
93
|
+
{
|
94
|
+
commands: commands,
|
95
|
+
description: res['desc'].short_desc
|
96
|
+
}
|
97
|
+
end
|
98
|
+
|
99
|
+
def parse_commands(commands)
|
100
|
+
commands.map { |cmd| parse_command(cmd) }
|
101
|
+
end
|
102
|
+
|
103
|
+
def generate_subcommand_completions
|
104
|
+
out = []
|
105
|
+
# processing = []
|
106
|
+
@commands.each_with_index do |cmd, i|
|
107
|
+
# processing << cmd[:commands].first
|
108
|
+
processing = cmd[:commands]
|
109
|
+
progress('Processing subcommands', i, @commands.count, processing)
|
110
|
+
cmd[:commands].each do |c|
|
111
|
+
out << "'#{c}:#{cmd[:description].gsub(/'/,'\\\'')}'"
|
112
|
+
end
|
113
|
+
end
|
114
|
+
|
115
|
+
out
|
116
|
+
end
|
117
|
+
|
118
|
+
def generate_subcommand_option_completions(indent: ' ')
|
119
|
+
|
120
|
+
out = []
|
121
|
+
need_export = []
|
122
|
+
# processing = []
|
123
|
+
|
124
|
+
@commands.each_with_index do |cmd, i|
|
125
|
+
# processing << cmd[:commands].first
|
126
|
+
processing = cmd[:commands]
|
127
|
+
progress('Processing subcommand options', i, @commands.count, processing)
|
128
|
+
|
129
|
+
data = get_help_sections(cmd[:commands].first)
|
130
|
+
option_arr = []
|
131
|
+
|
132
|
+
if data[:command_options]
|
133
|
+
parse_options(data[:command_options]).each do |option|
|
134
|
+
next if option.nil?
|
135
|
+
|
136
|
+
arg = option[:arg] ? '-r' : ''
|
137
|
+
short = option[:short] ? "-s #{option[:short]}" : ''
|
138
|
+
long = option[:long] ? "-l #{option[:long]}" : ''
|
139
|
+
arg = option[:arg] ? "=" : ''
|
140
|
+
option_arr << %({-#{option[:short]},--#{option[:long]}#{arg}}"[#{option[:description].gsub(/'/,'\\\'')}]")
|
141
|
+
end
|
142
|
+
end
|
143
|
+
|
144
|
+
cmd[:commands].each do |c|
|
145
|
+
out << "#{c}) \n#{indent+' '}args=( #{option_arr.join(' ')} )\n#{indent};;"
|
146
|
+
end
|
147
|
+
end
|
148
|
+
|
149
|
+
out
|
150
|
+
end
|
151
|
+
|
152
|
+
def initialize
|
153
|
+
status('Generating Zsh completions', reset: false)
|
154
|
+
data = get_help_sections
|
155
|
+
@global_options = parse_options(data[:global_options])
|
156
|
+
@commands = parse_commands(data[:commands])
|
157
|
+
end
|
158
|
+
|
159
|
+
def generate_completions
|
160
|
+
generate_helpers
|
161
|
+
end
|
162
|
+
end
|
163
|
+
|
164
|
+
puts FishCompletions.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.3.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-17 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,15 +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.fish
|
190
|
+
- doing.gemspec
|
191
|
+
- doing.rdoc
|
192
|
+
- example_plugin.rb
|
193
|
+
- generate_completions.sh
|
194
|
+
- img/doing-colors.jpg
|
195
|
+
- img/doing-printf-wrap-800.jpg
|
196
|
+
- img/doing-show-note-formatting-800.jpg
|
197
|
+
- lib/completion/_doing.zsh
|
198
|
+
- lib/completion/doing.bash
|
199
|
+
- lib/completion/doing.fish
|
167
200
|
- lib/doing.rb
|
168
|
-
- lib/doing/
|
201
|
+
- lib/doing/array.rb
|
202
|
+
- lib/doing/cli_status.rb
|
203
|
+
- lib/doing/colors.rb
|
204
|
+
- lib/doing/configuration.rb
|
205
|
+
- lib/doing/errors.rb
|
206
|
+
- lib/doing/hash.rb
|
207
|
+
- lib/doing/hooks.rb
|
208
|
+
- lib/doing/item.rb
|
209
|
+
- lib/doing/log_adapter.rb
|
210
|
+
- lib/doing/markdown_document_listener.rb
|
211
|
+
- lib/doing/note.rb
|
212
|
+
- lib/doing/pager.rb
|
213
|
+
- lib/doing/plugin_manager.rb
|
214
|
+
- lib/doing/plugins/export/csv_export.rb
|
215
|
+
- lib/doing/plugins/export/html_export.rb
|
216
|
+
- lib/doing/plugins/export/json_export.rb
|
217
|
+
- lib/doing/plugins/export/markdown_export.rb
|
218
|
+
- lib/doing/plugins/export/taskpaper_export.rb
|
219
|
+
- lib/doing/plugins/export/template_export.rb
|
220
|
+
- lib/doing/plugins/import/cal_to_json.scpt
|
221
|
+
- lib/doing/plugins/import/calendar_import.rb
|
222
|
+
- lib/doing/plugins/import/doing_import.rb
|
223
|
+
- lib/doing/plugins/import/timing_import.rb
|
224
|
+
- lib/doing/string.rb
|
225
|
+
- lib/doing/symbol.rb
|
226
|
+
- lib/doing/time.rb
|
227
|
+
- lib/doing/util.rb
|
169
228
|
- lib/doing/version.rb
|
170
229
|
- lib/doing/wwid.rb
|
230
|
+
- lib/doing/wwidfile.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
|
171
238
|
- lib/helpers/fuzzyfilefinder
|
239
|
+
- lib/templates/doing-markdown.erb
|
172
240
|
- lib/templates/doing.css
|
173
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
|
174
251
|
homepage: http://brettterpstra.com/project/doing/
|
175
252
|
licenses:
|
176
253
|
- MIT
|
@@ -183,7 +260,6 @@ rdoc_options:
|
|
183
260
|
- README.md
|
184
261
|
- "--markup"
|
185
262
|
- markdown
|
186
|
-
- "-ri"
|
187
263
|
require_paths:
|
188
264
|
- lib
|
189
265
|
- lib
|
@@ -194,9 +270,9 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
194
270
|
version: '0'
|
195
271
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
196
272
|
requirements:
|
197
|
-
- - "
|
273
|
+
- - ">"
|
198
274
|
- !ruby/object:Gem::Version
|
199
|
-
version:
|
275
|
+
version: 1.3.1
|
200
276
|
requirements: []
|
201
277
|
rubygems_version: 3.2.16
|
202
278
|
signing_key:
|