mdless 1.0.31 → 1.0.33

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 4e0a66c5ea1522d66b1cca9ad1e74e66b4e5dd301fd5b42eb9ff20d912074c02
4
- data.tar.gz: 75e46348a488ae50975f931b3164a127ae085d53b1eba3ebd1264ce19e5c6048
3
+ metadata.gz: 124d704b9e69d3c7afbba30442cc2e3f3b9ebd92edc16b345c3a5489b64a5823
4
+ data.tar.gz: 0e257d07a7c684441140ad2d526711c41127f97af37ae798311d9f04e5f832fd
5
5
  SHA512:
6
- metadata.gz: 362da8ff8940e858a31a5c40a375454d54b0632bfef39ab50426257424887115f56dfe92909ba00e365a6953c7c4381db34a3bb4b78995702c2e9668d82506c7
7
- data.tar.gz: 0e1df0694ecfc053517aa22cd0430e554dc06742a3443d37648f15cd2db82f97b5de697f18ab2982d9511d30d68a4165c813c23a8cfc33363bba92170cd539c3
6
+ metadata.gz: 621d98dd881546000fdff38ad51e691d1c729fce4a87f96dc19b5041b9fefefd826245ed9b865db272165b591a0d300b6d1c5dca71d2612b611bc9549dce3181
7
+ data.tar.gz: 33287f2fd78bdc15fd9bc15003a30df2396688475864063e012d96418c8e390a2c2e6c67c746831608a40e4bea0ee594540e209dbcc6806d3e7950c870406785
data/README.md CHANGED
@@ -1,12 +1,13 @@
1
1
  # mdless
2
2
 
3
3
  <!--README-->
4
+
4
5
  `mdless` is a utility that provides a formatted and highlighted view of Markdown files in Terminal.
5
6
 
6
7
  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.
7
8
 
8
9
  <!--GITHUB-->![mdless screenshot](screenshots/mdless.png)<!--END GITHUB-->
9
- <!--JEKYLL {% gif /uploads/2015/08/mdless.gif %} -->
10
+ <!--JEKYLL{% gif /uploads/2015/08/mdless.gif %}-->
10
11
 
11
12
  ## Features
12
13
 
@@ -17,7 +18,7 @@ I often use iTerm2 in visor mode, so `qlmanage -p` is annoying. I still wanted a
17
18
  - Display footnotes after each paragraph
18
19
  - Inline image display (local, optionally remote) if using iTerm2 2.9+
19
20
  - Syntax highlighting when [Pygments](http://pygments.org/) is installed
20
- - Only fenced code with a language defined (e.g. `\`\`\`python`) will be highlighted
21
+ - Only fenced code with a language defined (e.g. `python`) will be highlighted
21
22
  - Languages can also be determined by hashbang in the code block
22
23
  - List headlines in document
23
24
  - Display single section of the document based on headlines
@@ -114,4 +115,5 @@ Use 'r' to reverse foreground and background colors. `r white on_black` would di
114
115
  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`.
115
116
 
116
117
  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`.
118
+
117
119
  <!--END README-->
data/bin/mdless CHANGED
@@ -1,12 +1,13 @@
1
1
  #!/usr/bin/env ruby
2
- # coding: utf-8
2
+ # frozen_string_literal: true
3
+
3
4
  require 'mdless'
4
5
 
5
6
  def class_exists?(class_name)
6
7
  klass = Module.const_get(class_name)
7
- return klass.is_a?(Class)
8
+ klass.is_a?(Class)
8
9
  rescue NameError
9
- return false
10
+ false
10
11
  end
11
12
 
12
13
  if class_exists? 'Encoding'
@@ -22,11 +22,11 @@ module CLIMarkdown
22
22
  opts.banner = "#{version} by Brett Terpstra\n\n> Usage: #{CLIMarkdown::EXECUTABLE_NAME} [options] [path]\n\n"
23
23
 
24
24
  @options[:color] = true
25
- opts.on( '-c', '--[no-]color', 'Colorize output (default on)' ) do |c|
25
+ opts.on('-c', '--[no-]color', 'Colorize output (default on)') do |c|
26
26
  @options[:color] = c
27
27
  end
28
28
 
29
- opts.on( '-d', '--debug LEVEL', 'Level of debug messages to output' ) do |level|
29
+ opts.on('-d', '--debug LEVEL', 'Level of debug messages to output') do |level|
30
30
  if level.to_i > 0 && level.to_i < 5
31
31
  @log.level = 5 - level.to_i
32
32
  else
@@ -35,7 +35,7 @@ module CLIMarkdown
35
35
  end
36
36
  end
37
37
 
38
- opts.on( '-h', '--help', 'Display this screen' ) do
38
+ opts.on('-h', '--help', 'Display this screen') do
39
39
  puts opts
40
40
  exit
41
41
  end
@@ -54,8 +54,8 @@ module CLIMarkdown
54
54
  end
55
55
  end
56
56
  end
57
- opts.on('-I', '--all-images', 'Include local and remote images in output (requires imgcat or chafa)' ) do
58
- if exec_available('imgcat') || exec_available('chafa')# && ENV['TERM_PROGRAM'] == 'iTerm.app'
57
+ opts.on('-I', '--all-images', 'Include local and remote images in output (requires imgcat or chafa)') do
58
+ if exec_available('imgcat') || exec_available('chafa') # && ENV['TERM_PROGRAM'] == 'iTerm.app'
59
59
  @options[:local_images] = true
60
60
  @options[:remote_images] = true
61
61
  else
@@ -64,51 +64,51 @@ module CLIMarkdown
64
64
  end
65
65
 
66
66
  @options[:links] = :inline
67
- opts.on( '--links=FORMAT', 'Link style ([inline, reference], default inline) [NOT CURRENTLY IMPLEMENTED]' ) do |format|
67
+ opts.on('--links=FORMAT', 'Link style ([inline, reference], default inline) [NOT CURRENTLY IMPLEMENTED]') do |format|
68
68
  if format =~ /^r/i
69
69
  @options[:links] = :reference
70
70
  end
71
71
  end
72
72
 
73
73
  @options[:list] = false
74
- opts.on( '-l', '--list', 'List headers in document and exit' ) do
74
+ opts.on('-l', '--list', 'List headers in document and exit' ) do
75
75
  @options[:list] = true
76
76
  end
77
77
 
78
78
  @options[:pager] = true
79
- opts.on( '-p', '--[no-]pager', 'Formatted output to pager (default on)' ) do |p|
79
+ opts.on('-p', '--[no-]pager', 'Formatted output to pager (default on)') do |p|
80
80
  @options[:pager] = p
81
81
  end
82
82
 
83
- opts.on( '-P', 'Disable pager (same as --no-pager)' ) do
83
+ opts.on('-P', 'Disable pager (same as --no-pager)') do
84
84
  @options[:pager] = false
85
85
  end
86
86
 
87
87
  @options[:section] = nil
88
- opts.on( '-s', '--section=NUMBER', 'Output only a headline-based section of the input (numeric from --list)' ) do |section|
89
- @options[:section] = section.to_i
88
+ opts.on('-s', '--section=NUMBER[,NUMBER]', 'Output only a headline-based section of the input (numeric from --list)') do |section|
89
+ @options[:section] = section.split(/ *, */).map(&:strip).map(&:to_i)
90
90
  end
91
91
 
92
92
  @options[:theme] = 'default'
93
- opts.on( '-t', '--theme=THEME_NAME', 'Specify an alternate color theme to load' ) do |theme|
93
+ opts.on('-t', '--theme=THEME_NAME', 'Specify an alternate color theme to load') do |theme|
94
94
  @options[:theme] = theme
95
95
  end
96
96
 
97
- opts.on( '-v', '--version', 'Display version number' ) do
97
+ opts.on('-v', '--version', 'Display version number') do
98
98
  puts version
99
99
  exit
100
100
  end
101
101
 
102
- @options[:width] = %x{tput cols}.strip.to_i
103
- opts.on( '-w', '--width=COLUMNS', 'Column width to format for (default terminal width)' ) do |columns|
102
+ @options[:width] = `tput cols`.strip.to_i
103
+ opts.on('-w', '--width=COLUMNS', 'Column width to format for (default: terminal width)') do |columns|
104
104
  @options[:width] = columns.to_i
105
105
  end
106
106
  end
107
107
 
108
108
  begin
109
109
  optparse.parse!
110
- rescue OptionParser::ParseError => pe
111
- $stderr.puts "error: #{pe.message}"
110
+ rescue OptionParser::ParseError => e
111
+ warn "error: #{e.message}"
112
112
  exit 1
113
113
  end
114
114
 
@@ -122,33 +122,33 @@ module CLIMarkdown
122
122
  @ref_links = {}
123
123
  @footnotes = {}
124
124
 
125
- if args.length > 0
126
- files = args.delete_if { |f| !File.exists?(f) }
127
- files.each {|file|
128
- @log.info(%Q{Processing "#{file}"})
125
+ if !args.empty?
126
+ files = args.delete_if { |f| !File.exist?(f) }
127
+ files.each do |file|
128
+ @log.info(%(Processing "#{file}"))
129
129
  @file = file
130
130
  begin
131
131
  input = IO.read(file).force_encoding('utf-8')
132
- rescue
132
+ rescue StandardError
133
133
  input = IO.read(file)
134
134
  end
135
- input.gsub!(/\r?\n/,"\n")
135
+ input.gsub!(/\r?\n/, "\n")
136
136
  if @options[:list]
137
137
  puts list_headers(input)
138
138
  Process.exit 0
139
139
  else
140
140
  convert_markdown(input)
141
141
  end
142
- }
142
+ end
143
143
  printout
144
- elsif ! STDIN.tty?
144
+ elsif !$stdin.isatty
145
145
  @file = nil
146
146
  begin
147
- input = STDIN.read.force_encoding('utf-8')
148
- rescue
149
- input = STDIN.read
147
+ input = $stdin.read.force_encoding('utf-8')
148
+ rescue StandardError
149
+ input = $stdin.read
150
150
  end
151
- input.gsub!(/\r?\n/,"\n")
151
+ input.gsub!(/\r?\n/, "\n")
152
152
  if @options[:list]
153
153
  puts list_headers(input)
154
154
  Process.exit 0
@@ -157,7 +157,7 @@ module CLIMarkdown
157
157
  end
158
158
  printout
159
159
  else
160
- $stderr.puts "No input"
160
+ warn 'No input'
161
161
  Process.exit 1
162
162
  end
163
163
 
@@ -172,19 +172,17 @@ module CLIMarkdown
172
172
  @log.error("Invalid theme key: #{key}") unless keys[0] =~ /^text/
173
173
  return c([:reset])
174
174
  end
175
- keys.each {|k|
175
+ keys.each do |k|
176
176
  if val.key?(k)
177
177
  val = val[k]
178
178
  else
179
179
  @log.error("Invalid theme key: #{k}")
180
180
  return c([:reset])
181
181
  end
182
- }
183
- if val.kind_of? String
182
+ end
183
+ if val.is_a? String
184
184
  val = "x #{val}"
185
- res = val.split(/ /).map {|k|
186
- k.to_sym
187
- }
185
+ res = val.split(/ /).map { |k| k.to_sym }
188
186
  c(res)
189
187
  else
190
188
  c([:reset])
@@ -192,7 +190,7 @@ module CLIMarkdown
192
190
  end
193
191
 
194
192
  def get_headers(input)
195
- unless @headers && @headers.length > 0
193
+ unless @headers && !@headers.empty?
196
194
  @headers = []
197
195
  headers = input.scan(/^((?!#!)(\#{1,6})\s*([^#]+?)(?: #+)?\s*|(\S.+)\n([=-]+))$/i)
198
196
 
@@ -490,6 +488,10 @@ module CLIMarkdown
490
488
  end
491
489
 
492
490
  def convert_markdown(input)
491
+ ## Replace setex headers with ATX
492
+ input.gsub!(/^([^\n]+)\n={3,}\s*$/m, "# \\1\n")
493
+ input.gsub!(/^([^\n]+?)\n-{3,}\s*$/m, "## \\1\n")
494
+
493
495
  @headers = get_headers(input)
494
496
  input += "\n\n@@@"
495
497
  # yaml/MMD headers
@@ -529,7 +531,6 @@ module CLIMarkdown
529
531
 
530
532
  end
531
533
 
532
-
533
534
  # Gather reference links
534
535
  input.gsub!(/^\s{,3}(?<![\e*])\[\b(.+)\b\]: +(.+)/) do |m|
535
536
  match = Regexp.last_match
@@ -546,34 +547,34 @@ module CLIMarkdown
546
547
  end
547
548
 
548
549
  if @options[:section]
549
- in_section = false
550
- top_level = 1
551
550
  new_content = []
552
-
553
- input.split(/\n/).each {|graf|
554
- if graf =~ /^(#+) *(.*?)( *#+)?$/
555
- level = $1.length
556
- title = $2
557
-
558
- if in_section
559
- if level >= top_level
551
+ @options[:section].each do |sect|
552
+ in_section = false
553
+ top_level = 1
554
+ input.split(/\n/).each do |graf|
555
+ if graf =~ /^(#+) *(.*?)( *#+)?$/
556
+ m = Regexp.last_match
557
+ level = m[1].length
558
+ title = m[2]
559
+ if in_section
560
+ if level >= top_level
561
+ new_content.push(graf)
562
+ else
563
+ in_section = false
564
+ break
565
+ end
566
+ elsif title.downcase == @headers[sect - 1][1].downcase
567
+ in_section = true
568
+ top_level = level + 1
560
569
  new_content.push(graf)
561
570
  else
562
- in_section = false
563
- break
571
+ next
564
572
  end
565
- elsif title.downcase == "#{@headers[@options[:section] - 1][1].downcase}"
566
- in_section = true
567
- top_level = level + 1
573
+ elsif in_section
568
574
  new_content.push(graf)
569
- else
570
- next
571
575
  end
572
- elsif in_section
573
- new_content.push(graf)
574
576
  end
575
- }
576
-
577
+ end
577
578
  input = new_content.join("\n")
578
579
  end
579
580
 
@@ -1042,8 +1043,6 @@ module CLIMarkdown
1042
1043
  args = case pg
1043
1044
  when 'delta'
1044
1045
  ' --pager="less -Xr"'
1045
- when 'more'
1046
- ' -r'
1047
1046
  when 'less'
1048
1047
  ' -Xr'
1049
1048
  when 'bat'
data/lib/mdless/theme.rb CHANGED
@@ -2,92 +2,92 @@ module CLIMarkdown
2
2
  module Theme
3
3
 
4
4
  THEME_DEFAULTS = {
5
- 'metadata' => {
6
- 'border' => 'd blue on_black',
7
- 'marker' => 'd black on_black',
8
- 'color' => 'd white on_black'
9
- },
10
- 'emphasis' => {
11
- 'bold' => 'b',
12
- 'italic' => 'u i',
13
- 'bold-italic' => 'b u i'
14
- },
15
- 'h1' => {
16
- 'color' => 'b intense_black on_white',
17
- 'pad' => 'd black on_white',
18
- 'pad_char' => '='
19
- },
20
- 'h2' => {
21
- 'color' => 'b white on_intense_black',
22
- 'pad' => 'd white on_intense_black',
23
- 'pad_char' => '-'
24
- },
25
- 'h3' => {
26
- 'color' => 'u b yellow'
27
- },
28
- 'h4' => {
29
- 'color' => 'u yellow'
30
- },
31
- 'h5' => {
32
- 'color' => 'b white'
33
- },
34
- 'h6' => {
35
- 'color' => 'b white'
36
- },
37
- 'link' => {
38
- 'brackets' => 'b black',
39
- 'text' => 'u b blue',
40
- 'url' => 'cyan'
41
- },
42
- 'image' => {
43
- 'bang' => 'red',
44
- 'brackets' => 'b black',
45
- 'title' => 'cyan',
46
- 'url' => 'u yellow'
47
- },
48
- 'list' => {
49
- 'bullet' => 'b intense_red',
50
- 'number' => 'b intense_blue',
51
- 'color' => 'intense_white'
52
- },
53
- 'footnote' => {
54
- 'brackets' => 'b black on_black',
55
- 'caret' => 'b yellow on_black',
56
- 'title' => 'x yellow on_black',
57
- 'note' => 'u white on_black'
58
- },
59
- 'code_span' => {
60
- 'marker' => 'b white',
61
- 'color' => 'b white on_intense_black'
62
- },
63
- 'code_block' => {
64
- 'marker' => 'intense_black',
65
- 'bg' => 'on_black',
66
- 'color' => 'white on_black',
67
- 'border' => 'blue',
68
- 'title' => 'magenta',
69
- 'eol' => 'intense_black on_black',
70
- 'pygments_theme' => 'monokai'
71
- },
72
- 'dd' => {
73
- 'marker' => 'd red',
74
- 'color' => 'b white'
75
- },
76
- 'hr' => {
77
- 'color' => 'd white'
78
- },
79
- 'table' => {
80
- 'border' => 'd black',
81
- 'header' => 'yellow',
82
- 'divider' => 'b black',
83
- 'color' => 'white',
84
- 'bg' => 'on_black'
85
- },
86
- 'html' => {
87
- 'brackets' => 'd yellow on_black',
88
- 'color' => 'yellow on_black'
89
- }
5
+ 'metadata' => {
6
+ 'border' => 'd blue on_black',
7
+ 'marker' => 'd black on_black',
8
+ 'color' => 'd white on_black'
9
+ },
10
+ 'emphasis' => {
11
+ 'bold' => 'b',
12
+ 'italic' => 'u i',
13
+ 'bold-italic' => 'b u i'
14
+ },
15
+ 'h1' => {
16
+ 'color' => 'b intense_black on_white',
17
+ 'pad' => 'd black on_white',
18
+ 'pad_char' => '='
19
+ },
20
+ 'h2' => {
21
+ 'color' => 'b white on_intense_black',
22
+ 'pad' => 'd white on_intense_black',
23
+ 'pad_char' => '-'
24
+ },
25
+ 'h3' => {
26
+ 'color' => 'u b yellow'
27
+ },
28
+ 'h4' => {
29
+ 'color' => 'u yellow'
30
+ },
31
+ 'h5' => {
32
+ 'color' => 'b white'
33
+ },
34
+ 'h6' => {
35
+ 'color' => 'b white'
36
+ },
37
+ 'link' => {
38
+ 'brackets' => 'b black',
39
+ 'text' => 'u b blue',
40
+ 'url' => 'cyan'
41
+ },
42
+ 'image' => {
43
+ 'bang' => 'red',
44
+ 'brackets' => 'b black',
45
+ 'title' => 'cyan',
46
+ 'url' => 'u yellow'
47
+ },
48
+ 'list' => {
49
+ 'bullet' => 'b intense_red',
50
+ 'number' => 'b intense_blue',
51
+ 'color' => 'intense_white'
52
+ },
53
+ 'footnote' => {
54
+ 'brackets' => 'b black on_black',
55
+ 'caret' => 'b yellow on_black',
56
+ 'title' => 'x yellow on_black',
57
+ 'note' => 'u white on_black'
58
+ },
59
+ 'code_span' => {
60
+ 'marker' => 'b white',
61
+ 'color' => 'b white on_intense_black'
62
+ },
63
+ 'code_block' => {
64
+ 'marker' => 'intense_black',
65
+ 'bg' => 'on_black',
66
+ 'color' => 'white on_black',
67
+ 'border' => 'blue',
68
+ 'title' => 'magenta',
69
+ 'eol' => 'intense_black on_black',
70
+ 'pygments_theme' => 'monokai'
71
+ },
72
+ 'dd' => {
73
+ 'marker' => 'd red',
74
+ 'color' => 'b white'
75
+ },
76
+ 'hr' => {
77
+ 'color' => 'd white'
78
+ },
79
+ 'table' => {
80
+ 'border' => 'd black',
81
+ 'header' => 'yellow',
82
+ 'divider' => 'b black',
83
+ 'color' => 'white',
84
+ 'bg' => 'on_black'
85
+ },
86
+ 'html' => {
87
+ 'brackets' => 'd yellow on_black',
88
+ 'color' => 'yellow on_black'
90
89
  }
90
+ }
91
91
 
92
92
  def load_theme_file(theme_file)
93
93
  new_theme = YAML.load(IO.read(theme_file))
@@ -98,15 +98,13 @@ module CLIMarkdown
98
98
  # File.open(theme_file,'w') {|f|
99
99
  # f.puts theme.to_yaml
100
100
  # }
101
- rescue
101
+ rescue StandardError
102
102
  @log.warn('Error merging user theme')
103
103
  theme = THEME_DEFAULTS
104
104
  if File.basename(theme_file) =~ /mdless\.theme/
105
105
  FileUtils.rm(theme_file)
106
106
  @log.info("Rewriting default theme file to #{theme_file}")
107
- File.open(theme_file,'w') {|f|
108
- f.puts theme.to_yaml
109
- }
107
+ File.open(theme_file, 'w') { |f| f.puts theme.to_yaml }
110
108
  end
111
109
  end
112
110
  theme
@@ -114,12 +112,12 @@ module CLIMarkdown
114
112
 
115
113
  def load_theme(theme)
116
114
  config_dir = File.expand_path('~/.config/mdless')
117
- default_theme_file = File.join(config_dir,'mdless.theme')
115
+ default_theme_file = File.join(config_dir, 'mdless.theme')
118
116
  if theme =~ /default/i || !theme
119
117
  theme_file = default_theme_file
120
118
  else
121
- theme = theme.strip.sub(/(\.theme)?$/,'.theme')
122
- theme_file = File.join(config_dir,theme)
119
+ theme = theme.strip.sub(/(\.theme)?$/, '.theme')
120
+ theme_file = File.join(config_dir, theme)
123
121
  end
124
122
 
125
123
  unless File.directory?(config_dir)
@@ -127,16 +125,14 @@ module CLIMarkdown
127
125
  FileUtils.mkdir_p(config_dir)
128
126
  end
129
127
 
130
- unless File.exists?(theme_file)
131
- unless File.exists?(default_theme_file)
128
+ unless File.exist?(theme_file)
129
+ if File.exist?(default_theme_file)
130
+ @log.info('Specified theme not found, using default')
131
+ theme_file = default_theme_file
132
+ else
132
133
  theme = THEME_DEFAULTS
133
134
  @log.info("Writing fresh theme file to #{theme_file}")
134
- File.open(theme_file,'w') {|f|
135
- f.puts theme.to_yaml
136
- }
137
- else
138
- @log.info("Specified theme not found, using default")
139
- theme_file = default_theme_file
135
+ File.open(theme_file, 'w') { |f| f.puts theme.to_yaml }
140
136
  end
141
137
  end
142
138
 
@@ -1,3 +1,3 @@
1
1
  module CLIMarkdown
2
- VERSION = '1.0.31'
2
+ VERSION = '1.0.33'
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: 1.0.31
4
+ version: 1.0.33
5
5
  platform: ruby
6
6
  authors:
7
7
  - Brett Terpstra
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2022-08-02 00:00:00.000000000 Z
11
+ date: 2023-06-03 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rake