cani 0.1.2 → 0.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
 - data/Gemfile.lock +3 -1
 - data/cani.gemspec +2 -1
 - data/exe/cani +1 -14
 - data/lib/cani/api/browser.rb +21 -3
 - data/lib/cani/api/feature/viewer.rb +293 -0
 - data/lib/cani/api/feature.rb +17 -13
 - data/lib/cani/api.rb +14 -9
 - data/lib/cani/completions.rb +23 -12
 - data/lib/cani/config.rb +111 -0
 - data/lib/cani/fzf.rb +1 -1
 - data/lib/cani/version.rb +1 -1
 - data/lib/cani.rb +47 -11
 - data/shell/completions/functions.bash +3 -0
 - data/shell/completions/functions.zsh +3 -0
 - metadata +28 -13
 - data/lib/cani/api/config.rb +0 -121
 
    
        checksums.yaml
    CHANGED
    
    | 
         @@ -1,7 +1,7 @@ 
     | 
|
| 
       1 
1 
     | 
    
         
             
            ---
         
     | 
| 
       2 
2 
     | 
    
         
             
            SHA256:
         
     | 
| 
       3 
     | 
    
         
            -
              metadata.gz:  
     | 
| 
       4 
     | 
    
         
            -
              data.tar.gz:  
     | 
| 
      
 3 
     | 
    
         
            +
              metadata.gz: 9de90bea20bfdaed9282223a8f2326c9a57515cba421460382388152613a92d5
         
     | 
| 
      
 4 
     | 
    
         
            +
              data.tar.gz: a8dfeba0857de5d4e8a35e3971aa05feb3b1d60aca948d3383357074e449b581
         
     | 
| 
       5 
5 
     | 
    
         
             
            SHA512:
         
     | 
| 
       6 
     | 
    
         
            -
              metadata.gz:  
     | 
| 
       7 
     | 
    
         
            -
              data.tar.gz:  
     | 
| 
      
 6 
     | 
    
         
            +
              metadata.gz: 63e0d0bf53d8e72915b0c5fe5f7997e7f3dd5341b973dc37c3180fe3b4a91c7f35370d43f57ccc717c24ad3d12a42b6a9bbb413de5afb2901ae0ed66b4c4678d
         
     | 
| 
      
 7 
     | 
    
         
            +
              data.tar.gz: 514d3cf80000acd736d86f4bc5fdb991ed6d43a986cb6469760be5d92b4e1620ad4331fd34078906e17a3f1d16d17db11c52d2e4d63abba9560cee436b01d19b
         
     | 
    
        data/Gemfile.lock
    CHANGED
    
    
    
        data/cani.gemspec
    CHANGED
    
    | 
         @@ -23,10 +23,11 @@ Gem::Specification.new do |spec| 
     | 
|
| 
       23 
23 
     | 
    
         
             
              spec.require_paths = ['lib']
         
     | 
| 
       24 
24 
     | 
    
         | 
| 
       25 
25 
     | 
    
         
             
              spec.add_runtime_dependency 'colorize'
         
     | 
| 
      
 26 
     | 
    
         
            +
              spec.add_runtime_dependency 'curses'
         
     | 
| 
       26 
27 
     | 
    
         
             
              spec.add_runtime_dependency 'json'
         
     | 
| 
       27 
28 
     | 
    
         | 
| 
       28 
29 
     | 
    
         
             
              spec.add_development_dependency 'bundler', '~> 1.16'
         
     | 
| 
       29 
     | 
    
         
            -
              spec.add_development_dependency 'rake', '~> 10.0'
         
     | 
| 
       30 
30 
     | 
    
         
             
              spec.add_development_dependency 'pry'
         
     | 
| 
      
 31 
     | 
    
         
            +
              spec.add_development_dependency 'rake', '~> 10.0'
         
     | 
| 
       31 
32 
     | 
    
         
             
              spec.add_development_dependency 'rspec', '~> 3.0'
         
     | 
| 
       32 
33 
     | 
    
         
             
            end
         
     | 
    
        data/exe/cani
    CHANGED
    
    | 
         @@ -4,17 +4,4 @@ 
     | 
|
| 
       4 
4 
     | 
    
         
             
            require 'bundler/setup'
         
     | 
| 
       5 
5 
     | 
    
         
             
            require 'cani'
         
     | 
| 
       6 
6 
     | 
    
         | 
| 
       7 
     | 
    
         
            -
             
     | 
| 
       8 
     | 
    
         
            -
            # argument in ARGV.
         
     | 
| 
       9 
     | 
    
         
            -
            cmd ||= Cani.api.config.args.first
         
     | 
| 
       10 
     | 
    
         
            -
             
     | 
| 
       11 
     | 
    
         
            -
            # refresh all completions after new data has been fetched
         
     | 
| 
       12 
     | 
    
         
            -
            Cani::Completions.install! if Cani.api.updated?
         
     | 
| 
       13 
     | 
    
         
            -
             
     | 
| 
       14 
     | 
    
         
            -
            if cmd && Cani.respond_to?(cmd)
         
     | 
| 
       15 
     | 
    
         
            -
              # if the command is recognized, execute it
         
     | 
| 
       16 
     | 
    
         
            -
              Cani.send cmd
         
     | 
| 
       17 
     | 
    
         
            -
            else
         
     | 
| 
       18 
     | 
    
         
            -
              # otherwise, display help message
         
     | 
| 
       19 
     | 
    
         
            -
              Cani.help
         
     | 
| 
       20 
     | 
    
         
            -
            end
         
     | 
| 
      
 7 
     | 
    
         
            +
            Cani.exec! ARGV[0], *ARGV[1..-1]
         
     | 
    
        data/lib/cani/api/browser.rb
    CHANGED
    
    | 
         @@ -1,7 +1,7 @@ 
     | 
|
| 
       1 
1 
     | 
    
         
             
            module Cani
         
     | 
| 
       2 
2 
     | 
    
         
             
              class Api
         
     | 
| 
       3 
3 
     | 
    
         
             
                class Browser
         
     | 
| 
       4 
     | 
    
         
            -
                  attr_reader :name, :title, :prefix, :type, :versions, :usage, :abbr, :label
         
     | 
| 
      
 4 
     | 
    
         
            +
                  attr_reader :name, :title, :prefix, :type, :versions, :usage, :abbr, :label, :eras
         
     | 
| 
       5 
5 
     | 
    
         | 
| 
       6 
6 
     | 
    
         
             
                  ABBR_MAP  = { 'ios' => 'saf.ios' }.freeze
         
     | 
| 
       7 
7 
     | 
    
         
             
                  LABEL_MAP = {
         
     | 
| 
         @@ -34,12 +34,30 @@ module Cani 
     | 
|
| 
       34 
34 
     | 
    
         
             
                    @title    = attributes['browser'].downcase
         
     | 
| 
       35 
35 
     | 
    
         
             
                    @prefix   = attributes['prefix'].downcase
         
     | 
| 
       36 
36 
     | 
    
         
             
                    @type     = attributes['type'].downcase
         
     | 
| 
       37 
     | 
    
         
            -
                    @usage    = attributes['usage_global']
         
     | 
| 
      
 37 
     | 
    
         
            +
                    @usage    = attributes['usage_global'].each_with_object({}) do |(v, u), h|
         
     | 
| 
      
 38 
     | 
    
         
            +
                      v.split('-').each { |ver| h[ver] = u }
         
     | 
| 
      
 39 
     | 
    
         
            +
                    end
         
     | 
| 
      
 40 
     | 
    
         
            +
                    @eras = attributes['versions'].each_with_object([]) do |v, a|
         
     | 
| 
      
 41 
     | 
    
         
            +
                      if v
         
     | 
| 
      
 42 
     | 
    
         
            +
                        v.split('-').each { |ver| a << ver }
         
     | 
| 
      
 43 
     | 
    
         
            +
                      else
         
     | 
| 
      
 44 
     | 
    
         
            +
                        a << v
         
     | 
| 
      
 45 
     | 
    
         
            +
                      end
         
     | 
| 
      
 46 
     | 
    
         
            +
                    end
         
     | 
| 
       38 
47 
     | 
    
         
             
                    @versions = @usage.keys
         
     | 
| 
      
 48 
     | 
    
         
            +
                    @features = {}
         
     | 
| 
      
 49 
     | 
    
         
            +
                  end
         
     | 
| 
      
 50 
     | 
    
         
            +
             
     | 
| 
      
 51 
     | 
    
         
            +
                  def most_popular_era_idx
         
     | 
| 
      
 52 
     | 
    
         
            +
                    eras.find_index usage.sort_by { |_, v| -v }.first.first
         
     | 
| 
      
 53 
     | 
    
         
            +
                  end
         
     | 
| 
      
 54 
     | 
    
         
            +
             
     | 
| 
      
 55 
     | 
    
         
            +
                  def max_column_width
         
     | 
| 
      
 56 
     | 
    
         
            +
                    [name.size, versions.map(&:size).max].max
         
     | 
| 
       39 
57 
     | 
    
         
             
                  end
         
     | 
| 
       40 
58 
     | 
    
         | 
| 
       41 
59 
     | 
    
         
             
                  def features_for(version)
         
     | 
| 
       42 
     | 
    
         
            -
                    @features ||= Cani.api.features.each_with_object({}) do |ft, h|
         
     | 
| 
      
 60 
     | 
    
         
            +
                    @features[version] ||= Cani.api.features.each_with_object({}) do |ft, h|
         
     | 
| 
       43 
61 
     | 
    
         
             
                      type = ft.support_in name, version
         
     | 
| 
       44 
62 
     | 
    
         
             
                      (h[type] ||= []) << { support: type, title: ft.title,
         
     | 
| 
       45 
63 
     | 
    
         
             
                                            status: ft.status, percent: ft.percent }
         
     | 
| 
         @@ -0,0 +1,293 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            module Cani
         
     | 
| 
      
 2 
     | 
    
         
            +
              class Api
         
     | 
| 
      
 3 
     | 
    
         
            +
                class Feature
         
     | 
| 
      
 4 
     | 
    
         
            +
                  class Viewer
         
     | 
| 
      
 5 
     | 
    
         
            +
                    attr_reader :width, :height, :feature, :browsers, :viewable, :col_width, :table_width
         
     | 
| 
      
 6 
     | 
    
         
            +
             
     | 
| 
      
 7 
     | 
    
         
            +
                    COLOR_PAIRS = {
         
     | 
| 
      
 8 
     | 
    
         
            +
                      # foreground colors
         
     | 
| 
      
 9 
     | 
    
         
            +
                      69  => [70,  -1], # green on default   (legend supported, feature status, percentage counter)
         
     | 
| 
      
 10 
     | 
    
         
            +
                      213 => [214, -1], # orange on default  (legend partial, percentage counter)
         
     | 
| 
      
 11 
     | 
    
         
            +
                      195 => [9,   -1], # red on default     (legend unsupported, percentage counter)
         
     | 
| 
      
 12 
     | 
    
         
            +
                      133 => [128, -1], # magenta on default (legend flag, current feature status)
         
     | 
| 
      
 13 
     | 
    
         
            +
                      12  => [75,  -1], # blue on default    (legend prefix)
         
     | 
| 
      
 14 
     | 
    
         
            +
                      204 => [205, -1], # pink on default    (legend polyfill)
         
     | 
| 
      
 15 
     | 
    
         
            +
                      99  => [8,   -1], # gray on default    (legend unknown)
         
     | 
| 
      
 16 
     | 
    
         
            +
             
     | 
| 
      
 17 
     | 
    
         
            +
             
     | 
| 
      
 18 
     | 
    
         
            +
                      # background colors
         
     | 
| 
      
 19 
     | 
    
         
            +
                      70  => [7,  70], # white on green      (supported feature)
         
     | 
| 
      
 20 
     | 
    
         
            +
                      208 => [7, 214], # white on orange     (partial feature)
         
     | 
| 
      
 21 
     | 
    
         
            +
                      196 => [7,   9], # white on red        (unsupported feature)
         
     | 
| 
      
 22 
     | 
    
         
            +
                      134 => [7, 128], # white on magenta    (flag features)
         
     | 
| 
      
 23 
     | 
    
         
            +
                      11  => [7,  75], # white on blue       (prefix feature)
         
     | 
| 
      
 24 
     | 
    
         
            +
                      100 => [7,   8], # white on gray       (unknown features)
         
     | 
| 
      
 25 
     | 
    
         
            +
                      205 => [7, 205], # white on pink       (polyfill features)
         
     | 
| 
      
 26 
     | 
    
         
            +
             
     | 
| 
      
 27 
     | 
    
         
            +
                      # misc / one-off
         
     | 
| 
      
 28 
     | 
    
         
            +
                      254 => [238, 255], # black on light gray (browser names, legend title)
         
     | 
| 
      
 29 
     | 
    
         
            +
                    }.freeze
         
     | 
| 
      
 30 
     | 
    
         
            +
             
     | 
| 
      
 31 
     | 
    
         
            +
                    COLORS = {
         
     | 
| 
      
 32 
     | 
    
         
            +
                      # table headers
         
     | 
| 
      
 33 
     | 
    
         
            +
                      header:      {fg: Curses.color_pair(254), bg: Curses.color_pair(254)},
         
     | 
| 
      
 34 
     | 
    
         
            +
             
     | 
| 
      
 35 
     | 
    
         
            +
                      # support types
         
     | 
| 
      
 36 
     | 
    
         
            +
                      default:     {fg: Curses.color_pair(69),  bg: Curses.color_pair(70)},
         
     | 
| 
      
 37 
     | 
    
         
            +
                      partial:     {fg: Curses.color_pair(213), bg: Curses.color_pair(208)},
         
     | 
| 
      
 38 
     | 
    
         
            +
                      prefix:      {fg: Curses.color_pair(12),  bg: Curses.color_pair(11)},
         
     | 
| 
      
 39 
     | 
    
         
            +
                      polyfill:    {fg: Curses.color_pair(204), bg: Curses.color_pair(205)},
         
     | 
| 
      
 40 
     | 
    
         
            +
                      flag:        {fg: Curses.color_pair(133), bg: Curses.color_pair(134)},
         
     | 
| 
      
 41 
     | 
    
         
            +
                      unsupported: {fg: Curses.color_pair(195), bg: Curses.color_pair(196)},
         
     | 
| 
      
 42 
     | 
    
         
            +
                      unknown:     {fg: Curses.color_pair(99),  bg: Curses.color_pair(100)},
         
     | 
| 
      
 43 
     | 
    
         
            +
             
     | 
| 
      
 44 
     | 
    
         
            +
                      # statuses
         
     | 
| 
      
 45 
     | 
    
         
            +
                      un:          {fg: Curses.color_pair(213), bg: Curses.color_pair(208)},
         
     | 
| 
      
 46 
     | 
    
         
            +
                      ot:          {fg: Curses.color_pair(133), bg: Curses.color_pair(134)}
         
     | 
| 
      
 47 
     | 
    
         
            +
                    }.freeze
         
     | 
| 
      
 48 
     | 
    
         
            +
             
     | 
| 
      
 49 
     | 
    
         
            +
                    PERCENT_COLORS = {
         
     | 
| 
      
 50 
     | 
    
         
            +
                      70..101 => {fg: Curses.color_pair(69),  bg: Curses.color_pair(70)},
         
     | 
| 
      
 51 
     | 
    
         
            +
                      40..70  => {fg: Curses.color_pair(213), bg: Curses.color_pair(208)},
         
     | 
| 
      
 52 
     | 
    
         
            +
                      0..40   => {fg: Curses.color_pair(195), bg: Curses.color_pair(196)}
         
     | 
| 
      
 53 
     | 
    
         
            +
                    }.freeze
         
     | 
| 
      
 54 
     | 
    
         
            +
             
     | 
| 
      
 55 
     | 
    
         
            +
                    ERAS    = 6  # range of eras to show around current era (incl current)
         
     | 
| 
      
 56 
     | 
    
         
            +
                    COMPACT = 60 # column width at which to compress the layout
         
     | 
| 
      
 57 
     | 
    
         
            +
                    PADDING = 1  # horizontal cell padding
         
     | 
| 
      
 58 
     | 
    
         
            +
                    MARGIN  = 1  # horizontal cell margin
         
     | 
| 
      
 59 
     | 
    
         
            +
             
     | 
| 
      
 60 
     | 
    
         
            +
                    def initialize(feature, browsers = Cani.api.browsers)
         
     | 
| 
      
 61 
     | 
    
         
            +
                      @feature  = feature
         
     | 
| 
      
 62 
     | 
    
         
            +
                      @browsers = browsers
         
     | 
| 
      
 63 
     | 
    
         
            +
                      @viewable = browsers.size
         
     | 
| 
      
 64 
     | 
    
         
            +
             
     | 
| 
      
 65 
     | 
    
         
            +
                      resize
         
     | 
| 
      
 66 
     | 
    
         
            +
             
     | 
| 
      
 67 
     | 
    
         
            +
                      Curses.init_screen
         
     | 
| 
      
 68 
     | 
    
         
            +
                      Curses.curs_set 0
         
     | 
| 
      
 69 
     | 
    
         
            +
                      Curses.noecho
         
     | 
| 
      
 70 
     | 
    
         
            +
                      Curses.cbreak
         
     | 
| 
      
 71 
     | 
    
         
            +
             
     | 
| 
      
 72 
     | 
    
         
            +
                      if Curses.has_colors?
         
     | 
| 
      
 73 
     | 
    
         
            +
                        Curses.use_default_colors
         
     | 
| 
      
 74 
     | 
    
         
            +
                        Curses.start_color
         
     | 
| 
      
 75 
     | 
    
         
            +
                      end
         
     | 
| 
      
 76 
     | 
    
         
            +
             
     | 
| 
      
 77 
     | 
    
         
            +
                      COLOR_PAIRS.each do |(cn, clp)|
         
     | 
| 
      
 78 
     | 
    
         
            +
                        Curses.init_pair cn, *clp
         
     | 
| 
      
 79 
     | 
    
         
            +
                      end
         
     | 
| 
      
 80 
     | 
    
         
            +
             
     | 
| 
      
 81 
     | 
    
         
            +
                      trap('INT', &method(:close))
         
     | 
| 
      
 82 
     | 
    
         
            +
                      at_exit(&method(:close))
         
     | 
| 
      
 83 
     | 
    
         
            +
                    end
         
     | 
| 
      
 84 
     | 
    
         
            +
             
     | 
| 
      
 85 
     | 
    
         
            +
                    def close(*args)
         
     | 
| 
      
 86 
     | 
    
         
            +
                      Curses.close_screen
         
     | 
| 
      
 87 
     | 
    
         
            +
                    end
         
     | 
| 
      
 88 
     | 
    
         
            +
             
     | 
| 
      
 89 
     | 
    
         
            +
                    def draw
         
     | 
| 
      
 90 
     | 
    
         
            +
                      Curses.clear
         
     | 
| 
      
 91 
     | 
    
         
            +
             
     | 
| 
      
 92 
     | 
    
         
            +
                      percent_num   = format '%.2f%%', feature.percent
         
     | 
| 
      
 93 
     | 
    
         
            +
                      status_format = "[#{feature.status}]"
         
     | 
| 
      
 94 
     | 
    
         
            +
                      percent_label = compact? ? '' : 'support: '
         
     | 
| 
      
 95 
     | 
    
         
            +
                      legend_format = 'legend'.center table_width
         
     | 
| 
      
 96 
     | 
    
         
            +
             
     | 
| 
      
 97 
     | 
    
         
            +
                      title_size    = [table_width - percent_num.size - percent_label.size - status_format.size - 3, 1].max
         
     | 
| 
      
 98 
     | 
    
         
            +
                      title_size   += status_format.size if compact?
         
     | 
| 
      
 99 
     | 
    
         
            +
                      title_chunks  = feature.title.chars.each_slice(title_size).map { |chrs| chrs.compact.join }
         
     | 
| 
      
 100 
     | 
    
         
            +
             
     | 
| 
      
 101 
     | 
    
         
            +
                      type_count    = Feature::TYPES.keys.size
         
     | 
| 
      
 102 
     | 
    
         
            +
                      offset_x      = ((width - table_width) / 2.0).floor
         
     | 
| 
      
 103 
     | 
    
         
            +
                      offset_y      = ((height - ERAS - title_chunks.size - 10 - (type_count / [type_count, viewable].min.to_f).ceil) / 2.0).floor
         
     | 
| 
      
 104 
     | 
    
         
            +
                      cy            = 0
         
     | 
| 
      
 105 
     | 
    
         
            +
             
     | 
| 
      
 106 
     | 
    
         
            +
                      # positioning and drawing of percentage
         
     | 
| 
      
 107 
     | 
    
         
            +
                      perc_num_xs = table_width - percent_num.size
         
     | 
| 
      
 108 
     | 
    
         
            +
                      Curses.setpos offset_y + cy, offset_x + perc_num_xs
         
     | 
| 
      
 109 
     | 
    
         
            +
                      Curses.attron percent_color(feature.percent) do
         
     | 
| 
      
 110 
     | 
    
         
            +
                        Curses.addstr percent_num
         
     | 
| 
      
 111 
     | 
    
         
            +
                      end
         
     | 
| 
      
 112 
     | 
    
         
            +
             
     | 
| 
      
 113 
     | 
    
         
            +
                      # positioning and drawing of 'support: ' text
         
     | 
| 
      
 114 
     | 
    
         
            +
                      # ditch this part all together when in compact mode
         
     | 
| 
      
 115 
     | 
    
         
            +
                      unless compact?
         
     | 
| 
      
 116 
     | 
    
         
            +
                        perc_lbl_xs = perc_num_xs - percent_label.size
         
     | 
| 
      
 117 
     | 
    
         
            +
                        Curses.setpos offset_y + cy, offset_x + perc_lbl_xs
         
     | 
| 
      
 118 
     | 
    
         
            +
                        Curses.addstr percent_label
         
     | 
| 
      
 119 
     | 
    
         
            +
                      end
         
     | 
| 
      
 120 
     | 
    
         
            +
             
     | 
| 
      
 121 
     | 
    
         
            +
                      # draw possibly multi-line feature title
         
     | 
| 
      
 122 
     | 
    
         
            +
                      title_chunks.each do |part|
         
     | 
| 
      
 123 
     | 
    
         
            +
                        Curses.setpos offset_y + cy, offset_x
         
     | 
| 
      
 124 
     | 
    
         
            +
                        Curses.addstr part
         
     | 
| 
      
 125 
     | 
    
         
            +
             
     | 
| 
      
 126 
     | 
    
         
            +
                        cy += 1
         
     | 
| 
      
 127 
     | 
    
         
            +
                      end
         
     | 
| 
      
 128 
     | 
    
         
            +
             
     | 
| 
      
 129 
     | 
    
         
            +
                      # status positioning and drawing
         
     | 
| 
      
 130 
     | 
    
         
            +
                      # when compact? draw it on the second line instead of the first line at the end of the title
         
     | 
| 
      
 131 
     | 
    
         
            +
                      cy       += 1
         
     | 
| 
      
 132 
     | 
    
         
            +
                      status_yp = offset_y + (compact? ? 1 : 0)
         
     | 
| 
      
 133 
     | 
    
         
            +
                      status_xp = offset_x + (compact? ? table_width - status_format.size
         
     | 
| 
      
 134 
     | 
    
         
            +
                                                       : [title_size, feature.title.size].min + 1)
         
     | 
| 
      
 135 
     | 
    
         
            +
             
     | 
| 
      
 136 
     | 
    
         
            +
                      Curses.setpos status_yp, status_xp
         
     | 
| 
      
 137 
     | 
    
         
            +
                      Curses.attron status_color(feature.status) do
         
     | 
| 
      
 138 
     | 
    
         
            +
                        Curses.addstr status_format
         
     | 
| 
      
 139 
     | 
    
         
            +
                      end
         
     | 
| 
      
 140 
     | 
    
         
            +
             
     | 
| 
      
 141 
     | 
    
         
            +
                      # meaty part, loop through browsers to create
         
     | 
| 
      
 142 
     | 
    
         
            +
                      # the final feature table
         
     | 
| 
      
 143 
     | 
    
         
            +
                      browsers[0...viewable].each.with_index do |browser, x|
         
     | 
| 
      
 144 
     | 
    
         
            +
                        # some set up to find the current era for each browser
         
     | 
| 
      
 145 
     | 
    
         
            +
                        # and creating a range around that to show past / coming support
         
     | 
| 
      
 146 
     | 
    
         
            +
                        era_idx   = browser.most_popular_era_idx
         
     | 
| 
      
 147 
     | 
    
         
            +
                        era_range = (era_idx - (ERAS / 2.0).floor + 1)..(era_idx + (ERAS / 2.0).ceil)
         
     | 
| 
      
 148 
     | 
    
         
            +
                        bx        = offset_x + x * col_width + x
         
     | 
| 
      
 149 
     | 
    
         
            +
                        by        = offset_y + cy
         
     | 
| 
      
 150 
     | 
    
         
            +
             
     | 
| 
      
 151 
     | 
    
         
            +
                        # draw browser names
         
     | 
| 
      
 152 
     | 
    
         
            +
                        Curses.setpos by, bx
         
     | 
| 
      
 153 
     | 
    
         
            +
                        Curses.attron color(:header) do
         
     | 
| 
      
 154 
     | 
    
         
            +
                          Curses.addstr browser.name.tr('_', '.').center(col_width)
         
     | 
| 
      
 155 
     | 
    
         
            +
                        end
         
     | 
| 
      
 156 
     | 
    
         
            +
             
     | 
| 
      
 157 
     | 
    
         
            +
                        # accordingly increment current browser y for the table header (browser names)
         
     | 
| 
      
 158 
     | 
    
         
            +
                        # and an additional empty line below the table header
         
     | 
| 
      
 159 
     | 
    
         
            +
                        by += 2
         
     | 
| 
      
 160 
     | 
    
         
            +
             
     | 
| 
      
 161 
     | 
    
         
            +
                        # draw era's for the current browser
         
     | 
| 
      
 162 
     | 
    
         
            +
                        era_range.each.with_index do |cur_era, y|
         
     | 
| 
      
 163 
     | 
    
         
            +
                          era  = browser.eras[cur_era].to_s
         
     | 
| 
      
 164 
     | 
    
         
            +
                          colr = color(feature.support_in(browser.name, era))
         
     | 
| 
      
 165 
     | 
    
         
            +
             
     | 
| 
      
 166 
     | 
    
         
            +
                          # since the current era versions are displayed as 3-line rows
         
     | 
| 
      
 167 
     | 
    
         
            +
                          # with an empty line before and after them, when we are at the current
         
     | 
| 
      
 168 
     | 
    
         
            +
                          # era we increment era y by an additional 2 for the lines above,
         
     | 
| 
      
 169 
     | 
    
         
            +
                          # whenever we are past the current era, increment by 2 for above plus 2
         
     | 
| 
      
 170 
     | 
    
         
            +
                          # extra lines below the current era
         
     | 
| 
      
 171 
     | 
    
         
            +
                          ey = by + y + (cur_era == era_idx ? 2 : (cur_era > era_idx ? 4 : 0))
         
     | 
| 
      
 172 
     | 
    
         
            +
             
     | 
| 
      
 173 
     | 
    
         
            +
                          # only show relevant browsers
         
     | 
| 
      
 174 
     | 
    
         
            +
                          if browser.usage[era].to_i >= 0.5 || (!era.empty? && cur_era >= era_idx)
         
     | 
| 
      
 175 
     | 
    
         
            +
                            Curses.setpos ey, bx
         
     | 
| 
      
 176 
     | 
    
         
            +
                            Curses.attron colr do
         
     | 
| 
      
 177 
     | 
    
         
            +
                              Curses.addstr era.center(col_width)
         
     | 
| 
      
 178 
     | 
    
         
            +
                            end
         
     | 
| 
      
 179 
     | 
    
         
            +
             
     | 
| 
      
 180 
     | 
    
         
            +
                            # previously, we only skipped some lines in order to create
         
     | 
| 
      
 181 
     | 
    
         
            +
                            # enough space to create the 3-line current era
         
     | 
| 
      
 182 
     | 
    
         
            +
                            # this snippet fills the line before and after the current era
         
     | 
| 
      
 183 
     | 
    
         
            +
                            # with the same color that the era has for that browser / feature
         
     | 
| 
      
 184 
     | 
    
         
            +
                            if cur_era == era_idx
         
     | 
| 
      
 185 
     | 
    
         
            +
                              [-1, 1].each do |relative_y|
         
     | 
| 
      
 186 
     | 
    
         
            +
                                Curses.setpos ey - relative_y, bx
         
     | 
| 
      
 187 
     | 
    
         
            +
                                Curses.attron colr do
         
     | 
| 
      
 188 
     | 
    
         
            +
                                  Curses.addstr ' ' * col_width
         
     | 
| 
      
 189 
     | 
    
         
            +
                                end
         
     | 
| 
      
 190 
     | 
    
         
            +
                              end
         
     | 
| 
      
 191 
     | 
    
         
            +
                            end
         
     | 
| 
      
 192 
     | 
    
         
            +
                          end
         
     | 
| 
      
 193 
     | 
    
         
            +
                        end
         
     | 
| 
      
 194 
     | 
    
         
            +
                      end
         
     | 
| 
      
 195 
     | 
    
         
            +
             
     | 
| 
      
 196 
     | 
    
         
            +
                      # increment current y by amount of eras
         
     | 
| 
      
 197 
     | 
    
         
            +
                      # plus the 4 lines around the current era
         
     | 
| 
      
 198 
     | 
    
         
            +
                      # plus the 1 line of browser names
         
     | 
| 
      
 199 
     | 
    
         
            +
                      # plus the 2 blank lines above and below the eras
         
     | 
| 
      
 200 
     | 
    
         
            +
                      cy += ERAS + 7
         
     | 
| 
      
 201 
     | 
    
         
            +
             
     | 
| 
      
 202 
     | 
    
         
            +
                      # print legend header
         
     | 
| 
      
 203 
     | 
    
         
            +
                      Curses.setpos offset_y + cy, offset_x
         
     | 
| 
      
 204 
     | 
    
         
            +
                      Curses.attron color(:header) do
         
     | 
| 
      
 205 
     | 
    
         
            +
                        Curses.addstr legend_format
         
     | 
| 
      
 206 
     | 
    
         
            +
                      end
         
     | 
| 
      
 207 
     | 
    
         
            +
             
     | 
| 
      
 208 
     | 
    
         
            +
                      # increment current y by 2
         
     | 
| 
      
 209 
     | 
    
         
            +
                      # one for the header line
         
     | 
| 
      
 210 
     | 
    
         
            +
                      # plus one for a blank line below it
         
     | 
| 
      
 211 
     | 
    
         
            +
                      cy += 2
         
     | 
| 
      
 212 
     | 
    
         
            +
             
     | 
| 
      
 213 
     | 
    
         
            +
                      # loop through all features to create a legend
         
     | 
| 
      
 214 
     | 
    
         
            +
                      # showing which label belongs to which color
         
     | 
| 
      
 215 
     | 
    
         
            +
                      Feature::TYPES.values.each_slice viewable do |group|
         
     | 
| 
      
 216 
     | 
    
         
            +
                        group.compact.each.with_index do |type, lx|
         
     | 
| 
      
 217 
     | 
    
         
            +
                          Curses.setpos offset_y + cy, offset_x + lx * col_width + lx
         
     | 
| 
      
 218 
     | 
    
         
            +
                          Curses.attron color(type[:name], :fg) do
         
     | 
| 
      
 219 
     | 
    
         
            +
                            Curses.addstr "#{type[:short]}(#{type[:symbol]})".center(col_width)
         
     | 
| 
      
 220 
     | 
    
         
            +
                          end
         
     | 
| 
      
 221 
     | 
    
         
            +
                        end
         
     | 
| 
      
 222 
     | 
    
         
            +
             
     | 
| 
      
 223 
     | 
    
         
            +
                        # if there is more than one group, print the next
         
     | 
| 
      
 224 
     | 
    
         
            +
                        # group on a new line
         
     | 
| 
      
 225 
     | 
    
         
            +
                        cy += 1
         
     | 
| 
      
 226 
     | 
    
         
            +
                      end
         
     | 
| 
      
 227 
     | 
    
         
            +
             
     | 
| 
      
 228 
     | 
    
         
            +
                      Curses.refresh
         
     | 
| 
      
 229 
     | 
    
         
            +
                    end
         
     | 
| 
      
 230 
     | 
    
         
            +
             
     | 
| 
      
 231 
     | 
    
         
            +
                    def render
         
     | 
| 
      
 232 
     | 
    
         
            +
                      loop do
         
     | 
| 
      
 233 
     | 
    
         
            +
                        Curses.clear
         
     | 
| 
      
 234 
     | 
    
         
            +
                        draw
         
     | 
| 
      
 235 
     | 
    
         
            +
             
     | 
| 
      
 236 
     | 
    
         
            +
                        key = Curses.getch
         
     | 
| 
      
 237 
     | 
    
         
            +
                        case key
         
     | 
| 
      
 238 
     | 
    
         
            +
                        when Curses::KEY_RESIZE then resize
         
     | 
| 
      
 239 
     | 
    
         
            +
                        else break unless key.nil?
         
     | 
| 
      
 240 
     | 
    
         
            +
                        end
         
     | 
| 
      
 241 
     | 
    
         
            +
                      end
         
     | 
| 
      
 242 
     | 
    
         
            +
             
     | 
| 
      
 243 
     | 
    
         
            +
                      close
         
     | 
| 
      
 244 
     | 
    
         
            +
                    end
         
     | 
| 
      
 245 
     | 
    
         
            +
             
     | 
| 
      
 246 
     | 
    
         
            +
                    def colw
         
     | 
| 
      
 247 
     | 
    
         
            +
                      colw = PADDING * 2 + browsers[0..viewable].map(&:max_column_width).max
         
     | 
| 
      
 248 
     | 
    
         
            +
             
     | 
| 
      
 249 
     | 
    
         
            +
                      colw.even? ? colw : colw + 1
         
     | 
| 
      
 250 
     | 
    
         
            +
                    end
         
     | 
| 
      
 251 
     | 
    
         
            +
             
     | 
| 
      
 252 
     | 
    
         
            +
                    def tablew
         
     | 
| 
      
 253 
     | 
    
         
            +
                      colw * viewable + viewable - 1
         
     | 
| 
      
 254 
     | 
    
         
            +
                    end
         
     | 
| 
      
 255 
     | 
    
         
            +
             
     | 
| 
      
 256 
     | 
    
         
            +
                    def resize
         
     | 
| 
      
 257 
     | 
    
         
            +
                      @height, @width = IO.console.winsize
         
     | 
| 
      
 258 
     | 
    
         
            +
                      @viewable       = browsers.size
         
     | 
| 
      
 259 
     | 
    
         
            +
             
     | 
| 
      
 260 
     | 
    
         
            +
                      while tablew > @width
         
     | 
| 
      
 261 
     | 
    
         
            +
                        @viewable -= 1
         
     | 
| 
      
 262 
     | 
    
         
            +
                      end
         
     | 
| 
      
 263 
     | 
    
         
            +
             
     | 
| 
      
 264 
     | 
    
         
            +
                      @col_width   = [colw, Feature::TYPES.map { |(_, h)| h[:short].size }.max + 3].max
         
     | 
| 
      
 265 
     | 
    
         
            +
                      @table_width = tablew
         
     | 
| 
      
 266 
     | 
    
         
            +
                    end
         
     | 
| 
      
 267 
     | 
    
         
            +
             
     | 
| 
      
 268 
     | 
    
         
            +
                    def compact?
         
     | 
| 
      
 269 
     | 
    
         
            +
                      width < COMPACT
         
     | 
| 
      
 270 
     | 
    
         
            +
                    end
         
     | 
| 
      
 271 
     | 
    
         
            +
             
     | 
| 
      
 272 
     | 
    
         
            +
                    def color(key, type = :bg)
         
     | 
| 
      
 273 
     | 
    
         
            +
                      target = key.to_s.downcase.to_sym
         
     | 
| 
      
 274 
     | 
    
         
            +
                      type   = type.to_sym
         
     | 
| 
      
 275 
     | 
    
         
            +
             
     | 
| 
      
 276 
     | 
    
         
            +
                      COLORS.find { |(k, _)| k == target }.to_a
         
     | 
| 
      
 277 
     | 
    
         
            +
                            .fetch(1, {})
         
     | 
| 
      
 278 
     | 
    
         
            +
                            .fetch(type, COLORS[:default][type])
         
     | 
| 
      
 279 
     | 
    
         
            +
                    end
         
     | 
| 
      
 280 
     | 
    
         
            +
             
     | 
| 
      
 281 
     | 
    
         
            +
                    def status_color(status)
         
     | 
| 
      
 282 
     | 
    
         
            +
                      color status, :fg
         
     | 
| 
      
 283 
     | 
    
         
            +
                    end
         
     | 
| 
      
 284 
     | 
    
         
            +
             
     | 
| 
      
 285 
     | 
    
         
            +
                    def percent_color(percent)
         
     | 
| 
      
 286 
     | 
    
         
            +
                      PERCENT_COLORS.find { |(r, _)| r.include? percent }.to_a
         
     | 
| 
      
 287 
     | 
    
         
            +
                                    .fetch(1, {})
         
     | 
| 
      
 288 
     | 
    
         
            +
                                    .fetch(:fg, COLORS[:unknown][:fg])
         
     | 
| 
      
 289 
     | 
    
         
            +
                    end
         
     | 
| 
      
 290 
     | 
    
         
            +
                  end
         
     | 
| 
      
 291 
     | 
    
         
            +
                end
         
     | 
| 
      
 292 
     | 
    
         
            +
              end
         
     | 
| 
      
 293 
     | 
    
         
            +
            end
         
     | 
    
        data/lib/cani/api/feature.rb
    CHANGED
    
    | 
         @@ -1,7 +1,7 @@ 
     | 
|
| 
       1 
1 
     | 
    
         
             
            module Cani
         
     | 
| 
       2 
2 
     | 
    
         
             
              class Api
         
     | 
| 
       3 
3 
     | 
    
         
             
                class Feature
         
     | 
| 
       4 
     | 
    
         
            -
                  attr_reader :title, :status, :spec, :stats, :percent
         
     | 
| 
      
 4 
     | 
    
         
            +
                  attr_reader :title, :status, :spec, :stats, :percent, :name
         
     | 
| 
       5 
5 
     | 
    
         | 
| 
       6 
6 
     | 
    
         
             
                  STATUSES = {
         
     | 
| 
       7 
7 
     | 
    
         
             
                    'rec'   => 'rc',
         
     | 
| 
         @@ -10,38 +10,42 @@ module Cani 
     | 
|
| 
       10 
10 
     | 
    
         
             
                  }.freeze
         
     | 
| 
       11 
11 
     | 
    
         | 
| 
       12 
12 
     | 
    
         
             
                  TYPES = {
         
     | 
| 
       13 
     | 
    
         
            -
                    'y' => {symbol: '+', name: :default,     short: : 
     | 
| 
       14 
     | 
    
         
            -
                    'a' => {symbol: '~', name: :partial,     short: : 
     | 
| 
       15 
     | 
    
         
            -
                    'n' => {symbol: '-', name: :unsupported, short: : 
     | 
| 
       16 
     | 
    
         
            -
                    'p' => {symbol: '#', name: :polyfill,    short: : 
     | 
| 
       17 
     | 
    
         
            -
                    'x' => {symbol: '@', name: :prefix,      short: : 
     | 
| 
       18 
     | 
    
         
            -
                    'd' => {symbol: '!', name: :flag,        short: : 
     | 
| 
       19 
     | 
    
         
            -
                    'u' => {symbol: '?', name: :unknown,     short: : 
     | 
| 
      
 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 = {})
         
     | 
| 
      
 23 
     | 
    
         
            +
                    @name    = attributes[:name].to_s.downcase
         
     | 
| 
       23 
24 
     | 
    
         
             
                    @title   = attributes['title']
         
     | 
| 
       24 
25 
     | 
    
         
             
                    @status  = STATUSES.fetch attributes['status'], attributes['status']
         
     | 
| 
       25 
26 
     | 
    
         
             
                    @spec    = attributes['spec']
         
     | 
| 
       26 
27 
     | 
    
         
             
                    @percent = attributes['usage_perc_y']
         
     | 
| 
       27 
28 
     | 
    
         
             
                    @stats   = attributes['stats'].each_with_object({}) do |(k, v), h|
         
     | 
| 
       28 
     | 
    
         
            -
                      h[k] = v. 
     | 
| 
      
 29 
     | 
    
         
            +
                      h[k] = v.each_with_object({}) do |(vv, s), hh|
         
     | 
| 
      
 30 
     | 
    
         
            +
                        vv.split('-').each { |ver| hh[ver] = s[0] }
         
     | 
| 
      
 31 
     | 
    
         
            +
                      end
         
     | 
| 
       29 
32 
     | 
    
         
             
                    end
         
     | 
| 
       30 
33 
     | 
    
         
             
                  end
         
     | 
| 
       31 
34 
     | 
    
         | 
| 
       32 
35 
     | 
    
         
             
                  def current_support
         
     | 
| 
       33 
     | 
    
         
            -
                    @current_support ||= Cani. 
     | 
| 
      
 36 
     | 
    
         
            +
                    @current_support ||= Cani.config.browsers.map do |browser|
         
     | 
| 
       34 
37 
     | 
    
         
             
                      bridx = Cani.api.browsers.find_index { |brs| brs.name == browser }
         
     | 
| 
       35 
38 
     | 
    
         
             
                      brwsr = Cani.api.browsers[bridx] unless bridx.nil?
         
     | 
| 
       36 
     | 
    
         
            -
                      syms  = stats[browser].values. 
     | 
| 
       37 
     | 
    
         
            -
                                            . 
     | 
| 
      
 39 
     | 
    
         
            +
                      syms  = stats[browser].values.compact.last(Cani.config.versions)
         
     | 
| 
      
 40 
     | 
    
         
            +
                                            .map { |s| TYPES[s][:symbol] || '' }
         
     | 
| 
      
 41 
     | 
    
         
            +
                                            .join.rjust Cani.config.versions
         
     | 
| 
       38 
42 
     | 
    
         | 
| 
       39 
43 
     | 
    
         
             
                      syms + brwsr.abbr
         
     | 
| 
       40 
44 
     | 
    
         
             
                    end
         
     | 
| 
       41 
45 
     | 
    
         
             
                  end
         
     | 
| 
       42 
46 
     | 
    
         | 
| 
       43 
47 
     | 
    
         
             
                  def support_in(browser, version)
         
     | 
| 
       44 
     | 
    
         
            -
                    TYPES.fetch(stats[browser.to_s][version.to_s], {})
         
     | 
| 
      
 48 
     | 
    
         
            +
                    TYPES.fetch(stats[browser.to_s][version.to_s.downcase], {})
         
     | 
| 
       45 
49 
     | 
    
         
             
                         .fetch :name, :unknown
         
     | 
| 
       46 
50 
     | 
    
         
             
                  end
         
     | 
| 
       47 
51 
     | 
    
         | 
    
        data/lib/cani/api.rb
    CHANGED
    
    | 
         @@ -1,8 +1,8 @@ 
     | 
|
| 
       1 
1 
     | 
    
         
             
            require 'net/http'
         
     | 
| 
       2 
2 
     | 
    
         | 
| 
       3 
     | 
    
         
            -
            require_relative 'api/config'
         
     | 
| 
       4 
3 
     | 
    
         
             
            require_relative 'api/browser'
         
     | 
| 
       5 
4 
     | 
    
         
             
            require_relative 'api/feature'
         
     | 
| 
      
 5 
     | 
    
         
            +
            require_relative 'api/feature/viewer'
         
     | 
| 
       6 
6 
     | 
    
         | 
| 
       7 
7 
     | 
    
         
             
            module Cani
         
     | 
| 
       8 
8 
     | 
    
         
             
              class Api
         
     | 
| 
         @@ -12,9 +12,9 @@ module Cani 
     | 
|
| 
       12 
12 
     | 
    
         | 
| 
       13 
13 
     | 
    
         
             
                def load_data(fetch: false)
         
     | 
| 
       14 
14 
     | 
    
         
             
                  @upd = false
         
     | 
| 
       15 
     | 
    
         
            -
                  data_file       = File.join config.directory, 'caniuse.json'
         
     | 
| 
      
 15 
     | 
    
         
            +
                  data_file       = File.join Cani.config.directory, 'caniuse.json'
         
     | 
| 
       16 
16 
     | 
    
         
             
                  data_exists     = File.exist? data_file
         
     | 
| 
       17 
     | 
    
         
            -
                  data_up_to_date = data_exists ? (Time.now.to_i - File.mtime(data_file).to_i < config.expire.to_i)
         
     | 
| 
      
 17 
     | 
    
         
            +
                  data_up_to_date = data_exists ? (Time.now.to_i - File.mtime(data_file).to_i < Cani.config.expire.to_i)
         
     | 
| 
       18 
18 
     | 
    
         
             
                                                : false
         
     | 
| 
       19 
19 
     | 
    
         | 
| 
       20 
20 
     | 
    
         
             
                  if !fetch && data_exists && data_up_to_date
         
     | 
| 
         @@ -40,7 +40,7 @@ module Cani 
     | 
|
| 
       40 
40 
     | 
    
         
             
                end
         
     | 
| 
       41 
41 
     | 
    
         | 
| 
       42 
42 
     | 
    
         
             
                def remove!
         
     | 
| 
       43 
     | 
    
         
            -
                  data_file = File.join config.directory, 'caniuse.json'
         
     | 
| 
      
 43 
     | 
    
         
            +
                  data_file = File.join Cani.config.directory, 'caniuse.json'
         
     | 
| 
       44 
44 
     | 
    
         | 
| 
       45 
45 
     | 
    
         
             
                  File.unlink data_file if File.exist? data_file
         
     | 
| 
       46 
46 
     | 
    
         
             
                end
         
     | 
| 
         @@ -53,14 +53,19 @@ module Cani 
     | 
|
| 
       53 
53 
     | 
    
         
             
                  @upd
         
     | 
| 
       54 
54 
     | 
    
         
             
                end
         
     | 
| 
       55 
55 
     | 
    
         | 
| 
       56 
     | 
    
         
            -
                def  
     | 
| 
       57 
     | 
    
         
            -
                   
     | 
| 
      
 56 
     | 
    
         
            +
                def find_feature(name)
         
     | 
| 
      
 57 
     | 
    
         
            +
                  name = Regexp.new name.to_s.downcase.gsub(/(\W)/, '.*')
         
     | 
| 
      
 58 
     | 
    
         
            +
                  idx  = features.find_index do |ft|
         
     | 
| 
      
 59 
     | 
    
         
            +
                    ft.title.downcase.match?(name) || ft.name.downcase.match?(name)
         
     | 
| 
      
 60 
     | 
    
         
            +
                  end
         
     | 
| 
      
 61 
     | 
    
         
            +
             
     | 
| 
      
 62 
     | 
    
         
            +
                  features[idx] if idx
         
     | 
| 
       58 
63 
     | 
    
         
             
                end
         
     | 
| 
       59 
64 
     | 
    
         | 
| 
       60 
65 
     | 
    
         
             
                def find_browser(name)
         
     | 
| 
       61 
66 
     | 
    
         
             
                  name = name.to_s.downcase
         
     | 
| 
       62 
67 
     | 
    
         
             
                  idx  = browsers.find_index do |bwsr|
         
     | 
| 
       63 
     | 
    
         
            -
                    [bwsr.title, bwsr.name, bwsr.abbr].include? name
         
     | 
| 
      
 68 
     | 
    
         
            +
                    [bwsr.title, bwsr.name, bwsr.abbr].map(&:downcase).include? name
         
     | 
| 
       64 
69 
     | 
    
         
             
                  end
         
     | 
| 
       65 
70 
     | 
    
         | 
| 
       66 
71 
     | 
    
         
             
                  browsers[idx] if idx
         
     | 
| 
         @@ -73,12 +78,12 @@ module Cani 
     | 
|
| 
       73 
78 
     | 
    
         
             
                end
         
     | 
| 
       74 
79 
     | 
    
         | 
| 
       75 
80 
     | 
    
         
             
                def features
         
     | 
| 
       76 
     | 
    
         
            -
                  @features ||= @data['data']. 
     | 
| 
      
 81 
     | 
    
         
            +
                  @features ||= @data['data'].map { |(name, info)| Feature.new info.merge(name: name) }
         
     | 
| 
       77 
82 
     | 
    
         
             
                end
         
     | 
| 
       78 
83 
     | 
    
         | 
| 
       79 
84 
     | 
    
         
             
                def raw
         
     | 
| 
       80 
85 
     | 
    
         
             
                  begin
         
     | 
| 
       81 
     | 
    
         
            -
                    Net::HTTP.get URI(config.source)
         
     | 
| 
      
 86 
     | 
    
         
            +
                    Net::HTTP.get URI(Cani.config.source)
         
     | 
| 
       82 
87 
     | 
    
         
             
                  rescue
         
     | 
| 
       83 
88 
     | 
    
         
             
                    nil
         
     | 
| 
       84 
89 
     | 
    
         
             
                  end
         
     | 
    
        data/lib/cani/completions.rb
    CHANGED
    
    | 
         @@ -3,12 +3,21 @@ module Cani 
     | 
|
| 
       3 
3 
     | 
    
         
             
                def self.generate_fish
         
     | 
| 
       4 
4 
     | 
    
         
             
                  gem_root = File.join File.dirname(__FILE__), '../../'
         
     | 
| 
       5 
5 
     | 
    
         
             
                  tpl      = File.read File.join(gem_root, 'shell/completions/functions.fish')
         
     | 
| 
       6 
     | 
    
         
            -
             
     | 
| 
       7 
     | 
    
         
            -
             
     | 
| 
       8 
     | 
    
         
            -
             
     | 
| 
      
 6 
     | 
    
         
            +
             
     | 
| 
      
 7 
     | 
    
         
            +
                  shw = Cani.api.browsers.reduce String.new do |acc, browser|
         
     | 
| 
      
 8 
     | 
    
         
            +
                    versions = browser.versions.reverse.join(' ')
         
     | 
| 
      
 9 
     | 
    
         
            +
                    acc +
         
     | 
| 
      
 10 
     | 
    
         
            +
                    "\ncomplete -f -c cani -n '__fish_cani_using_command show' -a '#{browser.abbr}' -d '#{browser.label}'" +
         
     | 
| 
      
 11 
     | 
    
         
            +
                    "\ncomplete -f -c cani -n '__fish_cani_showing_browser #{browser.abbr}' -a '#{versions}'"
         
     | 
| 
      
 12 
     | 
    
         
            +
                  end
         
     | 
| 
      
 13 
     | 
    
         
            +
             
     | 
| 
      
 14 
     | 
    
         
            +
                  use = Cani.api.features.reduce String.new do |acc, feature|
         
     | 
| 
      
 15 
     | 
    
         
            +
                    description = feature.title.size > 40 ? feature.title[0..28] + '..' : feature.title
         
     | 
| 
      
 16 
     | 
    
         
            +
                    acc +
         
     | 
| 
      
 17 
     | 
    
         
            +
                    "\ncomplete -f -c cani -n '__fish_cani_using_command use' -a '#{feature.name}' -d '#{description}'"
         
     | 
| 
       9 
18 
     | 
    
         
             
                  end
         
     | 
| 
       10 
19 
     | 
    
         | 
| 
       11 
     | 
    
         
            -
                  tpl + shw
         
     | 
| 
      
 20 
     | 
    
         
            +
                  tpl + shw + "\n" + use
         
     | 
| 
       12 
21 
     | 
    
         
             
                end
         
     | 
| 
       13 
22 
     | 
    
         | 
| 
       14 
23 
     | 
    
         
             
                def self.generate_zsh
         
     | 
| 
         @@ -22,6 +31,7 @@ module Cani 
     | 
|
| 
       22 
31 
     | 
    
         
             
                  end.strip
         
     | 
| 
       23 
32 
     | 
    
         | 
| 
       24 
33 
     | 
    
         
             
                  tpl.gsub('{{names}}', Cani.api.browsers.map(&:abbr).join(' '))
         
     | 
| 
      
 34 
     | 
    
         
            +
                     .gsub('{{features}}', Cani.api.features.map(&:name).join(' '))
         
     | 
| 
       25 
35 
     | 
    
         
             
                     .gsub '{{versions}}', versions
         
     | 
| 
       26 
36 
     | 
    
         
             
                end
         
     | 
| 
       27 
37 
     | 
    
         | 
| 
         @@ -36,21 +46,22 @@ module Cani 
     | 
|
| 
       36 
46 
     | 
    
         
             
                  end.strip
         
     | 
| 
       37 
47 
     | 
    
         | 
| 
       38 
48 
     | 
    
         
             
                  tpl.gsub('{{names}}', Cani.api.browsers.map(&:abbr).join(' '))
         
     | 
| 
      
 49 
     | 
    
         
            +
                     .gsub('{{features}}', Cani.api.features.map(&:name).join(' '))
         
     | 
| 
       39 
50 
     | 
    
         
             
                     .gsub '{{versions}}', versions
         
     | 
| 
       40 
51 
     | 
    
         
             
                end
         
     | 
| 
       41 
52 
     | 
    
         | 
| 
       42 
53 
     | 
    
         
             
                def self.install!
         
     | 
| 
       43 
54 
     | 
    
         
             
                  # create all parent folders
         
     | 
| 
       44 
     | 
    
         
            -
                  FileUtils.mkdir_p Cani. 
     | 
| 
       45 
     | 
    
         
            -
                  FileUtils.mkdir_p Cani. 
     | 
| 
      
 55 
     | 
    
         
            +
                  FileUtils.mkdir_p Cani.config.fish_comp_dir
         
     | 
| 
      
 56 
     | 
    
         
            +
                  FileUtils.mkdir_p Cani.config.comp_dir
         
     | 
| 
       46 
57 
     | 
    
         | 
| 
       47 
58 
     | 
    
         
             
                  # write each completion file
         
     | 
| 
       48 
     | 
    
         
            -
                  File.open File.join(Cani. 
     | 
| 
      
 59 
     | 
    
         
            +
                  File.open File.join(Cani.config.fish_comp_dir, 'cani.fish'), 'w' do |file|
         
     | 
| 
       49 
60 
     | 
    
         
             
                    file << generate_fish
         
     | 
| 
       50 
61 
     | 
    
         
             
                  end
         
     | 
| 
       51 
62 
     | 
    
         | 
| 
       52 
63 
     | 
    
         
             
                  %w[bash zsh].each do |shell|
         
     | 
| 
       53 
     | 
    
         
            -
                    File.open File.join(Cani. 
     | 
| 
      
 64 
     | 
    
         
            +
                    File.open File.join(Cani.config.comp_dir, "_cani.#{shell}"), 'w' do |file|
         
     | 
| 
       54 
65 
     | 
    
         
             
                      file << send("generate_#{shell}")
         
     | 
| 
       55 
66 
     | 
    
         
             
                    end
         
     | 
| 
       56 
67 
     | 
    
         
             
                  end
         
     | 
| 
         @@ -60,12 +71,12 @@ module Cani 
     | 
|
| 
       60 
71 
     | 
    
         
             
                end
         
     | 
| 
       61 
72 
     | 
    
         | 
| 
       62 
73 
     | 
    
         
             
                def self.remove!
         
     | 
| 
       63 
     | 
    
         
            -
                  fish_comp = File.join Cani. 
     | 
| 
      
 74 
     | 
    
         
            +
                  fish_comp = File.join Cani.config.fish_comp_dir, 'cani.fish'
         
     | 
| 
       64 
75 
     | 
    
         | 
| 
       65 
76 
     | 
    
         
             
                  File.unlink fish_comp if File.exist? fish_comp
         
     | 
| 
       66 
77 
     | 
    
         | 
| 
       67 
78 
     | 
    
         
             
                  %w[bash zsh].each do |shell|
         
     | 
| 
       68 
     | 
    
         
            -
                    shell_comp = File.join Cani. 
     | 
| 
      
 79 
     | 
    
         
            +
                    shell_comp = File.join Cani.config.comp_dir, "_cani.#{shell}"
         
     | 
| 
       69 
80 
     | 
    
         | 
| 
       70 
81 
     | 
    
         
             
                    File.unlink shell_comp if File.exist? shell_comp
         
     | 
| 
       71 
82 
     | 
    
         
             
                  end
         
     | 
| 
         @@ -78,7 +89,7 @@ module Cani 
     | 
|
| 
       78 
89 
     | 
    
         
             
                  %w[bash zsh].each do |shell|
         
     | 
| 
       79 
90 
     | 
    
         
             
                    shellrc   = File.join Dir.home, ".#{shell}rc"
         
     | 
| 
       80 
91 
     | 
    
         
             
                    lines     = File.read(shellrc).split "\n"
         
     | 
| 
       81 
     | 
    
         
            -
                    comp_path = File.join Cani. 
     | 
| 
      
 92 
     | 
    
         
            +
                    comp_path = File.join Cani.config.comp_dir, "_cani.#{shell}"
         
     | 
| 
       82 
93 
     | 
    
         
             
                    rm_idx    = lines.find_index { |l| l.match? comp_path }
         
     | 
| 
       83 
94 
     | 
    
         | 
| 
       84 
95 
     | 
    
         
             
                    lines.delete_at rm_idx unless rm_idx.nil?
         
     | 
| 
         @@ -90,7 +101,7 @@ module Cani 
     | 
|
| 
       90 
101 
     | 
    
         
             
                  %w[bash zsh].each do |shell|
         
     | 
| 
       91 
102 
     | 
    
         
             
                    shellrc   = File.join Dir.home, ".#{shell}rc"
         
     | 
| 
       92 
103 
     | 
    
         
             
                    lines     = File.read(shellrc).split "\n"
         
     | 
| 
       93 
     | 
    
         
            -
                    comp_path = File.join Cani. 
     | 
| 
      
 104 
     | 
    
         
            +
                    comp_path = File.join Cani.config.comp_dir, "_cani.#{shell}"
         
     | 
| 
       94 
105 
     | 
    
         
             
                    slidx     = lines.find_index { |l| l.match? comp_path }
         
     | 
| 
       95 
106 
     | 
    
         | 
| 
       96 
107 
     | 
    
         
             
                    if slidx
         
     | 
    
        data/lib/cani/config.rb
    ADDED
    
    | 
         @@ -0,0 +1,111 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            module Cani
         
     | 
| 
      
 2 
     | 
    
         
            +
              class Config
         
     | 
| 
      
 3 
     | 
    
         
            +
                attr_reader :settings
         
     | 
| 
      
 4 
     | 
    
         
            +
             
     | 
| 
      
 5 
     | 
    
         
            +
                FILE          = File.join(Dir.home, '.config', 'cani', 'config.yml').freeze
         
     | 
| 
      
 6 
     | 
    
         
            +
                DIRECTORY     = File.dirname(FILE).freeze
         
     | 
| 
      
 7 
     | 
    
         
            +
                COMP_DIR      = File.join(DIRECTORY, 'completions').freeze
         
     | 
| 
      
 8 
     | 
    
         
            +
                FISH_DIR      = File.join(Dir.home, '.config', 'fish').freeze
         
     | 
| 
      
 9 
     | 
    
         
            +
                FISH_COMP_DIR = File.join(FISH_DIR, 'completions').freeze
         
     | 
| 
      
 10 
     | 
    
         
            +
                DEFAULTS      = {
         
     | 
| 
      
 11 
     | 
    
         
            +
                  # data settings
         
     | 
| 
      
 12 
     | 
    
         
            +
                  'expire'   => 86_400,
         
     | 
| 
      
 13 
     | 
    
         
            +
                  'source'   => 'https://raw.githubusercontent.com/Fyrd/caniuse/master/data.json',
         
     | 
| 
      
 14 
     | 
    
         
            +
             
     | 
| 
      
 15 
     | 
    
         
            +
                  # usage settings
         
     | 
| 
      
 16 
     | 
    
         
            +
                  'versions' => 1,
         
     | 
| 
      
 17 
     | 
    
         
            +
                  'browsers' => %w[ie edge chrome firefox safari ios_saf opera android bb]
         
     | 
| 
      
 18 
     | 
    
         
            +
                }.freeze
         
     | 
| 
      
 19 
     | 
    
         
            +
             
     | 
| 
      
 20 
     | 
    
         
            +
                def initialize(**opts)
         
     | 
| 
      
 21 
     | 
    
         
            +
                  @settings = DEFAULTS.merge opts
         
     | 
| 
      
 22 
     | 
    
         
            +
             
     | 
| 
      
 23 
     | 
    
         
            +
                  if File.exist? file
         
     | 
| 
      
 24 
     | 
    
         
            +
                    if (yml = YAML.load_file(file))
         
     | 
| 
      
 25 
     | 
    
         
            +
                      @settings.merge! yml
         
     | 
| 
      
 26 
     | 
    
         
            +
                    end
         
     | 
| 
      
 27 
     | 
    
         
            +
                  else
         
     | 
| 
      
 28 
     | 
    
         
            +
                    install!
         
     | 
| 
      
 29 
     | 
    
         
            +
                  end
         
     | 
| 
      
 30 
     | 
    
         
            +
                end
         
     | 
| 
      
 31 
     | 
    
         
            +
             
     | 
| 
      
 32 
     | 
    
         
            +
                def file
         
     | 
| 
      
 33 
     | 
    
         
            +
                  FILE
         
     | 
| 
      
 34 
     | 
    
         
            +
                end
         
     | 
| 
      
 35 
     | 
    
         
            +
             
     | 
| 
      
 36 
     | 
    
         
            +
                def directory
         
     | 
| 
      
 37 
     | 
    
         
            +
                  DIRECTORY
         
     | 
| 
      
 38 
     | 
    
         
            +
                end
         
     | 
| 
      
 39 
     | 
    
         
            +
             
     | 
| 
      
 40 
     | 
    
         
            +
                def comp_dir
         
     | 
| 
      
 41 
     | 
    
         
            +
                  COMP_DIR
         
     | 
| 
      
 42 
     | 
    
         
            +
                end
         
     | 
| 
      
 43 
     | 
    
         
            +
             
     | 
| 
      
 44 
     | 
    
         
            +
                def fish_dir
         
     | 
| 
      
 45 
     | 
    
         
            +
                  FISH_DIR
         
     | 
| 
      
 46 
     | 
    
         
            +
                end
         
     | 
| 
      
 47 
     | 
    
         
            +
             
     | 
| 
      
 48 
     | 
    
         
            +
                def fish_comp_dir
         
     | 
| 
      
 49 
     | 
    
         
            +
                  FISH_COMP_DIR
         
     | 
| 
      
 50 
     | 
    
         
            +
                end
         
     | 
| 
      
 51 
     | 
    
         
            +
             
     | 
| 
      
 52 
     | 
    
         
            +
                def remove!
         
     | 
| 
      
 53 
     | 
    
         
            +
                  File.unlink file if File.exist? file
         
     | 
| 
      
 54 
     | 
    
         
            +
                  FileUtils.rm_rf directory if Dir.exist? directory
         
     | 
| 
      
 55 
     | 
    
         
            +
                end
         
     | 
| 
      
 56 
     | 
    
         
            +
             
     | 
| 
      
 57 
     | 
    
         
            +
                def install!
         
     | 
| 
      
 58 
     | 
    
         
            +
                  hrs  = (DEFAULTS['expire'] / 3600.to_f).round 2
         
     | 
| 
      
 59 
     | 
    
         
            +
                  days = (hrs / 24.to_f).round 2
         
     | 
| 
      
 60 
     | 
    
         
            +
                  wk   = (days / 7.to_f).round 2
         
     | 
| 
      
 61 
     | 
    
         
            +
                  mo   = (days / 30.to_f).round 2
         
     | 
| 
      
 62 
     | 
    
         
            +
                  tstr = if mo >= 1
         
     | 
| 
      
 63 
     | 
    
         
            +
                           "#{mo == mo.to_i ? mo.to_i : mo} month#{mo != 1 ? 's' : ''}"
         
     | 
| 
      
 64 
     | 
    
         
            +
                         elsif wk >= 1
         
     | 
| 
      
 65 
     | 
    
         
            +
                           "#{wk == wk.to_i ? wk.to_i : wk} week#{wk != 1 ? 's' : ''}"
         
     | 
| 
      
 66 
     | 
    
         
            +
                         elsif days >= 1
         
     | 
| 
      
 67 
     | 
    
         
            +
                           "#{days == days.to_i ? days.to_i : days} day#{days != 1 ? 's' : ''}"
         
     | 
| 
      
 68 
     | 
    
         
            +
                         else
         
     | 
| 
      
 69 
     | 
    
         
            +
                           "#{hrs == hrs.to_i ? hrs.to_i : hrs} hour#{hrs != 1 ? 's' : ''}"
         
     | 
| 
      
 70 
     | 
    
         
            +
                         end
         
     | 
| 
      
 71 
     | 
    
         
            +
             
     | 
| 
      
 72 
     | 
    
         
            +
                  FileUtils.mkdir_p directory
         
     | 
| 
      
 73 
     | 
    
         
            +
                  File.open file, 'w' do |f|
         
     | 
| 
      
 74 
     | 
    
         
            +
                    f << "---\n"
         
     | 
| 
      
 75 
     | 
    
         
            +
                    f << "# this is the default configuration file for the \"Cani\" RubyGem.\n"
         
     | 
| 
      
 76 
     | 
    
         
            +
                    f << "# it contains some options to control what is shown, when new data\n"
         
     | 
| 
      
 77 
     | 
    
         
            +
                    f << "# is fetched, where it should be fetched from.\n"
         
     | 
| 
      
 78 
     | 
    
         
            +
                    f << "# documentation: https://github.com/sidofc/cani\n"
         
     | 
| 
      
 79 
     | 
    
         
            +
                    f << "# rubygems: https://rubygems.org/gems/cani\n\n"
         
     | 
| 
      
 80 
     | 
    
         
            +
                    f << "# the \"expire\" key defines the interval at which new data is\n"
         
     | 
| 
      
 81 
     | 
    
         
            +
                    f << "# fetched from \"source\". It's value is passed in as seconds\n"
         
     | 
| 
      
 82 
     | 
    
         
            +
                    f << "# default value: #{DEFAULTS['expire']} # => #{tstr}\n"
         
     | 
| 
      
 83 
     | 
    
         
            +
                    f << "expire: #{expire}\n\n"
         
     | 
| 
      
 84 
     | 
    
         
            +
                    f << "# the \"source\" key is used to fetch the data required for\n"
         
     | 
| 
      
 85 
     | 
    
         
            +
                    f << "# this command to work.\n"
         
     | 
| 
      
 86 
     | 
    
         
            +
                    f << "source: #{source}\n\n"
         
     | 
| 
      
 87 
     | 
    
         
            +
                    f << "# the \"versions\" key defines how many versions of support\n"
         
     | 
| 
      
 88 
     | 
    
         
            +
                    f << "# will be shown in the \"use\" command\n"
         
     | 
| 
      
 89 
     | 
    
         
            +
                    f << "# e.g. `-ie +edge` becomes `--ie ++edge` when this is set to 2, etc..."
         
     | 
| 
      
 90 
     | 
    
         
            +
                    f << "versions: #{versions}\n\n"
         
     | 
| 
      
 91 
     | 
    
         
            +
                    f << "# the \"browsers\" key defines which browsers are shown\n"
         
     | 
| 
      
 92 
     | 
    
         
            +
                    f << "# in the \"use\" command\n"
         
     | 
| 
      
 93 
     | 
    
         
            +
                    f << "browsers:\n"
         
     | 
| 
      
 94 
     | 
    
         
            +
                    f << "  # enabled:\n"
         
     | 
| 
      
 95 
     | 
    
         
            +
                    f << browsers.map { |bn| "  - #{bn}" }.join("\n") + "\n"
         
     | 
| 
      
 96 
     | 
    
         
            +
                    f << "  # others:\n"
         
     | 
| 
      
 97 
     | 
    
         
            +
                    f << (Cani.api.browsers.map(&:name) - browsers).map { |bn| "  # - #{bn}" }.join("\n")
         
     | 
| 
      
 98 
     | 
    
         
            +
                  end
         
     | 
| 
      
 99 
     | 
    
         
            +
             
     | 
| 
      
 100 
     | 
    
         
            +
                  Completions.install!
         
     | 
| 
      
 101 
     | 
    
         
            +
                end
         
     | 
| 
      
 102 
     | 
    
         
            +
             
     | 
| 
      
 103 
     | 
    
         
            +
                def method_missing(mtd, *args, &block)
         
     | 
| 
      
 104 
     | 
    
         
            +
                  settings.key?(mtd.to_s) ? settings[mtd.to_s] : super
         
     | 
| 
      
 105 
     | 
    
         
            +
                end
         
     | 
| 
      
 106 
     | 
    
         
            +
             
     | 
| 
      
 107 
     | 
    
         
            +
                def respond_to_missing?(mtd, include_private = false)
         
     | 
| 
      
 108 
     | 
    
         
            +
                  settings.key? mtd.to_s
         
     | 
| 
      
 109 
     | 
    
         
            +
                end
         
     | 
| 
      
 110 
     | 
    
         
            +
              end
         
     | 
| 
      
 111 
     | 
    
         
            +
            end
         
     | 
    
        data/lib/cani/fzf.rb
    CHANGED
    
    | 
         @@ -29,7 +29,7 @@ module Cani 
     | 
|
| 
       29 
29 
     | 
    
         
             
                end
         
     | 
| 
       30 
30 
     | 
    
         | 
| 
       31 
31 
     | 
    
         
             
                def self.feature_rows
         
     | 
| 
       32 
     | 
    
         
            -
                  Cani.api.features.map do |ft|
         
     | 
| 
      
 32 
     | 
    
         
            +
                  @feature_rows ||= Cani.api.features.map do |ft|
         
     | 
| 
       33 
33 
     | 
    
         
             
                    pc = format('%.2f%%', ft.percent).rjust 6
         
     | 
| 
       34 
34 
     | 
    
         
             
                    tt = format('%-24s', ft.title.size > 24 ? ft.title[0..23].strip + '..'
         
     | 
| 
       35 
35 
     | 
    
         
             
                                                            : ft.title)
         
     | 
    
        data/lib/cani/version.rb
    CHANGED
    
    
    
        data/lib/cani.rb
    CHANGED
    
    | 
         @@ -1,12 +1,15 @@ 
     | 
|
| 
       1 
1 
     | 
    
         
             
            # frozen_string_literal: true
         
     | 
| 
       2 
2 
     | 
    
         | 
| 
      
 3 
     | 
    
         
            +
            require 'io/console'
         
     | 
| 
      
 4 
     | 
    
         
            +
            require 'curses'
         
     | 
| 
       3 
5 
     | 
    
         
             
            require 'colorize'
         
     | 
| 
       4 
6 
     | 
    
         
             
            require 'json'
         
     | 
| 
       5 
7 
     | 
    
         
             
            require 'yaml'
         
     | 
| 
       6 
8 
     | 
    
         | 
| 
       7 
     | 
    
         
            -
            require 'cani/version'
         
     | 
| 
       8 
9 
     | 
    
         
             
            require 'cani/api'
         
     | 
| 
       9 
10 
     | 
    
         
             
            require 'cani/fzf'
         
     | 
| 
      
 11 
     | 
    
         
            +
            require 'cani/config'
         
     | 
| 
      
 12 
     | 
    
         
            +
            require 'cani/version'
         
     | 
| 
       10 
13 
     | 
    
         
             
            require 'cani/completions'
         
     | 
| 
       11 
14 
     | 
    
         | 
| 
       12 
15 
     | 
    
         
             
            # Cani
         
     | 
| 
         @@ -15,6 +18,27 @@ module Cani 
     | 
|
| 
       15 
18 
     | 
    
         
             
                @api ||= Api.new
         
     | 
| 
       16 
19 
     | 
    
         
             
              end
         
     | 
| 
       17 
20 
     | 
    
         | 
| 
      
 21 
     | 
    
         
            +
              def self.config
         
     | 
| 
      
 22 
     | 
    
         
            +
                @settings ||= Config.new
         
     | 
| 
      
 23 
     | 
    
         
            +
              end
         
     | 
| 
      
 24 
     | 
    
         
            +
             
     | 
| 
      
 25 
     | 
    
         
            +
             
     | 
| 
      
 26 
     | 
    
         
            +
              def self.exec!(command, *args)
         
     | 
| 
      
 27 
     | 
    
         
            +
                command = :help unless command && respond_to?(command)
         
     | 
| 
      
 28 
     | 
    
         
            +
                command = command.to_s.downcase.to_sym
         
     | 
| 
      
 29 
     | 
    
         
            +
             
     | 
| 
      
 30 
     | 
    
         
            +
                case command
         
     | 
| 
      
 31 
     | 
    
         
            +
                when :use
         
     | 
| 
      
 32 
     | 
    
         
            +
                  use args[0]
         
     | 
| 
      
 33 
     | 
    
         
            +
                when :show
         
     | 
| 
      
 34 
     | 
    
         
            +
                  show args[0], args[1]
         
     | 
| 
      
 35 
     | 
    
         
            +
                when :update, :purge, :help, :version, :install_completions
         
     | 
| 
      
 36 
     | 
    
         
            +
                  send command
         
     | 
| 
      
 37 
     | 
    
         
            +
                else
         
     | 
| 
      
 38 
     | 
    
         
            +
                  help
         
     | 
| 
      
 39 
     | 
    
         
            +
                end
         
     | 
| 
      
 40 
     | 
    
         
            +
              end
         
     | 
| 
      
 41 
     | 
    
         
            +
             
     | 
| 
       18 
42 
     | 
    
         
             
              def self.help
         
     | 
| 
       19 
43 
     | 
    
         
             
                puts "Cani #{VERSION} <https://github.com/SidOfc/cani>"
         
     | 
| 
       20 
44 
     | 
    
         
             
                puts ''
         
     | 
| 
         @@ -57,7 +81,7 @@ module Cani 
     | 
|
| 
       57 
81 
     | 
    
         
             
              def self.purge
         
     | 
| 
       58 
82 
     | 
    
         
             
                Completions.remove!
         
     | 
| 
       59 
83 
     | 
    
         
             
                api.remove!
         
     | 
| 
       60 
     | 
    
         
            -
                 
     | 
| 
      
 84 
     | 
    
         
            +
                config.remove!
         
     | 
| 
       61 
85 
     | 
    
         
             
              end
         
     | 
| 
       62 
86 
     | 
    
         | 
| 
       63 
87 
     | 
    
         
             
              def self.update
         
     | 
| 
         @@ -65,16 +89,28 @@ module Cani 
     | 
|
| 
       65 
89 
     | 
    
         
             
              end
         
     | 
| 
       66 
90 
     | 
    
         | 
| 
       67 
91 
     | 
    
         
             
              def self.edit
         
     | 
| 
       68 
     | 
    
         
            -
                system ENV.fetch('EDITOR', 'vim'),  
     | 
| 
      
 92 
     | 
    
         
            +
                system ENV.fetch('EDITOR', 'vim'), config.file
         
     | 
| 
       69 
93 
     | 
    
         
             
              end
         
     | 
| 
       70 
94 
     | 
    
         | 
| 
       71 
     | 
    
         
            -
              def self.use
         
     | 
| 
       72 
     | 
    
         
            -
                 
     | 
| 
       73 
     | 
    
         
            -
             
     | 
| 
       74 
     | 
    
         
            -
             
     | 
| 
      
 95 
     | 
    
         
            +
              def self.use(feature = nil)
         
     | 
| 
      
 96 
     | 
    
         
            +
                if feature && (feature = api.find_feature(feature))
         
     | 
| 
      
 97 
     | 
    
         
            +
                  Api::Feature::Viewer.new(feature).render
         
     | 
| 
      
 98 
     | 
    
         
            +
                  use
         
     | 
| 
      
 99 
     | 
    
         
            +
                elsif (chosen = Fzf.pick(Fzf.feature_rows,
         
     | 
| 
      
 100 
     | 
    
         
            +
                                         header: 'use]   [' + Api::Feature.support_legend,
         
     | 
| 
      
 101 
     | 
    
         
            +
                                         colors: %i[green light_black light_white light_black]))
         
     | 
| 
      
 102 
     | 
    
         
            +
             
     | 
| 
      
 103 
     | 
    
         
            +
                  # chosen[2] is the index of the title column from Fzf.feature_rows
         
     | 
| 
      
 104 
     | 
    
         
            +
                  if chosen.any? && (feature = api.find_feature(chosen[2]))
         
     | 
| 
      
 105 
     | 
    
         
            +
                    Api::Feature::Viewer.new(feature).render
         
     | 
| 
      
 106 
     | 
    
         
            +
                    use
         
     | 
| 
      
 107 
     | 
    
         
            +
                  else
         
     | 
| 
      
 108 
     | 
    
         
            +
                    exit
         
     | 
| 
      
 109 
     | 
    
         
            +
                  end
         
     | 
| 
      
 110 
     | 
    
         
            +
                end
         
     | 
| 
       75 
111 
     | 
    
         
             
              end
         
     | 
| 
       76 
112 
     | 
    
         | 
| 
       77 
     | 
    
         
            -
              def self.show(brws =  
     | 
| 
      
 113 
     | 
    
         
            +
              def self.show(brws = nil, version = nil)
         
     | 
| 
       78 
114 
     | 
    
         
             
                browser = api.find_browser brws
         
     | 
| 
       79 
115 
     | 
    
         | 
| 
       80 
116 
     | 
    
         
             
                if browser
         
     | 
| 
         @@ -83,14 +119,14 @@ module Cani 
     | 
|
| 
       83 
119 
     | 
    
         
             
                             header: "show:#{browser.title.downcase}:#{version}]   [#{Api::Feature.support_legend}",
         
     | 
| 
       84 
120 
     | 
    
         
             
                             colors: [:green, :light_black, :light_white]
         
     | 
| 
       85 
121 
     | 
    
         | 
| 
       86 
     | 
    
         
            -
                    show browser.title 
     | 
| 
      
 122 
     | 
    
         
            +
                    show browser.title
         
     | 
| 
       87 
123 
     | 
    
         
             
                  else
         
     | 
| 
       88 
124 
     | 
    
         
             
                    if (version = Fzf.pick(Fzf.browser_usage_rows(browser),
         
     | 
| 
       89 
125 
     | 
    
         
             
                                           header: [:show, browser.title],
         
     | 
| 
       90 
126 
     | 
    
         
             
                                           colors: %i[white light_black]).first)
         
     | 
| 
       91 
127 
     | 
    
         
             
                      show browser.title, version
         
     | 
| 
       92 
128 
     | 
    
         
             
                    else
         
     | 
| 
       93 
     | 
    
         
            -
                      show 
     | 
| 
      
 129 
     | 
    
         
            +
                      show
         
     | 
| 
       94 
130 
     | 
    
         
             
                    end
         
     | 
| 
       95 
131 
     | 
    
         
             
                  end
         
     | 
| 
       96 
132 
     | 
    
         
             
                else
         
     | 
| 
         @@ -98,7 +134,7 @@ module Cani 
     | 
|
| 
       98 
134 
     | 
    
         
             
                                                      header: [:show],
         
     | 
| 
       99 
135 
     | 
    
         
             
                                                      colors: %i[white light_black]).first
         
     | 
| 
       100 
136 
     | 
    
         | 
| 
       101 
     | 
    
         
            -
                  show browser.title 
     | 
| 
      
 137 
     | 
    
         
            +
                  show browser.title unless browser.nil?
         
     | 
| 
       102 
138 
     | 
    
         
             
                end
         
     | 
| 
       103 
139 
     | 
    
         
             
              end
         
     | 
| 
       104 
140 
     | 
    
         
             
            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. 
     | 
| 
      
 4 
     | 
    
         
            +
              version: 0.2.0
         
     | 
| 
       5 
5 
     | 
    
         
             
            platform: ruby
         
     | 
| 
       6 
6 
     | 
    
         
             
            authors:
         
     | 
| 
       7 
7 
     | 
    
         
             
            - Sidney Liebrand
         
     | 
| 
       8 
8 
     | 
    
         
             
            autorequire: 
         
     | 
| 
       9 
9 
     | 
    
         
             
            bindir: exe
         
     | 
| 
       10 
10 
     | 
    
         
             
            cert_chain: []
         
     | 
| 
       11 
     | 
    
         
            -
            date: 2018-07- 
     | 
| 
      
 11 
     | 
    
         
            +
            date: 2018-07-19 00:00:00.000000000 Z
         
     | 
| 
       12 
12 
     | 
    
         
             
            dependencies:
         
     | 
| 
       13 
13 
     | 
    
         
             
            - !ruby/object:Gem::Dependency
         
     | 
| 
       14 
14 
     | 
    
         
             
              name: colorize
         
     | 
| 
         @@ -25,7 +25,7 @@ dependencies: 
     | 
|
| 
       25 
25 
     | 
    
         
             
                  - !ruby/object:Gem::Version
         
     | 
| 
       26 
26 
     | 
    
         
             
                    version: '0'
         
     | 
| 
       27 
27 
     | 
    
         
             
            - !ruby/object:Gem::Dependency
         
     | 
| 
       28 
     | 
    
         
            -
              name:  
     | 
| 
      
 28 
     | 
    
         
            +
              name: curses
         
     | 
| 
       29 
29 
     | 
    
         
             
              requirement: !ruby/object:Gem::Requirement
         
     | 
| 
       30 
30 
     | 
    
         
             
                requirements:
         
     | 
| 
       31 
31 
     | 
    
         
             
                - - ">="
         
     | 
| 
         @@ -39,33 +39,33 @@ 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 
     | 
    
         
            +
                - - ">="
         
     | 
| 
       46 
46 
     | 
    
         
             
                  - !ruby/object:Gem::Version
         
     | 
| 
       47 
     | 
    
         
            -
                    version: ' 
     | 
| 
       48 
     | 
    
         
            -
              type: : 
     | 
| 
      
 47 
     | 
    
         
            +
                    version: '0'
         
     | 
| 
      
 48 
     | 
    
         
            +
              type: :runtime
         
     | 
| 
       49 
49 
     | 
    
         
             
              prerelease: false
         
     | 
| 
       50 
50 
     | 
    
         
             
              version_requirements: !ruby/object:Gem::Requirement
         
     | 
| 
       51 
51 
     | 
    
         
             
                requirements:
         
     | 
| 
       52 
     | 
    
         
            -
                - - " 
     | 
| 
      
 52 
     | 
    
         
            +
                - - ">="
         
     | 
| 
       53 
53 
     | 
    
         
             
                  - !ruby/object:Gem::Version
         
     | 
| 
       54 
     | 
    
         
            -
                    version: ' 
     | 
| 
      
 54 
     | 
    
         
            +
                    version: '0'
         
     | 
| 
       55 
55 
     | 
    
         
             
            - !ruby/object:Gem::Dependency
         
     | 
| 
       56 
     | 
    
         
            -
              name:  
     | 
| 
      
 56 
     | 
    
         
            +
              name: bundler
         
     | 
| 
       57 
57 
     | 
    
         
             
              requirement: !ruby/object:Gem::Requirement
         
     | 
| 
       58 
58 
     | 
    
         
             
                requirements:
         
     | 
| 
       59 
59 
     | 
    
         
             
                - - "~>"
         
     | 
| 
       60 
60 
     | 
    
         
             
                  - !ruby/object:Gem::Version
         
     | 
| 
       61 
     | 
    
         
            -
                    version: ' 
     | 
| 
      
 61 
     | 
    
         
            +
                    version: '1.16'
         
     | 
| 
       62 
62 
     | 
    
         
             
              type: :development
         
     | 
| 
       63 
63 
     | 
    
         
             
              prerelease: false
         
     | 
| 
       64 
64 
     | 
    
         
             
              version_requirements: !ruby/object:Gem::Requirement
         
     | 
| 
       65 
65 
     | 
    
         
             
                requirements:
         
     | 
| 
       66 
66 
     | 
    
         
             
                - - "~>"
         
     | 
| 
       67 
67 
     | 
    
         
             
                  - !ruby/object:Gem::Version
         
     | 
| 
       68 
     | 
    
         
            -
                    version: ' 
     | 
| 
      
 68 
     | 
    
         
            +
                    version: '1.16'
         
     | 
| 
       69 
69 
     | 
    
         
             
            - !ruby/object:Gem::Dependency
         
     | 
| 
       70 
70 
     | 
    
         
             
              name: pry
         
     | 
| 
       71 
71 
     | 
    
         
             
              requirement: !ruby/object:Gem::Requirement
         
     | 
| 
         @@ -80,6 +80,20 @@ dependencies: 
     | 
|
| 
       80 
80 
     | 
    
         
             
                - - ">="
         
     | 
| 
       81 
81 
     | 
    
         
             
                  - !ruby/object:Gem::Version
         
     | 
| 
       82 
82 
     | 
    
         
             
                    version: '0'
         
     | 
| 
      
 83 
     | 
    
         
            +
            - !ruby/object:Gem::Dependency
         
     | 
| 
      
 84 
     | 
    
         
            +
              name: rake
         
     | 
| 
      
 85 
     | 
    
         
            +
              requirement: !ruby/object:Gem::Requirement
         
     | 
| 
      
 86 
     | 
    
         
            +
                requirements:
         
     | 
| 
      
 87 
     | 
    
         
            +
                - - "~>"
         
     | 
| 
      
 88 
     | 
    
         
            +
                  - !ruby/object:Gem::Version
         
     | 
| 
      
 89 
     | 
    
         
            +
                    version: '10.0'
         
     | 
| 
      
 90 
     | 
    
         
            +
              type: :development
         
     | 
| 
      
 91 
     | 
    
         
            +
              prerelease: false
         
     | 
| 
      
 92 
     | 
    
         
            +
              version_requirements: !ruby/object:Gem::Requirement
         
     | 
| 
      
 93 
     | 
    
         
            +
                requirements:
         
     | 
| 
      
 94 
     | 
    
         
            +
                - - "~>"
         
     | 
| 
      
 95 
     | 
    
         
            +
                  - !ruby/object:Gem::Version
         
     | 
| 
      
 96 
     | 
    
         
            +
                    version: '10.0'
         
     | 
| 
       83 
97 
     | 
    
         
             
            - !ruby/object:Gem::Dependency
         
     | 
| 
       84 
98 
     | 
    
         
             
              name: rspec
         
     | 
| 
       85 
99 
     | 
    
         
             
              requirement: !ruby/object:Gem::Requirement
         
     | 
| 
         @@ -118,9 +132,10 @@ files: 
     | 
|
| 
       118 
132 
     | 
    
         
             
            - lib/cani.rb
         
     | 
| 
       119 
133 
     | 
    
         
             
            - lib/cani/api.rb
         
     | 
| 
       120 
134 
     | 
    
         
             
            - lib/cani/api/browser.rb
         
     | 
| 
       121 
     | 
    
         
            -
            - lib/cani/api/config.rb
         
     | 
| 
       122 
135 
     | 
    
         
             
            - lib/cani/api/feature.rb
         
     | 
| 
      
 136 
     | 
    
         
            +
            - lib/cani/api/feature/viewer.rb
         
     | 
| 
       123 
137 
     | 
    
         
             
            - lib/cani/completions.rb
         
     | 
| 
      
 138 
     | 
    
         
            +
            - lib/cani/config.rb
         
     | 
| 
       124 
139 
     | 
    
         
             
            - lib/cani/fzf.rb
         
     | 
| 
       125 
140 
     | 
    
         
             
            - lib/cani/version.rb
         
     | 
| 
       126 
141 
     | 
    
         
             
            - shell/completions/functions.bash
         
     | 
    
        data/lib/cani/api/config.rb
    DELETED
    
    | 
         @@ -1,121 +0,0 @@ 
     | 
|
| 
       1 
     | 
    
         
            -
            module Cani
         
     | 
| 
       2 
     | 
    
         
            -
              class Api
         
     | 
| 
       3 
     | 
    
         
            -
                class Config
         
     | 
| 
       4 
     | 
    
         
            -
                  attr_reader :settings
         
     | 
| 
       5 
     | 
    
         
            -
             
     | 
| 
       6 
     | 
    
         
            -
                  FILE          = File.join(Dir.home, '.config', 'cani', 'config.yml').freeze
         
     | 
| 
       7 
     | 
    
         
            -
                  DIRECTORY     = File.dirname(FILE).freeze
         
     | 
| 
       8 
     | 
    
         
            -
                  COMP_DIR      = File.join(DIRECTORY, 'completions').freeze
         
     | 
| 
       9 
     | 
    
         
            -
                  FISH_DIR      = File.join(Dir.home, '.config', 'fish').freeze
         
     | 
| 
       10 
     | 
    
         
            -
                  FISH_COMP_DIR = File.join(FISH_DIR, 'completions').freeze
         
     | 
| 
       11 
     | 
    
         
            -
                  DEFAULTS      = {
         
     | 
| 
       12 
     | 
    
         
            -
                    # data settings
         
     | 
| 
       13 
     | 
    
         
            -
                    'expire'   => 86_400,
         
     | 
| 
       14 
     | 
    
         
            -
                    'source'   => 'https://raw.githubusercontent.com/Fyrd/caniuse/master/data.json',
         
     | 
| 
       15 
     | 
    
         
            -
             
     | 
| 
       16 
     | 
    
         
            -
                    # usage settings
         
     | 
| 
       17 
     | 
    
         
            -
                    'versions' => 1,
         
     | 
| 
       18 
     | 
    
         
            -
                    'browsers' => %w[chrome firefox edge ie safari ios_saf opera android bb]
         
     | 
| 
       19 
     | 
    
         
            -
                  }.freeze
         
     | 
| 
       20 
     | 
    
         
            -
             
     | 
| 
       21 
     | 
    
         
            -
                  def initialize(**opts)
         
     | 
| 
       22 
     | 
    
         
            -
                    @settings = DEFAULTS.merge opts
         
     | 
| 
       23 
     | 
    
         
            -
             
     | 
| 
       24 
     | 
    
         
            -
                    if File.exist? file
         
     | 
| 
       25 
     | 
    
         
            -
                      if (yml = YAML.load_file(file))
         
     | 
| 
       26 
     | 
    
         
            -
                        @settings.merge! yml
         
     | 
| 
       27 
     | 
    
         
            -
                      end
         
     | 
| 
       28 
     | 
    
         
            -
                    else
         
     | 
| 
       29 
     | 
    
         
            -
                      install!
         
     | 
| 
       30 
     | 
    
         
            -
                    end
         
     | 
| 
       31 
     | 
    
         
            -
                  end
         
     | 
| 
       32 
     | 
    
         
            -
             
     | 
| 
       33 
     | 
    
         
            -
                  def file
         
     | 
| 
       34 
     | 
    
         
            -
                    FILE
         
     | 
| 
       35 
     | 
    
         
            -
                  end
         
     | 
| 
       36 
     | 
    
         
            -
             
     | 
| 
       37 
     | 
    
         
            -
                  def directory
         
     | 
| 
       38 
     | 
    
         
            -
                    DIRECTORY
         
     | 
| 
       39 
     | 
    
         
            -
                  end
         
     | 
| 
       40 
     | 
    
         
            -
             
     | 
| 
       41 
     | 
    
         
            -
                  def comp_dir
         
     | 
| 
       42 
     | 
    
         
            -
                    COMP_DIR
         
     | 
| 
       43 
     | 
    
         
            -
                  end
         
     | 
| 
       44 
     | 
    
         
            -
             
     | 
| 
       45 
     | 
    
         
            -
                  def fish_dir
         
     | 
| 
       46 
     | 
    
         
            -
                    FISH_DIR
         
     | 
| 
       47 
     | 
    
         
            -
                  end
         
     | 
| 
       48 
     | 
    
         
            -
             
     | 
| 
       49 
     | 
    
         
            -
                  def fish_comp_dir
         
     | 
| 
       50 
     | 
    
         
            -
                    FISH_COMP_DIR
         
     | 
| 
       51 
     | 
    
         
            -
                  end
         
     | 
| 
       52 
     | 
    
         
            -
             
     | 
| 
       53 
     | 
    
         
            -
                  def flags
         
     | 
| 
       54 
     | 
    
         
            -
                    @flags ||= ARGV.select { |arg| arg.start_with? '-' }
         
     | 
| 
       55 
     | 
    
         
            -
                  end
         
     | 
| 
       56 
     | 
    
         
            -
             
     | 
| 
       57 
     | 
    
         
            -
                  def args
         
     | 
| 
       58 
     | 
    
         
            -
                    @args ||= ARGV.reject { |arg| arg.start_with? '-' }
         
     | 
| 
       59 
     | 
    
         
            -
                  end
         
     | 
| 
       60 
     | 
    
         
            -
             
     | 
| 
       61 
     | 
    
         
            -
                  def remove!
         
     | 
| 
       62 
     | 
    
         
            -
                    File.unlink file if File.exist? file
         
     | 
| 
       63 
     | 
    
         
            -
                    FileUtils.rm_rf directory if Dir.exist? directory
         
     | 
| 
       64 
     | 
    
         
            -
                  end
         
     | 
| 
       65 
     | 
    
         
            -
             
     | 
| 
       66 
     | 
    
         
            -
                  def install!
         
     | 
| 
       67 
     | 
    
         
            -
                    hrs  = (DEFAULTS['expire'] / 3600.to_f).round 2
         
     | 
| 
       68 
     | 
    
         
            -
                    days = (hrs / 24.to_f).round 2
         
     | 
| 
       69 
     | 
    
         
            -
                    wk   = (days / 7.to_f).round 2
         
     | 
| 
       70 
     | 
    
         
            -
                    mo   = (days / 30.to_f).round 2
         
     | 
| 
       71 
     | 
    
         
            -
                    tstr = if mo >= 1
         
     | 
| 
       72 
     | 
    
         
            -
                             "#{mo == mo.to_i ? mo.to_i : mo} month#{mo != 1 ? 's' : ''}"
         
     | 
| 
       73 
     | 
    
         
            -
                           elsif wk >= 1
         
     | 
| 
       74 
     | 
    
         
            -
                             "#{wk == wk.to_i ? wk.to_i : wk} week#{wk != 1 ? 's' : ''}"
         
     | 
| 
       75 
     | 
    
         
            -
                           elsif days >= 1
         
     | 
| 
       76 
     | 
    
         
            -
                             "#{days == days.to_i ? days.to_i : days} day#{days != 1 ? 's' : ''}"
         
     | 
| 
       77 
     | 
    
         
            -
                           else
         
     | 
| 
       78 
     | 
    
         
            -
                             "#{hrs == hrs.to_i ? hrs.to_i : hrs} hour#{hrs != 1 ? 's' : ''}"
         
     | 
| 
       79 
     | 
    
         
            -
                           end
         
     | 
| 
       80 
     | 
    
         
            -
             
     | 
| 
       81 
     | 
    
         
            -
                    FileUtils.mkdir_p directory
         
     | 
| 
       82 
     | 
    
         
            -
                    File.open file, 'w' do |f|
         
     | 
| 
       83 
     | 
    
         
            -
                      f << "---\n"
         
     | 
| 
       84 
     | 
    
         
            -
                      f << "# this is the default configuration file for the \"Cani\" RubyGem.\n"
         
     | 
| 
       85 
     | 
    
         
            -
                      f << "# it contains some options to control what is shown, when new data\n"
         
     | 
| 
       86 
     | 
    
         
            -
                      f << "# is fetched, where it should be fetched from.\n"
         
     | 
| 
       87 
     | 
    
         
            -
                      f << "# documentation: https://github.com/sidofc/cani\n"
         
     | 
| 
       88 
     | 
    
         
            -
                      f << "# rubygems: https://rubygems.org/gems/cani\n\n"
         
     | 
| 
       89 
     | 
    
         
            -
                      f << "# the \"expire\" key defines the interval at which new data is\n"
         
     | 
| 
       90 
     | 
    
         
            -
                      f << "# fetched from \"source\". It's value is passed in as seconds\n"
         
     | 
| 
       91 
     | 
    
         
            -
                      f << "# default value: #{DEFAULTS['expire']} # => #{tstr}\n"
         
     | 
| 
       92 
     | 
    
         
            -
                      f << "expire: #{expire}\n\n"
         
     | 
| 
       93 
     | 
    
         
            -
                      f << "# the \"source\" key is used to fetch the data required for\n"
         
     | 
| 
       94 
     | 
    
         
            -
                      f << "# this command to work.\n"
         
     | 
| 
       95 
     | 
    
         
            -
                      f << "source: #{source}\n\n"
         
     | 
| 
       96 
     | 
    
         
            -
                      f << "# the \"versions\" key defines how many versions of support\n"
         
     | 
| 
       97 
     | 
    
         
            -
                      f << "# will be shown in the \"use\" command\n"
         
     | 
| 
       98 
     | 
    
         
            -
                      f << "# e.g. `-ie +edge` becomes `--ie ++edge` when this is set to 2, etc..."
         
     | 
| 
       99 
     | 
    
         
            -
                      f << "versions: #{versions}\n\n"
         
     | 
| 
       100 
     | 
    
         
            -
                      f << "# the \"browsers\" key defines which browsers are shown\n"
         
     | 
| 
       101 
     | 
    
         
            -
                      f << "# in the \"use\" command\n"
         
     | 
| 
       102 
     | 
    
         
            -
                      f << "browsers:\n"
         
     | 
| 
       103 
     | 
    
         
            -
                      f << "  # enabled:\n"
         
     | 
| 
       104 
     | 
    
         
            -
                      f << browsers.map { |bn| "  - #{bn}" }.join("\n") + "\n"
         
     | 
| 
       105 
     | 
    
         
            -
                      f << "  # others:\n"
         
     | 
| 
       106 
     | 
    
         
            -
                      f << (Cani.api.browsers.map(&:name) - browsers).map { |bn| "  # - #{bn}" }.join("\n")
         
     | 
| 
       107 
     | 
    
         
            -
                    end
         
     | 
| 
       108 
     | 
    
         
            -
             
     | 
| 
       109 
     | 
    
         
            -
                    Completions.install!
         
     | 
| 
       110 
     | 
    
         
            -
                  end
         
     | 
| 
       111 
     | 
    
         
            -
             
     | 
| 
       112 
     | 
    
         
            -
                  def method_missing(mtd, *args, &block)
         
     | 
| 
       113 
     | 
    
         
            -
                    settings.key?(mtd.to_s) ? settings[mtd.to_s] : super
         
     | 
| 
       114 
     | 
    
         
            -
                  end
         
     | 
| 
       115 
     | 
    
         
            -
             
     | 
| 
       116 
     | 
    
         
            -
                  def respond_to_missing?(mtd, include_private = false)
         
     | 
| 
       117 
     | 
    
         
            -
                    settings.key? mtd.to_s
         
     | 
| 
       118 
     | 
    
         
            -
                  end
         
     | 
| 
       119 
     | 
    
         
            -
                end
         
     | 
| 
       120 
     | 
    
         
            -
              end
         
     | 
| 
       121 
     | 
    
         
            -
            end
         
     |