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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 0a4f667f7783166c9dd1d60ae77698058d9c240d014cd911ac27c4cce2b616b7
4
- data.tar.gz: f1db62b7e655e58a2c391fa3092e2497f69ba36b31b327686ed7e79846fdd3a0
3
+ metadata.gz: 350da3408205b06f5ef3b792190c11f0a1f2a22139f40472da1922486f2b1358
4
+ data.tar.gz: aad6fe5044525feab00af45cd757c1f5d5b1f3478a429db681a1bf86d9ea863e
5
5
  SHA512:
6
- metadata.gz: 3ee079617708ae07d18265be581c983631c01ef19187079e137d2244493b09fef7ce6048c0104fb2fc4123a8fce46abadc301d46d391180e1d2f8c2fd6443bfd
7
- data.tar.gz: 1710ad0309375ef8728521c1d883a7f2b13c7bef2cf5ac5325f497de27b690d36b208f706ec8a8f9fec178a994f0abef698619636815c5d5425b949c6722e708
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 `pygmentize` is available
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=TITLE Output only a headline-based section of
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
- self.gsub(/(^|$)/,"\e[40m").gsub(/3([89])m/,"40;3\\1m")
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
- colors = {
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 colors.key? arg
113
- out << colors[arg]
116
+ if COLORS.key? arg
117
+ out << COLORS[arg]
114
118
  end
115
119
  }
116
120
 
@@ -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=TITLE', 'Output only a headline-based section of the input (numeric from -l)' ) do |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
- @header_arr = []
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 = input.scan(/^(#+)\s*(.*?)( #+)?\s*$/)
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.scan(/^(#+)/)
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!(/\|/, "#{c(%i[d black])}|#{c(%i[x yellow])}")
375
+ line.gsub!(/\|/, "#{color('table border')}|#{color('table header')}")
209
376
  elsif line.strip =~ /^[|:\- ]+$/
210
- line.gsub!(/^(.*)$/, "#{c(%i[d black])}\\1#{c(%i[x white])}")
211
- line.gsub!(/([:\-]+)/,"#{c(%i[b black])}\\1#{c(%i[d black])}")
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!(/\|/, "#{c(%i[d black])}|#{c(%i[x white])}")
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
- out = c(%i[b black])
293
- out += "[#{c(%i[u blue])}#{text}"
294
- out += c(%i[b black])
295
- out += "]("
296
- out += c(%i[x cyan])
297
- out += url
298
- out += c(%i[b black])
299
- out += ")"
300
- out += find_color(line)
301
- out
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/,c(%i[x cyan]))
306
-
307
- "#{c(%i[x red])}!#{c(%i[b black])}[#{c(%i[x cyan])}#{text}#{c(%i[b black])}](#{c(%i[u yellow])}#{url}#{c(%i[b black])})" + find_color(line)
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=monokai #{lexer} 2> /dev/null}, :stdin_data=>codeBlock)
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
- c(%i[x intense_black]),
527
+ color('code_block marker'),
344
528
  "> ",
345
529
  " "*first_indent,
346
- "#{c([:on_black])}#{l}"
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!(/ /, "#{c(%i[x white on_black])} ")
542
+ new_code_line.gsub!(/ /, "#{color('code_block color')} ")
359
543
  [
360
- c(%i[x intense_black]),
544
+ color('code_block marker'),
361
545
  "> ",
362
546
  " "*first_indent,
363
- c(%i[x white on_black]),
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
- "#{xc}\n#{" "*first_indent}#{c(%i[x blue]) + '--[ '}#{c(%i[x magenta])}#{leader}#{c(%i[x blue]) + ' ]' + '-'*(@cols-new_indent-leader.size+1) + xc}\n#{hilite}#{" "*(new_indent)}#{c(%i[x blue]) + '-'*(@cols-new_indent) + xc}\n"
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 = c(%i[d black on_black]) + "% " + c(%i[d black on_black]) + line
589
+ line = color('metadata marker') + "%% " + color('metadata border') + line
388
590
  else
389
591
  line.sub!(/^(.*?:)[ \t]+(\S)/, '\1 \2')
390
- line = c(%i[d black on_black]) + "% " + c(%i[d white]) + 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 = c(%i[d black on_black]) + "% " + c(%i[d white on_black]) + 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, "#{c(%i[intense_black on_black])}¬")
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
- "#{c(%i[b black])}`#{c(%i[b white])}#{match[1]}#{c(%i[b black])}`" + (last ? last : xc)
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
- c(%i[x black]) + '_'*@cols + xc
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
- "#{indent}#{c(%i[d red])}#{match[2]} " + (last ? last : xc)
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
- "#{c(%i[d red])}#{match[1]} #{c(%i[b white])}#{match[2]}#{xc}"
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
- "#{c(%i[d yellow on_black])}#{match[2]}#{match[3]}#{match[4]}" + (last ? last : xc)
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 += "\n\n#{c(%i[b black on_black])}[#{c(%i[b yellow on_black])}^#{c(%i[x yellow on_black])}#{t}#{c(%i[b black on_black])}]: #{c(%i[u white on_black])}#{v}#{xc}"
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
- system "which #{f}", :out => File::NULL
1065
+ system "which #{f}", :out => File::NULL
815
1066
  end
816
1067
  else
817
1068
  false
@@ -1,3 +1,3 @@
1
1
  module CLIMarkdown
2
- VERSION = '0.0.14'
2
+ VERSION = '0.0.15'
3
3
  end
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.14
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-12 00:00:00.000000000 Z
11
+ date: 2019-09-13 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rake