219 lines
6.1 KiB
Crystal
219 lines
6.1 KiB
Crystal
require "colorize"
|
|
require "yaml"
|
|
|
|
class Baguette::Context
|
|
# By default, just print everything.
|
|
class_property verbosity = 4
|
|
end
|
|
|
|
class Baguette::Configuration
|
|
class_property project_directory : String? = nil
|
|
|
|
class Base
|
|
include YAML::Serializable
|
|
|
|
# Check for $XDG_CONFIG_HOME/baguette/<project-name>/<class>.yml,
|
|
# then /etc/baguette/<project-name>/<class>.yml.
|
|
# (project name is not mandatory)
|
|
def self.get(file : String? = nil)
|
|
filename = "/" + (self.name.downcase.gsub /baguette::configuration::/, "") + ".yml"
|
|
directory = "/baguette"
|
|
|
|
if pdir = Baguette::Configuration.project_directory
|
|
directory += "/" + pdir
|
|
end
|
|
|
|
suffix = "#{directory}#{filename}"
|
|
user_configuration = (ENV["XDG_CONFIG_HOME"]? || "#{ENV["HOME"]}/.config") + suffix
|
|
system_configuration = "/etc#{suffix}"
|
|
|
|
if ! file.nil? && ! File.exists? file.not_nil!
|
|
Baguette::Log.warning "Provided configuration file does not exist: #{file}"
|
|
end
|
|
|
|
if ! file.nil? && File.exists? file.not_nil!
|
|
Baguette::Log.info "Using configuration file: #{file}"
|
|
self.from_yaml File.read(file.not_nil!)
|
|
elsif File.exists? user_configuration
|
|
Baguette::Log.info "Using user configuration: #{user_configuration}"
|
|
self.from_yaml File.read(user_configuration)
|
|
elsif File.exists? system_configuration
|
|
Baguette::Log.info "Using system configuration: #{system_configuration}"
|
|
self.from_yaml File.read(system_configuration)
|
|
else
|
|
Baguette::Log.warning "No configuration found"
|
|
Baguette::Log.warning "Searched in: #{user_configuration}"
|
|
Baguette::Log.warning "Searched in: #{system_configuration}"
|
|
nil
|
|
end
|
|
end
|
|
end
|
|
|
|
class IPC < Base
|
|
enum MESSAGE
|
|
TIMER
|
|
CONNECTION
|
|
DISCONNECTION
|
|
EXTERNAL # extra socket
|
|
RX
|
|
TX
|
|
SWITCH
|
|
ERROR
|
|
EXCEPTION
|
|
end
|
|
|
|
property ipc_timer : Int32 = 30_000 # 30 seconds.
|
|
property ipc_messages_to_show : Array(IPC::MESSAGE) = [MESSAGE::ERROR, MESSAGE::EXCEPTION]
|
|
property verbosity : Int32 = 4
|
|
|
|
def initialize
|
|
end
|
|
end
|
|
|
|
# Read options from the CLI.
|
|
# We currently want to know:
|
|
# - the program verbosity
|
|
# - the configuration directory to use (project name)
|
|
# - if the configuration files should be ignored
|
|
# - if this is just a simulation (used to print configuration then quit)
|
|
def self.option_parser
|
|
simulation = false
|
|
no_configuration = false
|
|
configuration_file = nil
|
|
|
|
help = false
|
|
|
|
OptionParser.parse do |parser|
|
|
parser.banner = "usage: #{PROGRAM_NAME} [-ns][--project project-name]"
|
|
|
|
parser.on "-s", "--simulation", "Print configuration then quit." do
|
|
simulation = true
|
|
end
|
|
|
|
parser.on "-n", "--no-configuration", "No configuration file should be read." do
|
|
no_configuration = true
|
|
end
|
|
|
|
parser.on "--configuration file", "Configuration file to use." do |f|
|
|
configuration_file = f
|
|
end
|
|
|
|
parser.on "-v verbosity", "--verbosity level",
|
|
"Verbosity level. From 0 to 4. Default: 4" do |v|
|
|
Baguette::Context.verbosity = v.to_i
|
|
end
|
|
|
|
parser.on "--project project-name",
|
|
"Project name. Will search in $XDG_CONFIG_HOME/baguette/<project-name>/<class>.yml then /etc/baguette/<project-name>/<class>.yml." do |dir|
|
|
Baguette::Configuration.project_directory = dir
|
|
end
|
|
|
|
parser.invalid_option do |arg|
|
|
# Do not print anything: we only check for configuration file stuff.
|
|
end
|
|
|
|
parser.on "-h", "--help", "Show this help" do
|
|
puts parser
|
|
help = true
|
|
end
|
|
end
|
|
|
|
# Options are removed once read from the ARGV array, but we want to propagate
|
|
# this particular option to print the second set of options.
|
|
ARGV.push "-h" if help
|
|
|
|
return simulation, no_configuration, configuration_file
|
|
end
|
|
end
|
|
|
|
# `Baguette::Log` is a library to display information.
|
|
# A filename can be given to write logs in a file.
|
|
class Baguette::Log
|
|
# FIXME: def log(), that puts stuff as-is in the logs.
|
|
|
|
# Name of the file.
|
|
class_property log_path : String? = nil
|
|
|
|
enum LOGTYPE
|
|
DEBUG = 5
|
|
INFO = 4
|
|
TITLE = 3
|
|
WARNING = 2
|
|
ERROR = 1
|
|
end
|
|
|
|
def self.now() : String
|
|
Time.local.to_s("%Y-%m-%d_%H:%M:%S")
|
|
end
|
|
|
|
def self.write_log_fancy(io : IO, logtype : LOGTYPE, text)
|
|
case logtype
|
|
when .debug?
|
|
io.<<(self.now).<<(" :: ".colorize(:cyan)).<<(text.colorize(:cyan)).<<("\n")
|
|
when .info?
|
|
io.<<(self.now).<<(" :: ".colorize(:blue)).<<(text.colorize(:white)).<<("\n")
|
|
when .title?
|
|
io.<<(self.now).<<(" |> ".colorize(:blue).bright).<<(text.colorize(:white).bright).<<("\n")
|
|
when .warning?
|
|
io.<<(self.now).<<(" :: ".colorize(:yellow).bright).<<(text.colorize(:yellow)).<<("\n")
|
|
when .error?
|
|
io.<<(self.now).<<(" !! ".colorize(:red).bright).<<(text.colorize(:red)).<<("\n")
|
|
end
|
|
end
|
|
|
|
def self.write_log_plain(io : IO, logtype : LOGTYPE, text)
|
|
case logtype
|
|
when .debug?
|
|
io.<<(self.now).<<(" (debug) ").<<(text).<<("\n")
|
|
when .info?
|
|
io.<<(self.now).<<(" (info) ").<<(text).<<("\n")
|
|
when .title?
|
|
io.<<(self.now).<<(" (title) ").<<(text).<<("\n")
|
|
when .warning?
|
|
io.<<(self.now).<<(" (warning) ").<<(text).<<("\n")
|
|
when .error?
|
|
io.<<(self.now).<<(" (error) ").<<(text).<<("\n")
|
|
end
|
|
end
|
|
|
|
def self.write_log(logtype : LOGTYPE, text)
|
|
if path = @@log_path
|
|
File.open path, "a" do |io|
|
|
self.write_log_plain io, logtype, text
|
|
end
|
|
|
|
# In case the thing we want to print is important, put it on the screen too.
|
|
if logtype <= LOGTYPE::WARNING
|
|
self.write_log_fancy STDERR, logtype, text
|
|
end
|
|
else
|
|
if logtype <= LOGTYPE::WARNING
|
|
self.write_log_fancy STDERR, logtype, text
|
|
else
|
|
self.write_log_fancy STDOUT, logtype, text
|
|
end
|
|
end
|
|
end
|
|
|
|
def self.debug(text)
|
|
return unless Baguette::Context.verbosity > 3
|
|
self.write_log LOGTYPE::DEBUG, text
|
|
end
|
|
def self.info(text)
|
|
return unless Baguette::Context.verbosity > 2
|
|
self.write_log LOGTYPE::INFO, text
|
|
end
|
|
def self.title(text)
|
|
return unless Baguette::Context.verbosity > 2
|
|
self.write_log LOGTYPE::TITLE, text
|
|
end
|
|
def self.warning(text)
|
|
return unless Baguette::Context.verbosity > 1
|
|
self.write_log LOGTYPE::WARNING, text
|
|
end
|
|
def self.error(text)
|
|
return unless Baguette::Context.verbosity > 0
|
|
self.write_log LOGTYPE::ERROR, text
|
|
end
|
|
end
|
|
|