howzit 2.0.26 → 2.0.29

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 0ef20bf69eaecc6f2d2df7ac9621dfbd227af13148ce2e0465d466b6206d8a59
4
- data.tar.gz: 5923dbabfc6ec5d6bc1783ebb21b1a231fbfdaaa2ecd3887582b014a9642d8ab
3
+ metadata.gz: 1e49b8c3399fb8c6aa96f857ea9dd77e8f91b1292783c0b25167ebf9aa380485
4
+ data.tar.gz: 9af75120a0e39cc371bf68f78335be3fcc8ea508e18c64fe5b94d1e9affec4a8
5
5
  SHA512:
6
- metadata.gz: b5e8c29926fa85e6b52e4d8463504a474f4d0e35765a8bf85294ab46f84e11c10d9f77f002d85ed2ea0db4657edd23a9faabe03f5c7ba0796aa38407d00e1180
7
- data.tar.gz: 9340eff4ab693b1e82e11b201d63da704a4dc4d647bd5443b7b2bdfa8b5f1af98dc61cf4b42f76247c2ba4adbf2651ab82ea082136f68bdf0c5ebc0c904898d5
6
+ metadata.gz: f13f6c1d353c0ef3f8e041a0e3b2864ad808601c5aa4f3423d2830872e26650d29c33fce7b723489ac0557e314e17de8b3aba333a9692dda4e375bd372f17988
7
+ data.tar.gz: 9ebc50f699029414cd72d12ac83a591d6bcbe8f18f1cab175ea6bb81e40baf19b823129c7458947d6d9806448e1018209572f73271ca5c2398ba73f3fa9b9967
data/CHANGELOG.md CHANGED
@@ -1,3 +1,33 @@
1
+ ### 2.0.29
2
+
3
+ 2022-08-30 04:20
4
+
5
+ #### NEW
6
+
7
+ - --yes flag will answer yes to all prompts when executing
8
+ - --force flag will continue executing directives after an error
9
+
10
+ #### IMPROVED
11
+
12
+ - A non-zero exit status on a run directive will stop processing additional directives
13
+ - A little extra output formatting, more descriptive results logging
14
+
15
+ ### 2.0.28
16
+
17
+ 2022-08-29 18:42
18
+
19
+ #### IMPROVED
20
+
21
+ - If a topic runs multiple directives, stop processing them if one returns a non-zero exit status
22
+
23
+ ### 2.0.27
24
+
25
+ 2022-08-23 12:25
26
+
27
+ #### IMPROVED
28
+
29
+ - Code cleanup
30
+
1
31
  ### 2.0.26
2
32
 
3
33
  2022-08-23 11:36
data/bin/howzit CHANGED
@@ -20,14 +20,16 @@ OptionParser.new do |opts|
20
20
 
21
21
  opts.separator " Behavior:\n\n" #=================================================================== BEHAVIOR
22
22
 
23
- opts.on('--ask', 'Request confirmation for all tasks when running a topic') do
24
- Howzit.options[:ask] = true
25
- end
23
+ opts.on('--ask', 'Request confirmation for all tasks when running a topic') { Howzit.options[:ask] = true }
26
24
 
27
25
  opts.on('--default', 'Answer all prompts with default response') do
26
+ raise '--default cannot be used with --yes' if Howzit.options[:yes]
27
+
28
28
  Howzit.options[:default] = true
29
29
  end
30
30
 
31
+ opts.on('-f', '--force', 'Continue executing after an error') { Howzit.options[:force] = true }
32
+
31
33
  opts.on('-m', '--matching TYPE', MATCHING_OPTIONS,
32
34
  'Topics matching type', "(#{MATCHING_OPTIONS.join(', ')})") do |c|
33
35
  Howzit.options[:matching] = c
@@ -42,6 +44,12 @@ OptionParser.new do |opts|
42
44
  Howzit.options[:include_upstream] = p
43
45
  end
44
46
 
47
+ opts.on('-y', '--yes', 'Answer yes to all prompts') do
48
+ raise '--default cannot be used with --yes' if Howzit.options[:default]
49
+
50
+ Howzit.options[:yes] = true
51
+ end
52
+
45
53
  opts.separator "\n Listing:\n\n" #=================================================================== LISTING
46
54
 
47
55
  opts.on('-L', '--list-completions', 'List topics (completion-compatible)') do
data/lib/howzit/colors.rb CHANGED
@@ -227,7 +227,7 @@ module Howzit
227
227
  def template(input)
228
228
  input = input.join(' ') if input.is_a? Array
229
229
  fmt = input.gsub(/%/, '%%')
230
- fmt = fmt.gsub(/\{(\w+)\}/) do
230
+ fmt = fmt.gsub(/(?<!\\u)\{(\w+)\}/i) do
231
231
  Regexp.last_match(1).split('').map { |c| "%<#{c}>s" }.join('')
232
232
  end
233
233
 
data/lib/howzit/config.rb CHANGED
@@ -91,6 +91,7 @@ module Howzit
91
91
  choose: false,
92
92
  default: false,
93
93
  for_topic: nil,
94
+ force: false,
94
95
  grep: nil,
95
96
  list_runnable: false,
96
97
  list_runnable_titles: false,
@@ -99,7 +100,8 @@ module Howzit
99
100
  quiet: false,
100
101
  run: false,
101
102
  title_only: false,
102
- verbose: false
103
+ verbose: false,
104
+ yes: false
103
105
  }
104
106
 
105
107
  config = load_config
data/lib/howzit/prompt.rb CHANGED
@@ -18,6 +18,8 @@ module Howzit
18
18
  def yn(prompt, default: true)
19
19
  return default unless $stdout.isatty
20
20
 
21
+ return true if Howzit.options[:yes]
22
+
21
23
  return default if Howzit.options[:default]
22
24
 
23
25
  tty_state = `stty -g`
@@ -87,60 +89,86 @@ module Howzit
87
89
  return [] if !$stdout.isatty || matches.count.zero?
88
90
 
89
91
  if Util.command_exist?('fzf')
90
- height = if height == :auto
91
- matches.count + 3
92
- else
93
- TTY::Screen.rows
94
- end
95
-
96
- settings = [
97
- '-0',
98
- '-1',
99
- '-m',
100
- "--height=#{height}",
101
- '--header="Tab: add selection, ctrl-a/d: (de)select all, return: display/run"',
102
- '--bind ctrl-a:select-all,ctrl-d:deselect-all,ctrl-t:toggle-all',
103
- '--prompt="Select a topic > "',
104
- %(--preview="howzit --no-pager --header-format block --no-color --default --multiple first {}")
105
- ]
92
+ height = height == :auto ? matches.count + 3 : TTY::Screen.rows
93
+
94
+ settings = fzf_options(height)
106
95
  res = `echo #{Shellwords.escape(matches.join("\n"))} | fzf #{settings.join(' ')}`.strip
107
- if res.nil? || res.empty?
108
- Howzit.console.info 'Cancelled'
109
- Process.exit 0
110
- end
111
- return res.split(/\n/)
96
+ return fzf_result(res)
97
+ end
98
+
99
+ tty_menu(matches)
100
+ end
101
+
102
+ def fzf_result(res)
103
+ if res.nil? || res.empty?
104
+ Howzit.console.info 'Cancelled'
105
+ Process.exit 0
112
106
  end
107
+ return res.split(/\n/)
108
+ end
109
+
110
+ def fzf_options(height)
111
+ [
112
+ '-0',
113
+ '-1',
114
+ '-m',
115
+ "--height=#{height}",
116
+ '--header="Tab: add selection, ctrl-a/d: (de)select all, return: display/run"',
117
+ '--bind ctrl-a:select-all,ctrl-d:deselect-all,ctrl-t:toggle-all',
118
+ '--prompt="Select a topic > "',
119
+ %(--preview="howzit --no-pager --header-format block --no-color --default --multiple first {}")
120
+ ]
121
+ end
113
122
 
123
+ ##
124
+ ## Display a numeric menu on the TTY
125
+ ##
126
+ ## @param matches The matches from which to select
127
+ ##
128
+ def tty_menu(matches)
114
129
  return matches if matches.count == 1
115
130
 
116
- res = matches[0..9]
117
- stty_save = `stty -g`.chomp
131
+ @stty_save = `stty -g`.chomp
118
132
 
119
133
  trap('INT') do
120
- system('stty', stty_save)
134
+ system('stty')
121
135
  exit
122
136
  end
123
137
 
124
138
  options_list(matches)
139
+ read_selection(matches)
140
+ end
125
141
 
126
- begin
127
- printf("Type 'q' to cancel, enter for first item", res.length)
128
- while (line = Readline.readline(': ', true))
129
- if line =~ /^[a-z]/i
130
- system('stty', stty_save) # Restore
131
- exit
132
- end
133
- line = line == '' ? 1 : line.to_i
142
+ ##
143
+ ## Read a single number response from the command line
144
+ ##
145
+ ## @param matches The matches
146
+ ##
147
+ def read_selection(matches)
148
+ printf "Type 'q' to cancel, enter for first item"
149
+ while (line = Readline.readline(': ', true))
150
+ line = read_num(line)
134
151
 
135
- return [matches[line - 1]] if line.positive? && line <= matches.length
152
+ return [matches[line - 1]] if line.positive? && line <= matches.length
136
153
 
137
- puts 'Out of range'
138
- options_list(matches)
139
- end
140
- ensure
141
- system('stty', stty_save)
154
+ puts 'Out of range'
155
+ read_selection(matches)
156
+ end
157
+ ensure
158
+ system('stty', @stty_save)
159
+ end
160
+
161
+ ##
162
+ ## Convert a response to an Integer
163
+ ##
164
+ ## @param line The response to convert
165
+ ##
166
+ def read_num(line)
167
+ if line =~ /^[a-z]/i
168
+ system('stty', @stty_save) # Restore
142
169
  exit
143
170
  end
171
+ line == '' ? 1 : line.to_i
144
172
  end
145
173
  end
146
174
  end
data/lib/howzit/task.rb CHANGED
@@ -19,6 +19,9 @@ module Howzit
19
19
  ## @option attributes :action [String] task action
20
20
  ## @option attributes :parent [String] title of nested (included) topic origin
21
21
  def initialize(attributes, optional: false, default: true)
22
+ @prefix = "{bw}\u{25B7}\u{25B7} {x}"
23
+ # arrow = "{bw}\u{279F}{x}"
24
+
22
25
  @type = attributes[:type] || :run
23
26
  @title = attributes[:title] || nil
24
27
  @action = attributes[:action].render_arguments || nil
@@ -49,18 +52,20 @@ module Howzit
49
52
  ## Execute a block type
50
53
  ##
51
54
  def run_block
52
- Howzit.console.info "{bg}Running block {bw}#{@title}{x}".c if Howzit.options[:log_level] < 2
55
+ Howzit.console.info "#{@prefix}{bg}Running block {bw}#{@title}{x}".c if Howzit.options[:log_level] < 2
53
56
  block = @action
54
57
  script = Tempfile.new('howzit_script')
55
58
  begin
56
59
  script.write(block)
57
60
  script.close
58
61
  File.chmod(0o777, script.path)
59
- system(%(/bin/sh -c "#{script.path}"))
62
+ res = system(%(/bin/sh -c "#{script.path}"))
60
63
  ensure
61
64
  script.close
62
65
  script.unlink
63
66
  end
67
+
68
+ res
64
69
  end
65
70
 
66
71
  ##
@@ -73,7 +78,7 @@ module Howzit
73
78
  matches = Howzit.buildnote.find_topic(@action)
74
79
  raise "Topic not found: #{@action}" if matches.empty?
75
80
 
76
- Howzit.console.info("{by}Running tasks from {bw}#{matches[0].title}{x}".c)
81
+ Howzit.console.info("#{@prefix}{by}Running tasks from {bw}#{matches[0].title}{x}".c)
77
82
  output.concat(matches[0].run(nested: true))
78
83
  Howzit.console.info("{by}End include: #{matches[0].tasks.count} tasks{x}".c)
79
84
  [output, matches[0].tasks.count]
@@ -84,8 +89,8 @@ module Howzit
84
89
  ##
85
90
  def run_run
86
91
  title = Howzit.options[:show_all_code] ? @action : @title
87
- Howzit.console.info("{bg}Running {bw}#{title}{x}".c)
88
- system(@action)
92
+ Howzit.console.info("#{@prefix}{bg}Running {bw}#{title}{x}".c)
93
+ return system(@action)
89
94
  end
90
95
 
91
96
  ##
@@ -93,8 +98,9 @@ module Howzit
93
98
  ##
94
99
  def run_copy
95
100
  title = Howzit.options[:show_all_code] ? @action : @title
96
- Howzit.console.info("{bg}Copied {bw}#{title}{bg} to clipboard{x}".c)
101
+ Howzit.console.info("#{@prefix}{bg}Copied {bw}#{title}{bg} to clipboard{x}".c)
97
102
  Util.os_copy(@action)
103
+ return true
98
104
  end
99
105
 
100
106
  ##
@@ -103,22 +109,22 @@ module Howzit
103
109
  def run
104
110
  output = []
105
111
  tasks = 1
106
- if @type == :block
107
- run_block
108
- else
109
- case @type
110
- when :include
111
- output, tasks = run_include
112
- when :run
113
- run_run
114
- when :copy
115
- run_copy
116
- when :open
117
- Util.os_open(@action)
118
- end
119
- end
112
+ res = if @type == :block
113
+ run_block
114
+ else
115
+ case @type
116
+ when :include
117
+ output, tasks = run_include
118
+ when :run
119
+ run_run
120
+ when :copy
121
+ run_copy
122
+ when :open
123
+ Util.os_open(@action)
124
+ end
125
+ end
120
126
 
121
- [output, tasks]
127
+ [output, tasks, res]
122
128
  end
123
129
 
124
130
  ##
data/lib/howzit/topic.rb CHANGED
@@ -7,7 +7,7 @@ module Howzit
7
7
 
8
8
  attr_accessor :content
9
9
 
10
- attr_reader :title, :tasks, :prereqs, :postreqs
10
+ attr_reader :title, :tasks, :prereqs, :postreqs, :results
11
11
 
12
12
  ##
13
13
  ## Initialize a topic object
@@ -21,6 +21,7 @@ module Howzit
21
21
  @parent = nil
22
22
  @nest_level = 0
23
23
  @tasks = gather_tasks
24
+ @results = { total: 0, success: 0, errors: 0, message: ''.c }
24
25
  end
25
26
 
26
27
  ##
@@ -35,7 +36,7 @@ module Howzit
35
36
  # Handle run command, execute directives in topic
36
37
  def run(nested: false)
37
38
  output = []
38
- tasks = 0
39
+
39
40
  cols = begin
40
41
  TTY::Screen.columns > 60 ? 60 : TTY::Screen.columns
41
42
  rescue StandardError
@@ -63,14 +64,36 @@ module Howzit
63
64
  next unless res
64
65
 
65
66
  end
66
- run_output, total = task.run
67
+ run_output, total, success = task.run
68
+
67
69
  output.concat(run_output)
68
- tasks += total
70
+ @results[:total] += total
71
+
72
+ if success
73
+ @results[:success] += total
74
+ else
75
+ Howzit.console.warn %({bw}\u{2297} {br}Error running task {bw}"#{task.title}"{x}).c
76
+
77
+ @results[:errors] += total
78
+
79
+ break unless Howzit.options[:force]
80
+ end
69
81
  end
82
+
83
+ total = "{bw}#{@results[:total]}{by} #{@results[:total] == 1 ? 'task' : 'tasks'}".c
84
+ errors = "{bw}#{@results[:errors]}{by} #{@results[:errors] == 1 ? 'error' : 'errors'}".c
85
+ @results[:message] += if @results[:errors].zero?
86
+ "{bg}\u{2713} {by}Ran #{total}{x}"
87
+ elsif Howzit.options[:force]
88
+ "{br}\u{2715} {by}Completed #{total} with #{errors}{x}".c
89
+ else
90
+ "{br}\u{2715} {by}Ran #{total}, terminated due to error{x}".c
91
+ end
70
92
  else
71
93
  Howzit.console.warn "{r}--run: No {br}@directive{xr} found in {bw}#{@title}{x}".c
72
94
  end
73
- output.push("{bm}Ran #{tasks} #{tasks == 1 ? 'task' : 'tasks'}{x}".c) if Howzit.options[:log_level] < 2 && !nested
95
+
96
+ output.push(@results[:message]) if Howzit.options[:log_level] < 2 && !nested
74
97
 
75
98
  puts TTY::Box.frame("{bw}#{@postreqs.join("\n\n").wrap(cols - 4)}{x}".c, width: cols) unless @postreqs.empty?
76
99
 
@@ -3,5 +3,5 @@
3
3
  # Primary module for this gem.
4
4
  module Howzit
5
5
  # Current Howzit version.
6
- VERSION = '2.0.26'
6
+ VERSION = '2.0.29'
7
7
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: howzit
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.0.26
4
+ version: 2.0.29
5
5
  platform: ruby
6
6
  authors:
7
7
  - Brett Terpstra
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2022-08-23 00:00:00.000000000 Z
11
+ date: 2022-08-30 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler