howzit 2.0.26 → 2.0.29

Sign up to get free protection for your applications and to get access to all the features.
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