all repos — taro @ 5f77c7867ef3e994058765bbf06560d0499e0c99

mblaze frontend in uxn + crystal

refactor mread into taro-reader, clean up some code, fix mouse bug in taro-ls
Iris Lightshard nilix@nilfm.cc
PGP Signature
-----BEGIN PGP SIGNATURE-----

iQIzBAABCAAdFiEEkFh6dA+k/6CXFXU4O3+8IhROY5gFAmQdNtQACgkQO3+8IhRO
Y5hy6Q//UJiUqaFSyX+UOl7z7v9vfwztTETvpQ37kTfsIEu3ZA1uzDEf4XCWi4LO
nrsT69xU5QgRFYcW9p1srlZoQqD9KhQHZ8L9ewATq5Sh5PVvTp0v8TEd927gkgKu
gCKZFk/+i49qm6t5/mq1dlcaUS4x1ijRDJiCmIJ7Q6crk8JEh8A9YM1bVNeOTHia
6c5+t8i2sWH65tYnheneWGyRDGYa1ff9GhJ9hcY9m6Zzkilp5sh1QoKvL6IEc48x
KFddZF8MH9QfPTLBjDMzkzTUwQ9403vjqMTn6eyqBZjXEBYvOio2q8H2SUM+1FMi
Vv5Mam7Tkn3HtLcvqeseG1Lot00F9yjo/0FjmHpx5zH9VxWghOHys1mN/XSwI+nZ
YsuidV2FFC3TASKHzcyf9kp8zinONeIDVzGpsAhFw/NNJVNj3dljJMXHksBJd/sg
Cb8WgZLAYt3jEu/79p00goA4nfPX2X6I5J7s6n0959y3Wydm9d0v8h+WkL4M/MXw
ae0kPE+gZ51Zyma6tkxjRtZNs9gD6vkcKMF7/0TuYTPWRjo72LfJm8XEq3cFcc5+
xZJ2MEOTAKa5VneqCLrE9Lhl/wj2zd6QlRJ9cWgdBX55ubsv3MRtxPxgn9890liM
2iKaiqgKObDfiOihQwXZhBIpqHoei5UTYK8Xw8gL5mJAsp4eL2I=
=p6Jv
-----END PGP SIGNATURE-----
commit

5f77c7867ef3e994058765bbf06560d0499e0c99

parent

c3f5e7a0411bb020302128a0da84d63b37994633

10 files changed, 146 insertions(+), 104 deletions(-)

jump to
M .gitignore.gitignore

@@ -1,4 +1,4 @@

-*.rom -*.rom.sym +taro-ls +*.sym test* taro-ctl
M README.mdREADME.md

@@ -4,14 +4,24 @@ [mblaze](https://git.vuxu.org/mblaze) frontend in [uxn](https://wiki.xxiivv.com/site/uxn.html) and [crystal](https://crystal-lang.org)

## build and install -1. [Configure mblaze](https://git.vuxu.org/mblaze/about/man/mblaze-profile.5) +1. [Install and configure mblaze](https://git.vuxu.org/mblaze/about/man/mblaze-profile.5) 2. Install [uxn](https://git.sr.ht/~rabbits/uxn) and [crystal](https://crystal-lang.org/install/) -3. Edit [conf.cr](./conf.cr) and probably the `handle` function in [mread](./mread) +3. Edit [config.cr](./config.cr) and probably the `mhandle` function in [taro-reader](./taro-reader) 4. Run [build.sh](./build.sh) 5. Copy `taro-ctl` to your path ## usage +`taro` is a multi-window MUA with three types of windows: + +- `taro-ls`: the main `uxn` window where you will check your inbox and organize your mail +- `taro-reader`: a terminal window that runs a shell script to read mail +- `taro-compose`: a terminal window running `mcom` + +The windows are managed by a master program, `taro-ctl`, which talks to them with `messages` (see below). + +### mail management + The `taro-ls` window has three main areas: - Mailboxes: it's assumed by taro-ctrl that your inbox is named INBOX, and it exists; it's put first, and the rest are shown in alphabetical order

@@ -31,18 +41,35 @@ - trash [`Del`]: move mail to the Trash folder, unless it's already in the Trash, in which case it's deleted

There is a resize handle in the bottom right - clicking and dragging it resizes the window. +### reading mail + +Reading mail is currently done in a terminal that pipes the mail content into `less` and gives some keybind options: + +- `q`: quit +- `r`: reply +- 'f': forward +- 'o': open an attachment - you are presented with the MIME structure of the mail with parts numbered and prompted to select a number to open. The programs to open each mimetype are in the aforementioned `handle` function of the script. +- `s`: save an attachment - like `o` but selecting a MIME part saves it to the folder `TARO_DOWNLOADS` in `config.cr` + +The attachment actions loop until you enter nothing or a non-numeric value. The whole script loops until you quit. + +### writing mail + +Writing mail is currently done by opening a terminal and calling `mcom`, which lets you compose in your `EDITOR` of choice and prompts for additional action. + +### crypto + If you try to decrypt/sign with either `pinenetry-tty` or `pinentry-curses`, GPG will attach it to the stdio of `taro-ctl`, not the terminal window where you are viewing/composing mail. Use a graphical pinentry program instead. ## TODO -- Make `mread` more user friendly - Implement keybinds for changing mailbox, selecting/scrolling mail, resizing - Add options to search for case-insensitivity and including body content - Add option to refile to copy instead of move - Flag/star messages? I never use this fature if IMAP... - Real `uxn` implementaions of reader/compose windows? Probably overkill -## messages +## messages (IPC) Messages are in the format `[1][2:3][...]`:

@@ -53,7 +80,7 @@

Even messages go from `taro-ctl` to the `uxn` windows. - `0`: mailbox list (truncated to 4k - this should be enough) -- `2`: list mail in current mailbox (or search results) (truncated to 32k - if you need more, use search) +- `2`: list mail in current mailbox (or search results) (truncated to 32k - if you need more, use search) Odd messages go from the `uxn` windows to `taro-ctl`.
M build.shbuild.sh

@@ -1,5 +1,5 @@

#!/bin/sh -uxnasm taro-ls.tal taro-ls.rom +uxnasm taro-ls.tal taro-ls -crystal build taro-ctl.cr+crystal build taro-ctl.cr
D conf.cr

@@ -1,3 +0,0 @@

-TARO_LIB = "/home/nilix/src/taro/" -READER_PROG = "st -t \"taro-reader\" -e #{TARO_LIB}/mread" -COMPOSE_PROG = "st -t \"taro-compose\" -e mcom"
A config.cr

@@ -0,0 +1,8 @@

+# where the rom and scripts will live +TARO_LIB = "/home/nilix/src/taro" +# where attachments are saved +TARO_DOWNLOADS = "/home/nilix/tmp" + +# terminal commands to wrap reading and writing mail +READER_PROG = "TARO_DOWNLOADS=#{TARO_DOWNLOADS} LESSKEYIN=#{TARO_LIB}/lesskey st -t \"taro-reader\" -e #{TARO_LIB}/taro-reader" +COMPOSE_PROG = "st -t \"taro-compose\" -e mcom"
A lesskey

@@ -0,0 +1,5 @@

+r quit r +f quit f +o quit o +s quit s +q quit q
D mread

@@ -1,74 +0,0 @@

-#!/bin/sh - -mhandle() { - case $2 in - text/html) - cp $1 ${1}.html - netsurf ${1}.html - rm ${1}.html;; - image/*) - qiv $1;; - audio/*|video/*) - mpv $1;; - pgp/encrypted) - gpg --decrypt $1;; - application/vnd*) - libreoffice $1;; - application/pdf) - zathura $1;; - esac -} - -_mread() { - local META - mflag -S ${this} - local this=$(mseq $@) - while true; do - mshow ${this} - - while true; do - META="" - printf "\n" - mshow -t - printf "\n" - printf "[1..n] view attachment (add s to save)\n" - printf "[r]reply, [f]orward, [q]uit\n" - read cmd - - case ${cmd} in - 1|2|3|4|5|6|7|8|9|10|\ - 11|12|13|14|15|16|17|18|19|20) - attachment=$(mktemp) - mshow -O . ${cmd} > ${attachment} - mimetype=$(mshow -t | grep ${cmd}: | awk '{print $2}') - mhandle ${attachment} ${mimetype} - rm ${attachment};; - 1s|2s|3s|4s|5s|6s|7s|8s|9s|10s|\ - 11s|12s|13s|14s|15s|16s|17s|18s|19s|20s) - mshow -x . ${cmd%s};; - q|quit) - META=q;; - r|reply) - META=r;; - f|forward) - META=f;; - esac - - [ ! -z "${META}" ] && break; - done - this="." - case ${META} in - f) - mfwd ${this};; - r) - mrep ${this};; - q) - return;; - *) - ;; - esac - mseq -f | mseq -S - done -} - -_mread $@
M taro-ctl.crtaro-ctl.cr

@@ -2,7 +2,7 @@ require "process"

require "io/memory" require "io" -require "./conf" +require "./config" MSG_SIZES = { 0_u8 => 4096_u16,

@@ -44,13 +44,11 @@ end

class ChildWindow @@msg : Channel(Mesg) = Channel(Mesg).new - @@id : UInt16 = 0_u16 def self.msg @@msg end - - @id : UInt16 + @lifetime : Channel(UInt8) @stdout_w : IO::FileDescriptor @stdout_r : IO::FileDescriptor

@@ -64,22 +62,20 @@ def initialize(w : WinType = WinType::LIST, arg : String = "")

@stdout_r, @stdout_w = IO.pipe @stdin_r, @stdin_w = IO.pipe @lifetime = Channel(UInt8).new - @id = @@id - @@id += 1 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", "#{TARO_LIB}/#{uxnrom}.rom"] case w when WinType::LIST then spawn do - Process.run(command: "uxnemu", args: uxnargs, input: @stdin_r, output: @stdout_w, error: Process::Redirect::Inherit) + Process.run( + command: "uxnemu", + args: [ "-s", "1", "taro-ls" ], + chdir: TARO_LIB, + input: @stdin_r, + output: @stdout_w, + error: Process::Redirect::Inherit) @lifetime.send(0) end spawn do

@@ -99,10 +95,6 @@ @@msg.send(Mesg.new(1_u8, MblazeProxy.mailbox.to_slice))

end end - end - - def id - @id end def lifetime
M taro-ls.taltaro-ls.tal

@@ -243,7 +243,11 @@

JMP2r @send_reader ( -> ) - + + ( reset the mouse state since if a window opens over the uxn window mid-click + and steals focus, the click never releases until we click the button again ) + + #00 .Mouse/state DEO READ_MAIL .Console/write DEO #0002 SWP .Console/write DEO .Console/write DEO .list LB_SELECT_IDX LDZ2 INC2 SWP .Console/write DEO .Console/write DEO

@@ -252,6 +256,10 @@ JMP2r

@send_compose ( -> ) + ( reset the mouse state since if a window opens over the uxn window mid-click + and steals focus, the click never releases until we click the button again ) + + #00 .Mouse/state DEO COMPOSE_MAIL .Console/write DEO #00 .Console/write DEOk DEO ( message size is 0, no payload )
A taro-reader

@@ -0,0 +1,79 @@

+#!/bin/sh + +mhandle() { + case $2 in + text/html) + cp $1 ${1}.html + netsurf ${1}.html + rm ${1}.html;; + image/*) + qiv $1;; + audio/*|video/*) + mpv $1;; + pgp/encrypted) + gpg --decrypt $1;; + application/vnd*) + libreoffice $1;; + application/pdf) + zathura $1;; + esac +} + +save_attachments() { + while true; do + printf "\n" + mshow -t + printf "\n" + + printf "select an attachment to save: " + read n + case ${n} in + ''|*[!0-9]*) return ;; + *) file=$(mshow -x . ${n}); mv ${file} ${TARO_DOWNLOADS} ;; + esac + done +} + +open_attachments() { + while true; do + printf "\n" + mshow -t + printf "\n" + + printf "select an attachment to open: " + read n + case $n in + ''|*[!0-9]*) return ;; + *) attachment=$(mktemp) + mshow -O . ${n} > ${attachment} + mimetype=$(mshow -t | grep ${n}: | awk '{print $2}') + mhandle ${attachment} ${mimetype} + rm ${attachment};; + esac + done +} + +mread() { + local META + mflag -S ${this} + local this=$(mseq $@) + local action="q" + while true; do + (mshow ${this} ; printf "\n"; mshow -t ${this}; printf "\n" ; printf "[o]pen or [s]ave attachments\n" ; printf "[r]reply, [f]orward, [q]uit\n")| less --mouse + + case $? in + 113) #q + break;; + 102) #f + mfwd ${this};; + 114) #r + mrep ${this};; + 115) #s + save_attachments;; + 111) #o + open_attachments;; + esac + done +} + +mread $@