irken: A tiny hackable full-featured IRC client

37 points by dzwdz a day ago on lobsters | 13 comments

[OP] dzwdz | a day ago

This is a graphical IRC client written in only 1290 lines of code (including blank lines and comments!) using Tcl/Tk. I would've put that in the title, but I didn't want to editorialize it.

I really ought to learn Tcl/Tk someday. I was always skeptical of how well it'd work for more complex programs, but this project seems encouraging.

creesch | 14 hours ago

IRC is a fun protocol to make something for regardless of language. In its core it is dead simple allowing you to get started with very little code as demonstrated by this client.

Even a "server" implementation is fairly simple.

Of course, making it more feature complete will also make more complex. As IRC as many older protocols and standards is more or less many standards in a trench coat with some room left over for interpenetration.

But it is a fun exercise dealing with two datastreams and just live having to parse out what you need.
Implementing terminal emulation over ssh is another one, but slightly more obtuse dealing with all ANSI characters.

As IRC as many older protocols and standards is more or less many standards in a trench coat with some room left over for interpenetration.

https://modern.ircdocs.horse/ should be a decent baseline that works for all software currently deployed, we welcome PRs to fix anything that is missing. And for the more advanced features there's https://ircv3.net/irc/

creesch | 8 hours ago

Neat, would have made things a whole lot easier for me back then :) Trawling through the various RFCs and documentation for various services was probably most of the work.

And for the more advanced features there's https://ircv3.net/irc/

You seem to be mixing in plenty of IRCV3 already. Which makes sense as a lot of those features are supported by both clients and servers.

Agree, it's a fun protocol!

As a teenager I learned C and networking by writing an IRC bot with plugin support, it also could send and receive files using XDCC

rprospero | 10 hours ago

I spent a couple of years in my twenties using Tcl/Tk as my daily driver. Oddly enough, I wish that I had encountered the language later in my life, as, even when I was a Tcl partisan, I didn't have the maturity to truly appreciate the truth: Tcl is one of the better Lisps.

[OP] dzwdz | 9 hours ago

What sort of programs did you use it for?

rprospero | 9 hours ago

I mostly used Tcl for a bunch of one off scripts where I was gluing other pieces together. The kind of program that's outgrown being a shell script, but still small enough that it would only be one file.

  • Reformatting data files to better fit gnuplot's expectations
  • A small webcomic aggregator for a bunch of comics with no RSS feed
  • Building a talking alarm clock that woke me up with instructions on what to wear and my day's schedule
  • Small desktop calculators for various formulas that showed up at work

atmosx | 4 hours ago

Well… may I propose a modern XMPP client instead? Looks like there is not much around…

jdpage | 3 hours ago

Tcl was my third-ever programming language (previously, BASIC and Python 2) and my on-ramp to C and UNIX; it's been a long while since it was my main language, but I spent many happy hours in my early teens reading the Tcler's Wiki, and learning how to structure programs by reading and modifying far more experienced programmers' code.

Tcl sort of takes the same attitude as Clojure does, and would rather give you a handful of data structures (most prominently lists, as despite "everything being a string", many of those strings are lists) and a larger number of operations on them, though it's certainly not as comprehensive as Clojure. When you want to encapsulate something, your best bet is to wrap it in some kind of opaque handle; there are a few ways to do this, the most modern being TclOO, though there's nothing stopping you from using e.g. (associative) arrays, though because of the difficulties of passing them around, using a struct-of-arrays approach is rather nicer in my opinion... the language is not very prescriptive, and things that are the same "shape" tend to compose well, to the point where one of the pre-TclOO object systems, Snit, works with objects from other object systems.

C extensions are a joy to write, and libtcl provides all of the stuff you'd write while falling prey to Greenspun's tenth rule; I don't think it'd be unreasonable to use it as a cross-platform compatibility library for a C program, and write little-to-no Tcl. If you don't like C, I've successfully written extensions in Go before; while Tcl is nominally reference-counted, handle-like things (widgets, TclOO objects, files, etc.) are manually managed, with explicit destruction, so you're not really in a position of having to make two separate GCs play nice.

The big footguns, then, are going to be the, uh, flexible approach to types, dynamic scoping, and some things needing explicit destruction. And while you CAN choose to treat, say, a dict as a list, switching back and forth between them in a hot loop will tank your performance; while "everything is a string", as a critical optimization, there's an internal structured representation, so as long as you treat a dict as a dict consistently, it'll have the performance characteristics of a hash table, but if you do a list operation on it, its internal representation will be converted to that of a list, and it'll need to be converted back to a dict again next time you use it as one. So in practice, it's better to treat values as if they have types, though that is in no way enforced.

There's also quite a bit of Tcl code out there written by non-software-engineers, as well. In a sense, that shows off the best side of the language, how accessible it is, but in another sense, you get the worst of it. Tools like Expect are a great source of this, as it has a history of being used to write test suites for embedded code.

Like many of my favorite languages, the ecosystem is a bit lacking, and my perception is that it's gotten worse over time, as things have fallen off the Internet or become less maintained. Dependency management, unless the story changed with Tcl 9 and I didn't notice, is best accomplished by vendoring.

If you want a single-file deployment independent of the system having an interpreter installed (for, say, Windows), I found the easiest option is to create a C application that calls TclZipfs_AppHook and append a zip archive of your scripts to it; I don't recommend messing with Tclkit in 2026, as the toolchain is somewhat arcane and unmaintained, and this really is a built-in improvement over that.

Also worth checking out is the Jim variant, originally from antirez but with improvements by many others, which provides a ref value which lets you opt-in to garbage collection, as well as a defer statement which can be used to do scoped resource cleanup.

This is already a monster comment, but I haven't even gotten into stuff like the event-driven I/O system (Tcl was cool before Node made it cool!), variable traces, and Tk (the most friend-shaped widget system). Tcl really is neat! It has a cool collection of features that are especially suited for *nix hacking. I'm sad I don't have more excuses to use it, but lately I've been more interested in statically-typed languages, and there are only so many hours in the day for fun coding. It'll always have a special place in my heart, though, as the first programming language I really fell in love with.

jdpage | 3 hours ago

Okay, one addendum. While I think lexical scoping is generally better for maintainability, the greatest argument I've seen for dynamic scoping is the sqlite3 Tcl extension (famously, its original form). Using prepared statements is free, in terms of readability/complexity, as the query procedure can grab the variables straight out of the caller scope, and when using sqlite's built-in iteration (think like Ruby's iteration, where you pass a block), the column names from your SELECT are available as variables. It feels very integrated with the language in a way that I've only seen with C#/LINQ, which was a huge change to the language; here it's provided as a regular extension.

donio | 22 hours ago

Looks neat although it's missing some basic stuff you'd expect from a client these days. SASL support at the very leas is a must for many users.

Made me think of Zircon, another IRC client which was the first Tcl/Tk program I used before I settled on terminal clients.

Levitating | 8 hours ago

I love that TC/Tk isn't dead yet. I think there's quite a need for a simple GUI framework in the current ecosystem.