utils 0.69.0 → 0.71.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 +4 -4
- data/Rakefile +1 -0
- data/bin/code_comment +141 -66
- data/lib/utils/version.rb +1 -1
- data/utils.gemspec +4 -3
- metadata +17 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: fb43a2fb980621c39c8dd83850e3b7752d3b8b2697d169d155ee2d541e9d4649
|
4
|
+
data.tar.gz: b804d7973f33d5ce1a8904d96d9b11b7e1560f73fd18facd6e0d1011de95b8a8
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 6214647c846b302c6ae3a02f4c58dd1520a58e5d61f6f7b9a5060d90d16c8663eae861ae866c43f5e70c01e3794a8376efccdd942e282efeaa3e130ee83d418b
|
7
|
+
data.tar.gz: 1a1e7c14221af1f4a72d0c94fa81915fd512378e62bd8981299e4ab697fb5a664c293387a96d368322ca75da30ac3f437dfb215c7a3bd45496100ae7f41ce602
|
data/Rakefile
CHANGED
data/bin/code_comment
CHANGED
@@ -32,6 +32,7 @@
|
|
32
32
|
require 'ollama'
|
33
33
|
include Ollama
|
34
34
|
require 'utils'
|
35
|
+
require 'context_spook'
|
35
36
|
|
36
37
|
META_METHOD = /(
|
37
38
|
(class_)? # Optional "class_" prefix
|
@@ -54,24 +55,18 @@ META_METHOD = /(
|
|
54
55
|
)? # Optional variant
|
55
56
|
)\s+:/x
|
56
57
|
|
57
|
-
|
58
|
-
#
|
59
|
-
# This method retrieves the source code of a method by analyzing the file
|
60
|
-
# location and line number provided. It attempts to identify the method
|
61
|
-
# definition by examining the surrounding context, including handling
|
62
|
-
# private and protected method declarations.
|
63
|
-
#
|
64
|
-
# @param filename_linenumber [ Object ] an object that responds to #source_location
|
65
|
-
# and provides filename and line number information
|
66
|
-
#
|
67
|
-
# @return [ String ] the source code of the method definition, or an empty string
|
68
|
-
# if the method cannot be determined
|
69
|
-
def fetch_method(filename_linenumber)
|
58
|
+
def fetch_construct(filename_linenumber)
|
70
59
|
result = ''
|
71
60
|
source_location = filename_linenumber.source_location
|
72
61
|
lf = Tins::LinesFile.for_filename(source_location.filename, source_location.linenumber)
|
62
|
+
if /^(?:\s*)(class|module)/ =~ lf.line
|
63
|
+
return lf.line, $1.to_sym
|
64
|
+
end
|
65
|
+
if /^(?:\s*)(?:[A-Z]\w*)\s*=\s*(Class|Module)\.new/ =~ lf.line
|
66
|
+
return lf.line, $1.downcase.to_sym
|
67
|
+
end
|
73
68
|
if lf.line =~ META_METHOD
|
74
|
-
return lf.line
|
69
|
+
return lf.line, :method
|
75
70
|
end
|
76
71
|
if spaces = lf.match_backward(/^(\s*?)(\S.*?\s+)?def\s+/)&.first
|
77
72
|
line_number_begin = lf.line_number
|
@@ -82,68 +77,148 @@ def fetch_method(filename_linenumber)
|
|
82
77
|
result << lf.line
|
83
78
|
end
|
84
79
|
end
|
85
|
-
result
|
80
|
+
return result, :method
|
86
81
|
end
|
87
82
|
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
#
|
83
|
+
def build_method_prompt(construct_type, construct, context)
|
84
|
+
default_prompt = <<~EOT
|
85
|
+
Look at this code to document it:
|
86
|
+
|
87
|
+
%{context}
|
88
|
+
|
89
|
+
Here's an example for how you should document a %{construct_type}.
|
90
|
+
|
91
|
+
# The foo %{construct_type} computes the bar result by processing…
|
92
|
+
# then it returns the result.
|
93
|
+
#
|
94
|
+
# @param first [ String ] the foo string
|
95
|
+
# @param second [ Integer ] the number of bars lengthy detailed mutltiline
|
96
|
+
# detailed explanation including a newline.
|
97
|
+
# @param third [ TrueClass, FalseClass ]
|
98
|
+
#
|
99
|
+
# @yield [ a, b ]
|
100
|
+
#
|
101
|
+
# @raise [ ArgumentError ] if block argument wasn't provided
|
102
|
+
# @raise [ ArgumentError ] if second parameter was too small.
|
103
|
+
#
|
104
|
+
# @return [ ProcessResult ]
|
105
|
+
|
106
|
+
And this is the %{construct_type} you should document:
|
107
|
+
|
108
|
+
%{construct}
|
109
|
+
|
110
|
+
Output a YARD comment for this %{construct_type}:
|
111
|
+
|
112
|
+
Format requirements:
|
113
|
+
|
114
|
+
1. Focus on providing a description of the %{construct_type}'s purpose
|
115
|
+
without including any code snippets.
|
116
|
+
2. You should omit the @raise if you are not sure.
|
117
|
+
3. Never use `, `ruby, ```, ```ruby in your response.
|
118
|
+
4. Never add any other remarks or explanation to your response.
|
119
|
+
5. Start each line of your comment with a single # character.
|
120
|
+
EOT
|
121
|
+
$config.read('method-prompt.txt', default: default_prompt) % {
|
122
|
+
construct_type:, construct:, context:,
|
123
|
+
}
|
124
|
+
end
|
97
125
|
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
EOT
|
104
|
-
system = config.read('system.txt', default: default_system)
|
126
|
+
def build_class_module_prompt(construct_type, construct, context)
|
127
|
+
default_prompt = <<~EOT
|
128
|
+
Look at this code to document it:
|
129
|
+
|
130
|
+
%{context}
|
105
131
|
|
106
|
-
|
107
|
-
default_prompt = <<EOT
|
108
|
-
Look at this code to document it:
|
132
|
+
Here's an example for how you should document a %{construct_type}.
|
109
133
|
|
110
|
-
%{
|
134
|
+
# A brief description of what this %{construct_type} does.
|
135
|
+
#
|
136
|
+
# @example
|
137
|
+
# MyClass.new do |obj|
|
138
|
+
# obj.method
|
139
|
+
# end
|
111
140
|
|
112
|
-
|
141
|
+
And this is the %{construct_type} you should document:
|
113
142
|
|
114
|
-
|
115
|
-
# then it returns the result.
|
116
|
-
#
|
117
|
-
# @param first [ String ] the foo string
|
118
|
-
# @param second [ Integer ] the number of bars lengthy detailed mutltiline
|
119
|
-
# detailed explanation including a newline.
|
120
|
-
# @param third [ TrueClass, FalseClass ]
|
121
|
-
#
|
122
|
-
# @yield [ a, b ]
|
123
|
-
#
|
124
|
-
# @raise [ ArgumentError ] if block argument wasn't provided
|
125
|
-
# @raise [ ArgumentError ] if second parameter was too small.
|
126
|
-
#
|
127
|
-
# @return [ ProcessResult ]
|
143
|
+
%{construct}
|
128
144
|
|
129
|
-
|
145
|
+
Output a YARD comment for this %{construct_type}:
|
130
146
|
|
131
|
-
|
147
|
+
Format requirements:
|
132
148
|
|
133
|
-
|
149
|
+
1. Focus on providing a description of the %{construct_type}'s purpose
|
150
|
+
without including any code snippets.
|
151
|
+
2. Include @example tag if there are notable usage patterns for this
|
152
|
+
construct.
|
153
|
+
3. Never use `, `ruby, ```, ```ruby in your response.
|
154
|
+
4. Never add any other remarks or explanation to your response.
|
155
|
+
5. Start each line of your comment with a single # character.
|
156
|
+
EOT
|
157
|
+
$config.read('class-module-prompt.txt', default: default_prompt) % {
|
158
|
+
construct_type:, construct:, context:,
|
159
|
+
}
|
160
|
+
end
|
134
161
|
|
135
|
-
|
162
|
+
def build_prompt(construct_type, construct, context)
|
163
|
+
case construct_type
|
164
|
+
when :method
|
165
|
+
build_method_prompt(construct_type, construct, context)
|
166
|
+
when :class, :module
|
167
|
+
build_class_module_prompt(construct_type, construct, context)
|
168
|
+
else
|
169
|
+
fail "unknown construct_type #{construct_type.inspect}"
|
170
|
+
end
|
171
|
+
end
|
136
172
|
|
137
|
-
|
138
|
-
|
139
|
-
|
140
|
-
|
141
|
-
|
142
|
-
|
173
|
+
filename_linenumber = ARGV.shift or fail "require file_name as second argument"
|
174
|
+
$config = Utils::ConfigDir.new('code_comment', env_var: 'XDG_CONFIG_HOME')
|
175
|
+
base_url = ENV['OLLAMA_URL'] || 'http://%s' % ENV.fetch('OLLAMA_HOST')
|
176
|
+
model = ENV.fetch('OLLAMA_MODEL', 'llama3.1')
|
177
|
+
construct, construct_type = fetch_construct(filename_linenumber)
|
178
|
+
construct_indent = construct[/\A( *)/, 1].size
|
179
|
+
context = if File.exist?(filename = 'contexts/code_comment.rb')
|
180
|
+
ContextSpook.generate_context(filename)
|
181
|
+
else
|
182
|
+
ContextSpook.generate_context do
|
183
|
+
context do
|
184
|
+
file "README.md", tags: %w[ documentation ]
|
185
|
+
|
186
|
+
# Auto-discover files using globs
|
187
|
+
%w[ lib spec test ].each do |dir|
|
188
|
+
namespace dir do
|
189
|
+
Dir["#{dir}/**/*.rb"].each do |filename|
|
190
|
+
file filename, tags: %w[ ruby ]
|
191
|
+
end
|
192
|
+
end
|
193
|
+
end
|
194
|
+
end
|
195
|
+
end
|
196
|
+
end.to_json
|
197
|
+
#call_sites = %x(cscope -L -3 "#{method_name}" $(find . -name '*.rb') | awk '{ print $1 ":" $3 }').lines.map(&:chomp).uniq
|
198
|
+
#methods = call_sites.map { fetch_method(_1) } * ?\n
|
199
|
+
|
200
|
+
default_system = <<~EOT
|
201
|
+
**Guidelines**
|
202
|
+
|
203
|
+
- When answering, assume an expert-level understanding of the programming
|
204
|
+
concepts involved.
|
205
|
+
|
206
|
+
- If given a **method**, provide high-quality YARD comments including:
|
207
|
+
* A brief description of its purpose
|
208
|
+
* Parameter documentation (@param)
|
209
|
+
* Return value documentation (@return)
|
210
|
+
* Exception documentation (@raise) when appropriate
|
211
|
+
* Avoid version information (@since)
|
212
|
+
|
213
|
+
- If given a **class or module**, provide high-quality YARD comments including:
|
214
|
+
* A brief description of its purpose
|
215
|
+
* Public interface documentation
|
216
|
+
* @example usage patterns when helpful
|
217
|
+
* Avoid version information (@since)
|
143
218
|
EOT
|
144
|
-
|
145
|
-
|
146
|
-
|
219
|
+
system = $config.read('system.txt', default: default_system)
|
220
|
+
|
221
|
+
prompt = build_prompt(construct_type, construct, context)
|
147
222
|
|
148
223
|
default_options = JSON(
|
149
224
|
#repeat_penalty: 1.8,
|
@@ -156,10 +231,10 @@ default_options = JSON(
|
|
156
231
|
min_p: 0.1,
|
157
232
|
)
|
158
233
|
|
159
|
-
client_config = Client::Config.load_from_json config + 'client.json'
|
234
|
+
client_config = Client::Config.load_from_json $config + 'client.json'
|
160
235
|
client_config.base_url = base_url
|
161
236
|
ollama = Client.configure_with(client_config)
|
162
|
-
options = JSON.parse(config.read('options.json', default: default_options))
|
237
|
+
options = JSON.parse($config.read('options.json', default: default_options))
|
163
238
|
|
164
239
|
if ENV['DEBUG'].to_i == 1
|
165
240
|
File.open('debug.log', ?w) do |log|
|
@@ -171,4 +246,4 @@ if ENV['DEBUG'].to_i == 1
|
|
171
246
|
end
|
172
247
|
|
173
248
|
response = ollama.generate(model:, system:, prompt:, options:, stream: false, think: false).response
|
174
|
-
puts response.gsub(/^/) { ' ' *
|
249
|
+
puts response.gsub(/^/) { ' ' * construct_indent }
|
data/lib/utils/version.rb
CHANGED
data/utils.gemspec
CHANGED
@@ -1,9 +1,9 @@
|
|
1
1
|
# -*- encoding: utf-8 -*-
|
2
|
-
# stub: utils 0.
|
2
|
+
# stub: utils 0.71.0 ruby lib
|
3
3
|
|
4
4
|
Gem::Specification.new do |s|
|
5
5
|
s.name = "utils".freeze
|
6
|
-
s.version = "0.
|
6
|
+
s.version = "0.71.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]
|
@@ -23,7 +23,7 @@ Gem::Specification.new do |s|
|
|
23
23
|
|
24
24
|
s.specification_version = 4
|
25
25
|
|
26
|
-
s.add_development_dependency(%q<gem_hadar>.freeze, ["~>
|
26
|
+
s.add_development_dependency(%q<gem_hadar>.freeze, ["~> 2.0".freeze])
|
27
27
|
s.add_development_dependency(%q<test-unit>.freeze, [">= 0".freeze])
|
28
28
|
s.add_runtime_dependency(%q<unix_socks>.freeze, [">= 0".freeze])
|
29
29
|
s.add_runtime_dependency(%q<webrick>.freeze, [">= 0".freeze])
|
@@ -37,6 +37,7 @@ Gem::Specification.new do |s|
|
|
37
37
|
s.add_runtime_dependency(%q<ollama-ruby>.freeze, ["~> 1.5.0".freeze])
|
38
38
|
s.add_runtime_dependency(%q<kramdown-ansi>.freeze, ["~> 0.0.1".freeze])
|
39
39
|
s.add_runtime_dependency(%q<figlet>.freeze, ["~> 1.0".freeze])
|
40
|
+
s.add_runtime_dependency(%q<context_spook>.freeze, ["~> 0.2".freeze])
|
40
41
|
s.add_runtime_dependency(%q<simplecov>.freeze, [">= 0".freeze])
|
41
42
|
s.add_runtime_dependency(%q<debug>.freeze, [">= 0".freeze])
|
42
43
|
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: utils
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.71.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: '
|
18
|
+
version: '2.0'
|
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: '
|
25
|
+
version: '2.0'
|
26
26
|
- !ruby/object:Gem::Dependency
|
27
27
|
name: test-unit
|
28
28
|
requirement: !ruby/object:Gem::Requirement
|
@@ -205,6 +205,20 @@ dependencies:
|
|
205
205
|
- - "~>"
|
206
206
|
- !ruby/object:Gem::Version
|
207
207
|
version: '1.0'
|
208
|
+
- !ruby/object:Gem::Dependency
|
209
|
+
name: context_spook
|
210
|
+
requirement: !ruby/object:Gem::Requirement
|
211
|
+
requirements:
|
212
|
+
- - "~>"
|
213
|
+
- !ruby/object:Gem::Version
|
214
|
+
version: '0.2'
|
215
|
+
type: :runtime
|
216
|
+
prerelease: false
|
217
|
+
version_requirements: !ruby/object:Gem::Requirement
|
218
|
+
requirements:
|
219
|
+
- - "~>"
|
220
|
+
- !ruby/object:Gem::Version
|
221
|
+
version: '0.2'
|
208
222
|
- !ruby/object:Gem::Dependency
|
209
223
|
name: simplecov
|
210
224
|
requirement: !ruby/object:Gem::Requirement
|