You are browsing as a guest. Sign up (or log in) to start making projects!

ethmarks

@ethmarks

Joined June 13th, 2026

  • 51Devlogs
  • 4Projects
  • 3Ships
  • 45Votes
Ahoy! I'm Ethan Marks. I'm 15 years old and I'm entering my third year at my local community college. I love programming, especially web development.
Open comments for this post

3h 41m 50s logged

I finished the README, did some bugfixes and refactors, and made a demo gif using VHS.


Unless I think of more features to add, this will probably be my second-to-last devlog. I’m still planning on writing my final devlog before shipping using deci.

1
0
10
Open comments for this post

2h 58m 16s logged

I wrote a first draft of the README. I’m pretty happy with it so far. I still need to add a “How it Works” section, though.

Oh and I also expanded the help screen to add more info.

0
0
10
Open comments for this post

2h 7m 16s logged

I added undo and redo!


Basically, every mutative keystroke (e.g. space or backspace) makes a snapshot of the current lines and editor position and adds it to the history slice. When you press ctrl+z, it decrements historyIndex and replaces the current lines and cursor position with history[historyIndex]. ctrl+y does the same thing but the opposite.


Oh and I also added word-skipping cursor movement. If you press ctrl+left or ctrl+right, the cursor will move in that direction until it reaches a delimiter (e.g. a space or a punctuation). It took embarrassingly long to get it to work perfectly. There’s a bunch of little edge case behaviors for cursor caret movement that are really subtle and kinda unintuitive, but which you’re so used to from writing text on computers that you can instantly spot if it’s not quite correct.


I think that next I’ll start working on the README.

0
0
21
Open comments for this post

2h 2m 27s logged

I added markdown previewing!

Just press ctrl+p, and it’ll switch to a new screen and render the current editor content as markdown with Glamour. The screenshot for this devlog is what the current README looks like when previewed.

It obviously works best with markdown files, but I’ve been unable to make it throw an error, even when I try to render .go files and whatnot that are definitely not markdown. I guess markdown is a pretty permissive spec.

I also added goreleaser, so it should automatically build binaries and release them for each new version now. You can check it out at https://github.com/ethmarks/deci/releases.


I think that deci is pretty close to finished. I honestly can’t think of much more to add. I still need to add that undo buffer that I promised in the first devlog, and write a README and better docs, but that’s basically it. How exciting!

0
0
25
Open comments for this post

3h 33m 31s logged

I refactored the rendering code so that it doesn’t break styled content.


I realized earlier today that there was absolutely zero reason for me to use a grid data structure in the rendering logic. The rendering pipeline went something like this:

  1. input a bunch of lines
  2. create a blank 2D grid of characters, one for each character in the terminal
  3. iterate over every single cell in that grid and set it to the relevant character from the input lines
  4. join all the columns in each row of the grid together into one line each
  5. join all lines together into one big string
  6. output the string for rendering

Using an extra intermediate dimension of data storage didn’t actually do anything except use way more memory and make it very difficult to use non-ASCII characters.

So I redesigned it and the new rendering pipeline works more like this:

  1. input a bunch of lines
  2. create a slice of blank lines, one for each row in the terminal
  3. trim the relevant input line and insert it into the slice
  4. join all the lines together into one big string
  5. output the string for rendering

This way is much simpler, and also much more memory efficient i think.


Plus, the new pipleine lets me used styled text. Before, when I tried out Lipgloss’s Border feature on the help page, the border was composed entirely of â characters. Idk why. I think it because each grid cell only used the first byte and didn’t consider the invisible ANSI characters. But the new one slices it safely using Charm’s ansi package, so it’s safe to use styled lines.

I used the new pipeline to make the help page more colorful and aesthetic. I made each character of the “deci” ASCII art be a different color to distinguish them, because a friend pointed out that the c and the i are really close together so it kinda looks like it says “ded”.

Soon, I should be able to add markdown previewing. It shouldn’t even be that much work (famous last words).

0
0
14
Open comments for this post

25m 29s logged

Just a small change this devlog. I added a keybind to change the cursor shape. The default is now block (it was bar before, but that seemed kinda un-nano), and you can toggle it to bar and then underline using alt+c.

I also added optional anonymous condition functions to the keybind struct, so I can toggle whether a keybind is visible or not. For example, the “Write Out” keybind is only visible on the editor screen because there’s no reason to write out the help screen.

0
0
15
Open comments for this post

3h 27m 37s logged

I’ve added a help screen and a keybind info bar!


For the help screen, I had to majorly refactor how line data is stored. Previously, there was just one big lines slice that was instantiated from the file content, directly written to to process keystrokes, and directly read from to render the view. But now I’ve moved most of that functionality to a separate editorLines variable, and lines is now a pointer that can be hotswapped. So when the user switches to the help screen, I just change the lines pointer from editorLines to helpLines, and voila everything works. As a bonus, this modular system should make it pretty easy to add markdown previews later.

I made the ASCII art “deci” logo in the help page using the Colossal font for FIGlet, which is the same font that nano uses for the ASCII art on its home page. I think it looks pretty good.

I’m also leaning into the slogan “your second-to-last next editor”. It’s a self-deprecating play on Zed’s slogan that I made up for the first devlog. But I’m really proud of it so I put it on the website and in the help screen.


The keybind info bar was pretty simple to make. The only thing worth remarking on is that it automatically limits the displayed keybinds to the width of the terminal screen, just like nano. Speaking of which, did you know that nano has 66 keybinds? I counted. I had to stretch a terminal window across two 1080p monitors and scale the font size down to 58% in order to see all of them. Currently, deci has 3 keybinds. I’ll need to think of more keybinds, because that’s embarrassing. Maybe a toggle between block mode and bar mode for the cursor.

0
0
13
Ship

Hadronize: a quark-themed set collection game.

It has a web UI with a custom SvelteKit virtual layout engine, a polyglot CLI that runs across Node, Deno, Bun, and the browser console, a QuickJS bot sandbox, a comprehensive test suite, and more.

I’m really proud of Hadronize and hope that you enjoy it.

  • 26 devlogs
  • 118h
Try project → See source code →
Open comments for this post

26m 14s logged

Shipping

I did a few miscellaneous things like make the remote script endpoint production-ready, fix some typos across the project, and create a favicon in Inkscape.

After I write this devlog, I’m going to press the big “Ship your project!” button. If you’re a reviewer reading this: I hope you enjoy Hadronize. It’s one of my biggest projects ever, and I’m really proud of how it’s turned out.

1
0
8
Open comments for this post

1h 7m 46s logged

I published some binaries on GitHub releases and also made a webpage.


The webpage is live at https://ethmarks.github.io/deci/. I made it using the Lume Tufte theme that I made on Stardance back in June: https://stardance.hackclub.com/projects/18206. It’s still a WIP, but it doesn’t need to be complicated. I don’t think that I really need to put anything on the website other than installation instructions and some screenshots.


I just used the GOOS and GOARCH flags of go build to make the binaries. For the v0.1.0 release, I published binaries for x86 Linux, ARM MacOS, and x86 Windows. I might add support for more platforms later. Meanwhile, if I didn’t make a binary for your platform, you can always just build it from source:

git clone https://github.com/ethmarks/deci.git
cd deci
go build

I do all of my developing work on Linux, so I’ve tested deci pretty thoroughly on Linux. I do have a Windows laptop, but I’ve misplaced the charging cable for it and it’s out of battery, so I can’t test it on Windows right now. I don’t even own an Apple device, so there’s no way I can test on MacOS.

There’s a pretty good chance that you’re reading this devlog on Windows or MacOS right now. If you are, I’d really appreciate it if you could try out deci and let me know if it works.

0
0
14
Open comments for this post

2h 12m 17s logged

Scrolling! If you move the cursor all the way to the bottom of the screen, it’ll shift the viewport down. And the opposite if you move the cursor to the top.

This took forever to get right. I kept breaking other things because I had juggle three different “perspectives”: the grid of characters output to the screen, the slice of the grid that’s the viewport, and the actual lines of the file. But it all works now.


I think next I might work on getting a demo set up. Most of the CLI binaries that I’ve downloaded before have used GitHub Releases, so I guess I should figure out how to make those work.

0
0
7
Open comments for this post

1h 8m 38s logged

Line numbers! Yay! It took a few attempts to get the Lipgloss structure right. For a while, it either wouldn’t highlight the line number of the active line, or it would only highlight the line number of the active line. But I got it working in the end.

0
0
7
Open comments for this post

2h 19m 10s logged

So Lipgloss is like powerful. Wow.

I was using Lipgloss to style the status bar (more on that in a bit), and I took some time to actually read through the docs.

I’d used the picocolors before, which is a JS package that makes working with ANSI codes easier. I had assumed that Lipgloss was kind of like that: you just type lipgloss.Blue rather than \x1b[34m. But it can do all sorts of stuff like borders and padding and centering and compositing and enumeration and like a bajillion other things. I don’t understand how the Lipgloss codebase is only ~12,000 lines; based on how powerful it is, it feels like it should be much bigger.


Anyways, I added active line highlighting and a status bar. Right now, I’ve just made the status bar barf out info about the most recent keypress. For example:

  • “inserted ‘a’ at 4:2”
  • “split line 4 to line 5”
  • “merged line 5 with 4”
  • …et cetera

I might decide to make the status bar a bit less talkative later, but for now it’s useful for debugging.


Next, I’m going to work on adding line numbers. I also might decide to refactor the text rendering to use Lipgloss layers.

1
0
47
Open comments for this post

1h 45m 42s logged

I’ve found something that I really like about Go compared to TypeScript: you don’t need to import identifiers (e.g. functions) from other files if they’re all part of the some package.

I did a big refactor to split the 400-line behemoth main.go into a handful of smaller files. I was fully expecting to have to import each and every constant, type, and function between files. But I didn’t have to! Because every file is part of the main package, they all use the same namespace or something. I defined the statusMsg struct in update.go, but I can just instantiate a statusMsg literal in file.go without any imports or anything! This is a really cool language feature. 10/10.


Anyways, apart from the big refactor, I did the following:

  • the cursor is now the actual terminal cursor rather than a fake drawn-on cursor.
  • if you use left arrow at the start of a line, the cursor moves to the end of the line above.
  • if you use right arrow at the end of a line, the cursor moves to the start of the line below.
  • delete! It’s exactly like backspace but in the opposite direction.
  • tab! As mentioned, deci operates on a strict “1 character = 1 byte = 1 column’ basis because I don’t wanna deal with Unicode, so properly implementing tabs was out of the question. Instead, I just made the tab key instantly insert 4 spaces.

None of this stuff was on last devlog’s list of features to implement. I just kept noticing that these behaviors were missing while playtesting, so I implemented them. Next up is the aesthetic stuff like the status bar that I promised last devlog.

1
0
10
Open comments for this post

3h 20m 22s logged

Hi again! The past three hours have been a manic frenzy of adding features. I’m starting to get the hang of Go. I’m not used to working so quickly, but working on this project is surprisingly exciting.


New features:

  • backspace! If you press backspace, it’ll either delete the character immediately before your cursor, or if you’re at the beginning of a line, it’ll merge current line with the previous one and then shift all other lines upwards.
  • enter! If you press enter, it’ll bifurcate the current line and split the right half onto a new line.
  • the cursor will now stop going out of bounds. It automatically clamps the mouse X position to the max length of the current line.
  • the top row is now reserved for a nano-style header that currently says deci 0.0.1 on the left and by @ethmarks on the right.
  • the cursor now highlights the character under it rather than replacing it with a solid white square.
  • plus lots of bugfixes, mainly fixing bugs that I added while adding the other features mentioned in this list.

Features I want to add next:

  • highlighting the active line by lightening the background color
  • a status bar
  • line numbers
  • a keybind info bar

Oh, and I’ve decided that deci is ASCII-only. Go is weird about counting characters if they occupy more than one byte, so it would be a huge pain to add support for Unicode and would probably lead to a bajillion bugs.

To make sure you understand what I mean about the ASCII thing, I’ll provide an example: the hamster emoji is 1 character, it occupies 2 columns in the terminal, and it’s made of 4 bytes. Because of the last part, len("🐹") returns 4 in Go, so any string with a hamster emoji in it will appear to have 3 more characters and occupy 2 more columns than it actually does.

Making sure that the code reliably distinguishes between those three very similar concepts would be really challenging, and the only benefit would be that you could use emojis and non-Latin characters in deci. I don’t really think that it’s worth it.


deci is shaping up shockingly quickly. I almost could have written this devlog in deci, though the lack of horizontal or vertical scrolling would probably prevent me from actually writing the full thing.

0
0
8
Open comments for this post

4h 2m 55s logged

I stayed up late into the night yesterday reading docs for Go and Bubble Tea. Here are the ones I read:

So far, my overall impressions are “wow, Go kinda sucks compared to TypeScript”. Maybe it’s just that I’m only scratching the surface and I’ve yet to see the true advantages of Go, but so far I am unimpressed. It’s just much more restrictive and much less expressive than TypeScript while simultaneously somehow being more prone to runtime panics, at least from my small amount of experience.


Anyways, I’ve also gotten a decent amount of work done. deci can now kind of edit files. Watch the video below for a demonstration.

Things that work:

  • reading files
  • creating files if they don’t exist
  • transforming the lines of a file into a slice (Go’s version of dynamic-length arrays) of strings
  • displaying the lines on screen
  • moving the cursor around
  • displaying the cursor
  • preventing the cursor from going out of bounds
  • inserting characters onto the current line at the cursor position
  • displaying a line of status text
  • writing lines to the file

Things that might seem like they would work based on the list above, but actually don’t:

  • backspaces
  • creating new lines (aka enter)
  • scrolling through a file
  • displaying the cursor when it isn’t directly over an existing character
  • preventing the cursor from going out of bounds when it goes above or below a line that’s longer than its neighbors
  • other subtle cursor behaviors that are difficult to describe that we take for granted in editors but are surprisingly difficult to implement

There’s still a lot to do. It might seem like I’ve made a lot of progress but I doubt that I’m even 10% of the way done.

2
0
32
Open comments for this post

46m 4s logged

Are you tired of using actual editors, but nano is still too feature-rich and stable for you?

Introducing deci, your second-to-last next editor

I’m making this because I want to learn the Go lang. I’ve heard that Bubble Tea is the best of the best for making TUIs, but I’ve never used it because it requires using Go. Since I want to learn Go anyways, I figured that I’d give Bubble Tea a shot. I was trying to think of what kind of TUI to make, and a nano/vim/helix style text editor was the first thing that sprang to my mind.


Obviously, my editor won’t have as many features as even nano (which is quite a low bar). I intend to have text rendering, file reading and writing, character insertion and deletion, an undo buffer, and maybe some other stuff.

Don’t hold me to this, but I might even implement markdown previewing via wrapping the Glamour utility.

The goal that I’m setting for myself is to write my final devlog for deci using deci itself.

Anyways, the name deci comes from the Metric prefix Deci, meaning 10^-1. nano comes from Nano, meaning 10^-9. It’s a bit of wordplay:

  • The Deci prefix is far larger than Nano, and I expect that the deci binary will be much heavier than the nano binary because it has to bundle the Go runtime which is like 3-10 MB.
  • Deci is not a very commonly used prefix. There’s basically nothing that uses Deci other than decibels and deciliters, and the “deci” in both of those terms is easy to miss (did you know that decibels are based on Bels? Also, the wikipedia page for Bel redirects to decibel). Nano, on the other hand is extremely common; everybody knows about nanobots and that “nano” means “very small”. Likewise, nobody except you, me, and a handful of other people know about deci editor, but tons of people know about nano.

Anyways, all that I’ve done so far is come up with a plan, write the stub README, and make the terrible banner that you see below.

Next, I’m going to install Go and start reading the Bubble Tea docs.

0
0
12
Open comments for this post

5h 8m 13s logged

Revised Readme (again)

Still working on the README. I think that Hadronize is more or less ready to ship now, but there’s probably still a bit more polishing I can do.


In my other Stardance projects, I’ve gotten really positive feedback on my READMEs, so apparently my writing style and README format of choice is a winning combination. I’ve been referencing my past READMEs and the Stardance README guide a lot while writing this one.


The bulk of what I added was the How it Works section, which explains some of the technical details and design choices that I made. It’s a dense topic so it’s obviously a long section. At first it was just a wall of text, even when I tried to break it up with lists and subheadings. So I spent about half an hour taking screenshots and editing them in GIMP until I had decorative images that I was satisfied with for each subsection. I think that drop shadows on transparent backgrounds look really cool in README images, so I used GIMP’s drop shadow filter to add them to my screenshots (in addition to cropping, rounding corners, et cetera). I kept fiddling with the drop shadow settings and I didn’t want to go back and redo the images that I’d already done, so the shadows are kind of inconsistent, which really irks me but I don’t think is very noticeable.

I also added a Running Locally section and fixed a few typos throughout the README.


Lastly, I did a bit of work on the home page. I added a big screenshot below the intro paragraph, thanks to feedback from the awesome @Luksus, whose project you should totally check out.

0
0
14
Open comments for this post

2h 44m 15s logged

Revised README

I worked on updating and basically completely rewriting the README to something more polished. I still need to add more sections and revise what I have, but I think that it’s alright. I’m trying to strike a balance between not having enough content and being a wall of text. It’s also surprisingly difficult to come up with bullet points for the features list.

After I finish up the README, I’m going to redesign the home page a bit. After that, I think I might be ready to ship.

0
0
14
Open comments for this post

6h 27m 50s logged

How to play page

I wrote a page that explains how to play, assuming zero knowledge. I think that this’ll be helpful for onboarding, because this way they learn the rules at the same time as they learn how to use the UI, rather than reading the abstract and theoretical rules and then trial-and-erroring their way through the UI.


The actual writing part took a few hours, and most of it was revision and trying to find better ways to phrase things. It’s nearly 1000 words, meaning I could turn it in for an essay assignment and not fail the word count, which is funny.

But what also took a lot of time was making the visual aid. I had to record myself performing the same action in the UI many times to get a perfect take, and then I had to craft an ffmpeg command to crop and trim it because I refuse to use graphical video editors. Also my recording software kept stuffing H.264 video data in a webm container, which made ffmpeg freak out because that file is technically corrupted. I also had to figure out how to screen record on my phone to get a tap indicator, which I’d never done before.

You can read the page here: https://ethmarks.github.io/hadronize/how

0
0
15
Loading more…

Followers

Loading…