howzit 2.1.16 → 2.1.18
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/.irbrc +7 -1
- data/CHANGELOG.md +8 -0
- data/bin/howzit +67 -67
- data/lib/howzit/buildnote.rb +70 -53
- data/lib/howzit/version.rb +1 -1
- metadata +3 -6
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 4c4fea8cf5770f7beb101c32a4596c4a4d58006d1378c95dd482e95052b2e672
|
4
|
+
data.tar.gz: d0e85f76ddf1dc2f02a0bfb7dc85f5495e749aa13bdda0ed773cb8ce11ff8fb7
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: bca6e7eb45d1c69862aa8e7ff25cd9ccf713826a61836d9d515f761eb1aee46ee6e5c90f5dfdbb120b02dcf0700023817a3fd5dd74a9538170188f8c23397eb9
|
7
|
+
data.tar.gz: e565bd5ff26d4788a72ecd776d39297ec11b2ffb1290b079496f4fdad3dc7faa4ccfebce8d725d9d503727cc06f4014bea34c6afff3bf70377d051594a033dfb
|
data/.irbrc
CHANGED
@@ -1,6 +1,12 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
|
-
|
2
|
+
IRB.conf[:AUTO_INDENT] = true
|
3
|
+
|
4
|
+
require "irb/completion"
|
5
|
+
require_relative "lib/conductor"
|
3
6
|
|
4
7
|
# rubocop:disable Style/MixinUsage
|
5
8
|
include Howzit # standard:disable all
|
6
9
|
# rubocop:enable Style/MixinUsage
|
10
|
+
|
11
|
+
require "awesome_print"
|
12
|
+
AwesomePrint.irb!
|
data/CHANGELOG.md
CHANGED
data/bin/howzit
CHANGED
@@ -1,8 +1,8 @@
|
|
1
1
|
#!/usr/bin/env ruby
|
2
2
|
# frozen_string_literal: true
|
3
3
|
|
4
|
-
$LOAD_PATH.unshift File.join(__dir__,
|
5
|
-
require
|
4
|
+
$LOAD_PATH.unshift File.join(__dir__, "..", "lib")
|
5
|
+
require "howzit"
|
6
6
|
|
7
7
|
Howzit::Color.coloring = $stdout.isatty
|
8
8
|
|
@@ -13,127 +13,127 @@ Howzit.named_arguments = {}
|
|
13
13
|
|
14
14
|
OptionParser.new do |opts|
|
15
15
|
opts.banner = "Usage: #{File.basename(__FILE__)} [OPTIONS] [TOPIC]"
|
16
|
-
opts.separator
|
17
|
-
opts.separator
|
18
|
-
Include a topic name to see just that topic, or no argument to display all.
|
19
|
-
opts.separator
|
20
|
-
opts.separator
|
16
|
+
opts.separator ""
|
17
|
+
opts.separator "Show build notes for the current project (buildnotes.md).
|
18
|
+
Include a topic name to see just that topic, or no argument to display all."
|
19
|
+
opts.separator ""
|
20
|
+
opts.separator "Options:"
|
21
21
|
|
22
22
|
opts.separator " Behavior:\n\n" #=================================================================== BEHAVIOR
|
23
23
|
|
24
|
-
opts.on(
|
24
|
+
opts.on("--ask", "Request confirmation for all tasks when running a topic") { Howzit.options[:ask] = true }
|
25
25
|
|
26
|
-
opts.on(
|
27
|
-
raise
|
26
|
+
opts.on("--default", "Answer all prompts with default response") do
|
27
|
+
raise "--default cannot be used with --yes or --no" if Howzit.options[:yes] || Howzit.options[:no]
|
28
28
|
|
29
29
|
Howzit.options[:default] = true
|
30
30
|
end
|
31
31
|
|
32
|
-
opts.on(
|
32
|
+
opts.on("-f", "--force", "Continue executing after an error") { Howzit.options[:force] = true }
|
33
33
|
|
34
|
-
opts.on(
|
35
|
-
|
34
|
+
opts.on("-m", "--matching TYPE", MATCHING_OPTIONS,
|
35
|
+
"Topics matching type", "(#{MATCHING_OPTIONS.join(", ")})") do |c|
|
36
36
|
Howzit.options[:matching] = c
|
37
37
|
end
|
38
38
|
|
39
|
-
opts.on(
|
40
|
-
|
39
|
+
opts.on("--multiple TYPE", MULTIPLE_OPTIONS,
|
40
|
+
"Multiple result handling", "(#{MULTIPLE_OPTIONS.join(", ")}, default choose)") do |c|
|
41
41
|
Howzit.options[:multiple_matches] = c.to_sym
|
42
42
|
end
|
43
43
|
|
44
|
-
opts.on(
|
44
|
+
opts.on("-u", "--[no-]upstream", "Traverse up parent directories for additional build notes") do |p|
|
45
45
|
Howzit.options[:include_upstream] = p
|
46
46
|
end
|
47
47
|
|
48
|
-
opts.on(
|
49
|
-
raise
|
48
|
+
opts.on("-y", "--yes", "Answer yes to all prompts") do
|
49
|
+
raise "--default cannot be used with --yes" if Howzit.options[:default]
|
50
50
|
|
51
51
|
Howzit.options[:yes] = true
|
52
52
|
end
|
53
53
|
|
54
|
-
opts.on(
|
55
|
-
raise
|
54
|
+
opts.on("-n", "--no", "Answer no to all prompts") do
|
55
|
+
raise "--default cannot be used with --no" if Howzit.options[:default]
|
56
56
|
|
57
57
|
Howzit.options[:no] = true
|
58
58
|
end
|
59
59
|
|
60
60
|
opts.separator "\n Listing:\n\n" #=================================================================== LISTING
|
61
61
|
|
62
|
-
opts.on(
|
62
|
+
opts.on("-L", "--list-completions", "List topics (completion-compatible)") do
|
63
63
|
Howzit.options[:list_topics] = true
|
64
64
|
Howzit.options[:list_topic_titles] = true
|
65
65
|
end
|
66
66
|
|
67
|
-
opts.on(
|
67
|
+
opts.on("-l", "--list", "List available topics") do
|
68
68
|
Howzit.options[:list_topics] = true
|
69
69
|
end
|
70
70
|
|
71
|
-
opts.on(
|
71
|
+
opts.on("-R", "--list-runnable [PATTERN]", "List topics containing @ directives (verbose)") do |pat|
|
72
72
|
Howzit.options[:for_topic] = pat
|
73
73
|
Howzit.options[:list_runnable] = true
|
74
74
|
end
|
75
75
|
|
76
|
-
opts.on(
|
76
|
+
opts.on("-T", "--task-list", "List topics containing @ directives (completion-compatible)") do
|
77
77
|
Howzit.options[:list_runnable] = true
|
78
78
|
Howzit.options[:list_runnable_titles] = true
|
79
79
|
end
|
80
80
|
|
81
|
-
opts.on(
|
81
|
+
opts.on("--templates", "List available templates") do
|
82
82
|
out = []
|
83
83
|
Dir.chdir(Howzit.config.template_folder)
|
84
|
-
Dir.glob(
|
85
|
-
template = File.basename(file,
|
84
|
+
Dir.glob("*.md").each do |file|
|
85
|
+
template = File.basename(file, ".md")
|
86
86
|
out.push(Howzit::Color.template("{Mk}template:{Yk}#{template}{x}"))
|
87
|
-
out.push(Howzit::Color.template(
|
87
|
+
out.push(Howzit::Color.template("{bk}[{bl}tasks{bk}]──────────────────────────────────────┐{x}"))
|
88
88
|
metadata = file.extract_metadata
|
89
89
|
topics = Howzit::BuildNote.new(file: file).topics
|
90
90
|
topics.each do |topic|
|
91
|
-
out.push(Howzit::Color.template(" {bk}│{bw}-{x} {bcK}#{template}:#{topic.title.sub(/^.*?:/,
|
91
|
+
out.push(Howzit::Color.template(" {bk}│{bw}-{x} {bcK}#{template}:#{topic.title.sub(/^.*?:/, "")}{x}"))
|
92
92
|
end
|
93
93
|
unless metadata.empty?
|
94
94
|
meta = []
|
95
|
-
meta << metadata[
|
96
|
-
meta << metadata[
|
97
|
-
out.push(Howzit::Color.template(
|
98
|
-
out.push(Howzit::Color.template(" {bk}│ {xw}#{meta.join(
|
95
|
+
meta << metadata["required"].split(/\s*,\s*/).map { |m| "*{bw}#{m}{xw}" } if metadata.key?("required")
|
96
|
+
meta << metadata["optional"].split(/\s*,\s*/).map(&:to_s) if metadata.key?("optional")
|
97
|
+
out.push(Howzit::Color.template("{bk}[{bl}meta{bk}]───────────────────────────────────────┤{x}"))
|
98
|
+
out.push(Howzit::Color.template(" {bk}│ {xw}#{meta.join(", ")}{x}"))
|
99
99
|
end
|
100
|
-
out.push(Howzit::Color.template(
|
100
|
+
out.push(Howzit::Color.template(" {bk}└───────────────────────────────────────────┘{x}"))
|
101
101
|
end
|
102
102
|
Howzit::Util.page out.join("\n")
|
103
103
|
Process.exit 0
|
104
104
|
end
|
105
105
|
|
106
|
-
opts.on(
|
106
|
+
opts.on("--templates-c", "List available templates in a format for completion") do
|
107
107
|
out = []
|
108
108
|
Dir.chdir(Howzit.config.template_folder)
|
109
|
-
Dir.glob(
|
110
|
-
template = File.basename(file,
|
109
|
+
Dir.glob("*.md").each do |file|
|
110
|
+
template = File.basename(file, ".md")
|
111
111
|
out.push(template)
|
112
112
|
end
|
113
113
|
puts out.join("\n")
|
114
114
|
Process.exit 0
|
115
115
|
end
|
116
116
|
|
117
|
-
opts.on(
|
117
|
+
opts.on("--title-only", "Output title only") do
|
118
118
|
Howzit.options[:output_title] = true
|
119
119
|
Howzit.options[:title_only] = true
|
120
120
|
end
|
121
121
|
|
122
122
|
opts.separator("\n Commands:\n\n") #=================================================================== COMMANDS
|
123
123
|
|
124
|
-
opts.on(
|
124
|
+
opts.on("-c", "--create", "Create a skeleton build note in the current working directory") do
|
125
125
|
Howzit.buildnote.create_note
|
126
126
|
Process.exit 0
|
127
127
|
end
|
128
128
|
|
129
|
-
opts.on(
|
129
|
+
opts.on("--config-get [KEY]", "Display the configuration settings or setting for a specific key") do |k|
|
130
130
|
if k.nil?
|
131
131
|
Howzit::Config::DEFAULTS.sort_by { |key, _| key }.each do |key, _|
|
132
132
|
print "#{key}: "
|
133
133
|
p Howzit.options[key]
|
134
134
|
end
|
135
135
|
else
|
136
|
-
k.sub!(/^:/,
|
136
|
+
k.sub!(/^:/, "")
|
137
137
|
if Howzit.options.key?(k.to_sym)
|
138
138
|
puts Howzit.options[k.to_sym]
|
139
139
|
else
|
@@ -143,12 +143,12 @@ OptionParser.new do |opts|
|
|
143
143
|
Process.exit 0
|
144
144
|
end
|
145
145
|
|
146
|
-
opts.on(
|
147
|
-
raise
|
146
|
+
opts.on("--config-set KEY=VALUE", "Set a config value (must be a valid key)") do |key|
|
147
|
+
raise "Argument must be KEY=VALUE" unless key =~ /\S=\S/
|
148
148
|
|
149
149
|
parts = key.split(/=/)
|
150
|
-
k = parts.shift.sub(/^:/,
|
151
|
-
v = parts.join(
|
150
|
+
k = parts.shift.sub(/^:/, "")
|
151
|
+
v = parts.join(" ")
|
152
152
|
|
153
153
|
if Howzit.options.key?(k.to_sym)
|
154
154
|
Howzit.options[k.to_sym] = v.to_config_value(Howzit.options[k.to_sym])
|
@@ -160,103 +160,103 @@ OptionParser.new do |opts|
|
|
160
160
|
end
|
161
161
|
|
162
162
|
desc = %(Edit buildnotes file in current working directory using default editor)
|
163
|
-
opts.on(
|
163
|
+
opts.on("-e", "--edit", desc) do
|
164
164
|
Howzit.buildnote.edit
|
165
165
|
Process.exit 0
|
166
166
|
end
|
167
167
|
|
168
|
-
opts.on(
|
168
|
+
opts.on("--edit-config", "Edit configuration file using default editor") do
|
169
169
|
Howzit.config.editor
|
170
170
|
Process.exit 0
|
171
171
|
end
|
172
172
|
|
173
|
-
opts.on(
|
173
|
+
opts.on("--edit-template NAME", "Create or edit a template") do |template|
|
174
174
|
Howzit.buildnote.edit_template(template)
|
175
175
|
Process.exit 0
|
176
176
|
end
|
177
177
|
|
178
|
-
opts.on(
|
178
|
+
opts.on("--grep PATTERN", "Display sections matching a search pattern") do |pat|
|
179
179
|
Howzit.options[:grep] = pat
|
180
180
|
end
|
181
181
|
|
182
|
-
opts.on(
|
182
|
+
opts.on("--hook", "Copy a link to the build note file, ready for pasting into Hook.app or other notes") do
|
183
183
|
Howzit.buildnote.hook
|
184
184
|
Process.exit 0
|
185
185
|
end
|
186
186
|
|
187
|
-
opts.on(
|
187
|
+
opts.on("-r", "--run", "Execute @run, @open, and/or @copy commands for given topic") do
|
188
188
|
Howzit.options[:run] = true
|
189
189
|
end
|
190
190
|
|
191
|
-
opts.on(
|
191
|
+
opts.on("-s", "--select", "Select topic from menu") do
|
192
192
|
Howzit.options[:choose] = true
|
193
193
|
end
|
194
194
|
|
195
195
|
opts.separator("\n Formatting:\n\n") #=================================================================== FORMATTING
|
196
196
|
|
197
|
-
opts.on(
|
197
|
+
opts.on("--[no-]color", "Colorize output (default on)") do |c|
|
198
198
|
Howzit.options[:color] = c
|
199
199
|
Howzit.options[:highlight] = false unless c
|
200
200
|
end
|
201
201
|
|
202
|
-
opts.on(
|
203
|
-
"Formatting style for topic titles (#{HEADER_FORMAT_OPTIONS.join(
|
202
|
+
opts.on("--header-format TYPE", HEADER_FORMAT_OPTIONS,
|
203
|
+
"Formatting style for topic titles (#{HEADER_FORMAT_OPTIONS.join(", ")})") do |t|
|
204
204
|
Howzit.options[:header_format] = t
|
205
205
|
end
|
206
206
|
|
207
|
-
opts.on(
|
207
|
+
opts.on("--[no-]md-highlight", "Highlight Markdown syntax (default on), requires mdless or mdcat") do |m|
|
208
208
|
Howzit.options[:highlight] = Howzit.options[:color] ? m : false
|
209
209
|
end
|
210
210
|
|
211
|
-
opts.on(
|
211
|
+
opts.on("--[no-]pager", "Paginate output (default on)") do |p|
|
212
212
|
Howzit.options[:paginate] = p
|
213
213
|
end
|
214
214
|
|
215
|
-
opts.on(
|
215
|
+
opts.on("--show-code", "Display the content of fenced run blocks") do
|
216
216
|
Howzit.options[:show_all_code] = true
|
217
217
|
end
|
218
218
|
|
219
|
-
opts.on(
|
219
|
+
opts.on("-t", "--title", "Output title with build notes") do
|
220
220
|
Howzit.options[:output_title] = true
|
221
221
|
end
|
222
222
|
|
223
|
-
opts.on(
|
223
|
+
opts.on("-w", "--wrap COLUMNS", "Wrap to specified width (default 80, 0 to disable)") do |w|
|
224
224
|
Howzit.options[:wrap] = w.to_i
|
225
225
|
end
|
226
226
|
|
227
227
|
opts.separator("\n Logging:\n\n") #=================================================================== LOGGING
|
228
228
|
|
229
|
-
opts.on(
|
229
|
+
opts.on("-d", "--debug", "Show debug messages (and all messages)") do
|
230
230
|
Howzit.options[:log_level] = 0
|
231
231
|
Howzit.console.reset_level
|
232
232
|
end
|
233
233
|
|
234
|
-
opts.on(
|
234
|
+
opts.on("-q", "--quiet", "Silence info message") do
|
235
235
|
Howzit.options[:log_level] = 4
|
236
236
|
Howzit.console.reset_level
|
237
237
|
end
|
238
238
|
|
239
|
-
opts.on(
|
239
|
+
opts.on("--verbose", "Show all messages") do
|
240
240
|
Howzit.options[:log_level] = 1
|
241
241
|
Howzit.console.reset_level
|
242
242
|
end
|
243
243
|
|
244
244
|
opts.separator("\n Misc:\n\n") #=================================================================== MISC
|
245
245
|
|
246
|
-
opts.on(
|
246
|
+
opts.on("-h", "--help", "Display this screen") do
|
247
247
|
Howzit::Util.page opts.to_s
|
248
248
|
Process.exit 0
|
249
249
|
end
|
250
250
|
|
251
|
-
opts.on(
|
251
|
+
opts.on("-v", "--version", "Display version number") do
|
252
252
|
puts "#{File.basename(__FILE__)} v#{Howzit::VERSION}"
|
253
253
|
Process.exit 0
|
254
254
|
end
|
255
255
|
end.parse!(args)
|
256
256
|
|
257
|
-
trap(
|
257
|
+
trap("INT") do
|
258
258
|
puts
|
259
|
-
puts
|
259
|
+
puts "Cancelled"
|
260
260
|
Process.exit 0
|
261
261
|
end
|
262
262
|
|
data/lib/howzit/buildnote.rb
CHANGED
@@ -57,7 +57,7 @@ module Howzit
|
|
57
57
|
## @param template [String] The template title
|
58
58
|
##
|
59
59
|
def edit_template(template)
|
60
|
-
file = template.sub(/(\.md)?$/i,
|
60
|
+
file = template.sub(/(\.md)?$/i, ".md")
|
61
61
|
file = File.join(Howzit.config.template_folder, file)
|
62
62
|
edit_template_file(file)
|
63
63
|
end
|
@@ -72,7 +72,7 @@ module Howzit
|
|
72
72
|
|
73
73
|
@topics.filter do |topic|
|
74
74
|
rx = term.to_rx
|
75
|
-
topic.title.downcase.sub(/ *\(.*?\) *$/,
|
75
|
+
topic.title.downcase.sub(/ *\(.*?\) *$/, "") =~ rx
|
76
76
|
end
|
77
77
|
end
|
78
78
|
|
@@ -84,7 +84,7 @@ module Howzit
|
|
84
84
|
title = "#{title} project notes"
|
85
85
|
url = "[#{title}](file://#{note_file})"
|
86
86
|
Util.os_copy(url)
|
87
|
-
Howzit.console.info(
|
87
|
+
Howzit.console.info("Link copied to clipboard.")
|
88
88
|
end
|
89
89
|
|
90
90
|
##
|
@@ -115,7 +115,13 @@ module Howzit
|
|
115
115
|
## @return [Array] array of topic titles
|
116
116
|
##
|
117
117
|
def list_topics
|
118
|
-
@topics.map
|
118
|
+
@topics.map do |topic|
|
119
|
+
title = topic.title
|
120
|
+
unless topic.named_args.empty?
|
121
|
+
title += "(#{topic.named_args.keys.join(", ")})"
|
122
|
+
end
|
123
|
+
title
|
124
|
+
end
|
119
125
|
end
|
120
126
|
|
121
127
|
##
|
@@ -137,7 +143,13 @@ module Howzit
|
|
137
143
|
def list_runnable_completions
|
138
144
|
output = []
|
139
145
|
@topics.each do |topic|
|
140
|
-
|
146
|
+
if topic.tasks.count.positive?
|
147
|
+
title = topic.title
|
148
|
+
unless topic.named_args.empty?
|
149
|
+
title += "(#{topic.named_args.keys.join(", ")})"
|
150
|
+
end
|
151
|
+
output.push(title)
|
152
|
+
end
|
141
153
|
end
|
142
154
|
output.join("\n")
|
143
155
|
end
|
@@ -159,7 +171,12 @@ module Howzit
|
|
159
171
|
|
160
172
|
next if s_out.empty?
|
161
173
|
|
162
|
-
|
174
|
+
title = topic.title
|
175
|
+
unless topic.named_args.empty?
|
176
|
+
title += " {dy}({xy}#{topic.named_args.keys.join(", ")}{dy}){x}"
|
177
|
+
end
|
178
|
+
|
179
|
+
output.push("- {g}#{title}{x}".c)
|
163
180
|
output.push(s_out.join("\n"))
|
164
181
|
end
|
165
182
|
|
@@ -182,7 +199,7 @@ module Howzit
|
|
182
199
|
## @param prompt [Boolean] confirm file creation?
|
183
200
|
##
|
184
201
|
def create_template_file(file, prompt: false)
|
185
|
-
trap(
|
202
|
+
trap("SIGINT") do
|
186
203
|
Howzit.console.info "\nCancelled"
|
187
204
|
exit!
|
188
205
|
end
|
@@ -194,7 +211,7 @@ module Howzit
|
|
194
211
|
Process.exit 0 unless res
|
195
212
|
end
|
196
213
|
|
197
|
-
title = File.basename(file,
|
214
|
+
title = File.basename(file, ".md")
|
198
215
|
|
199
216
|
note = <<~EOBUILDNOTES
|
200
217
|
# #{title}
|
@@ -206,12 +223,12 @@ module Howzit
|
|
206
223
|
if File.exist?(file) && !default
|
207
224
|
file = "{by}#{file}".c
|
208
225
|
unless Prompt.yn("Are you sure you want to overwrite #{file}", default: false)
|
209
|
-
Howzit.console.info(
|
226
|
+
Howzit.console.info("Cancelled")
|
210
227
|
Process.exit 0
|
211
228
|
end
|
212
229
|
end
|
213
230
|
|
214
|
-
File.open(file,
|
231
|
+
File.open(file, "w") do |f|
|
215
232
|
f.puts note
|
216
233
|
Howzit.console.info("{by}Template {bw}#{title}{by} written to {bw}#{file}{x}".c)
|
217
234
|
end
|
@@ -226,7 +243,7 @@ module Howzit
|
|
226
243
|
|
227
244
|
# Create a buildnotes skeleton
|
228
245
|
def create_note(prompt: false)
|
229
|
-
trap(
|
246
|
+
trap("SIGINT") do
|
230
247
|
Howzit.console.info "\nCancelled"
|
231
248
|
exit!
|
232
249
|
end
|
@@ -234,7 +251,7 @@ module Howzit
|
|
234
251
|
default = !$stdout.isatty || Howzit.options[:default]
|
235
252
|
|
236
253
|
if prompt && !default
|
237
|
-
res = Prompt.yn(
|
254
|
+
res = Prompt.yn("No build notes file found, create one?", default: true)
|
238
255
|
Process.exit 0 unless res
|
239
256
|
end
|
240
257
|
|
@@ -257,14 +274,14 @@ module Howzit
|
|
257
274
|
input = $stdin.gets.chomp
|
258
275
|
title = input unless input.empty?
|
259
276
|
end
|
260
|
-
summary =
|
277
|
+
summary = ""
|
261
278
|
unless default
|
262
|
-
printf
|
279
|
+
printf "{bw}Project summary: {x}".c
|
263
280
|
input = $stdin.gets.chomp
|
264
281
|
summary = input unless input.empty?
|
265
282
|
end
|
266
283
|
|
267
|
-
fname =
|
284
|
+
fname = "buildnotes.md"
|
268
285
|
unless default
|
269
286
|
printf "{bw}Build notes filename (must begin with 'howzit' or 'build')\n{xg}[#{fname}]{bw}: {x}".c
|
270
287
|
input = $stdin.gets.chomp
|
@@ -299,12 +316,12 @@ module Howzit
|
|
299
316
|
if File.exist?(fname) && !default
|
300
317
|
file = "{by}#{fname}".c
|
301
318
|
unless Prompt.yn("Are you absolutely sure you want to overwrite #{file}", default: false)
|
302
|
-
Howzit.console.info(
|
319
|
+
Howzit.console.info("Canceled")
|
303
320
|
Process.exit 0
|
304
321
|
end
|
305
322
|
end
|
306
323
|
|
307
|
-
File.open(fname,
|
324
|
+
File.open(fname, "w") do |f|
|
308
325
|
f.puts note
|
309
326
|
Howzit.console.info("{by}Build notes for {bw}#{title}{by} written to {bw}#{fname}{x}".c)
|
310
327
|
end
|
@@ -340,15 +357,15 @@ module Howzit
|
|
340
357
|
return mtch[0] unless File.exist?(file)
|
341
358
|
|
342
359
|
content = Util.read_file(file)
|
343
|
-
home = ENV[
|
344
|
-
short_path = File.dirname(file.sub(/^#{home}/,
|
360
|
+
home = ENV["HOME"]
|
361
|
+
short_path = File.dirname(file.sub(/^#{home}/, "~"))
|
345
362
|
prefix = "#{short_path}/#{File.basename(file)}:"
|
346
363
|
parts = content.split(/^##+/)
|
347
364
|
parts.shift
|
348
365
|
if parts.empty?
|
349
366
|
content
|
350
367
|
else
|
351
|
-
"## #{parts.join(
|
368
|
+
"## #{parts.join("## ")}".gsub(/^(##+ *)(?=\S)/, "\\1#{prefix}")
|
352
369
|
end
|
353
370
|
end
|
354
371
|
|
@@ -365,15 +382,15 @@ module Howzit
|
|
365
382
|
|
366
383
|
t_meta = t_leader.metadata
|
367
384
|
|
368
|
-
return unless t_meta.key?(
|
385
|
+
return unless t_meta.key?("required")
|
369
386
|
|
370
|
-
required = t_meta[
|
387
|
+
required = t_meta["required"].strip.split(/\s*,\s*/)
|
371
388
|
required.each do |req|
|
372
389
|
next if @metadata.keys.include?(req.downcase)
|
373
390
|
|
374
391
|
Howzit.console.error %({bRw}ERROR:{xbr} Missing required metadata key from template '{bw}#{File.basename(
|
375
|
-
|
376
|
-
|
392
|
+
template, ".md"
|
393
|
+
)}{xr}'{x}).c
|
377
394
|
Howzit.console.error %({br}Please define {by}#{req.downcase}{xr} in build notes{x}).c
|
378
395
|
Process.exit 1
|
379
396
|
end
|
@@ -391,8 +408,8 @@ module Howzit
|
|
391
408
|
subtopics = nil
|
392
409
|
|
393
410
|
if template =~ /\[(.*?)\]$/
|
394
|
-
subtopics = Regexp.last_match[1].split(/\s*\|\s*/).map { |t| t.gsub(/\*/,
|
395
|
-
template.sub!(/\[.*?\]$/,
|
411
|
+
subtopics = Regexp.last_match[1].split(/\s*\|\s*/).map { |t| t.gsub(/\*/, ".*?") }
|
412
|
+
template.sub!(/\[.*?\]$/, "").strip
|
396
413
|
end
|
397
414
|
|
398
415
|
[template, subtopics]
|
@@ -412,7 +429,7 @@ module Howzit
|
|
412
429
|
templates.each do |template|
|
413
430
|
template, subtopics = detect_subtopics(template)
|
414
431
|
|
415
|
-
file = template.sub(/(\.md)?$/i,
|
432
|
+
file = template.sub(/(\.md)?$/i, ".md")
|
416
433
|
file = File.join(Howzit.config.template_folder, file)
|
417
434
|
|
418
435
|
next unless File.exist?(file)
|
@@ -476,7 +493,7 @@ module Howzit
|
|
476
493
|
buildnotes = []
|
477
494
|
filename = nil
|
478
495
|
|
479
|
-
while dir !=
|
496
|
+
while dir != "/" && (dir =~ %r{[A-Z]:/}).nil?
|
480
497
|
Dir.chdir(dir)
|
481
498
|
filename = glob_note
|
482
499
|
unless filename.nil?
|
@@ -499,7 +516,7 @@ module Howzit
|
|
499
516
|
## @return [String] file path
|
500
517
|
##
|
501
518
|
def glob_note
|
502
|
-
Dir.glob(
|
519
|
+
Dir.glob("*.{txt,md,markdown}").select(&:build_note?).sort[0]
|
503
520
|
end
|
504
521
|
|
505
522
|
##
|
@@ -512,9 +529,9 @@ module Howzit
|
|
512
529
|
def find_note_file
|
513
530
|
filename = glob_note
|
514
531
|
|
515
|
-
if filename.nil? &&
|
532
|
+
if filename.nil? && "git".available?
|
516
533
|
proj_dir = `git rev-parse --show-toplevel 2>/dev/null`.strip
|
517
|
-
unless proj_dir ==
|
534
|
+
unless proj_dir == ""
|
518
535
|
Dir.chdir(proj_dir)
|
519
536
|
filename = glob_note
|
520
537
|
end
|
@@ -558,8 +575,8 @@ module Howzit
|
|
558
575
|
|
559
576
|
data = leader.metadata
|
560
577
|
|
561
|
-
if data.key?(
|
562
|
-
templates = data[
|
578
|
+
if data.key?("template")
|
579
|
+
templates = data["template"].strip.split(/\s*,\s*/)
|
563
580
|
|
564
581
|
template_topics.concat(gather_templates(templates))
|
565
582
|
end
|
@@ -601,13 +618,13 @@ module Howzit
|
|
601
618
|
|
602
619
|
lines = sect.split(/\n/)
|
603
620
|
title = lines.slice!(0).strip
|
604
|
-
prefix =
|
621
|
+
prefix = ""
|
605
622
|
if path && path != note_file
|
606
623
|
if path =~ /#{Howzit.config.template_folder}/
|
607
|
-
short_path = File.basename(path,
|
624
|
+
short_path = File.basename(path, ".md")
|
608
625
|
else
|
609
|
-
home = ENV[
|
610
|
-
short_path = File.dirname(path.sub(/^#{home}/,
|
626
|
+
home = ENV["HOME"]
|
627
|
+
short_path = File.dirname(path.sub(/^#{home}/, "~"))
|
611
628
|
prefix = "_from #{short_path}_\n\n"
|
612
629
|
end
|
613
630
|
title = "#{short_path}:#{title}"
|
@@ -619,7 +636,7 @@ module Howzit
|
|
619
636
|
end
|
620
637
|
|
621
638
|
template_topics.each do |topic|
|
622
|
-
topics.push(topic) unless find_topic(topic.title.sub(/^.+:/,
|
639
|
+
topics.push(topic) unless find_topic(topic.title.sub(/^.+:/, "")).count.positive?
|
623
640
|
end
|
624
641
|
|
625
642
|
topics
|
@@ -638,7 +655,7 @@ module Howzit
|
|
638
655
|
upstream_topics = read_upstream
|
639
656
|
|
640
657
|
upstream_topics.each do |topic|
|
641
|
-
@topics.push(topic) unless find_topic(topic.title.sub(/^.+:/,
|
658
|
+
@topics.push(topic) unless find_topic(topic.title.sub(/^.+:/, "")).count.positive?
|
642
659
|
end
|
643
660
|
Howzit.has_read_upstream = true
|
644
661
|
end
|
@@ -653,11 +670,11 @@ module Howzit
|
|
653
670
|
## Open build note in editor
|
654
671
|
##
|
655
672
|
def edit_note
|
656
|
-
editor = Howzit.options.fetch(:editor, ENV[
|
673
|
+
editor = Howzit.options.fetch(:editor, ENV["EDITOR"])
|
657
674
|
|
658
675
|
editor = Howzit.config.update_editor if editor.nil?
|
659
676
|
|
660
|
-
raise
|
677
|
+
raise "No editor defined" if editor.nil?
|
661
678
|
|
662
679
|
raise "Invalid editor (#{editor})" unless Util.valid_command?(editor)
|
663
680
|
|
@@ -671,7 +688,7 @@ module Howzit
|
|
671
688
|
## @param template [String] The template name
|
672
689
|
##
|
673
690
|
def create_template(template)
|
674
|
-
file = template.sub(/(\.md)?$/i,
|
691
|
+
file = template.sub(/(\.md)?$/i, ".md")
|
675
692
|
file = File.join(Howzit.config.template_folder, file)
|
676
693
|
create_template_file(file, prompt: false)
|
677
694
|
end
|
@@ -680,11 +697,11 @@ module Howzit
|
|
680
697
|
## Open template in editor
|
681
698
|
##
|
682
699
|
def edit_template_file(file)
|
683
|
-
editor = Howzit.options.fetch(:editor, ENV[
|
700
|
+
editor = Howzit.options.fetch(:editor, ENV["EDITOR"])
|
684
701
|
|
685
702
|
editor = Howzit.config.update_editor if editor.nil?
|
686
703
|
|
687
|
-
raise
|
704
|
+
raise "No editor defined" if editor.nil?
|
688
705
|
|
689
706
|
raise "Invalid editor (#{editor})" unless Util.valid_command?(editor)
|
690
707
|
|
@@ -705,12 +722,12 @@ module Howzit
|
|
705
722
|
new_topic = topic.is_a?(String) ? find_topic(topic)[0] : topic.dup
|
706
723
|
|
707
724
|
output = if run
|
708
|
-
|
709
|
-
|
710
|
-
|
711
|
-
|
725
|
+
new_topic.run
|
726
|
+
else
|
727
|
+
new_topic.print_out({ single: single })
|
728
|
+
end
|
712
729
|
|
713
|
-
output.nil? ?
|
730
|
+
output.nil? ? "" : output.join("\n\n")
|
714
731
|
end
|
715
732
|
|
716
733
|
##
|
@@ -731,7 +748,7 @@ module Howzit
|
|
731
748
|
Process.exit(0)
|
732
749
|
elsif Howzit.options[:output_title] && !Howzit.options[:run]
|
733
750
|
if @title && !@title.empty?
|
734
|
-
header = @title.format_header({ hr: "\u{2550}", color:
|
751
|
+
header = @title.format_header({ hr: "\u{2550}", color: "{bwK}" })
|
735
752
|
output.push("#{header}\n")
|
736
753
|
end
|
737
754
|
end
|
@@ -770,9 +787,9 @@ module Howzit
|
|
770
787
|
elsif Howzit.options[:choose]
|
771
788
|
titles = Prompt.choose(list_topics, height: :max)
|
772
789
|
titles.each { |title| topic_matches.push(find_topic(title)[0]) }
|
773
|
-
|
790
|
+
# If there are arguments use those to search for a matching topic
|
774
791
|
elsif !Howzit.cli_args.empty?
|
775
|
-
search = Howzit.cli_args.join(
|
792
|
+
search = Howzit.cli_args.join(" ").strip.downcase.split(/ *, */).map(&:strip)
|
776
793
|
|
777
794
|
search.each do |s|
|
778
795
|
matches = find_topic(s)
|
@@ -791,7 +808,7 @@ module Howzit
|
|
791
808
|
titles = matches.map(&:title)
|
792
809
|
res = Prompt.choose(titles)
|
793
810
|
old_matching = Howzit.options[:matching]
|
794
|
-
Howzit.options[:matching] =
|
811
|
+
Howzit.options[:matching] = "exact"
|
795
812
|
res.each { |title| topic_matches.concat(find_topic(title)) }
|
796
813
|
Howzit.options[:matching] = old_matching
|
797
814
|
end
|
data/lib/howzit/version.rb
CHANGED
metadata
CHANGED
@@ -1,14 +1,13 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: howzit
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 2.1.
|
4
|
+
version: 2.1.18
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Brett Terpstra
|
8
|
-
autorequire:
|
9
8
|
bindir: bin
|
10
9
|
cert_chain: []
|
11
|
-
date:
|
10
|
+
date: 2025-01-01 00:00:00.000000000 Z
|
12
11
|
dependencies:
|
13
12
|
- !ruby/object:Gem::Dependency
|
14
13
|
name: bundler
|
@@ -334,7 +333,6 @@ homepage: https://github.com/ttscoff/howzit
|
|
334
333
|
licenses:
|
335
334
|
- MIT
|
336
335
|
metadata: {}
|
337
|
-
post_install_message:
|
338
336
|
rdoc_options: []
|
339
337
|
require_paths:
|
340
338
|
- lib
|
@@ -349,8 +347,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
349
347
|
- !ruby/object:Gem::Version
|
350
348
|
version: '0'
|
351
349
|
requirements: []
|
352
|
-
rubygems_version: 3.2
|
353
|
-
signing_key:
|
350
|
+
rubygems_version: 3.6.2
|
354
351
|
specification_version: 4
|
355
352
|
summary: Provides a way to access Markdown project notes by topic with query capabilities
|
356
353
|
and the ability to execute the tasks it describes.
|