cani 0.5.8 → 0.5.9
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 +5 -5
- data/.rubocop.yml +1 -0
- data/CHANGELOG.md +15 -0
- data/Gemfile +1 -1
- data/README.md +10 -18
- data/cani.gemspec +11 -9
- data/lib/cani/api.rb +2 -2
- data/lib/cani/api/browser.rb +16 -16
- data/lib/cani/api/feature.rb +8 -8
- data/lib/cani/api/feature/viewer.rb +108 -79
- data/lib/cani/config.rb +3 -3
- data/lib/cani/fzf.rb +8 -8
- data/lib/cani/version.rb +1 -1
- metadata +18 -15
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
|
-
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
2
|
+
SHA1:
|
|
3
|
+
metadata.gz: bbdbb28b9c3709f04c106775b5d019f7d4e29177
|
|
4
|
+
data.tar.gz: cb812356aac2f7ad341f8d80fe16db97539813b4
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 01ffd79c7dcbb0aae80cac9585d687eaf00c2226f617d4a70cb409384d9938373363e5b38d93c8988f6e92a525ce88774cb0aa922a3435cf4381b1dbb203d8f0
|
|
7
|
+
data.tar.gz: fc4287ccb47965a06f6218af9de4d67d1ff63d677687d5042fd3df9bb9e13e630463727269bb08a89f2c58d31a05ee66739578b9a97a61a329983306e8fdd781
|
data/.rubocop.yml
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
TargetRubyVersion: "2.1"
|
data/CHANGELOG.md
ADDED
|
@@ -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
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
|
|
231
|
-
[un] 75.85% Animated PNG (APNG)
|
|
232
|
-
[ls] 94.32% Video element
|
|
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**
|
data/cani.gemspec
CHANGED
|
@@ -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)
|
|
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(
|
|
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
|
|
24
|
-
spec.require_paths
|
|
25
|
-
|
|
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'
|
|
34
|
+
spec.add_development_dependency 'bundler'
|
|
33
35
|
spec.add_development_dependency 'pry'
|
|
34
|
-
spec.add_development_dependency 'rake', '~>
|
|
35
|
-
spec.add_development_dependency 'rspec'
|
|
36
|
+
spec.add_development_dependency 'rake', '~> 12'
|
|
37
|
+
spec.add_development_dependency 'rspec'
|
|
36
38
|
end
|
data/lib/cani/api.rb
CHANGED
|
@@ -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
|
-
|
|
70
|
-
|
|
69
|
+
ft.name.downcase.match(name) ||
|
|
70
|
+
ft.description.downcase.match(name)
|
|
71
71
|
end
|
|
72
72
|
end
|
|
73
73
|
|
data/lib/cani/api/browser.rb
CHANGED
|
@@ -5,24 +5,24 @@ module Cani
|
|
|
5
5
|
|
|
6
6
|
ABBR_MAP = { 'ios' => 'saf.ios' }.freeze
|
|
7
7
|
LABEL_MAP = {
|
|
8
|
-
'ie'
|
|
9
|
-
'edge'
|
|
10
|
-
'ff'
|
|
11
|
-
'chr'
|
|
12
|
-
'saf'
|
|
13
|
-
'op'
|
|
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'
|
|
16
|
-
'and'
|
|
17
|
-
'bb'
|
|
18
|
-
'o.mob'
|
|
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'
|
|
21
|
-
'ie.mob'
|
|
22
|
-
'uc'
|
|
23
|
-
'ss'
|
|
24
|
-
'qq'
|
|
25
|
-
'baidu'
|
|
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 = {})
|
data/lib/cani/api/feature.rb
CHANGED
|
@@ -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'
|
|
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,
|
|
5
|
+
attr_reader :width, :height, :feature, :browsers, :viewable,
|
|
6
|
+
:col_width, :table_width
|
|
6
7
|
|
|
7
8
|
COLOR_PAIRS = {
|
|
8
9
|
# foreground colors
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
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
|
|
29
|
+
99 => [239, -1], # gray on default (legend unknown)
|
|
16
30
|
|
|
17
31
|
# note background + foreground colors
|
|
18
|
-
71
|
|
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
|
|
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
|
|
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
|
|
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:
|
|
56
|
+
header: { fg: Curses.color_pair(254), bg: Curses.color_pair(254) },
|
|
43
57
|
|
|
44
58
|
# current era border
|
|
45
|
-
era_border:
|
|
59
|
+
era_border: { fg: Curses.color_pair(239),
|
|
60
|
+
bg: Curses.color_pair(239) },
|
|
46
61
|
|
|
47
62
|
# support types
|
|
48
|
-
default:
|
|
49
|
-
partial:
|
|
50
|
-
prefix:
|
|
51
|
-
polyfill:
|
|
52
|
-
flag:
|
|
53
|
-
|
|
54
|
-
|
|
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:
|
|
58
|
-
ot:
|
|
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:
|
|
63
|
-
partial:
|
|
64
|
-
prefix:
|
|
65
|
-
polyfill:
|
|
66
|
-
flag:
|
|
67
|
-
|
|
68
|
-
|
|
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),
|
|
73
|
-
40..70
|
|
74
|
-
0..40
|
|
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
|
|
78
|
-
COMPACT
|
|
79
|
-
PADDING
|
|
80
|
-
|
|
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(*
|
|
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
|
|
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
|
|
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.
|
|
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 - (
|
|
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
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
Curses.
|
|
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
|
-
|
|
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
|
-
|
|
214
|
-
|
|
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
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
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
|
-
|
|
244
|
-
|
|
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 += (
|
|
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
|
-
|
|
296
|
-
|
|
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
|
|
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
|
data/lib/cani/config.rb
CHANGED
|
@@ -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'
|
|
14
|
-
'source'
|
|
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'
|
|
20
|
+
'notes' => 'relevant'
|
|
21
21
|
}.freeze
|
|
22
22
|
|
|
23
23
|
def initialize(**opts)
|
data/lib/cani/fzf.rb
CHANGED
|
@@ -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
|
data/lib/cani/version.rb
CHANGED
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.
|
|
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-
|
|
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:
|
|
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:
|
|
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: '
|
|
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: '
|
|
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: '
|
|
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: '
|
|
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: '
|
|
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: '
|
|
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
|
-
|
|
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.
|