clide-editor 0.2.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,106 @@
1
+ Metadata-Version: 2.4
2
+ Name: clide-editor
3
+ Version: 0.2.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
+ ## Changelog
34
+
35
+ - Added Proper UI at the Start
36
+ - Added Multi file management system
37
+
38
+ ## Features
39
+
40
+ - 🎨 **Syntax highlighting** for C — keywords, types, functions, strings, char literals, comments (single-line and block), numbers, and preprocessor directives
41
+ - 🔢 **Line numbers** that track scrolling and zoom
42
+ - 🔍 **Zoom in/out** with `Ctrl + Mouse Wheel`
43
+ - ⏎ **Auto-indent** — adds/removes indentation automatically after `{`, `}`, and `:`
44
+ - ▶️ **Run with F5** — compiles your file with `gcc` and runs it in a new console window
45
+ - 💾 **Open / Save / Save As** from the File menu or `Ctrl+O` / `Ctrl+S`
46
+ - 📋 **Paste-aware highlighting** — pasted multi-line code gets highlighted properly, not just the current line
47
+ - 🎨 **Style Configurator** — change background, foreground colour and also fonts
48
+ - 🖱️ **Undo/redo support** (unlimited undo history)
49
+ - 🗂️ **Multi file editor** -- Manage and code multiple files in on go.
50
+
51
+ ## Requirements
52
+
53
+ - Python 3.x with `tkinter` (usually bundled with Python on Windows)
54
+ - `gcc` installed and available on your system `PATH` (for the Run feature)
55
+ - Windows — the "Run" feature and maximized window launch currently rely on Windows-specific behavior (see Limitations below)
56
+
57
+ ## Getting Started
58
+
59
+ Install the latest version:
60
+
61
+ ```bash
62
+ pip install clide-editor
63
+ ```
64
+
65
+ Or install this specific version:
66
+
67
+ ```bash
68
+ pip install clide-editor==0.2.0
69
+ ```
70
+
71
+ Run CLIDE:
72
+
73
+ ```bash
74
+ python -m clide
75
+ ```
76
+
77
+ Open a `.c` file with `Ctrl+O`, write some code, hit `F5` to compile and run it.
78
+
79
+ ## Version
80
+
81
+ **v0.2.0** — Things work, but expect rough edges.
82
+
83
+ ## Limitations
84
+
85
+ - **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.
86
+ - **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.
87
+ - **No build configuration** — compilation is a hardcoded `gcc file.c -o file.exe`, no custom flags, no Makefile support.
88
+ - **No autocomplete, linting, or error highlighting** — you find out about bugs when `gcc` yells at you.
89
+ - **No find & replace** yet.
90
+
91
+ ## To Be Featured (Roadmap)
92
+
93
+ - [ ] Cross-platform support (Linux/macOS build + run)
94
+ - [ ] Find & Replace
95
+ - [ ] Custom compiler flags / build settings
96
+ - [ ] Bracket matching + auto-close brackets
97
+ - [ ] Inline error markers from `gcc` output
98
+ - [ ] Proper packaging (so you don't need Python installed to run it)
99
+
100
+ ## Contributing
101
+
102
+ This is a small personal project, but if you spot a bug or have an idea, feel free to open an issue or PR.
103
+
104
+ ## License
105
+
106
+ See [LICENSE](LICENSE) for details.
@@ -0,0 +1,84 @@
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
+ ## Changelog
12
+
13
+ - Added Proper UI at the Start
14
+ - Added Multi file management system
15
+
16
+ ## Features
17
+
18
+ - 🎨 **Syntax highlighting** for C — keywords, types, functions, strings, char literals, comments (single-line and block), numbers, and preprocessor directives
19
+ - 🔢 **Line numbers** that track scrolling and zoom
20
+ - 🔍 **Zoom in/out** with `Ctrl + Mouse Wheel`
21
+ - ⏎ **Auto-indent** — adds/removes indentation automatically after `{`, `}`, and `:`
22
+ - ▶️ **Run with F5** — compiles your file with `gcc` and runs it in a new console window
23
+ - 💾 **Open / Save / Save As** from the File menu or `Ctrl+O` / `Ctrl+S`
24
+ - 📋 **Paste-aware highlighting** — pasted multi-line code gets highlighted properly, not just the current line
25
+ - 🎨 **Style Configurator** — change background, foreground colour and also fonts
26
+ - 🖱️ **Undo/redo support** (unlimited undo history)
27
+ - 🗂️ **Multi file editor** -- Manage and code multiple files in on go.
28
+
29
+ ## Requirements
30
+
31
+ - Python 3.x with `tkinter` (usually bundled with Python on Windows)
32
+ - `gcc` installed and available on your system `PATH` (for the Run feature)
33
+ - Windows — the "Run" feature and maximized window launch currently rely on Windows-specific behavior (see Limitations below)
34
+
35
+ ## Getting Started
36
+
37
+ Install the latest version:
38
+
39
+ ```bash
40
+ pip install clide-editor
41
+ ```
42
+
43
+ Or install this specific version:
44
+
45
+ ```bash
46
+ pip install clide-editor==0.2.0
47
+ ```
48
+
49
+ Run CLIDE:
50
+
51
+ ```bash
52
+ python -m clide
53
+ ```
54
+
55
+ Open a `.c` file with `Ctrl+O`, write some code, hit `F5` to compile and run it.
56
+
57
+ ## Version
58
+
59
+ **v0.2.0** — Things work, but expect rough edges.
60
+
61
+ ## Limitations
62
+
63
+ - **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.
64
+ - **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.
65
+ - **No build configuration** — compilation is a hardcoded `gcc file.c -o file.exe`, no custom flags, no Makefile support.
66
+ - **No autocomplete, linting, or error highlighting** — you find out about bugs when `gcc` yells at you.
67
+ - **No find & replace** yet.
68
+
69
+ ## To Be Featured (Roadmap)
70
+
71
+ - [ ] Cross-platform support (Linux/macOS build + run)
72
+ - [ ] Find & Replace
73
+ - [ ] Custom compiler flags / build settings
74
+ - [ ] Bracket matching + auto-close brackets
75
+ - [ ] Inline error markers from `gcc` output
76
+ - [ ] Proper packaging (so you don't need Python installed to run it)
77
+
78
+ ## Contributing
79
+
80
+ This is a small personal project, but if you spot a bug or have an idea, feel free to open an issue or PR.
81
+
82
+ ## License
83
+
84
+ 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,887 @@
1
+ import tkinter as tk
2
+ import os, sys, subprocess
3
+ import tkinter.font as tkfont
4
+ from tkinter import colorchooser, ttk, simpledialog, filedialog, messagebox
5
+
6
+ CLIDE_VERSION = "v0.2.0"
7
+ SCRIPT_PATH = os.path.abspath(__file__)
8
+ LOGO_ICO = os.path.join(os.path.dirname(SCRIPT_PATH), "icons", "logo.ico")
9
+ LOGO_PNG = os.path.join(os.path.dirname(SCRIPT_PATH), "icons", "logo.png")
10
+ COMMON_BG = "gray5"
11
+ COMMON_FG = "gray70"
12
+ COMMON_FONTSIZE = 16
13
+ COMMON_FONT = "Iosevka"
14
+
15
+ C_TYPES = {
16
+ "void",
17
+ "char", "signed char", "unsigned char",
18
+ "short", "short int", "signed short", "signed short int",
19
+ "unsigned short", "unsigned short int",
20
+ "int", "signed", "signed int",
21
+ "unsigned", "unsigned int",
22
+ "long", "long int", "signed long", "signed long int",
23
+ "unsigned long", "unsigned long int",
24
+ "long long", "long long int", "signed long long", "signed long long int",
25
+ "unsigned long long", "unsigned long long int",
26
+ "float",
27
+ "double",
28
+ "long double",
29
+ "_Bool",
30
+ "_Complex",
31
+ "_Imaginary",
32
+
33
+ # <stddef.h>
34
+ "size_t", "ptrdiff_t", "wchar_t", "max_align_t", "nullptr_t", # nullptr_t is C23
35
+
36
+ # <stdint.h>
37
+ "int8_t", "int16_t", "int32_t", "int64_t",
38
+ "uint8_t", "uint16_t", "uint32_t", "uint64_t",
39
+ "int_least8_t", "int_least16_t", "int_least32_t", "int_least64_t",
40
+ "uint_least8_t", "uint_least16_t", "uint_least32_t", "uint_least64_t",
41
+ "int_fast8_t", "int_fast16_t", "int_fast32_t", "int_fast64_t",
42
+ "uint_fast8_t", "uint_fast16_t", "uint_fast32_t", "uint_fast64_t",
43
+ "intptr_t", "uintptr_t", "intmax_t", "uintmax_t",
44
+
45
+ # <stdio.h>
46
+ "FILE", "fpos_t",
47
+
48
+ # <time.h>
49
+ "time_t", "clock_t", "struct tm", "struct timespec",
50
+
51
+ # <stdarg.h>
52
+ "va_list",
53
+
54
+ # <stdlib.h>
55
+ "div_t", "ldiv_t", "lldiv_t",
56
+
57
+ # <setjmp.h>
58
+ "jmp_buf",
59
+
60
+ # <signal.h>
61
+ "sig_atomic_t",
62
+
63
+ # <wchar.h>
64
+ "wint_t", "mbstate_t",
65
+
66
+ # <locale.h>
67
+ "struct lconv",
68
+
69
+ # <threads.h> (C11)
70
+ "thrd_t", "mtx_t", "cnd_t", "tss_t", "once_flag", "thrd_start_t", "tss_dtor_t",
71
+
72
+ # <stdatomic.h> (C11)
73
+ "atomic_flag", "memory_order",
74
+ "atomic_bool", "atomic_char", "atomic_int", "atomic_long", "atomic_llong",
75
+ "atomic_uint", "atomic_ulong", "atomic_ullong", "atomic_size_t",
76
+ "atomic_intptr_t", "atomic_uintptr_t", "atomic_ptrdiff_t",
77
+ "atomic_intmax_t", "atomic_uintmax_t",
78
+
79
+ # <uchar.h>
80
+ "char8_t", # C23
81
+ "char16_t", "char32_t",
82
+ "bool"
83
+ }
84
+
85
+ C_FUNCTIONS = {
86
+ # <stdio.h>
87
+ "printf", "fprintf", "sprintf", "snprintf",
88
+ "vprintf", "vfprintf", "vsprintf", "vsnprintf",
89
+ "scanf", "fscanf", "sscanf", "vscanf", "vfscanf", "vsscanf",
90
+ "fopen", "freopen", "fclose", "fflush",
91
+ "fread", "fwrite",
92
+ "fgetc", "getc", "fgets", "fputc", "putc", "fputs",
93
+ "getchar", "putchar", "puts", "gets_s",
94
+ "ungetc",
95
+ "fseek", "ftell", "rewind", "fgetpos", "fsetpos",
96
+ "fseeko", "ftello",
97
+ "feof", "ferror", "clearerr", "perror",
98
+ "remove", "rename", "tmpfile", "tmpnam",
99
+ "setbuf", "setvbuf",
100
+
101
+ # <stdlib.h>
102
+ "malloc", "calloc", "realloc", "free", "aligned_alloc", "free_sized", "free_aligned_sized", # last two C23
103
+ "atof", "atoi", "atol", "atoll",
104
+ "strtod", "strtof", "strtold",
105
+ "strtol", "strtoll", "strtoul", "strtoull",
106
+ "rand", "srand",
107
+ "abort", "exit", "_Exit", "quick_exit",
108
+ "atexit", "at_quick_exit",
109
+ "system", "getenv",
110
+ "bsearch", "qsort", "qsort_r",
111
+ "abs", "labs", "llabs",
112
+ "div", "ldiv", "lldiv",
113
+ "mblen", "mbtowc", "wctomb", "mbstowcs", "wcstombs",
114
+
115
+ # <string.h>
116
+ "memcpy", "memmove", "memcmp", "memchr", "memset",
117
+ "memccpy",
118
+ "strcpy", "strncpy", "strcat", "strncat", "strcmp", "strncmp",
119
+ "strchr", "strrchr", "strstr", "strpbrk", "strspn", "strcspn",
120
+ "strtok", "strtok_r",
121
+ "strlen", "strerror", "strcoll", "strxfrm",
122
+ "strdup", "strndup",
123
+ "memset_explicit", "memset_s", # newer / annex-K style
124
+
125
+ # <ctype.h>
126
+ "isalnum", "isalpha", "isblank", "iscntrl", "isdigit", "isgraph",
127
+ "islower", "isprint", "ispunct", "isspace", "isupper", "isxdigit",
128
+ "tolower", "toupper",
129
+
130
+ # <math.h>
131
+ "sin", "cos", "tan", "asin", "acos", "atan", "atan2",
132
+ "sinh", "cosh", "tanh", "asinh", "acosh", "atanh",
133
+ "exp", "exp2", "expm1", "log", "log2", "log10", "log1p", "logb",
134
+ "pow", "sqrt", "cbrt", "hypot",
135
+ "ceil", "floor", "trunc", "round", "lround", "llround", "nearbyint", "rint", "lrint", "llrint",
136
+ "fmod", "remainder", "remquo",
137
+ "copysign", "nan", "nextafter", "nexttoward",
138
+ "fdim", "fmax", "fmin", "fma",
139
+ "fabs", "frexp", "ldexp", "modf", "scalbn", "scalbln",
140
+ "ilogb", "erf", "erfc", "tgamma", "lgamma",
141
+ "isfinite", "isinf", "isnan", "isnormal", "signbit",
142
+ "isgreater", "isgreaterequal", "isless", "islessequal", "islessgreater", "isunordered",
143
+
144
+ # <time.h>
145
+ "time", "difftime", "mktime", "asctime", "ctime",
146
+ "gmtime", "localtime", "strftime",
147
+ "clock", "timespec_get", "timespec_getres", # timespec_getres is C23
148
+
149
+ # <wchar.h>, <wctype.h> — wide-char variants
150
+ "wcslen", "wcscpy", "wcsncpy", "wcscat", "wcsncat", "wcscmp", "wcsncmp",
151
+ "wcschr", "wcsrchr", "wcsstr", "wcstok",
152
+ "fwprintf", "fwscanf", "swprintf", "swscanf", "wprintf", "wscanf",
153
+ "iswalpha", "iswdigit", "iswspace", "towlower", "towupper",
154
+
155
+ # <setjmp.h>
156
+ "setjmp", "longjmp",
157
+
158
+ # <signal.h>
159
+ "signal", "raise",
160
+
161
+ # <assert.h>
162
+ # assert() is a macro, listed above
163
+
164
+ # <locale.h>
165
+ "setlocale", "localeconv",
166
+
167
+ # <stdarg.h> (function-like macros)
168
+ "va_start", "va_arg", "va_end", "va_copy",
169
+
170
+ # <threads.h>
171
+ "thrd_create", "thrd_join", "thrd_detach", "thrd_exit", "thrd_yield",
172
+ "thrd_sleep", "thrd_current", "thrd_equal",
173
+ "mtx_init", "mtx_lock", "mtx_unlock", "mtx_trylock", "mtx_timedlock", "mtx_destroy",
174
+ "cnd_init", "cnd_signal", "cnd_broadcast", "cnd_wait", "cnd_timedwait", "cnd_destroy",
175
+ "call_once",
176
+ "tss_create", "tss_get", "tss_set", "tss_delete",
177
+
178
+ # <stdatomic.h>
179
+ "atomic_init", "atomic_store", "atomic_load", "atomic_exchange",
180
+ "atomic_compare_exchange_strong", "atomic_compare_exchange_weak",
181
+ "atomic_fetch_add", "atomic_fetch_sub", "atomic_fetch_or",
182
+ "atomic_fetch_and", "atomic_fetch_xor",
183
+ "atomic_flag_test_and_set", "atomic_flag_clear",
184
+ "atomic_thread_fence", "atomic_signal_fence", "atomic_is_lock_free",
185
+
186
+ # <uchar.h>
187
+ "mbrtoc8", "c8rtomb", # C23
188
+ "mbrtoc16", "c16rtomb", "mbrtoc32", "c32rtomb",
189
+
190
+ # <stdbit.h> (C23) — bit utilities
191
+ "stdc_leading_zeros", "stdc_leading_ones", "stdc_trailing_zeros", "stdc_trailing_ones",
192
+ "stdc_first_leading_zero", "stdc_first_leading_one",
193
+ "stdc_first_trailing_zero", "stdc_first_trailing_one",
194
+ "stdc_count_zeros", "stdc_count_ones", "stdc_has_single_bit",
195
+ "stdc_bit_width", "stdc_bit_floor", "stdc_bit_ceil",
196
+ }
197
+
198
+ C_KEYWORDS = {
199
+ "auto", "break", "case", "char", "const", "continue",
200
+ "default", "do", "else", "enum", "extern",
201
+ "float", "for", "goto", "if", "int", "long",
202
+ "register", "return", "short", "signed", "sizeof", "static",
203
+ "struct", "switch", "typedef", "union", "unsigned", "void",
204
+ "volatile", "while",
205
+ "inline",
206
+ "restrict",
207
+ "_Bool",
208
+ "_Complex",
209
+ "_Imaginary",
210
+ "_Alignas",
211
+ "_Alignof",
212
+ "_Atomic",
213
+ "_Generic",
214
+ "_Noreturn",
215
+ "_Static_assert",
216
+ "_Thread_local",
217
+ "alignas",
218
+ "alignof",
219
+ "bool",
220
+ "true",
221
+ "false",
222
+ "static_assert",
223
+ "thread_local",
224
+ "typeof",
225
+ "typeof_unqual",
226
+ "constexpr",
227
+ "nullptr",
228
+ "_BitInt",
229
+ "_Decimal32",
230
+ "_Decimal64",
231
+ "_Decimal128",
232
+ }
233
+
234
+ class WINDOW:
235
+ def __init__(self):
236
+ self.button_frame_list = []
237
+ self.is_saved = False
238
+ self.upper_frame = None
239
+ self.files_opened = {}
240
+ self.file = None
241
+ self.multiline_comment = False
242
+ self.fontsize = COMMON_FONTSIZE
243
+ self.bgcolor = COMMON_BG
244
+ self.fgcolor = COMMON_FG
245
+ self.indent_size = 4
246
+ self.indented_count = 0
247
+ self.window = tk.Tk()
248
+ self.window.configure(bg = "#202136")
249
+ self.main_frame = None
250
+ self.editor = None
251
+ self.line_numbers = None
252
+ self.main_scrollbar_x = None
253
+ self.main_scrollbar_y = None
254
+ self.line_numbers_width = 20
255
+ self.font = COMMON_FONT
256
+ if self.font not in tkfont.families():
257
+ self.font = "Courier New"
258
+ x = int((self.window.winfo_screenwidth() - self.window.winfo_screenwidth() / 1.4) // 2)
259
+ y = int((self.window.winfo_screenheight() - (self.window.winfo_screenheight() / 1.2) - 75) // 2)
260
+ self.window.geometry(f"{int(self.window.winfo_screenwidth() / 1.4)}x{int(self.window.winfo_screenheight() / 1.2)}+{x}+{y}")
261
+ self.window.state("zoomed")
262
+ self.window.title("CLIDE")
263
+ self.window.grid_rowconfigure(0, weight = 0)
264
+ self.window.grid_rowconfigure(1, weight = 1)
265
+ self.window.grid_columnconfigure(0, weight = 1)
266
+ try:
267
+ self.window.iconbitmap(LOGO_ICO)
268
+ except:
269
+ messagebox.showerror("Logo Error", f"Unable to find {LOGO_ICO}")
270
+
271
+ self.main_menubar = tk.Menu(self.window)
272
+ self.main_menubar_file_menu = tk.Menu(self.main_menubar, tearoff=0)
273
+ self.main_menubar_file_menu.add_command(label="Open", command = self.open_file)
274
+ self.main_menubar_file_menu.add_command(label="Save", command = self.save_file)
275
+ self.main_menubar_file_menu.add_command(label="Save as", command = self.saveas_file)
276
+ self.main_menubar_file_menu.add_separator()
277
+ self.main_menubar_file_menu.add_command(label="Exit", command=self.exit_app)
278
+ self.main_menubar.add_cascade(label="File", menu=self.main_menubar_file_menu)
279
+
280
+ self.main_menubar_run_menu = tk.Menu(self.main_menubar, tearoff=0)
281
+ self.main_menubar_run_menu.add_command(label="Run C file F5", command = self.run_file)
282
+ self.main_menubar.add_cascade(label="Run", menu=self.main_menubar_run_menu)
283
+
284
+ self.main_menubar_settings_menu = tk.Menu(self.main_menubar, tearoff=0)
285
+ self.main_menubar_settings_menu.add_command(label="Style Configurator...", command = self.style_configurator)
286
+ self.main_menubar_settings_menu.add_command(label="About and Info...", command = self.about_info)
287
+ self.main_menubar.add_cascade(label="Settings", menu=self.main_menubar_settings_menu)
288
+ self.window.config(menu=self.main_menubar)
289
+ self.window.protocol("WM_DELETE_WINDOW", self.exit_app)
290
+
291
+ self.logo_png = tk.PhotoImage(file=LOGO_PNG)
292
+ self.logo_label = tk.Label(self.window, image=self.logo_png)
293
+ self.logo_label.grid(row = 0, column = 0, sticky = "w", pady = (30,0), padx = 30)
294
+ self.open_file_button = tk.Button(self.window, text = "📂 Open File", command = self.open_file, bg = "#202136", relief = "flat", font = ("Consolas", 60), fg = "white")
295
+ self.open_file_button.grid(row = 0, column = 1, pady = (0, 350), padx =(0, 100))
296
+ self.exit_file_button = tk.Button(self.window, text = "🚪 Exit App", bg = "#202136", command = self.exit_app, relief = "flat", font = ("Consolas", 60), fg = "white")
297
+ self.exit_file_button.grid(row = 0, column = 1, pady = (350, 0), padx =(0, 100))
298
+
299
+ def exit_app(self):
300
+ if self.is_saved == False:
301
+ saved = messagebox.askyesno("Save before exit", "Do you want to save the current file before exit ?")
302
+ if not saved:
303
+ self.window.destroy()
304
+ return
305
+
306
+ self.save_file()
307
+ self.window.destroy()
308
+
309
+ def create_tab_area(self):
310
+ self.upper_frame = tk.Frame(self.window, bg = COMMON_BG, height = 25)
311
+ self.upper_frame.grid(row = 0, column = 0, columnspan = 3, sticky = "ew")
312
+
313
+ self.upper_frame.grid_rowconfigure(0, weight = 1)
314
+ self.upper_frame.grid_rowconfigure(1, weight = 0)
315
+
316
+ self.upper_frame.grid_columnconfigure(0, weight = 1)
317
+
318
+ self.tab_scrollbar = tk.Scrollbar(self.upper_frame, orient = "horizontal")
319
+ self.tab_scrollbar.grid(row = 1, column = 0, sticky = "ew")
320
+
321
+ self.tab_canvas = tk.Canvas(self.upper_frame, height = 25, xscrollcommand = self.tab_scrollbar.set, bg = COMMON_BG, relief = "sunken")
322
+ self.tab_canvas.grid(row = 0, column = 0, sticky = "ew")
323
+
324
+ self.canvas_inside_frame = tk.Frame(self.tab_canvas)
325
+
326
+ self.tab_canvas.create_window(
327
+ (0, 0),
328
+ window=self.canvas_inside_frame,
329
+ anchor="nw"
330
+ )
331
+
332
+ def hide_file(self, filename):
333
+ self.files_opened[filename][0].grid_remove()
334
+
335
+ def add_file(self, filename):
336
+ if self.logo_label:
337
+ self.logo_label.destroy()
338
+ self.logo_label = None
339
+
340
+ if self.open_file_button:
341
+ self.open_file_button.destroy()
342
+ self.open_file_button = None
343
+
344
+ if self.exit_file_button:
345
+ self.exit_file_button.destroy()
346
+ self.exit_file_button = None
347
+
348
+ if not self.upper_frame:
349
+ self.create_tab_area()
350
+ frame = tk.Frame(self.window, bg = COMMON_BG)
351
+ frame.grid(row = 1, column = 0, sticky = "nsew")
352
+
353
+ frame.grid_rowconfigure(0, weight = 1)
354
+ frame.grid_rowconfigure(1, weight = 0)
355
+
356
+ frame.grid_columnconfigure(0, weight = 0)
357
+ frame.grid_columnconfigure(1, weight = 1)
358
+ frame.grid_columnconfigure(2, weight = 0)
359
+
360
+ main_scrollbar_x = tk.Scrollbar(frame, orient="horizontal")
361
+ main_scrollbar_x.grid(row = 1, column = 0, columnspan = 3, sticky = "ew")
362
+
363
+ main_scrollbar_y = tk.Scrollbar(frame, orient="vertical")
364
+ main_scrollbar_y.grid(row = 0, column = 2, sticky = "ns")
365
+
366
+ line_numbers = tk.Canvas(frame, highlightthickness=0, width = self.line_numbers_width, bg = self.bgcolor)
367
+ line_numbers.grid(row = 0, column = 0, sticky = "ns")
368
+
369
+ def on_textscroll(first, last):
370
+ main_scrollbar_y.set(first, last)
371
+ self.update_clide()
372
+
373
+ editor = tk.Text(frame ,
374
+ bg = self.bgcolor,
375
+ insertbackground="gray70",
376
+ fg = self.fgcolor ,
377
+ wrap="none",
378
+ undo=True,
379
+ maxundo=-1,
380
+ font = (self.font, COMMON_FONTSIZE),
381
+ xscrollcommand = main_scrollbar_x.set,
382
+ yscrollcommand=on_textscroll)
383
+ editor.grid(row = 0, column = 1, sticky = "nsew")
384
+ editor.edit_modified(False)
385
+
386
+ main_scrollbar_x.config(command = editor.xview)
387
+ main_scrollbar_y.config(command = editor.yview)
388
+ editor.bind("<KeyRelease>", self.update_clide)
389
+ editor.bind("<Control-o>", self.open_file)
390
+ editor.bind("<Control-s>", self.save_file)
391
+ editor.bind("<Return>", self.indent_line)
392
+ editor.bind("<F5>", self.run_file)
393
+ editor.bind("<Control-v>", self.paste_text)
394
+ editor.bind("<Control-MouseWheel>", self.zoom_text)
395
+ editor.tag_configure("keyword", foreground="yellow")
396
+ editor.tag_configure("string", foreground="#ff8080")
397
+ editor.tag_configure("preprocessor", foreground="orange")
398
+ editor.tag_configure("brackets", foreground="lightblue")
399
+ editor.tag_configure("functions", foreground="violet")
400
+ editor.tag_configure("comment", foreground="grey")
401
+ editor.tag_configure("type", foreground="green")
402
+
403
+ self.files_opened[filename] = [frame, editor, line_numbers, main_scrollbar_x, main_scrollbar_y]
404
+ self.main_frame = frame
405
+ self.editor = editor
406
+ self.line_numbers = line_numbers
407
+ self.main_scrollbar_x = main_scrollbar_x
408
+ self.main_scrollbar_y = main_scrollbar_y
409
+
410
+ def shorten(filename):
411
+ if len(filename) > 20:
412
+ name = filename[:20] + "..."
413
+ return name
414
+ else:
415
+ return filename
416
+
417
+ button_frame = tk.Frame(
418
+ self.canvas_inside_frame,
419
+ width=80,
420
+ height=40,
421
+ relief="flat"
422
+ )
423
+
424
+ button_frame.pack(side="left", padx = 1)
425
+ button_frame.grid_columnconfigure(0, weight = 1)
426
+ button_frame.grid_columnconfigure(1, weight = 0)
427
+
428
+ tk.Button(button_frame, bg = COMMON_BG, fg = COMMON_FG, text = shorten(filename.split("/")[-1]), command = lambda : self.select_file(filename)).grid(row = 0, column = 0, sticky = "nsew")
429
+
430
+ def button_command(filename):
431
+ self.remove_file(filename)
432
+ button_frame.destroy()
433
+
434
+ tk.Button(button_frame, bg = COMMON_BG, fg = COMMON_FG, text = "❌", relief = "flat", command = lambda : button_command(filename)).grid(row = 0, column = 1, sticky = "nsew")
435
+ self.button_frame_list.append(button_frame)
436
+
437
+ def remove_file(self, filename):
438
+ if filename not in self.files_opened:
439
+ return
440
+
441
+ if self.is_saved == False:
442
+ saved = messagebox.askyesno("Save before exit", "Do you want to save the current file before exit ?")
443
+ if not saved:
444
+ pass
445
+ else:
446
+ self.save_file()
447
+
448
+ self.files_opened[filename][0].destroy()
449
+ self.main_frame = None
450
+ self.editor = None
451
+ self.line_numbers = None
452
+ self.main_scrollbar_x = None
453
+ self.main_scrollbar_y = None
454
+ del self.files_opened[filename]
455
+ if len(self.files_opened) > 0:
456
+ self.select_file(list(self.files_opened.keys())[0])
457
+ return
458
+
459
+ elif len(self.files_opened) == 0:
460
+ self.upper_frame.destroy()
461
+ self.upper_frame = None
462
+ self.main_frame = None
463
+ self.editor = None
464
+ self.line_numbers = None
465
+ self.main_scrollbar_x = None
466
+ self.main_scrollbar_y = None
467
+ self.file = None
468
+ self.logo_label = tk.Label(self.window, image=self.logo_png)
469
+ self.logo_label.grid(row = 0, column = 0, sticky = "w", pady = (30,0), padx = 30)
470
+ self.open_file_button = tk.Button(self.window, text = "📂 Open File", command = self.open_file, bg = "#202136", relief = "flat", font = ("Consolas", 60), fg = "white")
471
+ self.open_file_button.grid(row = 0, column = 1, pady = (0, 350), padx =(0, 100))
472
+ self.exit_file_button = tk.Button(self.window, text = "🚪 Exit App", bg = "#202136", command = self.window.quit, relief = "flat", font = ("Consolas", 60), fg = "white")
473
+ self.exit_file_button.grid(row = 0, column = 1, pady = (350, 0), padx =(0, 100))
474
+
475
+ def run_file(self, event=None):
476
+ if not self.file:
477
+ messagebox.showerror("No File", "Currently No File is opened")
478
+ return
479
+ exe = os.path.splitext(self.file)[0] + ".exe"
480
+
481
+ subprocess.Popen(f'cmd /k gcc "{self.file}" -o "{exe}" && "{exe}" & pause & exit', creationflags=subprocess.CREATE_NEW_CONSOLE)
482
+
483
+ def select_file(self, filename):
484
+ if filename == None:
485
+ return
486
+
487
+ if self.main_frame and self.main_frame.winfo_ismapped():
488
+ self.main_frame.grid_remove()
489
+ self.main_frame, self.editor, self.line_numbers, self.main_scrollbar_x, self.main_scrollbar_y = self.files_opened[filename]
490
+ self.main_frame.grid()
491
+ self.file = filename
492
+
493
+ def open_file(self, event=None):
494
+ filename = filedialog.askopenfilename(
495
+ filetypes=[
496
+ ("C Files", "*.c *.h")
497
+ ]
498
+ )
499
+ if not filename:
500
+ return
501
+
502
+ if filename in self.files_opened and filename != self.file:
503
+ self.select_file(filename)
504
+ return
505
+
506
+ size = os.path.getsize(filename)
507
+ size = size / 1024**2
508
+ if (size) > 1:
509
+ 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 ?")
510
+ if not permission:
511
+ return
512
+ text = None
513
+ try:
514
+ with open(filename, "r", encoding="utf-8") as f:
515
+ text = f.read().expandtabs(4)
516
+ except Exception as e:
517
+ messagebox.showerror("Unable", f"Unable to Load File {e}")
518
+
519
+ if self.file:
520
+ self.hide_file(self.file)
521
+ self.add_file(filename)
522
+ self.editor.delete("1.0", "end")
523
+ self.editor.insert("1.0", text)
524
+ self.multiline_comment = False
525
+ last_line = int(self.editor.index("end-1c").split(".")[0])
526
+
527
+ for line in range(1, last_line + 1):
528
+ self.syntax_highlight(f"{line}.0", f"{line}.end")
529
+
530
+ self.file = filename
531
+ self.editor.edit_modified(False)
532
+ self.window.title(f"CLIDE - {self.file}")
533
+ self.update_clide()
534
+
535
+ def save_file(self, event=None):
536
+ if not self.file:
537
+ return
538
+
539
+ with open(self.file, "w", encoding="utf-8") as f:
540
+ f.write(self.editor.get("1.0", "end-1c"))
541
+
542
+ self.update_clide()
543
+ self.editor.edit_modified(False)
544
+ self.window.title(f"CLIDE - {self.file}")
545
+ self.is_saved = True
546
+
547
+ def saveas_file(self, event=None):
548
+ path = filedialog.asksaveasfilename(
549
+ defaultextension=".c",
550
+ filetypes=[("C source", "*.c"), ("All Files", "*.*")]
551
+ )
552
+ if not path:
553
+ return
554
+ with open(path, "w", encoding="utf-8") as f:
555
+ f.write(self.editor.get("1.0", "end-1c"))
556
+ self.file = path
557
+ self.editor.edit_modified(False)
558
+ self.window.title(f"CLIDE - {self.file}")
559
+ self.update_clide()
560
+
561
+ def style_configurator(self, event = None):
562
+ win = tk.Toplevel(self.window)
563
+ win.attributes("-topmost", True)
564
+ win.title("Style Configurator")
565
+ x = int((win.winfo_screenwidth() - win.winfo_screenwidth() / 3) // 2)
566
+ y = int((win.winfo_screenheight() - (win.winfo_screenheight() / 2.5) - 75) // 2)
567
+ win.geometry(f"{int(win.winfo_screenwidth() / 3)}x{int(win.winfo_screenheight() / 2.5)}+{x}+{y}")
568
+ try:
569
+ win.iconbitmap(LOGO_ICO)
570
+ except:
571
+ messagebox.showerror("Logo Error", f"Unable to find {LOGO_ICO}")
572
+ win.focus_force()
573
+ win.focus_set()
574
+ win.configure(bg=self.bgcolor)
575
+ win.grid_rowconfigure(0, weight = 1)
576
+ win.grid_rowconfigure(1, weight = 1)
577
+ win.grid_rowconfigure(2, weight = 1)
578
+ win.grid_columnconfigure(0, weight = 1)
579
+ win.grid_columnconfigure(1, weight = 1)
580
+
581
+ def change_fg():
582
+ fg = colorchooser.askcolor()
583
+ if not fg[1]:
584
+ return
585
+ fg = fg[1]
586
+ self.fgcolor = fg
587
+ self.editor.configure(fg = self.fgcolor)
588
+ fg_button.config(text=f"{self.fgcolor} ➕", fg=self.fgcolor)
589
+ self.update_clide()
590
+
591
+ def change_bg():
592
+ bg = colorchooser.askcolor()
593
+ if not bg[1]:
594
+ return
595
+ bg = bg[1]
596
+ self.bgcolor = bg
597
+ self.editor.configure(bg = self.bgcolor)
598
+ bg_button.config(text=f"{self.bgcolor} ➕", fg=self.bgcolor)
599
+ self.line_numbers.configure(bg = self.bgcolor)
600
+ self.update_clide()
601
+
602
+ tk.Label(win, text = "Foreground Colour ", font = (self.font, 14), bg = self.bgcolor ,fg = "gray70").grid(row = 0, column = 0, padx = 30, sticky = "w")
603
+ fg_button = tk.Button(win, relief = "flat",font = (self.font, 14), text = f"{self.fgcolor} ➕", bg ="gray30" ,fg = self.fgcolor, command = change_fg)
604
+ fg_button.grid(row = 0, column = 1, sticky = "w", columnspan = 1)
605
+
606
+ tk.Label(win, text = "Background Colour ",font = (self.font, 14), bg = self.bgcolor ,fg = "gray70").grid(row = 1, column = 0, padx = 30, sticky = "w")
607
+ bg_button = tk.Button(win, relief = "flat",font = (self.font, 14), text = f"{self.bgcolor} ➕", bg ="gray30" ,fg = self.fgcolor, command = change_bg)
608
+ bg_button.grid(row = 1, column = 1, sticky = "w", columnspan = 1)
609
+
610
+ tk.Label(
611
+ win,
612
+ text="Font",
613
+ font=(self.font, 14),
614
+ bg=self.bgcolor,
615
+ fg="gray70"
616
+ ).grid(row=2, column=0, padx = 30, sticky="w")
617
+
618
+ choice = tk.StringVar(value=self.font)
619
+
620
+ def change_font(event = None):
621
+ self.font = combo.get()
622
+ self.editor.configure(font = (self.font, self.fontsize))
623
+ self.update_clide()
624
+
625
+ fonts = sorted(tkfont.families())
626
+ combo = ttk.Combobox(
627
+ win,
628
+ textvariable=choice,
629
+ values=fonts,
630
+ state="readonly",
631
+ width=30,
632
+ )
633
+ combo.grid(row=2, column=1, padx=10, pady=5, sticky="w")
634
+ win.after(100, lambda: combo.set(self.font))
635
+ combo.bind("<<ComboboxSelected>>", change_font)
636
+
637
+ def paste_text(self, event=None):
638
+ start = self.editor.index("insert")
639
+
640
+ try:
641
+ data = self.editor.clipboard_get()
642
+ except tk.TclError:
643
+ return "break"
644
+ self.editor.insert("insert", data)
645
+
646
+ end = self.editor.index(f"{start}+{len(data)}c")
647
+ pasted_first_line = int(self.editor.index(start).split(".")[0])
648
+ pasted_last_line = int(self.editor.index(end).split(".")[0])
649
+
650
+ for line in range(pasted_first_line, pasted_last_line + 1):
651
+ self.syntax_highlight(f"{line}.0", f"{line}.end")
652
+
653
+ return "break"
654
+
655
+ def zoom_text(self, event=None):
656
+ if event:
657
+ if event.delta > 0:
658
+ if self.fontsize >= 80:
659
+ return
660
+ self.fontsize += 1
661
+ self.editor.configure(font=(self.font, self.fontsize))
662
+ self.line_numbers_width += 1
663
+ self.line_numbers.configure(width = self.line_numbers_width)
664
+ self.update_clide()
665
+
666
+ elif event.delta < 0:
667
+ if self.fontsize <= 10:
668
+ return
669
+ self.fontsize -= 1
670
+ self.editor.configure(font=(self.font, self.fontsize))
671
+ self.line_numbers_width -= 1
672
+ self.line_numbers.configure(width = self.line_numbers_width)
673
+ self.update_clide()
674
+
675
+ def indent_line(self, event=None):
676
+ line = self.editor.get("insert linestart", "insert")
677
+
678
+ indent = len(line) - len(line.lstrip(" "))
679
+
680
+ if line.rstrip().endswith(("{", ":")):
681
+ indent += self.indent_size
682
+ elif line.rstrip().endswith("}"):
683
+ indent -= self.indent_size
684
+ self.editor.insert("insert", "\n" + " " * indent)
685
+ return "break"
686
+
687
+ def syntax_highlight(self, start, end):
688
+ self.editor.tag_remove("keyword", start, end)
689
+ self.editor.tag_remove("type", start, end)
690
+ self.editor.tag_remove("functions", start, end)
691
+ self.editor.tag_remove("string", start, end)
692
+ self.editor.tag_remove("comment", start, "end")
693
+ self.editor.tag_remove("preprocessor", start, end)
694
+ self.editor.tag_remove("brackets", start, end)
695
+
696
+ words = self.editor.get(start, end)
697
+ lc = len(words)
698
+
699
+ if self.multiline_comment and words.find("*/") == -1 and words.find("/*") == -1:
700
+ self.editor.tag_add("comment", start, end)
701
+ return
702
+
703
+ word = ""
704
+ word_start = 0
705
+
706
+ in_string = False
707
+ in_char = False
708
+ in_preprocessor = False
709
+
710
+ string_start = 0
711
+ char_start = 0
712
+
713
+ IDENT = "_abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"
714
+
715
+ i = 0
716
+ while i < lc:
717
+
718
+ ch = words[i]
719
+
720
+ if not in_string and not in_char and words[i:i+2] == "//":
721
+ self.editor.tag_add("comment", f"{start}+{i}c", end)
722
+ break
723
+
724
+ elif not in_string and not in_char and words[i:i+2] == "/*":
725
+ close = words.find("*/", i + 2)
726
+ if close == -1:
727
+ self.multiline_comment = True
728
+ self.editor.tag_add("comment", f"{start}+{i}c", end)
729
+ break
730
+ else:
731
+ self.editor.tag_add("comment", f"{start}+{i}c", f"{start}+{close+2}c")
732
+ i = close + 2
733
+ word = ""
734
+ continue
735
+
736
+ elif self.multiline_comment and words[i:i+2] == "*/":
737
+ self.multiline_comment = False
738
+ self.editor.tag_add("comment", start, f"{start}+{i+2}c")
739
+ i += 2
740
+ continue
741
+
742
+ if ch == '"':
743
+
744
+ if not in_string:
745
+ in_string = True
746
+ string_start = i
747
+ else:
748
+ in_string = False
749
+ self.editor.tag_add(
750
+ "string",
751
+ f"{start}+{string_start}c",
752
+ f"{start}+{i+1}c"
753
+ )
754
+
755
+ i += 1
756
+ continue
757
+
758
+ if ch == "'":
759
+
760
+ if not in_char:
761
+ in_char = True
762
+ char_start = i
763
+ else:
764
+ in_char = False
765
+ self.editor.tag_add(
766
+ "string",
767
+ f"{start}+{char_start}c",
768
+ f"{start}+{i+1}c"
769
+ )
770
+
771
+ i += 1
772
+ continue
773
+
774
+ if in_string or in_char:
775
+ i += 1
776
+ continue
777
+
778
+ if ch == "#":
779
+ self.editor.tag_add("preprocessor", f"{start}+{i}c", end)
780
+ break
781
+
782
+ if ch.isalnum() or ch == "_":
783
+
784
+ if not word:
785
+ word_start = i
786
+
787
+ word += ch
788
+
789
+ next_char = words[i + 1] if i + 1 < lc else " "
790
+
791
+ if next_char not in IDENT:
792
+
793
+ if word in C_TYPES:
794
+ self.editor.tag_add(
795
+ "type",
796
+ f"{start}+{word_start}c",
797
+ f"{start}+{i+1}c"
798
+ )
799
+
800
+ elif word in C_KEYWORDS:
801
+ self.editor.tag_add(
802
+ "keyword",
803
+ f"{start}+{word_start}c",
804
+ f"{start}+{i+1}c"
805
+ )
806
+
807
+ elif word in C_FUNCTIONS:
808
+ self.editor.tag_add(
809
+ "functions",
810
+ f"{start}+{word_start}c",
811
+ f"{start}+{i+1}c"
812
+ )
813
+
814
+ word = ""
815
+
816
+ else:
817
+ word = ""
818
+
819
+ if ch in "{}()[]":
820
+ self.editor.tag_add(
821
+ "brackets",
822
+ f"{start}+{i}c",
823
+ f"{start}+{i+1}c"
824
+ )
825
+
826
+ i += 1
827
+
828
+ def update_clide(self, event=None):
829
+ start = self.editor.index("insert linestart")
830
+ end = self.editor.index("insert lineend")
831
+ self.syntax_highlight(start, end)
832
+ if self.editor.edit_modified() and self.file:
833
+ self.window.title(f"CLIDE - *{self.file}")
834
+ self.is_saved = False
835
+
836
+ self.line_numbers.delete("all")
837
+ line_count = int(self.editor.index("end-1c").split(".")[0])
838
+ digits = len(str(line_count))
839
+ self.line_numbers.config(width=digits * self.fontsize + 1)
840
+ index = self.editor.index("@0,0")
841
+
842
+ while True:
843
+ info = self.editor.dlineinfo(index)
844
+ if info is None:
845
+ break
846
+
847
+ y = info[1]
848
+ line = index.split(".")[0]
849
+
850
+ self.line_numbers.create_text(5, y, font = (self.font, self.fontsize), fill=self.fgcolor, text=line, anchor="nw")
851
+ index = self.editor.index(f"{index}+1line")
852
+
853
+ def about_info(self, event = None):
854
+ win = tk.Toplevel(self.window)
855
+ win.attributes("-topmost", True)
856
+ win.title("About and Info")
857
+ try:
858
+ win.iconbitmap(LOGO_ICO)
859
+ except:
860
+ messagebox.showerror("Logo Error", f"Unable to find {LOGO_ICO}")
861
+ win.focus_force()
862
+ win.focus_set()
863
+ win.configure(bg=self.bgcolor)
864
+ tk.Label(win, text ="Software name : CLIDE", font = (self.font, 16), fg = self.fgcolor, bg = self.bgcolor).pack(pady=10, anchor = "nw")
865
+ tk.Label(win, text =f"Software version : {CLIDE_VERSION}", font = (self.font, 16), fg = self.fgcolor, bg = self.bgcolor).pack(pady=10, anchor = "nw")
866
+ tk.Label(win, text ="Maintainer : Moinak debnath", font = (self.font, 16), fg = self.fgcolor, bg = self.bgcolor).pack(pady=10, anchor = "nw")
867
+ tk.Label(win, text ="Contributors : Claude (AI assistance)", font = (self.font, 16), fg = self.fgcolor, bg = self.bgcolor).pack(pady=10, anchor = "nw")
868
+ 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")
869
+ tk.Label(win, text ="License : MIT", font = (self.font, 16), fg = self.fgcolor, bg = self.bgcolor).pack(pady=10, anchor = "nw")
870
+
871
+ win.update_idletasks()
872
+
873
+ w = win.winfo_width()
874
+ h = win.winfo_height()
875
+
876
+ x = (win.winfo_screenwidth() - w) // 2
877
+ y = ((win.winfo_screenheight() - h) // 2) - 50
878
+
879
+ win.geometry(f"{w}x{h}+{x}+{y}")
880
+
881
+ def main():
882
+ window = WINDOW()
883
+ window.window.mainloop()
884
+
885
+
886
+ if __name__ == "__main__":
887
+ main()
Binary file
Binary file
@@ -0,0 +1,106 @@
1
+ Metadata-Version: 2.4
2
+ Name: clide-editor
3
+ Version: 0.2.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
+ ## Changelog
34
+
35
+ - Added Proper UI at the Start
36
+ - Added Multi file management system
37
+
38
+ ## Features
39
+
40
+ - 🎨 **Syntax highlighting** for C — keywords, types, functions, strings, char literals, comments (single-line and block), numbers, and preprocessor directives
41
+ - 🔢 **Line numbers** that track scrolling and zoom
42
+ - 🔍 **Zoom in/out** with `Ctrl + Mouse Wheel`
43
+ - ⏎ **Auto-indent** — adds/removes indentation automatically after `{`, `}`, and `:`
44
+ - ▶️ **Run with F5** — compiles your file with `gcc` and runs it in a new console window
45
+ - 💾 **Open / Save / Save As** from the File menu or `Ctrl+O` / `Ctrl+S`
46
+ - 📋 **Paste-aware highlighting** — pasted multi-line code gets highlighted properly, not just the current line
47
+ - 🎨 **Style Configurator** — change background, foreground colour and also fonts
48
+ - 🖱️ **Undo/redo support** (unlimited undo history)
49
+ - 🗂️ **Multi file editor** -- Manage and code multiple files in on go.
50
+
51
+ ## Requirements
52
+
53
+ - Python 3.x with `tkinter` (usually bundled with Python on Windows)
54
+ - `gcc` installed and available on your system `PATH` (for the Run feature)
55
+ - Windows — the "Run" feature and maximized window launch currently rely on Windows-specific behavior (see Limitations below)
56
+
57
+ ## Getting Started
58
+
59
+ Install the latest version:
60
+
61
+ ```bash
62
+ pip install clide-editor
63
+ ```
64
+
65
+ Or install this specific version:
66
+
67
+ ```bash
68
+ pip install clide-editor==0.2.0
69
+ ```
70
+
71
+ Run CLIDE:
72
+
73
+ ```bash
74
+ python -m clide
75
+ ```
76
+
77
+ Open a `.c` file with `Ctrl+O`, write some code, hit `F5` to compile and run it.
78
+
79
+ ## Version
80
+
81
+ **v0.2.0** — Things work, but expect rough edges.
82
+
83
+ ## Limitations
84
+
85
+ - **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.
86
+ - **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.
87
+ - **No build configuration** — compilation is a hardcoded `gcc file.c -o file.exe`, no custom flags, no Makefile support.
88
+ - **No autocomplete, linting, or error highlighting** — you find out about bugs when `gcc` yells at you.
89
+ - **No find & replace** yet.
90
+
91
+ ## To Be Featured (Roadmap)
92
+
93
+ - [ ] Cross-platform support (Linux/macOS build + run)
94
+ - [ ] Find & Replace
95
+ - [ ] Custom compiler flags / build settings
96
+ - [ ] Bracket matching + auto-close brackets
97
+ - [ ] Inline error markers from `gcc` output
98
+ - [ ] Proper packaging (so you don't need Python installed to run it)
99
+
100
+ ## Contributing
101
+
102
+ This is a small personal project, but if you spot a bug or have an idea, feel free to open an issue or PR.
103
+
104
+ ## License
105
+
106
+ See [LICENSE](LICENSE) for details.
@@ -0,0 +1,13 @@
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/icons/logo.png
9
+ clide_editor.egg-info/PKG-INFO
10
+ clide_editor.egg-info/SOURCES.txt
11
+ clide_editor.egg-info/dependency_links.txt
12
+ clide_editor.egg-info/entry_points.txt
13
+ 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.2.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","icons/*.png"]
@@ -0,0 +1,4 @@
1
+ [egg_info]
2
+ tag_build =
3
+ tag_date = 0
4
+