shithub: irc.myr

Download patch

ref: cc395f1b257d9e7ec575ef4b3f49bbdea06277f7
parent: 1883b6157dbc02a03e4a678aa0ecdf8bee211129
author: Ori Bernstein <ori@eigenstate.org>
date: Sat Nov 11 08:42:51 EST 2017

Fixes and cleanups.

--- a/irc.myr
+++ b/irc.myr
@@ -29,6 +29,7 @@
 ;;
 
 type server = struct
+	id	: std.size
 	fd	: std.fd
 	user	: byte[:]
 	nick	: byte[:]
@@ -136,7 +137,9 @@
 		| "376":	srvmsg(irc, args)
 		| "NOTICE":	srvmsg(irc, args)
 		| "332":	topic(irc, srv, args)
-		| "353":	addnames(irc, srv, args)
+		| "353":	addusers(irc, srv, args)
+		| "QUIT":	deluser(irc, src)
+		| "PART":	delchanuser(irc, srv, args)
 		| "366":	shownames(irc, [][:])
 		| "PRIVMSG":	recievemsg(irc, srv, src, args)
 		| "PING":	send(irc, srv, "PONG :{}\r\n", args[0])
@@ -189,7 +192,7 @@
 	chanmsg(irc, c, src, args[1])
 }
 
-const addnames = {irc, srv, args
+const addusers = {irc, srv, args
 	var c
 
 	if args.len != 4
@@ -202,10 +205,39 @@
 		| `std.None:    std.slpush(&c.users, std.sldup(n))
 		| `std.Some _:  /* ignore */
 		;;
-		c.gutter = std.max(c.gutter, n.len + 1)
+		c.gutter = std.max(c.gutter, n.len + 2)
 	;;
 }
 
+const deluser = {irc, srv, user
+	var nick
+
+	for c : srv.chan
+		match std.strfind(sender, "!")
+		| `std.Some i:	nick = std.sldup(sender[:i])
+		| `std.None:	nick = std.sldup(sender)
+		;;
+		match std.lsearch(c.users, nick, std.strcmp)
+		| `std.None:    /* ignore */
+		| `std.Some i:  std.sldel(&c.users, i)
+		;;
+	;;
+}
+
+const delchanuser = {irc, src, args
+	if args.len == 0
+		-> void
+	;;
+	match std.strfind(sender, "!")
+	| `std.Some i:	nick = std.sldup(sender[:i])
+	| `std.None:	nick = std.sldup(sender)
+	;;
+	match std.lsearch(c.users, nick, std.strcmp)
+	| `std.None:    /* ignore */
+	| `std.Some i:  std.sldel(&c.users, i)
+	;;
+}
+
 const fd2srv = {irc, fd
 	for s : irc.srv
 		if s.fd == fd
@@ -223,12 +255,13 @@
 			-> c
 		;;
 	;;
-	new = mkchan(irc, chan, "")
+
+	new = mkchan(irc, srv, chan, "")
 	std.slpush(&srv.chan, new)
 	if srv.focus == -1
 		srv.focus = srv.chan.len - 1
 	;;
-	status(irc, new, "joined on {}\n", date.now("local"))
+	status(irc, new, "joined on {}", date.now("local"))
 	-> new
 }
 
@@ -307,7 +340,7 @@
 	])
 }
 
-const mkchan = {irc, name, topic
+const mkchan = {irc, srv, name, topic
 	var logpath, logfd
 
 	std.mkpath(irc.logdir)
@@ -369,6 +402,7 @@
 	| "help":	help(irc, sp[1:])
 	| "nick":	changenick(irc, sp[1:])
 	| "user":	changeuser(irc, sp[1:])
+	| "srv":	changeserver(irc, sp[1:])
 	| c:		status(irc, irc.self, "unknown command: /{}", text)
 	;;
 	std.slfree(sp)
@@ -410,6 +444,17 @@
 	;;
 }
 
+const changeserver = {irc, args
+	if args.len != 1
+		status(irc, irc.self, "/nick: invalid args {j= }", args)
+		-> void
+	;;
+	match findsrv(irc, args[0])
+	| `std.Some s:	irc.focus = s.id
+	| `std.None:	status(irc, irc.self, "no server '{}", args[0])
+	;;
+}
+
 const connect = {irc, args
 	var ds, srv
 
@@ -435,6 +480,7 @@
 	| `std.Ok fd:
 		srv = mksrv(irc, fd, ds)
 		if handshake(irc, srv)
+			srv.id = irc.srv.len
 			std.slpush(&irc.srv, srv)
 			if irc.focus == -1
 				irc.focus = irc.srv.len - 1
@@ -523,11 +569,14 @@
 	if irc.srv.len == 0
 		-> void
 	;;
-	if irc.focus < 0 || irc.focus >= irc.srv.len
-		irc.focus = 0
-	;;
 
-	while true
+	irc.chandirty = true
+	irc.cmddirty = true
+	for var i = 0; i < irc.srv.len; i++
+		if irc.focus < 0 || irc.focus >= irc.srv.len
+			irc.focus = 0
+		;;
+
 		srv = irc.srv[irc.focus]
 		srv.focus += delta
 		if srv.focus < 0 || srv.focus >= srv.chan.len
@@ -538,7 +587,9 @@
 			irc.focus %= irc.srv.len
 			irc.srv[irc.focus].focus = 0
 		;;
-		if srv.chan.len != 0
+		srv = irc.srv[irc.focus]
+		if srv.chan.len > 0
+			srv.chan[srv.focus].stale = false
 			break
 		;;
 	;;
@@ -553,6 +604,8 @@
 	else
 		srvidx = -1
 		idx = -1
+		irc.chandirty = true
+		irc.cmddirty = true
 		match std.strfind(irc.self.name, args[0])
 		| `std.None:	/* ok */
 		| `std.Some i:	idx = i
@@ -685,6 +738,9 @@
 			ln = getstr(irc.cmd)
 			do(irc, ln)
 			std.slfree(ln)
+			std.slfree(irc.cmd)
+			irc.cmd = [][:]
+			irc.off = 0
 		| `std.Some `termdraw.Ctrl 'n':
 			chancycle(irc, 1)
 		| `std.Some `termdraw.Ctrl 'p':
@@ -818,25 +874,28 @@
 		| `Msg (m, ln):
 			margin = c.gutter
 			width = termdraw.strwidth(t, ln)
-			height += width / (dx - margin + 1) + 1
 		| `Join user:
-			width = termdraw.strwidth(t, "#joined: ")
-			width += termdraw.strwidth(t, user)
-			height += width / (dx + 1) + 1
+			margin = termdraw.strwidth(t, "#joined: ")
+			width = termdraw.strwidth(t, user)
 		| `Part user:
-			width = termdraw.strwidth(t, "#parted: ")
-			width += termdraw.strwidth(t, user)
-			height += width / (dx + 1) + 1
+			margin = termdraw.strwidth(t, "#parted: ")
+			width = termdraw.strwidth(t, user)
 		| `Status msg:
-			width = termdraw.strwidth(t, "! ")
-			width += termdraw.strwidth(t, msg)
-			height += width / (dx + 1) + 1
+			margin = termdraw.strwidth(t, "! ")
+			width = termdraw.strwidth(t, msg)
 		;;
+		if dx - margin + 1 <=  0
+			-> void
+		;;
+		height++
+		if width > 0
+			height += (width - 1) / (dx - margin)
+		;;
 		count++
 		if height == dy
 			break
 		elif height > dy
-			off = (dx - margin)*(height - dy - 1)  + width % dx
+			off = (dx - margin)*(height - dy)
 			break
 		;;
 	;;
@@ -846,17 +905,18 @@
 	for (tm, h) : c.hist[c.hist.len - c.scroll - count:]
 		match h
 		| `Msg (m, ln):
-			(x, y) = draw(t, m, x0, y, x1, y1)
+			x = std.clamp(x0 + c.gutter - termdraw.strwidth(t, m)  - 3, 0, dx)
+			(x, y) = draw(t, m, x, y, x1, y1)
 			(x, y) = draw(t, ">", x0 + c.gutter - 2, y, x1, y1)
 			(x, y) = draw(t, ln[off:], x0 + c.gutter, y, x1, y1)
 		| `Join user:
 			(x, y) = draw(t, "#joined ", x0, y, x1, y1)
-			(x, y) = draw(t, user, x, y, x1, y1)
+			(x, y) = draw(t, user[off:], x, y, x1, y1)
 		| `Part user:
 			(x, y) = draw(t, "#parted ", x0, y, x1, y1)
-			(x, y) = draw(t, user, x, y0, y, y1)
+			(x, y) = draw(t, user[off:], x, y0, y, y1)
 		| `Status msg:
-			(x, y) = draw(t, "! : ", x0, y, x1, y1)
+			(x, y) = draw(t, "! ", x0, y, x1, y1)
 			(x, y) = draw(t, msg[off:], x, y, x1, y1)
 		;;
 		y++
--