Skip to content

Latest commit

 

History

1 Commit

Folders and files

NameName
Last commit message
Last commit date
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Aditya's Code Editor

Author: Aditya Yadav (@adityayadav07-ux)

A working desktop code editor, built from scratch in Python/Tkinter — no CodeMirror, no Monaco, no Pygments. Multi-tab editing, a hand-written regex tokenizer for syntax highlighting, line numbers, find & replace, dark/light themes, and a Run button that actually compiles and executes Python, C, and Java files and streams the output into a built-in console.

Why build this from scratch

Every popular "build your own code editor" tutorial wraps an existing component (CodeMirror, Monaco, Ace). That teaches you how to configure someone else's editor, not how one works. This project intentionally writes its own tokenizer and its own compile/run pipeline, because that's where the actual learning is — and because "I understand how syntax highlighting and code execution work under the hood" is a much stronger interview answer than "I imported a library that does it."

Features

  • Multi-tab editing with unsaved-changes (*) indicators
  • Syntax highlighting for Python, C, and Java — a hand-written, single-pass regex tokenizer (see syntax_highlighter.py), not a third-party library
  • Line numbers, synced scrolling, auto-indent (continues the previous line's indent, adds one level after a line ending in :)
  • Find & Replace (Find Next, Replace, Replace All)
  • Dark / light theme toggle
  • Run Current File (F5) — compiles (for C/Java) and runs the active file in a background thread (so the UI never freezes), streaming stdout/stderr into a console panel at the bottom
  • Undo/redo, standard file operations (New/Open/Save/Save As)

Architecture — logic separated from GUI on purpose

syntax_highlighter.py   <- pure tokenizer, zero GUI imports
run_manager.py           <- pure compile/run logic, zero GUI imports
theme.py                  <- color definitions
editor_app.py               <- Tkinter widgets, wires the above together
main.py                      <- entry point

This mirrors the same pattern used in projects 2 and 4 of this portfolio: keep the logic that actually needs to be correct completely separate from the UI, so it can be tested without a display. editor_app.py is intentionally "dumb" — it doesn't decide how to tokenize or how to run code, it just calls the tested modules and displays what they return.

Verification — what was actually tested, and what wasn't

Fully tested, with real execution (23 tests total):

  • tests/test_syntax_highlighter.py (14 tests) — verifies keywords inside strings/comments are correctly NOT re-tokenized as keywords, multi-line C block comments work, function-call detection works, token character-offsets are exactly correct
  • tests/test_run_manager.py (9 tests) — actually compiles and runs real C programs with gcc, and actually executes real Python scripts — checks real computed output (e.g. sum 1 to 100 = 5050 from both a Python and a C program), and confirms compile errors and non-zero exit codes are correctly reported as failures

Not testable in the environment this was built in: the Tkinter GUI itself. That sandbox has no display server, so editor_app.py could not be launched and clicked through automatically. It was carefully reviewed by hand instead, and one real bug was caught and fixed this way: Find & Replace edits happen programmatically and don't fire Tkinter's normal <KeyRelease> event, so syntax highlighting and the modified-file indicator would have silently gone stale after a replace — fixed by explicitly re-triggering them after any Find & Replace edit.

You should click through every feature yourself once before calling this "done" — open a .py and a .c file, edit them, run them, try Find & Replace, toggle the theme. That hands-on pass is also exactly what you'll want to be able to describe in an interview.

A known limitation (stated honestly)

Programs that call input() (Python) or scanf() (C) and wait for interactive keyboard input will hang until the 10-second timeout, because the Run feature captures output rather than connecting to a live interactive terminal. This is a real, common limitation of simple "run and capture output" designs — a proper fix means embedding a pseudo-terminal (PTY), which is meaningfully more complex and was left out of this MVP on purpose. Test your programs with hardcoded/no input, or note this limitation if a grader/interviewer tries a program that reads input.

Run it

Requires Python 3.8+ and Tkinter (bundled with most Python installs on Windows/macOS; on Linux: sudo apt install python3-tk if missing). Running C files also requires gcc on your PATH; running Java files requires a JDK (javac/java).

git clone https://github.com/adityayadav07-ux/CodeEditor.git
cd CodeEditor
python3 main.py

In VS Code

Open the folder, open main.py, press F5 to launch it (uses the included .vscode/launch.json).

Run the tests

python3 -m unittest tests/test_syntax_highlighter.py -v
python3 -m unittest tests/test_run_manager.py -v

All 23 tests should pass. test_run_manager.py needs gcc on your PATH for its C tests to run.

Project structure

CodeEditor/
├── main.py
├── editor_app.py            # all Tkinter UI code
├── syntax_highlighter.py     # tokenizer (tested, no GUI deps)
├── run_manager.py             # compile/run logic (tested, no GUI deps)
├── theme.py                    # dark/light color palettes
├── tests/
│   ├── test_syntax_highlighter.py
│   └── test_run_manager.py
├── .vscode/
│   └── launch.json
├── .gitignore
└── README.md

Design notes (the "why")

  • Single combined regex, not multiple passes: syntax_highlighter.py builds one big alternation pattern ((?P<COMMENT>...)|(?P<STRING>...)|...) and scans once with re.finditer. Order in the pattern matters — comments and strings are listed first so a # inside a string literal is correctly consumed as part of the STRING match, never re-considered as the start of a comment.
  • Background thread for Run: without threading, clicking Run would freeze the entire editor window until the program finished (Tkinter is single-threaded for UI). run_manager.run_file() runs on a worker thread, and the result is marshaled back via self.after(0, ...) — the standard safe way to touch Tkinter widgets from a background thread's result.
  • Character-offset tagging: the tokenizer returns plain character offsets into the text (not line/column pairs), because Tkinter's Text widget accepts index strings like "1.0+123c" (123 characters after position 1.0) directly — no manual line/column math needed.

Possible extensions (not built — noted honestly)

  • A pseudo-terminal (PTY) for real interactive input()/scanf() support
  • Autocomplete / IntelliSense
  • Multi-line (triple-quoted) Python string highlighting
  • A file-explorer sidebar for multi-file projects
  • Bracket matching / auto-closing brackets

License

MIT — free to use, learn from, or build on.

About

No description, website, or topics provided.

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages