documinty 0.2.0 → 0.3.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: bcd92454896ed0ffc0ab3f3e86a064d71a62e2da5430fa1b7920aecac854ce6b
4
- data.tar.gz: 740b56dd5581065c39d6cc09ff67c420867803d47c5420a5dfd4f8c682474616
3
+ metadata.gz: de1f0a6fded0793fb156e8111a074c44dda251836475980441b0c47576660147
4
+ data.tar.gz: 4fbb5cd7db1b97866eed50050754af3ac09998e7ff4486b5330adfd822fc1537
5
5
  SHA512:
6
- metadata.gz: 47a1af0117416167328b171df5a3869adf2847f928a4d76f9a6c4c0c99661650929a42ded453e970760d1cee05d9bb1c8d22eeec65e48725e393865a24d73351
7
- data.tar.gz: abdf028bb0da059b527b81198e4d7c00a6cc7fb71a4e6f31c5a97abecf059f69a4cb40216a8336377abc4650478f8270fc20bd96af8642defa8fc923b5d84aea
6
+ metadata.gz: f883d81566c6ab6013c5d6edbc77faf7b2661bb95ada107c1816787099ebc13e3dc92a246b36dbf1489620eed465e8da1c3e68896cd8d6a50224e93f6f9d4e7f
7
+ data.tar.gz: da024a6231ee1b7bbe131cf4393f5a20351ec7d8ae9e48655cd6ddfd9b8c89d3b0cf749af341970b666ff471704292ba79e904f974dbf4d5cceb67da54f00c98
data/LICENSE.txt CHANGED
@@ -1,6 +1,6 @@
1
1
  The MIT License (MIT)
2
2
 
3
- Copyright (c) 2025 TODO: Write your name
3
+ Copyright (c) 2025 Marcel Carrero Pedre
4
4
 
5
5
  Permission is hereby granted, free of charge, to any person obtaining a copy
6
6
  of this software and associated documentation files (the "Software"), to deal
data/README.md CHANGED
@@ -1,43 +1,129 @@
1
1
  # Documinty
2
2
 
3
- TODO: Delete this and the text below, and describe your gem
3
+ ![Alt text describing image](assets/logo.png)
4
+
5
+ **Documinty** (alias `dty`) is a lightweight CLI tool to help you document your Ruby codebase as you build features. It lets you:
6
+
7
+ - Create and manage **features**
8
+ - Tag files with a **node type**, **description**, and **methods**
9
+ - Query documentation by file or by feature
10
+ - Visualize which files belong to a feature (grouped by directory)
11
+ - Search for features by substring
12
+
13
+ Everything you record lives under a `.documinty/` folder in your project. You can version it alongside your code, making documentation part of your workflow.
4
14
 
5
- Welcome to your new gem! In this directory, you'll find the files you need to be able to package up your Ruby library into a gem. Put your Ruby code in the file `lib/documinty`. To experiment with that code, run `bin/console` for an interactive prompt.
6
15
 
7
16
  ## Installation
8
17
 
9
- TODO: Replace `UPDATE_WITH_YOUR_GEM_NAME_IMMEDIATELY_AFTER_RELEASE_TO_RUBYGEMS_ORG` with your gem name right after releasing it to RubyGems.org. Please do not do it earlier due to security reasons. Alternatively, replace this section with instructions to install your gem from git if you don't plan to release to RubyGems.org.
18
+ ### Prerequisites
19
+
20
+ - Ruby ≥ 3.1
21
+ - Bundler (optional, but recommended)
10
22
 
11
- Install the gem and add to the application's Gemfile by executing:
23
+ ### From RubyGems
12
24
 
13
25
  ```bash
14
- bundle add UPDATE_WITH_YOUR_GEM_NAME_IMMEDIATELY_AFTER_RELEASE_TO_RUBYGEMS_ORG
26
+ gem install documinty
27
+ # or, if you prefer the short alias:
28
+ # gem install dty
29
+
15
30
  ```
16
31
 
17
- If bundler is not being used to manage dependencies, install the gem by executing:
32
+ ### From Git(development version)
18
33
 
19
- ```bash
20
- gem install UPDATE_WITH_YOUR_GEM_NAME_IMMEDIATELY_AFTER_RELEASE_TO_RUBYGEMS_ORG
34
+ ```
35
+ git clone git@github.com:yourusername/documinty.git
36
+ cd documinty
37
+ ```
38
+
39
+ Build and install locally
40
+ ```
41
+ bundle install
42
+ bundle exec rake build
43
+ gem install pkg/documinty-<VERSION>.gem
21
44
  ```
22
45
 
23
46
  ## Usage
24
47
 
25
- TODO: Write usage instructions here
26
48
 
27
- ## Development
49
+ ### 1. Go into your existing codebase
50
+ ```
51
+ cd path/to/your-app
52
+ ```
28
53
 
29
- After checking out the repo, run `bin/setup` to install dependencies. Then, run `rake spec` to run the tests. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
54
+ ### 2. Initialize Documinty (creates .documinty/)
55
+ ```
56
+ dty init --codebase your-app
57
+ ```
58
+ ### 3. Create a feature called "user-auth"
59
+ ```
60
+ dty feat user-auth
61
+ ```
62
+ ### 4. Tag a file under "user-auth" as a controller, prompt for description & methods
63
+ ```
64
+ dty doc app/controllers/sessions_controller.rb -f user-auth -n controller
65
+
66
+ # • You’ll be prompted:
67
+ # Enter a brief description for this node⚙️:
68
+ # (e.g.) "Handles login/logout flows"
69
+ #
70
+ # Enter comma-separated methods for this node🛠️:
71
+ # (e.g.) :new, :create, :destroy
72
+ ```
73
+ ### 5. View documentation for that file
74
+ ```
75
+ dty show app/controllers/sessions_controller.rb
76
+ ```
77
+ ### 6. List all defined features
78
+ ```
79
+ dty features
80
+ ```
81
+ ### 7. Show all files under "user-auth"
82
+ ```
83
+ dty list_f user-auth
84
+ ```
85
+ ### 8. Show file structure under "user-auth"
86
+ ```
87
+ dty involved_f user-auth
88
+ ```
89
+ ### 9. Search for features that contain "user"
90
+ ```
91
+ dty search_f user
92
+ ```
30
93
 
31
- To install this gem onto your local machine, run `bundle exec rake install`. To release a new version, update the version number in `version.rb`, and then run `bundle exec rake release`, which will create a git tag for the version, push git commits and the created tag, and push the `.gem` file to [rubygems.org](https://rubygems.org).
94
+ ### Project layout
95
+ ```
96
+ .
97
+ ├── exe/
98
+ │ ├── documinty # primary executable stub
99
+ │ └── dty # short alias stub
100
+ ├── lib/
101
+ │ └── documinty/
102
+ │ ├── cli.rb # Thor CLI definitions
103
+ │ └── store.rb # YAML-backed storage logic
104
+ │ └── documinty.rb # loads version and CLI
105
+ │ └── documinty/version.rb
106
+ ├── .documinty/ # created once you run `dty init`
107
+ │ ├── config.yml
108
+ │ └── features/ # per-feature YAML files live here
109
+ ├── Rakefile # builds the gem
110
+ ├── documinty.gemspec # gemspec (metadata + dependencies)
111
+ ├── LICENSE.txt
112
+ └── README.md
113
+ ```
32
114
 
33
- ## Contributing
115
+ ### Contributing
116
+ 1 - Fork the repository
34
117
 
35
- Bug reports and pull requests are welcome on GitHub at https://github.com/[USERNAME]/documinty. This project is intended to be a safe, welcoming space for collaboration, and contributors are expected to adhere to the [code of conduct](https://github.com/[USERNAME]/documinty/blob/main/CODE_OF_CONDUCT.md).
118
+ 2 - Create a new branch (git checkout -b my-feature)
36
119
 
37
- ## License
120
+ 3 - Make your changes and add tests if applicable
38
121
 
39
- The gem is available as open source under the terms of the [MIT License](https://opensource.org/licenses/MIT).
122
+ 4 - Commit, push, and open a Pull Request
40
123
 
41
- ## Code of Conduct
124
+ 5 - We’ll review and merge!
42
125
 
43
- Everyone interacting in the Documinty project's codebases, issue trackers, chat rooms and mailing lists is expected to follow the [code of conduct](https://github.com/[USERNAME]/documinty/blob/main/CODE_OF_CONDUCT.md).
126
+ ### License
127
+ License
128
+ This project is licensed under the MIT License.
129
+ See LICENSE.txt for details.
data/exe/dty ADDED
@@ -0,0 +1,5 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require "rubygems"
4
+ require "documinty"
5
+ Documinty::CLI.start(ARGV)
data/lib/documinty/cli.rb CHANGED
@@ -4,6 +4,7 @@ require 'documinty/store'
4
4
 
5
5
  module Documinty
6
6
  class CLI < Thor
7
+ MAX_DESC_LENGTH = 80
7
8
  def self.exit_on_failure?
8
9
  true
9
10
  end
@@ -15,7 +16,7 @@ module Documinty
15
16
  end
16
17
 
17
18
  desc "feature NAME", "Create a new feature for tagging"
18
- def feature(name)
19
+ def feat(name)
19
20
  begin
20
21
  store.add_feature(name)
21
22
  say "✅ Created feature '#{name}'", :green
@@ -38,14 +39,23 @@ module Documinty
38
39
  desc "document FILE", "Tag FILE under an existing feature"
39
40
  option :feature, aliases: '-f', required: true, desc: 'Feature name to group under'
40
41
  option :node, aliases: '-n', required: true, desc: 'Node/type label'
41
- def document(path)
42
+ def doc(path)
42
43
  begin
44
+ description = ask("Enter a brief description for this node⚙️:")
45
+ methods_input = ask("Enter comma-separated methods for this node (or leave blank if none)🛠️:")
46
+ method_syms = methods_input
47
+ .split(",")
48
+ .map(&:strip)
49
+ .reject(&:empty?)
50
+ .map(&:to_sym)
51
+
43
52
  entry = store.add_entry(
44
- path: path,
45
- node: options[:node],
46
- feature: options[:feature],
47
- timestamp: Time.now.iso8601,
48
- description: options[:description] || ask("Enter a brief description for this node:")
53
+ path: path,
54
+ node: options[:node],
55
+ feature: options[:feature],
56
+ methods: method_syms,
57
+ timestamp: Time.now.iso8601,
58
+ description: description,
49
59
  )
50
60
  say "✅ Documented #{entry['path']} as #{entry['node']} under '#{entry['feature']}'", :green
51
61
  rescue Error => e
@@ -55,26 +65,81 @@ module Documinty
55
65
  end
56
66
 
57
67
  desc "show FILE", "Display documentation for FILE (node & feature)"
58
- def show_documented(path)
68
+ option :feature, aliases: '-f', desc: 'Only show documentation under this feature'
69
+ def show(path)
59
70
  entries = store.entries_for(path)
71
+
72
+ # If a specific feature is requested, filter to those entries
73
+ if options[:feature]
74
+ entries = entries.select { |e| Array(e['features'] || e['feature']).include?(options[:feature]) }
75
+ end
76
+
60
77
  if entries.empty?
61
- say "❌ No documentation found for '#{path}'", :red
78
+ if options[:feature]
79
+ say "❌ No documentation found for '#{path}' under feature '#{options[:feature]}'", :red
80
+ else
81
+ say "❌ No documentation found for '#{path}'", :red
82
+ end
62
83
  exit(1)
63
84
  end
64
85
 
65
86
  entries.each do |e|
66
- say "File: #{e['path']}", :magenta
67
- say "Node type: #{e['node']}", :magenta
68
- say "Feature: #{e['feature']}", :magenta
69
- say "Description: #{e['description']}", :magenta unless e['description'].to_s.empty?
70
- say "Tagged at: #{e['timestamp']}", :magenta
71
- say "-" * 40, :magenta
87
+ label_color = :cyan
88
+ value_color = :magenta
89
+
90
+ # File
91
+ say(
92
+ set_color("File📄", label_color) +
93
+ ": " +
94
+ set_color(e['path'], value_color)
95
+ )
96
+
97
+ # Node type
98
+ say(
99
+ set_color("Node type⚙️", label_color) +
100
+ ": " +
101
+ set_color(e['node'], value_color)
102
+ )
103
+
104
+ # Features
105
+ say(
106
+ set_color("Features🏷️", label_color) +
107
+ ": " +
108
+ set_color(Array(e['features'] || e['feature']).join(", "), value_color)
109
+ )
110
+
111
+ # Description (only if present)
112
+ unless e['description'].to_s.empty?
113
+ say(
114
+ set_color("Description📝", label_color) +
115
+ ": " +
116
+ set_color(truncate(e['description']), value_color)
117
+ )
118
+ end
119
+
120
+ # Methods (only if present)
121
+ if e['methods'] && !e['methods'].empty?
122
+ say(
123
+ set_color("Methods🛠️", label_color) +
124
+ ": " +
125
+ set_color(Array(e['methods']).join(", "), value_color)
126
+ )
127
+ end
128
+
129
+ # Timestamp
130
+ say(
131
+ set_color("Tagged at⏰", label_color) +
132
+ ": " +
133
+ set_color(e['timestamp'], value_color)
134
+ )
135
+
136
+ say "-" * 40
72
137
  end
73
138
  end
74
139
 
75
140
  desc "untag FILE", "Remove FILE’s tag from an existing feature"
76
141
  option :feature, aliases: '-f', required: true, desc: "Feature name"
77
- def undocument(path)
142
+ def untag(path)
78
143
  begin
79
144
  removed = store.remove_entry(path: path, feature: options[:feature])
80
145
  removed.each do |e|
@@ -86,7 +151,7 @@ module Documinty
86
151
  end
87
152
  end
88
153
 
89
- desc "show-feature FEATURE", "List all files documented under FEATURE"
154
+ desc "show_feature FEATURE", "List all files documented under FEATURE"
90
155
  def show_feature(feature)
91
156
  begin
92
157
  entries = store.entries_for_feature(feature)
@@ -99,14 +164,22 @@ module Documinty
99
164
  say "No entries under '#{feature}'.", :red
100
165
  else
101
166
  say "Entries for '#{feature}':"
167
+ label_color = :cyan
168
+ value_color = :magenta
102
169
  entries.each do |e|
103
- say "• #{e['path']} (#{e['node']}) – #{e['description']}", :green
170
+
171
+
172
+ # File
173
+ say(
174
+ set_color("📄#{e['path']} | ", label_color) +
175
+ set_color("(#{e['node']}) – #{e['description']}", value_color)
176
+ )
104
177
  end
105
178
  end
106
179
  end
107
180
 
108
- desc "show_feature_involved FEATURE", "Display files under FEATURE grouped by directory"
109
- def show_feature_involved(feature)
181
+ desc "involved_f FEATURE", "Display files under FEATURE grouped by directory"
182
+ def involved_f(feature)
110
183
  begin
111
184
  entries = store.entries_for_feature(feature)
112
185
  rescue Error => e
@@ -131,13 +204,86 @@ module Documinty
131
204
 
132
205
  entries_in_dir.each do |e|
133
206
  # Print each filename line with a file emoji, indented, in green
134
- say " 📄 #{File.basename(e['path'])}", :green
207
+ say " 📄 #{File.basename(e['path'])}", :green
208
+ end
209
+ end
210
+ end
211
+
212
+
213
+ desc "search_f QUERY", "List all features containing QUERY"
214
+ def search_f(query)
215
+ matches = store.features.select { |f| f.include?(query) }
216
+ if matches.empty?
217
+ say "❌ No features match '#{query}'", :red
218
+ else
219
+ say "Matching features:", :cyan
220
+ matches.each { |f| say "• #{f}", :green }
221
+ end
222
+ end
223
+
224
+ desc "add_methods FILE", "Prompt for and add methods to an existing documented file"
225
+ option :feature, aliases: '-f', required: true, desc: "Feature name"
226
+ def add_methods(path)
227
+ # Ask interactively for comma-separated methods
228
+ methods_input = ask("Enter comma-separated methods to add to this node🛠️:")
229
+ method_syms = methods_input
230
+ .split(",")
231
+ .map(&:strip)
232
+ .reject(&:empty?)
233
+ .map(&:to_sym)
234
+
235
+ begin
236
+ entry = store.add_methods(
237
+ path: path,
238
+ feature: options[:feature],
239
+ new_methods: method_syms
240
+ )
241
+ say "✅ Updated methods for #{entry['path']} under '#{entry['feature']}': #{Array(entry['methods']).join(', ')}", :green
242
+ rescue Error => e
243
+ say "❌ #{e.message}", :red
244
+ exit(1)
245
+ end
246
+ end
247
+
248
+ desc "describe FILE", "Display only the description for FILE"
249
+ option :feature, aliases: '-f', desc: "If provided, only show description under that feature"
250
+ def describe(path)
251
+ entries = store.entries_for(path)
252
+
253
+ # If a specific feature is requested, filter to those entries
254
+ if options[:feature]
255
+ entries = entries.select { |e| Array(e['features'] || e['feature']).include?(options[:feature]) }
256
+ end
257
+
258
+ if entries.empty?
259
+ if options[:feature]
260
+ say "❌ No description found for '#{path}' under feature '#{options[:feature]}'", :red
261
+ else
262
+ say "❌ No description found for '#{path}'", :red
263
+ end
264
+ exit(1)
265
+ end
266
+
267
+ entries.each do |e|
268
+ desc = e['description'].to_s.strip
269
+ if desc.empty?
270
+ say "ℹ️ No description provided for '#{path}' under '#{e['feature']}'", :yellow
271
+ else
272
+ say "📋 #{path}", :cyan
273
+ say "--→ #{desc}", :green
135
274
  end
136
275
  end
137
276
  end
138
277
 
139
278
  private
140
279
 
280
+
281
+ def truncate(text)
282
+ return "" unless text
283
+ return text if text.length <= MAX_DESC_LENGTH
284
+ text[0, MAX_DESC_LENGTH] + "(…)"
285
+ end
286
+
141
287
  def store
142
288
  @store ||= Store.new(Dir.pwd)
143
289
  end
@@ -43,7 +43,7 @@ module Documinty
43
43
 
44
44
  # ─── Entries API ──────────────────────────────────────────────────────────
45
45
  # Tag a file under a specific feature
46
- def add_entry(path:, node:, feature:, timestamp:, description: '')
46
+ def add_entry(path:, node:, feature:, methods: [], timestamp:, description: '')
47
47
  file = feature_file(feature)
48
48
  raise Error, "Feature '#{feature}' does not exist" unless File.exist?(file)
49
49
 
@@ -53,6 +53,7 @@ module Documinty
53
53
  'path' => path,
54
54
  'node' => node.to_s,
55
55
  'feature' => feature,
56
+ 'methods' => Array(methods).map(&:to_s),
56
57
  'description' => description.to_s.strip,
57
58
  'timestamp' => timestamp
58
59
  }
@@ -102,6 +103,33 @@ module Documinty
102
103
  data['entries'] || []
103
104
  end
104
105
 
106
+ # Add one or more methods to a documented file under a given feature
107
+ # @param path [String] relative file path
108
+ # @param feature [String] feature name (must already exist on that entry)
109
+ # @param new_methods [Array<Symbol>] list of symbols to add
110
+ # @return [Hash] the updated entry
111
+ def add_methods(path:, feature:, new_methods:)
112
+ file = feature_file(feature)
113
+ raise Error, "Feature '#{feature}' does not exist" unless File.exist?(file)
114
+
115
+ data = YAML.load_file(file) || {}
116
+ entries = data['entries'] || []
117
+
118
+ # Find the exact entry by path + feature
119
+ entry = entries.find { |e| e['path'] == path && e['feature'] == feature }
120
+ unless entry
121
+ raise Error, "No documentation found for '#{path}' under feature '#{feature}'"
122
+ end
123
+
124
+ # Merge existing methods (strings) with new ones, avoid duplicates
125
+ existing = Array(entry['methods']).map(&:to_s)
126
+ merged = (existing + new_methods.map(&:to_s)).uniq
127
+ entry['methods'] = merged
128
+
129
+ File.write(file, data.to_yaml)
130
+ entry
131
+ end
132
+
105
133
  private
106
134
 
107
135
  # Build the path to a feature’s YAML file
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Documinty
4
- VERSION = "0.2.0"
4
+ VERSION = "0.3.1"
5
5
  end
metadata CHANGED
@@ -1,13 +1,13 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: documinty
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.0
4
+ version: 0.3.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Marcel Carrero Pedre
8
8
  bindir: exe
9
9
  cert_chain: []
10
- date: 2025-05-31 00:00:00.000000000 Z
10
+ date: 2025-06-06 00:00:00.000000000 Z
11
11
  dependencies:
12
12
  - !ruby/object:Gem::Dependency
13
13
  name: thor
@@ -42,6 +42,7 @@ email:
42
42
  - marcel.pedre001@outlook.com
43
43
  executables:
44
44
  - documinty
45
+ - dty
45
46
  extensions: []
46
47
  extra_rdoc_files: []
47
48
  files:
@@ -50,17 +51,18 @@ files:
50
51
  - LICENSE.txt
51
52
  - README.md
52
53
  - exe/documinty
54
+ - exe/dty
53
55
  - lib/documinty.rb
54
56
  - lib/documinty/cli.rb
55
57
  - lib/documinty/store.rb
56
58
  - lib/documinty/version.rb
57
- homepage: https://github.com/yourusername/carreromarcel
59
+ homepage: https://github.com/BatouGlitch/documinty
58
60
  licenses:
59
61
  - MIT
60
62
  metadata:
61
- homepage_uri: https://github.com/yourusername/carreromarcel
62
- source_code_uri: https://github.com/yourusername/carreromarcel
63
- changelog_uri: https://github.com/yourusername/carreromarcel/blob/main/CHANGELOG.md
63
+ homepage_uri: https://github.com/BatouGlitch/documinty
64
+ source_code_uri: https://github.com/BatouGlitch/documinty
65
+ changelog_uri: https://github.com/BatouGlitch/documinty/blob/main/CHANGELOG.md
64
66
  rdoc_options: []
65
67
  require_paths:
66
68
  - lib