howzit 2.1.28 → 2.1.30
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 +121 -0
- data/README.md +5 -1
- data/Rakefile +11 -4
- data/bin/howzit +65 -65
- data/howzit.gemspec +1 -1
- data/lib/howzit/buildnote.rb +4 -8
- data/lib/howzit/colors.rb +50 -22
- data/lib/howzit/condition_evaluator.rb +307 -0
- data/lib/howzit/conditional_content.rb +96 -0
- data/lib/howzit/config.rb +28 -3
- data/lib/howzit/console_logger.rb +74 -2
- data/lib/howzit/directive.rb +137 -0
- data/lib/howzit/prompt.rb +20 -12
- data/lib/howzit/run_report.rb +1 -1
- data/lib/howzit/script_comm.rb +105 -0
- data/lib/howzit/script_support.rb +479 -0
- data/lib/howzit/stringutils.rb +4 -4
- data/lib/howzit/task.rb +68 -6
- data/lib/howzit/topic.rb +576 -13
- data/lib/howzit/util.rb +11 -3
- data/lib/howzit/version.rb +1 -1
- data/lib/howzit.rb +5 -0
- data/spec/condition_evaluator_spec.rb +261 -0
- data/spec/conditional_blocks_integration_spec.rb +159 -0
- data/spec/conditional_content_spec.rb +296 -0
- data/spec/log_level_spec.rb +247 -0
- data/spec/script_comm_spec.rb +303 -0
- data/spec/sequential_conditional_spec.rb +319 -0
- data/spec/set_var_spec.rb +603 -0
- data/spec/spec_helper.rb +3 -1
- data/spec/topic_spec.rb +8 -6
- data/src/_README.md +5 -1
- metadata +23 -4
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: e1b854ebbde3ca3bdeac5fa4a633911993e6a9361c02ccc8c7364b7624edb4a1
|
|
4
|
+
data.tar.gz: 3a7f716c2f331acb4cb767d0ea3eff2b59dfc82b8756f5716b86b6045d6c46f6
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: f2cec86d81ab9b1b51c65d21b0ef628483e214545bba722267e3670978305d862b634dcdb93db8bad56d66627213a60939784feb6d021d9cbd2bfc9639451bea
|
|
7
|
+
data.tar.gz: b925f6cbe26ac39b5aa18fcd21896885b85742b88098d25e0b1fb35915983da3c602bc912bc44745fe3fd6f92396bcecdf7ff036411ffe872c54145d00fdf888
|
data/CHANGELOG.md
CHANGED
|
@@ -1,3 +1,124 @@
|
|
|
1
|
+
### 2.1.30
|
|
2
|
+
|
|
3
|
+
2026-01-06 03:55
|
|
4
|
+
|
|
5
|
+
#### CHANGED
|
|
6
|
+
|
|
7
|
+
- Updated rubocop from version 0.93.1 to 1.82.1 for Ruby 3.4.4 compatibility
|
|
8
|
+
- Updated .rubocop.yml to use plugins syntax instead of require for rubocop extensions
|
|
9
|
+
- Updated .rubocop.yml to inherit from .rubocop_todo.yml and removed Max settings that were overriding todo file limits
|
|
10
|
+
- Added Security/YAMLLoad exception to .rubocop.yml to allow YAML.load usage (intentionally not using safe_load)
|
|
11
|
+
- Added Layout/LineLength exceptions for files with intentionally long lines (bin/howzit, task.rb, util.rb, stringutils.rb, buildnote.rb)
|
|
12
|
+
- Run blocks now execute scripts using appropriate interpreter commands instead of always using /bin/sh
|
|
13
|
+
- Moved @log_level and @set_var directive processing before task check in sequential execution to ensure they are processed correctly.
|
|
14
|
+
|
|
15
|
+
#### NEW
|
|
16
|
+
|
|
17
|
+
- Scripts can now communicate back to Howzit by writing to a communication file specified in HOWZIT_COMM_FILE environment variable, allowing scripts to send log messages (LOG:level:message) and set variables (VAR:KEY=value) that are available for subsequent tasks and conditional logic
|
|
18
|
+
- Added ScriptComm module to handle bidirectional communication between scripts and Howzit
|
|
19
|
+
- Added @if and @unless conditional blocks that allow content and tasks to be conditionally included or excluded based on evaluated conditions, with support for nested blocks
|
|
20
|
+
- Conditional blocks support string comparisons (==, =~ /regex/, *= contains, ^= starts with, $= ends with) and numeric comparisons (==, !=, >, >=, <, <=)
|
|
21
|
+
- Conditions can test against metadata keys, environment variables, positional arguments ($1, $2, etc.), named arguments, and script-set variables
|
|
22
|
+
- Added special condition checks: git dirty/clean, file exists <path>, dir exists <path>, topic exists <name>, and cwd/working directory
|
|
23
|
+
- Conditions support negation with 'not' or '!' prefix
|
|
24
|
+
- Added @elsif directive for alternative conditions in @if/@unless blocks, allowing multiple conditional branches
|
|
25
|
+
- Added @else directive for fallback branches in conditional blocks when all previous conditions are false
|
|
26
|
+
- Conditional blocks now support chaining multiple @elsif statements between @if/@unless and @else
|
|
27
|
+
- @elsif and @else work correctly with nested conditional blocks
|
|
28
|
+
- Added **= fuzzy match operator for string comparisons that matches if search string characters appear in order within the target string (e.g., "fluffy" **= "ffy" matches)
|
|
29
|
+
- Added file contents condition that reads file contents and performs string comparisons using any comparison operator (e.g., file contents VERSION.txt ^= 0.)
|
|
30
|
+
- File contents condition supports file paths as variables from metadata, named arguments, or environment variables
|
|
31
|
+
- ScriptSupport module provides helper functions (log_info, log_warn, log_error, log_debug, set_var) for bash, zsh, fish, ruby, python, perl, and node scripts in run blocks
|
|
32
|
+
- Automatic interpreter detection from hashbang lines in scripts
|
|
33
|
+
- Helper script injection into run blocks based on detected interpreter
|
|
34
|
+
- Support directory installation at ~/.local/share/howzit/support with language-specific helper scripts
|
|
35
|
+
- Add sequential conditional evaluation: @if/@unless blocks are now evaluated after each task runs, allowing variables set by scripts to affect subsequent conditional blocks in the same topic
|
|
36
|
+
- Add @log_level(LEVEL) directive to set log level for subsequent tasks in a topic
|
|
37
|
+
- Add log_level parameter to @run directives (e.g., @run(script.sh, log_level=debug))
|
|
38
|
+
- Add HOWZIT_LOG_LEVEL environment variable support for global log level configuration
|
|
39
|
+
- Add emoji and color indicators for log messages (debug, info, warn, error)
|
|
40
|
+
- Add comprehensive test coverage for sequential conditional evaluation including @if/@unless/@elsif/@else blocks with variables from run blocks
|
|
41
|
+
- Add comprehensive test coverage for log level configuration including @log_level directive, log_level parameter in @run directives, and HOWZIT_LOG_LEVEL environment variable
|
|
42
|
+
- Added @set_var directive to set variables in build notes. Takes two comma-separated arguments: variable name (alphanumeric, dashes, underscores only) and value. Variables are available as ${VAR} in subsequent @run directives, run blocks, and @if/@else conditional blocks.
|
|
43
|
+
- Added command substitution support to @set_var directive. Values can use backticks (`command`) or $() syntax ($(command)) to execute commands and use their output as the variable value. Commands can reference other variables using ${VAR} syntax.
|
|
44
|
+
- Added @set_var directive to set variables directly in build notes, making them available as ${VAR} in subsequent @run directives, run blocks, and @if/@else conditional blocks.
|
|
45
|
+
- Added command substitution support to @set_var so values can come from backtick commands (`command`) or $() syntax ($(command)), with command output (whitespace stripped) used as the variable value and ${VAR} substitutions applied inside the command.
|
|
46
|
+
|
|
47
|
+
#### IMPROVED
|
|
48
|
+
|
|
49
|
+
- Auto-corrected rubocop style offenses including string literals, redundant self, parentheses, and other correctable issues
|
|
50
|
+
- Fixed Lint/Void issue in buildnote.rb by simplifying conditional logic
|
|
51
|
+
- Cwd and working directory can now be used with string comparison operators (==, =~, *=, ^=, $=) to check the current directory path
|
|
52
|
+
- Conditions now support ${var} syntax in addition to var for consistency with variable substitution syntax
|
|
53
|
+
- String comparison operators (*=, ^=, $=) now treat unquoted strings that aren't found as variables as literal strings, allowing simpler syntax like template *= gem instead of template *= "gem"
|
|
54
|
+
- Log messages from scripts now display with visual indicators: debug messages show with magnifying glass emoji and dark color, info with info emoji and cyan, warnings with warning emoji and yellow, errors with X emoji and red
|
|
55
|
+
- Log level filtering now properly applies to script-to-howzit communication messages, showing only messages at or above the configured level
|
|
56
|
+
- Conditional blocks (@if/@unless/@elsif/@else) now re-evaluate after each task execution, enabling dynamic conditional flow based on variables set by preceding tasks
|
|
57
|
+
- Improve task directive parsing by refactoring to use unless/next pattern for better code organization and fixing @log_level directive handling
|
|
58
|
+
- Improve Directive#to_task to properly handle title rendering with variable substitution, argument parsing for include tasks, and action escaping for copy tasks
|
|
59
|
+
- Processed @set_var directives before task creation in topics without conditionals so variable substitution in @run actions works as expected even in the non-sequential execution path.
|
|
60
|
+
|
|
61
|
+
#### FIXED
|
|
62
|
+
|
|
63
|
+
- Resolved NameError for 'white' color method by generating escape codes directly from configured_colors hash instead of calling dynamically generated methods
|
|
64
|
+
- Fixed infinite recursion in ConsoleLogger by using $stderr.puts directly instead of calling warn method recursively
|
|
65
|
+
- Color template method now properly respects coloring? setting and returns empty strings when coloring is disabled
|
|
66
|
+
- Resolved test failures caused by Howzit.buildnote caching stale instances by resetting @buildnote in spec_helper before each test
|
|
67
|
+
- Fixed bug where @end statements failed to close conditional blocks when conditions evaluated to false, preventing subsequent conditional blocks from working correctly
|
|
68
|
+
- Fixed issue where named arguments from topic titles were not available when evaluating conditions in conditional blocks
|
|
69
|
+
- Suppressed EPIPE errors that occur when writing to stdout/stderr after pipes are closed, preventing error messages from appearing in terminal output
|
|
70
|
+
- Fix @elsif and @else conditional blocks not executing tasks when parent @if condition is false by correctly tracking branch indices and skipping parent @if index in conditional path evaluation
|
|
71
|
+
- Fix clipboard copy test failing due to cached console logger instance not updating when log_level option changes
|
|
72
|
+
- Fixed variable persistence issue in sequential execution where Howzit.named_arguments was being reset on each iteration, causing @set_var variables to be lost.
|
|
73
|
+
- Ensured variables set by @set_var and helper scripts persist correctly across sequential conditional evaluation by merging topic named arguments into Howzit.named_arguments instead of overwriting them.
|
|
74
|
+
|
|
75
|
+
### 2.1.29
|
|
76
|
+
|
|
77
|
+
2026-01-01 06:55
|
|
78
|
+
|
|
79
|
+
#### CHANGED
|
|
80
|
+
|
|
81
|
+
- Updated rubocop from version 0.93.1 to 1.82.1 for Ruby 3.4.4 compatibility
|
|
82
|
+
- Updated .rubocop.yml to use plugins syntax instead of require for rubocop extensions
|
|
83
|
+
- Updated .rubocop.yml to inherit from .rubocop_todo.yml and removed Max settings that were overriding todo file limits
|
|
84
|
+
- Added Security/YAMLLoad exception to .rubocop.yml to allow YAML.load usage (intentionally not using safe_load)
|
|
85
|
+
- Added Layout/LineLength exceptions for files with intentionally long lines (bin/howzit, task.rb, util.rb, stringutils.rb, buildnote.rb)
|
|
86
|
+
|
|
87
|
+
#### NEW
|
|
88
|
+
|
|
89
|
+
- Scripts can now communicate back to Howzit by writing to a communication file specified in HOWZIT_COMM_FILE environment variable, allowing scripts to send log messages (LOG:level:message) and set variables (VAR:KEY=value) that are available for subsequent tasks and conditional logic
|
|
90
|
+
- Added ScriptComm module to handle bidirectional communication between scripts and Howzit
|
|
91
|
+
- Added @if and @unless conditional blocks that allow content and tasks to be conditionally included or excluded based on evaluated conditions, with support for nested blocks
|
|
92
|
+
- Conditional blocks support string comparisons (==, =~ /regex/, *= contains, ^= starts with, $= ends with) and numeric comparisons (==, !=, >, >=, <, <=)
|
|
93
|
+
- Conditions can test against metadata keys, environment variables, positional arguments ($1, $2, etc.), named arguments, and script-set variables
|
|
94
|
+
- Added special condition checks: git dirty/clean, file exists <path>, dir exists <path>, topic exists <name>, and cwd/working directory
|
|
95
|
+
- Conditions support negation with 'not' or '!' prefix
|
|
96
|
+
- Added @elsif directive for alternative conditions in @if/@unless blocks, allowing multiple conditional branches
|
|
97
|
+
- Added @else directive for fallback branches in conditional blocks when all previous conditions are false
|
|
98
|
+
- Conditional blocks now support chaining multiple @elsif statements between @if/@unless and @else
|
|
99
|
+
- @elsif and @else work correctly with nested conditional blocks
|
|
100
|
+
- Added **= fuzzy match operator for string comparisons that matches if search string characters appear in order within the target string (e.g., "fluffy" **= "ffy" matches)
|
|
101
|
+
- Added file contents condition that reads file contents and performs string comparisons using any comparison operator (e.g., file contents VERSION.txt ^= 0.)
|
|
102
|
+
- File contents condition supports file paths as variables from metadata, named arguments, or environment variables
|
|
103
|
+
|
|
104
|
+
#### IMPROVED
|
|
105
|
+
|
|
106
|
+
- Auto-corrected rubocop style offenses including string literals, redundant self, parentheses, and other correctable issues
|
|
107
|
+
- Fixed Lint/Void issue in buildnote.rb by simplifying conditional logic
|
|
108
|
+
- Cwd and working directory can now be used with string comparison operators (==, =~, *=, ^=, $=) to check the current directory path
|
|
109
|
+
- Conditions now support ${var} syntax in addition to var for consistency with variable substitution syntax
|
|
110
|
+
- String comparison operators (*=, ^=, $=) now treat unquoted strings that aren't found as variables as literal strings, allowing simpler syntax like template *= gem instead of template *= "gem"
|
|
111
|
+
|
|
112
|
+
#### FIXED
|
|
113
|
+
|
|
114
|
+
- Resolved NameError for 'white' color method by generating escape codes directly from configured_colors hash instead of calling dynamically generated methods
|
|
115
|
+
- Fixed infinite recursion in ConsoleLogger by using $stderr.puts directly instead of calling warn method recursively
|
|
116
|
+
- Color template method now properly respects coloring? setting and returns empty strings when coloring is disabled
|
|
117
|
+
- Resolved test failures caused by Howzit.buildnote caching stale instances by resetting @buildnote in spec_helper before each test
|
|
118
|
+
- Fixed bug where @end statements failed to close conditional blocks when conditions evaluated to false, preventing subsequent conditional blocks from working correctly
|
|
119
|
+
- Fixed issue where named arguments from topic titles were not available when evaluating conditions in conditional blocks
|
|
120
|
+
- Suppressed EPIPE errors that occur when writing to stdout/stderr after pipes are closed, preventing error messages from appearing in terminal output
|
|
121
|
+
|
|
1
122
|
### 2.1.28
|
|
2
123
|
|
|
3
124
|
2025-12-31 10:21
|
data/README.md
CHANGED
|
@@ -4,11 +4,11 @@
|
|
|
4
4
|
[](https://rubygems.org/gems/howzit)
|
|
5
5
|
[](./LICENSE.txt)
|
|
6
6
|
|
|
7
|
+
|
|
7
8
|
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
|
-
|
|
12
12
|
## Features
|
|
13
13
|
|
|
14
14
|
- Match topic titles with any portion of title
|
|
@@ -16,6 +16,10 @@ Howzit is a tool that allows you to keep Markdown-formatted notes about a projec
|
|
|
16
16
|
- Use `@run()`, `@copy()`, and `@open()` to perform actions within a build notes file
|
|
17
17
|
- Use `@include()` to import another topic's tasks
|
|
18
18
|
- Use fenced code blocks to include/run embedded scripts
|
|
19
|
+
- Scripts can communicate back to Howzit, sending log messages and setting variables
|
|
20
|
+
- Conditional blocks (`@if`/`@unless`/`@elsif`/`@else`) for conditionally including content and tasks
|
|
21
|
+
- String comparison operators including fuzzy match (`**=`) for flexible pattern matching
|
|
22
|
+
- File contents conditions to check file contents in conditional blocks
|
|
19
23
|
- Sets iTerm 2 marks on topic titles for navigation when paging is disabled
|
|
20
24
|
- Inside of git repositories, howzit will work from subdirectories, assuming build notes are in top level of repo
|
|
21
25
|
- Templates for easily including repeat tasks
|
data/Rakefile
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
3
|
# require 'bump/tasks'
|
|
4
|
+
require 'English'
|
|
4
5
|
require 'bundler/gem_tasks'
|
|
5
6
|
require 'rspec/core/rake_task'
|
|
6
7
|
require 'rubocop/rake_task'
|
|
@@ -13,7 +14,7 @@ module TempFixForRakeLastComment
|
|
|
13
14
|
last_description
|
|
14
15
|
end
|
|
15
16
|
end
|
|
16
|
-
Rake::Application.
|
|
17
|
+
Rake::Application.include TempFixForRakeLastComment
|
|
17
18
|
|
|
18
19
|
Rake::RDocTask.new do |rd|
|
|
19
20
|
rd.main = 'README.rdoc'
|
|
@@ -45,9 +46,15 @@ task :ver do
|
|
|
45
46
|
puts "changelog: #{cver}"
|
|
46
47
|
end
|
|
47
48
|
|
|
49
|
+
desc 'Version.rb check'
|
|
50
|
+
task :vver do
|
|
51
|
+
res = `grep VERSION lib/howzit/version.rb`
|
|
52
|
+
print res.match(/VERSION *= *['"](\d+\.\d+\.\d+(\w+)?)/)[1]
|
|
53
|
+
end
|
|
54
|
+
|
|
48
55
|
desc 'Changelog version check'
|
|
49
56
|
task :cver do
|
|
50
|
-
|
|
57
|
+
print IO.read(File.join(File.dirname(__FILE__), 'CHANGELOG.md')).match(/^#+ (\d+\.\d+\.\d+(\w+)?)/)[1]
|
|
51
58
|
end
|
|
52
59
|
|
|
53
60
|
desc 'Run tests in Docker'
|
|
@@ -77,7 +84,7 @@ task :dockertest, :version, :login do |_, args|
|
|
|
77
84
|
file = 'docker/Dockerfile'
|
|
78
85
|
end
|
|
79
86
|
|
|
80
|
-
d_spinner = TTY::Spinner.new(
|
|
87
|
+
d_spinner = TTY::Spinner.new('[:spinner] Setting up Docker', hide_cursor: true, format: :dots)
|
|
81
88
|
d_spinner.auto_spin
|
|
82
89
|
`docker build . --file #{file} -t #{img} &> /dev/null`
|
|
83
90
|
d_spinner.success
|
|
@@ -90,7 +97,7 @@ task :dockertest, :version, :login do |_, args|
|
|
|
90
97
|
spinner.auto_spin
|
|
91
98
|
res = `docker run --rm -v #{File.dirname(__FILE__)}:/howzit -it #{img}`
|
|
92
99
|
commit = `bash -c "docker commit $(docker ps -a|grep #{img}|awk '{print $1}'|head -n 1) #{img}"`.strip
|
|
93
|
-
if
|
|
100
|
+
if $CHILD_STATUS.exitstatus.zero?
|
|
94
101
|
spinner.success
|
|
95
102
|
else
|
|
96
103
|
spinner.error
|
data/bin/howzit
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
#!/usr/bin/env ruby
|
|
2
2
|
# frozen_string_literal: true
|
|
3
3
|
|
|
4
|
-
$LOAD_PATH.unshift File.join(__dir__,
|
|
5
|
-
require
|
|
4
|
+
$LOAD_PATH.unshift File.join(__dir__, '..', 'lib')
|
|
5
|
+
require 'howzit'
|
|
6
6
|
|
|
7
7
|
Howzit::Color.coloring = $stdout.isatty
|
|
8
8
|
|
|
@@ -13,127 +13,127 @@ Howzit.named_arguments = {}
|
|
|
13
13
|
|
|
14
14
|
OptionParser.new do |opts|
|
|
15
15
|
opts.banner = "Usage: #{File.basename(__FILE__)} [OPTIONS] [TOPIC]"
|
|
16
|
-
opts.separator
|
|
16
|
+
opts.separator ''
|
|
17
17
|
opts.separator "Show build notes for the current project (buildnotes.md).
|
|
18
18
|
Include a topic name to see just that topic, or no argument to display all."
|
|
19
|
-
opts.separator
|
|
20
|
-
opts.separator
|
|
19
|
+
opts.separator ''
|
|
20
|
+
opts.separator 'Options:'
|
|
21
21
|
|
|
22
22
|
opts.separator " Behavior:\n\n" #=================================================================== BEHAVIOR
|
|
23
23
|
|
|
24
|
-
opts.on(
|
|
24
|
+
opts.on('--ask', 'Request confirmation for all tasks when running a topic') { Howzit.options[:ask] = true }
|
|
25
25
|
|
|
26
|
-
opts.on(
|
|
27
|
-
raise
|
|
26
|
+
opts.on('--default', 'Answer all prompts with default response') do
|
|
27
|
+
raise '--default cannot be used with --yes or --no' if Howzit.options[:yes] || Howzit.options[:no]
|
|
28
28
|
|
|
29
29
|
Howzit.options[:default] = true
|
|
30
30
|
end
|
|
31
31
|
|
|
32
|
-
opts.on(
|
|
32
|
+
opts.on('-f', '--force', 'Continue executing after an error') { Howzit.options[:force] = true }
|
|
33
33
|
|
|
34
|
-
opts.on(
|
|
35
|
-
|
|
34
|
+
opts.on('-m', '--matching TYPE', MATCHING_OPTIONS,
|
|
35
|
+
'Topics matching type', "(#{MATCHING_OPTIONS.join(', ').sub(/#{Howzit.options[:matching]}/, "*#{Howzit.options[:matching]}")})") do |c|
|
|
36
36
|
Howzit.options[:matching] = c
|
|
37
37
|
end
|
|
38
38
|
|
|
39
|
-
opts.on(
|
|
40
|
-
|
|
39
|
+
opts.on('--multiple TYPE', MULTIPLE_OPTIONS,
|
|
40
|
+
'Multiple result handling', "(#{MULTIPLE_OPTIONS.join(', ').sub(/#{Howzit.options[:multiple_matches]}/, "*#{Howzit.options[:multiple_matches]}")}, default choose)") do |c|
|
|
41
41
|
Howzit.options[:multiple_matches] = c.to_sym
|
|
42
42
|
end
|
|
43
43
|
|
|
44
|
-
opts.on(
|
|
44
|
+
opts.on('-u', '--[no-]upstream', 'Traverse up parent directories for additional build notes') do |p|
|
|
45
45
|
Howzit.options[:include_upstream] = p
|
|
46
46
|
end
|
|
47
47
|
|
|
48
|
-
opts.on(
|
|
49
|
-
raise
|
|
48
|
+
opts.on('-y', '--yes', 'Answer yes to all prompts') do
|
|
49
|
+
raise '--default cannot be used with --yes' if Howzit.options[:default]
|
|
50
50
|
|
|
51
51
|
Howzit.options[:yes] = true
|
|
52
52
|
end
|
|
53
53
|
|
|
54
|
-
opts.on(
|
|
55
|
-
raise
|
|
54
|
+
opts.on('-n', '--no', 'Answer no to all prompts') do
|
|
55
|
+
raise '--default cannot be used with --no' if Howzit.options[:default]
|
|
56
56
|
|
|
57
57
|
Howzit.options[:no] = true
|
|
58
58
|
end
|
|
59
59
|
|
|
60
60
|
opts.separator "\n Listing:\n\n" #=================================================================== LISTING
|
|
61
61
|
|
|
62
|
-
opts.on(
|
|
62
|
+
opts.on('-L', '--list-completions', 'List topics (completion-compatible)') do
|
|
63
63
|
Howzit.options[:list_topics] = true
|
|
64
64
|
Howzit.options[:list_topic_titles] = true
|
|
65
65
|
end
|
|
66
66
|
|
|
67
|
-
opts.on(
|
|
67
|
+
opts.on('-l', '--list', 'List available topics') do
|
|
68
68
|
Howzit.options[:list_topics] = true
|
|
69
69
|
end
|
|
70
70
|
|
|
71
|
-
opts.on(
|
|
71
|
+
opts.on('-R', '--list-runnable [PATTERN]', 'List topics containing @ directives (verbose)') do |pat|
|
|
72
72
|
Howzit.options[:for_topic] = pat
|
|
73
73
|
Howzit.options[:list_runnable] = true
|
|
74
74
|
end
|
|
75
75
|
|
|
76
|
-
opts.on(
|
|
76
|
+
opts.on('-T', '--task-list', 'List topics containing @ directives (completion-compatible)') do
|
|
77
77
|
Howzit.options[:list_runnable] = true
|
|
78
78
|
Howzit.options[:list_runnable_titles] = true
|
|
79
79
|
end
|
|
80
80
|
|
|
81
|
-
opts.on(
|
|
81
|
+
opts.on('--templates', 'List available templates') do
|
|
82
82
|
out = []
|
|
83
83
|
Dir.chdir(Howzit.config.template_folder)
|
|
84
|
-
Dir.glob(
|
|
85
|
-
template = File.basename(file,
|
|
84
|
+
Dir.glob('*.md').each do |file|
|
|
85
|
+
template = File.basename(file, '.md')
|
|
86
86
|
out.push(Howzit::Color.template("{Mk}template:{Yk}#{template}{x}"))
|
|
87
|
-
out.push(Howzit::Color.template(
|
|
87
|
+
out.push(Howzit::Color.template('{bk}[{bl}tasks{bk}]──────────────────────────────────────┐{x}'))
|
|
88
88
|
metadata = file.extract_metadata
|
|
89
89
|
topics = Howzit::BuildNote.new(file: file).topics
|
|
90
90
|
topics.each do |topic|
|
|
91
|
-
out.push(Howzit::Color.template(" {bk}│{bw}-{x} {bcK}#{template}:#{topic.title.sub(/^.*?:/,
|
|
91
|
+
out.push(Howzit::Color.template(" {bk}│{bw}-{x} {bcK}#{template}:#{topic.title.sub(/^.*?:/, '')}{x}"))
|
|
92
92
|
end
|
|
93
93
|
unless metadata.empty?
|
|
94
94
|
meta = []
|
|
95
|
-
meta << metadata[
|
|
96
|
-
meta << metadata[
|
|
97
|
-
out.push(Howzit::Color.template(
|
|
98
|
-
out.push(Howzit::Color.template(" {bk}│ {xw}#{meta.join(
|
|
95
|
+
meta << metadata['required'].split(/\s*,\s*/).map { |m| "*{bw}#{m}{xw}" } if metadata.key?('required')
|
|
96
|
+
meta << metadata['optional'].split(/\s*,\s*/).map(&:to_s) if metadata.key?('optional')
|
|
97
|
+
out.push(Howzit::Color.template('{bk}[{bl}meta{bk}]───────────────────────────────────────┤{x}'))
|
|
98
|
+
out.push(Howzit::Color.template(" {bk}│ {xw}#{meta.join(', ')}{x}"))
|
|
99
99
|
end
|
|
100
|
-
out.push(Howzit::Color.template(
|
|
100
|
+
out.push(Howzit::Color.template(' {bk}└───────────────────────────────────────────┘{x}'))
|
|
101
101
|
end
|
|
102
102
|
Howzit::Util.page out.join("\n")
|
|
103
103
|
Process.exit 0
|
|
104
104
|
end
|
|
105
105
|
|
|
106
|
-
opts.on(
|
|
106
|
+
opts.on('--templates-c', 'List available templates in a format for completion') do
|
|
107
107
|
out = []
|
|
108
108
|
Dir.chdir(Howzit.config.template_folder)
|
|
109
|
-
Dir.glob(
|
|
110
|
-
template = File.basename(file,
|
|
109
|
+
Dir.glob('*.md').each do |file|
|
|
110
|
+
template = File.basename(file, '.md')
|
|
111
111
|
out.push(template)
|
|
112
112
|
end
|
|
113
113
|
puts out.join("\n")
|
|
114
114
|
Process.exit 0
|
|
115
115
|
end
|
|
116
116
|
|
|
117
|
-
opts.on(
|
|
117
|
+
opts.on('--title-only', 'Output title only') do
|
|
118
118
|
Howzit.options[:output_title] = true
|
|
119
119
|
Howzit.options[:title_only] = true
|
|
120
120
|
end
|
|
121
121
|
|
|
122
122
|
opts.separator("\n Commands:\n\n") #=================================================================== COMMANDS
|
|
123
123
|
|
|
124
|
-
opts.on(
|
|
124
|
+
opts.on('-c', '--create', 'Create a skeleton build note in the current working directory') do
|
|
125
125
|
Howzit.buildnote.create_note
|
|
126
126
|
Process.exit 0
|
|
127
127
|
end
|
|
128
128
|
|
|
129
|
-
opts.on(
|
|
129
|
+
opts.on('--config-get [KEY]', 'Display the configuration settings or setting for a specific key') do |k|
|
|
130
130
|
if k.nil?
|
|
131
131
|
Howzit::Config::DEFAULTS.sort_by { |key, _| key }.each do |key, _|
|
|
132
132
|
print "#{key}: "
|
|
133
133
|
p Howzit.options[key]
|
|
134
134
|
end
|
|
135
135
|
else
|
|
136
|
-
k.sub!(/^:/,
|
|
136
|
+
k.sub!(/^:/, '')
|
|
137
137
|
if Howzit.options.key?(k.to_sym)
|
|
138
138
|
puts Howzit.options[k.to_sym]
|
|
139
139
|
else
|
|
@@ -143,12 +143,12 @@ OptionParser.new do |opts|
|
|
|
143
143
|
Process.exit 0
|
|
144
144
|
end
|
|
145
145
|
|
|
146
|
-
opts.on(
|
|
147
|
-
raise
|
|
146
|
+
opts.on('--config-set KEY=VALUE', 'Set a config value (must be a valid key)') do |key|
|
|
147
|
+
raise 'Argument must be KEY=VALUE' unless key =~ /\S=\S/
|
|
148
148
|
|
|
149
149
|
parts = key.split(/=/)
|
|
150
|
-
k = parts.shift.sub(/^:/,
|
|
151
|
-
v = parts.join(
|
|
150
|
+
k = parts.shift.sub(/^:/, '')
|
|
151
|
+
v = parts.join(' ')
|
|
152
152
|
|
|
153
153
|
if Howzit.options.key?(k.to_sym)
|
|
154
154
|
Howzit.options[k.to_sym] = v.to_config_value(Howzit.options[k.to_sym])
|
|
@@ -160,103 +160,103 @@ OptionParser.new do |opts|
|
|
|
160
160
|
end
|
|
161
161
|
|
|
162
162
|
desc = %(Edit buildnotes file in current working directory using default editor)
|
|
163
|
-
opts.on(
|
|
163
|
+
opts.on('-e', '--edit', desc) do
|
|
164
164
|
Howzit.buildnote.edit
|
|
165
165
|
Process.exit 0
|
|
166
166
|
end
|
|
167
167
|
|
|
168
|
-
opts.on(
|
|
168
|
+
opts.on('--edit-config', 'Edit configuration file using default editor') do
|
|
169
169
|
Howzit.config.editor
|
|
170
170
|
Process.exit 0
|
|
171
171
|
end
|
|
172
172
|
|
|
173
|
-
opts.on(
|
|
173
|
+
opts.on('--edit-template NAME', 'Create or edit a template') do |template|
|
|
174
174
|
Howzit.buildnote.edit_template(template)
|
|
175
175
|
Process.exit 0
|
|
176
176
|
end
|
|
177
177
|
|
|
178
|
-
opts.on(
|
|
178
|
+
opts.on('--grep PATTERN', 'Display sections matching a search pattern') do |pat|
|
|
179
179
|
Howzit.options[:grep] = pat
|
|
180
180
|
end
|
|
181
181
|
|
|
182
|
-
opts.on(
|
|
182
|
+
opts.on('--hook', 'Copy a link to the build note file, ready for pasting into Hook.app or other notes') do
|
|
183
183
|
Howzit.buildnote.hook
|
|
184
184
|
Process.exit 0
|
|
185
185
|
end
|
|
186
186
|
|
|
187
|
-
opts.on(
|
|
187
|
+
opts.on('-r', '--run', 'Execute @run, @open, and/or @copy commands for given topic') do
|
|
188
188
|
Howzit.options[:run] = true
|
|
189
189
|
end
|
|
190
190
|
|
|
191
|
-
opts.on(
|
|
191
|
+
opts.on('-s', '--select', 'Select topic from menu') do
|
|
192
192
|
Howzit.options[:choose] = true
|
|
193
193
|
end
|
|
194
194
|
|
|
195
195
|
opts.separator("\n Formatting:\n\n") #=================================================================== FORMATTING
|
|
196
196
|
|
|
197
|
-
opts.on(
|
|
197
|
+
opts.on('--[no-]color', 'Colorize output (default on)') do |c|
|
|
198
198
|
Howzit.options[:color] = c
|
|
199
199
|
Howzit.options[:highlight] = false unless c
|
|
200
200
|
end
|
|
201
201
|
|
|
202
|
-
opts.on(
|
|
203
|
-
"Formatting style for topic titles (#{HEADER_FORMAT_OPTIONS.join(
|
|
202
|
+
opts.on('--header-format TYPE', HEADER_FORMAT_OPTIONS,
|
|
203
|
+
"Formatting style for topic titles (#{HEADER_FORMAT_OPTIONS.join(', ')})") do |t|
|
|
204
204
|
Howzit.options[:header_format] = t
|
|
205
205
|
end
|
|
206
206
|
|
|
207
|
-
opts.on(
|
|
207
|
+
opts.on('--[no-]md-highlight', 'Highlight Markdown syntax (default on), requires mdless or mdcat') do |m|
|
|
208
208
|
Howzit.options[:highlight] = Howzit.options[:color] ? m : false
|
|
209
209
|
end
|
|
210
210
|
|
|
211
|
-
opts.on(
|
|
211
|
+
opts.on('--[no-]pager', 'Paginate output (default on)') do |p|
|
|
212
212
|
Howzit.options[:paginate] = p
|
|
213
213
|
end
|
|
214
214
|
|
|
215
|
-
opts.on(
|
|
215
|
+
opts.on('--show-code', 'Display the content of fenced run blocks') do
|
|
216
216
|
Howzit.options[:show_all_code] = true
|
|
217
217
|
end
|
|
218
218
|
|
|
219
|
-
opts.on(
|
|
219
|
+
opts.on('-t', '--title', 'Output title with build notes') do
|
|
220
220
|
Howzit.options[:output_title] = true
|
|
221
221
|
end
|
|
222
222
|
|
|
223
|
-
opts.on(
|
|
223
|
+
opts.on('-w', '--wrap COLUMNS', 'Wrap to specified width (default 80, 0 to disable)') do |w|
|
|
224
224
|
Howzit.options[:wrap] = w.to_i
|
|
225
225
|
end
|
|
226
226
|
|
|
227
227
|
opts.separator("\n Logging:\n\n") #=================================================================== LOGGING
|
|
228
228
|
|
|
229
|
-
opts.on(
|
|
229
|
+
opts.on('-d', '--debug', 'Show debug messages (and all messages)') do
|
|
230
230
|
Howzit.options[:log_level] = 0
|
|
231
231
|
Howzit.console.reset_level
|
|
232
232
|
end
|
|
233
233
|
|
|
234
|
-
opts.on(
|
|
234
|
+
opts.on('-q', '--quiet', 'Silence info message') do
|
|
235
235
|
Howzit.options[:log_level] = 4
|
|
236
236
|
Howzit.console.reset_level
|
|
237
237
|
end
|
|
238
238
|
|
|
239
|
-
opts.on(
|
|
239
|
+
opts.on('--verbose', 'Show all messages') do
|
|
240
240
|
Howzit.options[:log_level] = 1
|
|
241
241
|
Howzit.console.reset_level
|
|
242
242
|
end
|
|
243
243
|
|
|
244
244
|
opts.separator("\n Misc:\n\n") #=================================================================== MISC
|
|
245
245
|
|
|
246
|
-
opts.on(
|
|
246
|
+
opts.on('-h', '--help', 'Display this screen') do
|
|
247
247
|
Howzit::Util.page opts.to_s
|
|
248
248
|
Process.exit 0
|
|
249
249
|
end
|
|
250
250
|
|
|
251
|
-
opts.on(
|
|
251
|
+
opts.on('-v', '--version', 'Display version number') do
|
|
252
252
|
puts "#{File.basename(__FILE__)} v#{Howzit::VERSION}"
|
|
253
253
|
Process.exit 0
|
|
254
254
|
end
|
|
255
255
|
end.parse!(args)
|
|
256
256
|
|
|
257
|
-
trap(
|
|
257
|
+
trap('INT') do
|
|
258
258
|
puts
|
|
259
|
-
puts
|
|
259
|
+
puts 'Cancelled'
|
|
260
260
|
Process.exit 0
|
|
261
261
|
end
|
|
262
262
|
|
data/howzit.gemspec
CHANGED
|
@@ -35,7 +35,7 @@ Gem::Specification.new do |spec|
|
|
|
35
35
|
|
|
36
36
|
spec.add_development_dependency 'cli-test', '~> 1.0'
|
|
37
37
|
spec.add_development_dependency 'rspec', '~> 3.13'
|
|
38
|
-
spec.add_development_dependency 'rubocop', '~>
|
|
38
|
+
spec.add_development_dependency 'rubocop', '~> 1.60'
|
|
39
39
|
spec.add_development_dependency 'simplecov', '~> 0.9'
|
|
40
40
|
# spec.add_development_dependency 'codecov', '~> 0.1'
|
|
41
41
|
spec.add_development_dependency 'fuubar', '~> 2.0'
|
data/lib/howzit/buildnote.rb
CHANGED
|
@@ -290,11 +290,7 @@ module Howzit
|
|
|
290
290
|
|
|
291
291
|
title = File.basename(Dir.pwd)
|
|
292
292
|
# prompt = TTY::Prompt.new
|
|
293
|
-
|
|
294
|
-
title
|
|
295
|
-
else
|
|
296
|
-
title = Prompt.get_line('{bw}Project name{x}'.c, default: title)
|
|
297
|
-
end
|
|
293
|
+
title = Prompt.get_line('{bw}Project name{x}'.c, default: title) unless default
|
|
298
294
|
summary = ''
|
|
299
295
|
summary = Prompt.get_line('{bw}Project summary{x}'.c) unless default
|
|
300
296
|
|
|
@@ -670,7 +666,7 @@ module Howzit
|
|
|
670
666
|
## @return [String] file path
|
|
671
667
|
##
|
|
672
668
|
def glob_note
|
|
673
|
-
Dir.glob('*.{txt,md,markdown}').select(&:build_note?).
|
|
669
|
+
Dir.glob('*.{txt,md,markdown}').select(&:build_note?).min
|
|
674
670
|
end
|
|
675
671
|
|
|
676
672
|
##
|
|
@@ -784,7 +780,7 @@ module Howzit
|
|
|
784
780
|
title = "#{short_path}:#{title}"
|
|
785
781
|
end
|
|
786
782
|
|
|
787
|
-
topic = Topic.new(title, prefix + lines.join("\n").strip.render_template(@metadata))
|
|
783
|
+
topic = Topic.new(title, prefix + lines.join("\n").strip.render_template(@metadata), @metadata)
|
|
788
784
|
|
|
789
785
|
topics.push(topic)
|
|
790
786
|
end
|
|
@@ -1098,7 +1094,7 @@ module Howzit
|
|
|
1098
1094
|
when :first
|
|
1099
1095
|
[matches[0]]
|
|
1100
1096
|
when :best
|
|
1101
|
-
[matches.
|
|
1097
|
+
[matches.min_by { |a| [a.title.comp_distance(search_term), a.title.length] }]
|
|
1102
1098
|
when :all
|
|
1103
1099
|
matches
|
|
1104
1100
|
else
|