all_in_ruby 0.2.0 → 0.2.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: 6930c270ee263f4f0479be9854cf03b7af4db01e88e6ffa3ee585a2dad0f152b
4
- data.tar.gz: f0491de4a159d7e327d6e6f270146ec5546213b82d6ed68dc5cbd1e3f1cd610a
3
+ metadata.gz: 55c6359657b51756cdaf08ac451944c082a262648baacffd13b29149b232869e
4
+ data.tar.gz: b91ef1b9f442d440b060d4e3bdbcc59dbdcb4bfe63219dc8ce78f5cb9c33e629
5
5
  SHA512:
6
- metadata.gz: d771a3ce9f1669f73d1bb441dfaaae80b180570ddcce09d6ea38f1c709fee3d9a8df778b6a8e72aa7b213591777066e51f06f5f016c892a1f3a4ab8b46993311
7
- data.tar.gz: 66e7bffbd34e3f45f1bd8366e8cbd12f068f93de6f89e3ea6cf5424772e8cdd0224b360174d8b617cd4e09a48334fe1b123b6f84f051432b32d5a1179463de73
6
+ metadata.gz: 1c09f7d78f6481e65f229894d95f378c77283493facc7d970e3b0323eb8ef48bb84a4d7409e1e8884c86d7cc6442d5cd95a7633505d43787d552e86c94660758
7
+ data.tar.gz: 40030931d424fc53f95edc456afcfc1a56fd3a27b0e82029d51b2c8b6a2603791f8d3a5626083664f9f25eccba8789c9f895d0f63628703e5dcfb589a15bb30b
data/CHANGELOG.md CHANGED
@@ -1,5 +1,10 @@
1
1
  # Changelog
2
2
 
3
+ ## 0.2.1 (2026-08-04)
4
+
5
+ - Require a complete instruction block when checking installation status, and preserve malformed or unrelated content when removing a later valid block
6
+ - Simplify the CLI and installer internals so command execution, reporting, dry runs, and result construction read more explicitly without changing their behavior
7
+
3
8
  ## 0.2.0 (2026-08-03)
4
9
 
5
10
  - `install` and `uninstall` now back up any existing file before modifying it, writing a timestamped copy (`CLAUDE.md.20260802-153000.bak`) next to the original and listing the backups created at the end of the run. New files are not backed up. Pass `--no-backup` to skip, or `--dry-run` to preview which backups would be made
@@ -41,39 +41,17 @@ module AllInRuby
41
41
  return 1
42
42
  end
43
43
 
44
- agents = options[:agents].empty? ? Installer::AGENTS.dup : options[:agents]
44
+ agents = options[:agents].empty? ? Installer::AGENTS : options[:agents]
45
45
  scopes = scopes_for(command, options[:scopes])
46
46
  dry_run = options[:dry_run] && command != "status"
47
47
 
48
- scope_results = scopes.map do |scope|
49
- results =
50
- if command == "status"
51
- @installer.status(agents: agents, scope: scope)
52
- else
53
- @installer.public_send(command, agents: agents, scope: scope, dry_run: dry_run, backup: options[:backup])
54
- end
55
- [scope, results]
56
- end
57
-
48
+ scope_results = results_by_scope(command, agents:, scopes:, dry_run:, backup: options[:backup])
58
49
  print_statuses(scope_results, dry_run ? DRY_RUN_LABELS : STATUS_LABELS)
59
50
 
60
51
  results = scope_results.flat_map { |_scope, scope_result| scope_result }
61
- results.each do |result|
62
- next unless result.diff
63
-
64
- @stdout.puts
65
- @stdout.puts result.diff
66
- end
67
-
52
+ print_diffs(results)
68
53
  print_backups(results, dry_run)
69
-
70
- if command == "install" && results.any? { |result| result.status == :manual }
71
- @stdout.puts
72
- @stdout.puts "Cursor has no global rules file. To apply the instruction globally,"
73
- @stdout.puts "paste this into Cursor Settings > Rules:"
74
- @stdout.puts
75
- @stdout.puts Instruction.body
76
- end
54
+ print_manual_instruction(command, results)
77
55
  0
78
56
  rescue OptionParser::ParseError => e
79
57
  @stderr.puts e.message
@@ -87,16 +65,19 @@ module AllInRuby
87
65
  def scopes_for(command, requested)
88
66
  return requested.uniq unless requested.empty?
89
67
 
90
- command == "status" ? Installer::SCOPES.dup : ["local"]
68
+ command == "status" ? Installer::SCOPES : ["local"]
91
69
  end
92
70
 
93
- def print_backups(results, dry_run)
94
- backups = results.filter_map(&:backup)
95
- return if backups.empty?
96
-
97
- @stdout.puts
98
- @stdout.puts(dry_run ? "Backups that would be created:" : "Backups created:")
99
- backups.each { |backup| @stdout.puts " #{backup}" }
71
+ def results_by_scope(command, agents:, scopes:, dry_run:, backup:)
72
+ scopes.map do |scope|
73
+ results =
74
+ if command == "status"
75
+ @installer.status(agents: agents, scope: scope)
76
+ else
77
+ @installer.public_send(command, agents: agents, scope: scope, dry_run: dry_run, backup: backup)
78
+ end
79
+ [scope, results]
80
+ end
100
81
  end
101
82
 
102
83
  def print_statuses(scope_results, labels)
@@ -111,6 +92,34 @@ module AllInRuby
111
92
  end
112
93
  end
113
94
 
95
+ def print_diffs(results)
96
+ results.each do |result|
97
+ next unless result.diff
98
+
99
+ @stdout.puts
100
+ @stdout.puts result.diff
101
+ end
102
+ end
103
+
104
+ def print_backups(results, dry_run)
105
+ backups = results.filter_map(&:backup)
106
+ return if backups.empty?
107
+
108
+ @stdout.puts
109
+ @stdout.puts(dry_run ? "Backups that would be created:" : "Backups created:")
110
+ backups.each { |backup| @stdout.puts " #{backup}" }
111
+ end
112
+
113
+ def print_manual_instruction(command, results)
114
+ return unless command == "install" && results.any? { |result| result.status == :manual }
115
+
116
+ @stdout.puts
117
+ @stdout.puts "Cursor has no global rules file. To apply the instruction globally,"
118
+ @stdout.puts "paste this into Cursor Settings > Rules:"
119
+ @stdout.puts
120
+ @stdout.puts Instruction.body
121
+ end
122
+
114
123
  def build_parser(options)
115
124
  OptionParser.new do |opts|
116
125
  opts.banner = <<~BANNER
@@ -7,7 +7,7 @@ module AllInRuby
7
7
  AGENTS = %w[claude codex opencode cursor].freeze
8
8
  SCOPES = %w[local global].freeze
9
9
 
10
- Result = Struct.new(:agent, :path, :status, :diff, :backup)
10
+ Result = Struct.new(:agent, :path, :status, :diff, :backup, keyword_init: true)
11
11
 
12
12
  def initialize(root: Dir.pwd, home: Dir.home, env: ENV, clock: -> { Time.now })
13
13
  @root = root
@@ -41,9 +41,9 @@ module AllInRuby
41
41
  :already_installed
42
42
  elsif content
43
43
  new_content = content + separator_for(content) + Instruction.block
44
- apply(path, content, new_content, :updated, dry_run, backup, planned)
44
+ apply(path, content, new_content, :updated, dry_run:, backup:, planned:)
45
45
  else
46
- apply(path, nil, Instruction.block, :created, dry_run, backup, planned)
46
+ apply(path, nil, Instruction.block, :created, dry_run:, backup:, planned:)
47
47
  end
48
48
  end
49
49
  end
@@ -54,7 +54,7 @@ module AllInRuby
54
54
  content = current_content(path, planned)
55
55
 
56
56
  if content && Instruction.installed?(content)
57
- apply(path, content, Instruction.remove(content), :removed, dry_run, backup, planned)
57
+ apply(path, content, Instruction.remove(content), :removed, dry_run:, backup:, planned:)
58
58
  else
59
59
  :not_installed
60
60
  end
@@ -92,17 +92,18 @@ module AllInRuby
92
92
  # Returns [status, diff, backup]. A backup is made only when an existing
93
93
  # file is modified (never on create); a dry run computes the name it would
94
94
  # use so the preview can report it, but writes nothing.
95
- def apply(path, old_content, new_content, status, dry_run, backup, planned)
95
+ def apply(path, old_content, new_content, status, dry_run:, backup:, planned:)
96
96
  backup_path = backup && old_content ? backup_path_for(path) : nil
97
+
97
98
  if dry_run
98
99
  planned[path] = new_content
99
- [status, Diff.unified(old_content, new_content, path), backup_path]
100
- else
101
- FileUtils.cp(path, backup_path) if backup_path
102
- FileUtils.mkdir_p(File.dirname(path)) unless old_content
103
- File.write(path, new_content)
104
- [status, nil, backup_path]
100
+ return [status, Diff.unified(old_content, new_content, path), backup_path]
105
101
  end
102
+
103
+ FileUtils.cp(path, backup_path) if backup_path
104
+ FileUtils.mkdir_p(File.dirname(path)) unless old_content
105
+ File.write(path, new_content)
106
+ [status, nil, backup_path]
106
107
  end
107
108
 
108
109
  def backup_path_for(path)
@@ -112,8 +113,10 @@ module AllInRuby
112
113
  def each_target(agents, scope)
113
114
  agents.map do |agent|
114
115
  path = path_for(agent, scope)
115
- status, diff, backup = path ? yield(path) : :manual
116
- Result.new(agent, path, status, diff, backup)
116
+ next Result.new(agent:, path:, status: :manual) unless path
117
+
118
+ status, diff, backup = yield(path)
119
+ Result.new(agent:, path:, status:, diff:, backup:)
117
120
  end
118
121
  end
119
122
  end
@@ -22,6 +22,11 @@ module AllInRuby
22
22
  MARKDOWN
23
23
 
24
24
  BLOCK = "#{BEGIN_MARKER}\n#{BODY}#{END_MARKER}\n".freeze
25
+ BLOCK_PATTERN = /
26
+ #{Regexp.escape(BEGIN_MARKER)}
27
+ (?:(?!#{Regexp.escape(BEGIN_MARKER)}).)*?
28
+ #{Regexp.escape(END_MARKER)}\n?
29
+ /mx
25
30
 
26
31
  def self.block
27
32
  BLOCK
@@ -32,11 +37,11 @@ module AllInRuby
32
37
  end
33
38
 
34
39
  def self.installed?(content)
35
- content.include?(BEGIN_MARKER)
40
+ content.match?(BLOCK_PATTERN)
36
41
  end
37
42
 
38
43
  def self.remove(content)
39
- content.gsub(/\n?#{Regexp.escape(BEGIN_MARKER)}.*?#{Regexp.escape(END_MARKER)}\n?/m, "\n")
44
+ content.gsub(BLOCK_PATTERN, "")
40
45
  end
41
46
  end
42
47
  end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module AllInRuby
4
- VERSION = "0.2.0"
4
+ VERSION = "0.2.1"
5
5
  end
data/lib/all_in_ruby.rb CHANGED
@@ -5,7 +5,3 @@ require_relative "all_in_ruby/instruction"
5
5
  require_relative "all_in_ruby/diff"
6
6
  require_relative "all_in_ruby/installer"
7
7
  require_relative "all_in_ruby/cli"
8
-
9
- module AllInRuby
10
- class Error < StandardError; end
11
- end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: all_in_ruby
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.0
4
+ version: 0.2.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Lucian Ghinda