concat.rb 1.0.2 → 1.1.2

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: 3750abff2498ac5e9f3ecb6e2218cdc461a8fdf289f9e4829e6bdfd4ad4fd97b
4
- data.tar.gz: dee8579f28fe3e4f3b0fcf14b9b21e86e1fa01b0c353931d7a4c5a420492da21
3
+ metadata.gz: f0c056ff4a28f726096fcfe5fcbb3beb399b59fc02d695cde8f8359e8ab448b8
4
+ data.tar.gz: f2ca13f24a9289018d8c012c834d5c939410f0310a4eb04d5818371c08294443
5
5
  SHA512:
6
- metadata.gz: 11dfb98869135d7c1ea9c0276f16ba668c4769f95784d90baecf3211b58ad675c14a2a2ac36fe118bb2cfe85d6eafb244c795249c1a237e323cd1b3176f4132a
7
- data.tar.gz: ca88c21d02813873052d67d17f36706044d452a47dfe5652897c075fba76d6934211b2b123de905d5afcd0d2162c7bb20a83cebef734b8c4ce87a10cea63b246
6
+ metadata.gz: 7a663594927daece9d5067107e7fa626bd67256e0149a120c67f1e81ccee7135e4e14ccb554f8bc09791849873222bdf7d7cd20d06d53c57264d06617008f60c
7
+ data.tar.gz: 26807147e7dfa8b78331c30dc2ccee7b67c2d4ce665f478ee0871e767de6f112101ffb5faa15c2d26e6d950c3f2a6ac55adf646ac0c173a9941799b163819164
data/.rubocop.yml ADDED
@@ -0,0 +1,37 @@
1
+ AllCops:
2
+ DisabledByDefault: true
3
+
4
+ RubyInterpreters:
5
+ - ruby
6
+
7
+ Include:
8
+ - '**/*.rb'
9
+ - '.pryrc'
10
+
11
+ Exclude:
12
+ <% Dir.glob("#{__dir__}/*").grep_v(%r{#{__dir__}\/(app|lib)}).each do |dir| %>
13
+ - <%= dir %>/**/*
14
+ <% end %>
15
+ - 'lib/templates/**/*'
16
+
17
+ Layout/IndentationConsistency:
18
+ Enabled: true
19
+ EnforcedStyle: indented_internal_methods
20
+
21
+ Layout/BlockEndNewline:
22
+ Enabled: true
23
+
24
+ Layout/BeginEndAlignment:
25
+ Enabled: true
26
+ EnforcedStyleAlignWith: start_of_line
27
+
28
+ Layout/ElseAlignment:
29
+ Enabled: true
30
+
31
+ Layout/DefEndAlignment:
32
+ Enabled: true
33
+ EnforcedStyleAlignWith: def
34
+
35
+ Layout/EmptyLinesAroundAccessModifier:
36
+ Enabled: true
37
+ EnforcedStyle: around
data/AGENTS.md ADDED
@@ -0,0 +1,55 @@
1
+ # AGENTS.md
2
+
3
+ ## Specifications
4
+
5
+ **IMPORTANT:** Before implementing any feature, consult the specifications in `specs/README.md`.
6
+
7
+ - **Assume NOT implemented.** Many specs describe planned features that may not yet exist in the codebase.
8
+ - **Check the codebase first.** Before concluding something is or isn't implemented, search the actual code. Specs describe intent; code describes reality.
9
+ - **Use specs as guidance.** When implementing a feature, follow the design patterns, types, and architecture defined in the relevant spec.
10
+ - **Spec index:** `specs/README.md` lists all specifications organized by category (core, LLM, security, etc.).
11
+
12
+ ## Development Commands
13
+
14
+ ```bash
15
+ # Setup
16
+ bin/setup
17
+
18
+ # Run all tests
19
+ bin/test
20
+
21
+ # Run a single test file
22
+ bin/test test/cli_test.rb
23
+
24
+ # Lint
25
+ bin/rubocop
26
+
27
+ # Interactive console
28
+ bin/console
29
+ ```
30
+
31
+ ## Architecture
32
+
33
+ concat.rb is a Ruby gem providing two CLI tools for file concatenation and restoration.
34
+
35
+ ### Core Components
36
+
37
+ - **`Concat::CLI`** (`lib/concat/cli.rb`) - Recursively reads files from directories, outputs contents prefixed with `# File path: <path>` markers. Supports `--extensions` flag for filtering.
38
+
39
+ - **`Concat::DeconcatCLI`** (`lib/concat/deconcat_cli.rb`) - Parses concatenated output from STDIN, extracts file boundaries via `# File path:` markers, recreates directory structure and writes files.
40
+
41
+ ### Entry Points
42
+
43
+ Executables in `exe/` instantiate the CLI classes and call `#call(ARGV)`, returning exit codes.
44
+
45
+ ### File Format
46
+
47
+ The concatenation format uses `# File path: <relative_path>` as a delimiter:
48
+
49
+ ```
50
+ # File path: ./lib/foo.rb
51
+ <file contents>
52
+
53
+ # File path: ./lib/bar.rb
54
+ <file contents>
55
+ ```
data/CLAUDE.md ADDED
@@ -0,0 +1 @@
1
+ AGENTS.md
data/Gemfile CHANGED
@@ -2,7 +2,8 @@
2
2
 
3
3
  source "https://rubygems.org"
4
4
 
5
- gemspec
5
+ gemspec name: "concat.rb"
6
+
6
7
 
7
8
  group :development do
8
9
  #gem "minitest", "~> 5.0"
data/Gemfile.lock CHANGED
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- mirrorfile (0.1.0)
4
+ concat.rb (1.1.1)
5
5
 
6
6
  GEM
7
7
  remote: https://rubygems.org/
@@ -45,8 +45,8 @@ PLATFORMS
45
45
  x86_64-linux
46
46
 
47
47
  DEPENDENCIES
48
+ concat.rb!
48
49
  minitest (~> 5.0)
49
- mirrorfile!
50
50
  rake (~> 13.0)
51
51
  rubocop (~> 1.21)
52
52
  yard (~> 0.9)
data/bin/rubocop ADDED
@@ -0,0 +1,6 @@
1
+ #!/usr/bin/env bash
2
+ set -euo pipefail
3
+
4
+ cd "$(dirname "$0")/.."
5
+
6
+ bundle exec rubocop "$@"
data/bin/test ADDED
@@ -0,0 +1,10 @@
1
+ #!/usr/bin/env bash
2
+ set -euo pipefail
3
+
4
+ cd "$(dirname "$0")/.."
5
+
6
+ if [ $# -eq 0 ]; then
7
+ bundle exec ruby -Itest -e 'Dir.glob("test/**/*_test.rb").each { |f| require "./#{f}" }'
8
+ else
9
+ bundle exec ruby -Itest "$@"
10
+ fi
data/concat2.gemspec ADDED
@@ -0,0 +1,36 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative "lib/concat/version"
4
+
5
+ Gem::Specification.new do |spec|
6
+ spec.name = "concat"
7
+ spec.version = Concat::VERSION
8
+ spec.authors = ["Nathan Kidd"]
9
+ spec.email = ["nathankidd@hey.com"]
10
+
11
+ spec.summary = "Concatenate files from directories with optional extension filtering"
12
+
13
+ spec.description = <<~DESC
14
+ A simple CLI tool that recursively reads files from directories and outputs
15
+ their contents with file path comments. Supports filtering by file extensions.
16
+ DESC
17
+
18
+ spec.homepage = "https://github.com/n-at-han-k/concat.rb"
19
+ spec.license = "MIT"
20
+ spec.required_ruby_version = ">= 3.2.0"
21
+
22
+ spec.metadata["homepage_uri"] = spec.homepage
23
+ spec.metadata["source_code_uri"] = spec.homepage
24
+ spec.metadata["documentation_uri"] = spec.homepage
25
+ spec.metadata["rubygems_mfa_required"] = "true"
26
+
27
+ spec.files = `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features|data)/}) }
28
+ spec.bindir = "exe"
29
+ spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
30
+ spec.require_paths = ["lib"]
31
+
32
+ spec.add_development_dependency "minitest", "~> 5.0"
33
+ spec.add_development_dependency "rake", "~> 13.0"
34
+ spec.add_development_dependency "rubocop", "~> 1.21"
35
+ spec.add_development_dependency "yard", "~> 0.9"
36
+ end
data/lib/concat/cli.rb CHANGED
@@ -10,7 +10,7 @@ module Concat
10
10
  extensions = ""
11
11
 
12
12
  parser = OptionParser.new do |parse|
13
- parse.banner = "Usage: concat FOLDERS... --extensions=rb,py,md"
13
+ parse.banner = "Usage: concat PATHS... --extensions=rb,py,md"
14
14
  parse.on("--extensions=LIST", String, "File extensions to include") do |value|
15
15
  extensions = ".{#{value}}"
16
16
  end
@@ -24,18 +24,38 @@ module Concat
24
24
  return 1
25
25
  end
26
26
 
27
- argv.each do |folder|
28
- Dir.glob("#{folder}/**/*#{extensions}").each do |path|
29
- if File.file?(path)
30
- puts "#{COMMENT} File path: #{path}"
31
- puts File.read(path)
32
- puts
27
+ argv.each do |arg|
28
+ if File.file?(arg)
29
+ next if binary_file?(arg)
30
+ puts "#{COMMENT} File path: #{arg}"
31
+ puts File.read(arg)
32
+ puts
33
+ elsif File.directory?(arg)
34
+ Dir.glob("#{arg}/**/*#{extensions}").each do |path|
35
+ if File.file?(path) && !binary_file?(path)
36
+ puts "#{COMMENT} File path: #{path}"
37
+ puts File.read(path)
38
+ puts
39
+ end
33
40
  end
41
+ else
42
+ warn "concat: #{arg}: No such file or directory"
43
+ return 1
34
44
  end
35
45
  end
36
46
 
37
47
  0
38
48
  end
49
+
50
+ private
51
+
52
+ def binary_file?(path)
53
+ File.open(path, "rb") do |file|
54
+ chunk = file.read(8192)
55
+ return false if chunk.nil?
56
+ chunk.include?("\x00")
57
+ end
58
+ end
39
59
  end
40
60
  end
41
61
 
@@ -10,7 +10,7 @@ module Concat
10
10
 
11
11
  ARGF.each_line do |line|
12
12
  if line.start_with?("# File path: ")
13
- File.write(current_path, content.join) if current_path && !content.empty?
13
+ File.write(current_path, content.join.chomp) if current_path && !content.empty?
14
14
  current_path = line.sub("# File path: ", "").strip
15
15
  content = []
16
16
  FileUtils.mkdir_p(File.dirname(current_path))
@@ -19,7 +19,7 @@ module Concat
19
19
  end
20
20
  end
21
21
 
22
- File.write(current_path, content.join) if current_path && !content.empty?
22
+ File.write(current_path, content.join.chomp) if current_path && !content.empty?
23
23
 
24
24
  0
25
25
  end
@@ -1,6 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Concat
4
- VERSION = "1.0.2"
4
+ VERSION = "1.1.2"
5
5
  end
6
6
 
data/specs/README.md ADDED
@@ -0,0 +1,31 @@
1
+ <!--
2
+ Copyright (c) 2025 Nathan Kidd <nathankidd@hey.com>. All rights reserved.
3
+ SPDX-License-Identifier: Proprietary
4
+ -->
5
+
6
+ <!--
7
+ HOW TO MAINTAIN THIS FILE
8
+
9
+ This is the index of all design specifications for concat.rb.
10
+ Each row links a spec document to its implementation code and a short purpose summary.
11
+
12
+ When adding a new spec:
13
+ 1. Create the markdown file in this directory (specs/)
14
+ 2. Add a row to the appropriate table section below
15
+ 3. Link the spec file, the code path it describes, and a brief purpose
16
+
17
+ Table format:
18
+ | [spec-name.md](./spec-name.md) | [path/to/code](../path/to/code) | Short description |
19
+
20
+ Use "—" in the Code column if the spec has no implementation yet.
21
+ Group specs under heading sections by domain area.
22
+ -->
23
+
24
+ # Project Specifications
25
+
26
+ concat.rb is a CLI tool for concatenating files from directories into a single output with file path markers, and reversing the process.
27
+
28
+ ## Core
29
+
30
+ | Spec | Code | Purpose |
31
+ |------|------|---------|
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: concat.rb
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.0.2
4
+ version: 1.1.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - Nathan Kidd
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2026-01-15 00:00:00.000000000 Z
11
+ date: 2026-03-08 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: minitest
@@ -78,20 +78,27 @@ extensions: []
78
78
  extra_rdoc_files: []
79
79
  files:
80
80
  - ".github/workflows/gem-push.yml"
81
+ - ".rubocop.yml"
82
+ - AGENTS.md
83
+ - CLAUDE.md
81
84
  - Gemfile
82
85
  - Gemfile.lock
83
86
  - LICENSE.txt
84
87
  - README.md
85
88
  - Rakefile
86
89
  - bin/console
90
+ - bin/rubocop
87
91
  - bin/setup
92
+ - bin/test
88
93
  - concat.gemspec
94
+ - concat2.gemspec
89
95
  - exe/concat
90
96
  - exe/deconcat
91
97
  - lib/concat.rb
92
98
  - lib/concat/cli.rb
93
99
  - lib/concat/deconcat_cli.rb
94
100
  - lib/concat/version.rb
101
+ - specs/README.md
95
102
  homepage: https://github.com/n-at-han-k/concat.rb
96
103
  licenses:
97
104
  - MIT