mdless 0.0.14 → 0.0.15
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/README.md +52 -4
- data/lib/mdless/colors.rb +59 -55
- data/lib/mdless/converter.rb +321 -70
- data/lib/mdless/version.rb +1 -1
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 350da3408205b06f5ef3b792190c11f0a1f2a22139f40472da1922486f2b1358
|
4
|
+
data.tar.gz: aad6fe5044525feab00af45cd757c1f5d5b1f3478a429db681a1bf86d9ea863e
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 1a5a65f8caf5a8c62b3c0e2ba7a712df1d6d1ce1948e90e76c0ee599833f9b4844683c3d6d86874cb477b9ca307ec7f5b75339e26c7696117ac564ddd99b5cef
|
7
|
+
data.tar.gz: 9038fbdc4b9e161b6531af8ad59bbc9707f3eab158818e9b0b15b9434fd388f716d9e11602d8bfc15a8cbdbabe14efe462081a8d90ff41f3543106d924d07dc1
|
data/README.md
CHANGED
@@ -1,7 +1,6 @@
|
|
1
1
|
|
2
2
|
# mdless
|
3
3
|
|
4
|
-
|
5
4
|
`mdless` is a utility that provides a formatted and highlighted view of Markdown files in Terminal.
|
6
5
|
|
7
6
|
I often use iTerm2 in visor mode, so `qlmanage -p` is annoying. I still wanted a way to view Markdown files quickly and without cruft.
|
@@ -16,9 +15,12 @@ I often use iTerm2 in visor mode, so `qlmanage -p` is annoying. I still wanted a
|
|
16
15
|
- Normalize spacing and link formatting
|
17
16
|
- Display footnotes after each paragraph
|
18
17
|
- Inline image display (local, optionally remote) if using iTerm2 2.9+
|
19
|
-
- Syntax highlighting when
|
18
|
+
- Syntax highlighting when [Pygments](http://pygments.org/) is installed
|
19
|
+
- Only fenced code with a language defined (e.g. `\`\`\`python`) will be highlighted
|
20
|
+
- Languages can also be determined by hashbang in the code block
|
20
21
|
- List headlines in document
|
21
|
-
- Display single section of the document based on headlines
|
22
|
+
- Display single section of the document based on headlines
|
23
|
+
- Customizable colors
|
22
24
|
|
23
25
|
## Installation
|
24
26
|
|
@@ -40,7 +42,7 @@ The pager used is determined by system configuration in this order of preference
|
|
40
42
|
|
41
43
|
### Options
|
42
44
|
|
43
|
-
-s, --section=
|
45
|
+
-s, --section=NUMBER Output only a headline-based section of
|
44
46
|
the input (numeric based on --list output)
|
45
47
|
-w, --width=COLUMNS Column width to format for (default terminal width)
|
46
48
|
-p, --[no-]pager Formatted output to pager (default on)
|
@@ -54,5 +56,51 @@ The pager used is determined by system configuration in this order of preference
|
|
54
56
|
-h, --help Display this screen
|
55
57
|
-v, --version Display version number
|
56
58
|
|
59
|
+
## Customization
|
60
|
+
|
61
|
+
On first run a default theme file will be placed in `~/.config/mdless/mdless.theme`. You can edit this file to modify the colors mdless uses when highlighting your files.
|
62
|
+
|
63
|
+
Colors are limited to basic ANSI codes, with support for bold, underline, italics (if available for the terminal/font), dark and bright, and foreground and background colors.
|
64
|
+
|
65
|
+
Customizeable settings are stored in [YAML](https://yaml.org) format. A chunk of the settings file looks like this:
|
66
|
+
|
67
|
+
```yaml
|
68
|
+
h1:
|
69
|
+
color: b intense_black on_white
|
70
|
+
pad: d black on_white
|
71
|
+
pad_char: "="
|
72
|
+
```
|
73
|
+
|
74
|
+
Font and color settings are set using a string of color names and modifiers. A typical string looks like `b red on_white`, which would give you a bold red font on a white background. In the YAML settings file there's no need for quotes, just put the string following the colon for the setting.
|
75
|
+
|
76
|
+
Some extra (non-color) settings are available for certain keys, e.g. `pad_char` to define the right padding character used on level 1 and 2 headlines. Note that you can change the [Pygments](http://pygments.org/) theme used for syntax highlighting with the code_block.pygments_theme setting. For a list of available styles (assuming you have Pygments installed), use `pygmentize -L styles`.
|
77
|
+
|
78
|
+
*Note:* the ANSI escape codes are reset every time the color changes, so, for example, if you have a key that defines underlines for the url in a link, the underline will automatically be removed when it gets to a bracket. This also means that if you define a background color, you'll need to define it again on all the keys that it should affect.
|
79
|
+
|
80
|
+
Base colors:
|
81
|
+
|
82
|
+
- black
|
83
|
+
- red
|
84
|
+
- green
|
85
|
+
- yellow
|
86
|
+
- blue
|
87
|
+
- magenta
|
88
|
+
- cyan
|
89
|
+
- white
|
90
|
+
|
91
|
+
Emphasis:
|
92
|
+
|
93
|
+
- b (bold)
|
94
|
+
- d (dark)
|
95
|
+
- i (italic)
|
96
|
+
- u (underline)
|
97
|
+
- r (reverse, negative)
|
98
|
+
|
99
|
+
To modify the emphasis, use 'b' (bold), 'i' (italic), 'u' (underline), e.g. `u yellow` for underlined yellow. These can be combined, e.g. `b u red`.
|
100
|
+
|
101
|
+
Use 'r' to reverse foreground and background colors. `r white on_black` would display as `black on_white`. 'r' alone will reverse the current color set for a line.
|
102
|
+
|
103
|
+
To set a background color, use `on_[color]` with one of the 8 colors. This can be used with foreground colors in the same setting, e.g. `white on_black`.
|
57
104
|
|
105
|
+
Use 'd' (dark) to indicate the darker version of a foreground color. On macOS (and possibly other systems) you can use the brighter version of a color by prefixing with "intense", e.g. `intense_red` or `on_intense_black`.
|
58
106
|
|
data/lib/mdless/colors.rb
CHANGED
@@ -1,12 +1,66 @@
|
|
1
1
|
module CLIMarkdown
|
2
2
|
module Colors
|
3
3
|
|
4
|
+
COLORS = {
|
5
|
+
:reset => 0, # synonym for :clear
|
6
|
+
:x => 0,
|
7
|
+
:bold => 1,
|
8
|
+
:b => 1,
|
9
|
+
:dark => 2,
|
10
|
+
:d => 2,
|
11
|
+
:italic => 3, # not widely implemented
|
12
|
+
:i => 3,
|
13
|
+
:underline => 4,
|
14
|
+
:underscore => 4, # synonym for :underline
|
15
|
+
:u => 4,
|
16
|
+
:blink => 5,
|
17
|
+
:rapid_blink => 6, # not widely implemented
|
18
|
+
:negative => 7, # no reverse because of String#reverse
|
19
|
+
:r => 7,
|
20
|
+
:concealed => 8,
|
21
|
+
:strikethrough => 9, # not widely implemented
|
22
|
+
:black => 30,
|
23
|
+
:red => 31,
|
24
|
+
:green => 32,
|
25
|
+
:yellow => 33,
|
26
|
+
:blue => 34,
|
27
|
+
:magenta => 35,
|
28
|
+
:cyan => 36,
|
29
|
+
:white => 37,
|
30
|
+
:on_black => 40,
|
31
|
+
:on_red => 41,
|
32
|
+
:on_green => 42,
|
33
|
+
:on_yellow => 43,
|
34
|
+
:on_blue => 44,
|
35
|
+
:on_magenta => 45,
|
36
|
+
:on_cyan => 46,
|
37
|
+
:on_white => 47,
|
38
|
+
:intense_black => 90, # High intensity, aixterm (works in OS X)
|
39
|
+
:intense_red => 91,
|
40
|
+
:intense_green => 92,
|
41
|
+
:intense_yellow => 93,
|
42
|
+
:intense_blue => 94,
|
43
|
+
:intense_magenta => 95,
|
44
|
+
:intense_cyan => 96,
|
45
|
+
:intense_white => 97,
|
46
|
+
:on_intense_black => 100, # High intensity background, aixterm (works in OS X)
|
47
|
+
:on_intense_red => 101,
|
48
|
+
:on_intense_green => 102,
|
49
|
+
:on_intense_yellow => 103,
|
50
|
+
:on_intense_blue => 104,
|
51
|
+
:on_intense_magenta => 105,
|
52
|
+
:on_intense_cyan => 106,
|
53
|
+
:on_intense_white => 107
|
54
|
+
}
|
55
|
+
|
4
56
|
def uncolor
|
5
57
|
self.gsub(/\e\[[\d;]+m/,'')
|
6
58
|
end
|
7
59
|
|
8
|
-
def blackout
|
9
|
-
|
60
|
+
def blackout(bgcolor)
|
61
|
+
key = bgcolor.to_sym
|
62
|
+
bg = COLORS.key?(key) ? COLORS[key] : 40
|
63
|
+
self.gsub(/(^|$)/,"\e[#{bg}m").gsub(/3([89])m/,"#{bg};3\\1m")
|
10
64
|
end
|
11
65
|
|
12
66
|
def uncolor!
|
@@ -54,63 +108,13 @@ module CLIMarkdown
|
|
54
108
|
|
55
109
|
def c(args)
|
56
110
|
|
57
|
-
|
58
|
-
:reset => 0, # synonym for :clear
|
59
|
-
:x => 0,
|
60
|
-
:bold => 1,
|
61
|
-
:b => 1,
|
62
|
-
:dark => 2,
|
63
|
-
:d => 2,
|
64
|
-
:italic => 3, # not widely implemented
|
65
|
-
:i => 3,
|
66
|
-
:underline => 4,
|
67
|
-
:underscore => 4, # synonym for :underline
|
68
|
-
:u => 4,
|
69
|
-
:blink => 5,
|
70
|
-
:rapid_blink => 6, # not widely implemented
|
71
|
-
:negative => 7, # no reverse because of String#reverse
|
72
|
-
:r => 7,
|
73
|
-
:concealed => 8,
|
74
|
-
:strikethrough => 9, # not widely implemented
|
75
|
-
:black => 30,
|
76
|
-
:red => 31,
|
77
|
-
:green => 32,
|
78
|
-
:yellow => 33,
|
79
|
-
:blue => 34,
|
80
|
-
:magenta => 35,
|
81
|
-
:cyan => 36,
|
82
|
-
:white => 37,
|
83
|
-
:on_black => 40,
|
84
|
-
:on_red => 41,
|
85
|
-
:on_green => 42,
|
86
|
-
:on_yellow => 43,
|
87
|
-
:on_blue => 44,
|
88
|
-
:on_magenta => 45,
|
89
|
-
:on_cyan => 46,
|
90
|
-
:on_white => 47,
|
91
|
-
:intense_black => 90, # High intensity, aixterm (works in OS X)
|
92
|
-
:intense_red => 91,
|
93
|
-
:intense_green => 92,
|
94
|
-
:intense_yellow => 93,
|
95
|
-
:intense_blue => 94,
|
96
|
-
:intense_magenta => 95,
|
97
|
-
:intense_cyan => 96,
|
98
|
-
:intense_white => 97,
|
99
|
-
:on_intense_black => 100, # High intensity background, aixterm (works in OS X)
|
100
|
-
:on_intense_red => 101,
|
101
|
-
:on_intense_green => 102,
|
102
|
-
:on_intense_yellow => 103,
|
103
|
-
:on_intense_blue => 104,
|
104
|
-
:on_intense_magenta => 105,
|
105
|
-
:on_intense_cyan => 106,
|
106
|
-
:on_intense_white => 107
|
107
|
-
}
|
111
|
+
|
108
112
|
|
109
113
|
out = []
|
110
114
|
|
111
115
|
args.each {|arg|
|
112
|
-
if
|
113
|
-
out <<
|
116
|
+
if COLORS.key? arg
|
117
|
+
out << COLORS[arg]
|
114
118
|
end
|
115
119
|
}
|
116
120
|
|
data/lib/mdless/converter.rb
CHANGED
@@ -1,3 +1,13 @@
|
|
1
|
+
require 'fileutils'
|
2
|
+
require 'yaml'
|
3
|
+
|
4
|
+
class ::Hash
|
5
|
+
def deep_merge(second)
|
6
|
+
merger = proc { |key, v1, v2| Hash === v1 && Hash === v2 ? v1.merge(v2, &merger) : Array === v1 && Array === v2 ? v1 | v2 : [:undefined, nil, :nil].include?(v2) ? v1 : v2 }
|
7
|
+
self.merge(second.to_h, &merger)
|
8
|
+
end
|
9
|
+
end
|
10
|
+
|
1
11
|
module CLIMarkdown
|
2
12
|
class Converter
|
3
13
|
include Colors
|
@@ -12,12 +22,119 @@ module CLIMarkdown
|
|
12
22
|
@log = Logger.new(STDERR)
|
13
23
|
@log.level = Logger::ERROR
|
14
24
|
|
25
|
+
config_dir = File.expand_path('~/.config/mdless')
|
26
|
+
theme_file = File.join(config_dir,'mdless.theme')
|
27
|
+
|
28
|
+
theme_defaults = {
|
29
|
+
'metadata' => {
|
30
|
+
'border' => 'd blue on_black',
|
31
|
+
'marker' => 'd black on_black',
|
32
|
+
'color' => 'd white on_black'
|
33
|
+
},
|
34
|
+
'h1' => {
|
35
|
+
'color' => 'b intense_black on_white',
|
36
|
+
'pad' => 'd black on_white',
|
37
|
+
'pad_char' => '='
|
38
|
+
},
|
39
|
+
'h2' => {
|
40
|
+
'color' => 'b white on_intense_black',
|
41
|
+
'pad' => 'd white on_intense_black',
|
42
|
+
'pad_char' => '-'
|
43
|
+
},
|
44
|
+
'h3' => {
|
45
|
+
'color' => 'u b yellow'
|
46
|
+
},
|
47
|
+
'h4' => {
|
48
|
+
'color' => 'u yellow'
|
49
|
+
},
|
50
|
+
'h5' => {
|
51
|
+
'color' => 'b white'
|
52
|
+
},
|
53
|
+
'h6' => {
|
54
|
+
'color' => 'b white'
|
55
|
+
},
|
56
|
+
'link' => {
|
57
|
+
'brackets' => 'b black',
|
58
|
+
'text' => 'u b blue',
|
59
|
+
'url' => 'cyan'
|
60
|
+
},
|
61
|
+
'image' => {
|
62
|
+
'bang' => 'red',
|
63
|
+
'brackets' => 'b black',
|
64
|
+
'title' => 'cyan',
|
65
|
+
'url' => 'u yellow'
|
66
|
+
},
|
67
|
+
'list' => {
|
68
|
+
'bullet' => 'b intense_red',
|
69
|
+
'number' => 'b intense_blue',
|
70
|
+
'color' => 'intense_white'
|
71
|
+
},
|
72
|
+
'footnote' => {
|
73
|
+
'brackets' => 'b black on_black',
|
74
|
+
'caret' => 'b yellow on_black',
|
75
|
+
'title' => 'x yellow on_black',
|
76
|
+
'note' => 'u white on_black'
|
77
|
+
},
|
78
|
+
'code_span' => {
|
79
|
+
'marker' => 'b white',
|
80
|
+
'color' => 'b black on_intense_blue'
|
81
|
+
},
|
82
|
+
'code_block' => {
|
83
|
+
'marker' => 'intense_black',
|
84
|
+
'bg' => 'on_black',
|
85
|
+
'color' => 'white on_black',
|
86
|
+
'border' => 'blue',
|
87
|
+
'title' => 'magenta',
|
88
|
+
'eol' => 'intense_black on_black',
|
89
|
+
'pygments_theme' => 'monokai'
|
90
|
+
},
|
91
|
+
'dd' => {
|
92
|
+
'marker' => 'd red',
|
93
|
+
'color' => 'b white'
|
94
|
+
},
|
95
|
+
'hr' => {
|
96
|
+
'color' => 'd white'
|
97
|
+
},
|
98
|
+
'table' => {
|
99
|
+
'border' => 'd black',
|
100
|
+
'header' => 'yellow',
|
101
|
+
'divider' => 'b black',
|
102
|
+
'color' => 'white'
|
103
|
+
},
|
104
|
+
'html' => {
|
105
|
+
'brackets' => 'd yellow on_black',
|
106
|
+
'color' => 'yellow on_black'
|
107
|
+
}
|
108
|
+
}
|
109
|
+
|
110
|
+
unless File.directory?(config_dir)
|
111
|
+
@log.info("Creating config directory at #{config_dir}")
|
112
|
+
FileUtils.mkdir_p(config_dir)
|
113
|
+
end
|
114
|
+
|
115
|
+
unless File.exists?(theme_file)
|
116
|
+
@log.info("Writing fresh theme file to #{theme_file}")
|
117
|
+
File.open(theme_file,'w') {|f|
|
118
|
+
f.puts @theme.to_yaml
|
119
|
+
}
|
120
|
+
@theme = theme_defaults
|
121
|
+
else
|
122
|
+
new_theme = YAML.load(IO.read(theme_file))
|
123
|
+
begin
|
124
|
+
@theme = theme_defaults.deep_merge(new_theme)
|
125
|
+
rescue
|
126
|
+
@log.warn('Error merging user theme')
|
127
|
+
@theme = theme_defaults
|
128
|
+
end
|
129
|
+
end
|
130
|
+
|
131
|
+
|
15
132
|
@options = {}
|
16
133
|
optparse = OptionParser.new do |opts|
|
17
134
|
opts.banner = "#{version} by Brett Terpstra\n\n> Usage: #{CLIMarkdown::EXECUTABLE_NAME} [options] [path]\n\n"
|
18
135
|
|
19
136
|
@options[:section] = nil
|
20
|
-
opts.on( '-s', '--section=
|
137
|
+
opts.on( '-s', '--section=NUMBER', 'Output only a headline-based section of the input (numeric from --list)' ) do |section|
|
21
138
|
@options[:section] = section.to_i
|
22
139
|
end
|
23
140
|
|
@@ -41,7 +158,7 @@ module CLIMarkdown
|
|
41
158
|
end
|
42
159
|
|
43
160
|
@options[:links] = :inline
|
44
|
-
opts.on( '--links=FORMAT', 'Link style ([inline, reference], default inline)' ) do |format|
|
161
|
+
opts.on( '--links=FORMAT', 'Link style ([inline, reference], default inline) [NOT CURRENTLY IMPLEMENTED]' ) do |format|
|
45
162
|
if format =~ /^r/i
|
46
163
|
@options[:links] = :reference
|
47
164
|
end
|
@@ -95,7 +212,8 @@ module CLIMarkdown
|
|
95
212
|
|
96
213
|
@cols = @options[:width]
|
97
214
|
@output = ''
|
98
|
-
@
|
215
|
+
@headers = []
|
216
|
+
@setheaders = []
|
99
217
|
|
100
218
|
input = ''
|
101
219
|
@ref_links = {}
|
@@ -139,9 +257,58 @@ module CLIMarkdown
|
|
139
257
|
end
|
140
258
|
end
|
141
259
|
|
260
|
+
def color(key)
|
261
|
+
val = nil
|
262
|
+
keys = key.split(/[ ,>]/)
|
263
|
+
if @theme.key?(keys[0])
|
264
|
+
val = @theme[keys.shift]
|
265
|
+
else
|
266
|
+
@log.error("Invalid theme key: #{key}")
|
267
|
+
return c([:reset])
|
268
|
+
end
|
269
|
+
keys.each {|k|
|
270
|
+
if val.key?(k)
|
271
|
+
val = val[k]
|
272
|
+
else
|
273
|
+
@log.error("Invalid theme key: #{k}")
|
274
|
+
return c([:reset])
|
275
|
+
end
|
276
|
+
}
|
277
|
+
if val.kind_of? String
|
278
|
+
val = "x #{val}"
|
279
|
+
res = val.split(/ /).map {|k|
|
280
|
+
k.to_sym
|
281
|
+
}
|
282
|
+
c(res)
|
283
|
+
else
|
284
|
+
c([:reset])
|
285
|
+
end
|
286
|
+
end
|
287
|
+
|
142
288
|
def get_headers(input)
|
143
289
|
unless @headers && @headers.length > 0
|
144
|
-
@headers =
|
290
|
+
@headers = []
|
291
|
+
headers = input.scan(/^((?!#!)(\#{1,6})\s*([^#]+?)(?: #+)?\s*|(.*?)\n([=-]+))$/i)
|
292
|
+
|
293
|
+
headers.each {|h|
|
294
|
+
hlevel = 6
|
295
|
+
title = nil
|
296
|
+
if h[4] =~ /=+/
|
297
|
+
hlevel = 1
|
298
|
+
title = h[3]
|
299
|
+
elsif h[4] =~ /-+/
|
300
|
+
hlevel = 2
|
301
|
+
title = h[3]
|
302
|
+
else
|
303
|
+
hlevel = h[1].length
|
304
|
+
title = h[2]
|
305
|
+
end
|
306
|
+
@headers << [
|
307
|
+
'#'*hlevel,
|
308
|
+
title,
|
309
|
+
h[0]
|
310
|
+
]
|
311
|
+
}
|
145
312
|
end
|
146
313
|
@headers
|
147
314
|
end
|
@@ -192,9 +359,9 @@ module CLIMarkdown
|
|
192
359
|
end
|
193
360
|
|
194
361
|
def highest_header(input)
|
195
|
-
headers = input
|
362
|
+
@headers = get_headers(input)
|
196
363
|
top = 6
|
197
|
-
headers.each {|h|
|
364
|
+
@headers.each {|h|
|
198
365
|
top = h[0].length if h[0].length < top
|
199
366
|
}
|
200
367
|
top
|
@@ -205,12 +372,12 @@ module CLIMarkdown
|
|
205
372
|
input.split(/\n/).map{|line|
|
206
373
|
if first
|
207
374
|
first = false
|
208
|
-
line.gsub!(/\|/, "#{
|
375
|
+
line.gsub!(/\|/, "#{color('table border')}|#{color('table header')}")
|
209
376
|
elsif line.strip =~ /^[|:\- ]+$/
|
210
|
-
line.gsub!(/^(.*)$/, "#{
|
211
|
-
line.gsub!(/([:\-]+)/,"#{
|
377
|
+
line.gsub!(/^(.*)$/, "#{color('table border')}\\1#{color('table color')}")
|
378
|
+
line.gsub!(/([:\-]+)/,"#{color('table divider')}\\1#{color('table border')}")
|
212
379
|
else
|
213
|
-
line.gsub!(/\|/, "#{
|
380
|
+
line.gsub!(/\|/, "#{color('table border')}|#{color('table color')}")
|
214
381
|
end
|
215
382
|
}.join("\n")
|
216
383
|
end
|
@@ -289,22 +456,39 @@ module CLIMarkdown
|
|
289
456
|
end
|
290
457
|
|
291
458
|
def color_link(line, text, url)
|
292
|
-
|
293
|
-
|
294
|
-
|
295
|
-
|
296
|
-
|
297
|
-
|
298
|
-
|
299
|
-
|
300
|
-
|
301
|
-
|
459
|
+
[
|
460
|
+
color('link brackets'),
|
461
|
+
"[",
|
462
|
+
color('link text'),
|
463
|
+
text,
|
464
|
+
color('link brackets'),
|
465
|
+
"](",
|
466
|
+
color('link url'),
|
467
|
+
url,
|
468
|
+
color('link brackets'),
|
469
|
+
")",
|
470
|
+
find_color(line)
|
471
|
+
].join
|
302
472
|
end
|
303
473
|
|
304
474
|
def color_image(line, text, url)
|
305
|
-
text.gsub!(/\e\[0m/,
|
306
|
-
|
307
|
-
|
475
|
+
text.gsub!(/\e\[0m/,color('image title'))
|
476
|
+
|
477
|
+
[
|
478
|
+
color('image bang'),
|
479
|
+
"!",
|
480
|
+
color('image brackets'),
|
481
|
+
"[",
|
482
|
+
color('image title'),
|
483
|
+
text,
|
484
|
+
color('image brackets'),
|
485
|
+
"](",
|
486
|
+
color('image url'),
|
487
|
+
url,
|
488
|
+
color('image brackets'),
|
489
|
+
")",
|
490
|
+
find_color(line)
|
491
|
+
].join
|
308
492
|
end
|
309
493
|
|
310
494
|
def valid_lexer?(language)
|
@@ -333,19 +517,19 @@ module CLIMarkdown
|
|
333
517
|
if exec_available('pygmentize') && language && valid_lexer?(language)
|
334
518
|
lexer = "-l #{language}"
|
335
519
|
begin
|
336
|
-
hilite, s = Open3.capture2(%Q{pygmentize -f terminal256 -O style
|
520
|
+
hilite, s = Open3.capture2(%Q{pygmentize -f terminal256 -O style=#{@theme['code_block']['pygments_theme']} #{lexer} 2> /dev/null}, :stdin_data=>codeBlock)
|
337
521
|
if s.success?
|
338
522
|
|
339
523
|
hilite = xc + hilite.split(/\n/).map{|l|
|
340
524
|
new_code_line = l.gsub(/\t/, ' ')
|
341
525
|
new_code_line.sub!(/^#{" "*first_indent}/,'')
|
342
526
|
[
|
343
|
-
|
527
|
+
color('code_block marker'),
|
344
528
|
"> ",
|
345
529
|
" "*first_indent,
|
346
|
-
"#{
|
530
|
+
"#{color('code_block bg')}#{l}"
|
347
531
|
].join
|
348
|
-
}.join("\n").blackout + "#{xc}\n"
|
532
|
+
}.join("\n").blackout(@theme['code_block']['bg']) + "#{xc}\n"
|
349
533
|
end
|
350
534
|
rescue => e
|
351
535
|
@log.error(e)
|
@@ -355,19 +539,38 @@ module CLIMarkdown
|
|
355
539
|
hilite = codeBlock.split(/\n/).map do |line|
|
356
540
|
new_code_line = line.gsub(/\t/, ' ')
|
357
541
|
new_code_line.sub!(/^#{" "*first_indent}/,'')
|
358
|
-
new_code_line.gsub!(/ /, "#{
|
542
|
+
new_code_line.gsub!(/ /, "#{color('code_block color')} ")
|
359
543
|
[
|
360
|
-
|
544
|
+
color('code_block marker'),
|
361
545
|
"> ",
|
362
546
|
" "*first_indent,
|
363
|
-
|
547
|
+
color('code_block color'),
|
364
548
|
new_code_line,
|
365
549
|
xc
|
366
550
|
].join
|
367
551
|
end.join("\n") + "\n"
|
368
552
|
end
|
369
553
|
|
370
|
-
|
554
|
+
[
|
555
|
+
xc,
|
556
|
+
"\n",
|
557
|
+
" "*first_indent,
|
558
|
+
color('code_block border'),
|
559
|
+
'--[ ',
|
560
|
+
color('code_block title'),
|
561
|
+
leader,
|
562
|
+
color('code_block border'),
|
563
|
+
' ]',
|
564
|
+
'-'*(@cols-new_indent-leader.size+1),
|
565
|
+
xc,
|
566
|
+
"\n",
|
567
|
+
hilite,
|
568
|
+
" "*(new_indent),
|
569
|
+
color('code_block border'),
|
570
|
+
'-'*(@cols-new_indent),
|
571
|
+
xc,
|
572
|
+
"\n"
|
573
|
+
].join
|
371
574
|
end
|
372
575
|
|
373
576
|
def convert_markdown(input)
|
@@ -380,14 +583,13 @@ module CLIMarkdown
|
|
380
583
|
in_yaml = true
|
381
584
|
input.sub!(/(?i-m)^---[ \t]*\n([\s\S]*?)\n[\-.]{3}[ \t]*\n/) do |yaml|
|
382
585
|
m = Regexp.last_match
|
383
|
-
|
384
586
|
@log.info("Processing YAML Header")
|
385
587
|
m[0].split(/\n/).map {|line|
|
386
588
|
if line =~ /^[\-.]{3}\s*$/
|
387
|
-
line =
|
589
|
+
line = color('metadata marker') + "%% " + color('metadata border') + line
|
388
590
|
else
|
389
591
|
line.sub!(/^(.*?:)[ \t]+(\S)/, '\1 \2')
|
390
|
-
line =
|
592
|
+
line = color('metadata marker') + "%% " + color('metadata color') + line
|
391
593
|
end
|
392
594
|
if @cols - line.uncolor.size > 0
|
393
595
|
line += " "*(@cols-line.uncolor.size)
|
@@ -399,10 +601,9 @@ module CLIMarkdown
|
|
399
601
|
if !in_yaml && input.gsub(/\n/,' ') =~ /(?i-m)^\w.+:\s+\S+ /
|
400
602
|
@log.info("Found MMD Headers")
|
401
603
|
input.sub!(/(?i-m)^([\S ]+:[\s\S]*?)+(?=\n\n)/) do |mmd|
|
402
|
-
puts mmd
|
403
604
|
mmd.split(/\n/).map {|line|
|
404
605
|
line.sub!(/^(.*?:)[ \t]+(\S)/, '\1 \2')
|
405
|
-
line =
|
606
|
+
line = color('metadata marker') + "%% " + color('metadata color') + line
|
406
607
|
if @cols - line.uncolor.size > 0
|
407
608
|
line += " "*(@cols - line.uncolor.size)
|
408
609
|
end
|
@@ -420,6 +621,7 @@ module CLIMarkdown
|
|
420
621
|
end
|
421
622
|
|
422
623
|
# Gather footnotes (non-inline)
|
624
|
+
# TODO: Need to implement option to output links as references
|
423
625
|
input.gsub!(/^ {,3}(?<!\*)(?:\e\[[\d;]+m)*\[(?:\e\[[\d;]+m)*\^(?:\e\[[\d;]+m)*\b(.+)\b(?:\e\[[\d;]+m)*\]: *(.*?)\n/) do |m|
|
424
626
|
match = Regexp.last_match
|
425
627
|
@footnotes[match[1].uncolor] = match[2].uncolor
|
@@ -483,7 +685,7 @@ module CLIMarkdown
|
|
483
685
|
code_block = m[3]
|
484
686
|
leader = shebang[1] ? shebang[1] : 'code'
|
485
687
|
else
|
486
|
-
code_block = pad_max(m[3].to_s, "#{
|
688
|
+
code_block = pad_max(m[3].to_s, "#{color('code_block eol')}¬")
|
487
689
|
leader = language ? language : 'code'
|
488
690
|
end
|
489
691
|
end
|
@@ -519,31 +721,6 @@ module CLIMarkdown
|
|
519
721
|
# previous_indent = indent
|
520
722
|
# end
|
521
723
|
else
|
522
|
-
# Headlines
|
523
|
-
line.gsub!(/^(#+) *(.*?)(\s*#+)?\s*$/) do |match|
|
524
|
-
m = Regexp.last_match
|
525
|
-
pad = ""
|
526
|
-
ansi = ''
|
527
|
-
case m[1].length
|
528
|
-
when 1
|
529
|
-
ansi = c(%i[b black on_intense_white])
|
530
|
-
pad = c(%i[b white])
|
531
|
-
pad += m[2].length + 2 > @cols ? "*"*m[2].length : "*"*(@cols - (m[2].length + 2))
|
532
|
-
when 2
|
533
|
-
ansi = c(%i[b green on_black])
|
534
|
-
pad = c(%i[b black])
|
535
|
-
pad += m[2].length + 2 > @cols ? "-"*m[2].length : "-"*(@cols - (m[2].length + 2))
|
536
|
-
when 3
|
537
|
-
ansi = c(%i[u b yellow])
|
538
|
-
when 4
|
539
|
-
ansi = c(%i[x u yellow])
|
540
|
-
else
|
541
|
-
ansi = c(%i[b white])
|
542
|
-
end
|
543
|
-
|
544
|
-
"\n#{xc}#{ansi}#{m[2]} #{pad}#{xc}\n"
|
545
|
-
end
|
546
|
-
|
547
724
|
# place footnotes under paragraphs that reference them
|
548
725
|
if line =~ /\[(?:\e\[[\d;]+m)*\^(?:\e\[[\d;]+m)*(\S+)(?:\e\[[\d;]+m)*\]/
|
549
726
|
key = $1.uncolor
|
@@ -578,6 +755,7 @@ module CLIMarkdown
|
|
578
755
|
end
|
579
756
|
|
580
757
|
# make reference links inline
|
758
|
+
|
581
759
|
line.gsub!(/(?<![\e*])\[(\b.*?\b)?\]\[(\b.+?\b)?\]/) do |m|
|
582
760
|
match = Regexp.last_match
|
583
761
|
title = match[2] || ''
|
@@ -607,12 +785,20 @@ module CLIMarkdown
|
|
607
785
|
line.gsub!(/`(.*?)`/) do |m|
|
608
786
|
match = Regexp.last_match
|
609
787
|
last = find_color(match.pre_match, true)
|
610
|
-
|
788
|
+
[
|
789
|
+
color('code_span marker'),
|
790
|
+
'`',
|
791
|
+
color('code_span color'),
|
792
|
+
match[1],
|
793
|
+
color('code_span marker'),
|
794
|
+
'`',
|
795
|
+
last ? last : xc
|
796
|
+
].join
|
611
797
|
end
|
612
798
|
|
613
799
|
# horizontal rules
|
614
800
|
line.gsub!(/^ {,3}([\-*] ?){3,}$/) do |m|
|
615
|
-
|
801
|
+
color('hr color') + '_'*@cols + xc
|
616
802
|
end
|
617
803
|
|
618
804
|
# bold, bold/italic
|
@@ -659,14 +845,27 @@ module CLIMarkdown
|
|
659
845
|
line.gsub!(/^(\s*)([*\-+]|\d+\.) /) do |m|
|
660
846
|
match = Regexp.last_match
|
661
847
|
last = find_color(match.pre_match)
|
848
|
+
mcolor = match[2] =~ /^\d+\./ ? 'list number' : 'list bullet'
|
662
849
|
indent = match[1] || ''
|
663
|
-
|
850
|
+
[
|
851
|
+
indent,
|
852
|
+
color(mcolor),
|
853
|
+
match[2], " ",
|
854
|
+
color('list color')
|
855
|
+
].join
|
664
856
|
end
|
665
857
|
|
666
858
|
# definition lists
|
667
859
|
line.gsub!(/^(:\s*)(.*?)/) do |m|
|
668
860
|
match = Regexp.last_match
|
669
|
-
|
861
|
+
[
|
862
|
+
color('dd marker'),
|
863
|
+
match[1],
|
864
|
+
" ",
|
865
|
+
color('dd color'),
|
866
|
+
match[2],
|
867
|
+
xc
|
868
|
+
].join
|
670
869
|
end
|
671
870
|
|
672
871
|
# misc html
|
@@ -674,7 +873,15 @@ module CLIMarkdown
|
|
674
873
|
line.gsub!(/(?i-m)((<\/?)(\w+[\s\S]*?)(>))/) do |tag|
|
675
874
|
match = Regexp.last_match
|
676
875
|
last = find_color(match.pre_match)
|
677
|
-
|
876
|
+
[
|
877
|
+
color('html brackets'),
|
878
|
+
match[2],
|
879
|
+
color('html color'),
|
880
|
+
match[3],
|
881
|
+
color('html brackets'),
|
882
|
+
match[4],
|
883
|
+
last ? last : xc
|
884
|
+
].join
|
678
885
|
end
|
679
886
|
end
|
680
887
|
|
@@ -683,6 +890,36 @@ module CLIMarkdown
|
|
683
890
|
|
684
891
|
input = lines.join("\n")
|
685
892
|
|
893
|
+
# Headlines
|
894
|
+
@headers.each {|h|
|
895
|
+
input.sub!(/^#{h[2]}/) do |m|
|
896
|
+
pad = ""
|
897
|
+
ansi = ''
|
898
|
+
case h[0].length
|
899
|
+
when 1
|
900
|
+
ansi = color('h1 color')
|
901
|
+
pad = color('h1 pad')
|
902
|
+
char = @theme['h1']['pad_char'] || "="
|
903
|
+
pad += h[1].length + 2 > @cols ? char*h[1].length : char*(@cols - (h[1].length + 1))
|
904
|
+
when 2
|
905
|
+
ansi = color('h2 color')
|
906
|
+
pad = color('h2 pad')
|
907
|
+
char = @theme['h2']['pad_char'] || "-"
|
908
|
+
pad += h[1].length + 2 > @cols ? char*h[1].length : char*(@cols - (h[1].length + 1))
|
909
|
+
when 3
|
910
|
+
ansi = color('h3 color')
|
911
|
+
when 4
|
912
|
+
ansi = color('h4 color')
|
913
|
+
when 5
|
914
|
+
ansi = color('h5 color')
|
915
|
+
else
|
916
|
+
ansi = color('h6 color')
|
917
|
+
end
|
918
|
+
|
919
|
+
"\n#{xc}#{ansi}#{h[1]} #{pad}#{xc}\n"
|
920
|
+
end
|
921
|
+
}
|
922
|
+
|
686
923
|
# images
|
687
924
|
input.gsub!(/^(.*?)!\[(.*)?\]\((.*?\.(?:png|gif|jpg))( +.*)?\)/) do |m|
|
688
925
|
match = Regexp.last_match
|
@@ -731,7 +968,20 @@ module CLIMarkdown
|
|
731
968
|
end
|
732
969
|
|
733
970
|
@footnotes.each {|t, v|
|
734
|
-
input +=
|
971
|
+
input += [
|
972
|
+
"\n\n",
|
973
|
+
color('footnote brackets'),
|
974
|
+
"[",
|
975
|
+
color('footnote caret'),
|
976
|
+
"^",
|
977
|
+
color('footnote title'),
|
978
|
+
t,
|
979
|
+
color('footnote brackets'),
|
980
|
+
"]: ",
|
981
|
+
color('footnote note'),
|
982
|
+
v,
|
983
|
+
xc
|
984
|
+
].join
|
735
985
|
}
|
736
986
|
|
737
987
|
@output += input
|
@@ -760,6 +1010,7 @@ module CLIMarkdown
|
|
760
1010
|
IO.select [input]
|
761
1011
|
|
762
1012
|
pager = which_pager
|
1013
|
+
@log.info(%{Using #{pager} as pager})
|
763
1014
|
begin
|
764
1015
|
exec(pager.join(' '))
|
765
1016
|
rescue SystemCallError => e
|
@@ -805,13 +1056,13 @@ module CLIMarkdown
|
|
805
1056
|
def which_pager
|
806
1057
|
pagers = [ENV['GIT_PAGER'], ENV['PAGER'],
|
807
1058
|
`git config --get-all core.pager || true`.split.first,
|
808
|
-
'less', 'more', 'cat', 'pager']
|
1059
|
+
'bat', 'less', 'more', 'cat', 'pager']
|
809
1060
|
pagers.select! do |f|
|
810
1061
|
if f
|
811
1062
|
if f.strip =~ /[ |]/
|
812
1063
|
f
|
813
1064
|
else
|
814
|
-
|
1065
|
+
system "which #{f}", :out => File::NULL
|
815
1066
|
end
|
816
1067
|
else
|
817
1068
|
false
|
data/lib/mdless/version.rb
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: mdless
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.
|
4
|
+
version: 0.0.15
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Brett Terpstra
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2019-09-
|
11
|
+
date: 2019-09-13 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: rake
|