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.
Files changed (40) hide show
  1. {chemql_python-1.5.4 → chemql_python-1.5.6}/PKG-INFO +4 -4
  2. {chemql_python-1.5.4 → chemql_python-1.5.6}/README.md +3 -3
  3. {chemql_python-1.5.4 → chemql_python-1.5.6}/pyproject.toml +1 -1
  4. {chemql_python-1.5.4 → chemql_python-1.5.6}/src/chemql/__init__.py +26 -5
  5. {chemql_python-1.5.4 → chemql_python-1.5.6}/src/chemql/codecql.py +166 -27
  6. {chemql_python-1.5.4 → chemql_python-1.5.6}/src/chemql_python.egg-info/PKG-INFO +4 -4
  7. {chemql_python-1.5.4 → chemql_python-1.5.6}/LICENSE +0 -0
  8. {chemql_python-1.5.4 → chemql_python-1.5.6}/setup.cfg +0 -0
  9. {chemql_python-1.5.4 → chemql_python-1.5.6}/src/chemql/__main__.py +0 -0
  10. {chemql_python-1.5.4 → chemql_python-1.5.6}/src/chemql/colors.json +0 -0
  11. {chemql_python-1.5.4 → chemql_python-1.5.6}/src/chemql/data/BondEnergies.json +0 -0
  12. {chemql_python-1.5.4 → chemql_python-1.5.6}/src/chemql/data/MoleculeBonds.json +0 -0
  13. {chemql_python-1.5.4 → chemql_python-1.5.6}/src/chemql/data/Molecules.json +0 -0
  14. {chemql_python-1.5.4 → chemql_python-1.5.6}/src/chemql/data/PeriodicTableJSON.json +0 -0
  15. {chemql_python-1.5.4 → chemql_python-1.5.6}/src/chemql/data/Reactions.json +0 -0
  16. {chemql_python-1.5.4 → chemql_python-1.5.6}/src/chemql/data/THIRD_PARTY_LICENSES/PeriodicTableJSON.txt +0 -0
  17. {chemql_python-1.5.4 → chemql_python-1.5.6}/src/chemql/data/THIRD_PARTY_LICENSES/RHEA.txt +0 -0
  18. {chemql_python-1.5.4 → chemql_python-1.5.6}/src/chemql/html/periodic_table.html +0 -0
  19. {chemql_python-1.5.4 → chemql_python-1.5.6}/src/chemql/stdlib/README.md +0 -0
  20. {chemql_python-1.5.4 → chemql_python-1.5.6}/src/chemql/stdlib/collections.cql +0 -0
  21. {chemql_python-1.5.4 → chemql_python-1.5.6}/src/chemql/stdlib/datetime.cql +0 -0
  22. {chemql_python-1.5.4 → chemql_python-1.5.6}/src/chemql/stdlib/decimal.cql +0 -0
  23. {chemql_python-1.5.4 → chemql_python-1.5.6}/src/chemql/stdlib/fractions.cql +0 -0
  24. {chemql_python-1.5.4 → chemql_python-1.5.6}/src/chemql/stdlib/json.cql +0 -0
  25. {chemql_python-1.5.4 → chemql_python-1.5.6}/src/chemql/stdlib/math/statistics.cql +0 -0
  26. {chemql_python-1.5.4 → chemql_python-1.5.6}/src/chemql/stdlib/math.cql +0 -0
  27. {chemql_python-1.5.4 → chemql_python-1.5.6}/src/chemql/stdlib/pathlib.cql +0 -0
  28. {chemql_python-1.5.4 → chemql_python-1.5.6}/src/chemql/stdlib/random.cql +0 -0
  29. {chemql_python-1.5.4 → chemql_python-1.5.6}/src/chemql/stdlib/text.cql +0 -0
  30. {chemql_python-1.5.4 → chemql_python-1.5.6}/src/chemql_python.egg-info/SOURCES.txt +0 -0
  31. {chemql_python-1.5.4 → chemql_python-1.5.6}/src/chemql_python.egg-info/dependency_links.txt +0 -0
  32. {chemql_python-1.5.4 → chemql_python-1.5.6}/src/chemql_python.egg-info/entry_points.txt +0 -0
  33. {chemql_python-1.5.4 → chemql_python-1.5.6}/src/chemql_python.egg-info/requires.txt +0 -0
  34. {chemql_python-1.5.4 → chemql_python-1.5.6}/src/chemql_python.egg-info/top_level.txt +0 -0
  35. {chemql_python-1.5.4 → chemql_python-1.5.6}/tests/test_codecql.py +0 -0
  36. {chemql_python-1.5.4 → chemql_python-1.5.6}/tests/test_external_molecule_lookup.py +0 -0
  37. {chemql_python-1.5.4 → chemql_python-1.5.6}/tests/test_public_api.py +0 -0
  38. {chemql_python-1.5.4 → chemql_python-1.5.6}/tests/test_reactions.py +0 -0
  39. {chemql_python-1.5.4 → chemql_python-1.5.6}/tests/test_stdlib.py +0 -0
  40. {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.4
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.4`
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.4`
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
 
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "chemql-python"
7
- version = "1.5.4"
7
+ version = "1.5.6"
8
8
  authors = [
9
9
  { name = "Mohammad Rakibul Islam", email = "rakibulofficial1017@gmail.com" }
10
10
  ]
@@ -64,7 +64,7 @@ __all__ = [
64
64
  "__version__"
65
65
  ]
66
66
 
67
- __version__ = "1.5.4"
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
- return execute(
5709
- ["search", "elements", "name", "like", value, "or", "symbol", "like", value]
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
- with open(config_path, encoding="utf-8") as config_file:
207
- config = json.load(config_file)
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
- subprocess.run(os.environ.get("COMSPEC", "cmd.exe"), check=False)
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, 4)
620
- pane_height = min(max(4, rows // 3), rows - 2)
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
- self.message = "Terminal open: Esc or Ctrl+T returns"
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
- termios.TIOCSWINSZ,
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
- termios.TIOCSWINSZ,
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
- continue
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
- tty.tcsetattr(stdin_fd, termios.TCSADRAIN, old_settings)
702
- sys.stdout.write(
703
- "\x1b[?6l\x1b[r\x1b[?25h\x1b[?2004h\x1b[?1l\x1b[H\x1b[2J"
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
- os.close(master_fd)
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("file", help="ChemQL file to edit")
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.4
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.4`
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