howzit 2.1.10 → 2.1.13
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.rubocop.yml +36 -0
- data/CHANGELOG.md +12 -0
- data/Gemfile +3 -0
- data/README.md +3 -4
- data/Rakefile +31 -0
- data/lib/howzit/buildnote.rb +23 -21
- data/lib/howzit/colors.rb +30 -4
- data/lib/howzit/config.rb +3 -1
- data/lib/howzit/prompt.rb +1 -1
- data/lib/howzit/stringutils.rb +5 -5
- data/lib/howzit/task.rb +4 -3
- data/lib/howzit/topic.rb +182 -160
- data/lib/howzit/util.rb +27 -0
- data/lib/howzit/version.rb +1 -1
- data/lib/howzit.rb +2 -3
- data/spec/topic_spec.rb +11 -4
- data/src/_README.md +145 -0
- metadata +4 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: f0fc931036b21c7bb13c805751a146432d14c40a9a910fd9999aa42fb34658cb
|
4
|
+
data.tar.gz: 31b927c85e4c7ba6938eff929e7670c1a997d79f21053ce230da3a1a5ca4b246
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 6382fd78151da4a021d605276121fc48f0b1cb7692ee3a4657fd4dee820577f0f5357aa98be565dd120e440619906b1881da2269fe0e53c2321160a34dee26ac
|
7
|
+
data.tar.gz: d402a1dcf7715f04ed32fc282450c4132bf13cd3a43830eb464c298f79dc86fa4c47f30a6bd8d3698e588468f107b0b4eae6ad90c89195d878ef1f610846ab78
|
data/.rubocop.yml
CHANGED
@@ -1,15 +1,51 @@
|
|
1
|
+
require:
|
2
|
+
- rubocop-rspec
|
3
|
+
- rubocop-rake
|
4
|
+
|
1
5
|
AllCops:
|
2
6
|
Include:
|
3
7
|
- Gemfile
|
4
8
|
- Guardfile
|
5
9
|
- Rakefile
|
10
|
+
- bin/howzit
|
11
|
+
- lib/**/*.rb
|
12
|
+
|
13
|
+
Style/StringLiterals:
|
14
|
+
Enabled: true
|
15
|
+
EnforcedStyle: single_quotes
|
16
|
+
|
17
|
+
Style/StringLiteralsInInterpolation:
|
18
|
+
Enabled: true
|
19
|
+
EnforcedStyle: single_quotes
|
20
|
+
|
21
|
+
Layout/LineLength:
|
22
|
+
Max: 120
|
23
|
+
|
24
|
+
Metrics/MethodLength:
|
25
|
+
Max: 40
|
6
26
|
|
7
27
|
Metrics/BlockLength:
|
28
|
+
Max: 40
|
8
29
|
Exclude:
|
9
30
|
- Rakefile
|
10
31
|
- bin/howzit
|
11
32
|
- lib/*.rb
|
12
33
|
|
34
|
+
Metrics/ClassLength:
|
35
|
+
Max: 300
|
36
|
+
|
37
|
+
Metrics/CyclomaticComplexity:
|
38
|
+
Max: 10
|
39
|
+
|
40
|
+
Metrics/PerceivedComplexity:
|
41
|
+
Max: 30
|
42
|
+
|
43
|
+
Metrics/AbcSize:
|
44
|
+
Max: 45
|
45
|
+
|
46
|
+
Metrics/CyclomaticComplexity:
|
47
|
+
Max: 15
|
48
|
+
|
13
49
|
Style/RegexpLiteral:
|
14
50
|
Exclude:
|
15
51
|
- Guardfile
|
data/CHANGELOG.md
CHANGED
data/Gemfile
CHANGED
data/README.md
CHANGED
@@ -1,3 +1,4 @@
|
|
1
|
+
|
1
2
|
# Howzit
|
2
3
|
|
3
4
|
[![Gem](https://img.shields.io/gem/v/howzit.svg)](https://rubygems.org/gems/howzit)
|
@@ -8,8 +9,6 @@ A command-line reference tool for tracking project build systems
|
|
8
9
|
|
9
10
|
Howzit is a tool that allows you to keep Markdown-formatted notes about a project's tools and procedures. It functions as an easy lookup for notes about a particular task, as well as a task runner to automatically execute appropriate commands.
|
10
11
|
|
11
|
-
<!--README-->
|
12
|
-
|
13
12
|
## Features
|
14
13
|
|
15
14
|
- Match topic titles with any portion of title
|
@@ -55,8 +54,6 @@ If you run into permission errors using the above command, you'll need to use `g
|
|
55
54
|
|
56
55
|
This project is licensed under the MIT License - see the [LICENSE.txt](LICENSE.txt) file for details.
|
57
56
|
|
58
|
-
<!--END README-->
|
59
|
-
|
60
57
|
## Warranty
|
61
58
|
|
62
59
|
This software is provided "as is" and without any express or
|
@@ -74,6 +71,7 @@ purpose.
|
|
74
71
|
[RubyDoc]: http://www.rubydoc.info/gems/howzit
|
75
72
|
[Omniref]: https://www.omniref.com/ruby/gems/howzit
|
76
73
|
|
74
|
+
|
77
75
|
## Development and Testing
|
78
76
|
|
79
77
|
### Source Code
|
@@ -143,3 +141,4 @@ To submit a patch:
|
|
143
141
|
5. Push to the branch (`git push origin my-new-feature`).
|
144
142
|
6. Create a new Pull Request.
|
145
143
|
|
144
|
+
|
data/Rakefile
CHANGED
@@ -76,4 +76,35 @@ task :dockertest, :version, :login do |_, args|
|
|
76
76
|
# puts commit&.empty? ? "Error commiting Docker tag #{img}" : "Committed Docker tag #{img}"
|
77
77
|
end
|
78
78
|
|
79
|
+
desc 'Alias for build'
|
79
80
|
task package: :build
|
81
|
+
|
82
|
+
desc 'Bump incremental version number'
|
83
|
+
task :bump, :type do |_, args|
|
84
|
+
args.with_defaults(type: 'inc')
|
85
|
+
version_file = 'lib/howzit/version.rb'
|
86
|
+
content = IO.read(version_file)
|
87
|
+
content.sub!(/VERSION = '(?<major>\d+)\.(?<minor>\d+)\.(?<inc>\d+)(?<pre>\S+)?'/) do
|
88
|
+
m = Regexp.last_match
|
89
|
+
major = m['major'].to_i
|
90
|
+
minor = m['minor'].to_i
|
91
|
+
inc = m['inc'].to_i
|
92
|
+
pre = m['pre']
|
93
|
+
|
94
|
+
case args[:type]
|
95
|
+
when /^maj/
|
96
|
+
major += 1
|
97
|
+
minor = 0
|
98
|
+
inc = 0
|
99
|
+
when /^min/
|
100
|
+
minor += 1
|
101
|
+
inc = 0
|
102
|
+
else
|
103
|
+
inc += 1
|
104
|
+
end
|
105
|
+
|
106
|
+
$stdout.puts "At version #{major}.#{minor}.#{inc}#{pre}"
|
107
|
+
"VERSION = '#{major}.#{minor}.#{inc}#{pre}'"
|
108
|
+
end
|
109
|
+
File.open(version_file, 'w+') { |f| f.puts content }
|
110
|
+
end
|
data/lib/howzit/buildnote.rb
CHANGED
@@ -69,6 +69,7 @@ module Howzit
|
|
69
69
|
##
|
70
70
|
def find_topic(term = nil)
|
71
71
|
return @topics if term.nil?
|
72
|
+
|
72
73
|
@topics.filter do |topic|
|
73
74
|
rx = term.to_rx
|
74
75
|
topic.title.downcase.sub(/ *\(.*?\) *$/, '') =~ rx
|
@@ -114,7 +115,7 @@ module Howzit
|
|
114
115
|
## @return [Array] array of topic titles
|
115
116
|
##
|
116
117
|
def list_topics
|
117
|
-
@topics.map
|
118
|
+
@topics.map(&:title)
|
118
119
|
end
|
119
120
|
|
120
121
|
##
|
@@ -360,19 +361,21 @@ module Howzit
|
|
360
361
|
##
|
361
362
|
def ensure_requirements(template)
|
362
363
|
t_leader = Util.read_file(template).split(/^#/)[0].strip
|
363
|
-
|
364
|
-
|
365
|
-
|
366
|
-
|
367
|
-
|
368
|
-
|
369
|
-
|
370
|
-
|
371
|
-
|
372
|
-
|
373
|
-
|
374
|
-
|
375
|
-
|
364
|
+
return unless t_leader.length.positive?
|
365
|
+
|
366
|
+
t_meta = t_leader.get_metadata
|
367
|
+
|
368
|
+
return unless t_meta.key?('required')
|
369
|
+
|
370
|
+
required = t_meta['required'].strip.split(/\s*,\s*/)
|
371
|
+
required.each do |req|
|
372
|
+
next if @metadata.keys.include?(req.downcase)
|
373
|
+
|
374
|
+
Howzit.console.error %({bRw}ERROR:{xbr} Missing required metadata key from template '{bw}#{File.basename(
|
375
|
+
template, '.md'
|
376
|
+
)}{xr}'{x}).c
|
377
|
+
Howzit.console.error %({br}Please define {by}#{req.downcase}{xr} in build notes{x}).c
|
378
|
+
Process.exit 1
|
376
379
|
end
|
377
380
|
end
|
378
381
|
|
@@ -388,7 +391,7 @@ module Howzit
|
|
388
391
|
subtopics = nil
|
389
392
|
|
390
393
|
if template =~ /\[(.*?)\]$/
|
391
|
-
subtopics = Regexp.last_match[1].split(/\s*\|\s*/).map { |t| t.gsub(/\*/, '.*?')}
|
394
|
+
subtopics = Regexp.last_match[1].split(/\s*\|\s*/).map { |t| t.gsub(/\*/, '.*?') }
|
392
395
|
template.sub!(/\[.*?\]$/, '').strip
|
393
396
|
end
|
394
397
|
|
@@ -640,11 +643,10 @@ module Howzit
|
|
640
643
|
Howzit.has_read_upstream = true
|
641
644
|
end
|
642
645
|
|
643
|
-
|
644
|
-
Howzit.console.error("{br}Note file found but no topics detected in #{note_file}{x}".c)
|
645
|
-
Process.exit 1
|
646
|
-
end
|
646
|
+
return unless note_file && @topics.empty?
|
647
647
|
|
648
|
+
Howzit.console.error("{br}Note file found but no topics detected in #{note_file}{x}".c)
|
649
|
+
Process.exit 1
|
648
650
|
end
|
649
651
|
|
650
652
|
##
|
@@ -704,7 +706,7 @@ module Howzit
|
|
704
706
|
new_topic.print_out({ single: single })
|
705
707
|
end
|
706
708
|
|
707
|
-
output.nil? ? '' : output.join("\n")
|
709
|
+
output.nil? ? '' : output.join("\n\n")
|
708
710
|
end
|
709
711
|
|
710
712
|
##
|
@@ -782,7 +784,7 @@ module Howzit
|
|
782
784
|
when :all
|
783
785
|
topic_matches.concat(matches)
|
784
786
|
else
|
785
|
-
titles = matches.map
|
787
|
+
titles = matches.map(&:title)
|
786
788
|
res = Prompt.choose(titles)
|
787
789
|
old_matching = Howzit.options[:matching]
|
788
790
|
Howzit.options[:matching] = 'exact'
|
data/lib/howzit/colors.rb
CHANGED
@@ -5,7 +5,7 @@ module Howzit
|
|
5
5
|
# Terminal output color functions.
|
6
6
|
module Color
|
7
7
|
# Regexp to match excape sequences
|
8
|
-
ESCAPE_REGEX = /(?<=\[)(?:(?:(?:[349]|10)[0-9]|[0-9])?;?)+(?=m)
|
8
|
+
ESCAPE_REGEX = /(?<=\[)(?:(?:(?:[349]|10)[0-9]|[0-9])?;?)+(?=m)/
|
9
9
|
|
10
10
|
# All available color names. Available as methods and string extensions.
|
11
11
|
#
|
@@ -113,7 +113,9 @@ module Howzit
|
|
113
113
|
compiled = ''
|
114
114
|
normalize_color.split('').each do |char|
|
115
115
|
compiled += char
|
116
|
-
|
116
|
+
if Color.attributes.include?(compiled.to_sym) || compiled =~ /^([fb]g?)?#([a-f0-9]{6})$/i
|
117
|
+
valid_color = compiled
|
118
|
+
end
|
117
119
|
end
|
118
120
|
|
119
121
|
valid_color
|
@@ -271,7 +273,12 @@ module Howzit
|
|
271
273
|
input = input.join(' ') if input.is_a? Array
|
272
274
|
fmt = input.gsub(/%/, '%%')
|
273
275
|
fmt = fmt.gsub(/(?<!\\u|\$)\{(\w+)\}/i) do
|
274
|
-
Regexp.last_match(1)
|
276
|
+
m = Regexp.last_match(1)
|
277
|
+
if m =~ /^[wkglycmrWKGLYCMRdbuix]+$/
|
278
|
+
m.split('').map { |c| "%<#{c}>s" }.join('')
|
279
|
+
else
|
280
|
+
Regexp.last_match(0)
|
281
|
+
end
|
275
282
|
end
|
276
283
|
|
277
284
|
colors = { w: white, k: black, g: green, l: blue,
|
@@ -333,9 +340,28 @@ module Howzit
|
|
333
340
|
module_eval(new_method)
|
334
341
|
end
|
335
342
|
|
343
|
+
##
|
344
|
+
## Generate escape codes for hex colors
|
345
|
+
##
|
346
|
+
## @param hex [String] The hexadecimal color code
|
347
|
+
##
|
348
|
+
## @return [String] ANSI escape string
|
349
|
+
##
|
350
|
+
def rgb(hex)
|
351
|
+
is_bg = hex.match(/^bg?#/) ? true : false
|
352
|
+
hex_string = hex.sub(/^([fb]g?)?#/, '')
|
353
|
+
|
354
|
+
parts = hex_string.match(/(?<r>..)(?<g>..)(?<b>..)/)
|
355
|
+
t = []
|
356
|
+
%w[r g b].each do |e|
|
357
|
+
t << parts[e].hex
|
358
|
+
end
|
359
|
+
"\e[#{is_bg ? '48' : '38'};2;#{t.join(';')}m"
|
360
|
+
end
|
361
|
+
|
336
362
|
# Regular expression that is used to scan for ANSI-sequences while
|
337
363
|
# uncoloring strings.
|
338
|
-
COLORED_REGEXP = /\e\[(?:(?:[349]|10)[0-7]|[0-9])?m
|
364
|
+
COLORED_REGEXP = /\e\[(?:(?:[349]|10)[0-7]|[0-9])?m/
|
339
365
|
|
340
366
|
# Returns an uncolored version of the string, that is all
|
341
367
|
# ANSI-sequences are stripped from the string.
|
data/lib/howzit/config.rb
CHANGED
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module Howzit
|
2
4
|
# Config Class
|
3
5
|
class Config
|
@@ -95,7 +97,7 @@ module Howzit
|
|
95
97
|
def should_ignore(filename)
|
96
98
|
return false unless File.exist?(ignore_file)
|
97
99
|
|
98
|
-
@ignore_patterns ||= YAML.
|
100
|
+
@ignore_patterns ||= YAML.load(Util.read_file(ignore_file))
|
99
101
|
|
100
102
|
ignore = false
|
101
103
|
|
data/lib/howzit/prompt.rb
CHANGED
data/lib/howzit/stringutils.rb
CHANGED
@@ -103,7 +103,7 @@ module Howzit
|
|
103
103
|
|
104
104
|
# Just strip out color codes when requested
|
105
105
|
def uncolor
|
106
|
-
gsub(/\e\[[\d;]+m/, '').gsub(/\e\]1337;SetMark/,'')
|
106
|
+
gsub(/\e\[[\d;]+m/, '').gsub(/\e\]1337;SetMark/, '')
|
107
107
|
end
|
108
108
|
|
109
109
|
# Wrap text at a specified width.
|
@@ -277,7 +277,7 @@ module Howzit
|
|
277
277
|
def extract_metadata
|
278
278
|
if File.exist?(self)
|
279
279
|
leader = Util.read_file(self).split(/^#/)[0].strip
|
280
|
-
leader.length
|
280
|
+
leader.length.positive? ? leader.get_metadata : {}
|
281
281
|
else
|
282
282
|
{}
|
283
283
|
end
|
@@ -361,11 +361,11 @@ module Howzit
|
|
361
361
|
|
362
362
|
case Howzit.options[:header_format]
|
363
363
|
when :block
|
364
|
-
Color.template("#{options[:color]}\u{258C}#{title}#{should_mark_iterm? && options[:mark] ? iterm_marker : ''}{x}")
|
364
|
+
Color.template("\n\n#{options[:color]}\u{258C}#{title}#{should_mark_iterm? && options[:mark] ? iterm_marker : ''}{x}")
|
365
365
|
else
|
366
366
|
cols = TTY::Screen.columns
|
367
367
|
|
368
|
-
cols = Howzit.options[:wrap] if
|
368
|
+
cols = Howzit.options[:wrap] if Howzit.options[:wrap].positive? && cols > Howzit.options[:wrap]
|
369
369
|
title = Color.template("#{options[:border]}#{options[:hr] * 2}( #{options[:color]}#{title}#{options[:border]} )")
|
370
370
|
|
371
371
|
tail = if should_mark_iterm?
|
@@ -373,7 +373,7 @@ module Howzit
|
|
373
373
|
else
|
374
374
|
options[:hr] * (cols - title.uncolor.length)
|
375
375
|
end
|
376
|
-
Color.template("#{title}#{tail}{x}")
|
376
|
+
Color.template("\n\n#{title}#{tail}{x}")
|
377
377
|
end
|
378
378
|
end
|
379
379
|
end
|
data/lib/howzit/task.rb
CHANGED
@@ -39,7 +39,7 @@ module Howzit
|
|
39
39
|
## @return [String] description
|
40
40
|
##
|
41
41
|
def inspect
|
42
|
-
%(<#Howzit::Task @type=:#{@type} @title="#{@title}" @arguments=#{@arguments} @block?=#{@action.split(/\n/).count > 1}>)
|
42
|
+
%(<#Howzit::Task @type=:#{@type} @title="#{@title}" @action="#{@action}" @arguments=#{@arguments} @block?=#{@action.split(/\n/).count > 1}>)
|
43
43
|
end
|
44
44
|
|
45
45
|
##
|
@@ -95,7 +95,8 @@ module Howzit
|
|
95
95
|
def run_run
|
96
96
|
title = Howzit.options[:show_all_code] ? @action : @title
|
97
97
|
Howzit.console.info("#{@prefix}{bg}Running {bw}#{title}{x}".c)
|
98
|
-
|
98
|
+
ENV['HOWZIT_SCRIPTS'] = File.expand_path('~/.config/howzit/scripts')
|
99
|
+
system(@action)
|
99
100
|
end
|
100
101
|
|
101
102
|
##
|
@@ -105,7 +106,7 @@ module Howzit
|
|
105
106
|
title = Howzit.options[:show_all_code] ? @action : @title
|
106
107
|
Howzit.console.info("#{@prefix}{bg}Copied {bw}#{title}{bg} to clipboard{x}".c)
|
107
108
|
Util.os_copy(@action)
|
108
|
-
|
109
|
+
true
|
109
110
|
end
|
110
111
|
|
111
112
|
##
|
data/lib/howzit/topic.rb
CHANGED
@@ -56,15 +56,28 @@ module Howzit
|
|
56
56
|
@title =~ /#{term}/i || @content =~ /#{term}/i
|
57
57
|
end
|
58
58
|
|
59
|
+
def ask_task(task)
|
60
|
+
note = if task.type == :include
|
61
|
+
task_count = Howzit.buildnote.find_topic(task.action)[0].tasks.count
|
62
|
+
" (#{task_count} tasks)"
|
63
|
+
else
|
64
|
+
''
|
65
|
+
end
|
66
|
+
q = %({bg}#{task.type.to_s.capitalize} {xw}"{bw}#{task.title}{xw}"#{note}{x}).c
|
67
|
+
Prompt.yn(q, default: task.default)
|
68
|
+
end
|
69
|
+
|
70
|
+
def check_cols
|
71
|
+
TTY::Screen.columns > 60 ? 60 : TTY::Screen.columns
|
72
|
+
rescue StandardError
|
73
|
+
60
|
74
|
+
end
|
75
|
+
|
59
76
|
# Handle run command, execute directives in topic
|
60
77
|
def run(nested: false)
|
61
78
|
output = []
|
62
79
|
|
63
|
-
cols =
|
64
|
-
TTY::Screen.columns > 60 ? 60 : TTY::Screen.columns
|
65
|
-
rescue StandardError
|
66
|
-
60
|
67
|
-
end
|
80
|
+
cols = check_cols
|
68
81
|
|
69
82
|
if @tasks.count.positive?
|
70
83
|
unless @prereqs.empty?
|
@@ -75,18 +88,8 @@ module Howzit
|
|
75
88
|
end
|
76
89
|
|
77
90
|
@tasks.each do |task|
|
78
|
-
if task.optional || Howzit.options[:ask]
|
79
|
-
note = if task.type == :include
|
80
|
-
task_count = Howzit.buildnote.find_topic(task.action)[0].tasks.count
|
81
|
-
" (#{task_count} tasks)"
|
82
|
-
else
|
83
|
-
''
|
84
|
-
end
|
85
|
-
q = %({bg}#{task.type.to_s.capitalize} {xw}"{bw}#{task.title}{xw}"#{note}{x}).c
|
86
|
-
res = Prompt.yn(q, default: task.default)
|
87
|
-
next unless res
|
91
|
+
next if (task.optional || Howzit.options[:ask]) && !ask_task(task)
|
88
92
|
|
89
|
-
end
|
90
93
|
run_output, total, success = task.run
|
91
94
|
|
92
95
|
output.concat(run_output)
|
@@ -123,6 +126,116 @@ module Howzit
|
|
123
126
|
output
|
124
127
|
end
|
125
128
|
|
129
|
+
def title_option(color, topic, keys, opt)
|
130
|
+
option = colored_option(color, topic, keys)
|
131
|
+
"#{opt[:single] ? 'From' : 'Include'} #{topic.title}#{option}:"
|
132
|
+
end
|
133
|
+
|
134
|
+
def colored_option(color, topic, keys)
|
135
|
+
if topic.tasks.empty?
|
136
|
+
''
|
137
|
+
else
|
138
|
+
optional = keys[:optional] =~ /[?!]+/ ? true : false
|
139
|
+
default = keys[:optional] =~ /!/ ? false : true
|
140
|
+
if optional
|
141
|
+
colored_yn(color, default)
|
142
|
+
else
|
143
|
+
''
|
144
|
+
end
|
145
|
+
end
|
146
|
+
end
|
147
|
+
|
148
|
+
def colored_yn(color, default)
|
149
|
+
if default
|
150
|
+
" {xKk}[{gbK}Y{xKk}/{dbwK}n{xKk}]{x}#{color}".c
|
151
|
+
else
|
152
|
+
" {xKk}[{dbwK}y{xKk}/{bgK}N{xKk}]{x}#{color}".c
|
153
|
+
end
|
154
|
+
end
|
155
|
+
|
156
|
+
##
|
157
|
+
## Handle an include statement
|
158
|
+
##
|
159
|
+
## @param keys [Hash] The symbolized keys and values from the regex
|
160
|
+
## that found the statement
|
161
|
+
## @param opt [Hash] Options
|
162
|
+
##
|
163
|
+
def process_include(keys, opt)
|
164
|
+
output = []
|
165
|
+
|
166
|
+
if keys[:action] =~ / *\[(.*?)\] *$/
|
167
|
+
Howzit.named_arguments = @named_args
|
168
|
+
Howzit.arguments = Regexp.last_match(1).split(/ *, */).map!(&:render_arguments)
|
169
|
+
end
|
170
|
+
|
171
|
+
matches = Howzit.buildnote.find_topic(keys[:action].sub(/ *\[.*?\] *$/, ''))
|
172
|
+
|
173
|
+
return [] if matches.empty?
|
174
|
+
|
175
|
+
topic = matches[0]
|
176
|
+
|
177
|
+
rule = '{kKd}'
|
178
|
+
color = '{Kyd}'
|
179
|
+
title = title_option(color, topic, keys, opt)
|
180
|
+
options = { color: color, hr: '.', border: rule }
|
181
|
+
|
182
|
+
output.push("#{'> ' * @nest_level}#{title}".format_header(options)) unless Howzit.inclusions.include?(topic)
|
183
|
+
|
184
|
+
if opt[:single] && Howzit.inclusions.include?(topic)
|
185
|
+
output.push("#{'> ' * @nest_level}#{title} included above".format_header(options))
|
186
|
+
elsif opt[:single]
|
187
|
+
@nest_level += 1
|
188
|
+
|
189
|
+
output.concat(topic.print_out({ single: true, header: false }))
|
190
|
+
output.push("#{'> ' * @nest_level}...".format_header(options))
|
191
|
+
@nest_level -= 1
|
192
|
+
end
|
193
|
+
Howzit.inclusions.push(topic)
|
194
|
+
|
195
|
+
output
|
196
|
+
end
|
197
|
+
|
198
|
+
def color_directive_yn(keys)
|
199
|
+
optional, default = define_optional(keys[:optional])
|
200
|
+
if optional
|
201
|
+
default ? ' {xk}[{g}Y{xk}/{dbw}n{xk}]{x}'.c : ' {xk}[{dbw}y{xk}/{g}N{xk}]{x}'.c
|
202
|
+
else
|
203
|
+
''
|
204
|
+
end
|
205
|
+
end
|
206
|
+
|
207
|
+
def process_directive(keys)
|
208
|
+
cmd = keys[:cmd]
|
209
|
+
obj = keys[:action]
|
210
|
+
title = keys[:title].empty? ? obj : keys[:title].strip
|
211
|
+
title = Howzit.options[:show_all_code] ? obj : title
|
212
|
+
option = color_directive_yn(keys)
|
213
|
+
icon = case cmd
|
214
|
+
when 'run'
|
215
|
+
"\u{25B6}"
|
216
|
+
when 'copy'
|
217
|
+
"\u{271A}"
|
218
|
+
when /open|url/
|
219
|
+
"\u{279A}"
|
220
|
+
end
|
221
|
+
|
222
|
+
"{bmK}#{icon} {bwK}#{title.preserve_escapes}{x}#{option}".c
|
223
|
+
end
|
224
|
+
|
225
|
+
def define_optional(optional)
|
226
|
+
is_optional = optional =~ /[?!]+/ ? true : false
|
227
|
+
default = optional =~ /!/ ? false : true
|
228
|
+
[is_optional, default]
|
229
|
+
end
|
230
|
+
|
231
|
+
def title_code_block(keys)
|
232
|
+
if keys[:title].length.positive?
|
233
|
+
"Block: #{keys[:title]}#{color_directive_yn(keys)}"
|
234
|
+
else
|
235
|
+
"Code Block#{color_directive_yn(keys)}"
|
236
|
+
end
|
237
|
+
end
|
238
|
+
|
126
239
|
# Output a topic with fancy title and bright white text.
|
127
240
|
#
|
128
241
|
# @param options [Hash] The options
|
@@ -139,99 +252,23 @@ module Howzit
|
|
139
252
|
output.push('')
|
140
253
|
end
|
141
254
|
topic = @content.dup
|
142
|
-
|
255
|
+
unless Howzit.options[:show_all_code]
|
256
|
+
topic.gsub!(/(?mix)^(`{3,})run([?!]*)\s*
|
257
|
+
([^\n]*)[\s\S]*?\n\1\s*$/, '@@@run\2 \3')
|
258
|
+
end
|
143
259
|
topic.split(/\n/).each do |l|
|
144
260
|
case l
|
145
261
|
when /@(before|after|prereq|end)/
|
146
262
|
next
|
147
|
-
when /@include(?<optional>[!?]{1,2})?\((?<action>[
|
148
|
-
|
149
|
-
|
150
|
-
if m[:action] =~ / *\[(.*?)\] *$/
|
151
|
-
Howzit.named_arguments = @named_args
|
152
|
-
Howzit.arguments = Regexp.last_match(1).split(/ *, */).map!(&:render_arguments)
|
153
|
-
end
|
154
|
-
|
155
|
-
matches = Howzit.buildnote.find_topic(m[:action].sub(/ *\[.*?\] *$/, ''))
|
156
|
-
|
157
|
-
unless matches.empty?
|
158
|
-
i_topic = matches[0]
|
159
|
-
|
160
|
-
rule = '{kKd}'
|
161
|
-
color = '{Kyd}'
|
162
|
-
option = if i_topic.tasks.empty?
|
163
|
-
''
|
164
|
-
else
|
165
|
-
optional = m[:optional] =~ /[?!]+/ ? true : false
|
166
|
-
default = m[:optional] =~ /!/ ? false : true
|
167
|
-
if optional
|
168
|
-
default ? " {xKk}[{gbK}Y{xKk}/{dbwK}n{xKk}]{x}#{color}".c : " {xKk}[{dbwK}y{xKk}/{bgK}N{xKk}]{x}#{color}".c
|
169
|
-
else
|
170
|
-
''
|
171
|
-
end
|
172
|
-
end
|
173
|
-
title = "#{opt[:single] ? 'From' : 'Include'} #{i_topic.title}#{option}:"
|
174
|
-
options = { color: color, hr: '.', border: rule }
|
175
|
-
unless Howzit.inclusions.include?(i_topic)
|
176
|
-
output.push("#{'> ' * @nest_level}#{title}".format_header(options))
|
177
|
-
end
|
178
|
-
|
179
|
-
if opt[:single] && Howzit.inclusions.include?(i_topic)
|
180
|
-
output.push("#{'> ' * @nest_level}#{title} included above".format_header(options))
|
181
|
-
elsif opt[:single]
|
182
|
-
@nest_level += 1
|
183
|
-
|
184
|
-
output.concat(i_topic.print_out({ single: true, header: false }))
|
185
|
-
output.push("#{'> ' * @nest_level}...".format_header(options))
|
186
|
-
@nest_level -= 1
|
187
|
-
end
|
188
|
-
Howzit.inclusions.push(i_topic)
|
189
|
-
end
|
263
|
+
when /@include(?<optional>[!?]{1,2})?\((?<action>[^)]+)\)/
|
264
|
+
output.concat(process_include(Regexp.last_match.named_captures.symbolize_keys, opt))
|
190
265
|
when /@(?<cmd>run|copy|open|url)(?<optional>[?!]{1,2})?\((?<action>.*?)\) *(?<title>.*?)$/
|
191
|
-
|
192
|
-
cmd = m[:cmd]
|
193
|
-
obj = m[:action]
|
194
|
-
title = m[:title].empty? ? obj : m[:title].strip
|
195
|
-
title = Howzit.options[:show_all_code] ? obj : title
|
196
|
-
optional = m[:optional] =~ /[?!]+/ ? true : false
|
197
|
-
default = m[:optional] =~ /!/ ? false : true
|
198
|
-
option = if optional
|
199
|
-
default ? ' {xk}[{g}Y{xk}/{dbw}n{xk}]{x}'.c : ' {xk}[{dbw}y{xk}/{g}N{xk}]{x}'.c
|
200
|
-
else
|
201
|
-
''
|
202
|
-
end
|
203
|
-
icon = case cmd
|
204
|
-
when 'run'
|
205
|
-
"\u{25B6}"
|
206
|
-
when 'copy'
|
207
|
-
"\u{271A}"
|
208
|
-
when /open|url/
|
209
|
-
"\u{279A}"
|
210
|
-
end
|
211
|
-
|
212
|
-
output.push("{bmK}#{icon} {bwK}#{title.preserve_escapes}{x}#{option}".c)
|
266
|
+
output.push(process_directive(Regexp.last_match.named_captures.symbolize_keys))
|
213
267
|
when /(?<fence>`{3,})run(?<optional>[!?]{1,2})? *(?<title>.*?)$/i
|
214
|
-
|
215
|
-
optional = m[:optional] =~ /[?!]+/ ? true : false
|
216
|
-
default = m[:optional] =~ /!/ ? false : true
|
217
|
-
option = if optional
|
218
|
-
default ? ' {xk}[{g}Y{xk}/{dbw}n{xk}]{x}'.c : ' {xk}[{dbw}y{xk}/{g}N{xk}]{x}'.c
|
219
|
-
else
|
220
|
-
''
|
221
|
-
end
|
222
|
-
desc = m[:title].length.positive? ? "Block: #{m[:title]}#{option}" : "Code Block#{option}"
|
268
|
+
desc = title_code_block(Regexp.last_match.named_captures.symbolize_keys)
|
223
269
|
output.push("{bmK}\u{25B6} {bwK}#{desc}{x}\n```".c)
|
224
270
|
when /@@@run(?<optional>[!?]{1,2})? *(?<title>.*?)$/i
|
225
|
-
|
226
|
-
optional = m[:optional] =~ /[?!]+/ ? true : false
|
227
|
-
default = m[:optional] =~ /!/ ? false : true
|
228
|
-
option = if optional
|
229
|
-
default ? ' {xk}[{g}Y{xk}/{dbw}n{xk}]{x}'.c : ' {xk}[{dbw}y{xk}/{g}N{xk}]{x}'.c
|
230
|
-
else
|
231
|
-
''
|
232
|
-
end
|
233
|
-
desc = m[:title].length.positive? ? "Block: #{m[:title]}#{option}" : "Code Block#{option}"
|
234
|
-
output.push("{bmK}\u{25B6} {bwK}#{desc}{x}".c)
|
271
|
+
output.push("{bmK}\u{25B6} {bwK}#{title_code_block(Regexp.last_match.named_captures.symbolize_keys)}{x}".c)
|
235
272
|
else
|
236
273
|
l.wrap!(Howzit.options[:wrap]) if Howzit.options[:wrap].positive?
|
237
274
|
output.push(l)
|
@@ -241,6 +278,45 @@ module Howzit
|
|
241
278
|
output.push('').map(&:render_arguments)
|
242
279
|
end
|
243
280
|
|
281
|
+
include Comparable
|
282
|
+
def <=>(other)
|
283
|
+
@title <=> other.title
|
284
|
+
end
|
285
|
+
|
286
|
+
def define_task_args(keys)
|
287
|
+
cmd = keys[:cmd]
|
288
|
+
obj = keys[:action]
|
289
|
+
title = keys[:title].nil? ? obj : keys[:title].strip
|
290
|
+
title = Howzit.options[:show_all_code] ? obj : title
|
291
|
+
task_args = { type: :include,
|
292
|
+
arguments: nil,
|
293
|
+
title: title,
|
294
|
+
action: obj,
|
295
|
+
parent: self }
|
296
|
+
case cmd
|
297
|
+
when /include/i
|
298
|
+
if title =~ /\[(.*?)\] *$/
|
299
|
+
Howzit.named_arguments = @named_args
|
300
|
+
args = Regexp.last_match(1).split(/ *, */).map(&:render_arguments)
|
301
|
+
Howzit.arguments = args
|
302
|
+
arguments
|
303
|
+
title.sub!(/ *\[.*?\] *$/, '')
|
304
|
+
end
|
305
|
+
|
306
|
+
task_args[:type] = :include
|
307
|
+
task_args[:arguments] = Howzit.named_arguments
|
308
|
+
when /run/i
|
309
|
+
task_args[:type] = :run
|
310
|
+
when /copy/i
|
311
|
+
task_args[:type] = :copy
|
312
|
+
task_args[:action] = Shellwords.escape(obj)
|
313
|
+
when /open|url/i
|
314
|
+
task_args[:type] = :open
|
315
|
+
end
|
316
|
+
|
317
|
+
task_args
|
318
|
+
end
|
319
|
+
|
244
320
|
private
|
245
321
|
|
246
322
|
##
|
@@ -264,8 +340,7 @@ module Howzit
|
|
264
340
|
Howzit.named_arguments = @named_args
|
265
341
|
|
266
342
|
if c[:cmd].nil?
|
267
|
-
optional = c[:optional2]
|
268
|
-
default = c[:optional2] =~ /!/ ? false : true
|
343
|
+
optional, default = define_optional(c[:optional2])
|
269
344
|
title = c[:title2].nil? ? '' : c[:title2].strip
|
270
345
|
block = c[:block]&.strip
|
271
346
|
runnable << Howzit::Task.new({ type: :block,
|
@@ -275,63 +350,10 @@ module Howzit
|
|
275
350
|
optional: optional,
|
276
351
|
default: default)
|
277
352
|
else
|
278
|
-
|
279
|
-
|
280
|
-
|
281
|
-
|
282
|
-
title = c[:title].nil? ? obj : c[:title].strip
|
283
|
-
title = Howzit.options[:show_all_code] ? obj : title
|
284
|
-
case cmd
|
285
|
-
when /include/i
|
286
|
-
# matches = Howzit.buildnote.find_topic(obj)
|
287
|
-
# unless matches.empty? || Howzit.inclusions.include?(matches[0].title)
|
288
|
-
# tasks = matches[0].tasks.map do |inc|
|
289
|
-
# Howzit.inclusions.push(matches[0].title)
|
290
|
-
# inc.parent = matches[0]
|
291
|
-
# inc
|
292
|
-
# end
|
293
|
-
# runnable.concat(tasks)
|
294
|
-
# end
|
295
|
-
args = []
|
296
|
-
if title =~ /\[(.*?)\] *$/
|
297
|
-
Howzit.named_arguments = @named_args
|
298
|
-
args = Regexp.last_match(1).split(/ *, */).map(&:render_arguments)
|
299
|
-
Howzit.arguments = args
|
300
|
-
arguments
|
301
|
-
title.sub!(/ *\[.*?\] *$/, '')
|
302
|
-
end
|
303
|
-
|
304
|
-
runnable << Howzit::Task.new({ type: :include,
|
305
|
-
arguments: Howzit.named_arguments,
|
306
|
-
title: title,
|
307
|
-
action: obj,
|
308
|
-
parent: self },
|
309
|
-
optional: optional,
|
310
|
-
default: default)
|
311
|
-
when /run/i
|
312
|
-
# warn "{bg}Running {bw}#{obj}{x}".c if Howzit.options[:log_level] < 2
|
313
|
-
runnable << Howzit::Task.new({ type: :run,
|
314
|
-
title: title,
|
315
|
-
action: obj,
|
316
|
-
parent: self },
|
317
|
-
optional: optional,
|
318
|
-
default: default)
|
319
|
-
when /copy/i
|
320
|
-
# warn "{bg}Copied {bw}#{obj}{bg} to clipboard{x}".c if Howzit.options[:log_level] < 2
|
321
|
-
runnable << Howzit::Task.new({ type: :copy,
|
322
|
-
title: title,
|
323
|
-
action: Shellwords.escape(obj),
|
324
|
-
parent: self },
|
325
|
-
optional: optional,
|
326
|
-
default: default)
|
327
|
-
when /open|url/i
|
328
|
-
runnable << Howzit::Task.new({ type: :open,
|
329
|
-
title: title,
|
330
|
-
action: obj,
|
331
|
-
parent: self },
|
332
|
-
optional: optional,
|
333
|
-
default: default)
|
334
|
-
end
|
353
|
+
optional, default = define_optional(c[:optional])
|
354
|
+
runnable << Howzit::Task.new(define_task_args(c),
|
355
|
+
optional: optional,
|
356
|
+
default: default)
|
335
357
|
end
|
336
358
|
end
|
337
359
|
|
data/lib/howzit/util.rb
CHANGED
@@ -210,6 +210,33 @@ module Howzit
|
|
210
210
|
end
|
211
211
|
end
|
212
212
|
|
213
|
+
##
|
214
|
+
## Platform-agnostic paste-from-clipboard
|
215
|
+
##
|
216
|
+
def os_paste
|
217
|
+
os = RbConfig::CONFIG['target_os']
|
218
|
+
out = "{bg}Pasting from clipboard".c
|
219
|
+
case os
|
220
|
+
when /darwin.*/i
|
221
|
+
Howzit.console.debug("#{out} (macOS){x}".c)
|
222
|
+
`pbpaste`
|
223
|
+
when /mingw|mswin/i
|
224
|
+
Howzit.console.debug("#{out} (Windows){x}".c)
|
225
|
+
`cat /dev/clipboard`
|
226
|
+
else
|
227
|
+
if 'xsel'.available?
|
228
|
+
Howzit.console.debug("#{out} (Linux, xsel){x}".c)
|
229
|
+
`xsel --clipboard --output`
|
230
|
+
elsif 'xclip'.available?
|
231
|
+
Howzit.console.debug("#{out} (Linux, xclip){x}".c)
|
232
|
+
`xclip -selection clipboard -o`
|
233
|
+
else
|
234
|
+
Howzit.console.debug(out)
|
235
|
+
Howzit.console.warn('Unable to determine executable for clipboard.')
|
236
|
+
end
|
237
|
+
end
|
238
|
+
end
|
239
|
+
|
213
240
|
##
|
214
241
|
## Platform-agnostic open command
|
215
242
|
##
|
data/lib/howzit/version.rb
CHANGED
data/lib/howzit.rb
CHANGED
@@ -50,6 +50,7 @@ require 'tty/box'
|
|
50
50
|
module Howzit
|
51
51
|
class << self
|
52
52
|
attr_accessor :arguments, :named_arguments, :cli_args
|
53
|
+
|
53
54
|
##
|
54
55
|
## Holds a Configuration object with methods and a @settings hash
|
55
56
|
##
|
@@ -91,8 +92,6 @@ module Howzit
|
|
91
92
|
@has_read_upstream ||= false
|
92
93
|
end
|
93
94
|
|
94
|
-
|
95
|
-
@has_read_upstream = has_read
|
96
|
-
end
|
95
|
+
attr_writer :has_read_upstream
|
97
96
|
end
|
98
97
|
end
|
data/spec/topic_spec.rb
CHANGED
@@ -9,7 +9,7 @@ describe Howzit::Topic do
|
|
9
9
|
|
10
10
|
describe '.new' do
|
11
11
|
it 'makes a new topic instance' do
|
12
|
-
expect(topic).to be_a
|
12
|
+
expect(topic).to be_a described_class
|
13
13
|
end
|
14
14
|
it 'has the correct title' do
|
15
15
|
expect(topic.title).to eq title
|
@@ -51,9 +51,11 @@ describe Howzit::Topic do
|
|
51
51
|
it 'returns true for matching pattern in content' do
|
52
52
|
expect(topic.grep('prereq.*?ite')).to be_truthy
|
53
53
|
end
|
54
|
+
|
54
55
|
it 'returns true for matching pattern in title' do
|
55
56
|
expect(topic.grep('bal.*?na')).to be_truthy
|
56
57
|
end
|
58
|
+
|
57
59
|
it 'fails on bad pattern' do
|
58
60
|
expect(topic.grep('xxx+')).to_not be_truthy
|
59
61
|
end
|
@@ -61,10 +63,12 @@ describe Howzit::Topic do
|
|
61
63
|
|
62
64
|
describe '.run' do
|
63
65
|
Howzit.options[:default] = true
|
66
|
+
|
64
67
|
it 'shows prereq and postreq' do
|
65
68
|
expect { topic.run }.to output(/prerequisite/).to_stdout
|
66
69
|
expect { topic.run }.to output(/postrequisite/).to_stdout
|
67
70
|
end
|
71
|
+
|
68
72
|
it 'Copies to clipboard' do
|
69
73
|
expect {
|
70
74
|
ENV['RUBYOPT'] = '-W1'
|
@@ -77,15 +81,18 @@ describe Howzit::Topic do
|
|
77
81
|
describe '.print_out' do
|
78
82
|
Howzit.options[:header_format] = :block
|
79
83
|
Howzit.options[:color] = false
|
84
|
+
|
80
85
|
it 'prints the topic title' do
|
81
|
-
expect(topic.print_out({single: true, header: true}).join("\n").uncolor).to match(/▌Topic Balogna/)
|
86
|
+
expect(topic.print_out({ single: true, header: true }).join("\n").uncolor).to match(/▌Topic Balogna/)
|
82
87
|
end
|
88
|
+
|
83
89
|
it 'prints a task title' do
|
84
|
-
expect(topic.print_out({single: true, header: true}).join("\n").uncolor).to match(/▶ Null Output/)
|
90
|
+
expect(topic.print_out({ single: true, header: true }).join("\n").uncolor).to match(/▶ Null Output/)
|
85
91
|
end
|
92
|
+
|
86
93
|
it 'prints task action with --show-code' do
|
87
94
|
Howzit.options[:show_all_code] = true
|
88
|
-
expect(topic.print_out({single: true, header: true}).join("\n").uncolor).to match(/▶ ls -1/)
|
95
|
+
expect(topic.print_out({ single: true, header: true }).join("\n").uncolor).to match(/▶ ls -1/)
|
89
96
|
end
|
90
97
|
end
|
91
98
|
end
|
data/src/_README.md
ADDED
@@ -0,0 +1,145 @@
|
|
1
|
+
<!--README--><!--GITHUB-->
|
2
|
+
# Howzit
|
3
|
+
|
4
|
+
[![Gem](https://img.shields.io/gem/v/howzit.svg)](https://rubygems.org/gems/howzit)
|
5
|
+
[![Travis](https://api.travis-ci.com/ttscoff/howzit.svg?branch=main)](https://travis-ci.org/makenew/ruby-gem)
|
6
|
+
[![GitHub license](https://img.shields.io/github/license/ttscoff/howzit.svg)](./LICENSE.txt)
|
7
|
+
<!--END GITHUB-->
|
8
|
+
A command-line reference tool for tracking project build systems
|
9
|
+
|
10
|
+
Howzit is a tool that allows you to keep Markdown-formatted notes about a project's tools and procedures. It functions as an easy lookup for notes about a particular task, as well as a task runner to automatically execute appropriate commands.
|
11
|
+
|
12
|
+
## Features
|
13
|
+
|
14
|
+
- Match topic titles with any portion of title
|
15
|
+
- Automatic pagination of output, with optional Markdown highlighting
|
16
|
+
- Use `@run()`, `@copy()`, and `@open()` to perform actions within a build notes file
|
17
|
+
- Use `@include()` to import another topic's tasks
|
18
|
+
- Use fenced code blocks to include/run embedded scripts
|
19
|
+
- Sets iTerm 2 marks on topic titles for navigation when paging is disabled
|
20
|
+
- Inside of git repositories, howzit will work from subdirectories, assuming build notes are in top level of repo
|
21
|
+
- Templates for easily including repeat tasks
|
22
|
+
- Grep topics for pattern and choose from matches
|
23
|
+
- Use positional and named variables when executing tasks
|
24
|
+
|
25
|
+
## Getting Started
|
26
|
+
|
27
|
+
### Prerequisites
|
28
|
+
|
29
|
+
- Ruby 2.4+ (It probably works on older Rubys, but is untested prior to 2.4.1.)
|
30
|
+
- Optional: if [`fzf`](https://github.com/junegunn/fzf) is available, it will be used for handling multiple choice selections
|
31
|
+
- Optional: if [`bat`](https://github.com/sharkdp/bat) is available it will page with that
|
32
|
+
- Optional: [`mdless`](https://github.com/ttscoff/mdless) or [`mdcat`](https://github.com/lunaryorn/mdcat) for formatting output
|
33
|
+
|
34
|
+
### Installing
|
35
|
+
|
36
|
+
You can install `howzit` by running:
|
37
|
+
|
38
|
+
gem install howzit
|
39
|
+
|
40
|
+
If you run into permission errors using the above command, you'll need to use `gem install --user-install howzit`. If that fails, either use `sudo` (`sudo gem install howzit`) or if you're using Homebrew, you have the option to install via [brew-gem](https://github.com/sportngin/brew-gem):
|
41
|
+
|
42
|
+
brew install brew-gem
|
43
|
+
brew gem install howzit
|
44
|
+
|
45
|
+
### Usage
|
46
|
+
|
47
|
+
[See the wiki](https://github.com/ttscoff/howzit/wiki) for documentation.
|
48
|
+
|
49
|
+
## Author
|
50
|
+
|
51
|
+
**Brett Terpstra** - [brettterpstra.com](https://brettterpstra.com)
|
52
|
+
|
53
|
+
## License
|
54
|
+
|
55
|
+
This project is licensed under the MIT License - see the [LICENSE.txt](LICENSE.txt) file for details.
|
56
|
+
|
57
|
+
## Warranty
|
58
|
+
|
59
|
+
This software is provided "as is" and without any express or
|
60
|
+
implied warranties, including, without limitation, the implied
|
61
|
+
warranties of merchantibility and fitness for a particular
|
62
|
+
purpose.
|
63
|
+
|
64
|
+
## Documentation
|
65
|
+
|
66
|
+
- [Howzit Wiki][Wiki].
|
67
|
+
- [YARD documentation][RubyDoc] is hosted by RubyDoc.info.
|
68
|
+
- [Interactive documentation][Omniref] is hosted by Omniref.
|
69
|
+
|
70
|
+
[Wiki]: https://github.com/ttscoff/howzit/wiki
|
71
|
+
[RubyDoc]: http://www.rubydoc.info/gems/howzit
|
72
|
+
[Omniref]: https://www.omniref.com/ruby/gems/howzit
|
73
|
+
|
74
|
+
<!--GITHUB-->
|
75
|
+
## Development and Testing
|
76
|
+
|
77
|
+
### Source Code
|
78
|
+
|
79
|
+
The [howzit source] is hosted on GitHub.
|
80
|
+
Clone the project with
|
81
|
+
|
82
|
+
```
|
83
|
+
$ git clone https://github.com/ttscoff/howzit.git
|
84
|
+
```
|
85
|
+
|
86
|
+
[howzit source]: https://github.com/ttscoff/howzit
|
87
|
+
|
88
|
+
### Requirements
|
89
|
+
|
90
|
+
You will need [Ruby] with [Bundler].
|
91
|
+
|
92
|
+
Install the development dependencies with
|
93
|
+
|
94
|
+
```
|
95
|
+
$ bundle
|
96
|
+
```
|
97
|
+
|
98
|
+
[Bundler]: http://bundler.io/
|
99
|
+
[Ruby]: https://www.ruby-lang.org/
|
100
|
+
|
101
|
+
### Rake
|
102
|
+
|
103
|
+
Run `$ rake -T` to see all Rake tasks.
|
104
|
+
|
105
|
+
```
|
106
|
+
rake build # Build howzit-2.0.1.gem into the pkg directory
|
107
|
+
rake bump:current[tag] # Show current gem version
|
108
|
+
rake bump:major[tag] # Bump major part of gem version
|
109
|
+
rake bump:minor[tag] # Bump minor part of gem version
|
110
|
+
rake bump:patch[tag] # Bump patch part of gem version
|
111
|
+
rake bump:pre[tag] # Bump pre part of gem version
|
112
|
+
rake bump:set # Sets the version number using the VERSION environment variable
|
113
|
+
rake clean # Remove any temporary products
|
114
|
+
rake clobber # Remove any generated files
|
115
|
+
rake install # Build and install howzit-2.0.1.gem into system gems
|
116
|
+
rake install:local # Build and install howzit-2.0.1.gem into system gems without network access
|
117
|
+
rake release[remote] # Create tag v2.0.1 and build and push howzit-2.0.1.gem to Rubygems
|
118
|
+
rake rubocop # Run RuboCop
|
119
|
+
rake rubocop:auto_correct # Auto-correct RuboCop offenses
|
120
|
+
rake spec # Run RSpec code examples
|
121
|
+
rake test # Run test suite
|
122
|
+
rake yard # Generate YARD Documentation
|
123
|
+
```
|
124
|
+
|
125
|
+
### Guard
|
126
|
+
|
127
|
+
Guard tasks have been separated into the following groups:
|
128
|
+
`doc`, `lint`, and `unit`.
|
129
|
+
By default, `$ guard` will generate documentation, lint, and run unit tests.
|
130
|
+
|
131
|
+
## Contributing
|
132
|
+
|
133
|
+
Please submit and comment on bug reports and feature requests.
|
134
|
+
|
135
|
+
To submit a patch:
|
136
|
+
|
137
|
+
1. Fork it (https://github.com/ttscoff/howzit/fork).
|
138
|
+
2. Create your feature branch (`git checkout -b my-new-feature`).
|
139
|
+
3. Make changes. Write and run tests.
|
140
|
+
4. Commit your changes (`git commit -am 'Add some feature'`).
|
141
|
+
5. Push to the branch (`git push origin my-new-feature`).
|
142
|
+
6. Create a new Pull Request.
|
143
|
+
|
144
|
+
<!--END GITHUB-->
|
145
|
+
<!--END README-->
|
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.1.
|
4
|
+
version: 2.1.13
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Brett Terpstra
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2024-
|
11
|
+
date: 2024-08-05 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bundler
|
@@ -339,6 +339,7 @@ files:
|
|
339
339
|
- spec/task_spec.rb
|
340
340
|
- spec/topic_spec.rb
|
341
341
|
- spec/util_spec.rb
|
342
|
+
- src/_README.md
|
342
343
|
- update_readmes.rb
|
343
344
|
homepage: https://github.com/ttscoff/howzit
|
344
345
|
licenses:
|
@@ -359,7 +360,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
359
360
|
- !ruby/object:Gem::Version
|
360
361
|
version: '0'
|
361
362
|
requirements: []
|
362
|
-
rubygems_version: 3.2.
|
363
|
+
rubygems_version: 3.2.15
|
363
364
|
signing_key:
|
364
365
|
specification_version: 4
|
365
366
|
summary: Provides a way to access Markdown project notes by topic with query capabilities
|