Class: Kotoshu::Cli::CacheCommand

Inherits:
Thor
  • Object
show all
Defined in:
lib/kotoshu/cli/cache_command.rb

Overview

Cache management commands.

Provides CLI commands for managing the dictionary cache with automatic GitHub download support.

Examples:

List available languages

kotoshu cache list

Download a specific language

kotoshu cache download de

Show cache status

kotoshu cache status

Remove cached data

kotoshu cache purge

Instance Method Summary collapse

Instance Method Details

#download(language) ⇒ Object



110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
# File 'lib/kotoshu/cli/cache_command.rb', line 110

def download(language)
  cache = create_cache

  unless cache.available_languages.include?(language)
    puts "Error: Unknown language '#{language}'"
    puts
    puts "Available languages: #{cache.available_languages.join(', ')}"
    exit(1)
  end

  begin
    puts "Downloading #{language} dictionary from GitHub..."

    # Get dictionary (download if needed)
    dict_result = cache.get_dictionary(language, force_download: options[:force])

    if options[:force] || !dict_result[:metadata]['downloaded_at']
      puts "  ✓ Hunspell dictionary downloaded"
      puts "    Location: #{File.dirname(dict_result[:dic_path])}"
      puts "    Version: #{dict_result[:metadata]['version']}"
    else
      puts "  ✓ Using cached Hunspell dictionary"
      puts "    Location: #{File.dirname(dict_result[:dic_path])}"
      puts "    Cached: #{dict_result[:metadata]['downloaded_at']}"
    end

    # Try to download frequency data (may not be available yet)
    begin
      freq_result = cache.get_frequency_data(language, force_download: options[:force])
      if options[:force] || !freq_result[:metadata]['downloaded_at']
        puts "  ✓ Frequency data downloaded"
      else
        puts "  ✓ Using cached frequency data"
      end
    rescue StandardError => e
      # Frequency data may not be available yet - that's okay
      puts "  ⚠ Frequency data not available (#{e.message})"
    end

    puts
    puts "Dictionary for '#{language}' is ready to use!"
  rescue StandardError => e
    puts "Error downloading dictionary: #{e.message}"
    exit(1)
  end
end

#info(language) ⇒ Object



158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
# File 'lib/kotoshu/cli/cache_command.rb', line 158

def info(language)
  cache = create_cache

  unless cache.available_languages.include?(language)
    puts "Error: Unknown language '#{language}'"
    puts
    puts "Available languages: #{cache.available_languages.join(', ')}"
    exit(1)
  end

  info_data = cache.get_language_info(language)

  puts "Language: #{info_data[:name]}"
  puts "Code: #{language}"
  puts "Word count: #{info_data[:word_count]}"
  puts "License: #{info_data[:license]}"
  puts "Source: #{info_data[:source]}"
  puts "Cached: #{info_data[:downloaded] ? 'Yes' : 'No'}"

  # Show cached file info if available
  if info_data[:downloaded]
    lang_path = File.join(cache.cache_path, language)

    # Show spelling dict info
    spelling_path = File.join(lang_path, 'spelling', 'metadata.json')
    if File.exist?(spelling_path)
       = JSON.parse(File.read(spelling_path, encoding: 'UTF-8'))
      puts
      puts "Hunspell Dictionary:"
      puts "  Downloaded: #{['downloaded_at']}"
      puts "  Checksum: #{['checksum']}"
    end

    # Show frequency data info if available
    freq_path = File.join(lang_path, 'frequency', 'metadata.json')
    if File.exist?(freq_path)
       = JSON.parse(File.read(freq_path, encoding: 'UTF-8'))
      puts
      puts "Frequency Data:"
      puts "  Downloaded: #{['downloaded_at']}"
      puts "  Checksum: #{['checksum']}"
    end
  end
end

#listObject



35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
# File 'lib/kotoshu/cli/cache_command.rb', line 35

def list
  cache = create_cache
  status = cache.cache_status

  puts "Available languages:"
  puts

  # Show cached languages first
  unless status[:cached].empty?
    puts "Cached languages:"
    status[:cached].each do |info|
      print "  #{info[:code]}: #{info[:name]}"
      print " (#{info[:word_count]} words)" if options[:verbose]
      print " [#{info[:license]}]" if options[:verbose]
      puts ""
    end
    puts
  end

  # Show uncached languages
  unless status[:not_cached].empty?
    puts "Not cached (will be downloaded on first use):"
    status[:not_cached].each do |info|
      print "  #{info[:code]}: #{info[:name]}"
      print " (#{info[:word_count]} words)" if options[:verbose]
      puts
    end
  end
end

#purge(language = nil) ⇒ Object



205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
# File 'lib/kotoshu/cli/cache_command.rb', line 205

def purge(language = nil)
  cache = create_cache

  if language.nil?
    # Purge all
    unless options[:confirm]
      puts "This will remove all cached dictionaries and frequency data."
      print "Are you sure? [y/N] "
      return unless $stdin.gets.chomp =~ /^[Yy]/
    end

    count = cache.purge_all
    puts "Purged #{count} files from cache"
  else
    # Purge specific language
    unless cache.available_languages.include?(language)
      puts "Error: Unknown language '#{language}'"
      puts
      puts "Available languages: #{cache.available_languages.join(', ')}"
      exit(1)
    end

    lang_path = File.join(cache.cache_path, language)

    if File.exist?(lang_path)
      count = Dir.glob(File.join(lang_path, '**', '*')).count { |f| File.file?(f) }
      FileUtils.rm_rf(lang_path)
      puts "Purged #{language} cache (#{count} files)"
    else
      puts "No cached data for #{language}"
    end
  end
end

#statusObject



66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
# File 'lib/kotoshu/cli/cache_command.rb', line 66

def status
  cache = create_cache
  all_status = cache.cache_status

  total_languages = cache.available_languages.size
  cached_count = all_status[:cached].size
  not_cached_count = all_status[:not_cached].size

  puts "Cache Status:"
  puts "  Cache directory: #{cache.cache_path}"
  puts "  Total languages: #{total_languages}"
  puts "  Cached: #{cached_count}"
  puts "  Not cached: #{not_cached_count}"
  puts

  # Calculate cache size
  cache_size = Dir.glob(File.join(cache.cache_path, '**', '*'))
    .select { |f| File.file?(f) }
    .sum { |f| File.size(f) }

  puts "Cache size: #{format_bytes(cache_size)}"

  # Show oldest and newest cache entries
  all_cached = all_status[:cached].map do |info|
    lang_path = File.join(cache.cache_path, info[:code])
    spelling_meta = File.join(lang_path, 'spelling', 'metadata.json')
    if File.exist?(spelling_meta)
       = JSON.parse(File.read(spelling_meta, encoding: 'UTF-8'))
      [info[:code], Time.iso8601(['downloaded_at'])]
    end
  end.compact

  if all_cached.any?
    oldest = all_cached.min_by { |_, time| time }
    newest = all_cached.max_by { |_, time| time }

    puts
    puts "Oldest cache: #{oldest[0]} (#{oldest[1].strftime('%Y-%m-%d %H:%M')})"
    puts "Newest cache: #{newest[0]} (#{newest[1].strftime('%Y-%m-%d %H:%M')})"
  end
end

#validate(language) ⇒ Object



240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
# File 'lib/kotoshu/cli/cache_command.rb', line 240

def validate(language)
  cache = create_cache

  puts "Validating #{language}..."

  unless cache.available_languages.include?(language)
    puts "  ✗ Unknown language"
    return
  end

  # Check spelling
  spelling_path = File.join(cache.cache_path, language, 'spelling')
  spelling_meta = File.join(spelling_path, 'metadata.json')

  if File.exist?(spelling_meta)
     = JSON.parse(File.read(spelling_meta, encoding: 'UTF-8'))
    aff_file = File.join(spelling_path, 'index.aff')
    dic_file = File.join(spelling_path, 'index.dic')

    puts "  Spelling:"
    puts "    AFF file: #{File.exist?(aff_file) ? '' : ''}"
    puts "    DIC file: #{File.exist?(dic_file) ? '' : ''}"
    puts "    Metadata: ✓"
    puts "    Checksum: #{verify_checksum(dic_file, ['checksum']) ? '' : ''}" if ['checksum']
    puts "    Expired: #{expired?() ? 'Yes' : 'No'}"
  else
    puts "  Spelling: ✗ Not cached"
  end

  # Check frequency
  freq_path = File.join(cache.cache_path, language, 'frequency')
  freq_meta = File.join(freq_path, 'metadata.json')

  if File.exist?(freq_meta)
    puts "  Frequency: ✓"
  else
    puts "  Frequency: ✗ Not cached (optional)"
  end
end