Initial parametric Feather case generator
This commit is contained in:
@@ -0,0 +1,116 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
module FeatherCaseWizard
|
||||
class CLI
|
||||
def initialize(ui: HighLine.new, cases_root: CASES_ROOT,
|
||||
model_source: MODEL_SOURCE, renderer_source: RENDERER_SOURCE,
|
||||
toolchain: Toolchain.new)
|
||||
@ui = ui
|
||||
@cases_root = Pathname(cases_root)
|
||||
@model_source = Pathname(model_source)
|
||||
@renderer_source = Pathname(renderer_source)
|
||||
@toolchain = toolchain
|
||||
@wizard = Wizard.new(ui: ui)
|
||||
end
|
||||
|
||||
def run
|
||||
@ui.say(@ui.color("Feather Case Wizard", :bold))
|
||||
loop do
|
||||
action = @ui.choose("\nWhat would you like to do?") do |menu|
|
||||
menu.choice("Create a new case") { :create }
|
||||
menu.choice("Edit an existing case") { :edit }
|
||||
menu.choice("Rebuild an existing case") { :rebuild }
|
||||
menu.choice("Exit") { :exit }
|
||||
end
|
||||
return 0 if action == :exit
|
||||
|
||||
case action
|
||||
when :create then create_case
|
||||
when :edit then edit_case
|
||||
when :rebuild then rebuild_case
|
||||
end
|
||||
rescue ConfigError, ToolError, Errno::EACCES => e
|
||||
@ui.say(@ui.color("\n#{e.message}", :red))
|
||||
rescue Interrupt
|
||||
@ui.say("\nCancelled.")
|
||||
return 130
|
||||
end
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def create_case
|
||||
config = @wizard.create
|
||||
destination = config.package_dir(@cases_root)
|
||||
if destination.exist? &&
|
||||
!@ui.agree("#{destination} already exists. Replace it? (y/n) ") { |q| q.default = "no" }
|
||||
return
|
||||
end
|
||||
build(config, @model_source, @renderer_source) if @wizard.confirm_build(config)
|
||||
end
|
||||
|
||||
def edit_case
|
||||
path = choose_case
|
||||
return unless path
|
||||
|
||||
config = Config.load(path)
|
||||
package = path.dirname
|
||||
source = package.join("source/feather_case.scad")
|
||||
renderer = package.join("source/render_stl_previews.py")
|
||||
source, renderer = choose_generator(config, source, renderer)
|
||||
config = @wizard.edit(config)
|
||||
build(config, source, renderer) if @wizard.confirm_build(config)
|
||||
end
|
||||
|
||||
def rebuild_case
|
||||
path = choose_case
|
||||
return unless path
|
||||
|
||||
config = Config.load(path)
|
||||
return unless @wizard.confirm_build(config)
|
||||
|
||||
package = path.dirname
|
||||
build(config, package.join("source/feather_case.scad"),
|
||||
package.join("source/render_stl_previews.py"))
|
||||
end
|
||||
|
||||
def choose_case
|
||||
paths = Dir.glob(@cases_root.join("*/case.yml")).sort.map { |item| Pathname(item) }
|
||||
if paths.empty?
|
||||
@ui.say("No saved cases found under #{@cases_root}.")
|
||||
return nil
|
||||
end
|
||||
@ui.choose("Choose a saved case") do |menu|
|
||||
paths.each do |path|
|
||||
label = Config.load(path).name
|
||||
menu.choice("#{label} (#{path.dirname.basename})") { path }
|
||||
rescue ConfigError
|
||||
menu.choice("Invalid configuration (#{path.dirname.basename})") { path }
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
def choose_generator(config, snapshot, renderer)
|
||||
return [@model_source, @renderer_source] unless snapshot.file?
|
||||
|
||||
snapshot_sha = Digest::SHA256.file(snapshot).hexdigest
|
||||
current_sha = Digest::SHA256.file(@model_source).hexdigest
|
||||
return [snapshot, renderer] if snapshot_sha == current_sha
|
||||
|
||||
@ui.say("This case uses a different generator snapshot.")
|
||||
upgrade = @ui.agree("Upgrade it to the current generator? (y/n) ") do |question|
|
||||
question.default = "no"
|
||||
end
|
||||
upgrade ? [@model_source, @renderer_source] : [snapshot, renderer]
|
||||
end
|
||||
|
||||
def build(config, source, renderer)
|
||||
destination = PackageBuilder.new(
|
||||
config, root: @cases_root, toolchain: @toolchain,
|
||||
model_source: source, renderer_source: renderer,
|
||||
reporter: ->(message) { @ui.say(" #{message}…") }
|
||||
).build!
|
||||
@ui.say(@ui.color("\nGenerated #{destination}", :green))
|
||||
end
|
||||
end
|
||||
end
|
||||
Reference in New Issue
Block a user