require "process" require "io/memory" require "io" module Taro enum WinType LIST READER COMPOSE end class Mesg @type : UInt8 @data : Slice(UInt8) def type @type end def data @data end def initialize(@type, @data) end end class ChildWindow @lifetime : Channel(UInt8) @msg : Channel(Mesg) @stdout_w : IO::FileDescriptor @stdout_r : IO::FileDescriptor @stdin_w : IO::FileDescriptor @stdin_r : IO::FileDescriptor @decoding : Bool = false @szshort : UInt16 = 0 def initialize(w : WinType = WinType::LIST) @stdout_r, @stdout_w = IO.pipe @stdin_r, @stdin_w = IO.pipe @lifetime = Channel(UInt8).new @msg = Channel(Mesg).new uxnrom : String = "" case w when WinType::LIST then uxnrom = "taro-ls" when WinType::READER then uxnrom = "taro-reader" when WinType::COMPOSE then uxnrom = "taro-compose" end uxnargs = ["-s", "1", "#{uxnrom}.rom"] spawn do Process.run(command: "uxnemu", args: uxnargs, input: @stdin_r, output: @stdout_w, error: Process::Redirect::Inherit) @lifetime.send(0) end spawn do loop do @msg.send(read_msg) end end end def lifetime @lifetime end def msg @msg end def write_msg(msgtype : UInt8, data : Slice) msgsz = UInt16.new(data.size > 16384 ? 16384 : data.size) msgtype.to_io(@stdin_w, IO::ByteFormat::BigEndian) msgsz.to_io(@stdin_w, IO::ByteFormat::BigEndian) if msgsz == 16384 @stdin_w.write(data[0..msgsz - 2]) 10_u8.to_io(@stdin_w, IO::ByteFormat::BigEndian) else @stdin_w.write(data[0..msgsz - 1]) end end def read_msg msgType : UInt8 = 0 data : Slice(UInt8) = Slice(UInt8).new(0) loop do if @stdout_r.closed? break end if !@decoding msgType = @stdout_r.read_byte || 0_u8 @decoding = true elsif @szshort == 0 szslice = Slice(UInt8).new(2) @stdout_r.read_fully(szslice) szlow : UInt16 = UInt16.new(szslice[0])*256 szhigh : UInt16 = UInt16.new(szslice[1]) @szshort = szlow + szhigh else slc = Slice(UInt8).new(@szshort) @stdout_r.read_fully(slc) @decoding = false data = slc break end end return Mesg.new(msgType, data) end end class MblazeProxy def list_mail(box : String = "INBOX") mailCmd = " mbox=${MBOX_ROOT}/#{box} mdirs ${mbox} | xargs minc > /dev/null mlist ${mbox} | msort -dr | mseq -S | mscan" io = IO::Memory.new Process.run(mailCmd, shell: true, output: io) return io.to_s end def list_mboxes mailCmd ="for x in $(mdirs ${MBOX_ROOT}); do echo ${x#$MBOX_ROOT/}; done" io = IO::Memory.new Process.run(mailCmd, shell: true, output: io) return io.to_s end end class TaroCtl @mblaze : MblazeProxy @lsWin : ChildWindow @readWins : Array(ChildWindow) @composeWins : Array(ChildWindow) def initialize @lsWin = ChildWindow.new @readWins = Array(ChildWindow).new @composeWins = Array(ChildWindow).new @mblaze = MblazeProxy.new list = @mblaze.list_mail @lsWin.write_msg(2_u8, list.to_slice) end def mblaze @mblaze end def mainWindow @lsWin end def readWins @readWins end def composeWins @composeWins end end end taro = Taro::TaroCtl.new loop do select when taro.mainWindow.lifetime.receive? exit when m = taro.mainWindow.msg.receive # do something end end