context_spook 0.5.0 → 0.6.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: bf46500652e697db299ccdfe21d5dd4c02953b699ca528b21810f87348eddceb
4
- data.tar.gz: ad41e6c9f6141ba5303c845aaf26c2d141125201d82575834a62efc05c2ae7b8
3
+ metadata.gz: 58670ead7c97c0681f39da47670f4afeb1ac08d1dc3ab8ddcb740fa2bf679a00
4
+ data.tar.gz: 48db4e54b8a5bbdfe2dcd3e58196d0f42801ada41668d4e43338adb68a9acd82
5
5
  SHA512:
6
- metadata.gz: edab814b82519dc36f9bb01c4e59dfb372aad6c2e1fa0d8ef7f487a288281ad6bf9bf1474d09a7ff7b818c1a6140ef08c0ba464b986e9bf56a34bd2720f9e778
7
- data.tar.gz: 052e05ca7fc2825a75b43e1b9a8585344f9d4e8a6a805e3a5d826680d81bfed723d4359db7083d6451ce4afa6e35e82688a979dae0fcd0dcde401784d373b2de
6
+ metadata.gz: c6f4d3fc5143082767f5bd361575a130d37710eeeb36965a2d5cb578ddcea5716047b17f6220d4a2a82ad857685d58dae7ae77e53bb355f1c7e54807b941b0d8
7
+ data.tar.gz: e50fe54b405153348f1936023c81330b67bfe0f7dc620cf9d85cb929cb7558383c6a2ec65b37e4502a7fd5608ec8028935f56e229a4f9e0c4734948ce3176f77
data/.contexts/project.rb CHANGED
@@ -45,5 +45,9 @@ context do
45
45
 
46
46
  meta nixda_json: json('nixda_json.json')
47
47
 
48
+ meta hey_world: yaml('hey_world.yaml')
49
+
50
+ meta nixda_yaml: yaml('nixda_yaml.yaml')
51
+
48
52
  meta code_coverage: json('coverage/coverage_context.json')
49
53
  end
data/Rakefile CHANGED
@@ -36,6 +36,7 @@ GemHadar do
36
36
  dependency 'term-ansicolor', '~> 1.11'
37
37
  dependency 'mize', '~> 0.6'
38
38
  dependency 'mime-types', '~> 3.0'
39
+ dependency 'yaml', '~> 0.4'
39
40
  development_dependency 'all_images', '~> 0.6'
40
41
  development_dependency 'rspec', '~> 3.2'
41
42
  development_dependency 'debug'
@@ -1,9 +1,9 @@
1
1
  # -*- encoding: utf-8 -*-
2
- # stub: context_spook 0.5.0 ruby lib
2
+ # stub: context_spook 0.6.1 ruby lib
3
3
 
4
4
  Gem::Specification.new do |s|
5
5
  s.name = "context_spook".freeze
6
- s.version = "0.5.0".freeze
6
+ s.version = "0.6.1".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]
@@ -13,7 +13,7 @@ Gem::Specification.new do |s|
13
13
  s.email = "flori@ping.de".freeze
14
14
  s.executables = ["context_spook".freeze]
15
15
  s.extra_rdoc_files = ["README.md".freeze, "lib/context_spook.rb".freeze, "lib/context_spook/generator.rb".freeze, "lib/context_spook/version.rb".freeze]
16
- s.files = [".contexts/project.rb".freeze, "Gemfile".freeze, "LICENSE".freeze, "README.md".freeze, "Rakefile".freeze, "bin/context_spook".freeze, "context_spook.gemspec".freeze, "hello_world.json".freeze, "lib/context_spook.rb".freeze, "lib/context_spook/generator.rb".freeze, "lib/context_spook/version.rb".freeze, "spec/context_spook/generator_spec.rb".freeze, "spec/spec_helper.rb".freeze]
16
+ s.files = [".contexts/project.rb".freeze, "Gemfile".freeze, "LICENSE".freeze, "README.md".freeze, "Rakefile".freeze, "bin/context_spook".freeze, "context_spook.gemspec".freeze, "hello_world.json".freeze, "hey_world.yaml".freeze, "lib/context_spook.rb".freeze, "lib/context_spook/generator.rb".freeze, "lib/context_spook/version.rb".freeze, "spec/context_spook/generator_spec.rb".freeze, "spec/spec_helper.rb".freeze]
17
17
  s.homepage = "https://github.com/flori/context_spook".freeze
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]
@@ -34,4 +34,5 @@ Gem::Specification.new do |s|
34
34
  s.add_runtime_dependency(%q<term-ansicolor>.freeze, ["~> 1.11".freeze])
35
35
  s.add_runtime_dependency(%q<mize>.freeze, ["~> 0.6".freeze])
36
36
  s.add_runtime_dependency(%q<mime-types>.freeze, ["~> 3.0".freeze])
37
+ s.add_runtime_dependency(%q<yaml>.freeze, ["~> 0.4".freeze])
37
38
  end
data/hey_world.yaml ADDED
@@ -0,0 +1,2 @@
1
+ ---
2
+ hey: world
@@ -3,12 +3,37 @@ require 'term/ansicolor'
3
3
  require 'json'
4
4
  require 'mize'
5
5
  require 'mime-types'
6
+ require 'yaml'
6
7
 
7
8
  # The ContextSpook module serves as a namespace container for collecting and
8
9
  # organizing project information for AI assistance.
9
10
  module ContextSpook
10
11
  include DSLKit::Interpreter
11
12
 
13
+ # The VerbosePuts module provides a conditional output mechanism for
14
+ # displaying status or debug messages.
15
+ #
16
+ # This module includes a method that outputs messages to standard error only
17
+ # when a verbose flag is enabled. It is designed to be included in classes
18
+ # that need to conditionally emit verbose logging information during
19
+ # processing.
20
+ module VerbosePuts
21
+ # The verbose_puts method outputs the given arguments to standard error
22
+ # only if verbose mode is enabled.
23
+ #
24
+ # This method serves as a conditional output mechanism, allowing debug or
25
+ # status messages to be displayed based on the verbosity setting of the
26
+ # object.
27
+ #
28
+ # @param a [ Array ] the arguments to be printed to standard error
29
+ #
30
+ # @return [ nil ] always returns nil after attempting to output
31
+ def verbose_puts(*a)
32
+ @verbose or return
33
+ STDERR.puts(a)
34
+ end
35
+ end
36
+
12
37
  # The generate_context method processes a context definition file or block
13
38
  # and returns the resulting context object.
14
39
  #
@@ -32,10 +57,11 @@ module ContextSpook
32
57
  # @raise [ ArgumentError ] if neither a filename nor a block is provided
33
58
  # @raise [ ArgumentError ] if both a filename and a block are provided
34
59
  def self.generate_context(filename = nil, verbose: false, &block)
60
+ verbose = !!verbose
35
61
  filename.present? ^ block or
36
62
  raise ArgumentError, 'need either a filename or a &block argument'
37
63
  generator = if filename
38
- Generator.send(:new, verbose:).send(:parse, File.read(filename))
64
+ Generator.send(:new, verbose:).send(:parse, File.read(filename))
39
65
  else
40
66
  Generator.send(:new, verbose:, &block)
41
67
  end
@@ -48,6 +74,8 @@ module ContextSpook
48
74
  # project metadata, file contents, command outputs, and variables for AI
49
75
  # assistance.
50
76
  class Generator
77
+ include VerbosePuts
78
+
51
79
  private_class_method :new
52
80
 
53
81
  # The initialize method sets up the object by evaluating the provided block
@@ -58,7 +86,7 @@ module ContextSpook
58
86
  # @param block [ Proc ] a block of code to be evaluated within the object's context
59
87
  # If no block is given, the method does nothing.
60
88
  def initialize(verbose: false, &block)
61
- @verbose = verbose
89
+ @verbose = !!verbose
62
90
  block and instance_eval(&block)
63
91
  end
64
92
 
@@ -70,7 +98,7 @@ module ContextSpook
70
98
  def context(&block)
71
99
  if block
72
100
  @context and raise ArgumentError, "only one context allowed"
73
- @context = Context.new(&block)
101
+ @context = Context.new(verbose: @verbose, &block)
74
102
  else
75
103
  @context
76
104
  end
@@ -87,24 +115,27 @@ module ContextSpook
87
115
  json_content_size = Tins::Unit.format(
88
116
  context_size, format: '%.2f %U', unit: ?b, prefix: 1024
89
117
  )
90
- if @verbose
91
- STDERR.puts "Built #{json_content_size} of JSON context in total."
92
- end
118
+ verbose_puts "Built #{json_content_size} of JSON context in total."
93
119
  end
94
120
 
95
121
  # The Context class represents and manages project context data, providing
96
122
  # structured storage for file contents, command outputs, variables, and
97
123
  # metadata that can be serialized to JSON for AI assistance.
98
124
  class Context
125
+ include VerbosePuts
99
126
  include Tins::Scope
100
127
  include Tins::DSLAccessor
101
128
  include Term::ANSIColor
102
129
 
103
- # The initialize method sets up the object by evaluating a block in the
104
- # object's context.
130
+ # The initialize method sets up the object by evaluating the provided block
131
+ # in the object's context.
105
132
  #
106
- # @param block [ Proc ] A block to be evaluated within the object's context.
107
- def initialize(&block)
133
+ # @param verbose [ TrueClass, FalseClass ] flag to enable verbose output
134
+ # during processing, defaults to false.
135
+ # @param block [ Proc ] a block of code to be evaluated within the object's context
136
+ # If no block is given, the method does nothing.
137
+ def initialize(verbose: false, &block)
138
+ @verbose = !!verbose
108
139
  block and instance_eval(&block)
109
140
  end
110
141
 
@@ -173,14 +204,34 @@ module ContextSpook
173
204
  file_size = Tins::Unit.format(
174
205
  File.size(filename), format: '%.2f %U', unit: ?b, prefix: 1024
175
206
  )
176
- if @verbose
177
- STDERR.puts "Read #{filename.inspect} as JSON (%s) for context." % file_size
178
- end
207
+ verbose_puts "Read #{filename.inspect} as JSON (%s) for context." % file_size
179
208
  JSON.load_file(filename)
180
- rescue Errno::ENOENT => e
181
- if @verbose
182
- STDERR.puts color(208) { "Reading #{filename.inspect} as JSON caused #{e.class}: #{e}" }
183
- end
209
+ rescue Errno::ENOENT, JSON::ParserError => e
210
+ verbose_puts color(208) { "Reading #{filename.inspect} as JSON caused #{e.class}: #{e}" }
211
+ nil
212
+ end
213
+
214
+ # The yaml method reads and parses a YAML file, returning the resulting
215
+ # data structure.
216
+ #
217
+ # This method attempts to load a YAML file from the specified path and
218
+ # returns the resulting Ruby data structure. It provides verbose output
219
+ # about the file size when successfully reading the file. In case of file
220
+ # not found errors or YAML syntax errors, it outputs a colored warning
221
+ # message to standard error and returns nil.
222
+ #
223
+ # @param filename [ String ] the path to the YAML file to be read and parsed
224
+ #
225
+ # @return [ Object, nil ] the parsed YAML data structure or nil if the
226
+ # file cannot be read
227
+ def yaml(filename)
228
+ file_size = Tins::Unit.format(
229
+ File.size(filename), format: '%.2f %U', unit: ?b, prefix: 1024
230
+ )
231
+ verbose_puts "Read #{filename.inspect} as YAML (%s) for context." % file_size
232
+ YAML.load_file(filename)
233
+ rescue Errno::ENOENT, Psych::SyntaxError => e
234
+ verbose_puts color(208) { "Reading #{filename.inspect} as YAML caused #{e.class}: #{e}" }
184
235
  nil
185
236
  end
186
237
 
@@ -214,14 +265,10 @@ module ContextSpook
214
265
  file_size = Tins::Unit.format(
215
266
  content.size, format: '%.2f %U', unit: ?b, prefix: 1024
216
267
  )
217
- if @verbose
218
- STDERR.puts "Read #{filename.inspect} (%s) for context." % file_size
219
- end
268
+ verbose_puts "Read #{filename.inspect} (%s) for context." % file_size
220
269
  nil
221
270
  rescue Errno::ENOENT => e
222
- if @verbose
223
- STDERR.puts color(208) { "Reading #{filename.inspect} caused #{e.class}: #{e}" }
224
- end
271
+ verbose_puts color(208) { "Reading #{filename.inspect} caused #{e.class}: #{e}" }
225
272
  end
226
273
 
227
274
  # The commands method sets up a DSL accessor for provided command outputs.
@@ -244,11 +291,9 @@ module ContextSpook
244
291
  output = `#{shell_command}`
245
292
  exit_code = $?&.exitstatus.to_i
246
293
  if exit_code != 0
247
- if @verbose
248
- STDERR.puts color(208) {
249
- "Executing #{shell_command.inspect} resulted in exit code #{exit_code}."
250
- }
251
- end
294
+ verbose_puts color(208) {
295
+ "Executing #{shell_command.inspect} resulted in exit code #{exit_code}."
296
+ }
252
297
  end
253
298
  commands[shell_command] = {
254
299
  namespace: scope_top,
@@ -260,9 +305,7 @@ module ContextSpook
260
305
  output_size = Tins::Unit.format(
261
306
  output.size, format: '%.2f %U', unit: ?b, prefix: 1024
262
307
  )
263
- if @verbose
264
- STDERR.puts "Executed #{shell_command.inspect} with output (%s) for context." % output_size
265
- end
308
+ verbose_puts "Executed #{shell_command.inspect} with output (%s) for context." % output_size
266
309
  nil
267
310
  end
268
311
 
@@ -1,6 +1,6 @@
1
1
  module ContextSpook
2
2
  # ContextSpook version
3
- VERSION = '0.5.0'
3
+ VERSION = '0.6.1'
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:
@@ -2,7 +2,7 @@ require 'spec_helper'
2
2
 
3
3
  describe ContextSpook::Generator do
4
4
  let :context do
5
- ContextSpook.generate_context('.contexts/project.rb')
5
+ ContextSpook.generate_context('.contexts/project.rb', verbose: true)
6
6
  end
7
7
 
8
8
  it 'context can be generated from block' do
@@ -76,5 +76,37 @@ describe ContextSpook::Generator do
76
76
  it 'can have metada' do
77
77
  expect(context.metadata[:ruby]).to eq RUBY_DESCRIPTION
78
78
  end
79
+
80
+ it 'can have json metadata' do
81
+ expect(context.metadata[:hello_world]).to eq("hello" => "world")
82
+ end
83
+
84
+ it 'can have yaml metadata' do
85
+ expect(context.metadata[:hey_world]).to eq("hey" => "world")
86
+ end
87
+
88
+ it 'handles missing json files gracefully' do
89
+ expect(context.json('nixda.json')).to be_nil
90
+ end
91
+
92
+ it 'handles invalid json content gracefully' do
93
+ Tempfile.create('invalid.json') do |f|
94
+ f.write('{ invalid json }')
95
+ f.close
96
+ expect(context.json(f.path)).to be_nil
97
+ end
98
+ end
99
+
100
+ it 'handles missing yaml files gracefully' do
101
+ expect(context.yaml('nixda.yaml')).to be_nil
102
+ end
103
+
104
+ it 'handles invalid yaml content gracefully' do
105
+ Tempfile.create('invalid.yaml') do |f|
106
+ f.write('invalid: [yaml')
107
+ f.close
108
+ expect(context.yaml(f.path)).to be_nil
109
+ end
110
+ end
79
111
  end
80
112
  end
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.5.0
4
+ version: 0.6.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Florian Frank
@@ -149,6 +149,20 @@ dependencies:
149
149
  - - "~>"
150
150
  - !ruby/object:Gem::Version
151
151
  version: '3.0'
152
+ - !ruby/object:Gem::Dependency
153
+ name: yaml
154
+ requirement: !ruby/object:Gem::Requirement
155
+ requirements:
156
+ - - "~>"
157
+ - !ruby/object:Gem::Version
158
+ version: '0.4'
159
+ type: :runtime
160
+ prerelease: false
161
+ version_requirements: !ruby/object:Gem::Requirement
162
+ requirements:
163
+ - - "~>"
164
+ - !ruby/object:Gem::Version
165
+ version: '0.4'
152
166
  description: |
153
167
  context_spook is a library that collects and organizes project
154
168
  information to help AI assistants understand codebases better.
@@ -170,6 +184,7 @@ files:
170
184
  - bin/context_spook
171
185
  - context_spook.gemspec
172
186
  - hello_world.json
187
+ - hey_world.yaml
173
188
  - lib/context_spook.rb
174
189
  - lib/context_spook/generator.rb
175
190
  - lib/context_spook/version.rb