chemql-python 1.5.4__tar.gz → 1.5.6__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.4 → chemql_python-1.5.6}/PKG-INFO +4 -4
- {chemql_python-1.5.4 → chemql_python-1.5.6}/README.md +3 -3
- {chemql_python-1.5.4 → chemql_python-1.5.6}/pyproject.toml +1 -1
- {chemql_python-1.5.4 → chemql_python-1.5.6}/src/chemql/__init__.py +26 -5
- {chemql_python-1.5.4 → chemql_python-1.5.6}/src/chemql/codecql.py +166 -27
- {chemql_python-1.5.4 → chemql_python-1.5.6}/src/chemql_python.egg-info/PKG-INFO +4 -4
- {chemql_python-1.5.4 → chemql_python-1.5.6}/LICENSE +0 -0
- {chemql_python-1.5.4 → chemql_python-1.5.6}/setup.cfg +0 -0
- {chemql_python-1.5.4 → chemql_python-1.5.6}/src/chemql/__main__.py +0 -0
- {chemql_python-1.5.4 → chemql_python-1.5.6}/src/chemql/colors.json +0 -0
- {chemql_python-1.5.4 → chemql_python-1.5.6}/src/chemql/data/BondEnergies.json +0 -0
- {chemql_python-1.5.4 → chemql_python-1.5.6}/src/chemql/data/MoleculeBonds.json +0 -0
- {chemql_python-1.5.4 → chemql_python-1.5.6}/src/chemql/data/Molecules.json +0 -0
- {chemql_python-1.5.4 → chemql_python-1.5.6}/src/chemql/data/PeriodicTableJSON.json +0 -0
- {chemql_python-1.5.4 → chemql_python-1.5.6}/src/chemql/data/Reactions.json +0 -0
- {chemql_python-1.5.4 → chemql_python-1.5.6}/src/chemql/data/THIRD_PARTY_LICENSES/PeriodicTableJSON.txt +0 -0
- {chemql_python-1.5.4 → chemql_python-1.5.6}/src/chemql/data/THIRD_PARTY_LICENSES/RHEA.txt +0 -0
- {chemql_python-1.5.4 → chemql_python-1.5.6}/src/chemql/html/periodic_table.html +0 -0
- {chemql_python-1.5.4 → chemql_python-1.5.6}/src/chemql/stdlib/README.md +0 -0
- {chemql_python-1.5.4 → chemql_python-1.5.6}/src/chemql/stdlib/collections.cql +0 -0
- {chemql_python-1.5.4 → chemql_python-1.5.6}/src/chemql/stdlib/datetime.cql +0 -0
- {chemql_python-1.5.4 → chemql_python-1.5.6}/src/chemql/stdlib/decimal.cql +0 -0
- {chemql_python-1.5.4 → chemql_python-1.5.6}/src/chemql/stdlib/fractions.cql +0 -0
- {chemql_python-1.5.4 → chemql_python-1.5.6}/src/chemql/stdlib/json.cql +0 -0
- {chemql_python-1.5.4 → chemql_python-1.5.6}/src/chemql/stdlib/math/statistics.cql +0 -0
- {chemql_python-1.5.4 → chemql_python-1.5.6}/src/chemql/stdlib/math.cql +0 -0
- {chemql_python-1.5.4 → chemql_python-1.5.6}/src/chemql/stdlib/pathlib.cql +0 -0
- {chemql_python-1.5.4 → chemql_python-1.5.6}/src/chemql/stdlib/random.cql +0 -0
- {chemql_python-1.5.4 → chemql_python-1.5.6}/src/chemql/stdlib/text.cql +0 -0
- {chemql_python-1.5.4 → chemql_python-1.5.6}/src/chemql_python.egg-info/SOURCES.txt +0 -0
- {chemql_python-1.5.4 → chemql_python-1.5.6}/src/chemql_python.egg-info/dependency_links.txt +0 -0
- {chemql_python-1.5.4 → chemql_python-1.5.6}/src/chemql_python.egg-info/entry_points.txt +0 -0
- {chemql_python-1.5.4 → chemql_python-1.5.6}/src/chemql_python.egg-info/requires.txt +0 -0
- {chemql_python-1.5.4 → chemql_python-1.5.6}/src/chemql_python.egg-info/top_level.txt +0 -0
- {chemql_python-1.5.4 → chemql_python-1.5.6}/tests/test_codecql.py +0 -0
- {chemql_python-1.5.4 → chemql_python-1.5.6}/tests/test_external_molecule_lookup.py +0 -0
- {chemql_python-1.5.4 → chemql_python-1.5.6}/tests/test_public_api.py +0 -0
- {chemql_python-1.5.4 → chemql_python-1.5.6}/tests/test_reactions.py +0 -0
- {chemql_python-1.5.4 → chemql_python-1.5.6}/tests/test_stdlib.py +0 -0
- {chemql_python-1.5.4 → chemql_python-1.5.6}/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.6
|
|
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.6`
|
|
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.6`
|
|
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
|
|
|
@@ -64,7 +64,7 @@ __all__ = [
|
|
|
64
64
|
"__version__"
|
|
65
65
|
]
|
|
66
66
|
|
|
67
|
-
__version__ = "1.5.
|
|
67
|
+
__version__ = "1.5.6"
|
|
68
68
|
|
|
69
69
|
# Persistent preprocessor/function state for the current ChemQL session.
|
|
70
70
|
DEFINITIONS = {}
|
|
@@ -5699,15 +5699,36 @@ def execute(arguments, query_text=None, positions=None):
|
|
|
5699
5699
|
# These are syntactic sugar for normal search queries.
|
|
5700
5700
|
if arguments[0] == "findel":
|
|
5701
5701
|
if len(arguments) < 2:
|
|
5702
|
-
return "Usage: findel <name-or-symbol>"
|
|
5702
|
+
return "Usage: findel <name-or-symbol> [return <attribute> ...]"
|
|
5703
5703
|
|
|
5704
5704
|
value = arguments[1]
|
|
5705
5705
|
|
|
5706
5706
|
return_attributes = None
|
|
5707
|
+
if "return" in arguments[2:]:
|
|
5708
|
+
return_index = arguments.index("return", 2)
|
|
5709
|
+
return_attributes = arguments[return_index + 1:]
|
|
5707
5710
|
|
|
5708
|
-
|
|
5709
|
-
|
|
5710
|
-
|
|
5711
|
+
if not return_attributes:
|
|
5712
|
+
return "Usage: findel <name-or-formula> return <attribute> ..."
|
|
5713
|
+
|
|
5714
|
+
for attribute in return_attributes:
|
|
5715
|
+
if attribute not in elementKeys:
|
|
5716
|
+
return (f"There is no key `{attribute}`" if NO_ANSI else f"There is no key \033[1m{attribute}\033[22m")
|
|
5717
|
+
|
|
5718
|
+
if return_index != 2:
|
|
5719
|
+
return "Usage: findel <name-or-formula> [return <attribute> ...]"
|
|
5720
|
+
|
|
5721
|
+
elif len(arguments) > 2:
|
|
5722
|
+
return "Usage: findel <name-or-formula> [return <attribute> ...]"
|
|
5723
|
+
|
|
5724
|
+
if return_attributes is not None:
|
|
5725
|
+
return execute(
|
|
5726
|
+
["search", "elements", "name", "like", value, "or", "symbol", "like", value, "return", *return_attributes]
|
|
5727
|
+
)
|
|
5728
|
+
else:
|
|
5729
|
+
return execute(
|
|
5730
|
+
["search", "elements", "name", "like", value, "or", "symbol", "like", value]
|
|
5731
|
+
)
|
|
5711
5732
|
|
|
5712
5733
|
if arguments[0] == "findmol":
|
|
5713
5734
|
if len(arguments) < 2:
|
|
@@ -10,6 +10,8 @@ import shutil
|
|
|
10
10
|
import subprocess
|
|
11
11
|
import time
|
|
12
12
|
|
|
13
|
+
VERSION = "0.0.6"
|
|
14
|
+
|
|
13
15
|
|
|
14
16
|
def _write_system_clipboard(text):
|
|
15
17
|
"""Copy text to the host system clipboard when a clipboard command exists."""
|
|
@@ -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)
|
|
@@ -605,8 +628,43 @@ class Editor:
|
|
|
605
628
|
return False
|
|
606
629
|
|
|
607
630
|
def _run_split_terminal(self):
|
|
631
|
+
"""Open a shell in a manageable split pane where the platform allows it.
|
|
632
|
+
|
|
633
|
+
POSIX uses a PTY in the lower part of the current terminal. Ctrl+T or
|
|
634
|
+
Esc returns to the editor; Ctrl+Up/Down resizes the shell pane. Window
|
|
635
|
+
resize events are forwarded to the shell PTY. Windows Terminal owns
|
|
636
|
+
its split panes, so on Windows its pane is independently resizable and
|
|
637
|
+
closing the shell returns focus to the editor pane.
|
|
638
|
+
"""
|
|
608
639
|
if os.name == "nt":
|
|
609
|
-
|
|
640
|
+
shell = os.environ.get("COMSPEC", "cmd.exe")
|
|
641
|
+
wt = shutil.which("wt.exe") or shutil.which("wt")
|
|
642
|
+
|
|
643
|
+
if wt and os.environ.get("WT_SESSION"):
|
|
644
|
+
try:
|
|
645
|
+
subprocess.Popen([
|
|
646
|
+
wt, "-w", "0", "split-pane", "-V",
|
|
647
|
+
"--size", "0.35", "--title", "ChemQL Terminal",
|
|
648
|
+
shell, "/K",
|
|
649
|
+
])
|
|
650
|
+
except OSError as error:
|
|
651
|
+
self.message = f"Could not open Windows Terminal pane: {error}"
|
|
652
|
+
else:
|
|
653
|
+
self.message = (
|
|
654
|
+
"Terminal opened in a Windows Terminal pane; resize it with "
|
|
655
|
+
"Alt+Shift+Plus/Minus or drag the divider. Exit the shell to close it."
|
|
656
|
+
)
|
|
657
|
+
return
|
|
658
|
+
|
|
659
|
+
try:
|
|
660
|
+
subprocess.Popen(
|
|
661
|
+
[shell],
|
|
662
|
+
creationflags=getattr(subprocess, "CREATE_NEW_CONSOLE", 0),
|
|
663
|
+
)
|
|
664
|
+
except OSError as error:
|
|
665
|
+
self.message = f"Could not open terminal: {error}"
|
|
666
|
+
else:
|
|
667
|
+
self.message = "Terminal opened in a separate console window"
|
|
610
668
|
return
|
|
611
669
|
|
|
612
670
|
stdin_fd = sys.stdin.fileno()
|
|
@@ -616,15 +674,37 @@ class Editor:
|
|
|
616
674
|
cols, rows = os.get_terminal_size(stdin_fd)
|
|
617
675
|
except OSError:
|
|
618
676
|
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
|
|
677
|
+
rows, cols = max(rows, 6), max(cols, 20)
|
|
678
|
+
pane_height = min(max(4, rows // 3), rows - 3)
|
|
623
679
|
master_fd = None
|
|
624
680
|
child_pid = None
|
|
681
|
+
resize_pending = False
|
|
682
|
+
previous_winch_handler = None
|
|
683
|
+
|
|
684
|
+
def on_resize(_signum, _frame):
|
|
685
|
+
nonlocal resize_pending
|
|
686
|
+
resize_pending = True
|
|
625
687
|
|
|
626
688
|
try:
|
|
627
|
-
|
|
689
|
+
previous_winch_handler = signal.getsignal(signal.SIGWINCH)
|
|
690
|
+
signal.signal(signal.SIGWINCH, on_resize)
|
|
691
|
+
except (AttributeError, ValueError):
|
|
692
|
+
previous_winch_handler = None
|
|
693
|
+
|
|
694
|
+
def dimensions():
|
|
695
|
+
try:
|
|
696
|
+
current_cols, current_rows = os.get_terminal_size(stdin_fd)
|
|
697
|
+
except OSError:
|
|
698
|
+
current_cols, current_rows = 80, 24
|
|
699
|
+
current_rows = max(current_rows, 6)
|
|
700
|
+
current_cols = max(current_cols, 20)
|
|
701
|
+
current_pane_height = min(max(4, pane_height), current_rows - 3)
|
|
702
|
+
current_top = current_rows - current_pane_height + 1
|
|
703
|
+
return current_cols, current_rows, current_pane_height, current_top
|
|
704
|
+
|
|
705
|
+
try:
|
|
706
|
+
self.message = "Terminal open · Ctrl+T/Esc returns · Ctrl+↑/↓ resizes pane"
|
|
707
|
+
cols, rows, pane_height, pane_top = dimensions()
|
|
628
708
|
self.draw_screen(terminal_height=pane_height)
|
|
629
709
|
for row in range(pane_top, rows + 1):
|
|
630
710
|
sys.stdout.write(f"\x1b[{row};1H\x1b[2K")
|
|
@@ -633,11 +713,10 @@ class Editor:
|
|
|
633
713
|
child_pid, master_fd = pty.fork()
|
|
634
714
|
if child_pid == 0:
|
|
635
715
|
fcntl.ioctl(
|
|
636
|
-
sys.stdin.fileno(),
|
|
637
|
-
|
|
638
|
-
struct.pack("HHHH", shell_rows, cols, 0, 0),
|
|
716
|
+
sys.stdin.fileno(), termios.TIOCSWINSZ,
|
|
717
|
+
struct.pack("HHHH", pane_height, cols, 0, 0),
|
|
639
718
|
)
|
|
640
|
-
shell = os.environ.get("SHELL") or "bash"
|
|
719
|
+
shell = os.environ.get("SHELL") or ("/bin/bash" if os.path.exists("/bin/bash") else "/bin/sh")
|
|
641
720
|
try:
|
|
642
721
|
os.execvp(shell, [shell, "-i"])
|
|
643
722
|
except OSError as error:
|
|
@@ -645,19 +724,40 @@ class Editor:
|
|
|
645
724
|
os._exit(127)
|
|
646
725
|
|
|
647
726
|
fcntl.ioctl(
|
|
648
|
-
master_fd,
|
|
649
|
-
|
|
650
|
-
struct.pack("HHHH", shell_rows, cols, 0, 0),
|
|
727
|
+
master_fd, termios.TIOCSWINSZ,
|
|
728
|
+
struct.pack("HHHH", pane_height, cols, 0, 0),
|
|
651
729
|
)
|
|
652
730
|
tty.setraw(stdin_fd)
|
|
653
731
|
sys.stdout.write(f"\x1b[{pane_top};{rows}r\x1b[?6h\x1b[1;1H")
|
|
654
732
|
sys.stdout.flush()
|
|
655
733
|
|
|
734
|
+
resize_keys = {
|
|
735
|
+
b"\x1b[1;5A": -1, b"\x1b[1;5B": 1,
|
|
736
|
+
b"\x1b[1;5;1A": -1, b"\x1b[1;5;1B": 1,
|
|
737
|
+
}
|
|
656
738
|
while True:
|
|
657
739
|
try:
|
|
658
|
-
ready, _, _ = select.select([stdin_fd, master_fd], [], [])
|
|
740
|
+
ready, _, _ = select.select([stdin_fd, master_fd], [], [], 0.25)
|
|
659
741
|
except InterruptedError:
|
|
660
|
-
|
|
742
|
+
ready = []
|
|
743
|
+
|
|
744
|
+
if resize_pending:
|
|
745
|
+
resize_pending = False
|
|
746
|
+
cols, rows, pane_height, pane_top = dimensions()
|
|
747
|
+
fcntl.ioctl(
|
|
748
|
+
master_fd, termios.TIOCSWINSZ,
|
|
749
|
+
struct.pack("HHHH", pane_height, cols, 0, 0),
|
|
750
|
+
)
|
|
751
|
+
try:
|
|
752
|
+
os.kill(child_pid, signal.SIGWINCH)
|
|
753
|
+
except ProcessLookupError:
|
|
754
|
+
pass
|
|
755
|
+
sys.stdout.write("\x1b[r\x1b[H\x1b[2J")
|
|
756
|
+
self.draw_screen(terminal_height=pane_height)
|
|
757
|
+
for row in range(pane_top, rows + 1):
|
|
758
|
+
sys.stdout.write(f"\x1b[{row};1H\x1b[2K")
|
|
759
|
+
sys.stdout.write(f"\x1b[{pane_top};{rows}r\x1b[?6h")
|
|
760
|
+
sys.stdout.flush()
|
|
661
761
|
|
|
662
762
|
if master_fd in ready:
|
|
663
763
|
try:
|
|
@@ -675,6 +775,32 @@ class Editor:
|
|
|
675
775
|
user_input = os.read(stdin_fd, 4096)
|
|
676
776
|
if not user_input:
|
|
677
777
|
break
|
|
778
|
+
|
|
779
|
+
# Intercept pane controls without sending them to the shell.
|
|
780
|
+
resized = False
|
|
781
|
+
for sequence, delta in resize_keys.items():
|
|
782
|
+
if user_input == sequence:
|
|
783
|
+
pane_height = max(4, min(rows - 3, pane_height + delta))
|
|
784
|
+
cols, rows, pane_height, pane_top = dimensions()
|
|
785
|
+
fcntl.ioctl(
|
|
786
|
+
master_fd, termios.TIOCSWINSZ,
|
|
787
|
+
struct.pack("HHHH", pane_height, cols, 0, 0),
|
|
788
|
+
)
|
|
789
|
+
try:
|
|
790
|
+
os.kill(child_pid, signal.SIGWINCH)
|
|
791
|
+
except ProcessLookupError:
|
|
792
|
+
pass
|
|
793
|
+
sys.stdout.write("\x1b[r\x1b[H\x1b[2J")
|
|
794
|
+
self.draw_screen(terminal_height=pane_height)
|
|
795
|
+
for row in range(pane_top, rows + 1):
|
|
796
|
+
sys.stdout.write(f"\x1b[{row};1H\x1b[2K")
|
|
797
|
+
sys.stdout.write(f"\x1b[{pane_top};{rows}r\x1b[?6h")
|
|
798
|
+
sys.stdout.flush()
|
|
799
|
+
resized = True
|
|
800
|
+
break
|
|
801
|
+
if resized:
|
|
802
|
+
continue
|
|
803
|
+
|
|
678
804
|
exit_positions = [
|
|
679
805
|
position for marker in (b"\x14", b"\x11")
|
|
680
806
|
if (position := user_input.find(marker)) >= 0
|
|
@@ -682,9 +808,7 @@ class Editor:
|
|
|
682
808
|
escape_position = user_input.find(b"\x1b")
|
|
683
809
|
if escape_position >= 0 and user_input[escape_position:] == b"\x1b":
|
|
684
810
|
try:
|
|
685
|
-
escaped_input, _, _ = select.select(
|
|
686
|
-
[stdin_fd], [], [], 0.05
|
|
687
|
-
)
|
|
811
|
+
escaped_input, _, _ = select.select([stdin_fd], [], [], 0.05)
|
|
688
812
|
except InterruptedError:
|
|
689
813
|
escaped_input = []
|
|
690
814
|
if escaped_input:
|
|
@@ -697,14 +821,25 @@ class Editor:
|
|
|
697
821
|
os.write(master_fd, user_input[:exit_position])
|
|
698
822
|
break
|
|
699
823
|
os.write(master_fd, user_input)
|
|
824
|
+
except OSError as error:
|
|
825
|
+
self.message = f"Terminal error: {error}"
|
|
700
826
|
finally:
|
|
701
|
-
|
|
702
|
-
|
|
703
|
-
|
|
704
|
-
|
|
827
|
+
if previous_winch_handler is not None:
|
|
828
|
+
try:
|
|
829
|
+
signal.signal(signal.SIGWINCH, previous_winch_handler)
|
|
830
|
+
except (AttributeError, ValueError):
|
|
831
|
+
pass
|
|
832
|
+
try:
|
|
833
|
+
termios.tcsetattr(stdin_fd, termios.TCSADRAIN, old_settings)
|
|
834
|
+
except termios.error:
|
|
835
|
+
pass
|
|
836
|
+
sys.stdout.write("\x1b[?6l\x1b[r\x1b[?25h\x1b[?2004h\x1b[?1l\x1b[H\x1b[2J")
|
|
705
837
|
sys.stdout.flush()
|
|
706
838
|
if master_fd is not None:
|
|
707
|
-
|
|
839
|
+
try:
|
|
840
|
+
os.close(master_fd)
|
|
841
|
+
except OSError:
|
|
842
|
+
pass
|
|
708
843
|
if child_pid is not None:
|
|
709
844
|
try:
|
|
710
845
|
waited_pid, _ = os.waitpid(child_pid, os.WNOHANG)
|
|
@@ -733,6 +868,8 @@ class Editor:
|
|
|
733
868
|
os.waitpid(child_pid, 0)
|
|
734
869
|
except ChildProcessError:
|
|
735
870
|
pass
|
|
871
|
+
if not self.message.startswith("Terminal error:"):
|
|
872
|
+
self.message = "Terminal closed · returned to editor"
|
|
736
873
|
|
|
737
874
|
def _scroll_view(self, direction):
|
|
738
875
|
try:
|
|
@@ -1080,10 +1217,12 @@ def main(argv: list[str] | None = None) -> None:
|
|
|
1080
1217
|
prog="codecql",
|
|
1081
1218
|
description="Open and edit a ChemQL source file.",
|
|
1082
1219
|
)
|
|
1083
|
-
parser.add_argument("
|
|
1220
|
+
parser.add_argument("-V", "--version", action="version", version=f"codecql {VERSION}")
|
|
1221
|
+
parser.add_argument("file", nargs="?", help="ChemQL file to edit")
|
|
1084
1222
|
arguments = parser.parse_args(argv)
|
|
1223
|
+
if not arguments.file:
|
|
1224
|
+
parser.error("the following arguments are required: file")
|
|
1085
1225
|
Editor(arguments.file).run()
|
|
1086
1226
|
|
|
1087
|
-
|
|
1088
1227
|
if __name__ == "__main__":
|
|
1089
1228
|
main()
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: chemql-python
|
|
3
|
-
Version: 1.5.
|
|
3
|
+
Version: 1.5.6
|
|
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.6`
|
|
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
|