chemql-python 1.6.1__tar.gz → 1.6.3__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 (46) hide show
  1. chemql_python-1.6.3/PKG-INFO +1341 -0
  2. chemql_python-1.6.3/README.md +1327 -0
  3. {chemql_python-1.6.1 → chemql_python-1.6.3}/pyproject.toml +1 -1
  4. {chemql_python-1.6.1 → chemql_python-1.6.3}/src/chemql/__init__.py +283 -32
  5. {chemql_python-1.6.1 → chemql_python-1.6.3}/src/chemql/codecql.py +141 -9
  6. chemql_python-1.6.3/src/chemql/foo.py +8 -0
  7. chemql_python-1.6.3/src/chemql/highlighting.py +255 -0
  8. chemql_python-1.6.3/src/chemql_python.egg-info/PKG-INFO +1341 -0
  9. {chemql_python-1.6.1 → chemql_python-1.6.3}/src/chemql_python.egg-info/SOURCES.txt +2 -0
  10. chemql_python-1.6.1/PKG-INFO +0 -1240
  11. chemql_python-1.6.1/README.md +0 -1226
  12. chemql_python-1.6.1/src/chemql_python.egg-info/PKG-INFO +0 -1240
  13. {chemql_python-1.6.1 → chemql_python-1.6.3}/LICENSE +0 -0
  14. {chemql_python-1.6.1 → chemql_python-1.6.3}/setup.cfg +0 -0
  15. {chemql_python-1.6.1 → chemql_python-1.6.3}/src/chemql/__main__.py +0 -0
  16. {chemql_python-1.6.1 → chemql_python-1.6.3}/src/chemql/build.py +0 -0
  17. {chemql_python-1.6.1 → chemql_python-1.6.3}/src/chemql/colors.json +0 -0
  18. {chemql_python-1.6.1 → chemql_python-1.6.3}/src/chemql/data/BondEnergies.json +0 -0
  19. {chemql_python-1.6.1 → chemql_python-1.6.3}/src/chemql/data/MoleculeBonds.json +0 -0
  20. {chemql_python-1.6.1 → chemql_python-1.6.3}/src/chemql/data/Molecules.json +0 -0
  21. {chemql_python-1.6.1 → chemql_python-1.6.3}/src/chemql/data/PeriodicTableJSON.json +0 -0
  22. {chemql_python-1.6.1 → chemql_python-1.6.3}/src/chemql/data/Reactions.json +0 -0
  23. {chemql_python-1.6.1 → chemql_python-1.6.3}/src/chemql/data/THIRD_PARTY_LICENSES/PeriodicTableJSON.txt +0 -0
  24. {chemql_python-1.6.1 → chemql_python-1.6.3}/src/chemql/data/THIRD_PARTY_LICENSES/RHEA.txt +0 -0
  25. {chemql_python-1.6.1 → chemql_python-1.6.3}/src/chemql/html/periodic_table.html +0 -0
  26. {chemql_python-1.6.1 → chemql_python-1.6.3}/src/chemql/stdlib/README.md +0 -0
  27. {chemql_python-1.6.1 → chemql_python-1.6.3}/src/chemql/stdlib/collections.cql +0 -0
  28. {chemql_python-1.6.1 → chemql_python-1.6.3}/src/chemql/stdlib/datetime.cql +0 -0
  29. {chemql_python-1.6.1 → chemql_python-1.6.3}/src/chemql/stdlib/decimal.cql +0 -0
  30. {chemql_python-1.6.1 → chemql_python-1.6.3}/src/chemql/stdlib/fractions.cql +0 -0
  31. {chemql_python-1.6.1 → chemql_python-1.6.3}/src/chemql/stdlib/json.cql +0 -0
  32. {chemql_python-1.6.1 → chemql_python-1.6.3}/src/chemql/stdlib/math/statistics.cql +0 -0
  33. {chemql_python-1.6.1 → chemql_python-1.6.3}/src/chemql/stdlib/math.cql +0 -0
  34. {chemql_python-1.6.1 → chemql_python-1.6.3}/src/chemql/stdlib/pathlib.cql +0 -0
  35. {chemql_python-1.6.1 → chemql_python-1.6.3}/src/chemql/stdlib/random.cql +0 -0
  36. {chemql_python-1.6.1 → chemql_python-1.6.3}/src/chemql/stdlib/text.cql +0 -0
  37. {chemql_python-1.6.1 → chemql_python-1.6.3}/src/chemql_python.egg-info/dependency_links.txt +0 -0
  38. {chemql_python-1.6.1 → chemql_python-1.6.3}/src/chemql_python.egg-info/entry_points.txt +0 -0
  39. {chemql_python-1.6.1 → chemql_python-1.6.3}/src/chemql_python.egg-info/requires.txt +0 -0
  40. {chemql_python-1.6.1 → chemql_python-1.6.3}/src/chemql_python.egg-info/top_level.txt +0 -0
  41. {chemql_python-1.6.1 → chemql_python-1.6.3}/tests/test_codecql.py +0 -0
  42. {chemql_python-1.6.1 → chemql_python-1.6.3}/tests/test_external_molecule_lookup.py +0 -0
  43. {chemql_python-1.6.1 → chemql_python-1.6.3}/tests/test_public_api.py +0 -0
  44. {chemql_python-1.6.1 → chemql_python-1.6.3}/tests/test_reactions.py +0 -0
  45. {chemql_python-1.6.1 → chemql_python-1.6.3}/tests/test_stdlib.py +0 -0
  46. {chemql_python-1.6.1 → chemql_python-1.6.3}/tests/test_structured_types.py +0 -0
@@ -0,0 +1,1341 @@
1
+ Metadata-Version: 2.4
2
+ Name: chemql-python
3
+ Version: 1.6.3
4
+ Summary: A chemistry-focused query language and REPL
5
+ Author-email: Mohammad Rakibul Islam <rakibulofficial1017@gmail.com>
6
+ Requires-Python: >=3.10
7
+ Description-Content-Type: text/markdown
8
+ License-File: LICENSE
9
+ Requires-Dist: prompt_toolkit>=3.0
10
+ Requires-Dist: rich>=13.7
11
+ Provides-Extra: test
12
+ Requires-Dist: pytest>=8.0; extra == "test"
13
+ Dynamic: license-file
14
+
15
+ # ChemQL & CodecQL
16
+
17
+ ChemQL is a chemistry-oriented query and programming language with an
18
+ interactive terminal, a Python-backed execution environment, chemistry
19
+ data types and operations, user-defined functions, and a package system.
20
+
21
+ CodecQL is the terminal text editor distributed with ChemQL. It edits
22
+ source files, provides syntax highlighting, and supports configurable
23
+ highlighting profiles for multiple file extensions.
24
+
25
+ > **Version represented by this documentation:** ChemQL `1.6.3`; CodecQL
26
+ > `0.0.11`.
27
+ >
28
+ > This README documents the implementation represented by the
29
+ > accompanying source files. Some advanced syntax is intentionally
30
+ > described at a high level; use the built-in `help` system for the
31
+ > authoritative in-app reference.
32
+
33
+ ------------------------------------------------------------------------
34
+
35
+ ## Contents
36
+
37
+ - [Installation and requirements](#installation-and-requirements)
38
+ - [ChemQL](#chemql)
39
+ - [Starting ChemQL](#starting-chemql)
40
+ - [Running scripts and commands](#running-scripts-and-commands)
41
+ - [Language syntax at a glance](#language-syntax-at-a-glance)
42
+ - [Built-in functions](#built-in-functions)
43
+ - [Standard-library packages](#standard-library-packages)
44
+ - [Chemistry features](#chemistry-features)
45
+ - [Package management](#package-management)
46
+ - [Python interoperability](#python-interoperability)
47
+ - [Help and errors](#help-and-errors)
48
+ - [CodecQL](#codecql)
49
+ - [Opening and creating files](#opening-and-creating-files)
50
+ - [Keyboard shortcuts](#keyboard-shortcuts)
51
+ - [Search syntax](#search-syntax)
52
+ - [Terminal integration](#terminal-integration)
53
+ - [CodecQL configuration](#codecql-configuration)
54
+ - [`colors.json`: editor colors](#colorsjson-editor-colors)
55
+ - [`highlighting.json`: language
56
+ profiles](#highlightingjson-language-profiles)
57
+ - [Rule types](#rule-types)
58
+ - [Style syntax](#style-syntax)
59
+ - [Configuration lookup and
60
+ precedence](#configuration-lookup-and-precedence)
61
+ - [Editing configuration from
62
+ CodecQL](#editing-configuration-from-codecql)
63
+ - [Troubleshooting](#troubleshooting)
64
+
65
+ ------------------------------------------------------------------------
66
+
67
+ # Installation and requirements
68
+
69
+ ChemQL is a Python package. CodecQL is a Python terminal application
70
+ that is imported by ChemQL and can also be launched through its editor
71
+ command.
72
+
73
+ The ChemQL runtime imports `prompt_toolkit` for the interactive prompt.
74
+ The editor uses Python's standard library and ANSI terminal escape
75
+ sequences. On Windows it attempts to initialize ANSI support with
76
+ `colorama`, and falls back to enabling virtual-terminal processing when
77
+ `colorama` is unavailable.
78
+
79
+ Install ChemQL using the distribution method provided by the project. If
80
+ installing from a local source checkout, install the project from its
81
+ package root so that its package metadata and dependencies are installed
82
+ together.
83
+
84
+ Check the installed version:
85
+
86
+ ``` bash
87
+ chemql --version
88
+ codecql --version
89
+ ```
90
+
91
+ If the `codecql` command is not exposed as a separate executable in your
92
+ installation, launch the editor through ChemQL:
93
+
94
+ ``` bash
95
+ chemql edit path/to/file.cql
96
+ ```
97
+
98
+ ------------------------------------------------------------------------
99
+
100
+ # ChemQL
101
+
102
+ ## Starting ChemQL
103
+
104
+ Start the interactive prompt:
105
+
106
+ ``` bash
107
+ chemql
108
+ ```
109
+
110
+ The prompt accepts ChemQL commands and expressions. The welcome message
111
+ points to the built-in help system:
112
+
113
+ ``` text
114
+ help
115
+ ```
116
+
117
+ or:
118
+
119
+ ``` text
120
+ ?
121
+ ```
122
+
123
+ Exit the interactive prompt with:
124
+
125
+ ``` text
126
+ exit
127
+ ```
128
+
129
+ You can also press `Ctrl+C` to leave the prompt.
130
+
131
+ The prompt supports multiline input for constructs such as functions,
132
+ macros, Python blocks, and other block forms. The continuation prompt is
133
+ shown as `...`.
134
+
135
+ ## Running scripts and commands
136
+
137
+ Execute a one-line or multi-line ChemQL command supplied on the command
138
+ line:
139
+
140
+ ``` bash
141
+ chemql -c 'molar_mass{"H2O"}'
142
+ ```
143
+
144
+ Execute a source file:
145
+
146
+ ``` bash
147
+ chemql -f path/to/script.cql
148
+ ```
149
+
150
+ Write command or script output to a file without ANSI escape sequences:
151
+
152
+ ``` bash
153
+ chemql -f path/to/script.cql -o output.txt
154
+ ```
155
+
156
+ Useful runtime options:
157
+
158
+ -----------------------------------------------------------------------
159
+ Option Purpose
160
+ ----------------------------------- -----------------------------------
161
+ `-c`, `--command` Execute ChemQL code supplied as an
162
+ argument
163
+
164
+ `-f`, `--file` Execute ChemQL code from a file
165
+
166
+ `--no-ansi` Disable ANSI styling in output
167
+
168
+ `--suppress-warnings` Suppress warning messages
169
+
170
+ `-o`, `--output FILE` Write captured output to a file
171
+ without ANSI sequences
172
+
173
+ `-v`, `--version` Print the ChemQL version
174
+
175
+ `--upgrade [VERSION]` Upgrade ChemQL, optionally to a
176
+ specified version
177
+
178
+ `--force` / `--dangerously` Force an upgrade, including
179
+ bypassing system-package
180
+ protections
181
+ -----------------------------------------------------------------------
182
+
183
+ `-o` is only valid with `-c` or `-f`.
184
+
185
+ ## Language syntax at a glance
186
+
187
+ ChemQL combines its own command/query syntax with Python expressions and
188
+ statements in explicitly delimited blocks.
189
+
190
+ ### Function calls
191
+
192
+ ChemQL function calls use braces rather than parentheses:
193
+
194
+ ``` text
195
+ function_name{argument1, argument2}
196
+ ```
197
+
198
+ Examples:
199
+
200
+ ``` text
201
+ molar_mass{"H2O"}
202
+ upper{"hello world"}
203
+ math::sqrt{81}
204
+ ```
205
+
206
+ Separate arguments with commas. Quote text containing spaces.
207
+
208
+ ### Variables
209
+
210
+ Use `let` to assign a value:
211
+
212
+ ``` text
213
+ let answer = 42
214
+ let message = "Hello from ChemQL"
215
+ ```
216
+
217
+ Variables can be used in later expressions:
218
+
219
+ ``` text
220
+ let radius = 5
221
+ let area = math::PI * radius ** 2
222
+ ```
223
+
224
+ The runtime also supports listing and removing variables:
225
+
226
+ ``` text
227
+ variables
228
+ unset answer
229
+ ```
230
+
231
+ ### Definitions and macros
232
+
233
+ Definitions are expanded using an `@NAME` reference:
234
+
235
+ ``` text
236
+ define MAX {
237
+ 100
238
+ }
239
+ ```
240
+
241
+ Use the definition as:
242
+
243
+ ``` text
244
+ @MAX
245
+ ```
246
+
247
+ Definitions are maintained in the current ChemQL session. The
248
+ preprocessor performs one literal substitution pass; replacement text is
249
+ not recursively expanded.
250
+
251
+ Macros use a block form and are invoked by name according to the macro
252
+ syntax supported by the interpreter. Use `help{syntax}` and the in-app
253
+ completion/help facilities for the exact forms supported by your
254
+ installed version.
255
+
256
+ ### Embedded Python
257
+
258
+ A single-line Python statement or expression can be placed inside square
259
+ brackets:
260
+
261
+ ``` text
262
+ [print("Hello from Python")]
263
+ ```
264
+
265
+ A multiline Python block uses triple square brackets:
266
+
267
+ ``` text
268
+ [[[
269
+ numbers = [1, 2, 3, 4]
270
+ total = sum(numbers)
271
+ print(total)
272
+ ]]]
273
+ ```
274
+
275
+ Python code executes in ChemQL's Python-backed environment. This makes
276
+ Python expressions and available Python objects usable alongside ChemQL
277
+ features.
278
+
279
+ ### Embedded ChemQL expressions
280
+
281
+ Double curly braces are used for embedded/lazy ChemQL query expressions
282
+ in supported contexts:
283
+
284
+ ``` text
285
+ {{ search molecules ... }}
286
+ ```
287
+
288
+ The precise query expression depends on the operation being performed.
289
+ See `help{syntax}` and the query examples shipped with the project.
290
+
291
+ ### Control flow
292
+
293
+ ChemQL supports block-oriented control-flow constructs including `if`,
294
+ `elif`, `else`, `for`, and `while`. Closing markers are explicit:
295
+
296
+ ``` text
297
+ if condition
298
+ ...
299
+ else
300
+ ...
301
+ endif
302
+ ```
303
+
304
+ ``` text
305
+ for item in items
306
+ ...
307
+ endfor
308
+ ```
309
+
310
+ ``` text
311
+ while condition
312
+ ...
313
+ endwhile
314
+ ```
315
+
316
+ `break` and `continue` are also recognized control keywords.
317
+
318
+ ### Functions
319
+
320
+ User-defined functions are declared with `func` and closed with
321
+ `endfunc`. Functions can accept arguments and return values. Inside a
322
+ function, positional arguments are available through the function's
323
+ argument mechanism; the implementation also supports `\1`, `\2`, and so
324
+ on as positional argument references in function bodies.
325
+
326
+ A minimal illustrative shape:
327
+
328
+ ``` text
329
+ func greet
330
+ return "Hello"
331
+ endfunc
332
+ ```
333
+
334
+ Call a function using ChemQL's brace-call syntax:
335
+
336
+ ``` text
337
+ greet{}
338
+ ```
339
+
340
+ ### Structs, records, and enums
341
+
342
+ ChemQL supports user-defined `struct`, `record`, and `enum`
343
+ declarations. Structs and records can declare fields, and the
344
+ implementation supports inheritance using `from Base`. Structs can
345
+ inherit from structs, records, or Python classes; records can inherit
346
+ from records.
347
+
348
+ Declarations are closed with their corresponding terminators, such as
349
+ `endstruct`, `endrecord`, and `endenum`.
350
+
351
+ Example declaration shape:
352
+
353
+ ``` text
354
+ struct Point
355
+ x
356
+ y
357
+ endstruct
358
+ ```
359
+
360
+ Enum members can receive automatically generated values when values are
361
+ omitted.
362
+
363
+ ### Namespaces
364
+
365
+ Namespaces group related declarations and support public/private
366
+ members:
367
+
368
+ ``` text
369
+ namespace Geometry
370
+ public func ...
371
+ private func ...
372
+ endnamespace
373
+ ```
374
+
375
+ A namespace member is referenced with a qualified name using `::`, for
376
+ example `Geometry::member`. Private namespace members are intended for
377
+ internal use by functions in the same namespace.
378
+
379
+ ### Error handling and signals
380
+
381
+ The interpreter supports structured `risk`, `fix`, and `cleanup`
382
+ sections, closed by `endrisk`. It also supports `signal` and `warn`
383
+ statements in the relevant execution contexts.
384
+
385
+ The `fix` section is used when the risk section raises a handled error;
386
+ `cleanup` is for cleanup side effects. The current error information is
387
+ exposed to the execution environment.
388
+
389
+ ## Built-in functions
390
+
391
+ The built-in function set includes general-purpose operations, string
392
+ and collection helpers, file I/O, and chemistry helpers. Calls use
393
+ braces.
394
+
395
+ -----------------------------------------------------------------------
396
+ Category Functions
397
+ ----------------------------------- -----------------------------------
398
+ Numbers `abs`, `round`, `min`, `max`, `sum`
399
+
400
+ Core and conversion `len`, `type`, `str`, `int`,
401
+ `float`, `bool`
402
+
403
+ Strings `upper`, `lower`, `contains`,
404
+ `replace`, `split`, `join`
405
+
406
+ Collections `first`, `last`, `unique`, `sort`,
407
+ `reversed`
408
+
409
+ Files and data `read_text`, `read_lines`,
410
+ `read_json`, `read_csv`,
411
+ `write_text`, `write_json`,
412
+ `write_csv`, `file_exists`,
413
+ `list_files`
414
+
415
+ Chemistry `element`, `count_atoms`,
416
+ `molar_mass`, `empirical_formula`
417
+
418
+ Help `help`
419
+ -----------------------------------------------------------------------
420
+
421
+ Examples:
422
+
423
+ ``` text
424
+ abs{-15}
425
+ round{3.14159, 2}
426
+ sum{1, 2, 3, 4}
427
+ upper{"chemql"}
428
+ unique{1, 2, 2, 3}
429
+ molar_mass{"H2O"}
430
+ count_atoms{"H2SO4", "O"}
431
+ empirical_formula{"C6H12O6"}
432
+ ```
433
+
434
+ File examples:
435
+
436
+ ``` text
437
+ let text = read_text{"notes.txt"}
438
+ let rows = read_csv{"data.csv"}
439
+ let data = read_json{"data.json"}
440
+
441
+ write_text{"output.txt", "Hello"}
442
+ write_json{"output.json", data}
443
+ write_csv{"output.csv", rows}
444
+ ```
445
+
446
+ `read_csv` treats the first row as headers by default and returns rows
447
+ as dictionaries. Pass `false` as the `headers` argument to read rows as
448
+ lists.
449
+
450
+ For exact signatures, optional arguments, and examples, use:
451
+
452
+ ``` text
453
+ help{function_name}
454
+ ```
455
+
456
+ For example:
457
+
458
+ ``` text
459
+ help{read_csv}
460
+ help{molar_mass}
461
+ ```
462
+
463
+ ## Standard-library packages
464
+
465
+ ChemQL includes loadable standard-library namespaces. Load a package
466
+ before using its members:
467
+
468
+ ``` text
469
+ load math
470
+ math::sqrt{81}
471
+ ```
472
+
473
+ The source's built-in help index lists these standard-library
474
+ namespaces:
475
+
476
+ Package Purpose
477
+ -------------------- --------------------------------------------------
478
+ `math` Mathematical constants and numeric functions
479
+ `math::statistics` Descriptive statistics
480
+ `text` String operations and regular expressions
481
+ `collections` Collection and iterable helpers
482
+ `datetime` Dates, times, timestamps, and date arithmetic
483
+ `json` JSON serialization, parsing, and type inspection
484
+ `random` Pseudorandom values and sequence sampling
485
+
486
+ Ask ChemQL for a package's documented members:
487
+
488
+ ``` text
489
+ help{stdlib}
490
+ help{math}
491
+ help{math::statistics}
492
+ help{text}
493
+ ```
494
+
495
+ A function can be documented individually when its help entry is
496
+ registered:
497
+
498
+ ``` text
499
+ help{math::sqrt}
500
+ ```
501
+
502
+ ## Chemistry features
503
+
504
+ ChemQL exposes chemistry-oriented data types and operations, including:
505
+
506
+ - `Element`, `Molecule`, and `Reaction` objects.
507
+ - Element and molecule lookup helpers.
508
+ - Reaction lookup and reaction searching.
509
+ - Stoichiometric balancing through `balance_stoichiometry`.
510
+ - Reaction matching against the current temperature, pressure, and
511
+ catalyst conditions.
512
+ - Chemistry built-ins such as `element`, `count_atoms`, `molar_mass`,
513
+ and `empirical_formula`.
514
+
515
+ The interactive command set includes chemistry/query commands such as
516
+ `search`, `source`, `findel`, `findmol`, `findre`, `react`, `balance`,
517
+ `conditions`, and `view`.
518
+
519
+ Examples of built-in chemistry functions:
520
+
521
+ ``` text
522
+ element{"Na"}
523
+ count_atoms{"H2SO4", "O"}
524
+ molar_mass{"H2O"}
525
+ empirical_formula{"C6H12O6"}
526
+ ```
527
+
528
+ Reaction operations can depend on the current reaction conditions.
529
+ Inspect or set conditions with the relevant interactive commands and use
530
+ `conditions` to display the current state.
531
+
532
+ The available data sources and query fields are defined by the ChemQL
533
+ package/data files. Use the interactive prompt's completion and
534
+ `help{chemistry}` for the current details.
535
+
536
+ ## Package management
537
+
538
+ ChemQL provides package-management subcommands:
539
+
540
+ -------------------------------------------------------------------------------
541
+ Command Purpose
542
+ ------------------------------------------- -----------------------------------
543
+ `chemql init [NAME] [-d DIRECTORY]` Create a ChemQL package project
544
+
545
+ `chemql build` Build the current package
546
+
547
+ `chemql search QUERY` Search the package registry
548
+
549
+ `chemql info NAME` Show registry information for a
550
+ package
551
+
552
+ `chemql install NAME [--version VERSION]` Install a package
553
+
554
+ `chemql upgrade NAME [--version VERSION]` Upgrade an installed package
555
+
556
+ `chemql list` List installed packages
557
+
558
+ `chemql uninstall NAME` Uninstall a package
559
+
560
+ `chemql upload` Upload the current package to the
561
+ registry
562
+ -------------------------------------------------------------------------------
563
+
564
+ Example workflow:
565
+
566
+ ``` bash
567
+ chemql search statistics
568
+ chemql info package_name
569
+ chemql install package_name
570
+ chemql list
571
+ ```
572
+
573
+ Load an installed package from the ChemQL prompt:
574
+
575
+ ``` text
576
+ load package_name
577
+ ```
578
+
579
+ Then call its namespaced functions:
580
+
581
+ ``` text
582
+ package_name::function_name{...}
583
+ ```
584
+
585
+ The package manager also supports upgrading ChemQL itself:
586
+
587
+ ``` bash
588
+ chemql --upgrade
589
+ chemql --upgrade 1.6.3
590
+ ```
591
+
592
+ Use `--force` only when you understand that it bypasses normal
593
+ protections around system-managed installations.
594
+
595
+ ## Python interoperability
596
+
597
+ ChemQL is implemented in Python and evaluates embedded Python blocks in
598
+ its Python execution environment. The runtime imports and uses Python
599
+ modules internally, and the language exposes Python-backed objects and
600
+ functions.
601
+
602
+ Use square-bracket blocks for Python statements and expressions. Use
603
+ `[[[ ... ]]]` for multiline Python. This is the intended boundary
604
+ between ChemQL's command/query syntax and general Python code.
605
+
606
+ ## Help and errors
607
+
608
+ The interactive help system is the quickest way to discover the exact
609
+ syntax supported by the installed version:
610
+
611
+ ``` text
612
+ help
613
+ help{syntax}
614
+ help{errors}
615
+ help{files}
616
+ help{chemistry}
617
+ help{stdlib}
618
+ help{function_name}
619
+ ```
620
+
621
+ The runtime defines specific built-in error classes:
622
+
623
+ - `TooFewArguments`
624
+ - `TooManyArguments`
625
+ - `InvalidArgumentType`
626
+ - `InvalidArgumentValue`
627
+ - `FileReadError`
628
+ - `FileWriteError`
629
+
630
+ Other errors can include `SyntaxError`, `NameError`, and
631
+ `PermissionError`.
632
+
633
+ ------------------------------------------------------------------------
634
+
635
+ # CodecQL
636
+
637
+ CodecQL is a terminal-based text editor intended for ChemQL source
638
+ files. It also supports configurable syntax-highlighting profiles for
639
+ other extensions.
640
+
641
+ ## Opening and creating files
642
+
643
+ Open an existing file:
644
+
645
+ ``` bash
646
+ codecql script.cql
647
+ ```
648
+
649
+ Create a new file by opening a path that does not exist yet:
650
+
651
+ ``` bash
652
+ codecql new_script.cql
653
+ ```
654
+
655
+ The editor starts with an empty buffer when the file does not exist.
656
+ Save with `Ctrl+S` to create it.
657
+
658
+ Launch it through ChemQL:
659
+
660
+ ``` bash
661
+ chemql edit script.cql
662
+ ```
663
+
664
+ Open the editor's main highlighting configuration:
665
+
666
+ ``` bash
667
+ codecql --main-highlighting
668
+ ```
669
+
670
+ Open the current working directory's local highlighting configuration:
671
+
672
+ ``` bash
673
+ codecql --local-highlighting
674
+ ```
675
+
676
+ The two highlighting flags cannot be used together. If the selected
677
+ configuration file does not exist, CodecQL creates an empty JSON object
678
+ in that location.
679
+
680
+ ## Keyboard shortcuts
681
+
682
+ -----------------------------------------------------------------------
683
+ Shortcut Action
684
+ ----------------------------------- -----------------------------------
685
+ `Ctrl+S` Save the current file
686
+
687
+ `Ctrl+Q` Quit; if there are unsaved changes,
688
+ press it again to discard and quit
689
+
690
+ `Ctrl+Z` Undo
691
+
692
+ `Ctrl+Y` Redo
693
+
694
+ `Ctrl+F` Open search
695
+
696
+ `Ctrl+C` Copy the current selection
697
+
698
+ `Ctrl+X` Cut the current selection
699
+
700
+ `Ctrl+V` Paste the editor clipboard
701
+
702
+ `Shift+Insert` Paste the editor clipboard
703
+
704
+ `Ctrl+T` Open a split terminal
705
+
706
+ `Ctrl+R` Save if needed and run the current
707
+ file with ChemQL
708
+
709
+ `Shift+Arrow` Extend the selection while moving
710
+ the cursor
711
+
712
+ `Ctrl+Arrow Up/Down` Scroll the viewport
713
+
714
+ `Ctrl+Arrow Left/Right` Move by word
715
+
716
+ `Home` / `End` Move to the start/end of the line
717
+
718
+ `Backspace` / `Delete` Delete text
719
+ -----------------------------------------------------------------------
720
+
721
+ Clipboard integration uses the available system clipboard command when
722
+ possible: - Windows: `clip` - WSL: `clip.exe` - macOS: `pbcopy` - Linux:
723
+ `wl-copy`, `xclip`, or `xsel`
724
+
725
+ If no system clipboard utility is available, CodecQL keeps the copied
726
+ text in its own editor clipboard.
727
+
728
+ ## Search syntax
729
+
730
+ Press `Ctrl+F` to open search. Enter a query and use the arrow keys to
731
+ move between matches. Press `Enter` to select the next match; `Up` or
732
+ `Left` selects the previous match. `Esc` closes search.
733
+
734
+ Search supports optional prefix flags:
735
+
736
+ Flag Meaning
737
+ ------ -----------------------------------------
738
+ `r` Treat the query as a regular expression
739
+ `l` Literal search (the default)
740
+ `w` Match whole words
741
+ `i` Ignore case
742
+
743
+ Place flags before a colon. Examples:
744
+
745
+ ``` text
746
+ hello
747
+ i:hello
748
+ w:hello
749
+ ri:\b[A-Z]{2,}\b
750
+ lw:token
751
+ ```
752
+
753
+ Search is case-insensitive by default. `r` and `l` cannot be combined.
754
+
755
+ ## Terminal integration
756
+
757
+ - `Ctrl+T` opens a shell in a terminal pane/window.
758
+ - `Ctrl+R` saves the current buffer if it has unsaved changes, then
759
+ runs the file with `chemql -f`.
760
+ - On Windows, CodecQL uses a new console, or a Windows Terminal split
761
+ pane when running inside Windows Terminal.
762
+ - On Unix-like systems, CodecQL uses a pseudo-terminal for the
763
+ integrated terminal.
764
+
765
+ ------------------------------------------------------------------------
766
+
767
+ # CodecQL configuration
768
+
769
+ CodecQL has two separate JSON configuration files:
770
+
771
+ - `colors.json` controls the editor's ANSI color palette.
772
+ - `highlighting.json` controls which tokens are highlighted for each
773
+ file extension and which style is assigned to each rule.
774
+
775
+ They serve different purposes. Changing a color in `colors.json` changes
776
+ the appearance of a named style throughout the editor. Changing
777
+ `highlighting.json` changes which words are assigned to styles for a
778
+ language.
779
+
780
+ ## `colors.json`: editor colors
781
+
782
+ `colors.json` is read from the directory containing the CodecQL source
783
+ module. It has two top-level objects: `syntax` and `ui`.
784
+
785
+ Every color entry must be an object containing an integer `ansi256`
786
+ value from `0` through `255`. The optional `channel` is either
787
+ `foreground` (the default) or `background`.
788
+
789
+ Example:
790
+
791
+ ``` json
792
+ {
793
+ "syntax": {
794
+ "comment": { "ansi256": 244 },
795
+ "string": { "ansi256": 114 },
796
+ "number": { "ansi256": 179 },
797
+ "formula": { "ansi256": 117 },
798
+ "operator": { "ansi256": 213 },
799
+ "delimiter": { "ansi256": 250 },
800
+ "command": { "ansi256": 81 },
801
+ "keyword": { "ansi256": 141 },
802
+ "constant": { "ansi256": 215 },
803
+ "type": { "ansi256": 150 },
804
+ "source": { "ansi256": 110 },
805
+ "condition": { "ansi256": 180 },
806
+ "property": { "ansi256": 116 },
807
+ "builtin": { "ansi256": 222 }
808
+ },
809
+ "ui": {
810
+ "line_numbers": {
811
+ "ansi256": 244
812
+ },
813
+ "status_background": {
814
+ "ansi256": 24,
815
+ "channel": "background"
816
+ },
817
+ "status_foreground": {
818
+ "ansi256": 255
819
+ }
820
+ }
821
+ }
822
+ ```
823
+
824
+ The values above mirror the fallback palette in the editor source. If
825
+ `colors.json` is missing, CodecQL uses that fallback palette. If the
826
+ file exists but is malformed or missing a required top-level group,
827
+ loading the theme raises a configuration error.
828
+
829
+ ### Syntax color categories
830
+
831
+ The editor's syntax theme uses these categories:
832
+
833
+ Category Used for
834
+ ------------- ---------------------------------------------------
835
+ `comment` Comments
836
+ `string` Quoted strings
837
+ `number` Numeric literals
838
+ `formula` Chemical formula-like tokens
839
+ `operator` Operators
840
+ `delimiter` Brackets and punctuation delimiters
841
+ `command` ChemQL commands
842
+ `keyword` Language/control keywords
843
+ `constant` Values such as `true`, `false`, and `none`
844
+ `type` Type/declaration names and manifest table headers
845
+ `source` ChemQL data sources
846
+ `condition` Chemistry conditions and units
847
+ `property` Chemistry fields and manifest keys
848
+ `builtin` Python built-in names recognized by the editor
849
+
850
+ The UI categories are:
851
+
852
+ Category Used for
853
+ --------------------- -----------------------
854
+ `line_numbers` Line-number gutter
855
+ `status_background` Status bar background
856
+ `status_foreground` Status bar text
857
+
858
+ ### ANSI 256-color values
859
+
860
+ `ansi256` is a terminal color index, not an RGB hex value. It accepts
861
+ integers from `0` to `255`.
862
+
863
+ Common ranges in the standard 256-color palette:
864
+
865
+ - `0–15`: standard and bright terminal colors.
866
+ - `16–231`: 6×6×6 RGB color cube.
867
+ - `232–255`: grayscale ramp.
868
+
869
+ The actual appearance depends on the terminal's color palette and
870
+ settings.
871
+
872
+ To set a background color, add `"channel": "background"`:
873
+
874
+ ``` json
875
+ "status_background": {
876
+ "ansi256": 24,
877
+ "channel": "background"
878
+ }
879
+ ```
880
+
881
+ Foreground is assumed when `channel` is omitted.
882
+
883
+ ## `highlighting.json`: language profiles
884
+
885
+ `highlighting.json` maps file extensions to ordered lists of
886
+ highlighting rules.
887
+
888
+ CodecQL starts with a built-in `.cql` profile. It then loads the main
889
+ configuration and the current directory's local configuration, if
890
+ present. A custom profile for an existing extension replaces that
891
+ extension's previous profile; a new extension adds a profile.
892
+
893
+ A minimal configuration:
894
+
895
+ ``` json
896
+ {
897
+ ".py": [
898
+ {
899
+ "name": "python-keywords",
900
+ "type": "keywords",
901
+ "values": ["def", "class", "return", "if", "elif", "else", "for", "while", "import", "from", "as", "try", "except", "finally", "with", "pass", "break", "continue"],
902
+ "style": "keyword"
903
+ },
904
+ {
905
+ "name": "python-builtins",
906
+ "type": "keywords",
907
+ "values": ["print", "len", "range", "enumerate", "zip", "map", "filter", "sum", "min", "max", "str", "int", "float", "list", "dict", "set", "tuple"],
908
+ "style": "builtin"
909
+ }
910
+ ],
911
+ ".js": [
912
+ {
913
+ "name": "javascript-keywords",
914
+ "type": "keywords",
915
+ "values": ["const", "let", "var", "function", "return", "if", "else", "for", "while", "class", "new", "import", "export", "from", "async", "await"],
916
+ "style": "keyword"
917
+ }
918
+ ]
919
+ }
920
+ ```
921
+
922
+ ### Profile structure
923
+
924
+ The top-level value must be a JSON object. Each key is a file extension
925
+ and each value is an array of rules.
926
+
927
+ ``` json
928
+ {
929
+ ".extension": [
930
+ {
931
+ "name": "rule-name",
932
+ "type": "keywords",
933
+ "values": ["word1", "word2"],
934
+ "style": "keyword"
935
+ }
936
+ ]
937
+ }
938
+ ```
939
+
940
+ Extension normalization: - A leading dot is added if omitted. -
941
+ Extensions are converted to lowercase. - Empty extensions and values
942
+ containing path separators are rejected. - The profile is selected from
943
+ the file's final extension. For example, `script.py` uses `.py`.
944
+
945
+ Each rule must be an object with: - `name`: non-empty string identifying
946
+ the rule. - `type`: supported rule type (`keywords` or `regex`). -
947
+ `style`: non-empty style expression.
948
+
949
+ A keyword rule additionally requires: - `values`: a non-empty array of
950
+ non-empty strings.
951
+
952
+ Keyword matching is case-insensitive. Rule order matters: the first
953
+ matching keyword rule supplies the style for that word.
954
+
955
+ ### Rule types
956
+
957
+ #### `keywords`
958
+
959
+ Use this rule to assign a style to a list of exact words:
960
+
961
+ ``` json
962
+ {
963
+ "name": "control-flow",
964
+ "type": "keywords",
965
+ "values": ["if", "else", "while", "for", "return"],
966
+ "style": "keyword"
967
+ }
968
+ ```
969
+
970
+ The current implementation applies keyword rules during identifier
971
+ highlighting. Matching is case-insensitive.
972
+
973
+ #### `regex`
974
+
975
+ Regex rules are accepted and validated by the profile loader. A regex
976
+ rule must include a non-empty `pattern`; `case_sensitive` is optional
977
+ and defaults to `true`.
978
+
979
+ ``` json
980
+ {
981
+ "name": "special-identifiers",
982
+ "type": "regex",
983
+ "pattern": "\\b(?:TODO|FIXME|NOTE)\\b",
984
+ "case_sensitive": true,
985
+ "style": "#FFB000 bold"
986
+ }
987
+ ```
988
+
989
+ **Implementation note:** the current editor integration applies
990
+ `keywords` rules through `get_keyword_style`. Although `regex` rules are
991
+ parsed and validated by `highlighting.py`, they are not yet applied by
992
+ the current token-highlighting path. Treat regex highlighting as a
993
+ reserved/configuration-ready feature until regex application is wired
994
+ into the renderer.
995
+
996
+ ### Style syntax
997
+
998
+ A rule's `style` is a space-separated list of style components.
999
+ Components can be combined.
1000
+
1001
+ #### Named theme styles
1002
+
1003
+ These names refer to entries in `colors.json` under `syntax`:
1004
+
1005
+ ``` text
1006
+ keyword
1007
+ command
1008
+ operator
1009
+ string
1010
+ comment
1011
+ number
1012
+ constant
1013
+ type
1014
+ source
1015
+ condition
1016
+ property
1017
+ builtin
1018
+ ```
1019
+
1020
+ Example:
1021
+
1022
+ ``` json
1023
+ "style": "keyword"
1024
+ ```
1025
+
1026
+ #### Formatting modifiers
1027
+
1028
+ The editor recognizes these modifiers:
1029
+
1030
+ Modifier Effect
1031
+ ------------- -------------------------------
1032
+ `bold` Bold text
1033
+ `dim` Dim text
1034
+ `italic` Italic text
1035
+ `underline` Underlined text
1036
+ `reverse` Reverse foreground/background
1037
+ `strike` Strikethrough text
1038
+
1039
+ Example:
1040
+
1041
+ ``` json
1042
+ "style": "keyword bold underline"
1043
+ ```
1044
+
1045
+ #### Custom foreground colors
1046
+
1047
+ Use a six-digit hexadecimal RGB color prefixed with `#`:
1048
+
1049
+ ``` json
1050
+ "style": "#FF00FF"
1051
+ ```
1052
+
1053
+ #### Custom background colors
1054
+
1055
+ Use `bg:` followed by a six-digit hexadecimal RGB color:
1056
+
1057
+ ``` json
1058
+ "style": "bg:#202020"
1059
+ ```
1060
+
1061
+ #### Combining components
1062
+
1063
+ You can combine a named style, formatting modifiers, and custom
1064
+ foreground/background colors:
1065
+
1066
+ ``` json
1067
+ "style": "#FF00FF underline bold italic"
1068
+ ```
1069
+
1070
+ ``` json
1071
+ "style": "keyword bold"
1072
+ ```
1073
+
1074
+ ``` json
1075
+ "style": "#E0B0FF bg:#202020 bold"
1076
+ ```
1077
+
1078
+ Hexadecimal colors use true-color ANSI escape sequences. Your terminal
1079
+ must support ANSI styling and preferably 24-bit true color for the full
1080
+ effect.
1081
+
1082
+ ### Example: create a profile for Python
1083
+
1084
+ Create or edit `highlighting.json` in your project directory:
1085
+
1086
+ ``` json
1087
+ {
1088
+ ".py": [
1089
+ {
1090
+ "name": "python-keywords",
1091
+ "type": "keywords",
1092
+ "values": [
1093
+ "def", "class", "return", "if", "elif", "else",
1094
+ "for", "while", "in", "break", "continue",
1095
+ "import", "from", "as", "try", "except",
1096
+ "finally", "with", "raise", "yield", "lambda"
1097
+ ],
1098
+ "style": "keyword bold"
1099
+ },
1100
+ {
1101
+ "name": "python-constants",
1102
+ "type": "keywords",
1103
+ "values": ["True", "False", "None"],
1104
+ "style": "#FFB86C bold"
1105
+ },
1106
+ {
1107
+ "name": "python-builtins",
1108
+ "type": "keywords",
1109
+ "values": ["print", "len", "range", "enumerate", "zip", "sum", "min", "max"],
1110
+ "style": "builtin"
1111
+ }
1112
+ ]
1113
+ }
1114
+ ```
1115
+
1116
+ Then open a Python file from that directory:
1117
+
1118
+ ``` bash
1119
+ codecql example.py
1120
+ ```
1121
+
1122
+ The local `.py` profile is loaded and used for matching identifier
1123
+ tokens.
1124
+
1125
+ ### Example: add a language without changing ChemQL's built-in profile
1126
+
1127
+ You can define several extensions in the same JSON file:
1128
+
1129
+ ``` json
1130
+ {
1131
+ ".py": [
1132
+ {
1133
+ "name": "python-keywords",
1134
+ "type": "keywords",
1135
+ "values": ["def", "class", "return", "if", "else", "for", "while"],
1136
+ "style": "keyword"
1137
+ }
1138
+ ],
1139
+ ".rs": [
1140
+ {
1141
+ "name": "rust-keywords",
1142
+ "type": "keywords",
1143
+ "values": ["fn", "let", "mut", "pub", "struct", "enum", "impl", "trait", "use", "mod", "match", "if", "else", "loop", "while", "for", "return"],
1144
+ "style": "#D19A66 bold"
1145
+ }
1146
+ ],
1147
+ ".js": [
1148
+ {
1149
+ "name": "javascript-keywords",
1150
+ "type": "keywords",
1151
+ "values": ["const", "let", "var", "function", "return", "class", "new", "async", "await"],
1152
+ "style": "keyword"
1153
+ }
1154
+ ]
1155
+ }
1156
+ ```
1157
+
1158
+ This adds profiles for `.py`, `.rs`, and `.js`. It does not remove the
1159
+ built-in `.cql` profile unless you explicitly provide a `.cql` profile
1160
+ in a loaded configuration.
1161
+
1162
+ ### Configuration lookup and precedence
1163
+
1164
+ The editor loads highlighting profiles in this order:
1165
+
1166
+ 1. The built-in profiles in `highlighting.py` (currently includes
1167
+ `.cql`).
1168
+ 2. `highlighting.json` beside the CodecQL source module (the main
1169
+ configuration).
1170
+ 3. `highlighting.json` in the current working directory (the local
1171
+ configuration).
1172
+
1173
+ Later profiles replace earlier profiles for the same extension.
1174
+ Therefore:
1175
+
1176
+ - The main configuration can provide defaults shared by projects.
1177
+ - A local configuration can override those defaults for the current
1178
+ project.
1179
+ - Profiles for unrelated extensions are retained.
1180
+ - If the main and local paths point to the same file, it is loaded
1181
+ only once.
1182
+ - If neither file exists, the built-in profiles remain available.
1183
+
1184
+ **Important:** the local configuration is merged by extension; it does
1185
+ not merge individual rules into an existing extension profile. If a
1186
+ local `.py` profile is present, it replaces the main `.py` profile as a
1187
+ whole.
1188
+
1189
+ The main configuration path is relative to the installed CodecQL module.
1190
+ The local configuration path is relative to the directory from which
1191
+ CodecQL is launched.
1192
+
1193
+ ### Editing configuration from CodecQL
1194
+
1195
+ Open the main configuration:
1196
+
1197
+ ``` bash
1198
+ codecql --main-highlighting
1199
+ ```
1200
+
1201
+ Open the local configuration:
1202
+
1203
+ ``` bash
1204
+ codecql --local-highlighting
1205
+ ```
1206
+
1207
+ If the selected file does not exist, CodecQL creates it as:
1208
+
1209
+ ``` json
1210
+ {}
1211
+ ```
1212
+
1213
+ Edit the JSON, save with `Ctrl+S`, then restart CodecQL or reopen the
1214
+ file being edited so the editor reloads the profile configuration.
1215
+
1216
+ Do not combine `--main-highlighting` and `--local-highlighting`.
1217
+
1218
+ ## Built-in ChemQL highlighting
1219
+
1220
+ The built-in `.cql` profile groups words into these rules:
1221
+
1222
+ -----------------------------------------------------------------------
1223
+ Rule name Style Examples
1224
+ ----------------------- ----------------------- -----------------------
1225
+ `commands` `command` `search`, `source`,
1226
+ `findmol`, `react`,
1227
+ `balance`, `help`,
1228
+ `load`
1229
+
1230
+ `control-keywords` `keyword` `if`, `else`, `for`,
1231
+ `while`, `struct`,
1232
+ `record`, `enum`,
1233
+ `namespace`
1234
+
1235
+ `word-operators` `operator` `and`, `or`, `has`,
1236
+ `like`, `sort`,
1237
+ `limit`, `union`
1238
+
1239
+ `sources` `source` `elements`,
1240
+ `molecules`,
1241
+ `reactions`
1242
+
1243
+ `conditions` `condition` `temperature`,
1244
+ `pressure`, `catalyst`,
1245
+ `atm`, `bar`, `kpa`
1246
+
1247
+ `properties` `property` `name`, `symbol`,
1248
+ `atomic_mass`,
1249
+ `formula`, `reactants`,
1250
+ `products`
1251
+ -----------------------------------------------------------------------
1252
+
1253
+ The editor also recognizes lexical token categories such as comments,
1254
+ strings, numbers, chemical formula-like tokens, operators, and
1255
+ delimiters. JSON and TOML package manifests named `cqlpackage.json` and
1256
+ `cqlpackage.toml` receive dedicated manifest highlighting.
1257
+
1258
+ ------------------------------------------------------------------------
1259
+
1260
+ # Troubleshooting
1261
+
1262
+ ### A file opens without custom highlighting
1263
+
1264
+ Check that: 1. The file has the extension used as the profile key, such
1265
+ as `.py`. 2. The JSON file is named exactly `highlighting.json`. 3. The
1266
+ local file is in the current working directory from which CodecQL was
1267
+ launched. 4. The extension key includes the intended extension. 5. The
1268
+ rule uses `"type": "keywords"` and has a non-empty `values` array. 6.
1269
+ The token is recognized as an identifier by the editor's tokenizer.
1270
+
1271
+ Unknown extensions remain unhighlighted by language-specific keyword
1272
+ profiles, though the editor's general lexical token styling still
1273
+ applies.
1274
+
1275
+ ### My local profile is not overriding the main profile
1276
+
1277
+ Profiles are replaced per extension, not merged rule by rule. Make sure
1278
+ the local profile includes the complete rule list you want for that
1279
+ extension.
1280
+
1281
+ ### The editor rejects my highlighting JSON
1282
+
1283
+ Check standard JSON syntax: - Use double quotes around keys and string
1284
+ values. - Do not leave trailing commas. - Use `true` and `false` for
1285
+ booleans, not quoted strings. - Make sure each extension maps to an
1286
+ array of rules. - Make sure each rule has a non-empty `name`, supported
1287
+ `type`, and non-empty `style`.
1288
+
1289
+ For regex rules, `pattern` must be a valid Python regular expression.
1290
+ `case_sensitive` must be a JSON boolean.
1291
+
1292
+ ### My custom style is rejected
1293
+
1294
+ Use only recognized style components: - A named theme style listed in
1295
+ [Style syntax](#style-syntax). - One of `bold`, `dim`, `italic`,
1296
+ `underline`, `reverse`, or `strike`. - A foreground color such as
1297
+ `#FF00FF`. - A background color such as `bg:#202020`.
1298
+
1299
+ Separate components with spaces.
1300
+
1301
+ ### Colors look different in my terminal
1302
+
1303
+ ANSI 256-color and true-color output are interpreted by the terminal.
1304
+ Different terminal palettes, themes, and color capabilities can make the
1305
+ same color index or RGB value look different.
1306
+
1307
+ ### `Ctrl+R` does not run my file
1308
+
1309
+ `Ctrl+R` invokes `chemql -f` with the current file's absolute path.
1310
+ Ensure ChemQL is installed and its `chemql` command is available in the
1311
+ environment inherited by CodecQL. The editor saves a modified buffer
1312
+ before running it.
1313
+
1314
+ ------------------------------------------------------------------------
1315
+
1316
+ ## Project components
1317
+
1318
+ -----------------------------------------------------------------------
1319
+ File/component Responsibility
1320
+ ----------------------------------- -----------------------------------
1321
+ ChemQL package (`__init__.py`) Language runtime, interactive
1322
+ prompt, chemistry functionality,
1323
+ built-ins, package management
1324
+
1325
+ `codecql.py` Terminal editor, file operations,
1326
+ key handling, terminal integration,
1327
+ token rendering
1328
+
1329
+ `highlighting.py` Highlighting profile definitions,
1330
+ JSON loading, extension
1331
+ normalization, and rule validation
1332
+
1333
+ `colors.json` ANSI 256-color theme for syntax and
1334
+ editor UI
1335
+
1336
+ `highlighting.json` Optional user-defined language
1337
+ profiles
1338
+ -----------------------------------------------------------------------
1339
+
1340
+ ChemQL and CodecQL are related but separate components: ChemQL provides
1341
+ the language/runtime, while CodecQL provides the editing environment.