Class: Kotoshu::Configuration

Inherits:
Object
  • Object
show all
Defined in:
lib/kotoshu/configuration.rb,
lib/kotoshu/configuration/builder.rb,
lib/kotoshu/configuration/resolver.rb

Overview

Configuration for Kotoshu spell checker.

This class manages configuration options for spell checking, including dictionary settings, suggestion limits, and language options.

Configuration priority: CLI > ENV > Programmatic > Defaults

Examples:

Creating a configuration

config = Configuration.new
config.dictionary_path = "/usr/share/dict/words"
config.dictionary_type = :unix_words
config.max_suggestions = 15

Using a block

Configuration.new do |c|
  c.dictionary_path = "words.txt"
  c.language = "en-US"
end

Using environment variables

ENV['KOTOSHU_LANGUAGE'] = 'de'
config = Configuration.new
config.language  # => 'de'

Defined Under Namespace

Classes: Builder, Resolver

Constant Summary collapse

SCHEMA =

Configuration schema with ENV variable mappings.

Each key maps to a hash with:

  • :env - Environment variable name
  • :default - Default value (can be a proc for dynamic defaults)
  • :description - Human-readable description
  • :type - Expected type (for validation/conversion)
{
  dictionary_path: {
    env: "KOTOSHU_DICTIONARIES_PATH",
    default: nil,
    description: "Path to dictionary file",
    type: String
  },
  cache_path: {
    env: "KOTOSHU_CACHE_PATH",
    default: -> { default_cache_path },
    description: "Path to cache directory (~/.cache/kotoshu)",
    type: String
  },
  config_path: {
    env: "KOTOSHU_CONFIG_PATH",
    default: -> { default_config_path },
    description: "Path to user config directory (~/.config/kotoshu)",
    type: String
  },
  data_path: {
    env: "KOTOSHU_DATA_PATH",
    default: -> { default_data_path },
    description: "Path to data directory (~/.local/share/kotoshu)",
    type: String
  },
  dictionaries_url: {
    env: "KOTOSHU_DICTIONARIES_URL",
    default: "https://raw.githubusercontent.com/kotoshu/dictionaries/main",
    description: "Deprecated: use repos_base_url + dictionaries_pin via SourceRegistry",
    type: String
  },
  models_url: {
    env: "KOTOSHU_MODELS_URL",
    default: "https://github.com/kotoshu/models-fasttext-onnx/raw/main",
    description: "Deprecated: use repos_base_url + models_pin via SourceRegistry",
    type: String
  },
  repos_base_url: {
    env: "KOTOSHU_REPOS_BASE_URL",
    default: -> { Kotoshu::SourceRegistry::DEFAULT_BASE_URL },
    description: "GitHub raw root for all kotoshu content repos",
    type: String
  },
  dictionaries_pin: {
    env: "KOTOSHU_DICTIONARIES_PIN",
    default: "v1",
    description: "Branch/tag/commit pinned for kotoshu/dictionaries",
    type: String
  },
  frequency_pin: {
    env: "KOTOSHU_FREQUENCY_PIN",
    default: "main",
    description: "Branch/tag/commit pinned for kotoshu/frequency-list-kelly",
    type: String
  },
  models_pin: {
    env: "KOTOSHU_MODELS_PIN",
    default: "main",
    description: "Branch/tag/commit pinned for kotoshu/models-fasttext-onnx",
    type: String
  },
  auto_download: {
    env: "KOTOSHU_AUTO_DOWNLOAD",
    default: true,
    description: "Automatically download missing dictionaries",
    type: :boolean
  },
  cache_ttl: {
    env: "KOTOSHU_CACHE_TTL",
    default: 86_400, # 24 hours in seconds
    description: "Cache TTL in seconds",
    type: Integer
  },
  max_cache_size: {
    env: "KOTOSHU_MAX_CACHE_SIZE",
    default: 1_073_741_824, # 1GB
    description: "Maximum cache size in bytes",
    type: Integer
  },
  audit_max_bytes: {
    env: "KOTOSHU_AUDIT_MAX_BYTES",
    default: 10_485_760, # 10 MB
    description: "Audit log size threshold (bytes) that triggers rotation",
    type: Integer
  },
  audit_rotations: {
    env: "KOTOSHU_AUDIT_ROTATIONS",
    default: 5,
    description: "Number of historical audit log rotations to keep",
    type: Integer
  },
  dictionary_type: {
    env: "KOTOSHU_DICTIONARY_TYPE",
    default: :unix_words,
    description: "Dictionary type (:unix_words, :plain_text, :hunspell, :cspell, :custom)",
    type: Symbol
  },
  language: {
    env: "KOTOSHU_LANGUAGE",
    default: "en-US",
    description: "Language code (e.g., en-US, de-DE, ja-JP)",
    type: String
  },
  locale: {
    env: "KOTOSHU_LOCALE",
    default: nil,
    description: "Locale (e.g., en, en_US, de_DE)",
    type: String
  },
  max_suggestions: {
    env: "KOTOSHU_MAX_SUGGESTIONS",
    default: 10,
    description: "Maximum number of suggestions",
    type: Integer
  },
  case_sensitive: {
    env: "KOTOSHU_CASE_SENSITIVE",
    default: false,
    description: "Enable case-sensitive lookups",
    type: :boolean
  },
  verbose: {
    env: "KOTOSHU_VERBOSE",
    default: false,
    description: "Enable verbose output",
    type: :boolean
  },
  encoding: {
    env: "KOTOSHU_ENCODING",
    default: "UTF-8",
    description: "Character encoding",
    type: String
  },
  dictionaries_path: {
    env: "KOTOSHU_DICTIONARIES_PATH",
    default: nil,
    description: "Path to dictionaries directory (for grammar rules)",
    type: String
  },
  offline: {
    env: "KOTOSHU_OFFLINE",
    default: false,
    description: "Use only cached resources; never download",
    type: :boolean
  },
  resource_pin: {
    env: "KOTOSHU_RESOURCE_PIN",
    default: "main",
    description: "Branch/tag/commit pinned for resource downloads",
    type: String
  },
  default_language: {
    env: "KOTOSHU_DEFAULT_LANGUAGE",
    default: "en",
    description: "Fallback language when detection is inconclusive",
    type: String
  }
}.freeze
DEFAULTS =

Default configuration values (legacy, for backward compatibility).

{
  dictionary_path: nil,
  dictionary_type: :unix_words,
  language: "en-US",
  locale: nil,
  max_suggestions: 10,
  case_sensitive: false,
  verbose: false,
  suggestion_algorithms: nil, # Use defaults
  custom_words: [],
  encoding: "UTF-8",
  dictionaries_path: nil, # Path to dictionaries directory (for grammar rules)
  offline: false,
  default_language: "en",
  resource_pin: "main"
}.freeze

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(*args, **kwargs, &block) {|_self| ... } ⇒ Configuration

Create a new configuration.

Examples:

With hash

config = Configuration.new(
  dictionary_path: "/usr/share/dict/words",
  language: "en-US"
)

With block

Configuration.new do |c|
  c.dictionary_path = "words.txt"
  c.max_suggestions = 15
end

With CLI options (higher priority)

config = Configuration.new(
  language: "en-US",
  cli_options: { language: "ja" }  # ja will be used
)

Parameters:

  • args (Array)

    Variable arguments (positional hash or nothing)

  • kwargs (Hash)

    Keyword arguments for configuration

  • block (Proc)

    Optional block for configuration

Yields:

  • (_self)

Yield Parameters:



334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
# File 'lib/kotoshu/configuration.rb', line 334

def initialize(*args, **kwargs, &block)
  # Handle both positional hash and keyword arguments
  settings = args.first.is_a?(Hash) ? args.first : {}
  settings = settings.merge(kwargs)

  # Extract cli_options if provided
  cli_options = settings.delete(:cli_options) || {}

  # Build the resolver with settings as programmatic defaults
  @resolver = Resolver.new(
    env: settings[:env] || {},
    programmatic: settings,
    cli: cli_options,
    defaults: DEFAULTS
  )

  apply_defaults
  apply_resolver_values
  apply_explicit_settings(settings)

  yield self if block
end

Instance Attribute Details

#audit_max_bytesInteger

Returns Audit log size threshold (bytes) for rotation.

Returns:

  • (Integer)

    Audit log size threshold (bytes) for rotation



303
304
305
# File 'lib/kotoshu/configuration.rb', line 303

def audit_max_bytes
  @audit_max_bytes
end

#audit_rotationsInteger

Returns Number of historical audit log rotations to keep.

Returns:

  • (Integer)

    Number of historical audit log rotations to keep



306
307
308
# File 'lib/kotoshu/configuration.rb', line 306

def audit_rotations
  @audit_rotations
end

#auto_downloadBoolean

Returns Whether to automatically download missing dictionaries.

Returns:

  • (Boolean)

    Whether to automatically download missing dictionaries



294
295
296
# File 'lib/kotoshu/configuration.rb', line 294

def auto_download
  @auto_download
end

#cache_pathString?

Returns Path to cache directory.

Returns:

  • (String, nil)

    Path to cache directory



261
262
263
# File 'lib/kotoshu/configuration.rb', line 261

def cache_path
  @cache_path
end

#cache_ttlInteger

Returns Cache TTL in seconds.

Returns:

  • (Integer)

    Cache TTL in seconds



297
298
299
# File 'lib/kotoshu/configuration.rb', line 297

def cache_ttl
  @cache_ttl
end

#case_sensitiveBoolean

Returns Whether lookups are case-sensitive.

Returns:

  • (Boolean)

    Whether lookups are case-sensitive



231
232
233
# File 'lib/kotoshu/configuration.rb', line 231

def case_sensitive
  @case_sensitive
end

#config_pathString?

Returns Path to user config directory.

Returns:

  • (String, nil)

    Path to user config directory



264
265
266
# File 'lib/kotoshu/configuration.rb', line 264

def config_path
  @config_path
end

#custom_wordsArray<String>

Returns Custom words to add to dictionary.

Returns:

  • (Array<String>)

    Custom words to add to dictionary



240
241
242
# File 'lib/kotoshu/configuration.rb', line 240

def custom_words
  @custom_words
end

#data_pathString?

Returns Path to data directory (audit log, etc.).

Returns:

  • (String, nil)

    Path to data directory (audit log, etc.)



267
268
269
# File 'lib/kotoshu/configuration.rb', line 267

def data_path
  @data_path
end

#default_languageString

Returns Fallback language when detection is inconclusive.

Returns:

  • (String)

    Fallback language when detection is inconclusive



255
256
257
# File 'lib/kotoshu/configuration.rb', line 255

def default_language
  @default_language
end

#dictionaries_pathString?

Returns Path to dictionaries directory (for grammar rules).

Returns:

  • (String, nil)

    Path to dictionaries directory (for grammar rules)



249
250
251
# File 'lib/kotoshu/configuration.rb', line 249

def dictionaries_path
  @dictionaries_path
end

#dictionaries_pinString

Returns Pin for kotoshu/dictionaries.

Returns:

  • (String)

    Pin for kotoshu/dictionaries



279
280
281
# File 'lib/kotoshu/configuration.rb', line 279

def dictionaries_pin
  @dictionaries_pin
end

#dictionaries_urlString

Returns Base URL for downloading dictionaries (deprecated).

Returns:

  • (String)

    Base URL for downloading dictionaries (deprecated)



270
271
272
# File 'lib/kotoshu/configuration.rb', line 270

def dictionaries_url
  @dictionaries_url
end

#dictionaryDictionary::Base

Load or get the dictionary.

Returns:



246
247
248
# File 'lib/kotoshu/configuration.rb', line 246

def dictionary
  @dictionary
end

#dictionary_pathString?

Returns Path to the dictionary file.

Returns:

  • (String, nil)

    Path to the dictionary file



216
217
218
# File 'lib/kotoshu/configuration.rb', line 216

def dictionary_path
  @dictionary_path
end

#dictionary_typeSymbol

Returns Dictionary type (:unix_words, :plain_text, :hunspell, :cspell, :custom).

Returns:

  • (Symbol)

    Dictionary type (:unix_words, :plain_text, :hunspell, :cspell, :custom)



219
220
221
# File 'lib/kotoshu/configuration.rb', line 219

def dictionary_type
  @dictionary_type
end

#download_reporter#start, ...

Returns Optional progress reporter for downloads. Typically set by the CLI (Cli::ProgressReporter) for human-facing setup runs; nil (silent) for programmatic API usage.

Returns:

  • (#start, #update, #maybe_report_periodic, #finish, nil)

    Optional progress reporter for downloads. Typically set by the CLI (Cli::ProgressReporter) for human-facing setup runs; nil (silent) for programmatic API usage.



291
292
293
# File 'lib/kotoshu/configuration.rb', line 291

def download_reporter
  @download_reporter
end

#encodingString

Returns Character encoding.

Returns:

  • (String)

    Character encoding



243
244
245
# File 'lib/kotoshu/configuration.rb', line 243

def encoding
  @encoding
end

#frequency_pinString

Returns Pin for kotoshu/frequency-list-kelly.

Returns:

  • (String)

    Pin for kotoshu/frequency-list-kelly



282
283
284
# File 'lib/kotoshu/configuration.rb', line 282

def frequency_pin
  @frequency_pin
end

#languageString

Returns Language code (e.g., "en-US", "en-GB").

Returns:

  • (String)

    Language code (e.g., "en-US", "en-GB")



222
223
224
# File 'lib/kotoshu/configuration.rb', line 222

def language
  @language
end

#localeString?

Returns Locale (e.g., "en", "en_US").

Returns:

  • (String, nil)

    Locale (e.g., "en", "en_US")



225
226
227
# File 'lib/kotoshu/configuration.rb', line 225

def locale
  @locale
end

#max_cache_sizeInteger

Returns Maximum cache size in bytes.

Returns:

  • (Integer)

    Maximum cache size in bytes



300
301
302
# File 'lib/kotoshu/configuration.rb', line 300

def max_cache_size
  @max_cache_size
end

#max_suggestionsInteger

Returns Maximum number of suggestions to return.

Returns:

  • (Integer)

    Maximum number of suggestions to return



228
229
230
# File 'lib/kotoshu/configuration.rb', line 228

def max_suggestions
  @max_suggestions
end

#models_pinString

Returns Branch/tag/commit pinned for model downloads.

Returns:

  • (String)

    Branch/tag/commit pinned for model downloads



285
286
287
# File 'lib/kotoshu/configuration.rb', line 285

def models_pin
  @models_pin
end

#models_urlString

Returns Base URL for FastText ONNX models (deprecated).

Returns:

  • (String)

    Base URL for FastText ONNX models (deprecated)



273
274
275
# File 'lib/kotoshu/configuration.rb', line 273

def models_url
  @models_url
end

#offlineBoolean

Returns Whether to use only cached resources (no downloads).

Returns:

  • (Boolean)

    Whether to use only cached resources (no downloads)



252
253
254
# File 'lib/kotoshu/configuration.rb', line 252

def offline
  @offline
end

#repos_base_urlString

Returns GitHub raw root for all kotoshu content repos.

Returns:

  • (String)

    GitHub raw root for all kotoshu content repos



276
277
278
# File 'lib/kotoshu/configuration.rb', line 276

def repos_base_url
  @repos_base_url
end

#resolverResolver (readonly)

Returns The configuration resolver.

Returns:

  • (Resolver)

    The configuration resolver



309
310
311
# File 'lib/kotoshu/configuration.rb', line 309

def resolver
  @resolver
end

#resource_pinString

Returns Branch/tag/commit pinned for resource downloads.

Returns:

  • (String)

    Branch/tag/commit pinned for resource downloads



258
259
260
# File 'lib/kotoshu/configuration.rb', line 258

def resource_pin
  @resource_pin
end

#suggestion_algorithmsArray<Class>?

Returns Suggestion algorithms to use.

Returns:

  • (Array<Class>, nil)

    Suggestion algorithms to use



237
238
239
# File 'lib/kotoshu/configuration.rb', line 237

def suggestion_algorithms
  @suggestion_algorithms
end

#verboseBoolean

Returns Whether to enable verbose output.

Returns:

  • (Boolean)

    Whether to enable verbose output



234
235
236
# File 'lib/kotoshu/configuration.rb', line 234

def verbose
  @verbose
end

Class Method Details

.defaultConfiguration

Get the default configuration.

Examples:

config = Configuration.default

Returns:



480
481
482
# File 'lib/kotoshu/configuration.rb', line 480

def self.default
  new(DEFAULTS.dup)
end

.default_cache_pathString

Get default cache path.

Returns:

  • (String)

    The default cache path



623
624
625
# File 'lib/kotoshu/configuration.rb', line 623

def self.default_cache_path
  Paths.cache_path
end

.default_config_pathObject



627
628
629
# File 'lib/kotoshu/configuration.rb', line 627

def self.default_config_path
  Paths.config_path
end

.default_data_pathObject



631
632
633
# File 'lib/kotoshu/configuration.rb', line 631

def self.default_data_path
  Paths.data_path
end

.instanceConfiguration

Global configuration instance.

The process-default configuration instance.

New code should prefer passing a Configuration instance explicitly to Spellchecker.new (and friends) rather than reading this singleton — that path is testable without process-wide state and scopes the configuration per-call. This accessor is kept for backward compat with the facade methods in Kotoshu (Kotoshu.correct?, Kotoshu.spellchecker, etc.) that don't take a Configuration argument.

Examples:

Configuration.instance.dictionary_path = "/usr/share/dict/words"

Returns:



500
501
502
# File 'lib/kotoshu/configuration.rb', line 500

def self.instance
  @instance ||= default
end

.instance=(config) ⇒ Configuration

Replace the process-default configuration instance. Type-checked so a typo doesn't silently nil-out the singleton. Clears the cached Spellchecker built off the previous instance so the next Kotoshu.spellchecker rebuilds with the new config.

Parameters:

Returns:

Raises:

  • (ArgumentError)


511
512
513
514
515
# File 'lib/kotoshu/configuration.rb', line 511

def self.instance=(config)
  raise ArgumentError, "instance must be a Configuration" unless config.is_a?(Configuration)

  @instance = config
end

.resetConfiguration

Reset the global configuration.

Returns:



520
521
522
# File 'lib/kotoshu/configuration.rb', line 520

def self.reset
  @instance = default
end

Instance Method Details

#cloneConfiguration

Clone the configuration.

Returns:



470
471
472
# File 'lib/kotoshu/configuration.rb', line 470

def clone
  self.class.new(to_h)
end

#get(key) ⇒ Object

Get a configuration value using the resolver.

This respects the priority: CLI > ENV > Programmatic > Defaults

Examples:

config.get(:language)  # => resolved language value

Parameters:

  • key (Symbol)

    The configuration key

Returns:

  • (Object)

    The resolved value



366
367
368
# File 'lib/kotoshu/configuration.rb', line 366

def get(key)
  @resolver.get(key)
end

#key?(key) ⇒ Boolean

Check if a configuration key has a value set.

Parameters:

  • key (Symbol)

    The configuration key

Returns:

  • (Boolean)

    True if the key is set somewhere



374
375
376
# File 'lib/kotoshu/configuration.rb', line 374

def key?(key)
  @resolver.key?(key)
end

#load_dictionaryDictionary::Base

Load the dictionary based on configuration.

Returns:

Raises:



390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
# File 'lib/kotoshu/configuration.rb', line 390

def load_dictionary
  dict = case @dictionary_type
         when :unix_words
           load_unix_words_dictionary
         when :plain_text
           load_plain_text_dictionary
         when :custom
           load_custom_dictionary
         when :hunspell
           load_hunspell_dictionary
         when :cspell
           load_cspell_dictionary
         else
           raise ConfigurationError, "Unknown dictionary type: #{@dictionary_type}"
         end

  # Add custom words
  @custom_words.each do |word|
    dict.add_word(word)
  end

  dict
end

#reset_dictionaryself

Reset the dictionary (force reload on next access).

Returns:

  • (self)

    Self for chaining



417
418
419
420
# File 'lib/kotoshu/configuration.rb', line 417

def reset_dictionary
  @dictionary = nil
  self
end

#source_registryKotoshu::SourceRegistry

Build a SourceRegistry honoring this configuration's base URL and per-repo pins. Single source of truth for all resource URLs.



456
457
458
459
460
461
462
463
464
465
# File 'lib/kotoshu/configuration.rb', line 456

def source_registry
  Kotoshu::SourceRegistry.new(
    base_url: @repos_base_url,
    pins: {
      "dictionaries" => @dictionaries_pin,
      "frequency-list-kelly" => @frequency_pin,
      "models-fasttext-onnx" => @models_pin
    }
  )
end

#to_hHash

Convert to hash.

Returns:

  • (Hash)

    Hash representation



425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
# File 'lib/kotoshu/configuration.rb', line 425

def to_h
  {
    dictionary_path: @dictionary_path,
    dictionary_type: @dictionary_type,
    language: @language,
    locale: @locale,
    max_suggestions: @max_suggestions,
    case_sensitive: @case_sensitive,
    verbose: @verbose,
    suggestion_algorithms: @suggestion_algorithms&.map(&:name),
    custom_words: @custom_words,
    encoding: @encoding,
    dictionaries_path: @dictionaries_path,
    cache_path: @cache_path,
    config_path: @config_path,
    data_path: @data_path,
    dictionaries_url: @dictionaries_url,
    repos_base_url: @repos_base_url,
    dictionaries_pin: @dictionaries_pin,
    frequency_pin: @frequency_pin,
    models_pin: @models_pin,
    auto_download: @auto_download,
    cache_ttl: @cache_ttl,
    max_cache_size: @max_cache_size
  }
end