howzit 1.2.13 → 1.2.16
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/CHANGELOG.md +38 -0
- data/README.md +18 -5
- data/bin/howzit +193 -2
- data/lib/howzit/buildnote.rb +543 -0
- data/lib/howzit/buildnotes.rb +115 -37
- data/lib/howzit/colors.rb +3 -3
- 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 +79 -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 +42 -5
- data/spec/ruby_gem_spec.rb +87 -17
- metadata +8 -2
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
|
data/lib/howzit/util.rb
ADDED
@@ -0,0 +1,149 @@
|
|
1
|
+
module Howzit
|
2
|
+
module Util
|
3
|
+
class << self
|
4
|
+
def valid_command?(command)
|
5
|
+
cmd = command.split(' ')[0]
|
6
|
+
command_exist?(cmd)
|
7
|
+
end
|
8
|
+
|
9
|
+
def command_exist?(command)
|
10
|
+
exts = ENV.fetch('PATHEXT', '').split(::File::PATH_SEPARATOR)
|
11
|
+
if Pathname.new(command).absolute?
|
12
|
+
::File.exist?(command) ||
|
13
|
+
exts.any? { |ext| ::File.exist?("#{command}#{ext}") }
|
14
|
+
else
|
15
|
+
ENV.fetch('PATH', '').split(::File::PATH_SEPARATOR).any? do |dir|
|
16
|
+
file = ::File.join(dir, command)
|
17
|
+
::File.exist?(file) ||
|
18
|
+
exts.any? { |ext| ::File.exist?("#{file}#{ext}") }
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
# If either mdless or mdcat are installed, use that for highlighting
|
24
|
+
# markdown
|
25
|
+
def which_highlighter
|
26
|
+
if Howzit.options[:highlighter] =~ /auto/i
|
27
|
+
highlighters = %w[mdcat mdless]
|
28
|
+
highlighters.delete_if(&:nil?).select!(&:available?)
|
29
|
+
return nil if highlighters.empty?
|
30
|
+
|
31
|
+
hl = highlighters.first
|
32
|
+
args = case hl
|
33
|
+
when 'mdless'
|
34
|
+
'--no-pager'
|
35
|
+
end
|
36
|
+
|
37
|
+
[hl, args].join(' ')
|
38
|
+
else
|
39
|
+
hl = Howzit.options[:highlighter].split(/ /)[0]
|
40
|
+
if hl.available?
|
41
|
+
Howzit.options[:highlighter]
|
42
|
+
else
|
43
|
+
warn Color.template("{Rw}Error:{xbw} Specified highlighter (#{Howzit.options[:highlighter]}) not found, switching to auto")
|
44
|
+
Howzit.options[:highlighter] = 'auto'
|
45
|
+
which_highlighter
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
# When pagination is enabled, find the best (in my opinion) option,
|
51
|
+
# favoring environment settings
|
52
|
+
def which_pager
|
53
|
+
if Howzit.options[:pager] =~ /auto/i
|
54
|
+
pagers = [ENV['PAGER'], ENV['GIT_PAGER'],
|
55
|
+
'bat', 'less', 'more', 'pager']
|
56
|
+
pagers.delete_if(&:nil?).select!(&:available?)
|
57
|
+
return nil if pagers.empty?
|
58
|
+
|
59
|
+
pg = pagers.first
|
60
|
+
args = case pg
|
61
|
+
when 'delta'
|
62
|
+
'--pager="less -FXr"'
|
63
|
+
when /^(less|more)$/
|
64
|
+
'-FXr'
|
65
|
+
when 'bat'
|
66
|
+
if Howzit.options[:highlight]
|
67
|
+
'--language Markdown --style plain --pager="less -FXr"'
|
68
|
+
else
|
69
|
+
'--style plain --pager="less -FXr"'
|
70
|
+
end
|
71
|
+
else
|
72
|
+
''
|
73
|
+
end
|
74
|
+
|
75
|
+
[pg, args].join(' ')
|
76
|
+
else
|
77
|
+
pg = Howzit.options[:pager].split(/ /)[0]
|
78
|
+
if pg.available?
|
79
|
+
Howzit.options[:pager]
|
80
|
+
else
|
81
|
+
warn Color.template("{Rw}Error:{xbw} Specified pager (#{Howzit.options[:pager]}) not found, switching to auto")
|
82
|
+
Howzit.options[:pager] = 'auto'
|
83
|
+
which_pager
|
84
|
+
end
|
85
|
+
end
|
86
|
+
end
|
87
|
+
|
88
|
+
# Paginate the output
|
89
|
+
def page(text)
|
90
|
+
read_io, write_io = IO.pipe
|
91
|
+
|
92
|
+
input = $stdin
|
93
|
+
|
94
|
+
pid = Kernel.fork do
|
95
|
+
write_io.close
|
96
|
+
input.reopen(read_io)
|
97
|
+
read_io.close
|
98
|
+
|
99
|
+
# Wait until we have input before we start the pager
|
100
|
+
IO.select [input]
|
101
|
+
|
102
|
+
pager = which_pager
|
103
|
+
|
104
|
+
begin
|
105
|
+
exec(pager)
|
106
|
+
rescue SystemCallError => e
|
107
|
+
@log.error(e)
|
108
|
+
exit 1
|
109
|
+
end
|
110
|
+
end
|
111
|
+
|
112
|
+
read_io.close
|
113
|
+
write_io.write(text)
|
114
|
+
write_io.close
|
115
|
+
|
116
|
+
_, status = Process.waitpid2(pid)
|
117
|
+
|
118
|
+
status.success?
|
119
|
+
end
|
120
|
+
|
121
|
+
# print output to terminal
|
122
|
+
def show(string, opts = {})
|
123
|
+
options = {
|
124
|
+
color: true,
|
125
|
+
highlight: false,
|
126
|
+
wrap: 0
|
127
|
+
}
|
128
|
+
|
129
|
+
options.merge!(opts)
|
130
|
+
|
131
|
+
string = string.uncolor unless options[:color]
|
132
|
+
|
133
|
+
pipes = ''
|
134
|
+
if options[:highlight]
|
135
|
+
hl = which_highlighter
|
136
|
+
pipes = "|#{hl}" if hl
|
137
|
+
end
|
138
|
+
|
139
|
+
output = `echo #{Shellwords.escape(string.strip)}#{pipes}`.strip
|
140
|
+
|
141
|
+
if Howzit.options[:paginate]
|
142
|
+
page(output)
|
143
|
+
else
|
144
|
+
puts output
|
145
|
+
end
|
146
|
+
end
|
147
|
+
end
|
148
|
+
end
|
149
|
+
end
|
data/lib/howzit/version.rb
CHANGED
data/lib/howzit.rb
CHANGED
@@ -1,8 +1,17 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
|
4
|
-
|
5
|
-
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative 'howzit/version'
|
4
|
+
require_relative 'howzit/prompt'
|
5
|
+
require_relative 'howzit/colors'
|
6
|
+
require_relative 'howzit/stringutils'
|
7
|
+
|
8
|
+
require_relative 'howzit/util'
|
9
|
+
require_relative 'howzit/hash'
|
10
|
+
require_relative 'howzit/config'
|
11
|
+
require_relative 'howzit/task'
|
12
|
+
require_relative 'howzit/topic'
|
13
|
+
require_relative 'howzit/buildnote'
|
14
|
+
|
6
15
|
require 'optparse'
|
7
16
|
require 'shellwords'
|
8
17
|
require 'pathname'
|
@@ -16,3 +25,31 @@ CONFIG_DIR = '~/.config/howzit'
|
|
16
25
|
CONFIG_FILE = 'howzit.yaml'
|
17
26
|
IGNORE_FILE = 'ignore.yaml'
|
18
27
|
MATCHING_OPTIONS = %w[partial exact fuzzy beginswith].freeze
|
28
|
+
MULTIPLE_OPTIONS = %w[first best all choose].freeze
|
29
|
+
HEADER_FORMAT_OPTIONS = %w[border block].freeze
|
30
|
+
|
31
|
+
module Howzit
|
32
|
+
class << self
|
33
|
+
attr_accessor :arguments, :cli_args
|
34
|
+
##
|
35
|
+
## Holds a Configuration object with methods and a @settings hash
|
36
|
+
##
|
37
|
+
## @return [Configuration] Configuration object
|
38
|
+
##
|
39
|
+
def config
|
40
|
+
@config ||= Config.new
|
41
|
+
end
|
42
|
+
|
43
|
+
def inclusions
|
44
|
+
@inclusions ||= []
|
45
|
+
end
|
46
|
+
|
47
|
+
def options
|
48
|
+
config.options
|
49
|
+
end
|
50
|
+
|
51
|
+
def buildnote
|
52
|
+
@buildnote ||= BuildNote.new
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|
data/spec/ruby_gem_spec.rb
CHANGED
@@ -1,40 +1,110 @@
|
|
1
1
|
require 'spec_helper'
|
2
2
|
|
3
|
-
describe Howzit::
|
4
|
-
subject(:
|
3
|
+
describe Howzit::BuildNote do
|
4
|
+
subject(:buildnote) { Howzit.buildnote }
|
5
5
|
|
6
6
|
describe ".new" do
|
7
7
|
it "makes a new instance" do
|
8
|
-
expect(
|
8
|
+
expect(buildnote).to be_a Howzit::BuildNote
|
9
9
|
end
|
10
10
|
end
|
11
11
|
end
|
12
12
|
|
13
|
-
describe Howzit::
|
13
|
+
describe Howzit::Task do
|
14
|
+
subject(:task) { Howzit::Task.new(:run, 'List Directory', 'ls') }
|
15
|
+
|
16
|
+
describe ".new" do
|
17
|
+
it "makes a new task instance" do
|
18
|
+
expect(task).to be_a Howzit::Task
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
describe Howzit::Topic do
|
24
|
+
title = 'Test Title'
|
25
|
+
content = 'Test Content'
|
26
|
+
subject(:topic) { Howzit::Topic.new(title, content) }
|
27
|
+
|
28
|
+
describe ".new" do
|
29
|
+
it "makes a new topic instance" do
|
30
|
+
expect(topic).to be_a Howzit::Topic
|
31
|
+
end
|
32
|
+
it "has the correct title" do
|
33
|
+
expect(topic.title).to eq title
|
34
|
+
end
|
35
|
+
it "has the correct content" do
|
36
|
+
expect(topic.content).to eq content
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
describe Howzit::BuildNote do
|
14
42
|
Dir.chdir('spec')
|
15
|
-
|
16
|
-
|
17
|
-
|
43
|
+
Howzit.options[:include_upstream] = false
|
44
|
+
Howzit.options[:default] = true
|
45
|
+
hz = Howzit.buildnote
|
46
|
+
|
47
|
+
hz.create_note
|
48
|
+
subject(:how) { hz }
|
18
49
|
|
19
50
|
describe ".note_file" do
|
20
51
|
it "locates a build note file" do
|
21
|
-
expect(
|
52
|
+
expect(how.note_file).not_to be_empty
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
describe ".grep" do
|
57
|
+
it "finds topic containing 'editable'" do
|
58
|
+
expect(how.grep('editable').map { |topic| topic.title }).to include('File Structure')
|
59
|
+
end
|
60
|
+
it "does not return non-matching topic" do
|
61
|
+
expect(how.grep('editable').map { |topic| topic.title }).not_to include('Build')
|
22
62
|
end
|
23
63
|
end
|
24
64
|
|
25
|
-
describe ".
|
26
|
-
it "
|
27
|
-
|
28
|
-
expect(
|
65
|
+
describe ".find_topic" do
|
66
|
+
it "finds the File Structure topic" do
|
67
|
+
matches = how.find_topic('file struct')
|
68
|
+
expect(matches.count).to eq 1
|
69
|
+
expect(matches[0].title).to eq 'File Structure'
|
70
|
+
end
|
71
|
+
it "fuzzy matches" do
|
72
|
+
Howzit.options[:matching] = 'fuzzy'
|
73
|
+
matches = how.find_topic('flestct')
|
74
|
+
expect(matches.count).to eq 1
|
75
|
+
expect(matches[0].title).to eq 'File Structure'
|
76
|
+
end
|
77
|
+
it "succeeds with partial match" do
|
78
|
+
Howzit.options[:matching] = 'partial'
|
79
|
+
matches = how.find_topic('structure')
|
80
|
+
expect(matches.count).to eq 1
|
81
|
+
expect(matches[0].title).to eq 'File Structure'
|
82
|
+
end
|
83
|
+
it "succeeds with beginswith match" do
|
84
|
+
Howzit.options[:matching] = 'beginswith'
|
85
|
+
matches = how.find_topic('file')
|
86
|
+
expect(matches.count).to eq 1
|
87
|
+
expect(matches[0].title).to eq 'File Structure'
|
88
|
+
end
|
89
|
+
it "succeeds with exact match" do
|
90
|
+
Howzit.options[:matching] = 'exact'
|
91
|
+
matches = how.find_topic('file structure')
|
92
|
+
expect(matches.count).to eq 1
|
93
|
+
expect(matches[0].title).to eq 'File Structure'
|
94
|
+
end
|
95
|
+
it "fails with incomplete exact match" do
|
96
|
+
Howzit.options[:matching] = 'exact'
|
97
|
+
matches = how.find_topic('file struct')
|
98
|
+
expect(matches.count).to eq 0
|
29
99
|
end
|
30
100
|
end
|
31
101
|
|
32
|
-
describe ".
|
33
|
-
it "
|
34
|
-
expect(
|
102
|
+
describe ".topics" do
|
103
|
+
it "contains 4 topics" do
|
104
|
+
expect(how.list_topics.count).to eq 4
|
35
105
|
end
|
36
|
-
it "outputs a newline-separated string" do
|
37
|
-
expect(
|
106
|
+
it "outputs a newline-separated string for completion" do
|
107
|
+
expect(how.list_completions.scan(/\n/).count).to eq 3
|
38
108
|
end
|
39
109
|
end
|
40
110
|
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: 1.2.
|
4
|
+
version: 1.2.16
|
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-
|
11
|
+
date: 2022-08-03 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bundler
|
@@ -268,10 +268,16 @@ files:
|
|
268
268
|
- howzit.gemspec
|
269
269
|
- lib/.rubocop.yml
|
270
270
|
- lib/howzit.rb
|
271
|
+
- lib/howzit/buildnote.rb
|
271
272
|
- lib/howzit/buildnotes.rb
|
272
273
|
- lib/howzit/colors.rb
|
274
|
+
- lib/howzit/config.rb
|
275
|
+
- lib/howzit/hash.rb
|
273
276
|
- lib/howzit/prompt.rb
|
274
277
|
- lib/howzit/stringutils.rb
|
278
|
+
- lib/howzit/task.rb
|
279
|
+
- lib/howzit/topic.rb
|
280
|
+
- lib/howzit/util.rb
|
275
281
|
- lib/howzit/version.rb
|
276
282
|
- spec/.rubocop.yml
|
277
283
|
- spec/ruby_gem_spec.rb
|