clide-editor 0.1.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Moinak Debnath
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -0,0 +1,89 @@
1
+ Metadata-Version: 2.4
2
+ Name: clide-editor
3
+ Version: 0.1.0
4
+ Summary: A tiny, no-frills C code editor built with Python + tkinter
5
+ Author: Moinak Debnath
6
+ License-Expression: MIT
7
+ Project-URL: Homepage, https://github.com/findstring/clide
8
+ Project-URL: Repository, https://github.com/findstring/clide
9
+ Project-URL: Issues, https://github.com/findstring/clide/issues
10
+ Keywords: editor,c,ide,tkinter,syntax-highlighting
11
+ Classifier: Development Status :: 3 - Alpha
12
+ Classifier: Environment :: Win32 (MS Windows)
13
+ Classifier: Intended Audience :: Developers
14
+ Classifier: Programming Language :: Python :: 3
15
+ Classifier: Programming Language :: C
16
+ Classifier: Topic :: Software Development
17
+ Classifier: Topic :: Text Editors
18
+ Requires-Python: >=3.9
19
+ Description-Content-Type: text/markdown
20
+ License-File: LICENSE
21
+ Dynamic: license-file
22
+
23
+ > 🤖 **Note:** This README was written by Claude AI, because the dev (me) was too lazy to write one myself. The code, however, is 100% hand-written — except for the giant list of C keywords/types/functions used for syntax highlighting, which Claude also helped generate because who's memorizing `stdc_leading_zeros` for fun.
24
+
25
+ ---
26
+
27
+ ## What is this?
28
+
29
+ CLIDE is a lightweight library based C editor with syntax highlighting, line numbers, auto-indent, and a one-key "compile and run" workflow using `gcc`. No bloat, no plugins, no 400 MB Electron shell — just a `tkinter` window that gets out of your way.
30
+
31
+ Built mostly as a personal project / learning exercise, not (yet) a serious rival to VS Code.
32
+
33
+ ## Features
34
+
35
+ - 🎨 **Syntax highlighting** for C — keywords, types, functions, strings, char literals, comments (single-line and block), numbers, and preprocessor directives
36
+ - 🔢 **Line numbers** that track scrolling and zoom
37
+ - 🔍 **Zoom in/out** with `Ctrl + Mouse Wheel`
38
+ - ⏎ **Auto-indent** — adds/removes indentation automatically after `{`, `}`, and `:`
39
+ - ▶️ **Run with F5** — compiles your file with `gcc` and runs it in a new console window
40
+ - 💾 **Open / Save / Save As** from the File menu or `Ctrl+O` / `Ctrl+S`
41
+ - 📋 **Paste-aware highlighting** — pasted multi-line code gets highlighted properly, not just the current line
42
+ - 🎨 **Style Configurator** — change background, foreground colour and also fonts
43
+ - 🖱️ Undo/redo support (unlimited undo history)
44
+
45
+ ## Requirements
46
+
47
+ - Python 3.x with `tkinter` (usually bundled with Python on Windows)
48
+ - `gcc` installed and available on your system `PATH` (for the Run feature)
49
+ - Windows — the "Run" feature and maximized window launch currently rely on Windows-specific behavior (see Limitations below)
50
+
51
+ ## Getting Started
52
+
53
+ ```bash
54
+ pip install clide-editor
55
+ python -m clide
56
+ ```
57
+
58
+ Open a `.c` file with `Ctrl+O`, write some code, hit `F5` to compile and run it.
59
+
60
+ ## Version
61
+
62
+ **v0.1.0** — early days. Things work, but expect rough edges.
63
+
64
+ ## Limitations
65
+
66
+ - **Windows-only for now.** The maximized-window launch and the `F5` run command (`cmd /k gcc ...`) both assume Windows. Running this on Linux/macOS will likely misbehave or crash on the run step.
67
+ - **Single-line-focused highlighting.** Typing re-highlights the line you're on; large structural edits elsewhere in the file (outside of paste) aren't automatically re-scanned.
68
+ - **No project/workspace support** — it's a single-file editor, not a full IDE. No multi-file tabs yet.
69
+ - **No build configuration** — compilation is a hardcoded `gcc file.c -o file.exe`, no custom flags, no Makefile support.
70
+ - **No autocomplete, linting, or error highlighting** — you find out about bugs when `gcc` yells at you.
71
+ - **No find & replace** yet.
72
+
73
+ ## To Be Featured (Roadmap)
74
+
75
+ - [ ] Cross-platform support (Linux/macOS build + run)
76
+ - [ ] Find & Replace
77
+ - [ ] Multiple tabs / multi-file projects
78
+ - [ ] Custom compiler flags / build settings
79
+ - [ ] Bracket matching + auto-close brackets
80
+ - [ ] Inline error markers from `gcc` output
81
+ - [ ] Proper packaging (so you don't need Python installed to run it)
82
+
83
+ ## Contributing
84
+
85
+ This is a small personal project, but if you spot a bug or have an idea, feel free to open an issue or PR.
86
+
87
+ ## License
88
+
89
+ See [LICENSE](LICENSE) for details.
@@ -0,0 +1,67 @@
1
+ > 🤖 **Note:** This README was written by Claude AI, because the dev (me) was too lazy to write one myself. The code, however, is 100% hand-written — except for the giant list of C keywords/types/functions used for syntax highlighting, which Claude also helped generate because who's memorizing `stdc_leading_zeros` for fun.
2
+
3
+ ---
4
+
5
+ ## What is this?
6
+
7
+ CLIDE is a lightweight library based C editor with syntax highlighting, line numbers, auto-indent, and a one-key "compile and run" workflow using `gcc`. No bloat, no plugins, no 400 MB Electron shell — just a `tkinter` window that gets out of your way.
8
+
9
+ Built mostly as a personal project / learning exercise, not (yet) a serious rival to VS Code.
10
+
11
+ ## Features
12
+
13
+ - 🎨 **Syntax highlighting** for C — keywords, types, functions, strings, char literals, comments (single-line and block), numbers, and preprocessor directives
14
+ - 🔢 **Line numbers** that track scrolling and zoom
15
+ - 🔍 **Zoom in/out** with `Ctrl + Mouse Wheel`
16
+ - ⏎ **Auto-indent** — adds/removes indentation automatically after `{`, `}`, and `:`
17
+ - ▶️ **Run with F5** — compiles your file with `gcc` and runs it in a new console window
18
+ - 💾 **Open / Save / Save As** from the File menu or `Ctrl+O` / `Ctrl+S`
19
+ - 📋 **Paste-aware highlighting** — pasted multi-line code gets highlighted properly, not just the current line
20
+ - 🎨 **Style Configurator** — change background, foreground colour and also fonts
21
+ - 🖱️ Undo/redo support (unlimited undo history)
22
+
23
+ ## Requirements
24
+
25
+ - Python 3.x with `tkinter` (usually bundled with Python on Windows)
26
+ - `gcc` installed and available on your system `PATH` (for the Run feature)
27
+ - Windows — the "Run" feature and maximized window launch currently rely on Windows-specific behavior (see Limitations below)
28
+
29
+ ## Getting Started
30
+
31
+ ```bash
32
+ pip install clide-editor
33
+ python -m clide
34
+ ```
35
+
36
+ Open a `.c` file with `Ctrl+O`, write some code, hit `F5` to compile and run it.
37
+
38
+ ## Version
39
+
40
+ **v0.1.0** — early days. Things work, but expect rough edges.
41
+
42
+ ## Limitations
43
+
44
+ - **Windows-only for now.** The maximized-window launch and the `F5` run command (`cmd /k gcc ...`) both assume Windows. Running this on Linux/macOS will likely misbehave or crash on the run step.
45
+ - **Single-line-focused highlighting.** Typing re-highlights the line you're on; large structural edits elsewhere in the file (outside of paste) aren't automatically re-scanned.
46
+ - **No project/workspace support** — it's a single-file editor, not a full IDE. No multi-file tabs yet.
47
+ - **No build configuration** — compilation is a hardcoded `gcc file.c -o file.exe`, no custom flags, no Makefile support.
48
+ - **No autocomplete, linting, or error highlighting** — you find out about bugs when `gcc` yells at you.
49
+ - **No find & replace** yet.
50
+
51
+ ## To Be Featured (Roadmap)
52
+
53
+ - [ ] Cross-platform support (Linux/macOS build + run)
54
+ - [ ] Find & Replace
55
+ - [ ] Multiple tabs / multi-file projects
56
+ - [ ] Custom compiler flags / build settings
57
+ - [ ] Bracket matching + auto-close brackets
58
+ - [ ] Inline error markers from `gcc` output
59
+ - [ ] Proper packaging (so you don't need Python installed to run it)
60
+
61
+ ## Contributing
62
+
63
+ This is a small personal project, but if you spot a bug or have an idea, feel free to open an issue or PR.
64
+
65
+ ## License
66
+
67
+ See [LICENSE](LICENSE) for details.
@@ -0,0 +1,5 @@
1
+ from .clide import main, CLIDE_VERSION
2
+
3
+ __version__ = CLIDE_VERSION
4
+
5
+ __all__ = ["main", "__version__"]
@@ -0,0 +1,4 @@
1
+ from .clide import main
2
+
3
+ if __name__ == "__main__":
4
+ main()
@@ -0,0 +1,658 @@
1
+ import tkinter as tk
2
+ from tkinter import messagebox
3
+ from tkinter import filedialog
4
+ from tkinter import simpledialog
5
+ import tkinter.font as tkfont
6
+ from tkinter import ttk
7
+ from tkinter import colorchooser
8
+ import sys
9
+ import os
10
+ import subprocess
11
+
12
+ CLIDE_VERSION = "v0.1.0"
13
+ SCRIPT_PATH = os.path.abspath(__file__)
14
+ LOGO_ICO = os.path.join(os.path.dirname(SCRIPT_PATH), "icons", "logo.ico")
15
+ COMMON_BG = "gray5"
16
+ COMMON_FG = "gray70"
17
+ COMMON_FONTSIZE = 16
18
+ COMMON_FONT = "Iosevka" # You can change it to your desired font
19
+
20
+ # This Section is fully done by CLAUDE as i dont know all the types
21
+
22
+ C_TYPES = {
23
+ "void",
24
+ "char", "signed char", "unsigned char",
25
+ "short", "short int", "signed short", "signed short int",
26
+ "unsigned short", "unsigned short int",
27
+ "int", "signed", "signed int",
28
+ "unsigned", "unsigned int",
29
+ "long", "long int", "signed long", "signed long int",
30
+ "unsigned long", "unsigned long int",
31
+ "long long", "long long int", "signed long long", "signed long long int",
32
+ "unsigned long long", "unsigned long long int",
33
+ "float",
34
+ "double",
35
+ "long double",
36
+ "_Bool",
37
+ "_Complex",
38
+ "_Imaginary",
39
+
40
+ # <stddef.h>
41
+ "size_t", "ptrdiff_t", "wchar_t", "max_align_t", "nullptr_t", # nullptr_t is C23
42
+
43
+ # <stdint.h>
44
+ "int8_t", "int16_t", "int32_t", "int64_t",
45
+ "uint8_t", "uint16_t", "uint32_t", "uint64_t",
46
+ "int_least8_t", "int_least16_t", "int_least32_t", "int_least64_t",
47
+ "uint_least8_t", "uint_least16_t", "uint_least32_t", "uint_least64_t",
48
+ "int_fast8_t", "int_fast16_t", "int_fast32_t", "int_fast64_t",
49
+ "uint_fast8_t", "uint_fast16_t", "uint_fast32_t", "uint_fast64_t",
50
+ "intptr_t", "uintptr_t", "intmax_t", "uintmax_t",
51
+
52
+ # <stdio.h>
53
+ "FILE", "fpos_t",
54
+
55
+ # <time.h>
56
+ "time_t", "clock_t", "struct tm", "struct timespec",
57
+
58
+ # <stdarg.h>
59
+ "va_list",
60
+
61
+ # <stdlib.h>
62
+ "div_t", "ldiv_t", "lldiv_t",
63
+
64
+ # <setjmp.h>
65
+ "jmp_buf",
66
+
67
+ # <signal.h>
68
+ "sig_atomic_t",
69
+
70
+ # <wchar.h>
71
+ "wint_t", "mbstate_t",
72
+
73
+ # <locale.h>
74
+ "struct lconv",
75
+
76
+ # <threads.h> (C11)
77
+ "thrd_t", "mtx_t", "cnd_t", "tss_t", "once_flag", "thrd_start_t", "tss_dtor_t",
78
+
79
+ # <stdatomic.h> (C11)
80
+ "atomic_flag", "memory_order",
81
+ "atomic_bool", "atomic_char", "atomic_int", "atomic_long", "atomic_llong",
82
+ "atomic_uint", "atomic_ulong", "atomic_ullong", "atomic_size_t",
83
+ "atomic_intptr_t", "atomic_uintptr_t", "atomic_ptrdiff_t",
84
+ "atomic_intmax_t", "atomic_uintmax_t",
85
+
86
+ # <uchar.h>
87
+ "char8_t", # C23
88
+ "char16_t", "char32_t",
89
+ "bool"
90
+ }
91
+
92
+ C_FUNCTIONS = {
93
+ # <stdio.h>
94
+ "printf", "fprintf", "sprintf", "snprintf",
95
+ "vprintf", "vfprintf", "vsprintf", "vsnprintf",
96
+ "scanf", "fscanf", "sscanf", "vscanf", "vfscanf", "vsscanf",
97
+ "fopen", "freopen", "fclose", "fflush",
98
+ "fread", "fwrite",
99
+ "fgetc", "getc", "fgets", "fputc", "putc", "fputs",
100
+ "getchar", "putchar", "puts", "gets_s",
101
+ "ungetc",
102
+ "fseek", "ftell", "rewind", "fgetpos", "fsetpos",
103
+ "fseeko", "ftello",
104
+ "feof", "ferror", "clearerr", "perror",
105
+ "remove", "rename", "tmpfile", "tmpnam",
106
+ "setbuf", "setvbuf",
107
+
108
+ # <stdlib.h>
109
+ "malloc", "calloc", "realloc", "free", "aligned_alloc", "free_sized", "free_aligned_sized", # last two C23
110
+ "atof", "atoi", "atol", "atoll",
111
+ "strtod", "strtof", "strtold",
112
+ "strtol", "strtoll", "strtoul", "strtoull",
113
+ "rand", "srand",
114
+ "abort", "exit", "_Exit", "quick_exit",
115
+ "atexit", "at_quick_exit",
116
+ "system", "getenv",
117
+ "bsearch", "qsort", "qsort_r",
118
+ "abs", "labs", "llabs",
119
+ "div", "ldiv", "lldiv",
120
+ "mblen", "mbtowc", "wctomb", "mbstowcs", "wcstombs",
121
+
122
+ # <string.h>
123
+ "memcpy", "memmove", "memcmp", "memchr", "memset",
124
+ "memccpy",
125
+ "strcpy", "strncpy", "strcat", "strncat", "strcmp", "strncmp",
126
+ "strchr", "strrchr", "strstr", "strpbrk", "strspn", "strcspn",
127
+ "strtok", "strtok_r",
128
+ "strlen", "strerror", "strcoll", "strxfrm",
129
+ "strdup", "strndup",
130
+ "memset_explicit", "memset_s", # newer / annex-K style
131
+
132
+ # <ctype.h>
133
+ "isalnum", "isalpha", "isblank", "iscntrl", "isdigit", "isgraph",
134
+ "islower", "isprint", "ispunct", "isspace", "isupper", "isxdigit",
135
+ "tolower", "toupper",
136
+
137
+ # <math.h>
138
+ "sin", "cos", "tan", "asin", "acos", "atan", "atan2",
139
+ "sinh", "cosh", "tanh", "asinh", "acosh", "atanh",
140
+ "exp", "exp2", "expm1", "log", "log2", "log10", "log1p", "logb",
141
+ "pow", "sqrt", "cbrt", "hypot",
142
+ "ceil", "floor", "trunc", "round", "lround", "llround", "nearbyint", "rint", "lrint", "llrint",
143
+ "fmod", "remainder", "remquo",
144
+ "copysign", "nan", "nextafter", "nexttoward",
145
+ "fdim", "fmax", "fmin", "fma",
146
+ "fabs", "frexp", "ldexp", "modf", "scalbn", "scalbln",
147
+ "ilogb", "erf", "erfc", "tgamma", "lgamma",
148
+ "isfinite", "isinf", "isnan", "isnormal", "signbit",
149
+ "isgreater", "isgreaterequal", "isless", "islessequal", "islessgreater", "isunordered",
150
+
151
+ # <time.h>
152
+ "time", "difftime", "mktime", "asctime", "ctime",
153
+ "gmtime", "localtime", "strftime",
154
+ "clock", "timespec_get", "timespec_getres", # timespec_getres is C23
155
+
156
+ # <wchar.h>, <wctype.h> — wide-char variants
157
+ "wcslen", "wcscpy", "wcsncpy", "wcscat", "wcsncat", "wcscmp", "wcsncmp",
158
+ "wcschr", "wcsrchr", "wcsstr", "wcstok",
159
+ "fwprintf", "fwscanf", "swprintf", "swscanf", "wprintf", "wscanf",
160
+ "iswalpha", "iswdigit", "iswspace", "towlower", "towupper",
161
+
162
+ # <setjmp.h>
163
+ "setjmp", "longjmp",
164
+
165
+ # <signal.h>
166
+ "signal", "raise",
167
+
168
+ # <assert.h>
169
+ # assert() is a macro, listed above
170
+
171
+ # <locale.h>
172
+ "setlocale", "localeconv",
173
+
174
+ # <stdarg.h> (function-like macros)
175
+ "va_start", "va_arg", "va_end", "va_copy",
176
+
177
+ # <threads.h>
178
+ "thrd_create", "thrd_join", "thrd_detach", "thrd_exit", "thrd_yield",
179
+ "thrd_sleep", "thrd_current", "thrd_equal",
180
+ "mtx_init", "mtx_lock", "mtx_unlock", "mtx_trylock", "mtx_timedlock", "mtx_destroy",
181
+ "cnd_init", "cnd_signal", "cnd_broadcast", "cnd_wait", "cnd_timedwait", "cnd_destroy",
182
+ "call_once",
183
+ "tss_create", "tss_get", "tss_set", "tss_delete",
184
+
185
+ # <stdatomic.h>
186
+ "atomic_init", "atomic_store", "atomic_load", "atomic_exchange",
187
+ "atomic_compare_exchange_strong", "atomic_compare_exchange_weak",
188
+ "atomic_fetch_add", "atomic_fetch_sub", "atomic_fetch_or",
189
+ "atomic_fetch_and", "atomic_fetch_xor",
190
+ "atomic_flag_test_and_set", "atomic_flag_clear",
191
+ "atomic_thread_fence", "atomic_signal_fence", "atomic_is_lock_free",
192
+
193
+ # <uchar.h>
194
+ "mbrtoc8", "c8rtomb", # C23
195
+ "mbrtoc16", "c16rtomb", "mbrtoc32", "c32rtomb",
196
+
197
+ # <stdbit.h> (C23) — bit utilities
198
+ "stdc_leading_zeros", "stdc_leading_ones", "stdc_trailing_zeros", "stdc_trailing_ones",
199
+ "stdc_first_leading_zero", "stdc_first_leading_one",
200
+ "stdc_first_trailing_zero", "stdc_first_trailing_one",
201
+ "stdc_count_zeros", "stdc_count_ones", "stdc_has_single_bit",
202
+ "stdc_bit_width", "stdc_bit_floor", "stdc_bit_ceil",
203
+ }
204
+
205
+ C_KEYWORDS = {
206
+ "auto", "break", "case", "char", "const", "continue",
207
+ "default", "do", "else", "enum", "extern",
208
+ "float", "for", "goto", "if", "int", "long",
209
+ "register", "return", "short", "signed", "sizeof", "static",
210
+ "struct", "switch", "typedef", "union", "unsigned", "void",
211
+ "volatile", "while",
212
+ "inline",
213
+ "restrict",
214
+ "_Bool",
215
+ "_Complex",
216
+ "_Imaginary",
217
+ "_Alignas",
218
+ "_Alignof",
219
+ "_Atomic",
220
+ "_Generic",
221
+ "_Noreturn",
222
+ "_Static_assert",
223
+ "_Thread_local",
224
+ "alignas",
225
+ "alignof",
226
+ "bool",
227
+ "true",
228
+ "false",
229
+ "static_assert",
230
+ "thread_local",
231
+ "typeof",
232
+ "typeof_unqual",
233
+ "constexpr",
234
+ "nullptr",
235
+ "_BitInt",
236
+ "_Decimal32",
237
+ "_Decimal64",
238
+ "_Decimal128",
239
+ }
240
+
241
+ class WINDOW:
242
+ def __init__(self):
243
+ self.file = ""
244
+ self.multiline_comment = False
245
+ self.fontsize = COMMON_FONTSIZE
246
+ self.bgcolor = COMMON_BG
247
+ self.fgcolor = COMMON_FG
248
+ self.indent_size = 4
249
+ self.indented_count = 0
250
+ self.window = tk.Tk()
251
+ self.font = COMMON_FONT
252
+ if self.font not in tkfont.families():
253
+ self.font = "Courier New"
254
+ x = int((self.window.winfo_screenwidth() - self.window.winfo_screenwidth() / 1.4) // 2)
255
+ y = int((self.window.winfo_screenheight() - (self.window.winfo_screenheight() / 1.2) - 75) // 2)
256
+ self.window.geometry(f"{int(self.window.winfo_screenwidth() / 1.4)}x{int(self.window.winfo_screenheight() / 1.2)}+{x}+{y}")
257
+ self.window.state("zoomed")
258
+ self.window.title("CLIDE")
259
+ self.window.grid_rowconfigure(0, weight = 1)
260
+ self.window.grid_rowconfigure(1, weight = 0)
261
+ self.window.grid_columnconfigure(0, weight = 0)
262
+ self.window.grid_columnconfigure(1, weight = 1)
263
+ self.window.grid_columnconfigure(2, weight = 0)
264
+ try:
265
+ self.window.iconbitmap(LOGO_ICO)
266
+ except:
267
+ messagebox.showerror("Logo Error", f"Unable to find {LOGO_ICO}")
268
+
269
+ self.main_menubar = tk.Menu(self.window)
270
+ self.main_menubar_file_menu = tk.Menu(self.main_menubar, tearoff=0)
271
+ self.main_menubar_file_menu.add_command(label="Open", command = self.open_file)
272
+ self.main_menubar_file_menu.add_command(label="Save", command = self.save_file)
273
+ self.main_menubar_file_menu.add_command(label="Save as", command = self.saveas_file)
274
+ self.main_menubar_file_menu.add_separator()
275
+ self.main_menubar_file_menu.add_command(label="Exit", command=self.window.quit)
276
+ self.main_menubar.add_cascade(label="File", menu=self.main_menubar_file_menu)
277
+
278
+ self.main_menubar_run_menu = tk.Menu(self.main_menubar, tearoff=0)
279
+ self.main_menubar_run_menu.add_command(label="Run C file F5", command = self.run_file)
280
+ self.main_menubar.add_cascade(label="Run", menu=self.main_menubar_run_menu)
281
+
282
+ self.main_menubar_settings_menu = tk.Menu(self.main_menubar, tearoff=0)
283
+ self.main_menubar_settings_menu.add_command(label="Style Configurator...", command = self.style_configurator)
284
+ self.main_menubar_settings_menu.add_command(label="About and Info...", command = self.about_info)
285
+ self.main_menubar.add_cascade(label="Settings", menu=self.main_menubar_settings_menu)
286
+ self.window.config(menu=self.main_menubar)
287
+
288
+ self.main_scrollbar_x = tk.Scrollbar(self.window, orient="horizontal")
289
+ self.main_scrollbar_x.grid(row = 1, column = 0, columnspan = 2, sticky = "ew")
290
+
291
+ self.main_scrollbar_y = tk.Scrollbar(self.window, orient="vertical")
292
+ self.main_scrollbar_y.grid(row = 0, column = 2, sticky = "ns")
293
+
294
+ self.line_numbers_width = 20
295
+
296
+ self.line_numbers = tk.Canvas(self.window, highlightthickness=0, width = self.line_numbers_width, bg = self.bgcolor)
297
+ self.line_numbers.grid(row = 0, column = 0, sticky = "ns")
298
+
299
+ def on_textscroll(first, last):
300
+ self.main_scrollbar_y.set(first, last)
301
+ self.update_clide()
302
+
303
+ self.editor = tk.Text(self.window ,
304
+ bg = self.bgcolor,
305
+ insertbackground="gray70",
306
+ fg = self.fgcolor ,
307
+ wrap="none",
308
+ undo=True,
309
+ maxundo=-1,
310
+ font = (self.font, COMMON_FONTSIZE),
311
+ xscrollcommand = self.main_scrollbar_x.set,
312
+ yscrollcommand=on_textscroll)
313
+ self.editor.grid(row = 0, column = 1, sticky = "nsew")
314
+ self.editor.edit_modified(False)
315
+
316
+ self.main_scrollbar_x.config(command = self.editor.xview)
317
+ self.main_scrollbar_y.config(command = self.editor.yview)
318
+ self.editor.bind("<KeyRelease>", self.update_clide)
319
+ self.editor.bind("<Control-o>", self.open_file)
320
+ self.editor.bind("<Control-s>", self.save_file)
321
+ self.editor.bind("<Return>", self.indent_line)
322
+ self.editor.bind("<F5>", self.run_file)
323
+ self.editor.bind("<Control-v>", self.paste_text)
324
+ self.editor.bind("<Control-MouseWheel>", self.zoom_text)
325
+ self.editor.tag_configure("keyword", foreground="yellow")
326
+ self.editor.tag_configure("string", foreground="#ff8080")
327
+ self.editor.tag_configure("preprocessor", foreground="orange")
328
+ self.editor.tag_configure("brackets", foreground="lightblue")
329
+ self.editor.tag_configure("functions", foreground="violet")
330
+ self.editor.tag_configure("comment", foreground="grey")
331
+ self.editor.tag_configure("type", foreground="green")
332
+
333
+ def about_info(self, event = None):
334
+ win = tk.Toplevel(self.window)
335
+ win.attributes("-topmost", True)
336
+ win.title("About and Info")
337
+ try:
338
+ win.iconbitmap(LOGO_ICO)
339
+ except:
340
+ messagebox.showerror("Logo Error", f"Unable to find {LOGO_ICO}")
341
+ win.focus_force()
342
+ win.focus_set()
343
+ win.configure(bg=self.bgcolor)
344
+ tk.Label(win, text ="Software name : CLIDE", font = (self.font, 16), fg = self.fgcolor, bg = self.bgcolor).pack(pady=10, anchor = "nw")
345
+ tk.Label(win, text =f"Software version : {CLIDE_VERSION}", font = (self.font, 16), fg = self.fgcolor, bg = self.bgcolor).pack(pady=10, anchor = "nw")
346
+ tk.Label(win, text ="Maintainer : Moinak debnath", font = (self.font, 16), fg = self.fgcolor, bg = self.bgcolor).pack(pady=10, anchor = "nw")
347
+ tk.Label(win, text ="Contributors : Claude (AI assistance)", font = (self.font, 16), fg = self.fgcolor, bg = self.bgcolor).pack(pady=10, anchor = "nw")
348
+ tk.Label(win, text ="Description : A code editor for C", font = (self.font, 16), fg = self.fgcolor, bg = self.bgcolor).pack(pady=10, anchor = "nw")
349
+ tk.Label(win, text ="License : MIT", font = (self.font, 16), fg = self.fgcolor, bg = self.bgcolor).pack(pady=10, anchor = "nw")
350
+
351
+ win.update_idletasks()
352
+
353
+ w = win.winfo_width()
354
+ h = win.winfo_height()
355
+
356
+ x = (win.winfo_screenwidth() - w) // 2
357
+ y = ((win.winfo_screenheight() - h) // 2) - 50 # to remove the taskbar and show the relative center
358
+
359
+ win.geometry(f"{w}x{h}+{x}+{y}")
360
+
361
+ def style_configurator(self, event = None):
362
+ win = tk.Toplevel(self.window)
363
+ win.attributes("-topmost", True)
364
+ win.title("Style Configurator")
365
+ x = int((win.winfo_screenwidth() - win.winfo_screenwidth() / 3) // 2)
366
+ y = int((win.winfo_screenheight() - (win.winfo_screenheight() / 2.5) - 75) // 2)
367
+ win.geometry(f"{int(win.winfo_screenwidth() / 3)}x{int(win.winfo_screenheight() / 2.5)}+{x}+{y}")
368
+ try:
369
+ win.iconbitmap(LOGO_ICO)
370
+ except:
371
+ messagebox.showerror("Logo Error", f"Unable to find {LOGO_ICO}")
372
+ win.focus_force()
373
+ win.focus_set()
374
+ win.configure(bg=self.bgcolor)
375
+ win.grid_rowconfigure(0, weight = 1)
376
+ win.grid_rowconfigure(1, weight = 1)
377
+ win.grid_rowconfigure(2, weight = 1)
378
+ win.grid_columnconfigure(0, weight = 1)
379
+ win.grid_columnconfigure(1, weight = 1)
380
+
381
+ def change_fg():
382
+ fg = colorchooser.askcolor()
383
+ if not fg[1]:
384
+ return
385
+ fg = fg[1]
386
+ self.fgcolor = fg
387
+ self.editor.configure(fg = self.fgcolor)
388
+ fg_button.config(text=f"{self.fgcolor} ➕", fg=self.fgcolor)
389
+ self.update_clide()
390
+
391
+ def change_bg():
392
+ bg = colorchooser.askcolor()
393
+ if not bg[1]:
394
+ return
395
+ bg = bg[1]
396
+ self.bgcolor = bg
397
+ self.editor.configure(bg = self.bgcolor)
398
+ bg_button.config(text=f"{self.bgcolor} ➕", fg=self.bgcolor)
399
+ self.line_numbers.configure(bg = self.bgcolor)
400
+ self.update_clide()
401
+
402
+ tk.Label(win, text = "Foreground Colour ", font = (self.font, 14), bg = self.bgcolor ,fg = "gray70").grid(row = 0, column = 0, padx = 30, sticky = "w")
403
+ fg_button = tk.Button(win, relief = "flat",font = (self.font, 14), text = f"{self.fgcolor} ➕", bg ="gray30" ,fg = self.fgcolor, command = change_fg)
404
+ fg_button.grid(row = 0, column = 1, sticky = "w", columnspan = 1)
405
+
406
+ tk.Label(win, text = "Background Colour ",font = (self.font, 14), bg = self.bgcolor ,fg = "gray70").grid(row = 1, column = 0, padx = 30, sticky = "w")
407
+ bg_button = tk.Button(win, relief = "flat",font = (self.font, 14), text = f"{self.bgcolor} ➕", bg ="gray30" ,fg = self.fgcolor, command = change_bg)
408
+ bg_button.grid(row = 1, column = 1, sticky = "w", columnspan = 1)
409
+
410
+ tk.Label(
411
+ win,
412
+ text="Font",
413
+ font=(self.font, 14),
414
+ bg=self.bgcolor,
415
+ fg="gray70"
416
+ ).grid(row=2, column=0, padx = 30, sticky="w")
417
+
418
+ choice = tk.StringVar(value=self.font)
419
+
420
+ def change_font(event = None):
421
+ self.font = combo.get()
422
+ self.editor.configure(font = (self.font, self.fontsize))
423
+ self.update_clide()
424
+
425
+ fonts = sorted(tkfont.families())
426
+ combo = ttk.Combobox(
427
+ win,
428
+ textvariable=choice,
429
+ values=fonts,
430
+ state="readonly",
431
+ width=30,
432
+ )
433
+ combo.grid(row=2, column=1, padx=10, pady=5, sticky="w")
434
+ win.after(100, lambda: combo.set(self.font))
435
+ combo.bind("<<ComboboxSelected>>", change_font)
436
+
437
+ def paste_text(self, event=None):
438
+ start = self.editor.index("insert")
439
+
440
+ try:
441
+ data = self.editor.clipboard_get()
442
+ except tk.TclError:
443
+ return "break"
444
+ self.editor.insert("insert", data)
445
+
446
+ end = self.editor.index(f"{start}+{len(data)}c")
447
+ pasted_first_line = int(self.editor.index(start).split(".")[0])
448
+ pasted_last_line = int(self.editor.index(end).split(".")[0])
449
+
450
+ for line in range(pasted_first_line, pasted_last_line + 1):
451
+ self.syntax_highlight(f"{line}.0", f"{line}.end")
452
+
453
+ return "break"
454
+
455
+ def zoom_text(self, event=None):
456
+ if event:
457
+ if event.delta > 0:
458
+ if self.fontsize >= 80:
459
+ return
460
+ self.fontsize += 1
461
+ self.editor.configure(font=(self.font, self.fontsize, "bold"))
462
+ self.line_numbers_width += 1
463
+ self.line_numbers.configure(width = self.line_numbers_width)
464
+ self.update_clide()
465
+
466
+ elif event.delta < 0:
467
+ if self.fontsize <= 10:
468
+ return
469
+ self.fontsize -= 1
470
+ self.editor.configure(font=(self.font, self.fontsize, "bold"))
471
+ self.line_numbers_width -= 1
472
+ self.line_numbers.configure(width = self.line_numbers_width)
473
+ self.update_clide()
474
+
475
+ def indent_line(self, event=None):
476
+ line = self.editor.get("insert linestart", "insert")
477
+
478
+ indent = len(line) - len(line.lstrip(" "))
479
+
480
+ if line.rstrip().endswith(("{", ":")):
481
+ indent += self.indent_size
482
+ elif line.rstrip().endswith("}"):
483
+ indent -= self.indent_size
484
+ self.editor.insert("insert", "\n" + " " * indent)
485
+ return "break"
486
+
487
+ def syntax_highlight(self, start, end):
488
+ if self.multiline_comment:
489
+ self.editor.tag_add( "comment", start, end)
490
+ words = self.editor.get(start, end)
491
+ lc = len(words)
492
+ word = ""
493
+ in_string = False
494
+ in_char = False
495
+ in_preprocessor = False
496
+ string_start = 0
497
+ char_start = 0
498
+ for i in range(0, lc, 1):
499
+ if words[i] in (" ", "\t"):
500
+ continue
501
+ word += words[i]
502
+ if words[i:i+2] == "//" and not in_string and not in_preprocessor:
503
+ self.editor.tag_add( "comment", f"{start}+{i-1}c", end)
504
+ break
505
+
506
+ elif words[i:i+2] == "/*" and not in_string and not in_preprocessor:
507
+ self.multiline_comment = True
508
+ self.editor.tag_add( "comment", f"{start}+{i-1}c", end)
509
+ continue
510
+
511
+ elif words[i:i+2] == "*/" and not in_string and not in_preprocessor:
512
+ self.multiline_comment = False
513
+ continue
514
+
515
+ elif word in C_TYPES:
516
+ self.editor.tag_add( "type", f"{start}+{i-len(word)+1}c", f"{start}+{i+1}c")
517
+ word = ""
518
+
519
+ elif word in C_KEYWORDS:
520
+ self.editor.tag_add( "keyword", f"{start}+{i-len(word)+1}c", f"{start}+{i+1}c")
521
+ word = ""
522
+
523
+ elif word in C_FUNCTIONS:
524
+ self.editor.tag_add( "functions", f"{start}+{i-len(word)+1}c", f"{start}+{i+1}c")
525
+ word = ""
526
+
527
+ elif words[i] == '"':
528
+ if not in_string:
529
+ in_string = True
530
+ string_start = i
531
+ else:
532
+ in_string = False
533
+ self.editor.tag_add( "string", f"{start}+{string_start}c", f"{start}+{i+1}c")
534
+ word = ""
535
+
536
+ elif words[i] == "'":
537
+ if not in_char:
538
+ in_char = True
539
+ char_start = i
540
+ else:
541
+ in_char = False
542
+ self.editor.tag_add( "string", f"{start}+{char_start}c", f"{start}+{i+1}c")
543
+ word = ""
544
+
545
+ elif words[i] in "{}()[];,+-*=<>":
546
+ self.editor.tag_add( "brackets", f"{start}+{i}c", f"{start}+{i+1}c")
547
+ word = ""
548
+
549
+ elif words[i] in ".!%&|^~?:/":
550
+ # operators/punctuation not covered above (ternary, logical,
551
+ # bitwise, modulo, division, member access, etc.) aren't
552
+ # highlighted, but must still break the token so it doesn't
553
+ # glue onto the next identifier
554
+ word = ""
555
+
556
+ elif words[i:i+1] == "#":
557
+ self.editor.tag_add( "preprocessor", f"{start}+{i}c", end)
558
+ break
559
+
560
+ def update_clide(self, event=None):
561
+ start = self.editor.index("insert linestart")
562
+ end = self.editor.index("insert lineend")
563
+ self.syntax_highlight(start, end)
564
+ if self.editor.edit_modified() and self.file:
565
+ self.window.title(f"CLIDE - *{self.file}")
566
+
567
+ self.line_numbers.delete("all")
568
+ line_count = int(self.editor.index("end-1c").split(".")[0])
569
+ digits = len(str(line_count))
570
+ self.line_numbers.config(width=digits * self.fontsize + 1)
571
+ index = self.editor.index("@0,0")
572
+
573
+ while True:
574
+ info = self.editor.dlineinfo(index)
575
+ if info is None:
576
+ break
577
+
578
+ y = info[1]
579
+ line = index.split(".")[0]
580
+
581
+ self.line_numbers.create_text(5, y, font = (self.font, self.fontsize), fill=self.fgcolor, text=line, anchor="nw")
582
+ index = self.editor.index(f"{index}+1line")
583
+
584
+ def run_file(self, event=None):
585
+ if not self.file:
586
+ messagebox.showerror("No File", "Currently No File is opened")
587
+ return
588
+ exe = os.path.splitext(self.file)[0] + ".exe"
589
+
590
+ subprocess.Popen(f'cmd /k gcc "{self.file}" -o "{exe}" && "{exe}" & pause & exit', creationflags=subprocess.CREATE_NEW_CONSOLE)
591
+
592
+ def open_file(self, event=None):
593
+ filename = filedialog.askopenfilename(
594
+ filetypes=[
595
+ ("All Files", "*.*")
596
+ ]
597
+ )
598
+ if not filename:
599
+ return
600
+
601
+ size = os.path.getsize(filename)
602
+ size = size / 1024**2
603
+ if (size) > 1:
604
+ permission = messagebox.askyesno("Warning", f"Loading This File Could Take Time\n Size of the file is {size} mb\n Do you want to load it ?")
605
+ if not permission:
606
+ return
607
+ text = None
608
+ try:
609
+ with open(filename, "r", encoding="utf-8") as f:
610
+ text = f.read().expandtabs(4)
611
+ except Exception as e:
612
+ messagebox.showerror("Unable", f"Unable to Load File {e}")
613
+
614
+ self.editor.delete("1.0", "end")
615
+ self.editor.insert("1.0", text)
616
+ self.multiline_comment = False
617
+ last_line = int(self.editor.index("end-1c").split(".")[0])
618
+
619
+ for line in range(1, last_line + 1):
620
+ self.syntax_highlight(f"{line}.0", f"{line}.end")
621
+
622
+ self.file = filename
623
+ self.editor.edit_modified(False)
624
+ self.window.title(f"CLIDE - {self.file}")
625
+ self.update_clide()
626
+
627
+ def save_file(self, event=None):
628
+ if not self.file:
629
+ return
630
+
631
+ with open(self.file, "w", encoding="utf-8") as f:
632
+ f.write(self.editor.get("1.0", "end-1c"))
633
+
634
+ self.update_clide()
635
+ self.editor.edit_modified(False)
636
+ self.window.title(f"CLIDE - {self.file}")
637
+
638
+ def saveas_file(self, event=None):
639
+ path = filedialog.asksaveasfilename(
640
+ defaultextension=".c",
641
+ filetypes=[("C source", "*.c"), ("All Files", "*.*")]
642
+ )
643
+ if not path:
644
+ return
645
+ with open(path, "w", encoding="utf-8") as f:
646
+ f.write(self.editor.get("1.0", "end-1c"))
647
+ self.file = path
648
+ self.editor.edit_modified(False)
649
+ self.window.title(f"CLIDE - {self.file}")
650
+ self.update_clide()
651
+
652
+ def main():
653
+ window = WINDOW()
654
+ window.window.mainloop()
655
+
656
+
657
+ if __name__ == "__main__":
658
+ main()
Binary file
@@ -0,0 +1,89 @@
1
+ Metadata-Version: 2.4
2
+ Name: clide-editor
3
+ Version: 0.1.0
4
+ Summary: A tiny, no-frills C code editor built with Python + tkinter
5
+ Author: Moinak Debnath
6
+ License-Expression: MIT
7
+ Project-URL: Homepage, https://github.com/findstring/clide
8
+ Project-URL: Repository, https://github.com/findstring/clide
9
+ Project-URL: Issues, https://github.com/findstring/clide/issues
10
+ Keywords: editor,c,ide,tkinter,syntax-highlighting
11
+ Classifier: Development Status :: 3 - Alpha
12
+ Classifier: Environment :: Win32 (MS Windows)
13
+ Classifier: Intended Audience :: Developers
14
+ Classifier: Programming Language :: Python :: 3
15
+ Classifier: Programming Language :: C
16
+ Classifier: Topic :: Software Development
17
+ Classifier: Topic :: Text Editors
18
+ Requires-Python: >=3.9
19
+ Description-Content-Type: text/markdown
20
+ License-File: LICENSE
21
+ Dynamic: license-file
22
+
23
+ > 🤖 **Note:** This README was written by Claude AI, because the dev (me) was too lazy to write one myself. The code, however, is 100% hand-written — except for the giant list of C keywords/types/functions used for syntax highlighting, which Claude also helped generate because who's memorizing `stdc_leading_zeros` for fun.
24
+
25
+ ---
26
+
27
+ ## What is this?
28
+
29
+ CLIDE is a lightweight library based C editor with syntax highlighting, line numbers, auto-indent, and a one-key "compile and run" workflow using `gcc`. No bloat, no plugins, no 400 MB Electron shell — just a `tkinter` window that gets out of your way.
30
+
31
+ Built mostly as a personal project / learning exercise, not (yet) a serious rival to VS Code.
32
+
33
+ ## Features
34
+
35
+ - 🎨 **Syntax highlighting** for C — keywords, types, functions, strings, char literals, comments (single-line and block), numbers, and preprocessor directives
36
+ - 🔢 **Line numbers** that track scrolling and zoom
37
+ - 🔍 **Zoom in/out** with `Ctrl + Mouse Wheel`
38
+ - ⏎ **Auto-indent** — adds/removes indentation automatically after `{`, `}`, and `:`
39
+ - ▶️ **Run with F5** — compiles your file with `gcc` and runs it in a new console window
40
+ - 💾 **Open / Save / Save As** from the File menu or `Ctrl+O` / `Ctrl+S`
41
+ - 📋 **Paste-aware highlighting** — pasted multi-line code gets highlighted properly, not just the current line
42
+ - 🎨 **Style Configurator** — change background, foreground colour and also fonts
43
+ - 🖱️ Undo/redo support (unlimited undo history)
44
+
45
+ ## Requirements
46
+
47
+ - Python 3.x with `tkinter` (usually bundled with Python on Windows)
48
+ - `gcc` installed and available on your system `PATH` (for the Run feature)
49
+ - Windows — the "Run" feature and maximized window launch currently rely on Windows-specific behavior (see Limitations below)
50
+
51
+ ## Getting Started
52
+
53
+ ```bash
54
+ pip install clide-editor
55
+ python -m clide
56
+ ```
57
+
58
+ Open a `.c` file with `Ctrl+O`, write some code, hit `F5` to compile and run it.
59
+
60
+ ## Version
61
+
62
+ **v0.1.0** — early days. Things work, but expect rough edges.
63
+
64
+ ## Limitations
65
+
66
+ - **Windows-only for now.** The maximized-window launch and the `F5` run command (`cmd /k gcc ...`) both assume Windows. Running this on Linux/macOS will likely misbehave or crash on the run step.
67
+ - **Single-line-focused highlighting.** Typing re-highlights the line you're on; large structural edits elsewhere in the file (outside of paste) aren't automatically re-scanned.
68
+ - **No project/workspace support** — it's a single-file editor, not a full IDE. No multi-file tabs yet.
69
+ - **No build configuration** — compilation is a hardcoded `gcc file.c -o file.exe`, no custom flags, no Makefile support.
70
+ - **No autocomplete, linting, or error highlighting** — you find out about bugs when `gcc` yells at you.
71
+ - **No find & replace** yet.
72
+
73
+ ## To Be Featured (Roadmap)
74
+
75
+ - [ ] Cross-platform support (Linux/macOS build + run)
76
+ - [ ] Find & Replace
77
+ - [ ] Multiple tabs / multi-file projects
78
+ - [ ] Custom compiler flags / build settings
79
+ - [ ] Bracket matching + auto-close brackets
80
+ - [ ] Inline error markers from `gcc` output
81
+ - [ ] Proper packaging (so you don't need Python installed to run it)
82
+
83
+ ## Contributing
84
+
85
+ This is a small personal project, but if you spot a bug or have an idea, feel free to open an issue or PR.
86
+
87
+ ## License
88
+
89
+ See [LICENSE](LICENSE) for details.
@@ -0,0 +1,12 @@
1
+ LICENSE
2
+ README.md
3
+ pyproject.toml
4
+ clide/__init__.py
5
+ clide/__main__.py
6
+ clide/clide.py
7
+ clide/icons/logo.ico
8
+ clide_editor.egg-info/PKG-INFO
9
+ clide_editor.egg-info/SOURCES.txt
10
+ clide_editor.egg-info/dependency_links.txt
11
+ clide_editor.egg-info/entry_points.txt
12
+ clide_editor.egg-info/top_level.txt
@@ -0,0 +1,2 @@
1
+ [console_scripts]
2
+ clide = clide:main
@@ -0,0 +1,37 @@
1
+ [build-system]
2
+ requires = ["setuptools>=68", "wheel"]
3
+ build-backend = "setuptools.build_meta"
4
+
5
+ [project]
6
+ name = "clide-editor"
7
+ version = "0.1.0"
8
+ description = "A tiny, no-frills C code editor built with Python + tkinter"
9
+ readme = "README.md"
10
+ license = "MIT"
11
+ license-files = ["LICENSE"]
12
+ requires-python = ">=3.9"
13
+ authors = [
14
+ { name = "Moinak Debnath" }
15
+ ]
16
+ keywords = ["editor", "c", "ide", "tkinter", "syntax-highlighting"]
17
+ classifiers = [
18
+ "Development Status :: 3 - Alpha",
19
+ "Environment :: Win32 (MS Windows)",
20
+ "Intended Audience :: Developers",
21
+ "Programming Language :: Python :: 3",
22
+ "Programming Language :: C",
23
+ "Topic :: Software Development",
24
+ "Topic :: Text Editors",
25
+ ]
26
+ dependencies = []
27
+
28
+ [project.urls]
29
+ Homepage = "https://github.com/findstring/clide"
30
+ Repository = "https://github.com/findstring/clide"
31
+ Issues = "https://github.com/findstring/clide/issues"
32
+
33
+ [project.scripts]
34
+ clide = "clide:main"
35
+
36
+ [tool.setuptools.package-data]
37
+ clide = ["icons/*.ico"]
@@ -0,0 +1,4 @@
1
+ [egg_info]
2
+ tag_build =
3
+ tag_date = 0
4
+