<commit_before>require "yaml"
require "fileutils"

module Muzak
  # Muzak's static configuration dumping ground.
  # Key-value pairs are loaded from {CONFIG_FILE} and translated from
  # kebab-case to snake_case methods.
  # @example
  #   # corresponds to `art-geometry: 300x300` in configuration
  #   Config.art_geometry # => "300x300"
  # @see file:CONFIGURATION.md User Configuration
  class Config
    if File.exist?(CONFIG_FILE)
      @config = YAML::load_file(CONFIG_FILE)
    else
      @config = {
        "debug" => false,
        "verbose" => true,
        "music" => File.expand_path("~/music"),
        "player" => "mpv",
        "index-autobuild" => 86400,
        "deep-index" => false,
        "jukebox-size" => 100
      }

      [CONFIG_DIR, PLAYLIST_DIR, USER_PLUGIN_DIR, USER_COMMAND_DIR].each do |d|
        FileUtils.mkdir_p d
      end

      sync!
    end

    @config.each do |key, _|
      define_singleton_method Utils.resolve_command(key) do
        @config[key]
      end

      define_singleton_method "#{Utils.resolve_command(key)}=" do |value|
        @config[key] = value
        sync!
      end
    end

    # Catches all undefined configuration keys and defaults them to false.
    # @return [false]
    def self.method_missing(method, *args)
      false
    end

    # Synchronizes the in-memory configuration with {CONFIG_FILE}.
    # @return [void]
    def self.sync!
      File.open(CONFIG_FILE, "w") { |io| io.write @config.to_yaml }
    end

    # @return [Boolean] whether or not the given plugin is configured
    # @note the truth-value of this method is used to determine which
    #   plugins should be loaded.
    def self.plugin?(pname)
      respond_to? "plugin_#{pname}"
    end
  end
end<commit_msg>config: Define methods above configuration load.<commit_after>require "yaml"
require "fileutils"

module Muzak
  # Muzak's static configuration dumping ground.
  # Key-value pairs are loaded from {CONFIG_FILE} and translated from
  # kebab-case to snake_case methods.
  # @example
  #   # corresponds to `art-geometry: 300x300` in configuration
  #   Config.art_geometry # => "300x300"
  # @see file:CONFIGURATION.md User Configuration
  class Config
    # Catches all undefined configuration keys and defaults them to false.
    # @return [false]
    def self.method_missing(method, *args)
      false
    end

    # Synchronizes the in-memory configuration with {CONFIG_FILE}.
    # @return [void]
    def self.sync!
      File.open(CONFIG_FILE, "w") { |io| io.write @config.to_yaml }
    end

    # @return [Boolean] whether or not the given plugin is configured
    # @note the truth-value of this method is used to determine which
    #   plugins should be loaded.
    def self.plugin?(pname)
      respond_to? "plugin_#{pname}"
    end

    if File.exist?(CONFIG_FILE)
      @config = YAML::load_file(CONFIG_FILE)
    else
      @config = {
        "debug" => false,
        "verbose" => true,
        "music" => File.expand_path("~/music"),
        "player" => "mpv",
        "index-autobuild" => 86400,
        "deep-index" => false,
        "jukebox-size" => 100
      }

      [CONFIG_DIR, PLAYLIST_DIR, USER_PLUGIN_DIR, USER_COMMAND_DIR].each do |d|
        FileUtils.mkdir_p d
      end

      sync!
    end

    @config.each do |key, _|
      define_singleton_method Utils.resolve_command(key) do
        @config[key]
      end

      define_singleton_method "#{Utils.resolve_command(key)}=" do |value|
        @config[key] = value
        sync!
      end
    end
  end
end
{'fraction_non_alphanumeric': 0.10630477806050326, 'fraction_numerical': 0.01130901894260673, 'mean_word_length': 2.643666323377961, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 19, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '3175265', 'n_tokens_mistral': 1171, 'n_tokens_neox': 1116, 'n_words': 308}