howzit 2.1.29 → 2.1.31
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 +95 -0
- data/README.md +5 -1
- data/Rakefile +7 -1
- data/bin/howzit +5 -0
- data/lib/howzit/buildnote.rb +23 -1
- data/lib/howzit/config.rb +21 -0
- data/lib/howzit/console_logger.rb +62 -2
- data/lib/howzit/directive.rb +137 -0
- data/lib/howzit/script_support.rb +572 -0
- data/lib/howzit/stringutils.rb +47 -5
- data/lib/howzit/task.rb +57 -4
- data/lib/howzit/topic.rb +548 -5
- data/lib/howzit/version.rb +1 -1
- data/lib/howzit.rb +8 -1
- data/spec/buildnote_spec.rb +33 -4
- data/spec/log_level_spec.rb +247 -0
- data/spec/sequential_conditional_spec.rb +319 -0
- data/spec/set_var_spec.rb +603 -0
- data/spec/stringutils_spec.rb +41 -1
- data/spec/topic_spec.rb +8 -6
- data/src/_README.md +5 -1
- metadata +10 -2
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 937df7e90ef8641e22098de3ddba521506992d561bf29a225c3028fc8bbd8430
|
|
4
|
+
data.tar.gz: 0540d9f6a17567ca59627a64617c7f65148a0313c4d406df127fd01e50b4472d
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: bbcc5f97374ac62c822c5e0aec4d064dbe8635aabcb261cad9fe1a0ec92c1f4cf61bac0dcc2d8e330efac2dcdf141ea0e5e19ad8af307caa4782b14de1175f9a
|
|
7
|
+
data.tar.gz: 388f39ce1b755bf214b843ecc958bbe6058107004485be7e1aae8376177a8be720dc0c26fc863405fa0d0b6758d1bce7972a090f446b1879e1391f76cea1eed5
|
data/CHANGELOG.md
CHANGED
|
@@ -1,3 +1,98 @@
|
|
|
1
|
+
### 2.1.31
|
|
2
|
+
|
|
3
|
+
2026-01-06 04:57
|
|
4
|
+
|
|
5
|
+
#### CHANGED
|
|
6
|
+
|
|
7
|
+
- Updated Howzit to use XDG_CONFIG_HOME/howzit (or ~/.config/howzit if XDG_CONFIG_HOME is not set) for all configuration files, templates, themes, and script support files instead of ~/.local/share/howzit.
|
|
8
|
+
|
|
9
|
+
#### NEW
|
|
10
|
+
|
|
11
|
+
- Added automatic migration prompt that detects existing ~/.local/share/howzit directory and offers to migrate all files to the new config location, merging contents and overwriting existing files in the new location while preserving files that only exist in the new location.
|
|
12
|
+
- Added --migrate flag to explicitly trigger migration of legacy ~/.local/share/howzit directory to the new config location.
|
|
13
|
+
|
|
14
|
+
#### IMPROVED
|
|
15
|
+
|
|
16
|
+
- Migration prompt now appears during config initialization to catch legacy directories before creating new config files, preventing confusion about file locations.
|
|
17
|
+
|
|
18
|
+
#### FIXED
|
|
19
|
+
|
|
20
|
+
- Fixed ArgumentError when topic titles were longer than terminal width by ensuring horizontal rule width calculation never goes negative, clamping to zero when title exceeds available space.
|
|
21
|
+
|
|
22
|
+
### 2.1.30
|
|
23
|
+
|
|
24
|
+
2026-01-06 03:55
|
|
25
|
+
|
|
26
|
+
#### CHANGED
|
|
27
|
+
|
|
28
|
+
- Updated rubocop from version 0.93.1 to 1.82.1 for Ruby 3.4.4 compatibility
|
|
29
|
+
- Updated .rubocop.yml to use plugins syntax instead of require for rubocop extensions
|
|
30
|
+
- Updated .rubocop.yml to inherit from .rubocop_todo.yml and removed Max settings that were overriding todo file limits
|
|
31
|
+
- Added Security/YAMLLoad exception to .rubocop.yml to allow YAML.load usage (intentionally not using safe_load)
|
|
32
|
+
- Added Layout/LineLength exceptions for files with intentionally long lines (bin/howzit, task.rb, util.rb, stringutils.rb, buildnote.rb)
|
|
33
|
+
- Run blocks now execute scripts using appropriate interpreter commands instead of always using /bin/sh
|
|
34
|
+
- Moved @log_level and @set_var directive processing before task check in sequential execution to ensure they are processed correctly.
|
|
35
|
+
|
|
36
|
+
#### NEW
|
|
37
|
+
|
|
38
|
+
- 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
|
|
39
|
+
- Added ScriptComm module to handle bidirectional communication between scripts and Howzit
|
|
40
|
+
- 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
|
|
41
|
+
- Conditional blocks support string comparisons (==, =~ /regex/, *= contains, ^= starts with, $= ends with) and numeric comparisons (==, !=, >, >=, <, <=)
|
|
42
|
+
- Conditions can test against metadata keys, environment variables, positional arguments ($1, $2, etc.), named arguments, and script-set variables
|
|
43
|
+
- Added special condition checks: git dirty/clean, file exists <path>, dir exists <path>, topic exists <name>, and cwd/working directory
|
|
44
|
+
- Conditions support negation with 'not' or '!' prefix
|
|
45
|
+
- Added @elsif directive for alternative conditions in @if/@unless blocks, allowing multiple conditional branches
|
|
46
|
+
- Added @else directive for fallback branches in conditional blocks when all previous conditions are false
|
|
47
|
+
- Conditional blocks now support chaining multiple @elsif statements between @if/@unless and @else
|
|
48
|
+
- @elsif and @else work correctly with nested conditional blocks
|
|
49
|
+
- 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)
|
|
50
|
+
- Added file contents condition that reads file contents and performs string comparisons using any comparison operator (e.g., file contents VERSION.txt ^= 0.)
|
|
51
|
+
- File contents condition supports file paths as variables from metadata, named arguments, or environment variables
|
|
52
|
+
- 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
|
|
53
|
+
- Automatic interpreter detection from hashbang lines in scripts
|
|
54
|
+
- Helper script injection into run blocks based on detected interpreter
|
|
55
|
+
- Support directory installation at ~/.local/share/howzit/support with language-specific helper scripts
|
|
56
|
+
- 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
|
|
57
|
+
- Add @log_level(LEVEL) directive to set log level for subsequent tasks in a topic
|
|
58
|
+
- Add log_level parameter to @run directives (e.g., @run(script.sh, log_level=debug))
|
|
59
|
+
- Add HOWZIT_LOG_LEVEL environment variable support for global log level configuration
|
|
60
|
+
- Add emoji and color indicators for log messages (debug, info, warn, error)
|
|
61
|
+
- Add comprehensive test coverage for sequential conditional evaluation including @if/@unless/@elsif/@else blocks with variables from run blocks
|
|
62
|
+
- Add comprehensive test coverage for log level configuration including @log_level directive, log_level parameter in @run directives, and HOWZIT_LOG_LEVEL environment variable
|
|
63
|
+
- 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.
|
|
64
|
+
- 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.
|
|
65
|
+
- 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.
|
|
66
|
+
- 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.
|
|
67
|
+
|
|
68
|
+
#### IMPROVED
|
|
69
|
+
|
|
70
|
+
- Auto-corrected rubocop style offenses including string literals, redundant self, parentheses, and other correctable issues
|
|
71
|
+
- Fixed Lint/Void issue in buildnote.rb by simplifying conditional logic
|
|
72
|
+
- Cwd and working directory can now be used with string comparison operators (==, =~, *=, ^=, $=) to check the current directory path
|
|
73
|
+
- Conditions now support ${var} syntax in addition to var for consistency with variable substitution syntax
|
|
74
|
+
- 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"
|
|
75
|
+
- 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
|
|
76
|
+
- Log level filtering now properly applies to script-to-howzit communication messages, showing only messages at or above the configured level
|
|
77
|
+
- Conditional blocks (@if/@unless/@elsif/@else) now re-evaluate after each task execution, enabling dynamic conditional flow based on variables set by preceding tasks
|
|
78
|
+
- Improve task directive parsing by refactoring to use unless/next pattern for better code organization and fixing @log_level directive handling
|
|
79
|
+
- Improve Directive#to_task to properly handle title rendering with variable substitution, argument parsing for include tasks, and action escaping for copy tasks
|
|
80
|
+
- 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.
|
|
81
|
+
|
|
82
|
+
#### FIXED
|
|
83
|
+
|
|
84
|
+
- Resolved NameError for 'white' color method by generating escape codes directly from configured_colors hash instead of calling dynamically generated methods
|
|
85
|
+
- Fixed infinite recursion in ConsoleLogger by using $stderr.puts directly instead of calling warn method recursively
|
|
86
|
+
- Color template method now properly respects coloring? setting and returns empty strings when coloring is disabled
|
|
87
|
+
- Resolved test failures caused by Howzit.buildnote caching stale instances by resetting @buildnote in spec_helper before each test
|
|
88
|
+
- Fixed bug where @end statements failed to close conditional blocks when conditions evaluated to false, preventing subsequent conditional blocks from working correctly
|
|
89
|
+
- Fixed issue where named arguments from topic titles were not available when evaluating conditions in conditional blocks
|
|
90
|
+
- Suppressed EPIPE errors that occur when writing to stdout/stderr after pipes are closed, preventing error messages from appearing in terminal output
|
|
91
|
+
- 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
|
|
92
|
+
- Fix clipboard copy test failing due to cached console logger instance not updating when log_level option changes
|
|
93
|
+
- Fixed variable persistence issue in sequential execution where Howzit.named_arguments was being reset on each iteration, causing @set_var variables to be lost.
|
|
94
|
+
- 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.
|
|
95
|
+
|
|
1
96
|
### 2.1.29
|
|
2
97
|
|
|
3
98
|
2026-01-01 06:55
|
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
|
@@ -46,9 +46,15 @@ task :ver do
|
|
|
46
46
|
puts "changelog: #{cver}"
|
|
47
47
|
end
|
|
48
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
|
+
|
|
49
55
|
desc 'Changelog version check'
|
|
50
56
|
task :cver do
|
|
51
|
-
|
|
57
|
+
print IO.read(File.join(File.dirname(__FILE__), 'CHANGELOG.md')).match(/^#+ (\d+\.\d+\.\d+(\w+)?)/)[1]
|
|
52
58
|
end
|
|
53
59
|
|
|
54
60
|
desc 'Run tests in Docker'
|
data/bin/howzit
CHANGED
|
@@ -248,6 +248,11 @@ OptionParser.new do |opts|
|
|
|
248
248
|
Process.exit 0
|
|
249
249
|
end
|
|
250
250
|
|
|
251
|
+
opts.on('--migrate', 'Migrate legacy files from ~/.local/share/howzit to the new config location') do
|
|
252
|
+
Howzit::ScriptSupport.migrate_legacy_support(early_init: false)
|
|
253
|
+
Process.exit 0
|
|
254
|
+
end
|
|
255
|
+
|
|
251
256
|
opts.on('-v', '--version', 'Display version number') do
|
|
252
257
|
puts "#{File.basename(__FILE__)} v#{Howzit::VERSION}"
|
|
253
258
|
Process.exit 0
|
data/lib/howzit/buildnote.rb
CHANGED
|
@@ -21,9 +21,31 @@ module Howzit
|
|
|
21
21
|
content = Util.read_file(file)
|
|
22
22
|
raise "{br}No content found in build note (#{file}){x}".c if content.nil? || content.empty?
|
|
23
23
|
|
|
24
|
+
# Global metadata from config (e.g. ~/.config/howzit/howzit.yml)
|
|
25
|
+
# Expecting something like:
|
|
26
|
+
# metadata:
|
|
27
|
+
# author: Brett Terpstra
|
|
28
|
+
# license: MIT
|
|
29
|
+
global_meta = {}
|
|
30
|
+
raw_global = Howzit.options[:metadata] || Howzit.options['metadata']
|
|
31
|
+
if raw_global.is_a?(Hash)
|
|
32
|
+
raw_global.each do |k, v|
|
|
33
|
+
global_meta[k.to_s.downcase] = v
|
|
34
|
+
end
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
# Metadata defined in the build note itself (before the first heading)
|
|
24
38
|
this_meta = content.split(/^#/)[0].strip.metadata
|
|
25
39
|
|
|
26
|
-
|
|
40
|
+
# Merge order:
|
|
41
|
+
# 1. Global config metadata (lowest precedence)
|
|
42
|
+
# 2. Metadata passed in via meta argument (e.g. templates)
|
|
43
|
+
# 3. Build note metadata (highest precedence)
|
|
44
|
+
combined_meta = global_meta.dup
|
|
45
|
+
combined_meta.merge!(meta) if meta
|
|
46
|
+
combined_meta.merge!(this_meta) if this_meta
|
|
47
|
+
|
|
48
|
+
@metadata = combined_meta
|
|
27
49
|
|
|
28
50
|
read_help(file)
|
|
29
51
|
end
|
data/lib/howzit/config.rb
CHANGED
|
@@ -194,6 +194,19 @@ module Howzit
|
|
|
194
194
|
config = load_config
|
|
195
195
|
load_theme
|
|
196
196
|
@options = flags.merge(config)
|
|
197
|
+
|
|
198
|
+
# Check for HOWZIT_LOG_LEVEL environment variable
|
|
199
|
+
return unless ENV['HOWZIT_LOG_LEVEL']
|
|
200
|
+
|
|
201
|
+
level_str = ENV['HOWZIT_LOG_LEVEL'].downcase
|
|
202
|
+
level_map = {
|
|
203
|
+
'debug' => 0,
|
|
204
|
+
'info' => 1,
|
|
205
|
+
'warn' => 2,
|
|
206
|
+
'warning' => 2,
|
|
207
|
+
'error' => 3
|
|
208
|
+
}
|
|
209
|
+
@options[:log_level] = level_map[level_str] || level_str.to_i
|
|
197
210
|
end
|
|
198
211
|
|
|
199
212
|
##
|
|
@@ -238,6 +251,14 @@ module Howzit
|
|
|
238
251
|
## @param default [Hash] default configuration to write
|
|
239
252
|
##
|
|
240
253
|
def create_config(default)
|
|
254
|
+
# If a legacy ~/.local/share/howzit directory exists, offer to migrate it
|
|
255
|
+
# into the new config root before creating any new files to avoid confusion
|
|
256
|
+
# about where Howzit stores its configuration.
|
|
257
|
+
# Use early_init=true since we're called during config initialization and can't access Howzit.options yet
|
|
258
|
+
if defined?(Howzit::ScriptSupport) && File.directory?(File.expand_path(Howzit::ScriptSupport::LEGACY_SUPPORT_DIR))
|
|
259
|
+
Howzit::ScriptSupport.migrate_legacy_support(early_init: true)
|
|
260
|
+
end
|
|
261
|
+
|
|
241
262
|
unless File.directory?(config_dir)
|
|
242
263
|
Howzit::ConsoleLogger.new(1).info "Creating config directory at #{config_dir}"
|
|
243
264
|
FileUtils.mkdir_p(config_dir)
|
|
@@ -31,6 +31,50 @@ module Howzit
|
|
|
31
31
|
@log_level = Howzit.options[:log_level]
|
|
32
32
|
end
|
|
33
33
|
|
|
34
|
+
##
|
|
35
|
+
## Get emoji for log level
|
|
36
|
+
##
|
|
37
|
+
## @param level [Symbol] The level
|
|
38
|
+
##
|
|
39
|
+
## @return [String] Emoji for the level
|
|
40
|
+
##
|
|
41
|
+
def emoji_for_level(level)
|
|
42
|
+
case level
|
|
43
|
+
when :debug
|
|
44
|
+
'🔍'
|
|
45
|
+
when :info
|
|
46
|
+
'ℹ️'
|
|
47
|
+
when :warn
|
|
48
|
+
'⚠️'
|
|
49
|
+
when :error
|
|
50
|
+
'❌'
|
|
51
|
+
else
|
|
52
|
+
''
|
|
53
|
+
end
|
|
54
|
+
end
|
|
55
|
+
|
|
56
|
+
##
|
|
57
|
+
## Get color prefix for log level
|
|
58
|
+
##
|
|
59
|
+
## @param level [Symbol] The level
|
|
60
|
+
##
|
|
61
|
+
## @return [String] Color template string
|
|
62
|
+
##
|
|
63
|
+
def color_for_level(level)
|
|
64
|
+
case level
|
|
65
|
+
when :debug
|
|
66
|
+
'{d}'
|
|
67
|
+
when :info
|
|
68
|
+
'{c}'
|
|
69
|
+
when :warn
|
|
70
|
+
'{y}'
|
|
71
|
+
when :error
|
|
72
|
+
'{r}'
|
|
73
|
+
else
|
|
74
|
+
''
|
|
75
|
+
end
|
|
76
|
+
end
|
|
77
|
+
|
|
34
78
|
##
|
|
35
79
|
## Write a message to the console based on the urgency
|
|
36
80
|
## level and user's log level setting
|
|
@@ -41,8 +85,16 @@ module Howzit
|
|
|
41
85
|
def write(msg, level = :info)
|
|
42
86
|
return unless LOG_LEVELS[level] >= @log_level
|
|
43
87
|
|
|
88
|
+
emoji = emoji_for_level(level)
|
|
89
|
+
color = color_for_level(level)
|
|
90
|
+
formatted_msg = if emoji && color
|
|
91
|
+
"#{emoji} #{color}#{msg}{x}".c
|
|
92
|
+
else
|
|
93
|
+
msg
|
|
94
|
+
end
|
|
95
|
+
|
|
44
96
|
begin
|
|
45
|
-
$stderr.puts
|
|
97
|
+
$stderr.puts formatted_msg
|
|
46
98
|
rescue Errno::EPIPE
|
|
47
99
|
# Pipe closed, ignore
|
|
48
100
|
end
|
|
@@ -74,8 +126,16 @@ module Howzit
|
|
|
74
126
|
def warn(msg)
|
|
75
127
|
return unless LOG_LEVELS[:warn] >= @log_level
|
|
76
128
|
|
|
129
|
+
emoji = emoji_for_level(:warn)
|
|
130
|
+
color = color_for_level(:warn)
|
|
131
|
+
formatted_msg = if emoji && color
|
|
132
|
+
"#{emoji} #{color}#{msg}{x}".c
|
|
133
|
+
else
|
|
134
|
+
msg
|
|
135
|
+
end
|
|
136
|
+
|
|
77
137
|
begin
|
|
78
|
-
$stderr.puts
|
|
138
|
+
$stderr.puts formatted_msg
|
|
79
139
|
rescue Errno::EPIPE
|
|
80
140
|
# Pipe closed, ignore
|
|
81
141
|
end
|
|
@@ -0,0 +1,137 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require 'shellwords'
|
|
4
|
+
|
|
5
|
+
module Howzit
|
|
6
|
+
# Directive class
|
|
7
|
+
# Represents a parsed directive from topic content (tasks, conditionals, etc.)
|
|
8
|
+
class Directive
|
|
9
|
+
attr_reader :type, :content, :condition, :directive_type, :optional, :default, :line_number, :conditional_path,
|
|
10
|
+
:log_level_value, :var_name, :var_value
|
|
11
|
+
|
|
12
|
+
##
|
|
13
|
+
## Initialize a Directive
|
|
14
|
+
##
|
|
15
|
+
## @param type [Symbol] :task, :if, :unless, :elsif, :else, :end, :log_level
|
|
16
|
+
## @param content [String] The directive content (action, block, etc.)
|
|
17
|
+
## @param condition [String, nil] Condition string for conditionals
|
|
18
|
+
## @param directive_type [String, nil] 'if', 'unless', 'elsif', 'else' for conditionals
|
|
19
|
+
## @param optional [Boolean] Whether task requires confirmation
|
|
20
|
+
## @param default [Boolean] Default response for confirmation
|
|
21
|
+
## @param line_number [Integer] Line number in original content
|
|
22
|
+
## @param conditional_path [Array] Array of conditional indices this directive is nested in
|
|
23
|
+
## @param log_level_value [String, nil] Log level value for @log_level directives
|
|
24
|
+
## @param var_name [String, nil] Variable name for @set_var directives
|
|
25
|
+
## @param var_value [String, nil] Variable value for @set_var directives
|
|
26
|
+
##
|
|
27
|
+
def initialize(type:, content: nil, condition: nil, directive_type: nil, optional: false, default: true,
|
|
28
|
+
line_number: nil, conditional_path: [], log_level_value: nil, var_name: nil, var_value: nil)
|
|
29
|
+
@type = type
|
|
30
|
+
@content = content
|
|
31
|
+
@condition = condition
|
|
32
|
+
@directive_type = directive_type
|
|
33
|
+
@optional = optional
|
|
34
|
+
@default = default
|
|
35
|
+
@line_number = line_number
|
|
36
|
+
@conditional_path = conditional_path || []
|
|
37
|
+
@log_level_value = log_level_value
|
|
38
|
+
@var_name = var_name
|
|
39
|
+
@var_value = var_value
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
##
|
|
43
|
+
## Is this a conditional directive?
|
|
44
|
+
##
|
|
45
|
+
def conditional?
|
|
46
|
+
%i[if unless elsif else end].include?(@type)
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
##
|
|
50
|
+
## Is this a task directive?
|
|
51
|
+
##
|
|
52
|
+
def task?
|
|
53
|
+
@type == :task
|
|
54
|
+
end
|
|
55
|
+
|
|
56
|
+
##
|
|
57
|
+
## Is this a log_level directive?
|
|
58
|
+
##
|
|
59
|
+
def log_level?
|
|
60
|
+
@type == :log_level
|
|
61
|
+
end
|
|
62
|
+
|
|
63
|
+
##
|
|
64
|
+
## Is this a set_var directive?
|
|
65
|
+
##
|
|
66
|
+
def set_var?
|
|
67
|
+
@type == :set_var
|
|
68
|
+
end
|
|
69
|
+
|
|
70
|
+
##
|
|
71
|
+
## Convert directive to a Task object (only works for task directives)
|
|
72
|
+
##
|
|
73
|
+
## @param parent [Topic] The parent topic
|
|
74
|
+
## @param current_log_level [String, nil] Current log level to apply to task
|
|
75
|
+
##
|
|
76
|
+
## @return [Task] Task object
|
|
77
|
+
##
|
|
78
|
+
def to_task(parent, current_log_level: nil)
|
|
79
|
+
return nil unless task?
|
|
80
|
+
|
|
81
|
+
task_data = @content.dup
|
|
82
|
+
task_type = task_data[:type]
|
|
83
|
+
|
|
84
|
+
# Apply current log level if set and task doesn't have its own
|
|
85
|
+
task_data[:log_level] = current_log_level if current_log_level && !task_data[:log_level]
|
|
86
|
+
|
|
87
|
+
# Set named_arguments before processing titles for variable substitution
|
|
88
|
+
Howzit.named_arguments = parent.named_args
|
|
89
|
+
|
|
90
|
+
case task_type
|
|
91
|
+
when :block
|
|
92
|
+
# Block tasks are already properly formatted
|
|
93
|
+
task_data[:parent] = parent
|
|
94
|
+
Howzit::Task.new(task_data, optional: @optional, default: @default)
|
|
95
|
+
when :run
|
|
96
|
+
# Run tasks need title rendering (similar to define_task_args)
|
|
97
|
+
title = task_data[:title]
|
|
98
|
+
title = title.render_arguments if title && !title.empty?
|
|
99
|
+
task_data[:title] = title
|
|
100
|
+
task_data[:parent] = parent
|
|
101
|
+
Howzit::Task.new(task_data, optional: @optional, default: @default)
|
|
102
|
+
when :copy
|
|
103
|
+
# Copy tasks need title rendering and action escaping
|
|
104
|
+
title = task_data[:title]
|
|
105
|
+
title = title.render_arguments if title && !title.empty?
|
|
106
|
+
task_data[:title] = title
|
|
107
|
+
task_data[:action] = Shellwords.escape(task_data[:action])
|
|
108
|
+
task_data[:parent] = parent
|
|
109
|
+
Howzit::Task.new(task_data, optional: @optional, default: @default)
|
|
110
|
+
when :open
|
|
111
|
+
# Open tasks need title rendering
|
|
112
|
+
title = task_data[:title]
|
|
113
|
+
title = title.render_arguments if title && !title.empty?
|
|
114
|
+
task_data[:title] = title
|
|
115
|
+
task_data[:parent] = parent
|
|
116
|
+
Howzit::Task.new(task_data, optional: @optional, default: @default)
|
|
117
|
+
when :include
|
|
118
|
+
# Include tasks need special handling (title processing, arguments, etc.)
|
|
119
|
+
title = task_data[:title]
|
|
120
|
+
if title =~ /\[(.*?)\] *$/
|
|
121
|
+
args = Regexp.last_match(1).split(/ *, */).map(&:render_arguments)
|
|
122
|
+
Howzit.arguments = args
|
|
123
|
+
parent.arguments
|
|
124
|
+
title.sub!(/ *\[.*?\] *$/, '')
|
|
125
|
+
end
|
|
126
|
+
title = title.render_arguments if title && !title.empty?
|
|
127
|
+
task_data[:title] = title
|
|
128
|
+
task_data[:parent] = parent
|
|
129
|
+
task_data[:arguments] = Howzit.named_arguments
|
|
130
|
+
Howzit::Task.new(task_data, optional: @optional, default: @default)
|
|
131
|
+
else
|
|
132
|
+
task_data[:parent] = parent
|
|
133
|
+
Howzit::Task.new(task_data, optional: @optional, default: @default)
|
|
134
|
+
end
|
|
135
|
+
end
|
|
136
|
+
end
|
|
137
|
+
end
|