howzit 2.0.4 → 2.0.7
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +29 -0
- data/README.md +36 -8
- data/bin/howzit +10 -3
- data/lib/howzit/buildnote.rb +3 -3
- data/lib/howzit/config.rb +2 -2
- data/lib/howzit/console_logger.rb +43 -0
- data/lib/howzit/hash.rb +20 -0
- data/lib/howzit/prompt.rb +1 -1
- data/lib/howzit/task.rb +9 -3
- data/lib/howzit/topic.rb +107 -71
- data/lib/howzit/util.rb +3 -3
- data/lib/howzit/version.rb +1 -1
- data/lib/howzit.rb +6 -1
- metadata +2 -1
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 8ad8cdc085654826428d432429473e7b12375288058f3c0ce993f94937441485
|
4
|
+
data.tar.gz: 8dfda4d862d35559b0cd9a1e89c4a69597aa16ef9dba5dac29eff1ee61ed295a
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 9ec8eea72d9177717e0ed6dcd07c35d9eb12f998dabea1347efae1dca1fc145a8c5e4b8317f1cf4805606a86209e389643c959aa60deb240ebd2808ddbe456f4
|
7
|
+
data.tar.gz: a9f3e5472866af519bc053ab50ef3f6a5089ddc4334e9687cb64dd9a8e026d00a0b2bb12d1246631f209892de9bb03168cb05cbaa852d97c44734395b00b122b
|
data/CHANGELOG.md
CHANGED
@@ -1,3 +1,32 @@
|
|
1
|
+
### 2.0.7
|
2
|
+
|
3
|
+
2022-08-04 13:04
|
4
|
+
|
5
|
+
#### NEW
|
6
|
+
|
7
|
+
- --debug flag (shortcut for :log_level: 0)
|
8
|
+
|
9
|
+
#### IMPROVED
|
10
|
+
|
11
|
+
- Console output now gets log levels, so :log_level: config option and --quiet/verbose have more utility
|
12
|
+
|
13
|
+
### 2.0.6
|
14
|
+
|
15
|
+
2022-08-04 11:08
|
16
|
+
|
17
|
+
### 2.0.5
|
18
|
+
|
19
|
+
2022-08-04 10:50
|
20
|
+
|
21
|
+
#### NEW
|
22
|
+
|
23
|
+
- Make any task optional when running by adding a ? (@open?(...))
|
24
|
+
- Optional tasks default to yes when you hit enter, invert by using a ! (@open?!(...)) to make default "no"
|
25
|
+
|
26
|
+
#### FIXED
|
27
|
+
|
28
|
+
- Replace escaped newlines in task list output so that they don't trigger a newline in the shell
|
29
|
+
|
1
30
|
### 2.0.4
|
2
31
|
|
3
32
|
2022-08-04 06:25
|
data/README.md
CHANGED
@@ -94,6 +94,18 @@ You can include commands that can be executed by howzit. Commands start at the b
|
|
94
94
|
|
95
95
|
A block defined between @after and @end markers will be displayed after a topic is run. Use it to remind yourself of additional tasks after automated ones have been executed. The content between these markers is still included when viewing the topic, but the tags themselves do not show up in output.
|
96
96
|
|
97
|
+
### Adding Titles
|
98
|
+
|
99
|
+
When displaying a topic, howzit can display a title instead of the contents of a directive. Any text after the closing parenthesis will be considered the task title.
|
100
|
+
|
101
|
+
```
|
102
|
+
@run(~/scripts/deploy.sh) Deploy script
|
103
|
+
```
|
104
|
+
|
105
|
+
When the topic is displayed, it will now show "Run Deploy script" instead of the path to the script. This can be overridden with the `--show-code` flag, which will instead show the contents of the directive.
|
106
|
+
|
107
|
+
For adding titles to run blocks (fenced code), see below.
|
108
|
+
|
97
109
|
### Run blocks (embedded scripts)
|
98
110
|
|
99
111
|
For longer scripts you can write shell scripts and then call them with `@run(myscript.sh)`. For those in-between cases where you need a few commands but aren't motivated to create a separate file, you can use fenced code blocks with `run` as the language.
|
@@ -117,6 +129,12 @@ Example:
|
|
117
129
|
|
118
130
|
Multiple blocks can be included in a topic. @commands take priority over code blocks and will be run first if they exist in the same topic.
|
119
131
|
|
132
|
+
### Requiring Confirmation
|
133
|
+
|
134
|
+
You can have howzit confirm whether to execute an @command at runtime by including a question mark to the directive, e.g. `@run?(...)`. This will present a yes/no dialog before running the directive, with a default response of "yes" if you just hit return. To make the default response "no," add an exclamation point, e.g. `@run?!(...)`.
|
135
|
+
|
136
|
+
This works for any directive, including `@include`, and run blocks, which can use `run?` as the language specifier.
|
137
|
+
|
120
138
|
### Variables
|
121
139
|
|
122
140
|
When running commands in a topic, you can use a double dash (`--`) in the command line (surrounded by spaces) and anything after it will be interpreted as shell arguments. These can be used in commands with `$` placeholders. `$1` represents the first argument, counting up from there. Use `$@` to pass all arguments as a shell-escaped string.
|
@@ -255,17 +273,21 @@ Some of the command line options can be set as defaults. The first time you run
|
|
255
273
|
|
256
274
|
---
|
257
275
|
:color: true
|
276
|
+
:config_editor: subl
|
277
|
+
:editor: subl
|
278
|
+
:header_format: block
|
258
279
|
:highlight: true
|
259
|
-
:
|
260
|
-
:
|
280
|
+
:highlighter: mdcat
|
281
|
+
:include_upstream: true
|
282
|
+
:log_level: 0
|
283
|
+
:matching: fuzzy
|
284
|
+
:multiple_matches: choose
|
261
285
|
:output_title: false
|
262
|
-
:highlighter: auto
|
263
286
|
:pager: auto
|
264
|
-
:
|
265
|
-
:
|
266
|
-
:
|
267
|
-
:
|
268
|
-
:header_format: border
|
287
|
+
:paginate: true
|
288
|
+
:show_all_code: false
|
289
|
+
:show_all_on_error: false
|
290
|
+
:wrap: 0
|
269
291
|
|
270
292
|
If `:color:` is false, output will not be colored, and markdown highlighting will be bypassed.
|
271
293
|
|
@@ -336,6 +358,12 @@ If set to `auto` howzit will look for markdown highlighters in this order, using
|
|
336
358
|
|
337
359
|
If you're combining a highlighter with howzit's pagination, include any flags needed to disable the highlighter's pagination (e.g. `mdless --no-pager`).
|
338
360
|
|
361
|
+
### Configuring from the Command Line
|
362
|
+
|
363
|
+
You can get and set config options from the command line using `--config-get` and `--config-set`. If you run `--config-get` with no argument, it will display all config options. If you add a key (exact match required) you can get just the value for that key.
|
364
|
+
|
365
|
+
Using `--config-set` requires an argument in the format `key=value`. The type of the value (boolean, integer, string, symbol) will be automatically determined and converted. To change your highlighter, for example, use `howzit --config-set highlighter=mdcat`.
|
366
|
+
|
339
367
|
## Shell Integration
|
340
368
|
|
341
369
|
I personally like to alias `bld` to `howzit -r`. If you define a function in your shell, you can have it default to "build" but accept an alternate argument. There's an example for Fish included, and in Bash it would be as simple as `howzit -r ${1:build}`.
|
data/bin/howzit
CHANGED
@@ -74,11 +74,18 @@ OptionParser.new do |opts|
|
|
74
74
|
end
|
75
75
|
|
76
76
|
opts.on('-q', '--quiet', 'Silence info message') do
|
77
|
-
Howzit.options[:log_level] =
|
77
|
+
Howzit.options[:log_level] = 4
|
78
|
+
Howzit.console.reset_level
|
78
79
|
end
|
79
80
|
|
80
81
|
opts.on('-v', '--verbose', 'Show all messages') do
|
82
|
+
Howzit.options[:log_level] = 1
|
83
|
+
Howzit.console.reset_level
|
84
|
+
end
|
85
|
+
|
86
|
+
opts.on('-d', '--debug', 'Show debug messages (and all messages)') do
|
81
87
|
Howzit.options[:log_level] = 0
|
88
|
+
Howzit.console.reset_level
|
82
89
|
end
|
83
90
|
|
84
91
|
opts.on('-u', '--[no-]upstream', 'Traverse up parent directories for additional build notes') do |p|
|
@@ -114,8 +121,8 @@ OptionParser.new do |opts|
|
|
114
121
|
raise 'Argument must be KEY=VALUE' unless key =~ /\S=\S/
|
115
122
|
|
116
123
|
parts = key.split(/=/)
|
117
|
-
k = parts
|
118
|
-
v = parts
|
124
|
+
k = parts.shift.sub(/^:/, '')
|
125
|
+
v = parts.join(' ')
|
119
126
|
|
120
127
|
if Howzit.options.key?(k.to_sym)
|
121
128
|
Howzit.options[k.to_sym] = v.to_config_value(Howzit.options[k.to_sym])
|
data/lib/howzit/buildnote.rb
CHANGED
@@ -89,7 +89,7 @@ module Howzit
|
|
89
89
|
# Create a buildnotes skeleton
|
90
90
|
def create_note
|
91
91
|
trap('SIGINT') do
|
92
|
-
|
92
|
+
Howzit.console.info "\nCanceled"
|
93
93
|
exit!
|
94
94
|
end
|
95
95
|
default = !$stdout.isatty || Howzit.options[:default]
|
@@ -269,8 +269,8 @@ module Howzit
|
|
269
269
|
required = t_meta['required'].strip.split(/\s*,\s*/)
|
270
270
|
required.each do |req|
|
271
271
|
unless @metadata.keys.include?(req.downcase)
|
272
|
-
|
273
|
-
|
272
|
+
Howzit.console.error %({xr}ERROR: Missing required metadata key from template '{bw}#{File.basename(template, '.md')}{xr}'{x}).c
|
273
|
+
Howzit.console.error %({xr}Please define {by}#{req.downcase}{xr} in build notes{x}).c
|
274
274
|
Process.exit 1
|
275
275
|
end
|
276
276
|
end
|
data/lib/howzit/config.rb
CHANGED
@@ -91,12 +91,12 @@ module Howzit
|
|
91
91
|
|
92
92
|
def create_config(d)
|
93
93
|
unless File.directory?(config_dir)
|
94
|
-
|
94
|
+
Howzit.console.info "Creating config directory at #{config_dir}"
|
95
95
|
FileUtils.mkdir_p(config_dir)
|
96
96
|
end
|
97
97
|
|
98
98
|
unless File.exist?(config_file)
|
99
|
-
|
99
|
+
Howzit.console.info "Writing fresh config file to #{config_file}"
|
100
100
|
write_config(d)
|
101
101
|
end
|
102
102
|
config_file
|
@@ -0,0 +1,43 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
LOG_LEVELS = {
|
4
|
+
debug: 0,
|
5
|
+
info: 1,
|
6
|
+
warn: 2,
|
7
|
+
error: 3
|
8
|
+
}.deep_freeze
|
9
|
+
|
10
|
+
module Howzit
|
11
|
+
# Console logging
|
12
|
+
class ConsoleLogger
|
13
|
+
attr_accessor :log_level
|
14
|
+
|
15
|
+
def initialize(level = nil)
|
16
|
+
@log_level = level || Howzit.options[:log_level]
|
17
|
+
end
|
18
|
+
|
19
|
+
def reset_level
|
20
|
+
@log_level = Howzit.options[:log_level]
|
21
|
+
end
|
22
|
+
|
23
|
+
def write(msg, level = :info)
|
24
|
+
$stderr.puts msg if LOG_LEVELS[level] >= @log_level
|
25
|
+
end
|
26
|
+
|
27
|
+
def debug(msg)
|
28
|
+
write msg, :debug
|
29
|
+
end
|
30
|
+
|
31
|
+
def info(msg)
|
32
|
+
write msg, :info
|
33
|
+
end
|
34
|
+
|
35
|
+
def warn(msg)
|
36
|
+
write msg, :warn
|
37
|
+
end
|
38
|
+
|
39
|
+
def error(msg)
|
40
|
+
write msg, :error
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
data/lib/howzit/hash.rb
CHANGED
@@ -32,4 +32,24 @@ class ::Hash
|
|
32
32
|
def deep_thaw!
|
33
33
|
replace deep_thaw
|
34
34
|
end
|
35
|
+
|
36
|
+
# Turn all keys into string
|
37
|
+
#
|
38
|
+
# Return a copy of the hash where all its keys are strings
|
39
|
+
def stringify_keys
|
40
|
+
each_with_object({}) { |(k, v), hsh| hsh[k.to_s] = v.is_a?(Hash) ? v.stringify_keys : v }
|
41
|
+
end
|
42
|
+
|
43
|
+
def stringify_keys!
|
44
|
+
replace stringify_keys
|
45
|
+
end
|
46
|
+
|
47
|
+
# Turn all keys into symbols
|
48
|
+
def symbolize_keys
|
49
|
+
each_with_object({}) { |(k, v), hsh| hsh[k.to_sym] = v.is_a?(Hash) ? v.symbolize_keys : v }
|
50
|
+
end
|
51
|
+
|
52
|
+
def symbolize_keys!
|
53
|
+
replace symbolize_keys
|
54
|
+
end
|
35
55
|
end
|
data/lib/howzit/prompt.rb
CHANGED
data/lib/howzit/task.rb
CHANGED
@@ -2,13 +2,19 @@
|
|
2
2
|
|
3
3
|
module Howzit
|
4
4
|
class Task
|
5
|
-
attr_reader :type, :title, :action, :parent
|
5
|
+
attr_reader :type, :title, :action, :parent, :optional, :default
|
6
6
|
|
7
|
-
def initialize(type, title, action, parent = nil)
|
7
|
+
def initialize(type, title, action, parent = nil, optional: false, default: true)
|
8
8
|
@type = type
|
9
9
|
@title = title
|
10
10
|
@action = action.render_arguments
|
11
11
|
@parent = parent
|
12
|
+
@optional = optional
|
13
|
+
@default = default
|
14
|
+
end
|
15
|
+
|
16
|
+
def inspect
|
17
|
+
%(<#Howzit::Task @type=:#{@type} @title="#{@title}" @block?=#{@action.split(/\n/).count > 1}>)
|
12
18
|
end
|
13
19
|
|
14
20
|
def to_s
|
@@ -16,7 +22,7 @@ module Howzit
|
|
16
22
|
end
|
17
23
|
|
18
24
|
def to_list
|
19
|
-
" * #{@type}: #{@title}"
|
25
|
+
" * #{@type}: #{@title.gsub(/\\n/, '\n')}"
|
20
26
|
end
|
21
27
|
end
|
22
28
|
end
|
data/lib/howzit/topic.rb
CHANGED
@@ -28,14 +28,21 @@ module Howzit
|
|
28
28
|
if @tasks.count.positive?
|
29
29
|
unless @prereqs.empty?
|
30
30
|
puts @prereqs.join("\n\n")
|
31
|
-
res = Prompt.yn('This
|
31
|
+
res = Prompt.yn('This topic has prerequisites, have they been met?', default: true)
|
32
32
|
Process.exit 1 unless res
|
33
33
|
|
34
34
|
end
|
35
35
|
|
36
36
|
@tasks.each do |task|
|
37
|
+
if task.optional
|
38
|
+
q = %({bg}#{task.type.to_s.capitalize} {xw}"{bw}#{task.title}{xw}"{x}).c
|
39
|
+
res = Prompt.yn(q, default: task.default)
|
40
|
+
next unless res
|
41
|
+
|
42
|
+
end
|
43
|
+
|
37
44
|
if task.type == :block
|
38
|
-
|
45
|
+
Howzit.console.info "{bg}Running block {bw}#{title}{x}".c if Howzit.options[:log_level] < 2
|
39
46
|
block = task.action
|
40
47
|
script = Tempfile.new('howzit_script')
|
41
48
|
begin
|
@@ -74,7 +81,7 @@ module Howzit
|
|
74
81
|
end
|
75
82
|
end
|
76
83
|
else
|
77
|
-
warn "{r}--run: No {br}@directive{xr} found in {bw}#{
|
84
|
+
Howzit.console.warn "{r}--run: No {br}@directive{xr} found in {bw}#{@title}{x}".c
|
78
85
|
end
|
79
86
|
output.push("{bm}Ran #{tasks} #{tasks == 1 ? 'task' : 'tasks'}{x}".c) if Howzit.options[:log_level] < 2 && !nested
|
80
87
|
|
@@ -88,21 +95,21 @@ module Howzit
|
|
88
95
|
out = "{bg}Copying {bw}#{string}".c
|
89
96
|
case os
|
90
97
|
when /darwin.*/i
|
91
|
-
|
98
|
+
$stderr.puts "#{out} (macOS){x}".c if Howzit.options[:log_level].zero?
|
92
99
|
`echo #{Shellwords.escape(string)}'\\c'|pbcopy`
|
93
100
|
when /mingw|mswin/i
|
94
|
-
|
101
|
+
$stderr.puts "#{out} (Windows){x}".c if Howzit.options[:log_level].zero?
|
95
102
|
`echo #{Shellwords.escape(string)} | clip`
|
96
103
|
else
|
97
104
|
if 'xsel'.available?
|
98
|
-
|
105
|
+
$stderr.puts "#{out} (Linux, xsel){x}".c if Howzit.options[:log_level].zero?
|
99
106
|
`echo #{Shellwords.escape(string)}'\\c'|xsel -i`
|
100
107
|
elsif 'xclip'.available?
|
101
|
-
|
108
|
+
$stderr.puts "#{out} (Linux, xclip){x}".c if Howzit.options[:log_level].zero?
|
102
109
|
`echo #{Shellwords.escape(string)}'\\c'|xclip -i`
|
103
110
|
else
|
104
|
-
|
105
|
-
|
111
|
+
$stderr.puts out if Howzit.options[:log_level].zero?
|
112
|
+
$stderr.puts 'Unable to determine executable for clipboard.'
|
106
113
|
end
|
107
114
|
end
|
108
115
|
end
|
@@ -112,18 +119,18 @@ module Howzit
|
|
112
119
|
out = "{bg}Opening {bw}#{command}".c
|
113
120
|
case os
|
114
121
|
when /darwin.*/i
|
115
|
-
|
122
|
+
Howzit.console.debug "#{out} (macOS){x}".c if Howzit.options[:log_level] < 2
|
116
123
|
`open #{Shellwords.escape(command)}`
|
117
124
|
when /mingw|mswin/i
|
118
|
-
|
125
|
+
Howzit.console.debug "#{out} (Windows){x}".c if Howzit.options[:log_level] < 2
|
119
126
|
`start #{Shellwords.escape(command)}`
|
120
127
|
else
|
121
128
|
if 'xdg-open'.available?
|
122
|
-
|
129
|
+
Howzit.console.debug "#{out} (Linux){x}".c if Howzit.options[:log_level] < 2
|
123
130
|
`xdg-open #{Shellwords.escape(command)}`
|
124
131
|
else
|
125
|
-
|
126
|
-
|
132
|
+
Howzit.console.debug out if Howzit.options[:log_level] < 2
|
133
|
+
Howzit.console.debug 'Unable to determine executable for `open`.'
|
127
134
|
end
|
128
135
|
end
|
129
136
|
end
|
@@ -139,49 +146,57 @@ module Howzit
|
|
139
146
|
output.push('')
|
140
147
|
end
|
141
148
|
topic = @content.dup
|
142
|
-
topic.gsub!(/(?mi)^(`{3,})run *([^\n]*)[\s\S]*?\n\1\s*$/, '@@@run \
|
149
|
+
topic.gsub!(/(?mi)^(`{3,})run([?!]*) *([^\n]*)[\s\S]*?\n\1\s*$/, '@@@run\2 \3') unless Howzit.options[:show_all_code]
|
143
150
|
topic.split(/\n/).each do |l|
|
144
151
|
case l
|
145
152
|
when /@(before|after|prereq|end)/
|
146
153
|
next
|
147
|
-
when /@include
|
148
|
-
m = Regexp.last_match
|
149
|
-
matches = Howzit.buildnote.find_topic(m[
|
154
|
+
when /@include(?<optional>[!?]{1,2})?\((?<action>.*?)\)/
|
155
|
+
m = Regexp.last_match.named_captures.symbolize_keys
|
156
|
+
matches = Howzit.buildnote.find_topic(m[:action])
|
150
157
|
unless matches.empty?
|
151
|
-
|
152
|
-
|
153
|
-
|
154
|
-
|
155
|
-
|
156
|
-
|
157
|
-
|
158
|
-
|
159
|
-
|
160
|
-
|
161
|
-
|
158
|
+
i_topic = matches[0]
|
159
|
+
rule = '{kKd}'
|
160
|
+
color = '{Kyd}'
|
161
|
+
option = if i_topic.tasks.empty?
|
162
|
+
''
|
163
|
+
else
|
164
|
+
optional = m[:optional] =~ /[?!]+/ ? true : false
|
165
|
+
default = m[:optional] =~ /!/ ? false : true
|
166
|
+
if optional
|
167
|
+
default ? " {xKk}[{gbK}Y{xKk}/{dbwK}n{xKk}]{x}#{color}".c : " {xKk}[{dbwK}y{xKk}/{bgK}N{xKk}]{x}#{color}".c
|
168
|
+
else
|
169
|
+
''
|
170
|
+
end
|
171
|
+
end
|
172
|
+
title = "#{opt[:single] ? 'From' : 'Include'} #{i_topic.title}#{option}:"
|
173
|
+
options = { color: color, hr: '.', border: rule }
|
174
|
+
unless Howzit.inclusions.include?(i_topic)
|
175
|
+
output.push("#{'> ' * @nest_level}#{title}".format_header(options))
|
162
176
|
end
|
163
177
|
|
164
|
-
if opt[:single]
|
165
|
-
|
166
|
-
|
167
|
-
|
168
|
-
|
169
|
-
|
170
|
-
|
171
|
-
@nest_level -= 1
|
172
|
-
end
|
173
|
-
unless Howzit.inclusions.include?(matches[0])
|
174
|
-
output.push("#{'> ' * @nest_level}...".format_header({ color: color, hr: '.', border: rule }))
|
175
|
-
end
|
178
|
+
if opt[:single] && Howzit.inclusions.include?(i_topic)
|
179
|
+
output.push("#{'> ' * @nest_level}#{title} included above".format_header(options))
|
180
|
+
elsif opt[:single]
|
181
|
+
@nest_level += 1
|
182
|
+
output.concat(i_topic.print_out({ single: true, header: false }))
|
183
|
+
output.push("#{'> ' * @nest_level}...".format_header(options))
|
184
|
+
@nest_level -= 1
|
176
185
|
end
|
177
|
-
Howzit.inclusions.push(
|
186
|
+
Howzit.inclusions.push(i_topic)
|
178
187
|
end
|
179
|
-
|
180
|
-
|
181
|
-
|
182
|
-
|
183
|
-
|
184
|
-
|
188
|
+
when /@(?<cmd>run|copy|open|url|include)(?<optional>[?!]{1,2})?\((?<action>.*?)\) *(?<title>.*?)$/
|
189
|
+
m = Regexp.last_match.named_captures.symbolize_keys
|
190
|
+
cmd = m[:cmd]
|
191
|
+
obj = m[:action]
|
192
|
+
title = m[:title].empty? ? obj : m[:title].strip
|
193
|
+
optional = m[:optional] =~ /[?!]+/ ? true : false
|
194
|
+
default = m[:optional] =~ /!/ ? false : true
|
195
|
+
option = if optional
|
196
|
+
default ? ' {xk}[{g}Y{xk}/{dbw}n{xk}]{x}'.c : ' {xk}[{dbw}y{xk}/{g}N{xk}]{x}'.c
|
197
|
+
else
|
198
|
+
''
|
199
|
+
end
|
185
200
|
icon = case cmd
|
186
201
|
when 'run'
|
187
202
|
"\u{25B6}"
|
@@ -191,14 +206,28 @@ module Howzit
|
|
191
206
|
"\u{279A}"
|
192
207
|
end
|
193
208
|
|
194
|
-
output.push("{bmK}#{icon} {bwK}#{title.gsub(/\\n/, '\n')}{x}".c)
|
195
|
-
when /(
|
196
|
-
m = Regexp.last_match
|
197
|
-
|
209
|
+
output.push("{bmK}#{icon} {bwK}#{title.gsub(/\\n/, '\n')}{x}#{option}".c)
|
210
|
+
when /(?<fence>`{3,})run(?<optional>[!?]{1,2})? *(?<title>.*?)$/i
|
211
|
+
m = Regexp.last_match.named_captures.symbolize_keys
|
212
|
+
optional = m[:optional] =~ /[?!]+/ ? true : false
|
213
|
+
default = m[:optional] =~ /!/ ? false : true
|
214
|
+
option = if optional
|
215
|
+
default ? ' {xk}[{g}Y{xk}/{dbw}n{xk}]{x}'.c : ' {xk}[{dbw}y{xk}/{g}N{xk}]{x}'.c
|
216
|
+
else
|
217
|
+
''
|
218
|
+
end
|
219
|
+
desc = m[:title].length.positive? ? "Block: #{m[:title]}#{option}" : "Code Block#{option}"
|
198
220
|
output.push("{bmK}\u{25B6} {bwK}#{desc}{x}\n```".c)
|
199
|
-
when /@@@run *(
|
200
|
-
m = Regexp.last_match
|
201
|
-
|
221
|
+
when /@@@run(?<optional>[!?]{1,2})? *(?<title>.*?)$/i
|
222
|
+
m = Regexp.last_match.named_captures.symbolize_keys
|
223
|
+
optional = m[:optional] =~ /[?!]+/ ? true : false
|
224
|
+
default = m[:optional] =~ /!/ ? false : true
|
225
|
+
option = if optional
|
226
|
+
default ? ' {xk}[{g}Y{xk}/{dbw}n{xk}]{x}'.c : ' {xk}[{dbw}y{xk}/{g}N{xk}]{x}'.c
|
227
|
+
else
|
228
|
+
''
|
229
|
+
end
|
230
|
+
desc = m[:title].length.positive? ? "Block: #{m[:title]}#{option}" : "Code Block#{option}"
|
202
231
|
output.push("{bmK}\u{25B6} {bwK}#{desc}{x}".c)
|
203
232
|
else
|
204
233
|
l.wrap!(Howzit.options[:wrap]) if Howzit.options[:wrap].positive?
|
@@ -215,18 +244,27 @@ module Howzit
|
|
215
244
|
@prereqs = @content.scan(/(?<=@before\n).*?(?=\n@end)/im).map(&:strip)
|
216
245
|
@postreqs = @content.scan(/(?<=@after\n).*?(?=\n@end)/im).map(&:strip)
|
217
246
|
|
218
|
-
rx = /(
|
219
|
-
|
247
|
+
rx = /(?mix)(?:
|
248
|
+
@(?<cmd>include|run|copy|open|url)(?<optional>[!?]{1,2})?\((?<action>[^)]*?)\)(?<title>[^\n]+)?
|
249
|
+
|(?<fence>`{3,})run(?<optional2>[!?]{1,2})?(?<title2>[^\n]+)?(?<block>.*?)\k<fence>
|
250
|
+
)/
|
251
|
+
matches = []
|
252
|
+
@content.scan(rx) { matches << Regexp.last_match }
|
253
|
+
matches.each do |m|
|
254
|
+
c = m.named_captures.symbolize_keys
|
220
255
|
|
221
|
-
|
222
|
-
|
223
|
-
|
224
|
-
|
225
|
-
|
256
|
+
if c[:cmd].nil?
|
257
|
+
optional = c[:optional2] =~ /[?!]{1,2}/ ? true : false
|
258
|
+
default = c[:optional2] =~ /!/ ? false : true
|
259
|
+
title = c[:title2].nil? ? '' : c[:title2].strip
|
260
|
+
block = c[:block]&.strip
|
261
|
+
runnable << Howzit::Task.new(:block, title, block, optional: optional, default: default)
|
226
262
|
else
|
227
|
-
cmd = c[
|
228
|
-
|
229
|
-
|
263
|
+
cmd = c[:cmd]
|
264
|
+
optional = c[:optional] =~ /[?!]{1,2}/ ? true : false
|
265
|
+
default = c[:optional] =~ /!/ ? false : true
|
266
|
+
obj = c[:action]
|
267
|
+
title = c[:title].nil? ? obj : c[:title].strip
|
230
268
|
|
231
269
|
case cmd
|
232
270
|
when /include/i
|
@@ -239,17 +277,15 @@ module Howzit
|
|
239
277
|
# end
|
240
278
|
# runnable.concat(tasks)
|
241
279
|
# end
|
242
|
-
title
|
243
|
-
runnable << Howzit::Task.new(:include, title, obj)
|
280
|
+
runnable << Howzit::Task.new(:include, title, obj, optional: optional, default: default)
|
244
281
|
when /run/i
|
245
|
-
title = c[3] || obj
|
246
282
|
# warn "{bg}Running {bw}#{obj}{x}".c if Howzit.options[:log_level] < 2
|
247
|
-
runnable << Howzit::Task.new(:run, title, obj)
|
283
|
+
runnable << Howzit::Task.new(:run, title, obj, optional: optional, default: default)
|
248
284
|
when /copy/i
|
249
285
|
# warn "{bg}Copied {bw}#{obj}{bg} to clipboard{x}".c if Howzit.options[:log_level] < 2
|
250
|
-
runnable << Howzit::Task.new(:copy, title, Shellwords.escape(obj))
|
286
|
+
runnable << Howzit::Task.new(:copy, title, Shellwords.escape(obj), optional: optional, default: default)
|
251
287
|
when /open|url/i
|
252
|
-
runnable << Howzit::Task.new(:open, title, obj)
|
288
|
+
runnable << Howzit::Task.new(:open, title, obj, optional: optional, default: default)
|
253
289
|
end
|
254
290
|
end
|
255
291
|
end
|
data/lib/howzit/util.rb
CHANGED
@@ -40,7 +40,7 @@ module Howzit
|
|
40
40
|
if hl.available?
|
41
41
|
Howzit.options[:highlighter]
|
42
42
|
else
|
43
|
-
|
43
|
+
Howzit.console.error Color.template("{Rw}Error:{xbw} Specified highlighter (#{Howzit.options[:highlighter]}) not found, switching to auto")
|
44
44
|
Howzit.options[:highlighter] = 'auto'
|
45
45
|
which_highlighter
|
46
46
|
end
|
@@ -78,7 +78,7 @@ module Howzit
|
|
78
78
|
if pg.available?
|
79
79
|
Howzit.options[:pager]
|
80
80
|
else
|
81
|
-
|
81
|
+
Howzit.console.error Color.template("{Rw}Error:{xbw} Specified pager (#{Howzit.options[:pager]}) not found, switching to auto")
|
82
82
|
Howzit.options[:pager] = 'auto'
|
83
83
|
which_pager
|
84
84
|
end
|
@@ -104,7 +104,7 @@ module Howzit
|
|
104
104
|
begin
|
105
105
|
exec(pager)
|
106
106
|
rescue SystemCallError => e
|
107
|
-
|
107
|
+
Howzit.console.error(e)
|
108
108
|
exit 1
|
109
109
|
end
|
110
110
|
end
|
data/lib/howzit/version.rb
CHANGED
data/lib/howzit.rb
CHANGED
@@ -5,8 +5,9 @@ require_relative 'howzit/prompt'
|
|
5
5
|
require_relative 'howzit/colors'
|
6
6
|
require_relative 'howzit/stringutils'
|
7
7
|
|
8
|
-
require_relative 'howzit/util'
|
9
8
|
require_relative 'howzit/hash'
|
9
|
+
require_relative 'howzit/console_logger'
|
10
|
+
require_relative 'howzit/util'
|
10
11
|
require_relative 'howzit/config'
|
11
12
|
require_relative 'howzit/task'
|
12
13
|
require_relative 'howzit/topic'
|
@@ -52,5 +53,9 @@ module Howzit
|
|
52
53
|
def buildnote
|
53
54
|
@buildnote ||= BuildNote.new
|
54
55
|
end
|
56
|
+
|
57
|
+
def console
|
58
|
+
@console ||= Howzit::ConsoleLogger.new(options[:log_level])
|
59
|
+
end
|
55
60
|
end
|
56
61
|
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: howzit
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 2.0.
|
4
|
+
version: 2.0.7
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Brett Terpstra
|
@@ -272,6 +272,7 @@ files:
|
|
272
272
|
- lib/howzit/buildnotes.rb
|
273
273
|
- lib/howzit/colors.rb
|
274
274
|
- lib/howzit/config.rb
|
275
|
+
- lib/howzit/console_logger.rb
|
275
276
|
- lib/howzit/hash.rb
|
276
277
|
- lib/howzit/prompt.rb
|
277
278
|
- lib/howzit/stringutils.rb
|