mirror of
https://hacklab.nilfm.cc/taro
synced 2024-10-22 14:31:48 +00:00
241 lines
No EOL
5.4 KiB
Crystal
241 lines
No EOL
5.4 KiB
Crystal
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
|
|
@sizing : 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)
|
|
if msgsz != 0
|
|
msgsz.to_io(@stdin_w, IO::ByteFormat::BigEndian)
|
|
else
|
|
8_u16.to_io(@stdin_w, IO::ByteFormat::BigEndian)
|
|
end
|
|
|
|
if msgsz == 16384
|
|
@stdin_w.write(data[0..msgsz - 2])
|
|
10_u8.to_io(@stdin_w, IO::ByteFormat::BigEndian)
|
|
elsif msgsz != 0
|
|
@stdin_w.write(data[0..msgsz - 1])
|
|
else
|
|
@stdin_w.write("nothing\n".to_slice)
|
|
end
|
|
end
|
|
|
|
def read_msg
|
|
msgType : UInt8 = 0
|
|
data : Slice(UInt8) = Slice(UInt8).new(0)
|
|
loop do
|
|
if @stdout_r.closed?
|
|
@decoding = false
|
|
@sizing = false
|
|
@szshort = 0
|
|
break
|
|
end
|
|
if !@decoding
|
|
msgType = @stdout_r.read_byte || 0_u8
|
|
@decoding = true
|
|
@sizing = true
|
|
elsif @sizing
|
|
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
|
|
@sizing = false
|
|
if @szshort == 0
|
|
@decoding = false
|
|
break
|
|
end
|
|
else
|
|
slc = Slice(UInt8).new(@szshort)
|
|
@stdout_r.read_fully(slc)
|
|
data = slc
|
|
@decoding = false
|
|
@szshort = 0
|
|
break
|
|
end
|
|
end
|
|
return Mesg.new(msgType, data)
|
|
end
|
|
|
|
end
|
|
|
|
class MblazeProxy
|
|
@mailbox : String
|
|
|
|
def initialize
|
|
@mailbox = "INBOX"
|
|
end
|
|
|
|
private def run_cmd(cmdtxt : String) : String
|
|
puts cmdtxt
|
|
io = IO::Memory.new
|
|
Process.run(cmdtxt, shell: true, output: io)
|
|
return io.to_s
|
|
end
|
|
|
|
def list_mail : String
|
|
cmd = "
|
|
mbox=${MBOX_ROOT}/#{@mailbox}
|
|
|
|
mdirs ${mbox} | xargs minc > /dev/null
|
|
mlist ${mbox} | msort -dr | mseq -S | mscan"
|
|
|
|
return run_cmd(cmd)
|
|
end
|
|
|
|
def list_mboxes : String
|
|
cmd = "echo 'INBOX' ; for x in $(mdirs -a ${MBOX_ROOT} | sort | grep -v INBOX); do echo ${x#$MBOX_ROOT/}; done"
|
|
|
|
return run_cmd(cmd)
|
|
end
|
|
|
|
def mark_all_read
|
|
cmd = "mflag -S :"
|
|
run_cmd(cmd)
|
|
end
|
|
|
|
def set_mbox(box : String)
|
|
@mailbox = box
|
|
end
|
|
|
|
def trash_mail(range : String)
|
|
cmd = "mflag -T #{range}; mlist ${MBOX_ROOT}/#{@mailbox} | mseq -S | mpick -t 'trashed' | mrefile ${MBOX_ROOT}/Trash"
|
|
run_cmd(cmd)
|
|
end
|
|
|
|
def refile_mail(range : String, to_mbox : String)
|
|
cmd = "mrefile #{range} ${MBOX_ROOT}/#{to_mbox}"
|
|
run_cmd(cmd)
|
|
end
|
|
|
|
def search_mail(query : String, body : Bool) : String
|
|
mailCmd = "mlist ${MBOX_ROOT}/#{@mailbox} | magrep #{body ? "/" : "*"} | msort -dr | mseq -S | mscan | uniq"
|
|
return run_cmd(cmd)
|
|
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
|
|
mboxes = @mblaze.list_mboxes
|
|
@lsWin.write_msg(0_u8, mboxes.to_slice)
|
|
@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
|
|
case m.type
|
|
when 1 then
|
|
taro.mblaze.set_mbox(String.new(m.data))
|
|
taro.mainWindow.write_msg(2_u8, taro.mblaze.list_mail.to_slice)
|
|
when 3 then
|
|
taro.mblaze.mark_all_read
|
|
taro.mainWindow.write_msg(2_u8, taro.mblaze.list_mail.to_slice)
|
|
end
|
|
end
|
|
end |