howzit 2.1.48 → 2.1.49
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 +14 -0
- data/README.md +1 -1
- data/bin/howzit +1 -1
- data/lib/howzit/topic.rb +41 -3
- data/lib/howzit/util.rb +41 -22
- data/lib/howzit/version.rb +1 -1
- data/spec/topic_spec.rb +30 -0
- data/spec/util_spec.rb +40 -0
- data/src/_README.md +1 -1
- metadata +1 -1
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 91e3e382d6e58e8a3a50cb663de149af066ee02b80bafcdbf6db5d68c79426af
|
|
4
|
+
data.tar.gz: ebaf51a69ba374ba5fa64a548560cfa0b8e03f70b85a77de3a1f43aa94baf944
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 96e353abbe3fec9eb5cce2c1fcbbdc45d425394594f394251dc2719937ba69a2acbf87e7d3ccae437baf25b33c400ef0ddf7c01cd42765cc4f39009968f703cf
|
|
7
|
+
data.tar.gz: 48c8b7253abbd0adfe88a0b5ccb1108684db73252c87823ef29aa59507feefd814bc689831585255e73624136f55cd39ee0797ab84666c49dc3a56107b76fa31
|
data/CHANGELOG.md
CHANGED
|
@@ -1,3 +1,17 @@
|
|
|
1
|
+
### 2.1.49
|
|
2
|
+
|
|
3
|
+
2026-10-21 05:15
|
|
4
|
+
|
|
5
|
+
#### CHANGED
|
|
6
|
+
|
|
7
|
+
- **Markdown highlighting** tries `apex` first when `:highlighter:` is `auto`, then mdcat, then mdless. mdless is still installed with the gem
|
|
8
|
+
- **Directives inside a code fence** are shown as code instead of being turned into tasks
|
|
9
|
+
|
|
10
|
+
#### FIXED
|
|
11
|
+
|
|
12
|
+
- **Apex output** uses `-t terminal256 --no-paginate`, including when `:highlighter:` is set to `apex` alone, so topics render as terminal color instead of HTML
|
|
13
|
+
- **Placeholders inside fenced code** are left as written, so a syntax highlighter such as Pygments does not print howzit's color codes as text like `[1m`
|
|
14
|
+
|
|
1
15
|
### 2.1.48
|
|
2
16
|
|
|
3
17
|
2026-10-09 07:20
|
data/README.md
CHANGED
|
@@ -37,7 +37,7 @@ Howzit is a tool that allows you to keep Markdown-formatted notes about a projec
|
|
|
37
37
|
- Ruby 2.4+ (It probably works on older Rubys, but is untested prior to 2.4.1.)
|
|
38
38
|
- Optional: if [`fzf`](https://github.com/junegunn/fzf) is available, it will be used for handling multiple choice selections
|
|
39
39
|
- Optional: if [`bat`](https://github.com/sharkdp/bat) is available it will page with that
|
|
40
|
-
- Optional: [`
|
|
40
|
+
- Optional: [`apex`](https://github.com/ApexMarkdown/apex) is preferred for formatting output when it is installed. Otherwise howzit uses [`mdcat`](https://github.com/lunaryorn/mdcat) or [`mdless`](https://github.com/ttscoff/mdless). mdless is installed with the howzit gem.
|
|
41
41
|
|
|
42
42
|
### Installing
|
|
43
43
|
|
data/bin/howzit
CHANGED
|
@@ -210,7 +210,7 @@ OptionParser.new do |opts|
|
|
|
210
210
|
Howzit.options[:header_format] = t
|
|
211
211
|
end
|
|
212
212
|
|
|
213
|
-
opts.on('--[no-]md-highlight', 'Highlight Markdown syntax (default on),
|
|
213
|
+
opts.on('--[no-]md-highlight', 'Highlight Markdown syntax (default on), prefers apex, then mdcat or mdless') do |m|
|
|
214
214
|
Howzit.options[:highlight] = Howzit.options[:color] ? m : false
|
|
215
215
|
end
|
|
216
216
|
|
data/lib/howzit/topic.rb
CHANGED
|
@@ -493,7 +493,18 @@ module Howzit
|
|
|
493
493
|
topic.gsub!(/(?mix)^(`{3,})run([?!]*)\s*
|
|
494
494
|
([^\n]*)[\s\S]*?\n\1\s*$/, '@@@run\2 \3')
|
|
495
495
|
end
|
|
496
|
+
in_fence = false
|
|
497
|
+
fence_char = nil
|
|
498
|
+
fence_len = 0
|
|
496
499
|
topic.split(/\n/).each do |l|
|
|
500
|
+
# Fenced code is passed through unchanged. Howzit color codes inside a
|
|
501
|
+
# fence get mangled by the syntax highlighter Apex shells out to.
|
|
502
|
+
if in_fence
|
|
503
|
+
output.push(l)
|
|
504
|
+
in_fence = false if closing_fence?(l, fence_char, fence_len)
|
|
505
|
+
next
|
|
506
|
+
end
|
|
507
|
+
|
|
497
508
|
case l
|
|
498
509
|
when /@(before|after|prereq|end|if|unless)/
|
|
499
510
|
next
|
|
@@ -504,12 +515,22 @@ module Howzit
|
|
|
504
515
|
when /(?<fence>`{3,})run(?<optional>[!?]{1,2})? *(?<title>.*?)$/i
|
|
505
516
|
desc = title_code_block(Regexp.last_match.named_captures.symbolize_keys)
|
|
506
517
|
output.push("{bmK}\u{25B6} {bwK}#{desc}{x}\n```".c)
|
|
518
|
+
fence_char = '`'
|
|
519
|
+
fence_len = Regexp.last_match[:fence].length
|
|
520
|
+
in_fence = true
|
|
507
521
|
when /@@@run(?<optional>[!?]{1,2})? *(?<title>.*?)$/i
|
|
508
522
|
output.push("{bmK}\u{25B6} {bwK}#{title_code_block(Regexp.last_match.named_captures.symbolize_keys)}{x}".c)
|
|
509
523
|
else
|
|
510
|
-
l
|
|
511
|
-
|
|
512
|
-
|
|
524
|
+
opened = opening_fence(l)
|
|
525
|
+
if opened
|
|
526
|
+
fence_char, fence_len = opened
|
|
527
|
+
in_fence = true
|
|
528
|
+
output.push(l)
|
|
529
|
+
else
|
|
530
|
+
l.wrap!(Howzit.options[:wrap]) if Howzit.options[:wrap].positive?
|
|
531
|
+
# Highlight variable placeholders in content
|
|
532
|
+
output.push(highlight_variables(l))
|
|
533
|
+
end
|
|
513
534
|
end
|
|
514
535
|
end
|
|
515
536
|
Howzit.named_arguments = @named_args
|
|
@@ -620,6 +641,23 @@ module Howzit
|
|
|
620
641
|
|
|
621
642
|
private
|
|
622
643
|
|
|
644
|
+
##
|
|
645
|
+
## A markdown opening fence (` ``` ` or `~~~`, up to three spaces of indent)
|
|
646
|
+
##
|
|
647
|
+
## @return [Array(String, Integer), nil] fence character and length
|
|
648
|
+
##
|
|
649
|
+
def opening_fence(line)
|
|
650
|
+
match = line.match(/\A {0,3}(?<marker>`{3,}|~{3,})/)
|
|
651
|
+
return unless match
|
|
652
|
+
|
|
653
|
+
marker = match[:marker]
|
|
654
|
+
[marker[0], marker.length]
|
|
655
|
+
end
|
|
656
|
+
|
|
657
|
+
def closing_fence?(line, char, length)
|
|
658
|
+
line.match?(/\A {0,3}#{Regexp.escape(char)}{#{length},}[ \t]*\z/)
|
|
659
|
+
end
|
|
660
|
+
|
|
623
661
|
def run_topic(nested:, as_subtopic:)
|
|
624
662
|
@results = { total: 0, success: 0, errors: 0, message: ''.c }
|
|
625
663
|
output = []
|
data/lib/howzit/util.rb
CHANGED
|
@@ -50,31 +50,50 @@ module Howzit
|
|
|
50
50
|
end
|
|
51
51
|
end
|
|
52
52
|
|
|
53
|
-
#
|
|
54
|
-
#
|
|
53
|
+
# Prefer apex, then mdcat, then mdless. mdless ships with the gem,
|
|
54
|
+
# so highlighting still works when apex is not installed.
|
|
55
55
|
def which_highlighter
|
|
56
|
-
if Howzit.options[:highlighter] =~ /auto/i
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
56
|
+
command = if Howzit.options[:highlighter] =~ /auto/i
|
|
57
|
+
auto_highlighter
|
|
58
|
+
else
|
|
59
|
+
configured_highlighter
|
|
60
|
+
end
|
|
61
|
+
apex_command(command)
|
|
62
|
+
end
|
|
60
63
|
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
64
|
+
# Apex defaults to HTML. Howzit always wants terminal escapes, and it
|
|
65
|
+
# pages the result itself, so add those flags unless the command
|
|
66
|
+
# already sets a format or a pagination option. This covers both
|
|
67
|
+
# auto and an explicit `:highlighter: apex`.
|
|
68
|
+
def apex_command(command)
|
|
69
|
+
return command if command.nil? || command.empty?
|
|
70
|
+
return command unless command.split.first == 'apex'
|
|
66
71
|
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
72
|
+
args = command.split[1..]
|
|
73
|
+
has_format = args.any? { |arg| ['-t', '--to'].include?(arg) || arg.start_with?('--to=') }
|
|
74
|
+
args.push('-t', 'terminal256') unless has_format
|
|
75
|
+
has_pager = args.any? { |arg| ['--no-paginate', '--paginate', '-p'].include?(arg) }
|
|
76
|
+
args << '--no-paginate' unless has_pager
|
|
77
|
+
['apex', *args].join(' ')
|
|
78
|
+
end
|
|
79
|
+
|
|
80
|
+
def auto_highlighter
|
|
81
|
+
highlighters = %w[apex mdcat mdless]
|
|
82
|
+
highlighters.delete_if(&:nil?).select!(&:available?)
|
|
83
|
+
return nil if highlighters.empty?
|
|
84
|
+
|
|
85
|
+
hl = highlighters.first
|
|
86
|
+
args = '--no-pager' if hl == 'mdless'
|
|
87
|
+
[hl, args].compact.join(' ')
|
|
88
|
+
end
|
|
89
|
+
|
|
90
|
+
def configured_highlighter
|
|
91
|
+
hl = Howzit.options[:highlighter].split(/ /)[0]
|
|
92
|
+
return Howzit.options[:highlighter] if hl.available?
|
|
93
|
+
|
|
94
|
+
Howzit.console.error Color.template("{Rw}Error:{xbw} Specified highlighter (#{Howzit.options[:highlighter]}) not found, switching to auto")
|
|
95
|
+
Howzit.options[:highlighter] = 'auto'
|
|
96
|
+
auto_highlighter
|
|
78
97
|
end
|
|
79
98
|
|
|
80
99
|
# When pagination is enabled, find the best (in my opinion) option,
|
data/lib/howzit/version.rb
CHANGED
data/spec/topic_spec.rb
CHANGED
|
@@ -103,6 +103,36 @@ describe Howzit::Topic do
|
|
|
103
103
|
Howzit.options[:show_all_code] = true
|
|
104
104
|
expect(topic.print_out({ single: true, header: true }).join("\n").uncolor).to match(/▶ ls -1/)
|
|
105
105
|
end
|
|
106
|
+
|
|
107
|
+
it 'leaves placeholders inside fenced code for the syntax highlighter' do
|
|
108
|
+
Howzit::Color.coloring = true
|
|
109
|
+
Howzit.options[:show_all_code] = true
|
|
110
|
+
note = Howzit::Topic.new('Widgets', <<~MD)
|
|
111
|
+
We set ${TEST_VAR} in a script block
|
|
112
|
+
|
|
113
|
+
```bash
|
|
114
|
+
echo "${TEST_VAR}"
|
|
115
|
+
@run(ls) shown as code
|
|
116
|
+
```
|
|
117
|
+
|
|
118
|
+
```run Full capture script
|
|
119
|
+
if [[ -n ${only} ]]
|
|
120
|
+
```
|
|
121
|
+
MD
|
|
122
|
+
|
|
123
|
+
lines = note.print_out({ single: true, header: false })
|
|
124
|
+
prose = lines.find { |line| line.include?('We set') }
|
|
125
|
+
echo_line = lines.find { |line| line.include?('echo') }
|
|
126
|
+
directive = lines.find { |line| line.include?('@run') }
|
|
127
|
+
condition = lines.find { |line| line.include?('only') }
|
|
128
|
+
|
|
129
|
+
expect(prose).to include("\e[")
|
|
130
|
+
expect(echo_line).to eq('echo "${TEST_VAR}"')
|
|
131
|
+
expect(directive).to eq('@run(ls) shown as code')
|
|
132
|
+
expect(condition).to eq('if [[ -n ${only} ]]')
|
|
133
|
+
ensure
|
|
134
|
+
Howzit::Color.coloring = false
|
|
135
|
+
end
|
|
106
136
|
end
|
|
107
137
|
|
|
108
138
|
describe '.arguments' do
|
data/spec/util_spec.rb
CHANGED
|
@@ -23,10 +23,50 @@ describe Howzit::Util do
|
|
|
23
23
|
end
|
|
24
24
|
|
|
25
25
|
describe '.which_highlighter' do
|
|
26
|
+
after { Howzit.options[:highlighter] = 'auto' }
|
|
27
|
+
|
|
26
28
|
it 'finds mdless' do
|
|
27
29
|
Howzit.options[:highlighter] = 'mdless'
|
|
28
30
|
expect(util.which_highlighter).to eq 'mdless'
|
|
29
31
|
end
|
|
32
|
+
|
|
33
|
+
it 'prefers apex with terminal256 output and pagination disabled' do
|
|
34
|
+
Howzit.options[:highlighter] = 'auto'
|
|
35
|
+
allow(util).to receive(:command_exist?).and_return(false)
|
|
36
|
+
allow(util).to receive(:command_exist?).with('apex').and_return(true)
|
|
37
|
+
|
|
38
|
+
expect(util.which_highlighter).to eq 'apex -t terminal256 --no-paginate'
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
it 'uses mdcat when apex is not installed' do
|
|
42
|
+
Howzit.options[:highlighter] = 'auto'
|
|
43
|
+
allow(util).to receive(:command_exist?).and_return(false)
|
|
44
|
+
allow(util).to receive(:command_exist?).with('mdcat').and_return(true)
|
|
45
|
+
|
|
46
|
+
expect(util.which_highlighter).to eq 'mdcat'
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
it 'uses mdless without its pager when apex and mdcat are not installed' do
|
|
50
|
+
Howzit.options[:highlighter] = 'auto'
|
|
51
|
+
allow(util).to receive(:command_exist?).and_return(false)
|
|
52
|
+
allow(util).to receive(:command_exist?).with('mdless').and_return(true)
|
|
53
|
+
|
|
54
|
+
expect(util.which_highlighter).to eq 'mdless --no-pager'
|
|
55
|
+
end
|
|
56
|
+
|
|
57
|
+
it 'adds terminal256 output when the highlighter is set to apex' do
|
|
58
|
+
Howzit.options[:highlighter] = 'apex'
|
|
59
|
+
allow(util).to receive(:command_exist?).with('apex').and_return(true)
|
|
60
|
+
|
|
61
|
+
expect(util.which_highlighter).to eq 'apex -t terminal256 --no-paginate'
|
|
62
|
+
end
|
|
63
|
+
|
|
64
|
+
it 'keeps an explicit apex output format' do
|
|
65
|
+
Howzit.options[:highlighter] = 'apex -t html'
|
|
66
|
+
allow(util).to receive(:command_exist?).with('apex').and_return(true)
|
|
67
|
+
|
|
68
|
+
expect(util.which_highlighter).to eq 'apex -t html --no-paginate'
|
|
69
|
+
end
|
|
30
70
|
end
|
|
31
71
|
|
|
32
72
|
describe '.which_pager' do
|
data/src/_README.md
CHANGED
|
@@ -37,7 +37,7 @@ Howzit is a tool that allows you to keep Markdown-formatted notes about a projec
|
|
|
37
37
|
- Ruby 2.4+ (It probably works on older Rubys, but is untested prior to 2.4.1.)
|
|
38
38
|
- Optional: if [`fzf`](https://github.com/junegunn/fzf) is available, it will be used for handling multiple choice selections
|
|
39
39
|
- Optional: if [`bat`](https://github.com/sharkdp/bat) is available it will page with that
|
|
40
|
-
- Optional: [`
|
|
40
|
+
- Optional: [`apex`](https://github.com/ApexMarkdown/apex) is preferred for formatting output when it is installed. Otherwise howzit uses [`mdcat`](https://github.com/lunaryorn/mdcat) or [`mdless`](https://github.com/ttscoff/mdless). mdless is installed with the howzit gem.
|
|
41
41
|
|
|
42
42
|
### Installing
|
|
43
43
|
|