yaml_smith 0.1.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 ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: d7ff73d942d1f809bbac011b168ef43cd3ce7b8d193292c661e6d2d65a358498
4
+ data.tar.gz: 4e6fe2d3391a53d6fd9d364d0b87061342409033ba9be4e29520eb8ab75b4e20
5
+ SHA512:
6
+ metadata.gz: 0da49b2b19add33c7a5137624bb6347c39c87ea6bc203c7ad416a77e026bf3c387b3ca5f0fbb10e550716f50c6729592c4ffa8b1204ef255d808e5c15782baf4
7
+ data.tar.gz: 241861d560bdce07bdfe246c11618f83750a00f31d338a140c820147faf9482df223ff115df8fcf0fe6b29db93f4d1544cb82efd19be7422ba304a8b59662609
data/AGENTS.md ADDED
@@ -0,0 +1,22 @@
1
+ # Agent Guide
2
+
3
+ ## Commands
4
+
5
+ - Install dependencies with `bundle install`.
6
+ - Run all tests with `bundle exec rake test`.
7
+ - Run one test file with `bundle exec ruby -Ilib:test test/test_add_key.rb` (replace the filename as needed).
8
+ - The CI/default task is `bundle exec rake`, which runs tests followed by RuboCop.
9
+
10
+ ## Structure
11
+
12
+ - `exe/yaml-smith` is only the executable wrapper; CLI dispatch and error handling belong in `lib/yaml_smith/cli.rb`.
13
+ - Each command has its own class and file: `AddKey`, `SetKey`, and `DeleteKey`.
14
+ - Shared file loading, validation, and atomic writing live in `YamlSmith::FileCommand`.
15
+ - Commands currently operate on top-level mapping keys only; do not add nested-path behavior implicitly.
16
+
17
+ ## YAML Behavior
18
+
19
+ - Use `Psych::Pure`, not standard `Psych`; it is required to preserve comments where possible.
20
+ - Load existing files and values with `comments: true`.
21
+ - Values passed on the command line are YAML and should retain their YAML types.
22
+ - File edits are written through a same-directory temporary file and rename; preserve this atomic-write behavior.
data/LICENSE.txt ADDED
@@ -0,0 +1,21 @@
1
+ The MIT License (MIT)
2
+
3
+ Copyright (c) 2026 Andy Waite
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in
13
+ all copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21
+ THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,60 @@
1
+ # YamlSmith
2
+
3
+ A command-line tool for manipulating YAML files while preserving comments,
4
+ powered by [Psych::Pure](https://github.com/kddnewton/psych-pure).
5
+
6
+ ## Installation
7
+
8
+ Install the gem and add it to your application's Gemfile:
9
+
10
+ ```bash
11
+ bundle add yaml_smith
12
+ ```
13
+
14
+ If Bundler is not being used, install the gem directly:
15
+
16
+ ```bash
17
+ gem install yaml_smith
18
+ ```
19
+
20
+ ## Usage
21
+
22
+ Add a top-level key to an existing YAML file:
23
+
24
+ ```bash
25
+ yaml-smith add config.yml timeout 30
26
+ ```
27
+
28
+ The value is parsed as YAML, so values such as `true`, `null`, arrays, and
29
+ objects retain their YAML types. Existing keys are not overwritten.
30
+
31
+ Set or replace a top-level key:
32
+
33
+ ```bash
34
+ yaml-smith set config.yml timeout 60
35
+ ```
36
+
37
+ Delete a top-level key:
38
+
39
+ ```bash
40
+ yaml-smith delete config.yml timeout
41
+ ```
42
+
43
+ ## Development
44
+
45
+ After checking out the repo, run `bin/setup` to install dependencies. Then,
46
+ run `bundle exec rake test` to run the tests. You can also run `bin/console` for
47
+ an interactive prompt.
48
+
49
+ To install this gem locally, run `bundle exec rake install`. To release a new
50
+ version, update `version.rb`, then run `bundle exec rake release`.
51
+
52
+ ## Contributing
53
+
54
+ Bug reports and pull requests are welcome on GitHub at
55
+ https://github.com/andyw8/yaml_smith.
56
+
57
+ ## License
58
+
59
+ The gem is available as open source under the terms of the [MIT
60
+ License](https://opensource.org/licenses/MIT).
data/Rakefile ADDED
@@ -0,0 +1,12 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "bundler/gem_tasks"
4
+ require "minitest/test_task"
5
+
6
+ Minitest::TestTask.create
7
+
8
+ require "rubocop/rake_task"
9
+
10
+ RuboCop::RakeTask.new
11
+
12
+ task default: %i[test rubocop]
data/exe/yaml-smith ADDED
@@ -0,0 +1,6 @@
1
+ #!/usr/bin/env ruby
2
+ # frozen_string_literal: true
3
+
4
+ require 'yaml_smith/cli'
5
+
6
+ exit YamlSmith::CLI.call(ARGV)
@@ -0,0 +1,17 @@
1
+ # frozen_string_literal: true
2
+
3
+ module YamlSmith
4
+ # Adds a top-level key to a YAML file.
5
+ class AddKey < FileCommand
6
+ def call
7
+ document = load_file(@path)
8
+ value = load(@value)
9
+
10
+ ensure_mapping(document)
11
+ raise Error, "key already exists: #{@key}" if document.key?(@key)
12
+
13
+ document[@key] = value
14
+ write(Psych::Pure.dump(document))
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,54 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative '../yaml_smith'
4
+
5
+ module YamlSmith
6
+ # Dispatches command-line arguments to a YAML Smith command.
7
+ class CLI
8
+ COMMANDS = {
9
+ 'add' => AddKey,
10
+ 'set' => SetKey,
11
+ 'delete' => DeleteKey
12
+ }.freeze
13
+ USAGE = 'Usage: yaml-smith COMMAND FILE KEY [VALUE]'
14
+
15
+ def self.call(arguments)
16
+ new(arguments).call
17
+ end
18
+
19
+ def initialize(arguments)
20
+ @arguments = arguments
21
+ end
22
+
23
+ def call
24
+ command = COMMANDS[@arguments.first]
25
+ return usage unless valid_arguments?(command)
26
+
27
+ command.call(*command_arguments)
28
+ rescue Error => e
29
+ warn e.message
30
+ 1
31
+ end
32
+
33
+ private
34
+
35
+ def valid_arguments?(command)
36
+ return false unless command
37
+
38
+ @arguments.length == (delete_command? ? 3 : 4)
39
+ end
40
+
41
+ def delete_command?
42
+ @arguments.first == 'delete'
43
+ end
44
+
45
+ def command_arguments
46
+ @arguments.drop(1)
47
+ end
48
+
49
+ def usage
50
+ warn USAGE
51
+ 1
52
+ end
53
+ end
54
+ end
@@ -0,0 +1,16 @@
1
+ # frozen_string_literal: true
2
+
3
+ module YamlSmith
4
+ # Deletes a top-level key from a YAML file.
5
+ class DeleteKey < FileCommand
6
+ def call
7
+ document = load_file(@path)
8
+
9
+ ensure_mapping(document)
10
+ raise Error, "key does not exist: #{@key}" unless document.key?(@key)
11
+
12
+ document.delete(@key)
13
+ write(Psych::Pure.dump(document))
14
+ end
15
+ end
16
+ end
@@ -0,0 +1,48 @@
1
+ # frozen_string_literal: true
2
+
3
+ module YamlSmith
4
+ # Provides shared YAML file editing behavior for commands.
5
+ class FileCommand
6
+ def initialize(path, key, value = nil)
7
+ @path = path
8
+ @key = key
9
+ @value = value
10
+ end
11
+
12
+ def self.call(...)
13
+ new(...).call
14
+ end
15
+
16
+ private
17
+
18
+ def load_file(path)
19
+ load(File.read(path, encoding: 'UTF-8'))
20
+ rescue SystemCallError => e
21
+ raise Error, e.message
22
+ end
23
+
24
+ def load(source)
25
+ Psych::Pure.load(source, comments: true)
26
+ rescue Psych::Exception => e
27
+ raise Error, "invalid YAML: #{e.message}"
28
+ end
29
+
30
+ def ensure_mapping(document)
31
+ return if document.instance_of?(Psych::Pure::LoadedHash)
32
+
33
+ raise Error, 'YAML document must contain a top-level mapping'
34
+ end
35
+
36
+ def write(contents)
37
+ mode = File.stat(@path).mode & 0o7777
38
+
39
+ Tempfile.create(['.yaml-smith-', '.tmp'], File.dirname(@path)) do |file|
40
+ file.chmod(mode)
41
+ file.write(contents)
42
+ file.flush
43
+ file.fsync
44
+ File.rename(file.path, @path)
45
+ end
46
+ end
47
+ end
48
+ end
@@ -0,0 +1,15 @@
1
+ # frozen_string_literal: true
2
+
3
+ module YamlSmith
4
+ # Sets a top-level key in a YAML file, adding or replacing it.
5
+ class SetKey < FileCommand
6
+ def call
7
+ document = load_file(@path)
8
+ value = load(@value)
9
+
10
+ ensure_mapping(document)
11
+ document[@key] = value
12
+ write(Psych::Pure.dump(document))
13
+ end
14
+ end
15
+ end
@@ -0,0 +1,5 @@
1
+ # frozen_string_literal: true
2
+
3
+ module YamlSmith
4
+ VERSION = "0.1.0"
5
+ end
data/lib/yaml_smith.rb ADDED
@@ -0,0 +1,14 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative 'yaml_smith/version'
4
+ require 'psych/pure'
5
+ require 'tempfile'
6
+
7
+ module YamlSmith
8
+ class Error < StandardError; end
9
+ end
10
+
11
+ require_relative 'yaml_smith/file_command'
12
+ require_relative 'yaml_smith/add_key'
13
+ require_relative 'yaml_smith/set_key'
14
+ require_relative 'yaml_smith/delete_key'
@@ -0,0 +1,4 @@
1
+ module YamlSmith
2
+ VERSION: String
3
+ # See the writing guide of rbs: https://github.com/ruby/rbs#guides
4
+ end
metadata ADDED
@@ -0,0 +1,71 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: yaml_smith
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ platform: ruby
6
+ authors:
7
+ - Andy Waite
8
+ bindir: exe
9
+ cert_chain: []
10
+ date: 1980-01-02 00:00:00.000000000 Z
11
+ dependencies:
12
+ - !ruby/object:Gem::Dependency
13
+ name: psych-pure
14
+ requirement: !ruby/object:Gem::Requirement
15
+ requirements:
16
+ - - ">="
17
+ - !ruby/object:Gem::Version
18
+ version: '0'
19
+ type: :runtime
20
+ prerelease: false
21
+ version_requirements: !ruby/object:Gem::Requirement
22
+ requirements:
23
+ - - ">="
24
+ - !ruby/object:Gem::Version
25
+ version: '0'
26
+ description: YamlSmith manipulates YAML files from the command line and uses Psych::Pure
27
+ to preserve comments where possible.
28
+ email:
29
+ - andyw8@users.noreply.github.com
30
+ executables:
31
+ - yaml-smith
32
+ extensions: []
33
+ extra_rdoc_files: []
34
+ files:
35
+ - AGENTS.md
36
+ - LICENSE.txt
37
+ - README.md
38
+ - Rakefile
39
+ - exe/yaml-smith
40
+ - lib/yaml_smith.rb
41
+ - lib/yaml_smith/add_key.rb
42
+ - lib/yaml_smith/cli.rb
43
+ - lib/yaml_smith/delete_key.rb
44
+ - lib/yaml_smith/file_command.rb
45
+ - lib/yaml_smith/set_key.rb
46
+ - lib/yaml_smith/version.rb
47
+ - sig/yaml_smith.rbs
48
+ homepage: https://github.com/andyw8/yaml_smith
49
+ licenses:
50
+ - MIT
51
+ metadata:
52
+ homepage_uri: https://github.com/andyw8/yaml_smith
53
+ source_code_uri: https://github.com/andyw8/yaml_smith
54
+ rdoc_options: []
55
+ require_paths:
56
+ - lib
57
+ required_ruby_version: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - ">="
60
+ - !ruby/object:Gem::Version
61
+ version: 3.2.0
62
+ required_rubygems_version: !ruby/object:Gem::Requirement
63
+ requirements:
64
+ - - ">="
65
+ - !ruby/object:Gem::Version
66
+ version: '0'
67
+ requirements: []
68
+ rubygems_version: 4.0.16
69
+ specification_version: 4
70
+ summary: A command-line tool for manipulating YAML files while preserving comments.
71
+ test_files: []