context_spook 0.4.0 → 0.5.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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: acac1bb23044efca6b50d929dfeda70b409cb95fc81f2a18f269d67ca2fb857d
4
- data.tar.gz: 80c69f95ab2f595daf33eb5646d0cc0133c0752ea74ac73b4737eb0b2f57cd32
3
+ metadata.gz: bf46500652e697db299ccdfe21d5dd4c02953b699ca528b21810f87348eddceb
4
+ data.tar.gz: ad41e6c9f6141ba5303c845aaf26c2d141125201d82575834a62efc05c2ae7b8
5
5
  SHA512:
6
- metadata.gz: c68f160740a7b1af14ce1f6260fd08430745e7f338e4151c88a46da708d8635572471400600ad119fcfdd9c33d7f9944ec9fe5ca8710778d61f919403de8c38d
7
- data.tar.gz: 20a6c25fc8097d67d6b4111b4d6fd6c15b5ad12512e05b93e68d27f32ca8adb58d9f20255a30b9dfcb679b2c4e89a4108eaaa37fc2388153243ae6812f33b4f7
6
+ metadata.gz: edab814b82519dc36f9bb01c4e59dfb372aad6c2e1fa0d8ef7f487a288281ad6bf9bf1474d09a7ff7b818c1a6140ef08c0ba464b986e9bf56a34bd2720f9e778
7
+ data.tar.gz: 052e05ca7fc2825a75b43e1b9a8585344f9d4e8a6a805e3a5d826680d81bfed723d4359db7083d6451ce4afa6e35e82688a979dae0fcd0dcde401784d373b2de
data/.contexts/project.rb CHANGED
@@ -5,6 +5,12 @@ context do
5
5
  command "tree", tags: %w[ project_structure ]
6
6
  end
7
7
 
8
+ namespace "bin" do
9
+ Dir['bin/**/*'].each do |filename|
10
+ file filename, tags: 'bin'
11
+ end
12
+ end
13
+
8
14
  namespace "lib" do
9
15
  Dir['lib/**/*.rb'].each do |filename|
10
16
  file filename, tags: 'lib'
data/README.md CHANGED
@@ -12,6 +12,10 @@ information. The `.contexts/project.rb` example below demonstrates how to
12
12
  describe a Ruby project, but the same principles apply across many different
13
13
  domains.
14
14
 
15
+ ## Documentation
16
+
17
+ Complete API documentation is available at: [GitHub.io](https://flori.github.io/context_spook/)
18
+
15
19
  ## Installation
16
20
 
17
21
  Add this line to your application's Gemfile:
@@ -128,13 +132,35 @@ Generate context and save to file:
128
132
 
129
133
  Or pipe directly to another tool:
130
134
 
131
- ```
135
+ ```bash
132
136
  ./bin/context_spook .contexts/project.rb | ollama_chat_send
133
137
  ```
134
138
 
135
- You will see two orange warning messages, that demonstrates how errors like
139
+
140
+ The CLI tool also supports verbose output:
141
+
142
+ ```bash
143
+ # Generate context with verbose output
144
+ ./bin/context_spook .contexts/project.rb -v
145
+ ```
146
+
147
+ Now you can see two orange warning messages, that demonstrates how errors like
136
148
  missing files or commands with failing exit codes are handled.
137
149
 
150
+ The CLI tool also supports file redirection:
151
+
152
+ ```bash
153
+ # Generate context and save to file
154
+ ./bin/context_spook .contexts/project.rb -o context.json
155
+ ```
156
+
157
+ This is how you can show the usage message:
158
+
159
+ ```
160
+ # Show help
161
+ ./bin/context_spook -h
162
+ ```
163
+
138
164
  ## What Gets Collected
139
165
 
140
166
  The DSL collects various types of project information:
data/Rakefile CHANGED
@@ -9,7 +9,6 @@ GemHadar do
9
9
  email 'flori@ping.de'
10
10
  homepage "https://github.com/flori/context_spook"
11
11
  summary "#{name} collects project context for AI"
12
- executables 'context_spook'
13
12
 
14
13
  description <<~EOT
15
14
  #{name} is a library that collects and organizes project
@@ -24,6 +23,12 @@ GemHadar do
24
23
  '.rspec', '.github'
25
24
  readme 'README.md'
26
25
 
26
+ executables 'context_spook'
27
+
28
+ github_workflows(
29
+ 'static.yml' => {}
30
+ )
31
+
27
32
  required_ruby_version '~> 3.1'
28
33
 
29
34
  dependency 'tins', '~>1.39'
data/bin/context_spook CHANGED
@@ -1,7 +1,57 @@
1
1
  #!/usr/bin/env ruby
2
2
 
3
3
  require 'context_spook'
4
+ require 'tins/go'
5
+ include Tins::GO
6
+ require 'json'
4
7
 
5
- filename = ARGV.shift or fail 'require context definition file as first argument'
6
- context_json = ContextSpook.generate_context(filename).to_json
7
- puts context_json
8
+ # The usage method displays the command-line interface help text and example
9
+ # usage patterns for the ContextSpook tool.
10
+ #
11
+ # This method outputs a formatted help message that includes the tool's usage
12
+ # syntax, available options, and practical examples.
13
+ #
14
+ # @see ContextSpook::generate_context
15
+ # @see ContextSpook::Generator
16
+ # @see ContextSpook::Generator::Context
17
+ def usage
18
+ puts <<~EOT
19
+
20
+ Usage: #{File.basename($0)} [options] <context_definition_file>
21
+
22
+ Options:
23
+ -o FILE Write output to FILE instead of stdout
24
+ -v Verbose output
25
+ -h Show this help message
26
+
27
+ Examples:
28
+ # Generate context and output to stdout
29
+ #{File.basename($0)} .contexts/project.rb
30
+
31
+ # Generate context and save to file
32
+ #{File.basename($0)} .contexts/project.rb -o context.json
33
+
34
+ # Generate context with verbose output
35
+ #{File.basename($0)} .contexts/project.rb -v
36
+
37
+ # Generate context and pipe to another tool
38
+ #{File.basename($0)} .contexts/project.rb | ollama_chat_send
39
+
40
+ EOT
41
+ exit 0
42
+ end
43
+
44
+ opts = go 'o:pvh'
45
+ opts[?h] and usage
46
+ filename = ARGV.shift or fail 'require context definition file as an argument'
47
+ output = nil
48
+ context = ContextSpook.generate_context(filename, verbose: opts[?v])
49
+ if output_filename = opts[?o]
50
+ if File.exist?(output_filename)
51
+ fail "Filename #{output_filename.inspect} already exists!"
52
+ end
53
+ output = File.new output_filename, ?w
54
+ else
55
+ output = STDOUT
56
+ end
57
+ JSON.dump(context.as_json, output)
@@ -1,9 +1,9 @@
1
1
  # -*- encoding: utf-8 -*-
2
- # stub: context_spook 0.4.0 ruby lib
2
+ # stub: context_spook 0.5.0 ruby lib
3
3
 
4
4
  Gem::Specification.new do |s|
5
5
  s.name = "context_spook".freeze
6
- s.version = "0.4.0".freeze
6
+ s.version = "0.5.0".freeze
7
7
 
8
8
  s.required_rubygems_version = Gem::Requirement.new(">= 0".freeze) if s.respond_to? :required_rubygems_version=
9
9
  s.require_paths = ["lib".freeze]
@@ -18,13 +18,13 @@ Gem::Specification.new do |s|
18
18
  s.licenses = ["MIT".freeze]
19
19
  s.rdoc_options = ["--title".freeze, "ContextSpook - context_spook collects project context for AI".freeze, "--main".freeze, "README.md".freeze]
20
20
  s.required_ruby_version = Gem::Requirement.new("~> 3.1".freeze)
21
- s.rubygems_version = "3.6.9".freeze
21
+ s.rubygems_version = "3.7.2".freeze
22
22
  s.summary = "context_spook collects project context for AI".freeze
23
23
  s.test_files = ["spec/context_spook/generator_spec.rb".freeze, "spec/spec_helper.rb".freeze]
24
24
 
25
25
  s.specification_version = 4
26
26
 
27
- s.add_development_dependency(%q<gem_hadar>.freeze, ["~> 2.2".freeze])
27
+ s.add_development_dependency(%q<gem_hadar>.freeze, ["~> 2.8".freeze])
28
28
  s.add_development_dependency(%q<all_images>.freeze, ["~> 0.6".freeze])
29
29
  s.add_development_dependency(%q<rspec>.freeze, ["~> 3.2".freeze])
30
30
  s.add_development_dependency(%q<debug>.freeze, [">= 0".freeze])
@@ -9,24 +9,35 @@ require 'mime-types'
9
9
  module ContextSpook
10
10
  include DSLKit::Interpreter
11
11
 
12
- # The generate_context method processes a context definition file and returns
13
- # the resulting context object.
12
+ # The generate_context method processes a context definition file or block
13
+ # and returns the resulting context object.
14
14
  #
15
- # This method reads the content of a specified file, parses it using the
16
- # generator's parsing mechanism, and extracts the configured context from the
17
- # parsed result.
15
+ # This method serves as the primary entry point for generating project
16
+ # context data. It accepts either a filename pointing to a context definition
17
+ # file or a block containing the context definition, but not both.
18
+ # When a filename is provided, it reads and parses the file content. When a
19
+ # block is provided, it evaluates the block within the generator's context.
20
+ # The method ensures that only one context definition mechanism is used.
18
21
  #
19
- # @param filename [ String ] the path to the context definition file to be processed
22
+ # @param filename [ String, nil ] the path to the context definition file to
23
+ # be processed
24
+ # @param verbose [ TrueClass, FalseClass ] flag to enable verbose output
25
+ # during processing, defaults to false.
26
+ # @param block [ Proc ] a block containing the context definition to be
27
+ # evaluated
20
28
  #
21
29
  # @return [ ContextSpook::Generator::Context ] the context object generated
22
- # from the file contents
23
- def self.generate_context(filename = nil, &block)
30
+ # from the file contents or block
31
+ #
32
+ # @raise [ ArgumentError ] if neither a filename nor a block is provided
33
+ # @raise [ ArgumentError ] if both a filename and a block are provided
34
+ def self.generate_context(filename = nil, verbose: false, &block)
24
35
  filename.present? ^ block or
25
36
  raise ArgumentError, 'need either a filename or a &block argument'
26
37
  generator = if filename
27
- Generator.send(:new).send(:parse, File.read(filename))
38
+ Generator.send(:new, verbose:).send(:parse, File.read(filename))
28
39
  else
29
- Generator.send(:new, &block)
40
+ Generator.send(:new, verbose:, &block)
30
41
  end
31
42
  generator.output_context_size
32
43
  generator.context
@@ -39,11 +50,15 @@ module ContextSpook
39
50
  class Generator
40
51
  private_class_method :new
41
52
 
42
- # The initialize method sets up the object by evaluating the provided block in the object's context.
53
+ # The initialize method sets up the object by evaluating the provided block
54
+ # in the object's context.
43
55
  #
44
- # @param block [ Proc ] A block of code to be evaluated within the object's context.
56
+ # @param verbose [ TrueClass, FalseClass ] flag to enable verbose
57
+ # output during processing, defaults to lfalse.
58
+ # @param block [ Proc ] a block of code to be evaluated within the object's context
45
59
  # If no block is given, the method does nothing.
46
- def initialize(&block)
60
+ def initialize(verbose: false, &block)
61
+ @verbose = verbose
47
62
  block and instance_eval(&block)
48
63
  end
49
64
 
@@ -72,7 +87,9 @@ module ContextSpook
72
87
  json_content_size = Tins::Unit.format(
73
88
  context_size, format: '%.2f %U', unit: ?b, prefix: 1024
74
89
  )
75
- STDERR.puts "Built #{json_content_size} of JSON context in total."
90
+ if @verbose
91
+ STDERR.puts "Built #{json_content_size} of JSON context in total."
92
+ end
76
93
  end
77
94
 
78
95
  # The Context class represents and manages project context data, providing
@@ -156,10 +173,14 @@ module ContextSpook
156
173
  file_size = Tins::Unit.format(
157
174
  File.size(filename), format: '%.2f %U', unit: ?b, prefix: 1024
158
175
  )
159
- STDERR.puts "Read #{filename.inspect} as JSON (%s) for context." % file_size
176
+ if @verbose
177
+ STDERR.puts "Read #{filename.inspect} as JSON (%s) for context." % file_size
178
+ end
160
179
  JSON.load_file(filename)
161
180
  rescue Errno::ENOENT => e
162
- STDERR.puts color(208) { "Reading #{filename.inspect} as JSON caused #{e.class}: #{e}" }
181
+ if @verbose
182
+ STDERR.puts color(208) { "Reading #{filename.inspect} as JSON caused #{e.class}: #{e}" }
183
+ end
163
184
  nil
164
185
  end
165
186
 
@@ -193,10 +214,14 @@ module ContextSpook
193
214
  file_size = Tins::Unit.format(
194
215
  content.size, format: '%.2f %U', unit: ?b, prefix: 1024
195
216
  )
196
- STDERR.puts "Read #{filename.inspect} (%s) for context." % file_size
217
+ if @verbose
218
+ STDERR.puts "Read #{filename.inspect} (%s) for context." % file_size
219
+ end
197
220
  nil
198
221
  rescue Errno::ENOENT => e
199
- STDERR.puts color(208) { "Reading #{filename.inspect} caused #{e.class}: #{e}" }
222
+ if @verbose
223
+ STDERR.puts color(208) { "Reading #{filename.inspect} caused #{e.class}: #{e}" }
224
+ end
200
225
  end
201
226
 
202
227
  # The commands method sets up a DSL accessor for provided command outputs.
@@ -219,7 +244,11 @@ module ContextSpook
219
244
  output = `#{shell_command}`
220
245
  exit_code = $?&.exitstatus.to_i
221
246
  if exit_code != 0
222
- STDERR.puts color(208) { "Executing #{shell_command.inspect} resulted in exit code #{exit_code}." }
247
+ if @verbose
248
+ STDERR.puts color(208) {
249
+ "Executing #{shell_command.inspect} resulted in exit code #{exit_code}."
250
+ }
251
+ end
223
252
  end
224
253
  commands[shell_command] = {
225
254
  namespace: scope_top,
@@ -231,7 +260,9 @@ module ContextSpook
231
260
  output_size = Tins::Unit.format(
232
261
  output.size, format: '%.2f %U', unit: ?b, prefix: 1024
233
262
  )
234
- STDERR.puts "Executed #{shell_command.inspect} with output (%s) for context." % output_size
263
+ if @verbose
264
+ STDERR.puts "Executed #{shell_command.inspect} with output (%s) for context." % output_size
265
+ end
235
266
  nil
236
267
  end
237
268
 
@@ -1,6 +1,6 @@
1
1
  module ContextSpook
2
2
  # ContextSpook version
3
- VERSION = '0.4.0'
3
+ VERSION = '0.5.0'
4
4
  VERSION_ARRAY = VERSION.split('.').map(&:to_i) # :nodoc:
5
5
  VERSION_MAJOR = VERSION_ARRAY[0] # :nodoc:
6
6
  VERSION_MINOR = VERSION_ARRAY[1] # :nodoc:
@@ -64,7 +64,7 @@ describe ContextSpook::Generator do
64
64
  command = context.commands['tree']
65
65
  expect(command).to be_present
66
66
  expect(command[:working_directory]).to eq Dir.pwd
67
- expect(command[:exit_code]).to be_present
67
+ expect(command[:exit_code]).not_to be_nil
68
68
  if command[:exit_code] == 0
69
69
  expect(command[:output]).to be_present
70
70
  else
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: context_spook
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.4.0
4
+ version: 0.5.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Florian Frank
@@ -15,14 +15,14 @@ dependencies:
15
15
  requirements:
16
16
  - - "~>"
17
17
  - !ruby/object:Gem::Version
18
- version: '2.2'
18
+ version: '2.8'
19
19
  type: :development
20
20
  prerelease: false
21
21
  version_requirements: !ruby/object:Gem::Requirement
22
22
  requirements:
23
23
  - - "~>"
24
24
  - !ruby/object:Gem::Version
25
- version: '2.2'
25
+ version: '2.8'
26
26
  - !ruby/object:Gem::Dependency
27
27
  name: all_images
28
28
  requirement: !ruby/object:Gem::Requirement
@@ -197,7 +197,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
197
197
  - !ruby/object:Gem::Version
198
198
  version: '0'
199
199
  requirements: []
200
- rubygems_version: 3.6.9
200
+ rubygems_version: 3.7.2
201
201
  specification_version: 4
202
202
  summary: context_spook collects project context for AI
203
203
  test_files: