Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?
# A crude YaST UI recoder and player
#
# Usage:
# Y2UI_RECORD=/tmp/y2host.yaml LANG=en_US.UTF-8 \
# ruby -r ./ui_recorder.rb /usr/lib/YaST2/bin/y2start host qt
# less /tmp/y2host.yaml
# Y2UI_PLAY=/tmp/y2host.yaml LANG=en_US.UTF-8 \
# ruby -r ./ui_recorder.rb /usr/lib/YaST2/bin/y2start host qt
require "set"
require "yaml"
require "yast"
Yast.ui_component = "qt" # FIXME: figure out why it fails in y2start
Yast.import "UI"
# A recorded call of a UI method + arguments + return value.
class Record
attr_reader :name, :args, :ret
def initialize(name, args, ret)
@name = name
@args = args
@ret = ret
end
def to_hash
rec = { "n" => @name.to_s }
rec["r"] = @ret unless @ret.nil?
rec["a"] = @args unless @args.empty?
rec
end
def self.from_hash(hash)
name = hash["n"].to_sym
args = hash.fetch("a", [])
ret = hash["r"]
new(name, args, ret)
end
end
class Recorder
# We record more data than we play back, to provide context
RECORD_METHODS = [
:OpenDialog,
:CloseDialog,
:ReplaceWidget,
:QueryWidget,
:ChangeWidget,
:UserInput
].freeze
def initialize(filename:)
@filename = filename
@records = []
recorder = self
RECORD_METHODS.each do |uim|
old_method = Yast::UI.singleton_method(uim)
Yast::UI.define_singleton_method(uim) do |*args|
ret = old_method.call(*args)
recorder.record(uim, args, ret)
ret
end
end
end
def record(name, args, ret)
@records << Record.new(name, args, ret)
end
def finish
File.open(@filename, "w") do |f|
YAML.dump(@records.map(&:to_hash), f)
end
end
end
class Player
PLAY_METHODS = Set.new [
:QueryWidget,
:ChangeWidget,
:UserInput
]
attr_reader :records
def initialize(filename:)
@records = YAML.load(File.read(filename)).map { |h| Record.from_hash(h) }
record_methods = Set.new(@records, &:name)
player = self
(record_methods & PLAY_METHODS).each do |uim|
old_method = Yast::UI.singleton_method(uim)
Yast::UI.define_singleton_method(uim) do |*args|
player.play(old_method, uim, args)
end
end
end
def play(old_method, name, args)
i = records.find_index do |r|
r.name == name && r.args == args
end
if i.nil?
Yast.y2warning("Player: NOT found %1 %2", name, args)
old_method.call(*args)
else
r = records.delete_at(i)
Yast.y2warning("Player: DID find %1 %2 -> %3", name, args, r.ret)
r.ret
end
end
end
if ENV["Y2UI_RECORD"]
recorder = Recorder.new(filename: ENV["Y2UI_RECORD"])
at_exit do
recorder.finish
end
elsif ENV["Y2UI_PLAY"]
Player.new(filename: ENV["Y2UI_PLAY"])
else
puts "Nothing to record/play"
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.