Skip to content

Latest commit

 

History

2 Commits

Folders and files

NameName
Last commit message
Last commit date
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Worst Text Editor Ever

A working line editor in 119 lines of ISO C23, written to be as unreadable as the standard permits while still compiling clean and doing its job.

It edits text. It has append, insert, delete, print, substitute, read and write. It handles files of any size and lines of any length. It also has exactly one error message, no undo, no unsaved-changes warning, and no way to look at a single line. Both halves of that are on purpose.

$ wtee notes.txt
*a
The quick brown fox
jumps over the lazy dog
.
*p
1	The quick brown fox
2	jumps over the lazy dog
*w
2
*q

The build system is 138 lines. The program is 119. This is also on purpose.

Intent

This is an obfuscation exercise, not a tool. The goal was code that is hostile to read but honest to run — no undefined behaviour, no memory leaks, no "it works on my machine". Every construct below is load-bearing; nothing is dead code added for decoration.

Digraphs, because trigraphs are gone. C23 removed trigraphs (N2940), so ??< is no longer available to anyone. Digraphs survived. Braces are <% and %>, subscripts are <: and :>, and preprocessor directives use %: for # and %:%: for ##. All of it is hidden behind macros named OPEN, SHUT, AT() and WELD(), so the digraphs aren't visible until you preprocess the file.

A seven-level pointer. The line buffer is a char **, but it is never named directly. O1 through O5 form a chain of addresses terminating in static char *******O5, and every access goes through #define l1 (*****NECRO(5)) — five dereferences of a seven-star pointer, reached through a token-pasting macro. realloc works correctly through the chain, which is the genuinely upsetting part.

Function pointers past the point of usefulness. Command dispatch is a 128-entry table of int (*)(char *) reached via:

static int(*(*(*top(void))(void))(int))(char*);

A function returning a pointer to a function returning a pointer to a function returning a pointer to a function returning int. The call site reads top()()(c)(args). None of the intermediate levels do anything.

Everything else. Indentation uncorrelated with nesting. Comma operators where statement sequences belong. Numeric constants in binary. A goto inside a loop that could be a continue. OOPS is a macro that expands to a return. main ends with return free(l1),free(FN),0;.

C23 features used, since the point was to use them: nullptr, constexpr, auto type inference, typeof, [[noreturn]], [[maybe_unused]], single-argument static_assert, and strdup — which only became standard library in C23.

Building

cmake -B build
cmake --build build
ctest --test-dir build --output-on-failure

Needs CMake 3.21 or newer (the first release with C_STANDARD 23) and a compiler with C23 support. GCC 13 and earlier spell the standard -std=c2x; CMake translates that for you, which is why the build file sets C_STANDARD 23 rather than hardcoding a flag. Tested on GCC 13 and GCC 14. Clang 18+ should work. MSVC does not, and is not supported.

Installing puts the binary somewhere useful:

cmake --install build --prefix ~/.local

The build suppresses -Wmisleading-indentation. Five instances of it are intentional. It is otherwise warning-clean under -Wall -Wextra.

The build system

Disproportionate by design. A 119-line joke does not need a feature probe, a smoke test and an in-source-build guard, which is precisely why it has them. Everything in it does something real, though — none of it is padding.

Options

Option Default Effect
CMAKE_BUILD_TYPE Debug Set automatically for single-config generators if you don't pass one, since the CMake default of no build type means no optimisation and no debug info. Left alone for Visual Studio and Ninja Multi-Config, which choose at build time.
BUILD_TESTING ON Registers the smoke test with CTest. -DBUILD_TESTING=OFF removes it.
CMAKE_INSTALL_PREFIX platform default Where cmake --install puts things. --prefix ~/.local for a per-user install.
CMAKE_EXPORT_COMPILE_COMMANDS forced ON Writes compile_commands.json. Without it clangd has no idea what -std this file needs, and the digraphs confuse it completely.

WTEE_SOURCE near the top of CMakeLists.txt names the source file. It's a plain variable, not a cache entry, so edit the line rather than passing -D. Change it if your file is called worst_text_editor_ever.c.

What it does beyond building

Version range. cmake_minimum_required(VERSION 3.21...4.2) — 3.21 is the genuine floor, 4.2 is the newest version whose policy defaults were tested. The range form means people on distro CMake can still configure the project, while newer CMake still uses modern policies.

A C23 feature probe. Compiles a throwaway program using nullptr, constexpr, auto, typeof, attributes and strdup before building anything. If it fails, configuration stops with a message naming what's missing. This is the one piece worth stealing: without it, a compiler lacking typeof desynchronises the parser and produces dozens of errors on the wrong lines, and the digraphs make the result completely unreadable.

An in-source build guard. Stops cmake . from scattering CMakeCache.txt, CMakeFiles/ and object files next to your .git.

A smoke test. Drives a real session — append, insert-before, substitute, delete, write — and diffs the resulting file against a known-good one. It covers 1-based numbering, insert positioning, first-match-only substitution and range deletion, which are exactly the things this code invites you to break. The test input and the stdin-redirect helper are generated into the build directory at configure time, so one test doesn't earn a tests/ directory.

A summary line. Prints compiler, version, standard and build type at the end of configure, so you can see what you actually got.

CLion

The wtee run configuration works out of the box. For the CTest ones:

  1. Tools → CMake → Reset Cache and Reload Project. Tests registered by add_test only show up in CLion after a reload; adding them mid-session isn't picked up.
  2. Build wtee at least once first. The test invokes cmake -P rather than a target binary, so CLion can't infer that it needs to build the editor before running the test. If the binary doesn't exist yet the test fails with a confusing error rather than an obviously missing file.
  3. To fix that permanently: Edit Configurations → the CTest configuration → Before launch → Add → Build → target wtee.

If it still won't go, run ctest --test-dir cmake-build-debug --output-on-failure in the terminal. That tells you whether the problem is the test or the IDE, which is worth knowing before spending an evening on it.

Files

File
wtee.c The entire program
CMakeLists.txt Build system. Longer than the program.
MANUAL.md Full manual — every command, in detail
README.md The README file you're reading right now
.gitignore The gitignore file
LICENSE The license (MIT)

Start with MANUAL.md. It documents the behaviour that was verified against the compiled binary rather than the behaviour the commands look like they should have, and the difference is larger than you'd expect.

Disclaimer

This was written by Claude Opus 5, an AI model made by Anthropic, from a prompt asking for the most unreadable C23 program that could still be called a text editor. The code was compiled and the commands were exercised before delivery, but it has had no review beyond that and no use beyond that.

Treat it accordingly. It is a joke that happens to work — fine to read, run and laugh at, unwise to trust with anything you would be upset to lose. It has one smoke test, which is one more than it deserves, and no coverage beyond that. The q command discards your buffer without asking.

Do not copy patterns from wtee.c into real code. Every technique in it is one that a maintainer would be right to reject in review, and that is the whole point of it. CMakeLists.txt is the exception — that one is fine to steal.


This project is licensed under the MIT License (MIT). See the LICENSE file for details.

About

wtee — a line-oriented text editor, written in ISO C23, that does the absolute minimum required to qualify for the noun. Written by Opus 5.

Topics

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages