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.
- clide_editor-0.2.0/LICENSE +21 -0
- clide_editor-0.2.0/PKG-INFO +106 -0
- clide_editor-0.2.0/README.md +84 -0
- clide_editor-0.2.0/clide/__init__.py +5 -0
- clide_editor-0.2.0/clide/__main__.py +4 -0
- clide_editor-0.2.0/clide/clide.py +887 -0
- clide_editor-0.2.0/clide/icons/logo.ico +0 -0
- clide_editor-0.2.0/clide/icons/logo.png +0 -0
- clide_editor-0.2.0/clide_editor.egg-info/PKG-INFO +106 -0
- clide_editor-0.2.0/clide_editor.egg-info/SOURCES.txt +13 -0
- clide_editor-0.2.0/clide_editor.egg-info/dependency_links.txt +1 -0
- clide_editor-0.2.0/clide_editor.egg-info/entry_points.txt +2 -0
- clide_editor-0.2.0/clide_editor.egg-info/top_level.txt +1 -0
- clide_editor-0.2.0/pyproject.toml +37 -0
- clide_editor-0.2.0/setup.cfg +4 -0
|
@@ -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,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 @@
|
|
|
1
|
+
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
clide
|
|
@@ -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"]
|