chemql-python 1.5.5__tar.gz → 1.5.7__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.
- {chemql_python-1.5.5 → chemql_python-1.5.7}/PKG-INFO +4 -4
- {chemql_python-1.5.5 → chemql_python-1.5.7}/README.md +3 -3
- {chemql_python-1.5.5 → chemql_python-1.5.7}/pyproject.toml +1 -1
- {chemql_python-1.5.5 → chemql_python-1.5.7}/src/chemql/__init__.py +1 -1
- {chemql_python-1.5.5 → chemql_python-1.5.7}/src/chemql/codecql.py +188 -31
- {chemql_python-1.5.5 → chemql_python-1.5.7}/src/chemql_python.egg-info/PKG-INFO +4 -4
- {chemql_python-1.5.5 → chemql_python-1.5.7}/LICENSE +0 -0
- {chemql_python-1.5.5 → chemql_python-1.5.7}/setup.cfg +0 -0
- {chemql_python-1.5.5 → chemql_python-1.5.7}/src/chemql/__main__.py +0 -0
- {chemql_python-1.5.5 → chemql_python-1.5.7}/src/chemql/colors.json +0 -0
- {chemql_python-1.5.5 → chemql_python-1.5.7}/src/chemql/data/BondEnergies.json +0 -0
- {chemql_python-1.5.5 → chemql_python-1.5.7}/src/chemql/data/MoleculeBonds.json +0 -0
- {chemql_python-1.5.5 → chemql_python-1.5.7}/src/chemql/data/Molecules.json +0 -0
- {chemql_python-1.5.5 → chemql_python-1.5.7}/src/chemql/data/PeriodicTableJSON.json +0 -0
- {chemql_python-1.5.5 → chemql_python-1.5.7}/src/chemql/data/Reactions.json +0 -0
- {chemql_python-1.5.5 → chemql_python-1.5.7}/src/chemql/data/THIRD_PARTY_LICENSES/PeriodicTableJSON.txt +0 -0
- {chemql_python-1.5.5 → chemql_python-1.5.7}/src/chemql/data/THIRD_PARTY_LICENSES/RHEA.txt +0 -0
- {chemql_python-1.5.5 → chemql_python-1.5.7}/src/chemql/html/periodic_table.html +0 -0
- {chemql_python-1.5.5 → chemql_python-1.5.7}/src/chemql/stdlib/README.md +0 -0
- {chemql_python-1.5.5 → chemql_python-1.5.7}/src/chemql/stdlib/collections.cql +0 -0
- {chemql_python-1.5.5 → chemql_python-1.5.7}/src/chemql/stdlib/datetime.cql +0 -0
- {chemql_python-1.5.5 → chemql_python-1.5.7}/src/chemql/stdlib/decimal.cql +0 -0
- {chemql_python-1.5.5 → chemql_python-1.5.7}/src/chemql/stdlib/fractions.cql +0 -0
- {chemql_python-1.5.5 → chemql_python-1.5.7}/src/chemql/stdlib/json.cql +0 -0
- {chemql_python-1.5.5 → chemql_python-1.5.7}/src/chemql/stdlib/math/statistics.cql +0 -0
- {chemql_python-1.5.5 → chemql_python-1.5.7}/src/chemql/stdlib/math.cql +0 -0
- {chemql_python-1.5.5 → chemql_python-1.5.7}/src/chemql/stdlib/pathlib.cql +0 -0
- {chemql_python-1.5.5 → chemql_python-1.5.7}/src/chemql/stdlib/random.cql +0 -0
- {chemql_python-1.5.5 → chemql_python-1.5.7}/src/chemql/stdlib/text.cql +0 -0
- {chemql_python-1.5.5 → chemql_python-1.5.7}/src/chemql_python.egg-info/SOURCES.txt +0 -0
- {chemql_python-1.5.5 → chemql_python-1.5.7}/src/chemql_python.egg-info/dependency_links.txt +0 -0
- {chemql_python-1.5.5 → chemql_python-1.5.7}/src/chemql_python.egg-info/entry_points.txt +0 -0
- {chemql_python-1.5.5 → chemql_python-1.5.7}/src/chemql_python.egg-info/requires.txt +0 -0
- {chemql_python-1.5.5 → chemql_python-1.5.7}/src/chemql_python.egg-info/top_level.txt +0 -0
- {chemql_python-1.5.5 → chemql_python-1.5.7}/tests/test_codecql.py +0 -0
- {chemql_python-1.5.5 → chemql_python-1.5.7}/tests/test_external_molecule_lookup.py +0 -0
- {chemql_python-1.5.5 → chemql_python-1.5.7}/tests/test_public_api.py +0 -0
- {chemql_python-1.5.5 → chemql_python-1.5.7}/tests/test_reactions.py +0 -0
- {chemql_python-1.5.5 → chemql_python-1.5.7}/tests/test_stdlib.py +0 -0
- {chemql_python-1.5.5 → chemql_python-1.5.7}/tests/test_structured_types.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: chemql-python
|
|
3
|
-
Version: 1.5.
|
|
3
|
+
Version: 1.5.7
|
|
4
4
|
Summary: A chemistry-focused query language and REPL
|
|
5
5
|
Author-email: Mohammad Rakibul Islam <rakibulofficial1017@gmail.com>
|
|
6
6
|
Requires-Python: >=3.10
|
|
@@ -19,7 +19,7 @@ SQL-inspired syntax, inspect elements and molecules, look up reactions,
|
|
|
19
19
|
balance equations, and combine chemistry queries with Python and shell
|
|
20
20
|
commands.
|
|
21
21
|
|
|
22
|
-
- **Version:** `1.5.
|
|
22
|
+
- **Version:** `1.5.7`
|
|
23
23
|
- **PyPI distribution:** `chemql-python`
|
|
24
24
|
- **Python import / CLI name:** `chemql`
|
|
25
25
|
- **Author:** Mohammad Rakibul Islam
|
|
@@ -170,10 +170,10 @@ default. Prefix a query with `r:` for a case-sensitive regular expression,
|
|
|
170
170
|
literal text, or `li:` for case-insensitive literal text. Add `w` to match
|
|
171
171
|
whole words, for example `lwi:cat`.
|
|
172
172
|
|
|
173
|
-
Press `CTRL+T` to open a terminal inside the code editor to test your code. You can leave the terminal by pressing the Escape key
|
|
173
|
+
Press `CTRL+T` to open a terminal inside the code editor to test your code. You can leave the terminal by pressing the Escape key or typing `exit` on Unix-like systems but on windows, you have to type in `exit` or if you have already typed in commands, you have to typed in commands, you have to type `exit` followed by pressing `Ctrl+D`
|
|
174
174
|
|
|
175
175
|
Use `Ctrl+Up` and `Ctrl+Down` to scroll the viewport while keeping the cursor
|
|
176
|
-
at the same screen position.
|
|
176
|
+
at the same screen position. However on Unix-like systems `Ctrl+Up` and `Ctrl+Down` in the terminal mode resizes the editor to terminal emulator ratio
|
|
177
177
|
|
|
178
178
|
## Query language
|
|
179
179
|
|
|
@@ -6,7 +6,7 @@ SQL-inspired syntax, inspect elements and molecules, look up reactions,
|
|
|
6
6
|
balance equations, and combine chemistry queries with Python and shell
|
|
7
7
|
commands.
|
|
8
8
|
|
|
9
|
-
- **Version:** `1.5.
|
|
9
|
+
- **Version:** `1.5.7`
|
|
10
10
|
- **PyPI distribution:** `chemql-python`
|
|
11
11
|
- **Python import / CLI name:** `chemql`
|
|
12
12
|
- **Author:** Mohammad Rakibul Islam
|
|
@@ -157,10 +157,10 @@ default. Prefix a query with `r:` for a case-sensitive regular expression,
|
|
|
157
157
|
literal text, or `li:` for case-insensitive literal text. Add `w` to match
|
|
158
158
|
whole words, for example `lwi:cat`.
|
|
159
159
|
|
|
160
|
-
Press `CTRL+T` to open a terminal inside the code editor to test your code. You can leave the terminal by pressing the Escape key
|
|
160
|
+
Press `CTRL+T` to open a terminal inside the code editor to test your code. You can leave the terminal by pressing the Escape key or typing `exit` on Unix-like systems but on windows, you have to type in `exit` or if you have already typed in commands, you have to typed in commands, you have to type `exit` followed by pressing `Ctrl+D`
|
|
161
161
|
|
|
162
162
|
Use `Ctrl+Up` and `Ctrl+Down` to scroll the viewport while keeping the cursor
|
|
163
|
-
at the same screen position.
|
|
163
|
+
at the same screen position. However on Unix-like systems `Ctrl+Up` and `Ctrl+Down` in the terminal mode resizes the editor to terminal emulator ratio
|
|
164
164
|
|
|
165
165
|
## Query language
|
|
166
166
|
|
|
@@ -10,6 +10,8 @@ import shutil
|
|
|
10
10
|
import subprocess
|
|
11
11
|
import time
|
|
12
12
|
|
|
13
|
+
VERSION = "0.0.7"
|
|
14
|
+
|
|
13
15
|
|
|
14
16
|
def _write_system_clipboard(text):
|
|
15
17
|
"""Copy text to the host system clipboard when a clipboard command exists."""
|
|
@@ -127,7 +129,7 @@ if os.name == 'nt':
|
|
|
127
129
|
0x48: "arrow_up", 0x50: "arrow_down",
|
|
128
130
|
0x4B: "arrow_left", 0x4D: "arrow_right",
|
|
129
131
|
0x47: "arrow_home", 0x4F: "arrow_end",
|
|
130
|
-
0x53: "delete", 0x73: "ctrl+arrow_left",
|
|
132
|
+
0x53: "delete", 0x93: "ctrl+delete", 0x73: "ctrl+arrow_left",
|
|
131
133
|
0x74: "ctrl+arrow_right", 0x8D: "ctrl+arrow_up",
|
|
132
134
|
0x91: "ctrl+arrow_down", 0x9B: "alt+arrow_left",
|
|
133
135
|
0x9D: "alt+arrow_right",
|
|
@@ -203,8 +205,29 @@ DIM = "\x1b[2m"
|
|
|
203
205
|
|
|
204
206
|
def load_color_styles():
|
|
205
207
|
config_path = os.path.join(os.path.dirname(os.path.abspath(__file__)), "colors.json")
|
|
206
|
-
|
|
207
|
-
|
|
208
|
+
try:
|
|
209
|
+
with open(config_path, encoding="utf-8") as config_file:
|
|
210
|
+
config = json.load(config_file)
|
|
211
|
+
except FileNotFoundError:
|
|
212
|
+
# Keep informational flags such as --version usable without the theme
|
|
213
|
+
# file. The editor still gets a readable built-in ANSI palette.
|
|
214
|
+
syntax_colors = {
|
|
215
|
+
"comment": 244, "string": 114, "number": 179,
|
|
216
|
+
"formula": 117, "operator": 213, "delimiter": 250,
|
|
217
|
+
"command": 81, "keyword": 141, "constant": 215,
|
|
218
|
+
"type": 150, "source": 110, "condition": 180,
|
|
219
|
+
"property": 116, "builtin": 222,
|
|
220
|
+
}
|
|
221
|
+
ui_colors = {"line_numbers": 244, "status_background": 24,
|
|
222
|
+
"status_foreground": 255}
|
|
223
|
+
config = {
|
|
224
|
+
"syntax": {key: {"ansi256": value} for key, value in syntax_colors.items()},
|
|
225
|
+
"ui": {
|
|
226
|
+
"line_numbers": {"ansi256": ui_colors["line_numbers"]},
|
|
227
|
+
"status_background": {"ansi256": ui_colors["status_background"], "channel": "background"},
|
|
228
|
+
"status_foreground": {"ansi256": ui_colors["status_foreground"]},
|
|
229
|
+
},
|
|
230
|
+
}
|
|
208
231
|
groups = {}
|
|
209
232
|
for group_name in ("syntax", "ui"):
|
|
210
233
|
colors = config.get(group_name)
|
|
@@ -432,7 +455,7 @@ class Editor:
|
|
|
432
455
|
if self.search_active
|
|
433
456
|
else self.message or (
|
|
434
457
|
"Ctrl+S Save Ctrl+Z Undo Ctrl+Y Redo Ctrl+Q Quit "
|
|
435
|
-
"Ctrl+F Search Ctrl+T Terminal Ctrl+Backspace/Delete Word"
|
|
458
|
+
"Ctrl+F Search Ctrl+T Terminal Ctrl+R Run ChemQL Ctrl+Backspace/Delete Word"
|
|
436
459
|
)
|
|
437
460
|
)
|
|
438
461
|
output.extend((DIM, footer[:cols].ljust(cols), RESET))
|
|
@@ -506,7 +529,9 @@ class Editor:
|
|
|
506
529
|
return self._handle_search_key(key)
|
|
507
530
|
if key in ("\x14", "ctrl+t"):
|
|
508
531
|
self._run_split_terminal()
|
|
509
|
-
|
|
532
|
+
return False
|
|
533
|
+
if key in ("\x12", "ctrl+r"):
|
|
534
|
+
self._run_split_terminal(run_chemql=True)
|
|
510
535
|
return False
|
|
511
536
|
if key in ("\x06", "ctrl+f"):
|
|
512
537
|
self._open_search()
|
|
@@ -604,9 +629,58 @@ class Editor:
|
|
|
604
629
|
self.cursor_x = min(self.cursor_x, len(self.lines[self.cursor_y]))
|
|
605
630
|
return False
|
|
606
631
|
|
|
607
|
-
def _run_split_terminal(self):
|
|
632
|
+
def _run_split_terminal(self, run_chemql=False):
|
|
633
|
+
"""Open a shell; Ctrl+R also runs ChemQL on this file's absolute path."""
|
|
634
|
+
command = None
|
|
635
|
+
if run_chemql:
|
|
636
|
+
# Run the current buffer rather than stale on-disk contents.
|
|
637
|
+
if self.dirty:
|
|
638
|
+
self.save_file()
|
|
639
|
+
if self.dirty:
|
|
640
|
+
return
|
|
641
|
+
absolute_path = os.path.abspath(self.filename)
|
|
642
|
+
if os.name == "nt":
|
|
643
|
+
command = "chemql -f " + subprocess.list2cmdline([absolute_path])
|
|
644
|
+
else:
|
|
645
|
+
import shlex
|
|
646
|
+
command = "chemql -f " + shlex.quote(absolute_path)
|
|
647
|
+
|
|
608
648
|
if os.name == "nt":
|
|
609
|
-
|
|
649
|
+
shell = os.environ.get("COMSPEC", "cmd.exe")
|
|
650
|
+
wt = shutil.which("wt.exe") or shutil.which("wt")
|
|
651
|
+
|
|
652
|
+
if wt and os.environ.get("WT_SESSION"):
|
|
653
|
+
try:
|
|
654
|
+
args = [
|
|
655
|
+
wt, "-w", "0", "split-pane", "-V",
|
|
656
|
+
"--size", "0.35", "--title", "ChemQL Terminal",
|
|
657
|
+
shell, "/K",
|
|
658
|
+
]
|
|
659
|
+
if command:
|
|
660
|
+
args.append(command)
|
|
661
|
+
subprocess.Popen(args)
|
|
662
|
+
except OSError as error:
|
|
663
|
+
self.message = f"Could not open Windows Terminal pane: {error}"
|
|
664
|
+
else:
|
|
665
|
+
self.message = (
|
|
666
|
+
"ChemQL running in Windows Terminal pane" if command else
|
|
667
|
+
"Terminal opened in a Windows Terminal pane; resize it with "
|
|
668
|
+
"Alt+Shift+Plus/Minus or drag the divider. Exit the shell to close it."
|
|
669
|
+
)
|
|
670
|
+
return
|
|
671
|
+
|
|
672
|
+
try:
|
|
673
|
+
args = [shell]
|
|
674
|
+
if command:
|
|
675
|
+
args.extend(["/K", command])
|
|
676
|
+
subprocess.Popen(
|
|
677
|
+
args,
|
|
678
|
+
creationflags=getattr(subprocess, "CREATE_NEW_CONSOLE", 0),
|
|
679
|
+
)
|
|
680
|
+
except OSError as error:
|
|
681
|
+
self.message = f"Could not open terminal: {error}"
|
|
682
|
+
else:
|
|
683
|
+
self.message = "ChemQL running in a separate console" if command else "Terminal opened in a separate console window"
|
|
610
684
|
return
|
|
611
685
|
|
|
612
686
|
stdin_fd = sys.stdin.fileno()
|
|
@@ -616,15 +690,37 @@ class Editor:
|
|
|
616
690
|
cols, rows = os.get_terminal_size(stdin_fd)
|
|
617
691
|
except OSError:
|
|
618
692
|
cols, rows = 80, 24
|
|
619
|
-
rows = max(rows,
|
|
620
|
-
pane_height = min(max(4, rows // 3), rows -
|
|
621
|
-
pane_top = rows - pane_height + 1
|
|
622
|
-
shell_rows = rows - pane_top + 1
|
|
693
|
+
rows, cols = max(rows, 6), max(cols, 20)
|
|
694
|
+
pane_height = min(max(4, rows // 3), rows - 3)
|
|
623
695
|
master_fd = None
|
|
624
696
|
child_pid = None
|
|
697
|
+
resize_pending = False
|
|
698
|
+
previous_winch_handler = None
|
|
699
|
+
|
|
700
|
+
def on_resize(_signum, _frame):
|
|
701
|
+
nonlocal resize_pending
|
|
702
|
+
resize_pending = True
|
|
625
703
|
|
|
626
704
|
try:
|
|
627
|
-
|
|
705
|
+
previous_winch_handler = signal.getsignal(signal.SIGWINCH)
|
|
706
|
+
signal.signal(signal.SIGWINCH, on_resize)
|
|
707
|
+
except (AttributeError, ValueError):
|
|
708
|
+
previous_winch_handler = None
|
|
709
|
+
|
|
710
|
+
def dimensions():
|
|
711
|
+
try:
|
|
712
|
+
current_cols, current_rows = os.get_terminal_size(stdin_fd)
|
|
713
|
+
except OSError:
|
|
714
|
+
current_cols, current_rows = 80, 24
|
|
715
|
+
current_rows = max(current_rows, 6)
|
|
716
|
+
current_cols = max(current_cols, 20)
|
|
717
|
+
current_pane_height = min(max(4, pane_height), current_rows - 3)
|
|
718
|
+
current_top = current_rows - current_pane_height + 1
|
|
719
|
+
return current_cols, current_rows, current_pane_height, current_top
|
|
720
|
+
|
|
721
|
+
try:
|
|
722
|
+
self.message = "Terminal open · Ctrl+T/Esc returns · Ctrl+↑/↓ resizes pane"
|
|
723
|
+
cols, rows, pane_height, pane_top = dimensions()
|
|
628
724
|
self.draw_screen(terminal_height=pane_height)
|
|
629
725
|
for row in range(pane_top, rows + 1):
|
|
630
726
|
sys.stdout.write(f"\x1b[{row};1H\x1b[2K")
|
|
@@ -633,11 +729,10 @@ class Editor:
|
|
|
633
729
|
child_pid, master_fd = pty.fork()
|
|
634
730
|
if child_pid == 0:
|
|
635
731
|
fcntl.ioctl(
|
|
636
|
-
sys.stdin.fileno(),
|
|
637
|
-
|
|
638
|
-
struct.pack("HHHH", shell_rows, cols, 0, 0),
|
|
732
|
+
sys.stdin.fileno(), termios.TIOCSWINSZ,
|
|
733
|
+
struct.pack("HHHH", pane_height, cols, 0, 0),
|
|
639
734
|
)
|
|
640
|
-
shell = os.environ.get("SHELL") or "bash"
|
|
735
|
+
shell = os.environ.get("SHELL") or ("/bin/bash" if os.path.exists("/bin/bash") else "/bin/sh")
|
|
641
736
|
try:
|
|
642
737
|
os.execvp(shell, [shell, "-i"])
|
|
643
738
|
except OSError as error:
|
|
@@ -645,19 +740,42 @@ class Editor:
|
|
|
645
740
|
os._exit(127)
|
|
646
741
|
|
|
647
742
|
fcntl.ioctl(
|
|
648
|
-
master_fd,
|
|
649
|
-
|
|
650
|
-
struct.pack("HHHH", shell_rows, cols, 0, 0),
|
|
743
|
+
master_fd, termios.TIOCSWINSZ,
|
|
744
|
+
struct.pack("HHHH", pane_height, cols, 0, 0),
|
|
651
745
|
)
|
|
652
746
|
tty.setraw(stdin_fd)
|
|
747
|
+
if command:
|
|
748
|
+
os.write(master_fd, command.encode("utf-8") + b"\n")
|
|
653
749
|
sys.stdout.write(f"\x1b[{pane_top};{rows}r\x1b[?6h\x1b[1;1H")
|
|
654
750
|
sys.stdout.flush()
|
|
655
751
|
|
|
752
|
+
resize_keys = {
|
|
753
|
+
b"\x1b[1;5A": -1, b"\x1b[1;5B": 1,
|
|
754
|
+
b"\x1b[1;5;1A": -1, b"\x1b[1;5;1B": 1,
|
|
755
|
+
}
|
|
656
756
|
while True:
|
|
657
757
|
try:
|
|
658
|
-
ready, _, _ = select.select([stdin_fd, master_fd], [], [])
|
|
758
|
+
ready, _, _ = select.select([stdin_fd, master_fd], [], [], 0.25)
|
|
659
759
|
except InterruptedError:
|
|
660
|
-
|
|
760
|
+
ready = []
|
|
761
|
+
|
|
762
|
+
if resize_pending:
|
|
763
|
+
resize_pending = False
|
|
764
|
+
cols, rows, pane_height, pane_top = dimensions()
|
|
765
|
+
fcntl.ioctl(
|
|
766
|
+
master_fd, termios.TIOCSWINSZ,
|
|
767
|
+
struct.pack("HHHH", pane_height, cols, 0, 0),
|
|
768
|
+
)
|
|
769
|
+
try:
|
|
770
|
+
os.kill(child_pid, signal.SIGWINCH)
|
|
771
|
+
except ProcessLookupError:
|
|
772
|
+
pass
|
|
773
|
+
sys.stdout.write("\x1b[r\x1b[H\x1b[2J")
|
|
774
|
+
self.draw_screen(terminal_height=pane_height)
|
|
775
|
+
for row in range(pane_top, rows + 1):
|
|
776
|
+
sys.stdout.write(f"\x1b[{row};1H\x1b[2K")
|
|
777
|
+
sys.stdout.write(f"\x1b[{pane_top};{rows}r\x1b[?6h")
|
|
778
|
+
sys.stdout.flush()
|
|
661
779
|
|
|
662
780
|
if master_fd in ready:
|
|
663
781
|
try:
|
|
@@ -675,6 +793,32 @@ class Editor:
|
|
|
675
793
|
user_input = os.read(stdin_fd, 4096)
|
|
676
794
|
if not user_input:
|
|
677
795
|
break
|
|
796
|
+
|
|
797
|
+
# Intercept pane controls without sending them to the shell.
|
|
798
|
+
resized = False
|
|
799
|
+
for sequence, delta in resize_keys.items():
|
|
800
|
+
if user_input == sequence:
|
|
801
|
+
pane_height = max(4, min(rows - 3, pane_height + delta))
|
|
802
|
+
cols, rows, pane_height, pane_top = dimensions()
|
|
803
|
+
fcntl.ioctl(
|
|
804
|
+
master_fd, termios.TIOCSWINSZ,
|
|
805
|
+
struct.pack("HHHH", pane_height, cols, 0, 0),
|
|
806
|
+
)
|
|
807
|
+
try:
|
|
808
|
+
os.kill(child_pid, signal.SIGWINCH)
|
|
809
|
+
except ProcessLookupError:
|
|
810
|
+
pass
|
|
811
|
+
sys.stdout.write("\x1b[r\x1b[H\x1b[2J")
|
|
812
|
+
self.draw_screen(terminal_height=pane_height)
|
|
813
|
+
for row in range(pane_top, rows + 1):
|
|
814
|
+
sys.stdout.write(f"\x1b[{row};1H\x1b[2K")
|
|
815
|
+
sys.stdout.write(f"\x1b[{pane_top};{rows}r\x1b[?6h")
|
|
816
|
+
sys.stdout.flush()
|
|
817
|
+
resized = True
|
|
818
|
+
break
|
|
819
|
+
if resized:
|
|
820
|
+
continue
|
|
821
|
+
|
|
678
822
|
exit_positions = [
|
|
679
823
|
position for marker in (b"\x14", b"\x11")
|
|
680
824
|
if (position := user_input.find(marker)) >= 0
|
|
@@ -682,9 +826,7 @@ class Editor:
|
|
|
682
826
|
escape_position = user_input.find(b"\x1b")
|
|
683
827
|
if escape_position >= 0 and user_input[escape_position:] == b"\x1b":
|
|
684
828
|
try:
|
|
685
|
-
escaped_input, _, _ = select.select(
|
|
686
|
-
[stdin_fd], [], [], 0.05
|
|
687
|
-
)
|
|
829
|
+
escaped_input, _, _ = select.select([stdin_fd], [], [], 0.05)
|
|
688
830
|
except InterruptedError:
|
|
689
831
|
escaped_input = []
|
|
690
832
|
if escaped_input:
|
|
@@ -697,14 +839,25 @@ class Editor:
|
|
|
697
839
|
os.write(master_fd, user_input[:exit_position])
|
|
698
840
|
break
|
|
699
841
|
os.write(master_fd, user_input)
|
|
842
|
+
except OSError as error:
|
|
843
|
+
self.message = f"Terminal error: {error}"
|
|
700
844
|
finally:
|
|
701
|
-
|
|
702
|
-
|
|
703
|
-
|
|
704
|
-
|
|
845
|
+
if previous_winch_handler is not None:
|
|
846
|
+
try:
|
|
847
|
+
signal.signal(signal.SIGWINCH, previous_winch_handler)
|
|
848
|
+
except (AttributeError, ValueError):
|
|
849
|
+
pass
|
|
850
|
+
try:
|
|
851
|
+
termios.tcsetattr(stdin_fd, termios.TCSADRAIN, old_settings)
|
|
852
|
+
except termios.error:
|
|
853
|
+
pass
|
|
854
|
+
sys.stdout.write("\x1b[?6l\x1b[r\x1b[?25h\x1b[?2004h\x1b[?1l\x1b[H\x1b[2J")
|
|
705
855
|
sys.stdout.flush()
|
|
706
856
|
if master_fd is not None:
|
|
707
|
-
|
|
857
|
+
try:
|
|
858
|
+
os.close(master_fd)
|
|
859
|
+
except OSError:
|
|
860
|
+
pass
|
|
708
861
|
if child_pid is not None:
|
|
709
862
|
try:
|
|
710
863
|
waited_pid, _ = os.waitpid(child_pid, os.WNOHANG)
|
|
@@ -733,6 +886,8 @@ class Editor:
|
|
|
733
886
|
os.waitpid(child_pid, 0)
|
|
734
887
|
except ChildProcessError:
|
|
735
888
|
pass
|
|
889
|
+
if not self.message.startswith("Terminal error:"):
|
|
890
|
+
self.message = "Terminal closed · returned to editor"
|
|
736
891
|
|
|
737
892
|
def _scroll_view(self, direction):
|
|
738
893
|
try:
|
|
@@ -1080,10 +1235,12 @@ def main(argv: list[str] | None = None) -> None:
|
|
|
1080
1235
|
prog="codecql",
|
|
1081
1236
|
description="Open and edit a ChemQL source file.",
|
|
1082
1237
|
)
|
|
1083
|
-
parser.add_argument("
|
|
1238
|
+
parser.add_argument("-V", "--version", action="version", version=f"codecql {VERSION}")
|
|
1239
|
+
parser.add_argument("file", nargs="?", help="ChemQL file to edit")
|
|
1084
1240
|
arguments = parser.parse_args(argv)
|
|
1241
|
+
if not arguments.file:
|
|
1242
|
+
parser.error("the following arguments are required: file")
|
|
1085
1243
|
Editor(arguments.file).run()
|
|
1086
1244
|
|
|
1087
|
-
|
|
1088
1245
|
if __name__ == "__main__":
|
|
1089
1246
|
main()
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: chemql-python
|
|
3
|
-
Version: 1.5.
|
|
3
|
+
Version: 1.5.7
|
|
4
4
|
Summary: A chemistry-focused query language and REPL
|
|
5
5
|
Author-email: Mohammad Rakibul Islam <rakibulofficial1017@gmail.com>
|
|
6
6
|
Requires-Python: >=3.10
|
|
@@ -19,7 +19,7 @@ SQL-inspired syntax, inspect elements and molecules, look up reactions,
|
|
|
19
19
|
balance equations, and combine chemistry queries with Python and shell
|
|
20
20
|
commands.
|
|
21
21
|
|
|
22
|
-
- **Version:** `1.5.
|
|
22
|
+
- **Version:** `1.5.7`
|
|
23
23
|
- **PyPI distribution:** `chemql-python`
|
|
24
24
|
- **Python import / CLI name:** `chemql`
|
|
25
25
|
- **Author:** Mohammad Rakibul Islam
|
|
@@ -170,10 +170,10 @@ default. Prefix a query with `r:` for a case-sensitive regular expression,
|
|
|
170
170
|
literal text, or `li:` for case-insensitive literal text. Add `w` to match
|
|
171
171
|
whole words, for example `lwi:cat`.
|
|
172
172
|
|
|
173
|
-
Press `CTRL+T` to open a terminal inside the code editor to test your code. You can leave the terminal by pressing the Escape key
|
|
173
|
+
Press `CTRL+T` to open a terminal inside the code editor to test your code. You can leave the terminal by pressing the Escape key or typing `exit` on Unix-like systems but on windows, you have to type in `exit` or if you have already typed in commands, you have to typed in commands, you have to type `exit` followed by pressing `Ctrl+D`
|
|
174
174
|
|
|
175
175
|
Use `Ctrl+Up` and `Ctrl+Down` to scroll the viewport while keeping the cursor
|
|
176
|
-
at the same screen position.
|
|
176
|
+
at the same screen position. However on Unix-like systems `Ctrl+Up` and `Ctrl+Down` in the terminal mode resizes the editor to terminal emulator ratio
|
|
177
177
|
|
|
178
178
|
## Query language
|
|
179
179
|
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|