-- Leo's gemini proxy

-- Connecting to tilde.pink:1965...

-- Connected

-- Sending request

-- Meta line: 20 text/gemini;

gmi100


I wrote about gmi100 [1] project already in few places but it definitely deserves a few words to be written on Gemini space. In short: gmi100 is a Gemini protocol Command Line Interface (CLI) client written in exactly 100 lines of C programming language, the c89 standard. It supports all basics like navigation, query and redirection but also browsing history, works with different pagers and can execute arbitrary command on currently loaded page so you can open media files easily.


Backstory


From my very first encounter with Gemini I knew that they had in protocol documentation bold statement regarding simplicity. From Gemini protocol FAQ page [2]:


> A basic but usable (not ultra-spartan) client should fit comfortably within 50 or so lines of code in a modern high-level language. Certainly not more than 100.


And at that time there where 3 clients that achieved this and where listed on Gemini software page [3]. But none of them written in C as this is not a high level language and probably no one thought it is possible. I think it was beginning of 2021.


2 years later I grow to enjoy writing small projects in C and I always wanted to write simple web client. This project idea was coming back to me from time to time. And you know when you have a good idea when it "sticks" to your brain. I was no longer browsing Gemini space at that time but the stars aligned and somehow I ended up back on protocol official website. I was curtain that after 2 years Gemini software will be saturated with many great projects. I was looking around for an example for client written in 100 lines of C so I could read it and learn from it. Somehow I assumed that at this point there will be few such solutions. But I found none. Maybe it's not possible - I pondered. From thought to curiosity. From curiosity to experiments. And so it began.


Process


At first it was rather simple. I got to the point where I could open connection and get content of page to the screen. No URI parsing, no navigation, no nothing. But it was just few lines of code giving me confidence that I will fit in 100 lines 3 essentials:


Navigation be selecting or typing URL.

Automatic redirection based on server response.

Query or so called the input.


Along the way I developed some strategies to limit number of lines. Most of them taken from forbidden bad practices like global one letter variables reused for multiple purposes and goto statements used to control program flow. Dark side of the code is strong. But I kept some error handling. I also had this idea that if at any point I run out of lines then I could get ride of all includes by moving them to compiler arguments. This felt like cheating and I'm glad that I managed to complete project without such tricks.


Anyway, eventually I got first version. But it fallen short on many other basics like browsing history and there was no way to handle other file types then text. I was not satisfied. Current version was handling everything in program memory but I realized that to make it work with arbitrary file types I have to use files. I could not afford to have one implementation for handling text responses in memory and second implementation for any other response that works on files. There was no space left. I was already at limit of 100 lines. So I redesigned the whole thing. This time everything was planed to work only on files.


After rewriting code from scratch I had implementation that was more flexible as I could now integrate it easily with other programs. This extensibility made project feel bigger than it was. Adding extra luxury commands was now possible and it finally felt like complete Gemini client as user could open any file received from server.


I struggled only with parsing links. In general in gmi100 text responses are just displayed as they are including main text/gemini MIME type. But links felt special. And I don't mean the index numbers that are required to select link. I wanted to separate description from URI to make it more readable when links are long. In the end I managed to do that but with the cost of adding yet another goto statement. Don't worry, special place in hell is already prepared for me.


Summary


All of this to answer initial question. Is it possible to write Gemini client in 100 lines of C? Indeed it is. But probably not without the power of bad programming practices.


Project was completed at 2023.07.24. Since then I actually use it as my main Gemini client and it is the reason for me to go back into browsing Gemini space. At the same time official Gemini capsule [4] and website was rewritten and moved to new domain. Good timing. I posted project on Hackernews [5] and it attracted more people than I thought. It's now also listed on official Gemini software page [3] and I'm very proud of that.


Maybe it is time for me to write Gemini server in 200 lines? No god, please no, noooooo! Anyway I have no intentions of going back to this project. It is completed \m/ [6].


> I am complete!

> Ha-aaaack!

> Yes, you are hacked

> Overflow stack

> Now I'm complete

> And my log you debug

> This code will be mine

> #include in first line

> <you_brought_me_the_lib.h>

> And now your shell compile


[1] gmi100 github repository

[2] Gemini protocol FAQ

[3] Gemini software

[4] Gemini official capsule

[5] Hackernews post

[6] Beelzeboss

-- Response ended

-- Page fetched on Sun May 19 14:34:41 2024