nexus-dsl 1.0.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,161 @@
1
+ Metadata-Version: 2.4
2
+ Name: nexus-dsl
3
+ Version: 1.0.0
4
+ Summary: NEXUS: A Custom Domain-Specific Scripting Language (DSL) for local automation
5
+ Author-email: Yuvneil <yuvneiledu44@gmail.com>
6
+ Classifier: Programming Language :: Python :: 3
7
+ Classifier: License :: OSI Approved :: MIT License
8
+ Classifier: Operating System :: Microsoft :: Windows
9
+ Requires-Python: >=3.10
10
+ Description-Content-Type: text/markdown
11
+ Requires-Dist: colorama>=0.4.6
12
+ Requires-Dist: plyer>=2.1.0
13
+ Requires-Dist: pyttsx3>=2.90
14
+
15
+ # NEXUS: A Custom Domain-Specific Scripting Language (DSL)
16
+
17
+ NEXUS is an elegant, cross-platform, domain-specific scripting language engineered entirely in Python. It abstracts complex localized operating system tasks, directory architectures, cryptographic transformations, and core machine telemetry workflows into a highly readable, human-centric syntax layout [Example 4].
18
+
19
+ Developed as a breakthrough milestone during the First-Year Passed Industrial Training curriculum at Lovely Professional University (LPU), Jalandhar, this framework implements a modular token parsing architecture that lets you automate system scripts natively.
20
+
21
+ ---
22
+
23
+ ## 🚀 Installation & Setup
24
+
25
+ Install the stable release of the NEXUS engine directly from PyPI using `pip`:
26
+
27
+ ```bash
28
+ pip install nexus-dsl
29
+ ```
30
+
31
+ *(Note: If the name 'nexus' is already reserved on PyPI, it is standard convention to register it as `nexus-dsl` or `nexus-runtime` while keeping the package import name as `nexus`.)*
32
+
33
+ ### External Dependencies
34
+ NEXUS requires a few lightweight libraries to power its native notification toaster and hardware audio modules:
35
+ ```bash
36
+ pip install colorama plyer pyttsx3
37
+ ```
38
+
39
+ ---
40
+
41
+ ## 💻 Python Integration API
42
+
43
+ You can easily load and run `.nxs` automation scripts straight from your standard Python files.
44
+
45
+ ```python
46
+ from nexus import nexus
47
+
48
+ # Simply pass the path of your .nxs script file to the core execution engine
49
+ nexus.nexus("main.nxs")
50
+ ```
51
+
52
+ ---
53
+
54
+ ## 📖 Keyword Reference Manual & Syntax Specs
55
+
56
+ NEXUS statement expressions read line-by-line. Comments must begin with a `#` token. Any multi-word string parameters containing spaces must be cleanly wrapped inside double quotes (`"..."`).
57
+
58
+ ### 1. Console Operations & Core Logging
59
+ * **`Show [string]`**
60
+ Strips enclosing quote markers and prints clean string characters directly onto the active console view.
61
+ *Syntax:* `Show "Hello, World!"`
62
+ * **`Wait [seconds]`**
63
+ Pauses the script execution stream for an integer or floating-point timeline duration. Generates a high-contrast red error message if the parameter value is non-numeric.
64
+ *Syntax:* `Wait 1.5`
65
+ * **`Speak [string]`**
66
+ Hooks directly into your machine's hardware sound drivers to speak a line of text out loud natively using offline speech synthesis.
67
+ *Syntax:* `Speak "Automation sequence initiated"`
68
+ * **`Notify "[Title]" "[Message]"`**
69
+ Uses a token slice delimiter to push a real, native desktop notification toast banner into the system screen space. Requires both parameters to be wrapped in double quotes.
70
+ *Syntax:* `Notify "NEXUS Core" "Task Completed Successfully"`
71
+
72
+ ### 2. File & Storage Operations
73
+ * **`Create [filename]`**
74
+ Safely generates an empty file inside your active working workspace folder if it doesn't already exist.
75
+ *Syntax:* `Create log.txt`
76
+ * **`Write [filename] [string]`**
77
+ Completely overwrites a file with a fresh text payload, wiping any trailing historical characters out of the file buffer.
78
+ *Syntax:* `Write log.txt "Initial Payload"`
79
+ * **`MuteWrite [filename] [Line / NewLine] [string]`**
80
+ Appends text data onto the end of a file. Use `Line` to paste characters on the active row, or `NewLine` to prefix a line break.
81
+ *Syntax:* `MuteWrite log.txt NewLine "Appended system note."`
82
+ * **`Truncate [filename]`**
83
+ Instantly clears and zeroes out all data content inside a document without dropping the file pointer from your storage.
84
+ *Syntax:* `Truncate log.txt`
85
+ * **`Delete [filename]`**
86
+ Hard-drops and permanently removes a targeted file path from your computer disk storage.
87
+ *Syntax:* `Delete obsolete.txt`
88
+ * **`Rename [old_filename] [new_filename]`**
89
+ Modifies the naming characteristics of a target file path in-place.
90
+ *Syntax:* `Rename records.txt old_records.txt`
91
+ * **`Copy [source_path] [destination_path]`**
92
+ Clones a localized file into a fresh directory lane safely.
93
+ *Syntax:* `Copy data.txt backup_data.txt`
94
+ * **`Move [filename] [directory_folder]`**
95
+ Relocates an asset file out of your active workspace directory and paths it into a target folder directory.
96
+ *Syntax:* `Move log.txt BackupsFolder`
97
+ * **`SizeOf [unit] [filename]`**
98
+ Uses pattern matching (`match-case`) to convert file weights into human-readable scales including `bytes`, `kb`, `mb`, `gb`, `tb`, `pb`, and `eb`.
99
+ *Syntax:* `SizeOf mb archive.zip`
100
+ * **`Backup [filename]`**
101
+ Creates an automated timestamped duplicate copy of the target file for recovery purposes (e.g., `data_20260616_161022.txt`).
102
+ *Syntax:* `Backup data.txt`
103
+
104
+ ### 3. Directory Management
105
+ * **`MakeDir [base_directory] [new_folder_name]`**
106
+ Joins variables securely to deploy a new nested workspace directory folder.
107
+ *Syntax:* `MakeDir . "BackupsFolder"`
108
+ * **`DelDir [directory_path]`**
109
+ Flashes an engine warning prompt asking for explicit terminal confirmation (`yes/no`) before wiping a directory.
110
+ *Syntax:* `DelDir BackupsFolder`
111
+
112
+ ### 4. Application Control & Cryptography
113
+ * **`Run [executable.exe]`**
114
+ Asynchronously spawns independent system application processes (like `notepad.exe`) without freezing your main interpreter loop.
115
+ *Syntax:* `Run notepad.exe`
116
+ * **`Open [filename]`**
117
+ Launches a text document natively inside the operating system's standard text editor (Notepad).
118
+ *Syntax:* `Open hello.txt`
119
+ * **`Browse [URL]`**
120
+ Triggers your default web browser tool to spin open and target a live web URL natively.
121
+ *Syntax:* `Browse https://lpu.in`
122
+ * **`Progress [seconds]`**
123
+ Renders an active graphical loading progress tracking bar loop (`[██████░░░░]`) directly across the terminal row workspace console over X seconds.
124
+ *Syntax:* `Progress 5`
125
+ * **`Compress [folder_or_file_path]`**
126
+ Packages an independent text file or an entire nested directory workspace into a compressed binary `.zip` archive payload.
127
+ *Syntax:* `Compress "MyProjectFolder"`
128
+ * **`Extract [source_archive.zip] [destination_folder]`**
129
+ Extracts compressed zip archives directly into a targeted folder destination directory path.
130
+ *Syntax:* `Extract archive.zip ExtractedFiles`
131
+ * **`SystemInfo`**
132
+ Pulls operational machine configurations, including kernel type, operating system version, processor architecture, and host network identity node parameters.
133
+ *Syntax:* `SystemInfo`
134
+ * **`Encrypt [filename]`**
135
+ Recursively strips newline markers, processes file lines through a proprietary substitution cipher dictionary matrix, and overwrites with the scrambled hash text payload.
136
+ *Syntax:* `Encrypt secrets.txt`
137
+ * **`Decrypt [filename]`**
138
+ Reverses encrypted files back into natural readable text using an advanced forward lookup character window scanner module.
139
+ *Syntax:* `Decrypt secrets.txt`
140
+
141
+ ---
142
+
143
+ ## 🛠️ Example Automation Script (`main.nxs`)
144
+
145
+ ```text
146
+ # Boot diagnostic evaluation sequences
147
+ SystemInfo
148
+ Wait 1
149
+
150
+ # Manage backup files
151
+ Create telemetry.txt
152
+ Write telemetry.txt "NEXUS Automation Runtime"
153
+ MuteWrite telemetry.txt NewLine "LPU Industrial Passed First Year Assessment"
154
+ SizeOf kb telemetry.txt
155
+
156
+ # Run background applications and secure records
157
+ Run notepad.exe
158
+ Encrypt telemetry.txt
159
+ Speak "Process framework executed cleanly"
160
+ Notify "NEXUS" "Automation routine finished."
161
+ ```
@@ -0,0 +1,147 @@
1
+ # NEXUS: A Custom Domain-Specific Scripting Language (DSL)
2
+
3
+ NEXUS is an elegant, cross-platform, domain-specific scripting language engineered entirely in Python. It abstracts complex localized operating system tasks, directory architectures, cryptographic transformations, and core machine telemetry workflows into a highly readable, human-centric syntax layout [Example 4].
4
+
5
+ Developed as a breakthrough milestone during the First-Year Passed Industrial Training curriculum at Lovely Professional University (LPU), Jalandhar, this framework implements a modular token parsing architecture that lets you automate system scripts natively.
6
+
7
+ ---
8
+
9
+ ## 🚀 Installation & Setup
10
+
11
+ Install the stable release of the NEXUS engine directly from PyPI using `pip`:
12
+
13
+ ```bash
14
+ pip install nexus-dsl
15
+ ```
16
+
17
+ *(Note: If the name 'nexus' is already reserved on PyPI, it is standard convention to register it as `nexus-dsl` or `nexus-runtime` while keeping the package import name as `nexus`.)*
18
+
19
+ ### External Dependencies
20
+ NEXUS requires a few lightweight libraries to power its native notification toaster and hardware audio modules:
21
+ ```bash
22
+ pip install colorama plyer pyttsx3
23
+ ```
24
+
25
+ ---
26
+
27
+ ## 💻 Python Integration API
28
+
29
+ You can easily load and run `.nxs` automation scripts straight from your standard Python files.
30
+
31
+ ```python
32
+ from nexus import nexus
33
+
34
+ # Simply pass the path of your .nxs script file to the core execution engine
35
+ nexus.nexus("main.nxs")
36
+ ```
37
+
38
+ ---
39
+
40
+ ## 📖 Keyword Reference Manual & Syntax Specs
41
+
42
+ NEXUS statement expressions read line-by-line. Comments must begin with a `#` token. Any multi-word string parameters containing spaces must be cleanly wrapped inside double quotes (`"..."`).
43
+
44
+ ### 1. Console Operations & Core Logging
45
+ * **`Show [string]`**
46
+ Strips enclosing quote markers and prints clean string characters directly onto the active console view.
47
+ *Syntax:* `Show "Hello, World!"`
48
+ * **`Wait [seconds]`**
49
+ Pauses the script execution stream for an integer or floating-point timeline duration. Generates a high-contrast red error message if the parameter value is non-numeric.
50
+ *Syntax:* `Wait 1.5`
51
+ * **`Speak [string]`**
52
+ Hooks directly into your machine's hardware sound drivers to speak a line of text out loud natively using offline speech synthesis.
53
+ *Syntax:* `Speak "Automation sequence initiated"`
54
+ * **`Notify "[Title]" "[Message]"`**
55
+ Uses a token slice delimiter to push a real, native desktop notification toast banner into the system screen space. Requires both parameters to be wrapped in double quotes.
56
+ *Syntax:* `Notify "NEXUS Core" "Task Completed Successfully"`
57
+
58
+ ### 2. File & Storage Operations
59
+ * **`Create [filename]`**
60
+ Safely generates an empty file inside your active working workspace folder if it doesn't already exist.
61
+ *Syntax:* `Create log.txt`
62
+ * **`Write [filename] [string]`**
63
+ Completely overwrites a file with a fresh text payload, wiping any trailing historical characters out of the file buffer.
64
+ *Syntax:* `Write log.txt "Initial Payload"`
65
+ * **`MuteWrite [filename] [Line / NewLine] [string]`**
66
+ Appends text data onto the end of a file. Use `Line` to paste characters on the active row, or `NewLine` to prefix a line break.
67
+ *Syntax:* `MuteWrite log.txt NewLine "Appended system note."`
68
+ * **`Truncate [filename]`**
69
+ Instantly clears and zeroes out all data content inside a document without dropping the file pointer from your storage.
70
+ *Syntax:* `Truncate log.txt`
71
+ * **`Delete [filename]`**
72
+ Hard-drops and permanently removes a targeted file path from your computer disk storage.
73
+ *Syntax:* `Delete obsolete.txt`
74
+ * **`Rename [old_filename] [new_filename]`**
75
+ Modifies the naming characteristics of a target file path in-place.
76
+ *Syntax:* `Rename records.txt old_records.txt`
77
+ * **`Copy [source_path] [destination_path]`**
78
+ Clones a localized file into a fresh directory lane safely.
79
+ *Syntax:* `Copy data.txt backup_data.txt`
80
+ * **`Move [filename] [directory_folder]`**
81
+ Relocates an asset file out of your active workspace directory and paths it into a target folder directory.
82
+ *Syntax:* `Move log.txt BackupsFolder`
83
+ * **`SizeOf [unit] [filename]`**
84
+ Uses pattern matching (`match-case`) to convert file weights into human-readable scales including `bytes`, `kb`, `mb`, `gb`, `tb`, `pb`, and `eb`.
85
+ *Syntax:* `SizeOf mb archive.zip`
86
+ * **`Backup [filename]`**
87
+ Creates an automated timestamped duplicate copy of the target file for recovery purposes (e.g., `data_20260616_161022.txt`).
88
+ *Syntax:* `Backup data.txt`
89
+
90
+ ### 3. Directory Management
91
+ * **`MakeDir [base_directory] [new_folder_name]`**
92
+ Joins variables securely to deploy a new nested workspace directory folder.
93
+ *Syntax:* `MakeDir . "BackupsFolder"`
94
+ * **`DelDir [directory_path]`**
95
+ Flashes an engine warning prompt asking for explicit terminal confirmation (`yes/no`) before wiping a directory.
96
+ *Syntax:* `DelDir BackupsFolder`
97
+
98
+ ### 4. Application Control & Cryptography
99
+ * **`Run [executable.exe]`**
100
+ Asynchronously spawns independent system application processes (like `notepad.exe`) without freezing your main interpreter loop.
101
+ *Syntax:* `Run notepad.exe`
102
+ * **`Open [filename]`**
103
+ Launches a text document natively inside the operating system's standard text editor (Notepad).
104
+ *Syntax:* `Open hello.txt`
105
+ * **`Browse [URL]`**
106
+ Triggers your default web browser tool to spin open and target a live web URL natively.
107
+ *Syntax:* `Browse https://lpu.in`
108
+ * **`Progress [seconds]`**
109
+ Renders an active graphical loading progress tracking bar loop (`[██████░░░░]`) directly across the terminal row workspace console over X seconds.
110
+ *Syntax:* `Progress 5`
111
+ * **`Compress [folder_or_file_path]`**
112
+ Packages an independent text file or an entire nested directory workspace into a compressed binary `.zip` archive payload.
113
+ *Syntax:* `Compress "MyProjectFolder"`
114
+ * **`Extract [source_archive.zip] [destination_folder]`**
115
+ Extracts compressed zip archives directly into a targeted folder destination directory path.
116
+ *Syntax:* `Extract archive.zip ExtractedFiles`
117
+ * **`SystemInfo`**
118
+ Pulls operational machine configurations, including kernel type, operating system version, processor architecture, and host network identity node parameters.
119
+ *Syntax:* `SystemInfo`
120
+ * **`Encrypt [filename]`**
121
+ Recursively strips newline markers, processes file lines through a proprietary substitution cipher dictionary matrix, and overwrites with the scrambled hash text payload.
122
+ *Syntax:* `Encrypt secrets.txt`
123
+ * **`Decrypt [filename]`**
124
+ Reverses encrypted files back into natural readable text using an advanced forward lookup character window scanner module.
125
+ *Syntax:* `Decrypt secrets.txt`
126
+
127
+ ---
128
+
129
+ ## 🛠️ Example Automation Script (`main.nxs`)
130
+
131
+ ```text
132
+ # Boot diagnostic evaluation sequences
133
+ SystemInfo
134
+ Wait 1
135
+
136
+ # Manage backup files
137
+ Create telemetry.txt
138
+ Write telemetry.txt "NEXUS Automation Runtime"
139
+ MuteWrite telemetry.txt NewLine "LPU Industrial Passed First Year Assessment"
140
+ SizeOf kb telemetry.txt
141
+
142
+ # Run background applications and secure records
143
+ Run notepad.exe
144
+ Encrypt telemetry.txt
145
+ Speak "Process framework executed cleanly"
146
+ Notify "NEXUS" "Automation routine finished."
147
+ ```
File without changes
@@ -0,0 +1,217 @@
1
+ import os
2
+ import sys
3
+ import subprocess
4
+ import time
5
+ import shutil
6
+ import platform
7
+ import zipfile
8
+ import webbrowser
9
+ import pyttsx3
10
+ from colorama import Fore, init
11
+ from plyer import notification
12
+ from datetime import datetime
13
+ from pathlib import Path
14
+
15
+ engine = pyttsx3.init()
16
+ engine.setProperty("rate", 150)
17
+
18
+ init(autoreset=True)
19
+
20
+ def check_if_file_exists(FILE_NAME):
21
+ if not os.path.exists(FILE_NAME):
22
+ print(Fore.RED + "FileNotFound Error: ", end = "")
23
+ print(f"Designated file: ", end = "")
24
+ print(Fore.GREEN + f"\"{FILE_NAME}\"", end = "")
25
+ print(" not found in the mentioned directory", end = "")
26
+ sys.exit()
27
+
28
+ def check_if_dir_exists(dir):
29
+ folder = Path(dir)
30
+ if not folder.is_dir():
31
+ print(Fore.RED + "DirectoryNotFound Error: ", end = "")
32
+ print(f"Designated directory: ", end = "")
33
+ print(Fore.GREEN + f"\"{dir}\"", end = "")
34
+ print(" not found")
35
+ sys.exit()
36
+
37
+ def show(li: list | str):
38
+ if type(li)==list:
39
+ st = " ".join(li)
40
+ print(st)
41
+ else:
42
+ print(li)
43
+
44
+ def create(FILE_NAME: str):
45
+ if not os.path.exists(FILE_NAME):
46
+ with open(FILE_NAME, "w") as file:
47
+ pass
48
+
49
+ def write(FILE_NAME:str, text: str):
50
+ check_if_file_exists(FILE_NAME)
51
+
52
+ file = open(FILE_NAME, "w")
53
+ file.write(text)
54
+
55
+ def open_file(FILE_NAME: str):
56
+ check_if_file_exists(FILE_NAME)
57
+ subprocess.Popen(['notepad.exe', FILE_NAME])
58
+
59
+ def delete(FILE_NAME: str):
60
+ check_if_file_exists(FILE_NAME)
61
+ os.remove(FILE_NAME)
62
+
63
+ def wait(time_d: int | float):
64
+ time.sleep(time_d)
65
+
66
+ def MuteWrite(FILE_NAME: str, text: str):
67
+ check_if_file_exists(FILE_NAME)
68
+ file = open(FILE_NAME, "a")
69
+ file.write(text)
70
+
71
+ def rename(FILE_NAME: str, FILE_NAME2: str):
72
+ check_if_file_exists(FILE_NAME)
73
+ os.rename(FILE_NAME, FILE_NAME2)
74
+
75
+ def copy(FILE_NAME: str, FILE_NAME2: str):
76
+ check_if_file_exists(FILE_NAME)
77
+ if not os.path.exists(FILE_NAME2):
78
+ shutil.copy(FILE_NAME, FILE_NAME2)
79
+ else:
80
+ print(Fore.RED + f"File with name {FILE_NAME2} already exists")
81
+
82
+ def run(Application_name: str):
83
+ try:
84
+ subprocess.run(Application_name, shell=True, check=True)
85
+ except Exception as e:
86
+ print(Fore.RED + f"Error while running the application: \"{Application_name}\"")
87
+ print(Fore.YELLOW + f"[OS Debug Details]: {e}")
88
+
89
+ def system_info():
90
+ print(f"OS Platform: {platform.system()}")
91
+ print(f"Kernel: {sys.platform}")
92
+ print(f"Architecture: {platform.architecture()}")
93
+ print(f"Release: {platform.release()}")
94
+ print(f"Version: {platform.version()}")
95
+ print(f"Processor: {platform.processor()}")
96
+ print(f"Machine: {platform.machine()}")
97
+ print(f"Connected Network: {platform.node()}")
98
+
99
+ def notify_(title: str, text: str):
100
+ notification.notify(
101
+ title = title,
102
+ message = text,
103
+ app_name = "AURA",
104
+ timeout = 5
105
+ )
106
+
107
+ def browse(url: str):
108
+ webbrowser.open(url)
109
+
110
+ def backup(FILE_NAME: str):
111
+ check_if_file_exists(FILE_NAME)
112
+ timestamp = datetime.now().strftime("%Y%m%d_%H%M%S")
113
+ name, ext = os.path.splitext(FILE_NAME)
114
+ backup_name = f"{name}_{timestamp}{ext}"
115
+
116
+ copy(FILE_NAME, backup_name)
117
+
118
+ def speak(text: str):
119
+ engine.say(text)
120
+ engine.runAndWait()
121
+
122
+ def make_dir(dir: str, folder_name: str):
123
+ check_if_dir_exists(dir)
124
+ path = os.path.join(dir, folder_name)
125
+ os.makedirs(path, exist_ok=True)
126
+
127
+ def rem_dir(dir: str):
128
+ check_if_dir_exists(dir)
129
+ print(Fore.YELLOW + "Deleting folder will permanently erase all the data inside it!")
130
+ choice = input("Do you want to continue?(yes/no): ").lower()
131
+ if choice == "yes" or choice == "y":
132
+ shutil.rmtree(dir)
133
+ elif choice == "no" or choice =="n":
134
+ pass
135
+ else:
136
+ print(Fore.RED + f"Unknown command entered: {choice}, aborting deletion process")
137
+
138
+ def calc_size(FILE_NAME: str, unit: str):
139
+ check_if_file_exists(FILE_NAME)
140
+ bytes_ = os.path.getsize(FILE_NAME)
141
+ kb = round(bytes_/1024, 2)
142
+ mb = round(kb/1024, 2)
143
+ gb = round(mb/1024, 2)
144
+ tb = round(gb/1024, 2)
145
+ pb = round(tb/1024, 2)
146
+ eb = round(pb/1024, 2)
147
+ match(unit):
148
+ case "bytes":
149
+ print(f"Memory storage of file {FILE_NAME} is {bytes_} bytes")
150
+ case "kb":
151
+ print(f"Memory storage of file {FILE_NAME} is {kb} kb")
152
+ case "mb":
153
+ print(f"Memory storage of file {FILE_NAME} is {mb} mb")
154
+ case "gb":
155
+ print(f"Memory storage of file {FILE_NAME} is {gb} gb")
156
+ case "tb":
157
+ print(f"Memory storage of file {FILE_NAME} is {tb} tb")
158
+ case "pb":
159
+ print(f"Memory storage of file {FILE_NAME} is {pb} pb")
160
+ case "eb":
161
+ print(f"Memory storage of file {FILE_NAME} is {eb} eb")
162
+
163
+ def draw_progress(seconds: str | float):
164
+ total_time = float(seconds)
165
+ steps = 20
166
+ delay = total_time / steps
167
+ for i in range(steps + 1):
168
+ percent = int((i / steps) * 100)
169
+ bar = "█" * i + "░" * (steps - i)
170
+ sys.stdout.write(f"\r[{bar}] {percent}% Complete")
171
+ sys.stdout.flush()
172
+ time.sleep(delay)
173
+ print()
174
+
175
+ def truncate(FILE_NAME):
176
+ check_if_file_exists(FILE_NAME)
177
+ with open(FILE_NAME, "w") as file:
178
+ file.write("")
179
+
180
+ def move(FILE_NAME: str, dir: str):
181
+ check_if_file_exists(FILE_NAME)
182
+ check_if_dir_exists(dir)
183
+ shutil.move(FILE_NAME, dir)
184
+
185
+ import zipfile
186
+
187
+ def zip_unzip(Name: str | list, task: str):
188
+ if task == "zip":
189
+ check_if_file_exists(Name)
190
+
191
+ path = Path(Name)
192
+
193
+ if path.is_dir():
194
+ parent_dir = path.parent
195
+ folder_name = path.name
196
+ output_zip = parent_dir / folder_name
197
+ shutil.make_archive(
198
+ base_name=str(output_zip),
199
+ format='zip',
200
+ root_dir=str(parent_dir),
201
+ base_dir=folder_name
202
+ )
203
+
204
+ else:
205
+ zip_name = f"{path.stem}.zip"
206
+ with zipfile.ZipFile(zip_name, 'w', zipfile.ZIP_DEFLATED) as zipf:
207
+ zipf.write(Name, arcname=path.name)
208
+
209
+ elif task == "unzip":
210
+ check_if_file_exists(Name[0])
211
+
212
+ check_if_dir_exists(Name[1])
213
+ archive = Path(Name[0])
214
+ target = Path(Name[1])
215
+
216
+ with zipfile.ZipFile(archive, 'r') as zip_ref:
217
+ zip_ref.extractall(target)
@@ -0,0 +1,178 @@
1
+ from . import function_executors as fe
2
+ from . import hash
3
+
4
+ LANGUAGE_NAME = "AURA"
5
+
6
+ def clean_quotes(text: str) -> str:
7
+ if text.startswith('"') and text.endswith('"'):
8
+ return text[1:-1]
9
+ return text
10
+
11
+ def execute(list_of_commands: list):
12
+ li: list = list_of_commands
13
+ if "#" in li[0]:
14
+ pass
15
+ elif li[0]=="Show":
16
+ string = " ".join(li[1:len(li)])
17
+ string = clean_quotes(string)
18
+ fe.show(string)
19
+
20
+ elif li[0]=="Create":
21
+ fe.create(li[1])
22
+
23
+ elif li[0]=="Write":
24
+ string = " ".join(li[2:len(li)])
25
+ string = clean_quotes(string)
26
+ fe.write(str(li[1]), string)
27
+
28
+ elif li[0]=="Open":
29
+ fe.open_file(li[1])
30
+
31
+ elif li[0]=="Delete":
32
+ fe.delete(li[1])
33
+
34
+ elif li[0]=="Wait":
35
+ try:
36
+ fe.wait(float(li[1]))
37
+ except ValueError:
38
+ print(fe.Fore.RED + "Given value is not an number for function wait")
39
+ fe.sys.exit()
40
+
41
+ elif li[0]=="MuteWrite":
42
+
43
+ if li[2]=="Line":
44
+ string = " ".join(li[3:len(li)])
45
+ string = clean_quotes(string)
46
+ fe.MuteWrite(li[1], string)
47
+
48
+ elif li[2]=="NewLine":
49
+ string = " ".join(li[3:len(li)])
50
+ string = clean_quotes(string)
51
+ fe.MuteWrite(li[1], f"\n{string}")
52
+
53
+ else:
54
+ print(fe.Fore.RED + f"Expected an argument after file name {li[1]}")
55
+ fe.sys.exit()
56
+
57
+ elif li[0]=="Rename":
58
+ fe.rename(li[1], li[2])
59
+
60
+ elif li[0]=="Copy":
61
+ fe.copy(li[1], li[2])
62
+
63
+ elif li[0]=="Run":
64
+ fe.run(li[1])
65
+
66
+ elif li[0]=="SystemInfo":
67
+ fe.system_info()
68
+
69
+ elif li[0] == "Notify":
70
+ full_arguments = " ".join(li[1:len(li)])
71
+
72
+ quote_indices = [index for index, char in enumerate(full_arguments) if char == '"']
73
+
74
+ if len(quote_indices) == 4:
75
+ title = full_arguments[quote_indices[0] + 1 : quote_indices[1]]
76
+ message = full_arguments[quote_indices[2] + 1 : quote_indices[3]]
77
+
78
+ fe.notify_(title, message)
79
+ else:
80
+ print(fe.Fore.RED + 'Syntax Error: Notify requires "Title" and "Message" wrapped in double quotes.')
81
+ fe.sys.exit()
82
+
83
+ elif li[0] == "Browse":
84
+ fe.browse(li[1])
85
+
86
+ elif li[0] == "Encrypt":
87
+ FILE_NAME = li[1]
88
+ fe.check_if_file_exists(FILE_NAME)
89
+ file = open(FILE_NAME, "r")
90
+ file1_list = FILE_NAME.split(".")
91
+ file1_list[0] = f"{file1_list[0]}2"
92
+ FILE_NAME2 = ".".join(file1_list)
93
+
94
+ is_first_line = True
95
+
96
+ with open(FILE_NAME2, "a") as file2:
97
+ for line in file:
98
+ line = line.replace("\n", "")
99
+
100
+ if is_first_line:
101
+ execute(["MuteWrite", FILE_NAME2, "Line", hash.hash(line)])
102
+ is_first_line = False
103
+ else:
104
+ execute(["MuteWrite", FILE_NAME2, "NewLine", hash.hash(line)])
105
+
106
+ file.close()
107
+
108
+ execute(["Delete", FILE_NAME])
109
+ execute(["Rename", FILE_NAME2, FILE_NAME])
110
+
111
+
112
+ elif li[0] == "Decrypt":
113
+ FILE_NAME = li[1]
114
+ fe.check_if_file_exists(FILE_NAME)
115
+ file = open(FILE_NAME, "r")
116
+ file1_list = FILE_NAME.split(".")
117
+ file1_list[0] = f"{file1_list[0]}2"
118
+ FILE_NAME2 = ".".join(file1_list)
119
+
120
+ is_first_line = True
121
+
122
+ with open(FILE_NAME2, "a") as file2:
123
+ for line in file:
124
+ line = line.replace("\n", "")
125
+
126
+ if is_first_line:
127
+ execute(["MuteWrite", FILE_NAME2, "Line", hash.hash(line, "dehash")])
128
+ is_first_line = False
129
+ else:
130
+ execute(["MuteWrite", FILE_NAME2, "NewLine", hash.hash(line, "dehash")])
131
+
132
+ file.close()
133
+
134
+ execute(["Delete", FILE_NAME])
135
+ execute(["Rename", FILE_NAME2, FILE_NAME])
136
+
137
+
138
+ elif li[0] == "Backup":
139
+ fe.backup(li[1])
140
+
141
+ elif li[0] == "Speak":
142
+ string = " ".join(li[1:len(li)])
143
+ string = clean_quotes(string)
144
+ fe.speak(string)
145
+
146
+ elif li[0] == "MakeDir":
147
+ fe.make_dir(li[1], li[2])
148
+
149
+ elif li[0] == "DelDir":
150
+ if len(li) < 2:
151
+ print(fe.Fore.RED + "Syntax Error: DelDir requires a folder path parameter.")
152
+ fe.sys.exit()
153
+ fe.rem_dir(li[1])
154
+
155
+ elif li[0] == "SizeOf":
156
+ fe.calc_size(li[2], li[1])
157
+
158
+ elif li[0] == "Progress":
159
+ fe.draw_progress(li[1])
160
+
161
+ elif li[0] == "Truncate":
162
+ fe.truncate(li[1])
163
+
164
+ elif li[0] == "Move":
165
+ fe.move(li[1], li[2])
166
+
167
+ elif li[0] == "Compress":
168
+ fe.zip_unzip(li[1], "zip")
169
+
170
+ elif li[0] == "Extract":
171
+ fe.zip_unzip(li[1:3], "unzip")
172
+
173
+ else:
174
+ print(fe.Fore.RED + f"Command ", end = "")
175
+ print(fe.Fore.MAGENTA + f"{li[0]}", end = "")
176
+ print(fe.Fore.RED + f" is not recognized as an internal or external command for the language", end = "")
177
+ print(fe.Fore.GREEN + f" {LANGUAGE_NAME}", end = "")
178
+ fe.sys.exit()
@@ -0,0 +1,137 @@
1
+ def hash(pw: str, hash_or_dehash: str = "hash") -> str:
2
+ default = {
3
+ ' ': "so48oz4igl",
4
+ '!': "cqp2bepgf",
5
+ '"': "6c31mk7ya1",
6
+ '#': "um9axgoy",
7
+ '$': "oo1z3dsz",
8
+ '%': "djetbm7els",
9
+ '&': "ll4vm8dl",
10
+ "'": "b3yc8g9j",
11
+ '(': "bg36gdd5bx",
12
+ ')': "ph1wirauz",
13
+ '*': "61a57ig7",
14
+ '+': "d2hw35n1",
15
+ ',': "pqks18l82n8",
16
+ '-': "xs9t9fzkmifw",
17
+ '.': "92qr5qfcs",
18
+ '/': "ianmknjsmsc",
19
+ '0': "4dw03kn541j",
20
+ '1': "scuiftsfsp",
21
+ '2': "aas1pwbx3",
22
+ '3': "tv4ltnwctc1",
23
+ '4': "fq1ilqiam9",
24
+ '5': "slo0v6vp0q",
25
+ '6': "h5yo2v70nu",
26
+ '7': "yub08e2w",
27
+ '8': "yfe5gtfs01xv",
28
+ '9': "rfq7srqcocs",
29
+ ':': "qo318v3zz",
30
+ ';': "dlazora1",
31
+ '<': "vy6lhq5y",
32
+ '=': "d507m414",
33
+ '>': "aqglfsk84",
34
+ '?': "b4rcvgil",
35
+ '@': "sg8m72f0bo",
36
+ 'A': "cjdn0ga9",
37
+ 'B': "gk2ba6vnh20",
38
+ 'C': "eado9oi2y72",
39
+ 'D': "gezn677xc",
40
+ 'E': "ukarhuug",
41
+ 'F': "iwje65vvza2p",
42
+ 'G': "xz2442vkcdlk",
43
+ 'H': "wiluw5ihsnnf",
44
+ 'I': "5rodt3kw5g75",
45
+ 'J': "6e5lgaps91i",
46
+ 'K': "al4wlffp9",
47
+ 'L': "puprq2gi",
48
+ 'M': "52ywdv7ya948",
49
+ 'N': "9skjt5m7w",
50
+ 'O': "yxwe9ohi795l",
51
+ 'P': "znrdsp60wr2a",
52
+ 'Q': "okhf097ec",
53
+ 'R': "eenm9r8n4ubk",
54
+ 'S': "dj41hglrbp2",
55
+ 'T': "ykb9lpk9k3",
56
+ 'U': "qcu9e3tk7m",
57
+ 'V': "k8d0hw03spaa",
58
+ 'W': "nw7hp6g8",
59
+ 'X': "8tl6yw08",
60
+ 'Y': "d5bars9r",
61
+ 'Z': "p9oznvvli8l",
62
+ '[': "01ycuakh8t9n",
63
+ '\\': "ppybqq9vvk",
64
+ ']': "0qht72y9yt",
65
+ '^': "me09ur5r",
66
+ '_': "t0uufklgauh",
67
+ '`': "gozq6or4n2",
68
+ 'a': "ejx7jl1c23",
69
+ 'b': "k0f6w3nkk80v",
70
+ 'c': "9eltrwl6cje",
71
+ 'd': "3cbfep0f2",
72
+ 'e': "mvtesakcs",
73
+ 'f': "e0qwgp3aml",
74
+ 'g': "sux7tcww0uy2",
75
+ 'h': "x6tnhlas5",
76
+ 'i': "wcq0vme6o",
77
+ 'j': "y4xx0nwah37l",
78
+ 'k': "91icof91",
79
+ 'l': "p128g8tfxj",
80
+ 'm': "iqdntlynt9e9",
81
+ 'n': "h6ernlqdvm",
82
+ 'o': "95r3o7hkzjfb",
83
+ 'p': "39wao8wz",
84
+ 'q': "490pkeji1w",
85
+ 'r': "bn6f6n0n",
86
+ 's': "r7qvsssww0j",
87
+ 't': "0vgi054zxl",
88
+ 'u': "33cvw1kpfpa",
89
+ 'v': "kv6ollgkui5e",
90
+ 'w': "3vijck0s",
91
+ 'x': "gy0ry24j9k",
92
+ 'y': "sg2ussnoqi",
93
+ 'z': "za6vzho263",
94
+ '{': "nso7ciav8",
95
+ '|': "fy9kjp5bgkk",
96
+ '}': "slg03rqso",
97
+ '~': "qh1qndxi0"
98
+ }
99
+
100
+ if hash_or_dehash == "hash":
101
+ pwlist = list(pw)
102
+ new_list = []
103
+ i = 0
104
+ while i < len(pwlist):
105
+ char = pwlist[i]
106
+ if char in default:
107
+ new_list.append(default[char])
108
+ else:
109
+ new_list.append(char)
110
+ i += 1
111
+ return "".join(new_list)
112
+
113
+ elif hash_or_dehash == "dehash":
114
+ reverse_map = {value: key for key, value in default.items()}
115
+
116
+ decoded_chars = []
117
+ index = 0
118
+ text_length = len(pw)
119
+
120
+ while index < text_length:
121
+ matched = False
122
+
123
+ for chunk_size in range(15, 0, -1):
124
+ if index + chunk_size <= text_length:
125
+ substring_probe = pw[index : index + chunk_size]
126
+
127
+ if substring_probe in reverse_map:
128
+ decoded_chars.append(reverse_map[substring_probe])
129
+ index += chunk_size
130
+ matched = True
131
+ break
132
+
133
+ if not matched:
134
+ decoded_chars.append(pw[index])
135
+ index += 1
136
+
137
+ return "".join(decoded_chars)
@@ -0,0 +1,28 @@
1
+ import os
2
+ from colorama import Fore, init
3
+ import sys
4
+ from . import function_passer as fp
5
+
6
+ init(autoreset=True)
7
+
8
+ def nexus(FILE_NAME: str):
9
+ if not os.path.exists(FILE_NAME):
10
+ print(Fore.RED + "FileNotFound Error: ", end = "")
11
+ print("Designated file: ", end = "")
12
+ print(Fore.GREEN + f"\"{FILE_NAME}\"", end = "")
13
+ print(" not found in the mentioned directory", end = "")
14
+ sys.exit()
15
+
16
+ if not FILE_NAME.endswith(".nxs"):
17
+ print(Fore.RED + "Invalid FileType!")
18
+ sys.exit()
19
+
20
+ file = open(FILE_NAME, "r+")
21
+
22
+ for Line in file:
23
+ line_list = Line.split()
24
+ if not line_list:
25
+ continue
26
+ fp.execute(line_list)
27
+
28
+ file.close()
@@ -0,0 +1,161 @@
1
+ Metadata-Version: 2.4
2
+ Name: nexus-dsl
3
+ Version: 1.0.0
4
+ Summary: NEXUS: A Custom Domain-Specific Scripting Language (DSL) for local automation
5
+ Author-email: Yuvneil <yuvneiledu44@gmail.com>
6
+ Classifier: Programming Language :: Python :: 3
7
+ Classifier: License :: OSI Approved :: MIT License
8
+ Classifier: Operating System :: Microsoft :: Windows
9
+ Requires-Python: >=3.10
10
+ Description-Content-Type: text/markdown
11
+ Requires-Dist: colorama>=0.4.6
12
+ Requires-Dist: plyer>=2.1.0
13
+ Requires-Dist: pyttsx3>=2.90
14
+
15
+ # NEXUS: A Custom Domain-Specific Scripting Language (DSL)
16
+
17
+ NEXUS is an elegant, cross-platform, domain-specific scripting language engineered entirely in Python. It abstracts complex localized operating system tasks, directory architectures, cryptographic transformations, and core machine telemetry workflows into a highly readable, human-centric syntax layout [Example 4].
18
+
19
+ Developed as a breakthrough milestone during the First-Year Passed Industrial Training curriculum at Lovely Professional University (LPU), Jalandhar, this framework implements a modular token parsing architecture that lets you automate system scripts natively.
20
+
21
+ ---
22
+
23
+ ## 🚀 Installation & Setup
24
+
25
+ Install the stable release of the NEXUS engine directly from PyPI using `pip`:
26
+
27
+ ```bash
28
+ pip install nexus-dsl
29
+ ```
30
+
31
+ *(Note: If the name 'nexus' is already reserved on PyPI, it is standard convention to register it as `nexus-dsl` or `nexus-runtime` while keeping the package import name as `nexus`.)*
32
+
33
+ ### External Dependencies
34
+ NEXUS requires a few lightweight libraries to power its native notification toaster and hardware audio modules:
35
+ ```bash
36
+ pip install colorama plyer pyttsx3
37
+ ```
38
+
39
+ ---
40
+
41
+ ## 💻 Python Integration API
42
+
43
+ You can easily load and run `.nxs` automation scripts straight from your standard Python files.
44
+
45
+ ```python
46
+ from nexus import nexus
47
+
48
+ # Simply pass the path of your .nxs script file to the core execution engine
49
+ nexus.nexus("main.nxs")
50
+ ```
51
+
52
+ ---
53
+
54
+ ## 📖 Keyword Reference Manual & Syntax Specs
55
+
56
+ NEXUS statement expressions read line-by-line. Comments must begin with a `#` token. Any multi-word string parameters containing spaces must be cleanly wrapped inside double quotes (`"..."`).
57
+
58
+ ### 1. Console Operations & Core Logging
59
+ * **`Show [string]`**
60
+ Strips enclosing quote markers and prints clean string characters directly onto the active console view.
61
+ *Syntax:* `Show "Hello, World!"`
62
+ * **`Wait [seconds]`**
63
+ Pauses the script execution stream for an integer or floating-point timeline duration. Generates a high-contrast red error message if the parameter value is non-numeric.
64
+ *Syntax:* `Wait 1.5`
65
+ * **`Speak [string]`**
66
+ Hooks directly into your machine's hardware sound drivers to speak a line of text out loud natively using offline speech synthesis.
67
+ *Syntax:* `Speak "Automation sequence initiated"`
68
+ * **`Notify "[Title]" "[Message]"`**
69
+ Uses a token slice delimiter to push a real, native desktop notification toast banner into the system screen space. Requires both parameters to be wrapped in double quotes.
70
+ *Syntax:* `Notify "NEXUS Core" "Task Completed Successfully"`
71
+
72
+ ### 2. File & Storage Operations
73
+ * **`Create [filename]`**
74
+ Safely generates an empty file inside your active working workspace folder if it doesn't already exist.
75
+ *Syntax:* `Create log.txt`
76
+ * **`Write [filename] [string]`**
77
+ Completely overwrites a file with a fresh text payload, wiping any trailing historical characters out of the file buffer.
78
+ *Syntax:* `Write log.txt "Initial Payload"`
79
+ * **`MuteWrite [filename] [Line / NewLine] [string]`**
80
+ Appends text data onto the end of a file. Use `Line` to paste characters on the active row, or `NewLine` to prefix a line break.
81
+ *Syntax:* `MuteWrite log.txt NewLine "Appended system note."`
82
+ * **`Truncate [filename]`**
83
+ Instantly clears and zeroes out all data content inside a document without dropping the file pointer from your storage.
84
+ *Syntax:* `Truncate log.txt`
85
+ * **`Delete [filename]`**
86
+ Hard-drops and permanently removes a targeted file path from your computer disk storage.
87
+ *Syntax:* `Delete obsolete.txt`
88
+ * **`Rename [old_filename] [new_filename]`**
89
+ Modifies the naming characteristics of a target file path in-place.
90
+ *Syntax:* `Rename records.txt old_records.txt`
91
+ * **`Copy [source_path] [destination_path]`**
92
+ Clones a localized file into a fresh directory lane safely.
93
+ *Syntax:* `Copy data.txt backup_data.txt`
94
+ * **`Move [filename] [directory_folder]`**
95
+ Relocates an asset file out of your active workspace directory and paths it into a target folder directory.
96
+ *Syntax:* `Move log.txt BackupsFolder`
97
+ * **`SizeOf [unit] [filename]`**
98
+ Uses pattern matching (`match-case`) to convert file weights into human-readable scales including `bytes`, `kb`, `mb`, `gb`, `tb`, `pb`, and `eb`.
99
+ *Syntax:* `SizeOf mb archive.zip`
100
+ * **`Backup [filename]`**
101
+ Creates an automated timestamped duplicate copy of the target file for recovery purposes (e.g., `data_20260616_161022.txt`).
102
+ *Syntax:* `Backup data.txt`
103
+
104
+ ### 3. Directory Management
105
+ * **`MakeDir [base_directory] [new_folder_name]`**
106
+ Joins variables securely to deploy a new nested workspace directory folder.
107
+ *Syntax:* `MakeDir . "BackupsFolder"`
108
+ * **`DelDir [directory_path]`**
109
+ Flashes an engine warning prompt asking for explicit terminal confirmation (`yes/no`) before wiping a directory.
110
+ *Syntax:* `DelDir BackupsFolder`
111
+
112
+ ### 4. Application Control & Cryptography
113
+ * **`Run [executable.exe]`**
114
+ Asynchronously spawns independent system application processes (like `notepad.exe`) without freezing your main interpreter loop.
115
+ *Syntax:* `Run notepad.exe`
116
+ * **`Open [filename]`**
117
+ Launches a text document natively inside the operating system's standard text editor (Notepad).
118
+ *Syntax:* `Open hello.txt`
119
+ * **`Browse [URL]`**
120
+ Triggers your default web browser tool to spin open and target a live web URL natively.
121
+ *Syntax:* `Browse https://lpu.in`
122
+ * **`Progress [seconds]`**
123
+ Renders an active graphical loading progress tracking bar loop (`[██████░░░░]`) directly across the terminal row workspace console over X seconds.
124
+ *Syntax:* `Progress 5`
125
+ * **`Compress [folder_or_file_path]`**
126
+ Packages an independent text file or an entire nested directory workspace into a compressed binary `.zip` archive payload.
127
+ *Syntax:* `Compress "MyProjectFolder"`
128
+ * **`Extract [source_archive.zip] [destination_folder]`**
129
+ Extracts compressed zip archives directly into a targeted folder destination directory path.
130
+ *Syntax:* `Extract archive.zip ExtractedFiles`
131
+ * **`SystemInfo`**
132
+ Pulls operational machine configurations, including kernel type, operating system version, processor architecture, and host network identity node parameters.
133
+ *Syntax:* `SystemInfo`
134
+ * **`Encrypt [filename]`**
135
+ Recursively strips newline markers, processes file lines through a proprietary substitution cipher dictionary matrix, and overwrites with the scrambled hash text payload.
136
+ *Syntax:* `Encrypt secrets.txt`
137
+ * **`Decrypt [filename]`**
138
+ Reverses encrypted files back into natural readable text using an advanced forward lookup character window scanner module.
139
+ *Syntax:* `Decrypt secrets.txt`
140
+
141
+ ---
142
+
143
+ ## 🛠️ Example Automation Script (`main.nxs`)
144
+
145
+ ```text
146
+ # Boot diagnostic evaluation sequences
147
+ SystemInfo
148
+ Wait 1
149
+
150
+ # Manage backup files
151
+ Create telemetry.txt
152
+ Write telemetry.txt "NEXUS Automation Runtime"
153
+ MuteWrite telemetry.txt NewLine "LPU Industrial Passed First Year Assessment"
154
+ SizeOf kb telemetry.txt
155
+
156
+ # Run background applications and secure records
157
+ Run notepad.exe
158
+ Encrypt telemetry.txt
159
+ Speak "Process framework executed cleanly"
160
+ Notify "NEXUS" "Automation routine finished."
161
+ ```
@@ -0,0 +1,12 @@
1
+ README.md
2
+ pyproject.toml
3
+ nexus/__init__.py
4
+ nexus/function_executors.py
5
+ nexus/function_passer.py
6
+ nexus/hash.py
7
+ nexus/nexus.py
8
+ nexus_dsl.egg-info/PKG-INFO
9
+ nexus_dsl.egg-info/SOURCES.txt
10
+ nexus_dsl.egg-info/dependency_links.txt
11
+ nexus_dsl.egg-info/requires.txt
12
+ nexus_dsl.egg-info/top_level.txt
@@ -0,0 +1,3 @@
1
+ colorama>=0.4.6
2
+ plyer>=2.1.0
3
+ pyttsx3>=2.90
@@ -0,0 +1 @@
1
+ nexus
@@ -0,0 +1,26 @@
1
+ [build-system]
2
+ requires = ["setuptools>=61.0.0", "wheel"]
3
+ build-backend = "setuptools.build_meta"
4
+
5
+ [project]
6
+ name = "nexus-dsl" # The unique download name registered on PyPI
7
+ version = "1.0.0"
8
+ authors = [
9
+ { name="Yuvneil", email="yuvneiledu44@gmail.com" }
10
+ ]
11
+ description = "NEXUS: A Custom Domain-Specific Scripting Language (DSL) for local automation"
12
+ readme = "README.md"
13
+ requires-python = ">=3.10"
14
+ classifiers = [
15
+ "Programming Language :: Python :: 3",
16
+ "License :: OSI Approved :: MIT License",
17
+ "Operating System :: Microsoft :: Windows",
18
+ ]
19
+
20
+ # AUTOMATIC DEPENDENCY RESOLUTION:
21
+ # When users run pip install, these modules download automatically first!
22
+ dependencies = [
23
+ "colorama>=0.4.6",
24
+ "plyer>=2.1.0",
25
+ "pyttsx3>=2.90"
26
+ ]
@@ -0,0 +1,4 @@
1
+ [egg_info]
2
+ tag_build =
3
+ tag_date = 0
4
+