cani 0.5.8 → 0.5.9

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
- SHA256:
3
- metadata.gz: 97a7a44de697f793827e056d88bc55cdc51c8d5d44119b75c3f1fc619b1c10a3
4
- data.tar.gz: dc62177619b558a496c499c63754210b157f1a84513b4f24636ad20961995df3
2
+ SHA1:
3
+ metadata.gz: bbdbb28b9c3709f04c106775b5d019f7d4e29177
4
+ data.tar.gz: cb812356aac2f7ad341f8d80fe16db97539813b4
5
5
  SHA512:
6
- metadata.gz: ad9b0f922f4816e1ab336a868f06a732298837ef5d9eecf271e93aa29bee6c78a14f7d04241ef3d2b123fbd117cec43b731edfeaf8df4873a463b24c0280c06b
7
- data.tar.gz: '09a7aee1a40aada6855807b20f5de20b4cd5a91db1ff0cdd65d89969ffa3ac50fd762a0f480abc21a470f685b0d78f244f66a0d5a18c5ce6c685b7a3a775231c'
6
+ metadata.gz: 01ffd79c7dcbb0aae80cac9585d687eaf00c2226f617d4a70cb409384d9938373363e5b38d93c8988f6e92a525ce88774cb0aa922a3435cf4381b1dbb203d8f0
7
+ data.tar.gz: fc4287ccb47965a06f6218af9de4d67d1ff63d677687d5042fd3df9bb9e13e630463727269bb08a89f2c58d31a05ee66739578b9a97a61a329983306e8fdd781
@@ -0,0 +1 @@
1
+ TargetRubyVersion: "2.1"
@@ -0,0 +1,15 @@
1
+ ### 24-07-2019 VERSION 0.5.6
2
+
3
+ - Fix issue where `cani` would crash when used without arguments. Original behavior of showing `cani help` in that case is restored. ([#14](../../pull/14))
4
+ - Disable FZF's preview window using `--no-preview` to override `FZF_DEFAULT_OPTS` ([#12](../../issues/12))
5
+
6
+ ### 06-07-2019 VERSION 0.5.5
7
+
8
+ - Added ability to (permanently) toggle between enabling and disabling of automatic shell configuration injection
9
+
10
+ ### 06-10-2018 VERSION 0.5.4
11
+
12
+ - Fixed issue where `system` prints the version of fzf before running the command.
13
+ - When multiple matches are found for a given query: `cani use shadow`, an fzf window will
14
+ now be opened with results filtered by the text `shadow` as initial query string.
15
+
data/Gemfile CHANGED
@@ -1,6 +1,6 @@
1
1
  source "https://rubygems.org"
2
2
 
3
- git_source(:github) {|repo_name| "https://github.com/#{repo_name}" }
3
+ git_source(:github) { |repo_name| "https://github.com/#{repo_name}" }
4
4
 
5
5
  # Specify your gem's dependencies in cani.gemspec
6
6
  gemspec
data/README.md CHANGED
@@ -10,6 +10,13 @@ on a regular interval together with completions.
10
10
 
11
11
  ## Latest changes
12
12
 
13
+ dates are in dd-mm-yyyy format older changes can be found in the [changelog](/CHANGELOG.md)
14
+
15
+ ### 16-09-2019 VERSION 0.5.9
16
+
17
+ - Fix glitch where current era border would be drawn incorrectly at certain widths.
18
+ - Do not print an empty era row if none of the visible browsers show anything.
19
+
13
20
  ### 28-07-2019 VERSION 0.5.8
14
21
 
15
22
  - Fix line overflow issue when terminal is too small for "widest" display
@@ -19,21 +26,6 @@ on a regular interval together with completions.
19
26
 
20
27
  - Titles shown in `cani use` may take up to 50 characters if the terminal is wide enough.
21
28
 
22
- ### 24-07-2019 VERSION 0.5.6
23
-
24
- - Fix issue where `cani` would crash when used without arguments. Original behavior of showing `cani help` in that case is restored. ([#14](../../pull/14))
25
- - Disable FZF's preview window using `--no-preview` to override `FZF_DEFAULT_OPTS` ([#12](../../issues/12))
26
-
27
- ### 06-07-2019 VERSION 0.5.5
28
-
29
- - Added ability to (permanently) toggle between enabling and disabling of automatic shell configuration injection
30
-
31
- ### 06-10-2018 VERSION 0.5.4
32
-
33
- - Fixed issue where `system` prints the version of fzf before running the command.
34
- - When multiple matches are found for a given query: `cani use shadow`, an fzf window will
35
- now be opened with results filtered by the text `shadow` as initial query string.
36
-
37
29
  ## Installation
38
30
 
39
31
  Add this line to your application's Gemfile:
@@ -227,9 +219,9 @@ Last but not least, all `cani` commands can be piped. This will skip running `fz
227
219
  **use** _(the output of_ `cani use ft-name` _cannot be piped)_
228
220
  ```sh
229
221
  cani use | head -3
230
- [rc] 97.11% PNG alpha transparency +chr +ff +edge +ie +saf +saf.ios +op +and +bb
231
- [un] 75.85% Animated PNG (APNG) +chr +ff -edge -ie +saf +saf.ios +op -and -bb
232
- [ls] 94.32% Video element +chr +ff +edge +ie +saf +saf.ios +op +and +bb
222
+ [rc] 97.11% PNG alpha transparency +chr +ff +edge +ie +saf +saf.ios +op +and +bb
223
+ [un] 75.85% Animated PNG (APNG) +chr +ff -edge -ie +saf +saf.ios +op -and -bb
224
+ [ls] 94.32% Video element +chr +ff +edge +ie +saf +saf.ios +op +and +bb
233
225
  ```
234
226
 
235
227
  **show**
@@ -10,27 +10,29 @@ Gem::Specification.new do |spec|
10
10
  spec.email = ['sidneyliebrand@gmail.com']
11
11
 
12
12
  spec.summary = 'A simple caniuse CLI.'
13
- spec.description = 'An interactive TUI (using FZF / Curses) for exploring caniuse.com in your terminal.'
13
+ spec.description = 'An interactive TUI (using FZF / Curses) ' \
14
+ 'for exploring caniuse.com in your terminal.'
14
15
  spec.homepage = 'https://github.com/SidOfc/cani'
15
16
  spec.license = 'MIT'
16
17
 
17
- spec.files = Dir.chdir(File.expand_path('..', __FILE__)) do
18
+ spec.files = Dir.chdir(File.expand_path(__dir__)) do
18
19
  `git ls-files -z`.split("\x0").reject do |f|
19
20
  f.match(%r{^(test|spec|features|assets)/})
20
21
  end
21
22
  end
22
23
 
23
- spec.bindir = 'exe'
24
- spec.require_paths = ['lib']
25
- spec.executables << 'cani'
24
+ spec.bindir = 'exe'
25
+ spec.require_paths = ['lib']
26
+
27
+ spec.executables << 'cani'
26
28
 
27
29
  spec.add_runtime_dependency 'colorize'
28
30
  spec.add_runtime_dependency 'curses'
29
- spec.add_runtime_dependency 'tty-screen'
30
31
  spec.add_runtime_dependency 'json'
32
+ spec.add_runtime_dependency 'tty-screen'
31
33
 
32
- spec.add_development_dependency 'bundler', '~> 1.16'
34
+ spec.add_development_dependency 'bundler'
33
35
  spec.add_development_dependency 'pry'
34
- spec.add_development_dependency 'rake', '~> 10.0'
35
- spec.add_development_dependency 'rspec', '~> 3.0'
36
+ spec.add_development_dependency 'rake', '~> 12'
37
+ spec.add_development_dependency 'rspec'
36
38
  end
@@ -66,8 +66,8 @@ module Cani
66
66
  name = Regexp.new name.to_s.downcase.gsub(/(\W)/, '.*'), :i
67
67
  features.select do |ft|
68
68
  ft.title.downcase.match(name) ||
69
- ft.name.downcase.match(name) ||
70
- ft.description.downcase.match(name)
69
+ ft.name.downcase.match(name) ||
70
+ ft.description.downcase.match(name)
71
71
  end
72
72
  end
73
73
 
@@ -5,24 +5,24 @@ module Cani
5
5
 
6
6
  ABBR_MAP = { 'ios' => 'saf.ios' }.freeze
7
7
  LABEL_MAP = {
8
- 'ie' => 'Internet Explorer',
9
- 'edge' => 'Edge',
10
- 'ff' => 'Firefox',
11
- 'chr' => 'Chrome',
12
- 'saf' => 'Safari',
13
- 'op' => 'Opera',
8
+ 'ie' => 'Internet Explorer',
9
+ 'edge' => 'Edge',
10
+ 'ff' => 'Firefox',
11
+ 'chr' => 'Chrome',
12
+ 'saf' => 'Safari',
13
+ 'op' => 'Opera',
14
14
  'saf.ios' => 'IOS Safari',
15
- 'o.mini' => 'Opera Mini',
16
- 'and' => 'Android Browser',
17
- 'bb' => 'BlackBerry Browser',
18
- 'o.mob' => 'Opera Mobile',
15
+ 'o.mini' => 'Opera Mini',
16
+ 'and' => 'Android Browser',
17
+ 'bb' => 'BlackBerry Browser',
18
+ 'o.mob' => 'Opera Mobile',
19
19
  'chr.and' => 'Chrome for Android',
20
- 'ff.and' => 'Firefox for Android',
21
- 'ie.mob' => 'Internet Explorer Mobile',
22
- 'uc' => 'UC Browser for android',
23
- 'ss' => 'Samsung Internet',
24
- 'qq' => 'QQ Browser',
25
- 'baidu' => 'Baidu Browser'
20
+ 'ff.and' => 'Firefox for Android',
21
+ 'ie.mob' => 'Internet Explorer Mobile',
22
+ 'uc' => 'UC Browser for android',
23
+ 'ss' => 'Samsung Internet',
24
+ 'qq' => 'QQ Browser',
25
+ 'baidu' => 'Baidu Browser'
26
26
  }.freeze
27
27
 
28
28
  def initialize(attributes = {})
@@ -4,19 +4,19 @@ module Cani
4
4
  attr_reader :title, :status, :spec, :stats, :percent, :name, :browser_note_nums, :notes, :notes_by_num, :description
5
5
 
6
6
  STATUSES = {
7
- 'rec' => 'rc',
7
+ 'rec' => 'rc',
8
8
  'unoff' => 'un',
9
9
  'other' => 'ot'
10
10
  }.freeze
11
11
 
12
12
  TYPES = {
13
- 'y' => {symbol: '+', name: :default, short: :sup},
14
- 'a' => {symbol: '~', name: :partial, short: :prt},
15
- 'n' => {symbol: '-', name: :unsupported, short: :not},
16
- 'p' => {symbol: '#', name: :polyfill, short: :ply},
17
- 'x' => {symbol: '@', name: :prefix, short: :pfx},
18
- 'd' => {symbol: '!', name: :flag, short: :flg},
19
- 'u' => {symbol: '?', name: :unknown, short: :unk}
13
+ 'y' => { symbol: '+', name: :default, short: :sup },
14
+ 'a' => { symbol: '~', name: :partial, short: :prt },
15
+ 'n' => { symbol: '-', name: :unsupported, short: :not },
16
+ 'p' => { symbol: '#', name: :polyfill, short: :ply },
17
+ 'x' => { symbol: '@', name: :prefix, short: :pfx },
18
+ 'd' => { symbol: '!', name: :flag, short: :flg },
19
+ 'u' => { symbol: '?', name: :unknown, short: :unk }
20
20
  }.freeze
21
21
 
22
22
  def initialize(attributes = {})
@@ -2,33 +2,47 @@ module Cani
2
2
  class Api
3
3
  class Feature
4
4
  class Viewer
5
- attr_reader :width, :height, :feature, :browsers, :viewable, :col_width, :table_width
5
+ attr_reader :width, :height, :feature, :browsers, :viewable,
6
+ :col_width, :table_width
6
7
 
7
8
  COLOR_PAIRS = {
8
9
  # foreground colors
9
- 69 => [70, -1], # green on default (legend supported, feature status, percentage counter)
10
- 213 => [208, -1], # orange on default (legend partial, percentage counter)
11
- 195 => [160, -1], # red on default (legend unsupported, percentage counter)
12
- 133 => [134, -1], # magenta on default (legend flag, current feature status)
13
- 12 => [75, -1], # blue on default (legend prefix)
10
+
11
+ # green on default
12
+ # (legend supported, feature status, percentage counter)
13
+ 69 => [70, -1],
14
+
15
+ # orange on default
16
+ # (legend partial, percentage counter)
17
+ 213 => [208, -1],
18
+
19
+ # red on default
20
+ # (legend unsupported, percentage counter)
21
+ 195 => [160, -1],
22
+
23
+ # magenta on default
24
+ # (legend flag, current feature status)
25
+ 133 => [134, -1],
26
+
27
+ 12 => [75, -1], # blue on default (legend prefix)
14
28
  204 => [205, -1], # pink on default (legend polyfill)
15
- 99 => [239, -1], # gray on default (legend unknown)
29
+ 99 => [239, -1], # gray on default (legend unknown)
16
30
 
17
31
  # note background + foreground colors
18
- 71 => [22, 70], # dark green on green (supported feature)
32
+ 71 => [22, 70], # dark green on green (supported feature)
19
33
  209 => [130, 208], # dark orange on orange (partial feature)
20
34
  197 => [88, 160], # dark red on red (unsupported feature)
21
35
  135 => [91, 134], # dark magenta on magenta (flag features)
22
- 13 => [27, 75], # dark blue on blue (prefix feature)
36
+ 13 => [27, 75], # dark blue on blue (prefix feature)
23
37
  101 => [235, 239], # dark gray on gray (unknown features)
24
38
  206 => [127, 205], # dark pink on pink (polyfill features)
25
39
 
26
40
  # background colors
27
- 70 => [7, 70], # white on green (supported feature)
41
+ 70 => [7, 70], # white on green (supported feature)
28
42
  208 => [7, 208], # white on orange (partial feature)
29
43
  196 => [7, 160], # white on red (unsupported feature)
30
44
  134 => [7, 134], # white on magenta (flag features)
31
- 11 => [7, 75], # white on blue (prefix feature)
45
+ 11 => [7, 75], # white on blue (prefix feature)
32
46
  100 => [7, 239], # white on gray (unknown features)
33
47
  205 => [7, 205], # white on pink (polyfill features)
34
48
 
@@ -39,45 +53,48 @@ module Cani
39
53
 
40
54
  COLORS = {
41
55
  # table headers
42
- header: {fg: Curses.color_pair(254), bg: Curses.color_pair(254)},
56
+ header: { fg: Curses.color_pair(254), bg: Curses.color_pair(254) },
43
57
 
44
58
  # current era border
45
- era_border: {fg: Curses.color_pair(239), bg: Curses.color_pair(239)},
59
+ era_border: { fg: Curses.color_pair(239),
60
+ bg: Curses.color_pair(239) },
46
61
 
47
62
  # support types
48
- default: {fg: Curses.color_pair(69), bg: Curses.color_pair(70)},
49
- partial: {fg: Curses.color_pair(213), bg: Curses.color_pair(208)},
50
- prefix: {fg: Curses.color_pair(12), bg: Curses.color_pair(11)},
51
- polyfill: {fg: Curses.color_pair(204), bg: Curses.color_pair(205)},
52
- flag: {fg: Curses.color_pair(133), bg: Curses.color_pair(134)},
53
- unsupported: {fg: Curses.color_pair(195), bg: Curses.color_pair(196)},
54
- unknown: {fg: Curses.color_pair(99), bg: Curses.color_pair(100)},
63
+ default: { fg: Curses.color_pair(69), bg: Curses.color_pair(70) },
64
+ partial: { fg: Curses.color_pair(213), bg: Curses.color_pair(208) },
65
+ prefix: { fg: Curses.color_pair(12), bg: Curses.color_pair(11) },
66
+ polyfill: { fg: Curses.color_pair(204), bg: Curses.color_pair(205) },
67
+ flag: { fg: Curses.color_pair(133), bg: Curses.color_pair(134) },
68
+ unknown: { fg: Curses.color_pair(99), bg: Curses.color_pair(100) },
69
+ unsupported: { fg: Curses.color_pair(195),
70
+ bg: Curses.color_pair(196) },
55
71
 
56
72
  # statuses
57
- un: {fg: Curses.color_pair(213), bg: Curses.color_pair(208)},
58
- ot: {fg: Curses.color_pair(133), bg: Curses.color_pair(134)}
73
+ un: { fg: Curses.color_pair(213), bg: Curses.color_pair(208) },
74
+ ot: { fg: Curses.color_pair(133), bg: Curses.color_pair(134) }
59
75
  }.freeze
60
76
 
61
77
  NOTE_COLORS = {
62
- default: {fg: Curses.color_pair(71), bg: Curses.color_pair(70)},
63
- partial: {fg: Curses.color_pair(209), bg: Curses.color_pair(208)},
64
- prefix: {fg: Curses.color_pair(13), bg: Curses.color_pair(11)},
65
- polyfill: {fg: Curses.color_pair(206), bg: Curses.color_pair(205)},
66
- flag: {fg: Curses.color_pair(135), bg: Curses.color_pair(134)},
67
- unsupported: {fg: Curses.color_pair(197), bg: Curses.color_pair(196)},
68
- unknown: {fg: Curses.color_pair(101), bg: Curses.color_pair(100)},
69
- }
78
+ default: { fg: Curses.color_pair(71), bg: Curses.color_pair(70) },
79
+ partial: { fg: Curses.color_pair(209), bg: Curses.color_pair(208) },
80
+ prefix: { fg: Curses.color_pair(13), bg: Curses.color_pair(11) },
81
+ polyfill: { fg: Curses.color_pair(206), bg: Curses.color_pair(205) },
82
+ flag: { fg: Curses.color_pair(135), bg: Curses.color_pair(134) },
83
+ unknown: { fg: Curses.color_pair(101), bg: Curses.color_pair(100) },
84
+ unsupported: { fg: Curses.color_pair(197),
85
+ bg: Curses.color_pair(196) }
86
+ }.freeze
70
87
 
71
88
  PERCENT_COLORS = {
72
- 70..101 => {fg: Curses.color_pair(69), bg: Curses.color_pair(70)},
73
- 40..70 => {fg: Curses.color_pair(213), bg: Curses.color_pair(208)},
74
- 0..40 => {fg: Curses.color_pair(195), bg: Curses.color_pair(196)}
89
+ 70..101 => { fg: Curses.color_pair(69), bg: Curses.color_pair(70) },
90
+ 40..70 => { fg: Curses.color_pair(213), bg: Curses.color_pair(208) },
91
+ 0..40 => { fg: Curses.color_pair(195), bg: Curses.color_pair(196) }
75
92
  }.freeze
76
93
 
77
- ERAS = 6 # range of eras to show around current era (incl current)
78
- COMPACT = 60 # column width at which to compress the layout
79
- PADDING = 1 # horizontal cell padding
80
- MARGIN = 1 # horizontal cell margin
94
+ ERAS = 6 # range of eras to show around current era (incl current)
95
+ COMPACT = 60 # column width at which to compress the layout
96
+ PADDING = 1 # horizontal cell padding
97
+ MARKET_SHARE_THRESHHOLD = 0.5 # predefined market share threshhold
81
98
 
82
99
  def initialize(feature, browsers = Cani.api.browsers)
83
100
  @feature = feature
@@ -103,7 +120,7 @@ module Cani
103
120
  at_exit(&method(:close))
104
121
  end
105
122
 
106
- def close(*args)
123
+ def close(*_args)
107
124
  Curses.close_screen
108
125
  end
109
126
 
@@ -149,7 +166,8 @@ module Cani
149
166
  end
150
167
 
151
168
  # status positioning and drawing
152
- # when compact? draw it on the second line instead of the first line at the end of the title
169
+ # when compact? draw it on the second line instead of the
170
+ # first line at the end of the title
153
171
  cy += 1
154
172
  status_yp = offset_y + (compact? ? 1 : 0)
155
173
  status_xp = offset_x + (compact? ? table_width - status_format.size
@@ -161,7 +179,8 @@ module Cani
161
179
  end
162
180
 
163
181
  # 'more or less' predict a height that is too small
164
- # since we don't know the entire height but draw it line-by-line at the moment
182
+ # since we don't know the entire height but draw
183
+ # it line-by-line at the moment
165
184
  compact_height = height <= 40
166
185
 
167
186
  # by default, notes are only shown if visible in the actual table
@@ -173,21 +192,28 @@ module Cani
173
192
 
174
193
  # meaty part, loop through browsers to create
175
194
  # the final feature table
176
- browsers.each.with_index do |browser, x|
195
+ relevant_era_count = browsers[0...viewable].map do |browser|
196
+ era_idx = browser.most_popular_era_idx
197
+ era_range = (era_idx - (ERAS / 2.0).floor + 1)..(era_idx + (ERAS / 2.0).ceil)
198
+
199
+ era_range.map do |cur_era|
200
+ era = browser.eras[cur_era].to_s
201
+ browser.usage[era].to_f >= MARKET_SHARE_THRESHHOLD || (!era.empty? && cur_era >= era_idx - 1)
202
+ end.select { |x| x }.size
203
+ end.max
204
+
205
+ browsers[0...viewable].each.with_index do |browser, x|
177
206
  # some set up to find the current era for each browser
178
207
  # and creating a range around that to show past / coming support
179
208
  era_idx = browser.most_popular_era_idx
180
- era_range = (era_idx - (ERAS / 2.0).floor + 1)..(era_idx + (ERAS / 2.0).ceil)
209
+ era_range = (era_idx - (relevant_era_count / 2.0).floor + 1)..(era_idx + (relevant_era_count / 2.0).ceil)
181
210
  bx = offset_x + x * col_width + x
182
211
  by = offset_y + cy
183
- do_draw = x < viewable
184
212
 
185
- if do_draw
186
- # draw browser names
187
- Curses.setpos by, bx
188
- Curses.attron color(:header) do
189
- Curses.addstr browser.name.tr('_', '.').center(col_width)
190
- end
213
+ # draw browser names
214
+ Curses.setpos by, bx
215
+ Curses.attron color(:header) do
216
+ Curses.addstr browser.name.tr('_', '.').center(col_width)
191
217
  end
192
218
 
193
219
  # accordingly increment current browser y for the table header (browser names)
@@ -205,45 +231,45 @@ module Cani
205
231
  bot_pad = compact_height ? 0 : 1
206
232
  ey = by + (y * (2 + top_pad + bot_pad)) + (bot_pad.zero? && past_curr ? 1 : 0)
207
233
  note_nums = feature.browser_note_nums.fetch(browser.name, {})
208
- .fetch(era, [])
234
+ .fetch(era, [])
209
235
 
210
236
  # do not draw era's that exceed screen height
211
237
  break if (ey + (is_current ? 1 : bot_pad) + 1) >= height
212
238
 
213
- if do_draw && is_current
214
- Curses.setpos ey - top_pad - 1, bx - 1
239
+ # draw current era outline before drawing all era cells on top
240
+ if is_current
241
+ Curses.setpos ey - top_pad - 1, [bx - 1, 0].max
215
242
  Curses.attron(color(:era_border)) { Curses.addstr ' ' * (col_width + 2) }
216
243
 
217
- Curses.setpos ey + (is_current ? 1 : bot_pad) + 1, bx - 1
244
+ Curses.setpos ey + (is_current ? 1 : bot_pad) + 1, [bx - 1, 0].max
218
245
  Curses.attron(color(:era_border)) { Curses.addstr ' ' * (col_width + 2) }
219
246
  end
220
247
 
221
248
  # only show visible / relevant browsers
222
- if browser.usage[era].to_i >= 0.5 || (!era.empty? && cur_era >= era_idx - 1)
223
- if do_draw
224
- ((ey - top_pad)..(ey + (is_current ? 1 : bot_pad))).each do |ry|
225
- txt = (bot_pad.zero? && !is_current) ? (ry >= ey + (is_current ? 1 : bot_pad) ? era.to_s : ' ')
226
- : (ry == ey ? era.to_s : ' ')
227
-
228
- Curses.setpos ry, bx
229
- Curses.attron(colr) { Curses.addstr txt.center(col_width) }
230
-
231
- if is_current
232
- Curses.setpos ry, bx - 1
233
- Curses.attron(color(:era_border)) { Curses.addstr ' ' }
234
-
235
- Curses.setpos ry, offset_x + table_width + 2
236
- Curses.attron(color(:era_border)) { Curses.addstr ' ' }
237
- end
249
+ # era's can either be empty or too new to determine
250
+ # their usefulness by usage (when newer than current era).
251
+ if browser.usage[era].to_f >= MARKET_SHARE_THRESHHOLD || (!era.empty? && cur_era >= era_idx - 1)
252
+ ((ey - top_pad)..(ey + (is_current ? 1 : bot_pad))).each do |ry|
253
+ txt = (bot_pad.zero? && !is_current) ? (ry >= ey + (is_current ? 1 : bot_pad) ? era.to_s : ' ')
254
+ : (ry == ey ? era.to_s : ' ')
255
+
256
+ Curses.setpos ry, bx
257
+ Curses.attron(colr) { Curses.addstr txt.center(col_width) }
258
+
259
+ # draw current ara border inbetween the cells
260
+ if is_current
261
+ Curses.setpos ry, bx - 1
262
+ Curses.attron(color(:era_border)) { Curses.addstr ' ' }
263
+
264
+ Curses.setpos ry, offset_x + table_width + 2
265
+ Curses.attron(color(:era_border)) { Curses.addstr ' ' }
238
266
  end
239
267
  end
240
268
 
241
269
  if note_nums.any?
242
270
  notes_visible.concat(note_nums).uniq!
243
- if do_draw
244
- Curses.setpos ey - top_pad, bx
245
- Curses.attron(note_color(supp_type)) { Curses.addstr ' ' + note_nums.join(' ') }
246
- end
271
+ Curses.setpos ey - top_pad, bx
272
+ Curses.attron(note_color(supp_type)) { Curses.addstr ' ' + note_nums.join(' ') }
247
273
  end
248
274
  end
249
275
  end
@@ -253,7 +279,7 @@ module Cani
253
279
  # plus the 4 lines around the current era
254
280
  # plus the 1 line of browser names
255
281
  # plus the 2 blank lines above and below the eras
256
- cy += (ERAS - 1) * (compact_height ? 3 : 4) + ERAS
282
+ cy += (relevant_era_count - 1) * (compact_height ? 3 : 4) + relevant_era_count + (relevant_era_count % 2 == 0 ? 0 : 1)
257
283
 
258
284
  if height > cy + 3
259
285
  # print legend header
@@ -272,6 +298,7 @@ module Cani
272
298
  # showing which label belongs to which color
273
299
  if height > cy + 1
274
300
  Feature::TYPES.values.each_slice viewable do |group|
301
+ # draw legend texts at proper position
275
302
  group.compact.each.with_index do |type, lx|
276
303
  Curses.setpos offset_y + cy, offset_x + lx * col_width + lx
277
304
  Curses.attron color(type[:name], :fg) do
@@ -292,8 +319,8 @@ module Cani
292
319
  filter_vis = Cani.config.notes == 'relevant' ? notes_visible.map(&:to_s) : feature.notes_by_num.keys
293
320
 
294
321
  num_chunked = feature.notes_by_num
295
- .select { |(k, _)| filter_vis.include? k }
296
- .each_with_object({}) { |(k, nt), h| h[k] = nt.chars.each_slice(outer_width - 5).map(&:join).map(&:strip) }
322
+ .select { |(k, _)| filter_vis.include? k }
323
+ .each_with_object({}) { |(k, nt), h| h[k] = nt.chars.each_slice(outer_width - 5).map(&:join).map(&:strip) }
297
324
  notes_total = (notes_chunked.map(&:size) + num_chunked.map(&:size)).reduce(0) { |total, add| total + add }
298
325
 
299
326
  if height > cy + 2 && (notes_chunked.any? || num_chunked.any?)
@@ -308,8 +335,10 @@ module Cani
308
335
  # and one empty line below it
309
336
  cy += 2
310
337
 
338
+ # print global notes, wrapped on terminal width
311
339
  notes_chunked.each do |chunks|
312
340
  break if cy + 1 + chunks.size > height
341
+
313
342
  chunks.each do |part|
314
343
  Curses.setpos offset_y + cy, offset_x
315
344
  Curses.addstr part
@@ -319,8 +348,10 @@ module Cani
319
348
  cy += 1
320
349
  end
321
350
 
351
+ # print numbered notes, wrapped on terminal width
322
352
  num_chunked.each do |num, chunks|
323
353
  break if cy + 1 + chunks.size > height
354
+
324
355
  Curses.setpos offset_y + cy, offset_x
325
356
  Curses.attron color(:header) do
326
357
  Curses.addstr num.center(3)
@@ -367,9 +398,7 @@ module Cani
367
398
  @height, @width = IO.console.winsize
368
399
  @viewable = browsers.size
369
400
 
370
- while tablew > @width
371
- @viewable -= 1
372
- end
401
+ @viewable -= 1 while tablew >= @width
373
402
 
374
403
  @col_width = [colw, Feature::TYPES.map { |(_, h)| h[:short].size }.max + 3].max
375
404
  @table_width = tablew - 2 # vertical padding at start and end of current era line
@@ -10,14 +10,14 @@ module Cani
10
10
  NO_MODIFY_FILE = File.join(DIRECTORY, '.no-modify-shellrc').freeze
11
11
  DEFAULTS = {
12
12
  # data settings
13
- 'expire' => 86_400,
14
- 'source' => 'https://raw.githubusercontent.com/Fyrd/caniuse/master/data.json',
13
+ 'expire' => 86_400,
14
+ 'source' => 'https://raw.githubusercontent.com/Fyrd/caniuse/master/data.json',
15
15
 
16
16
  # usage settings
17
17
  'versions' => 1,
18
18
  'browsers' => %w[ie edge chrome firefox safari ios_saf opera android bb],
19
19
  'navigate' => 'always',
20
- 'notes' => 'relevant'
20
+ 'notes' => 'relevant'
21
21
  }.freeze
22
22
 
23
23
  def initialize(**opts)
@@ -44,7 +44,7 @@ module Cani
44
44
 
45
45
  def self.to_feature_row(ft)
46
46
  pc = format('%.2f%%', ft.percent).rjust 6
47
- cl = {'un' => :yellow, 'ot' => :magenta}.fetch ft.status, :green
47
+ cl = { 'un' => :yellow, 'ot' => :magenta }.fetch ft.status, :green
48
48
 
49
49
  total_len = ft.current_support.map(&:size).reduce(&:+) + pc.size + 6 + (ft.current_support.size + 2) * 3
50
50
  rem_len = [longest_title_size, 50, [dimensions.first - total_len, 24].max].min
@@ -52,19 +52,19 @@ module Cani
52
52
  tt = format("%-#{rem_len}s", ft.title.size > rem_len ? ft.title[0...rem_len].strip + '..'
53
53
  : ft.title)
54
54
 
55
- [{content: "[#{ft.status}]", color: cl}, pc,
56
- {content: tt, color: :default}, *ft.current_support]
55
+ [{ content: "[#{ft.status}]", color: cl }, pc,
56
+ { content: tt, color: :default }, *ft.current_support]
57
57
  end
58
58
 
59
59
  def self.browser_rows
60
60
  @browser_rows ||= Cani.api.browsers.map do |bwsr|
61
- [{content: bwsr.title, color: :default},
61
+ [{ content: bwsr.title, color: :default },
62
62
  'usage: ' + format('%.4f%%', bwsr.usage.values.reduce(0) { |total, add| total + add })]
63
63
  end
64
64
  end
65
65
 
66
66
  def self.browser_usage_rows(brwsr)
67
- brwsr.usage.map { |(v, u)| [{content: v, color: :default}, 'usage: ' + format('%.4f%%', u)] }.reverse
67
+ brwsr.usage.map { |(v, u)| [{ content: v, color: :default }, 'usage: ' + format('%.4f%%', u)] }.reverse
68
68
  end
69
69
 
70
70
  def self.browser_feature_rows(brwsr, version)
@@ -73,9 +73,9 @@ module Cani
73
73
  Api::Feature::TYPES.flat_map do |(status, type)|
74
74
  if (features = features_by_support.fetch(type[:name], nil))
75
75
  features.map do |feature|
76
- color = {'un' => :yellow, 'ot' => :magenta}.fetch feature[:status], :green
77
- [{content: "[#{feature[:status]}]", color: color},
78
- "[#{type[:symbol]}]", {content: feature[:title], color: :default}]
76
+ color = { 'un' => :yellow, 'ot' => :magenta }.fetch feature[:status], :green
77
+ [{ content: "[#{feature[:status]}]", color: color },
78
+ "[#{type[:symbol]}]", { content: feature[:title], color: :default }]
79
79
  end
80
80
  end
81
81
  end.compact
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Cani
4
- VERSION = '0.5.8'
4
+ VERSION = '0.5.9'.freeze
5
5
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: cani
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.5.8
4
+ version: 0.5.9
5
5
  platform: ruby
6
6
  authors:
7
7
  - Sidney Liebrand
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2019-07-28 00:00:00.000000000 Z
11
+ date: 2019-09-16 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: colorize
@@ -39,7 +39,7 @@ dependencies:
39
39
  - !ruby/object:Gem::Version
40
40
  version: '0'
41
41
  - !ruby/object:Gem::Dependency
42
- name: tty-screen
42
+ name: json
43
43
  requirement: !ruby/object:Gem::Requirement
44
44
  requirements:
45
45
  - - ">="
@@ -53,7 +53,7 @@ dependencies:
53
53
  - !ruby/object:Gem::Version
54
54
  version: '0'
55
55
  - !ruby/object:Gem::Dependency
56
- name: json
56
+ name: tty-screen
57
57
  requirement: !ruby/object:Gem::Requirement
58
58
  requirements:
59
59
  - - ">="
@@ -70,16 +70,16 @@ dependencies:
70
70
  name: bundler
71
71
  requirement: !ruby/object:Gem::Requirement
72
72
  requirements:
73
- - - "~>"
73
+ - - ">="
74
74
  - !ruby/object:Gem::Version
75
- version: '1.16'
75
+ version: '0'
76
76
  type: :development
77
77
  prerelease: false
78
78
  version_requirements: !ruby/object:Gem::Requirement
79
79
  requirements:
80
- - - "~>"
80
+ - - ">="
81
81
  - !ruby/object:Gem::Version
82
- version: '1.16'
82
+ version: '0'
83
83
  - !ruby/object:Gem::Dependency
84
84
  name: pry
85
85
  requirement: !ruby/object:Gem::Requirement
@@ -100,28 +100,28 @@ dependencies:
100
100
  requirements:
101
101
  - - "~>"
102
102
  - !ruby/object:Gem::Version
103
- version: '10.0'
103
+ version: '12'
104
104
  type: :development
105
105
  prerelease: false
106
106
  version_requirements: !ruby/object:Gem::Requirement
107
107
  requirements:
108
108
  - - "~>"
109
109
  - !ruby/object:Gem::Version
110
- version: '10.0'
110
+ version: '12'
111
111
  - !ruby/object:Gem::Dependency
112
112
  name: rspec
113
113
  requirement: !ruby/object:Gem::Requirement
114
114
  requirements:
115
- - - "~>"
115
+ - - ">="
116
116
  - !ruby/object:Gem::Version
117
- version: '3.0'
117
+ version: '0'
118
118
  type: :development
119
119
  prerelease: false
120
120
  version_requirements: !ruby/object:Gem::Requirement
121
121
  requirements:
122
- - - "~>"
122
+ - - ">="
123
123
  - !ruby/object:Gem::Version
124
- version: '3.0'
124
+ version: '0'
125
125
  description: An interactive TUI (using FZF / Curses) for exploring caniuse.com in
126
126
  your terminal.
127
127
  email:
@@ -133,7 +133,9 @@ extra_rdoc_files: []
133
133
  files:
134
134
  - ".gitignore"
135
135
  - ".rspec"
136
+ - ".rubocop.yml"
136
137
  - ".travis.yml"
138
+ - CHANGELOG.md
137
139
  - CODE_OF_CONDUCT.md
138
140
  - Gemfile
139
141
  - LICENSE.txt
@@ -175,7 +177,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
175
177
  - !ruby/object:Gem::Version
176
178
  version: '0'
177
179
  requirements: []
178
- rubygems_version: 3.0.3
180
+ rubyforge_project:
181
+ rubygems_version: 2.6.8
179
182
  signing_key:
180
183
  specification_version: 4
181
184
  summary: A simple caniuse CLI.