Class: RubynCode::Skills::Catalog

Inherits:
Object
  • Object
show all
Defined in:
lib/rubyn_code/skills/catalog.rb

Constant Summary collapse

SKILL_GLOB =
'**/*.md'

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(skills_dirs) ⇒ Catalog

Returns a new instance of Catalog.



10
11
12
13
# File 'lib/rubyn_code/skills/catalog.rb', line 10

def initialize(skills_dirs)
  @skills_dirs = Array(skills_dirs)
  @index = nil
end

Instance Attribute Details

#skills_dirsObject (readonly)

Returns the value of attribute skills_dirs.



8
9
10
# File 'lib/rubyn_code/skills/catalog.rb', line 8

def skills_dirs
  @skills_dirs
end

Instance Method Details

#availableObject



22
23
24
25
# File 'lib/rubyn_code/skills/catalog.rb', line 22

def available
  build_index unless @index
  @index
end

#by_category(category) ⇒ Array<Hash>

Filter skills by category (subdirectory name). Skills are organized in subdirectories under each skills_dir.

Parameters:

  • category (String)

    category/directory name (e.g. “rails”, “testing”)

Returns:

  • (Array<Hash>)

    matching entries



57
58
59
60
61
62
# File 'lib/rubyn_code/skills/catalog.rb', line 57

def by_category(category)
  normalized = category.to_s.downcase
  available.select do |entry|
    path_category(entry[:path]).downcase == normalized
  end
end

#categoriesArray<String>

Return the list of unique categories derived from skill file paths.

Returns:

  • (Array<String>)

    sorted category names



67
68
69
70
71
72
# File 'lib/rubyn_code/skills/catalog.rb', line 67

def categories
  available.map { |e| path_category(e[:path]) }
           .reject(&:empty?)
           .uniq
           .sort
end

#descriptionsObject



15
16
17
18
19
20
# File 'lib/rubyn_code/skills/catalog.rb', line 15

def descriptions
  entries = available
  return '' if entries.empty?

  entries.map { |entry| "- /#{entry[:name]}: #{entry[:description]}" }.join("\n")
end

#find(name) ⇒ Object



31
32
33
34
# File 'lib/rubyn_code/skills/catalog.rb', line 31

def find(name)
  entry = available.find { |e| e[:name] == name.to_s }
  entry&.fetch(:path)
end

#listObject



27
28
29
# File 'lib/rubyn_code/skills/catalog.rb', line 27

def list
  available.map { |e| e[:name] }
end

#search(term) ⇒ Array<Hash>

Search skill content — matches against names, descriptions, and tags. Returns matching entries sorted by relevance (number of field matches).

Parameters:

  • term (String)

    search term (case-insensitive)

Returns:

  • (Array<Hash>)

    matching entries with :name, :description, :path, :relevance



41
42
43
44
45
46
47
48
49
50
# File 'lib/rubyn_code/skills/catalog.rb', line 41

def search(term)
  pattern = /#{Regexp.escape(term)}/i
  matches = available.filter_map do |entry|
    relevance = compute_relevance(entry, pattern)
    next if relevance.zero?

    entry.merge(relevance: relevance)
  end
  matches.sort_by { |e| -e[:relevance] }
end