howzit 1.2.14 → 1.2.17
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/.rubocop.yml +5 -0
- data/CHANGELOG.md +33 -0
- data/README.md +3 -0
- data/bin/howzit +193 -2
- data/lib/howzit/buildnote.rb +543 -0
- data/lib/howzit/buildnotes.rb +22 -11
- data/lib/howzit/colors.rb +2 -2
- data/lib/howzit/config.rb +128 -0
- data/lib/howzit/hash.rb +35 -0
- data/lib/howzit/prompt.rb +84 -11
- data/lib/howzit/stringutils.rb +54 -8
- data/lib/howzit/task.rb +22 -0
- data/lib/howzit/topic.rb +233 -0
- data/lib/howzit/util.rb +149 -0
- data/lib/howzit/version.rb +1 -1
- data/lib/howzit.rb +41 -5
- data/spec/ruby_gem_spec.rb +87 -17
- metadata +8 -2
@@ -0,0 +1,128 @@
|
|
1
|
+
module Howzit
|
2
|
+
# Config Class
|
3
|
+
class Config
|
4
|
+
attr_reader :options
|
5
|
+
|
6
|
+
DEFAULTS = {
|
7
|
+
color: true,
|
8
|
+
config_editor: ENV['EDITOR'] || nil,
|
9
|
+
editor: ENV['EDITOR'] || nil,
|
10
|
+
header_format: 'border',
|
11
|
+
highlight: true,
|
12
|
+
highlighter: 'auto',
|
13
|
+
include_upstream: false,
|
14
|
+
log_level: 1, # 0: debug, 1: info, 2: warn, 3: error
|
15
|
+
matching: 'partial', # exact, partial, fuzzy, beginswith
|
16
|
+
multiple_matches: 'choose',
|
17
|
+
output_title: false,
|
18
|
+
pager: 'auto',
|
19
|
+
paginate: true,
|
20
|
+
show_all_code: false,
|
21
|
+
show_all_on_error: false,
|
22
|
+
wrap: 0
|
23
|
+
}.deep_freeze
|
24
|
+
|
25
|
+
def initialize
|
26
|
+
load_options
|
27
|
+
end
|
28
|
+
|
29
|
+
def write_config(config)
|
30
|
+
File.open(config_file, 'w') { |f| f.puts config.to_yaml }
|
31
|
+
end
|
32
|
+
|
33
|
+
def should_ignore(filename)
|
34
|
+
return false unless File.exist?(ignore_file)
|
35
|
+
|
36
|
+
@ignore_patterns ||= YAML.safe_load(IO.read(ignore_file))
|
37
|
+
|
38
|
+
ignore = false
|
39
|
+
|
40
|
+
@ignore_patterns.each do |pat|
|
41
|
+
if filename =~ /#{pat}/
|
42
|
+
ignore = true
|
43
|
+
break
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
ignore
|
48
|
+
end
|
49
|
+
|
50
|
+
def template_folder
|
51
|
+
File.join(config_dir, 'templates')
|
52
|
+
end
|
53
|
+
|
54
|
+
def editor
|
55
|
+
edit_config(DEFAULTS)
|
56
|
+
end
|
57
|
+
|
58
|
+
private
|
59
|
+
|
60
|
+
def load_options
|
61
|
+
Color.coloring = $stdout.isatty
|
62
|
+
flags = {
|
63
|
+
choose: false,
|
64
|
+
default: false,
|
65
|
+
grep: nil,
|
66
|
+
list_runnable: false,
|
67
|
+
list_runnable_titles: false,
|
68
|
+
list_topic_titles: false,
|
69
|
+
list_topics: false,
|
70
|
+
quiet: false,
|
71
|
+
run: false,
|
72
|
+
title_only: false,
|
73
|
+
verbose: false
|
74
|
+
}
|
75
|
+
|
76
|
+
config = load_config
|
77
|
+
@options = flags.merge(config)
|
78
|
+
end
|
79
|
+
|
80
|
+
def config_dir
|
81
|
+
File.expand_path(CONFIG_DIR)
|
82
|
+
end
|
83
|
+
|
84
|
+
def config_file
|
85
|
+
File.join(config_dir, CONFIG_FILE)
|
86
|
+
end
|
87
|
+
|
88
|
+
def ignore_file
|
89
|
+
File.join(config_dir, IGNORE_FILE)
|
90
|
+
end
|
91
|
+
|
92
|
+
def create_config(d)
|
93
|
+
unless File.directory?(config_dir)
|
94
|
+
warn "Creating config directory at #{config_dir}"
|
95
|
+
FileUtils.mkdir_p(config_dir)
|
96
|
+
end
|
97
|
+
|
98
|
+
unless File.exist?(config_file)
|
99
|
+
warn "Writing fresh config file to #{config_file}"
|
100
|
+
write_config(d)
|
101
|
+
end
|
102
|
+
config_file
|
103
|
+
end
|
104
|
+
|
105
|
+
def load_config
|
106
|
+
file = create_config(DEFAULTS)
|
107
|
+
config = YAML.load(IO.read(file))
|
108
|
+
newconfig = config ? DEFAULTS.merge(config) : DEFAULTS
|
109
|
+
write_config(newconfig)
|
110
|
+
newconfig.dup
|
111
|
+
end
|
112
|
+
|
113
|
+
def edit_config(d)
|
114
|
+
editor = Howzit.options.fetch(:config_editor, ENV['EDITOR'])
|
115
|
+
|
116
|
+
raise 'No config_editor defined' if editor.nil?
|
117
|
+
|
118
|
+
# raise "Invalid editor (#{editor})" unless Util.valid_command?(editor)
|
119
|
+
|
120
|
+
load_config
|
121
|
+
if Util.valid_command?(editor.split(/ /).first)
|
122
|
+
system %(#{editor} "#{config_file}")
|
123
|
+
else
|
124
|
+
`open -a "#{editor}" "#{config_file}"`
|
125
|
+
end
|
126
|
+
end
|
127
|
+
end
|
128
|
+
end
|
data/lib/howzit/hash.rb
ADDED
@@ -0,0 +1,35 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
# Hash helpers
|
4
|
+
class ::Hash
|
5
|
+
##
|
6
|
+
## Freeze all values in a hash
|
7
|
+
##
|
8
|
+
## @return Hash with all values frozen
|
9
|
+
##
|
10
|
+
def deep_freeze
|
11
|
+
chilled = {}
|
12
|
+
each do |k, v|
|
13
|
+
chilled[k] = v.is_a?(Hash) ? v.deep_freeze : v.freeze
|
14
|
+
end
|
15
|
+
|
16
|
+
chilled.freeze
|
17
|
+
end
|
18
|
+
|
19
|
+
def deep_freeze!
|
20
|
+
replace deep_thaw.deep_freeze
|
21
|
+
end
|
22
|
+
|
23
|
+
def deep_thaw
|
24
|
+
chilled = {}
|
25
|
+
each do |k, v|
|
26
|
+
chilled[k] = v.is_a?(Hash) ? v.deep_thaw : v.dup
|
27
|
+
end
|
28
|
+
|
29
|
+
chilled.dup
|
30
|
+
end
|
31
|
+
|
32
|
+
def deep_thaw!
|
33
|
+
replace deep_thaw
|
34
|
+
end
|
35
|
+
end
|
data/lib/howzit/prompt.rb
CHANGED
@@ -3,17 +3,90 @@
|
|
3
3
|
module Howzit
|
4
4
|
# Command line prompt utils
|
5
5
|
module Prompt
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
6
|
+
class << self
|
7
|
+
def yn(prompt, default = true)
|
8
|
+
return default if !$stdout.isatty
|
9
|
+
|
10
|
+
system 'stty cbreak'
|
11
|
+
yn = color_single_options(default ? %w[Y n] : %w[y N])
|
12
|
+
$stdout.syswrite "\e[1;37m#{prompt} #{yn}\e[1;37m? \e[0m"
|
13
|
+
res = $stdin.sysread 1
|
14
|
+
res.chomp!
|
15
|
+
puts
|
16
|
+
system 'stty cooked'
|
17
|
+
res.empty? ? default : res =~ /y/i
|
18
|
+
end
|
19
|
+
|
20
|
+
def color_single_options(choices = %w[y n])
|
21
|
+
out = []
|
22
|
+
choices.each do |choice|
|
23
|
+
case choice
|
24
|
+
when /[A-Z]/
|
25
|
+
out.push(Color.template("{bg}#{choice}{xg}"))
|
26
|
+
else
|
27
|
+
out.push(Color.template("{w}#{choice}"))
|
28
|
+
end
|
29
|
+
end
|
30
|
+
Color.template("{g}[#{out.join('/')}{g}]{x}")
|
31
|
+
end
|
32
|
+
|
33
|
+
def options_list(matches)
|
34
|
+
counter = 1
|
35
|
+
puts
|
36
|
+
matches.each do |match|
|
37
|
+
printf("%<counter>2d ) %<option>s\n", counter: counter, option: match)
|
38
|
+
counter += 1
|
39
|
+
end
|
40
|
+
puts
|
41
|
+
end
|
42
|
+
|
43
|
+
def choose(matches)
|
44
|
+
if Util.command_exist?('fzf')
|
45
|
+
settings = [
|
46
|
+
'-0',
|
47
|
+
'-1',
|
48
|
+
'-m',
|
49
|
+
"--height=#{matches.count + 2}",
|
50
|
+
'--header="Use tab to mark multiple selections, enter to display/run"',
|
51
|
+
'--prompt="Select a section > "'
|
52
|
+
]
|
53
|
+
res = `echo #{Shellwords.escape(matches.join("\n"))} | fzf #{settings.join(' ')}`.strip
|
54
|
+
if res.nil? || res.empty?
|
55
|
+
warn 'Cancelled'
|
56
|
+
Process.exit 0
|
57
|
+
end
|
58
|
+
return res.split(/\n/)
|
59
|
+
end
|
60
|
+
|
61
|
+
res = matches[0..9]
|
62
|
+
stty_save = `stty -g`.chomp
|
63
|
+
|
64
|
+
trap('INT') do
|
65
|
+
system('stty', stty_save)
|
66
|
+
exit
|
67
|
+
end
|
68
|
+
|
69
|
+
options_list(matches)
|
70
|
+
|
71
|
+
begin
|
72
|
+
printf("Type 'q' to cancel, enter for first item", res.length)
|
73
|
+
while (line = Readline.readline(': ', true))
|
74
|
+
if line =~ /^[a-z]/i
|
75
|
+
system('stty', stty_save) # Restore
|
76
|
+
exit
|
77
|
+
end
|
78
|
+
line = line == '' ? 1 : line.to_i
|
79
|
+
|
80
|
+
return matches[line - 1] if line.positive? && line <= matches.length
|
81
|
+
|
82
|
+
puts 'Out of range'
|
83
|
+
options_list(matches)
|
84
|
+
end
|
85
|
+
rescue Interrupt
|
86
|
+
system('stty', stty_save)
|
87
|
+
exit
|
88
|
+
end
|
89
|
+
end
|
17
90
|
end
|
18
91
|
end
|
19
92
|
end
|
data/lib/howzit/stringutils.rb
CHANGED
@@ -28,6 +28,19 @@ module Howzit
|
|
28
28
|
end
|
29
29
|
end
|
30
30
|
|
31
|
+
def to_rx
|
32
|
+
case Howzit.options[:matching]
|
33
|
+
when 'exact'
|
34
|
+
/^#{self}$/i
|
35
|
+
when 'beginswith'
|
36
|
+
/^#{self}/i
|
37
|
+
when 'fuzzy'
|
38
|
+
/#{split(//).join('.*?')}/i
|
39
|
+
else
|
40
|
+
/#{self}/i
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
31
44
|
# Just strip out color codes when requested
|
32
45
|
def uncolor
|
33
46
|
gsub(/\e\[[\d;]+m/, '').gsub(/\e\]1337;SetMark/,'')
|
@@ -103,20 +116,15 @@ module Howzit
|
|
103
116
|
end
|
104
117
|
|
105
118
|
def available?
|
106
|
-
|
107
|
-
File.executable?(File.expand_path(self))
|
108
|
-
else
|
109
|
-
system "which #{self}", out: File::NULL
|
110
|
-
end
|
119
|
+
Util.valid_command?(self)
|
111
120
|
end
|
112
121
|
|
113
122
|
def render_template(vars)
|
114
|
-
content = dup
|
115
123
|
vars.each do |k, v|
|
116
|
-
|
124
|
+
gsub!(/\[%#{k}(:.*?)?\]/, v)
|
117
125
|
end
|
118
126
|
|
119
|
-
|
127
|
+
gsub(/\[%(.*?):(.*?)\]/, '\2')
|
120
128
|
end
|
121
129
|
|
122
130
|
def render_template!(vars)
|
@@ -154,6 +162,44 @@ module Howzit
|
|
154
162
|
end
|
155
163
|
data
|
156
164
|
end
|
165
|
+
|
166
|
+
def should_mark_iterm?
|
167
|
+
ENV['TERM_PROGRAM'] =~ /^iTerm/ && !Howzit.options[:run] && !Howzit.options[:paginate]
|
168
|
+
end
|
169
|
+
|
170
|
+
def iterm_marker
|
171
|
+
"\e]1337;SetMark\a" if should_mark_iterm?
|
172
|
+
end
|
173
|
+
|
174
|
+
# Make a fancy title line for the topic
|
175
|
+
def format_header(opts = {})
|
176
|
+
title = dup
|
177
|
+
options = {
|
178
|
+
hr: "\u{254C}",
|
179
|
+
color: '{bg}',
|
180
|
+
border: '{x}',
|
181
|
+
mark: should_mark_iterm?
|
182
|
+
}
|
183
|
+
|
184
|
+
options.merge!(opts)
|
185
|
+
|
186
|
+
case Howzit.options[:header_format]
|
187
|
+
when :block
|
188
|
+
Color.template("#{options[:color]}\u{258C}#{title}#{should_mark_iterm? && options[:mark] ? iterm_marker : ''}{x}")
|
189
|
+
else
|
190
|
+
cols = TTY::Screen.columns
|
191
|
+
|
192
|
+
cols = Howzit.options[:wrap] if (Howzit.options[:wrap]).positive? && cols > Howzit.options[:wrap]
|
193
|
+
title = Color.template("#{options[:border]}#{options[:hr] * 2}( #{options[:color]}#{title}#{options[:border]} )")
|
194
|
+
|
195
|
+
tail = if should_mark_iterm?
|
196
|
+
"#{options[:hr] * (cols - title.uncolor.length - 15)}#{options[:mark] ? iterm_marker : ''}"
|
197
|
+
else
|
198
|
+
options[:hr] * (cols - title.uncolor.length)
|
199
|
+
end
|
200
|
+
Color.template("#{title}#{tail}{x}")
|
201
|
+
end
|
202
|
+
end
|
157
203
|
end
|
158
204
|
end
|
159
205
|
|
data/lib/howzit/task.rb
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Howzit
|
4
|
+
class Task
|
5
|
+
attr_reader :type, :title, :action, :parent
|
6
|
+
|
7
|
+
def initialize(type, title, action, parent = nil)
|
8
|
+
@type = type
|
9
|
+
@title = title
|
10
|
+
@action = action
|
11
|
+
@parent = parent
|
12
|
+
end
|
13
|
+
|
14
|
+
def to_s
|
15
|
+
@title
|
16
|
+
end
|
17
|
+
|
18
|
+
def to_list
|
19
|
+
" * #{@type}: #{@title}"
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
data/lib/howzit/topic.rb
ADDED
@@ -0,0 +1,233 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Howzit
|
4
|
+
# Topic Class
|
5
|
+
class Topic
|
6
|
+
attr_writer :parent
|
7
|
+
|
8
|
+
attr_reader :title, :content, :tasks, :prereqs, :postreqs
|
9
|
+
|
10
|
+
def initialize(title, content)
|
11
|
+
@title = title
|
12
|
+
@content = content
|
13
|
+
@parent = nil
|
14
|
+
@nest_level = 0
|
15
|
+
@tasks = gather_tasks
|
16
|
+
end
|
17
|
+
|
18
|
+
def grep(term)
|
19
|
+
@title =~ /#{term}/i || @content =~ /#{term}/i
|
20
|
+
end
|
21
|
+
|
22
|
+
# Handle run command, execute directives
|
23
|
+
def run(nested: false)
|
24
|
+
output = []
|
25
|
+
tasks = 0
|
26
|
+
if @tasks.count.positive?
|
27
|
+
unless @prereqs.empty?
|
28
|
+
puts @prereqs.join("\n\n")
|
29
|
+
res = Prompt.yn('This task has prerequisites, have they been met?', true)
|
30
|
+
Process.exit 1 unless res
|
31
|
+
|
32
|
+
end
|
33
|
+
|
34
|
+
@tasks.each do |task|
|
35
|
+
if task.type == :block
|
36
|
+
warn Color.template("{bg}Running block {bw}#{title}{x}") if Howzit.options[:log_level] < 2
|
37
|
+
block = task.action
|
38
|
+
script = Tempfile.new('howzit_script')
|
39
|
+
begin
|
40
|
+
script.write(block)
|
41
|
+
script.close
|
42
|
+
File.chmod(0777, script.path)
|
43
|
+
system(%(/bin/sh -c "#{script.path}"))
|
44
|
+
tasks += 1
|
45
|
+
ensure
|
46
|
+
script.close
|
47
|
+
script.unlink
|
48
|
+
end
|
49
|
+
else
|
50
|
+
case task.type
|
51
|
+
when :include
|
52
|
+
matches = Howzit.buildnote.find_topic(task.action)
|
53
|
+
raise "Topic not found: #{task.action}" if matches.empty?
|
54
|
+
|
55
|
+
warn Color.template("{by}Running tasks from {bw}#{matches[0].title}{x}") if Howzit.options[:log_level] < 2
|
56
|
+
output.push(matches[0].run(nested: true))
|
57
|
+
warn Color.template("{by}End include: #{matches[0].tasks.count} tasks") if Howzit.options[:log_level] < 2
|
58
|
+
tasks += matches[0].tasks.count
|
59
|
+
when :run
|
60
|
+
warn Color.template("{bg}Running {bw}#{task.title}{x}") if Howzit.options[:log_level] < 2
|
61
|
+
system(task.action)
|
62
|
+
tasks += 1
|
63
|
+
when :copy
|
64
|
+
warn Color.template("{bg}Copied {bw}#{task.title}{bg} to clipboard{x}") if Howzit.options[:log_level] < 2
|
65
|
+
`echo #{Shellwords.escape(task.action)}'\\c'|pbcopy`
|
66
|
+
tasks += 1
|
67
|
+
when :open
|
68
|
+
os_open(task.action)
|
69
|
+
tasks += 1
|
70
|
+
end
|
71
|
+
end
|
72
|
+
end
|
73
|
+
else
|
74
|
+
warn Color.template("{r}--run: No {br}@directive{xr} found in {bw}#{key}{x}")
|
75
|
+
end
|
76
|
+
output.push(Color.template("{bm}Ran #{tasks} #{tasks == 1 ? 'task' : 'tasks'}{x}")) if Howzit.options[:log_level] < 2 && !nested
|
77
|
+
|
78
|
+
puts postreqs.join("\n\n") unless postreqs.empty?
|
79
|
+
|
80
|
+
output
|
81
|
+
end
|
82
|
+
|
83
|
+
def os_open(command)
|
84
|
+
os = RbConfig::CONFIG['target_os']
|
85
|
+
out = Color.template("{bg}Opening {bw}#{command}")
|
86
|
+
case os
|
87
|
+
when /darwin.*/i
|
88
|
+
warn Color.template("#{out} (macOS){x}") if Howzit.options[:log_level] < 2
|
89
|
+
`open #{Shellwords.escape(command)}`
|
90
|
+
when /mingw|mswin/i
|
91
|
+
warn Color.template("#{out} (Windows){x}") if Howzit.options[:log_level] < 2
|
92
|
+
`start #{Shellwords.escape(command)}`
|
93
|
+
else
|
94
|
+
if 'xdg-open'.available?
|
95
|
+
warn Color.template("#{out} (Linux){x}") if Howzit.options[:log_level] < 2
|
96
|
+
`xdg-open #{Shellwords.escape(command)}`
|
97
|
+
else
|
98
|
+
warn out if Howzit.options[:log_level] < 2
|
99
|
+
warn 'Unable to determine executable for `open`.'
|
100
|
+
end
|
101
|
+
end
|
102
|
+
end
|
103
|
+
|
104
|
+
# Output a topic with fancy title and bright white text.
|
105
|
+
def print_out(options = {})
|
106
|
+
defaults = { single: false, header: true }
|
107
|
+
opt = defaults.merge(options)
|
108
|
+
|
109
|
+
output = []
|
110
|
+
if opt[:header]
|
111
|
+
output.push(@title.format_header)
|
112
|
+
output.push('')
|
113
|
+
end
|
114
|
+
topic = @content.dup
|
115
|
+
topic.gsub!(/(?mi)^(`{3,})run *([^\n]*)[\s\S]*?\n\1\s*$/, '@@@run \2') unless Howzit.options[:show_all_code]
|
116
|
+
topic.split(/\n/).each do |l|
|
117
|
+
case l
|
118
|
+
when /@(before|after|prereq|end)/
|
119
|
+
next
|
120
|
+
when /@include\((.*?)\)/
|
121
|
+
|
122
|
+
m = Regexp.last_match
|
123
|
+
matches = Howzit.buildnote.find_topic(m[1])
|
124
|
+
unless matches.empty?
|
125
|
+
if opt[:single]
|
126
|
+
title = "From #{matches[0].title}:"
|
127
|
+
color = '{Kyd}'
|
128
|
+
rule = '{kKd}'
|
129
|
+
else
|
130
|
+
title = "Include #{matches[0].title}"
|
131
|
+
color = '{Kyd}'
|
132
|
+
rule = '{kKd}'
|
133
|
+
end
|
134
|
+
unless Howzit.inclusions.include?(matches[0])
|
135
|
+
output.push("#{'> ' * @nest_level}#{title}".format_header({ color: color, hr: '.', border: rule }))
|
136
|
+
end
|
137
|
+
|
138
|
+
if opt[:single]
|
139
|
+
if Howzit.inclusions.include?(matches[0])
|
140
|
+
output.push("#{'> ' * @nest_level}#{title} included above".format_header({
|
141
|
+
color: color, hr: '.', border: rule }))
|
142
|
+
else
|
143
|
+
@nest_level += 1
|
144
|
+
output.concat(matches[0].print_out({ single: true, header: false }))
|
145
|
+
@nest_level -= 1
|
146
|
+
end
|
147
|
+
unless Howzit.inclusions.include?(matches[0])
|
148
|
+
output.push("#{'> ' * @nest_level}...".format_header({ color: color, hr: '.', border: rule }))
|
149
|
+
end
|
150
|
+
end
|
151
|
+
Howzit.inclusions.push(matches[0])
|
152
|
+
end
|
153
|
+
|
154
|
+
when /@(run|copy|open|url|include)\((.*?)\)/
|
155
|
+
m = Regexp.last_match
|
156
|
+
cmd = m[1]
|
157
|
+
obj = m[2]
|
158
|
+
icon = case cmd
|
159
|
+
when 'run'
|
160
|
+
"\u{25B6}"
|
161
|
+
when 'copy'
|
162
|
+
"\u{271A}"
|
163
|
+
when /open|url/
|
164
|
+
"\u{279A}"
|
165
|
+
end
|
166
|
+
|
167
|
+
output.push(Color.template("{bmK}#{icon} {bwK}#{obj.gsub(/\\n/, '\n')}{x}"))
|
168
|
+
when /(`{3,})run *(.*?)$/i
|
169
|
+
m = Regexp.last_match
|
170
|
+
desc = m[2].length.positive? ? "Block: #{m[2]}" : 'Code Block'
|
171
|
+
output.push(Color.template("{bmK}\u{25B6} {bwK}#{desc}{x}\n```"))
|
172
|
+
when /@@@run *(.*?)$/i
|
173
|
+
m = Regexp.last_match
|
174
|
+
desc = m[1].length.positive? ? "Block: #{m[1]}" : 'Code Block'
|
175
|
+
output.push(Color.template("{bmK}\u{25B6} {bwK}#{desc}{x}"))
|
176
|
+
else
|
177
|
+
l.wrap!(Howzit.options[:wrap]) if (Howzit.options[:wrap]).positive?
|
178
|
+
output.push(l)
|
179
|
+
end
|
180
|
+
end
|
181
|
+
output.push('') # FIXME: Is this where the extra line is coming from?
|
182
|
+
end
|
183
|
+
|
184
|
+
private
|
185
|
+
|
186
|
+
def gather_tasks
|
187
|
+
runnable = []
|
188
|
+
@prereqs = @content.scan(/(?<=@before\n).*?(?=\n@end)/im).map(&:strip)
|
189
|
+
@postreqs = @content.scan(/(?<=@after\n).*?(?=\n@end)/im).map(&:strip)
|
190
|
+
|
191
|
+
rx = /(?:@(include|run|copy|open|url)\((.*?)\) *(.*?)(?=$)|(`{3,})run(?: +([^\n]+))?(.*?)\4)/mi
|
192
|
+
directives = @content.scan(rx)
|
193
|
+
|
194
|
+
directives.each do |c|
|
195
|
+
if c[0].nil?
|
196
|
+
title = c[4] ? c[4].strip : ''
|
197
|
+
block = c[5].strip
|
198
|
+
runnable << Howzit::Task.new(:block, title, block)
|
199
|
+
else
|
200
|
+
cmd = c[0]
|
201
|
+
obj = c[1]
|
202
|
+
title = c[3] || obj
|
203
|
+
|
204
|
+
case cmd
|
205
|
+
when /include/i
|
206
|
+
# matches = Howzit.buildnote.find_topic(obj)
|
207
|
+
# unless matches.empty? || Howzit.inclusions.include?(matches[0].title)
|
208
|
+
# tasks = matches[0].tasks.map do |inc|
|
209
|
+
# Howzit.inclusions.push(matches[0].title)
|
210
|
+
# inc.parent = matches[0]
|
211
|
+
# inc
|
212
|
+
# end
|
213
|
+
# runnable.concat(tasks)
|
214
|
+
# end
|
215
|
+
title = c[3] || obj
|
216
|
+
runnable << Howzit::Task.new(:include, title, obj)
|
217
|
+
when /run/i
|
218
|
+
title = c[3] || obj
|
219
|
+
# warn Color.template("{bg}Running {bw}#{obj}{x}") if Howzit.options[:log_level] < 2
|
220
|
+
runnable << Howzit::Task.new(:run, title, obj)
|
221
|
+
when /copy/i
|
222
|
+
# warn Color.template("{bg}Copied {bw}#{obj}{bg} to clipboard{x}") if Howzit.options[:log_level] < 2
|
223
|
+
runnable << Howzit::Task.new(:copy, title, Shellwords.escape(obj))
|
224
|
+
when /open|url/i
|
225
|
+
runnable << Howzit::Task.new(:open, title, obj)
|
226
|
+
end
|
227
|
+
end
|
228
|
+
end
|
229
|
+
|
230
|
+
runnable
|
231
|
+
end
|
232
|
+
end
|
233
|
+
end
|