bundle_update_interactive 0.9.0 → 0.9.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: c5fa0d1bf9fc3114b352236559c7a91b460b6b2816b3cd0cd3b7bc848fd072b5
4
- data.tar.gz: d70836e166741cf2efe13d188d393e094fe1adf50bb02e64f7e997a853dd65a2
3
+ metadata.gz: f45b67dd4da1f56e5bad0b154acfb7dce40b4f518eb1cf9c1101302ec3ee71f4
4
+ data.tar.gz: 9d763c27460be163b2dc6eaa818e770e81448244bcd0c2c94dee368b148d4a1d
5
5
  SHA512:
6
- metadata.gz: ab496890f43f89d9519b3e14e32998fad0d888295419dd09ce2d69f546b09a8699e635c31a442aa3990d048dc09d0a864a488307c6f047213369c198aa8b3403
7
- data.tar.gz: 4030b23f6982f0732f4a289d637ff94b1881e5b907377af69dcb0f5125c7fa19f29bb016a957c630a094268f30ecdda1d60f9978f1f9231a7e0cff4ca0b6ab23
6
+ metadata.gz: 5bf17f343e90aa16f244c470ad9f58590702d61f610e9ac6bb4623990b997f103ea52448433f8c5273880b3f110e467c72c841fa25274c9770e21805c3ce403a
7
+ data.tar.gz: 248b8e8b066fa56574297c76ce25eab8bbd6b14e10ca1a8d83444679a82dae76ae7117775fa6df9753a1c847a337d2c4730270d87ec55c33186e249e9d002a02
@@ -5,87 +5,89 @@ require "pastel"
5
5
  require "tty/prompt"
6
6
  require "tty/screen"
7
7
 
8
- class BundleUpdateInteractive::CLI
9
- class MultiSelect
10
- extend BundleUpdateInteractive::StringHelper
8
+ module BundleUpdateInteractive
9
+ class CLI
10
+ class MultiSelect
11
+ extend BundleUpdateInteractive::StringHelper
11
12
 
12
- class List < TTY::Prompt::MultiList
13
- def initialize(prompt, **options)
14
- @opener = options.delete(:opener)
15
- defaults = {
16
- cycle: true,
17
- help_color: :itself.to_proc,
18
- per_page: [TTY::Prompt::Paginator::DEFAULT_PAGE_SIZE, TTY::Screen.height.to_i - 3].max,
19
- quiet: true,
20
- show_help: :always
21
- }
22
- super(prompt, **defaults.merge(options))
23
- end
13
+ class List < TTY::Prompt::MultiList
14
+ def initialize(prompt, **options)
15
+ @opener = options.delete(:opener)
16
+ defaults = {
17
+ cycle: true,
18
+ help_color: :itself.to_proc,
19
+ per_page: [TTY::Prompt::Paginator::DEFAULT_PAGE_SIZE, TTY::Screen.height.to_i - 3].max,
20
+ quiet: true,
21
+ show_help: :always
22
+ }
23
+ super(prompt, **defaults.merge(options))
24
+ end
24
25
 
25
- def selected_names
26
- ""
27
- end
26
+ def selected_names
27
+ ""
28
+ end
28
29
 
29
- # Unregister tty-prompt's default ctrl-a and ctrl-r bindings
30
- alias select_all keyctrl_a
31
- alias reverse_selection keyctrl_r
32
- def keyctrl_a(*); end
33
- def keyctrl_r(*); end
30
+ # Unregister tty-prompt's default ctrl-a and ctrl-r bindings
31
+ alias select_all keyctrl_a
32
+ alias reverse_selection keyctrl_r
33
+ def keyctrl_a(*); end
34
+ def keyctrl_r(*); end
34
35
 
35
- def keypress(event)
36
- case event.value
37
- when "k", "p" then keyup
38
- when "j", "n" then keydown
39
- when "a" then select_all
40
- when "r" then reverse_selection
41
- when "o" then opener&.call(choices[@active - 1].value)
36
+ def keypress(event)
37
+ case event.value
38
+ when "k", "p" then keyup
39
+ when "j", "n" then keydown
40
+ when "a" then select_all
41
+ when "r" then reverse_selection
42
+ when "o" then opener&.call(choices[@active - 1].value)
43
+ end
42
44
  end
43
- end
44
45
 
45
- private
46
+ private
46
47
 
47
- attr_reader :opener
48
- end
48
+ attr_reader :opener
49
+ end
49
50
 
50
- def self.prompt_for_gems_to_update(outdated_gems, prompt: nil)
51
- table = Table.updatable(outdated_gems)
52
- title = "#{pluralize(outdated_gems.length, 'gem')} can be updated."
53
- opener = lambda do |gem|
54
- url = outdated_gems[gem].changelog_uri
55
- Launchy.open(url) unless url.nil?
51
+ def self.prompt_for_gems_to_update(outdated_gems, prompt: nil)
52
+ table = Table.updatable(outdated_gems)
53
+ title = "#{pluralize(outdated_gems.length, 'gem')} can be updated."
54
+ opener = lambda do |gem|
55
+ url = outdated_gems[gem].changelog_uri
56
+ Launchy.open(url) unless url.nil?
57
+ end
58
+ chosen = new(title: title, table: table, prompt: prompt, opener: opener).prompt
59
+ outdated_gems.slice(*chosen)
56
60
  end
57
- chosen = new(title: title, table: table, prompt: prompt, opener: opener).prompt
58
- outdated_gems.slice(*chosen)
59
- end
60
61
 
61
- def initialize(title:, table:, opener: nil, prompt: nil)
62
- @title = title
63
- @table = table
64
- @opener = opener
65
- @tty_prompt = prompt || TTY::Prompt.new(
66
- interrupt: lambda {
67
- puts
68
- exit(130)
69
- }
70
- )
71
- @pastel = BundleUpdateInteractive.pastel
72
- end
62
+ def initialize(title:, table:, opener: nil, prompt: nil)
63
+ @title = title
64
+ @table = table
65
+ @opener = opener
66
+ @tty_prompt = prompt || TTY::Prompt.new(
67
+ interrupt: lambda {
68
+ puts
69
+ exit(130)
70
+ }
71
+ )
72
+ @pastel = BundleUpdateInteractive.pastel
73
+ end
73
74
 
74
- def prompt
75
- choices = table.gem_names.to_h { |name| [table.render_gem(name), name] }
76
- tty_prompt.invoke_select(List, title, choices, help: help, opener: opener)
77
- end
75
+ def prompt
76
+ choices = table.gem_names.to_h { |name| [table.render_gem(name), name] }
77
+ tty_prompt.invoke_select(List, title, choices, help: help, opener: opener)
78
+ end
78
79
 
79
- private
80
+ private
80
81
 
81
- attr_reader :pastel, :table, :opener, :tty_prompt, :title
82
+ attr_reader :pastel, :table, :opener, :tty_prompt, :title
82
83
 
83
- def help
84
- [
85
- pastel.dim("\nPress <space> to select, ↑/↓ move, <a> all, <r> reverse, <o> open url, <enter> to finish."),
86
- "\n ",
87
- table.render_header
88
- ].join
84
+ def help
85
+ [
86
+ pastel.dim("\nPress <space> to select, ↑/↓ move, <a> all, <r> reverse, <o> open url, <enter> to finish."),
87
+ "\n ",
88
+ table.render_header
89
+ ].join
90
+ end
89
91
  end
90
92
  end
91
93
  end
@@ -3,110 +3,112 @@
3
3
  require "optparse"
4
4
 
5
5
  module BundleUpdateInteractive
6
- class CLI::Options
7
- class << self
8
- def parse(argv=ARGV)
9
- options = new
10
- remaining = build_parser(options).parse!(argv.dup)
11
- raise Error, "update-interactive does not accept arguments. See --help for available options." if remaining.any?
12
-
13
- options.freeze
14
- end
6
+ class CLI
7
+ class Options
8
+ class << self
9
+ def parse(argv=ARGV)
10
+ options = new
11
+ remain = build_parser(options).parse!(argv.dup)
12
+ raise Error, "update-interactive does not accept arguments. See --help for available options." if remain.any?
13
+
14
+ options.freeze
15
+ end
15
16
 
16
- def summary
17
- build_parser(new).summarize.join.gsub(/^\s+-.*? /, pastel.yellow('\0'))
18
- end
17
+ def summary
18
+ build_parser(new).summarize.join.gsub(/^\s+-.*? /, pastel.yellow('\0'))
19
+ end
19
20
 
20
- def help # rubocop:disable Metrics/AbcSize
21
- <<~HELP
22
- Provides an easy way to update gems to their latest versions.
21
+ def help # rubocop:disable Metrics/AbcSize
22
+ <<~HELP
23
+ Provides an easy way to update gems to their latest versions.
23
24
 
24
- #{pastel.bold.underline('USAGE')}
25
- #{pastel.green('bundle update-interactive')} #{pastel.yellow('[options]')}
26
- #{pastel.green('bundle ui')} #{pastel.yellow('[options]')}
25
+ #{pastel.bold.underline('USAGE')}
26
+ #{pastel.green('bundle update-interactive')} #{pastel.yellow('[options]')}
27
+ #{pastel.green('bundle ui')} #{pastel.yellow('[options]')}
27
28
 
28
- #{pastel.bold.underline('OPTIONS')}
29
- #{summary}
30
- #{pastel.bold.underline('DESCRIPTION')}
31
- Displays the list of gems that would be updated by `bundle update`, allowing you
32
- to navigate them by keyboard and pick which ones to update. A changelog URL,
33
- when available, is displayed alongside each update. Gems with known security
34
- vulnerabilities are also highlighted.
29
+ #{pastel.bold.underline('OPTIONS')}
30
+ #{summary}
31
+ #{pastel.bold.underline('DESCRIPTION')}
32
+ Displays the list of gems that would be updated by `bundle update`, allowing you
33
+ to navigate them by keyboard and pick which ones to update. A changelog URL,
34
+ when available, is displayed alongside each update. Gems with known security
35
+ vulnerabilities are also highlighted.
35
36
 
36
- Your Gemfile.lock will be updated conservatively based on the gems you select.
37
- Transitive dependencies are not affected.
37
+ Your Gemfile.lock will be updated conservatively based on the gems you select.
38
+ Transitive dependencies are not affected.
38
39
 
39
- More information: #{pastel.blue('https://github.com/mattbrictson/bundle_update_interactive')}
40
+ More information: #{pastel.blue('https://github.com/mattbrictson/bundle_update_interactive')}
40
41
 
41
- #{pastel.bold.underline('EXAMPLES')}
42
- Show all gems that can be updated.
43
- #{pastel.green('bundle update-interactive')}
42
+ #{pastel.bold.underline('EXAMPLES')}
43
+ Show all gems that can be updated.
44
+ #{pastel.green('bundle update-interactive')}
44
45
 
45
- The "ui" command alias can also be used.
46
- #{pastel.green('bundle ui')}
46
+ The "ui" command alias can also be used.
47
+ #{pastel.green('bundle ui')}
47
48
 
48
- Show updates for development and test gems only, leaving production gems untouched.
49
- #{pastel.green('bundle update-interactive')} #{pastel.yellow('-D')}
49
+ Show updates for development and test gems only, leaving production gems untouched.
50
+ #{pastel.green('bundle update-interactive')} #{pastel.yellow('-D')}
50
51
 
51
- Allow the latest gem versions, ignoring Gemfile pins. May modify the Gemfile.
52
- #{pastel.green('bundle update-interactive')} #{pastel.yellow('--latest')}
52
+ Allow the latest gem versions, ignoring Gemfile pins. May modify the Gemfile.
53
+ #{pastel.green('bundle update-interactive')} #{pastel.yellow('--latest')}
53
54
 
54
- HELP
55
- end
55
+ HELP
56
+ end
56
57
 
57
- private
58
+ private
58
59
 
59
- def pastel
60
- BundleUpdateInteractive.pastel
61
- end
60
+ def pastel
61
+ BundleUpdateInteractive.pastel
62
+ end
62
63
 
63
- def build_parser(options) # rubocop:disable Metrics/AbcSize, Metrics/MethodLength
64
- OptionParser.new do |parser| # rubocop:disable Metrics/BlockLength
65
- parser.summary_indent = " "
66
- parser.summary_width = 24
67
- parser.on("--commit", "Create a git commit for each selected gem update") do
68
- options.commit = true
69
- end
70
- parser.on("--latest", "Modify the Gemfile to allow the latest gem versions") do
71
- options.latest = true
72
- end
73
- parser.on(
74
- "--exclusively=GROUP",
75
- "Update gems exclusively belonging to the specified Gemfile GROUP(s)"
76
- ) do |value|
77
- options.exclusively = value.split(",").map(&:strip).reject(&:empty?).map(&:to_sym)
78
- end
79
- parser.on("-D", "Shorthand for --exclusively=development,test") do
80
- options.exclusively = %i[development test]
81
- end
82
- parser.on("-v", "--version", "Display version") do
83
- require "bundler"
84
- puts "bundle_update_interactive/#{VERSION} bundler/#{Bundler::VERSION} #{RUBY_DESCRIPTION}"
85
- exit
86
- end
87
- parser.on("-h", "--help", "Show this help") do
88
- puts help
89
- exit
64
+ def build_parser(options) # rubocop:disable Metrics/AbcSize, Metrics/MethodLength
65
+ OptionParser.new do |parser| # rubocop:disable Metrics/BlockLength
66
+ parser.summary_indent = " "
67
+ parser.summary_width = 24
68
+ parser.on("--commit", "Create a git commit for each selected gem update") do
69
+ options.commit = true
70
+ end
71
+ parser.on("--latest", "Modify the Gemfile to allow the latest gem versions") do
72
+ options.latest = true
73
+ end
74
+ parser.on(
75
+ "--exclusively=GROUP",
76
+ "Update gems exclusively belonging to the specified Gemfile GROUP(s)"
77
+ ) do |value|
78
+ options.exclusively = value.split(",").map(&:strip).reject(&:empty?).map(&:to_sym)
79
+ end
80
+ parser.on("-D", "Shorthand for --exclusively=development,test") do
81
+ options.exclusively = %i[development test]
82
+ end
83
+ parser.on("-v", "--version", "Display version") do
84
+ require "bundler"
85
+ puts "bundle_update_interactive/#{VERSION} bundler/#{Bundler::VERSION} #{RUBY_DESCRIPTION}"
86
+ exit
87
+ end
88
+ parser.on("-h", "--help", "Show this help") do
89
+ puts help
90
+ exit
91
+ end
90
92
  end
91
93
  end
92
94
  end
93
- end
94
95
 
95
- attr_accessor :exclusively
96
- attr_writer :commit, :latest
96
+ attr_accessor :exclusively
97
+ attr_writer :commit, :latest
97
98
 
98
- def initialize
99
- @exclusively = []
100
- @commit = false
101
- @latest = false
102
- end
99
+ def initialize
100
+ @exclusively = []
101
+ @commit = false
102
+ @latest = false
103
+ end
103
104
 
104
- def commit?
105
- @commit
106
- end
105
+ def commit?
106
+ @commit
107
+ end
107
108
 
108
- def latest?
109
- @latest
109
+ def latest?
110
+ @latest
111
+ end
110
112
  end
111
113
  end
112
114
  end
@@ -3,53 +3,55 @@
3
3
  require "delegate"
4
4
  require "pastel"
5
5
 
6
- class BundleUpdateInteractive::CLI
7
- class Row < SimpleDelegator
8
- SEMVER_COLORS = {
9
- major: :red,
10
- minor: :yellow,
11
- patch: :green
12
- }.freeze
13
-
14
- def initialize(outdated_gem)
15
- super
16
- @pastel = BundleUpdateInteractive.pastel
17
- end
6
+ module BundleUpdateInteractive
7
+ class CLI
8
+ class Row < SimpleDelegator
9
+ SEMVER_COLORS = {
10
+ major: :red,
11
+ minor: :yellow,
12
+ patch: :green
13
+ }.freeze
18
14
 
19
- def formatted_gem_name
20
- vulnerable? ? pastel.white.on_red(name) : apply_semver_highlight(name)
21
- end
15
+ def initialize(outdated_gem)
16
+ super
17
+ @pastel = BundleUpdateInteractive.pastel
18
+ end
22
19
 
23
- def formatted_current_version
24
- [current_version.to_s, current_git_version].compact.join(" ")
25
- end
20
+ def formatted_gem_name
21
+ vulnerable? ? pastel.white.on_red(name) : apply_semver_highlight(name)
22
+ end
26
23
 
27
- def formatted_updated_version
28
- version = semver_change.format { |part| apply_semver_highlight(part) }
29
- git_version = apply_semver_highlight(updated_git_version)
24
+ def formatted_current_version
25
+ [current_version.to_s, current_git_version].compact.join(" ")
26
+ end
30
27
 
31
- [version, git_version].compact.join(" ")
32
- end
28
+ def formatted_updated_version
29
+ version = semver_change.format { |part| apply_semver_highlight(part) }
30
+ git_version = apply_semver_highlight(updated_git_version)
33
31
 
34
- def formatted_gemfile_groups
35
- gemfile_groups&.map(&:inspect)&.join(", ")
36
- end
32
+ [version, git_version].compact.join(" ")
33
+ end
37
34
 
38
- def formatted_gemfile_requirement
39
- gemfile_requirement.to_s == ">= 0" ? "" : gemfile_requirement.to_s
40
- end
35
+ def formatted_gemfile_groups
36
+ gemfile_groups&.map(&:inspect)&.join(", ")
37
+ end
41
38
 
42
- def formatted_changelog_uri
43
- pastel.blue(changelog_uri)
44
- end
39
+ def formatted_gemfile_requirement
40
+ gemfile_requirement.to_s == ">= 0" ? "" : gemfile_requirement.to_s
41
+ end
45
42
 
46
- def apply_semver_highlight(value)
47
- color = git_version_changed? ? :cyan : SEMVER_COLORS.fetch(semver_change.severity)
48
- pastel.decorate(value, color)
49
- end
43
+ def formatted_changelog_uri
44
+ pastel.blue(changelog_uri)
45
+ end
50
46
 
51
- private
47
+ def apply_semver_highlight(value)
48
+ color = git_version_changed? ? :cyan : SEMVER_COLORS.fetch(semver_change.severity)
49
+ pastel.decorate(value, color)
50
+ end
52
51
 
53
- attr_reader :pastel
52
+ private
53
+
54
+ attr_reader :pastel
55
+ end
54
56
  end
55
57
  end
@@ -2,83 +2,85 @@
2
2
 
3
3
  require "pastel"
4
4
 
5
- class BundleUpdateInteractive::CLI
6
- class Table
7
- class << self
8
- def withheld(gems)
9
- columns = [
10
- ["name", :formatted_gem_name],
11
- ["requirement", :formatted_gemfile_requirement],
12
- ["current", :formatted_current_version],
13
- ["latest", :formatted_updated_version],
14
- ["group", :formatted_gemfile_groups],
15
- ["url", :formatted_changelog_uri]
16
- ]
17
- new(gems, columns)
18
- end
5
+ module BundleUpdateInteractive
6
+ class CLI
7
+ class Table
8
+ class << self
9
+ def withheld(gems)
10
+ columns = [
11
+ ["name", :formatted_gem_name],
12
+ ["requirement", :formatted_gemfile_requirement],
13
+ ["current", :formatted_current_version],
14
+ ["latest", :formatted_updated_version],
15
+ ["group", :formatted_gemfile_groups],
16
+ ["url", :formatted_changelog_uri]
17
+ ]
18
+ new(gems, columns)
19
+ end
19
20
 
20
- def updatable(gems)
21
- columns = [
22
- ["name", :formatted_gem_name],
23
- ["from", :formatted_current_version],
24
- [nil, "→"],
25
- ["to", :formatted_updated_version],
26
- ["group", :formatted_gemfile_groups],
27
- ["url", :formatted_changelog_uri]
28
- ]
29
- new(gems, columns)
21
+ def updatable(gems)
22
+ columns = [
23
+ ["name", :formatted_gem_name],
24
+ ["from", :formatted_current_version],
25
+ [nil, "→"],
26
+ ["to", :formatted_updated_version],
27
+ ["group", :formatted_gemfile_groups],
28
+ ["url", :formatted_changelog_uri]
29
+ ]
30
+ new(gems, columns)
31
+ end
30
32
  end
31
- end
32
33
 
33
- def initialize(gems, columns)
34
- @pastel = BundleUpdateInteractive.pastel
35
- @headers = columns.map { |header, _| pastel.dim.underline(header) }
36
- @rows = gems.transform_values do |gem|
37
- row = Row.new(gem)
38
- columns.map do |_, col|
39
- case col
40
- when Symbol then row.public_send(col).to_s
41
- when String then col
34
+ def initialize(gems, columns)
35
+ @pastel = BundleUpdateInteractive.pastel
36
+ @headers = columns.map { |header, _| pastel.dim.underline(header) }
37
+ @rows = gems.transform_values do |gem|
38
+ row = Row.new(gem)
39
+ columns.map do |_, col|
40
+ case col
41
+ when Symbol then row.public_send(col).to_s
42
+ when String then col
43
+ end
42
44
  end
43
45
  end
46
+ @column_widths = calculate_column_widths
44
47
  end
45
- @column_widths = calculate_column_widths
46
- end
47
48
 
48
- def gem_names
49
- rows.keys
50
- end
49
+ def gem_names
50
+ rows.keys
51
+ end
51
52
 
52
- def render_header
53
- render_row(headers)
54
- end
53
+ def render_header
54
+ render_row(headers)
55
+ end
55
56
 
56
- def render_gem(name)
57
- row = rows.fetch(name)
58
- render_row(row)
59
- end
57
+ def render_gem(name)
58
+ row = rows.fetch(name)
59
+ render_row(row)
60
+ end
60
61
 
61
- def render
62
- lines = [render_header]
63
- rows.keys.sort.each { |name| lines << render_gem(name) }
64
- lines.join("\n")
65
- end
62
+ def render
63
+ lines = [render_header]
64
+ rows.keys.sort.each { |name| lines << render_gem(name) }
65
+ lines.join("\n")
66
+ end
66
67
 
67
- private
68
+ private
68
69
 
69
- attr_reader :column_widths, :pastel, :rows, :headers
70
+ attr_reader :column_widths, :pastel, :rows, :headers
70
71
 
71
- def render_row(row)
72
- row.zip(column_widths).map do |value, width|
73
- padding = width && (" " * (width - pastel.strip(value).length))
74
- "#{value}#{padding}"
75
- end.join(" ")
76
- end
72
+ def render_row(row)
73
+ row.zip(column_widths).map do |value, width|
74
+ padding = width && (" " * (width - pastel.strip(value).length))
75
+ "#{value}#{padding}"
76
+ end.join(" ")
77
+ end
77
78
 
78
- def calculate_column_widths
79
- rows_with_header = [headers, *rows.values]
80
- Array.new(headers.length - 1) do |i|
81
- rows_with_header.map { |values| pastel.strip(values[i]).length }.max
79
+ def calculate_column_widths
80
+ rows_with_header = [headers, *rows.values]
81
+ Array.new(headers.length - 1) do |i|
82
+ rows_with_header.map { |values| pastel.strip(values[i]).length }.max
83
+ end
82
84
  end
83
85
  end
84
86
  end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module BundleUpdateInteractive
4
- VERSION = "0.9.0"
4
+ VERSION = "0.9.1"
5
5
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: bundle_update_interactive
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.9.0
4
+ version: 0.9.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Matt Brictson
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2024-09-19 00:00:00.000000000 Z
11
+ date: 2024-11-24 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
@@ -168,7 +168,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
168
168
  - !ruby/object:Gem::Version
169
169
  version: '0'
170
170
  requirements: []
171
- rubygems_version: 3.5.19
171
+ rubygems_version: 3.5.23
172
172
  signing_key:
173
173
  specification_version: 4
174
174
  summary: Adds an update-interactive command to Bundler