CurseMol 4.1.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- cursemol-4.1.0/.claude/settings.local.json +10 -0
- cursemol-4.1.0/.gitignore +11 -0
- cursemol-4.1.0/.style.yapf +3 -0
- cursemol-4.1.0/.tokens +2 -0
- cursemol-4.1.0/CLAUDE.md +161 -0
- cursemol-4.1.0/LICENSE +28 -0
- cursemol-4.1.0/PKG-INFO +67 -0
- cursemol-4.1.0/README.md +48 -0
- cursemol-4.1.0/cursemol.log +0 -0
- cursemol-4.1.0/demo.gif +0 -0
- cursemol-4.1.0/l +145 -0
- cursemol-4.1.0/notes +44 -0
- cursemol-4.1.0/pyproject.toml +36 -0
- cursemol-4.1.0/src/cursemol/.__init__.py.swp +0 -0
- cursemol-4.1.0/src/cursemol/__init__.py +1863 -0
- cursemol-4.1.0/src/cursemol/py.typed +0 -0
- cursemol-4.1.0/uv.lock +206 -0
- cursemol-4.1.0/x +193 -0
- cursemol-4.1.0/x.smi +1 -0
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
{
|
|
2
|
+
"permissions": {
|
|
3
|
+
"allow": [
|
|
4
|
+
"Bash(python3 -m py_compile cursemol.py)",
|
|
5
|
+
"Bash(python3 -c \"import cursemol; print\\('Module loaded successfully'\\)\")",
|
|
6
|
+
"Bash(timeout 2 uv run ./cursemol.py \"CCO\" 2>&1 | head -20 || true)",
|
|
7
|
+
"Bash(python -m py_compile cursemol.py)"
|
|
8
|
+
]
|
|
9
|
+
}
|
|
10
|
+
}
|
cursemol-4.1.0/.tokens
ADDED
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
TEST_PYPI_TOKEN=pypi-AgENdGVzdC5weXBpLm9yZwIkMDIwNTk1YzMtMDQ3NC00NzI1LWJjZGUtNjYwZjU3MjRhZTcwAAIqWzMsIjc5NzJkNTJiLWIwMDgtNDc3YS1hY2IwLTU1NjhlZjY4NDkyZiJdAAAGIAi7P9yqYsM8CF1KN_c5HIAzKSXweQ__wsC5U3KuMjDu
|
|
2
|
+
PYPI_TOKEN=pypi-AgEIcHlwaS5vcmcCJDRjMDk2ODYzLTgxMGMtNDA1OS1iZmZlLWYwY2UwNzU4Y2RkNQACKlszLCJmMzI3MGQyMi05ZDAxLTQyN2QtYmY1OS0wNmI3ODQ4NmQ3ZmIiXQAABiAz2GRvHEwziWkKwgOl50WDB23f5rT6bpidWOjpjMrGKA
|
cursemol-4.1.0/CLAUDE.md
ADDED
|
@@ -0,0 +1,161 @@
|
|
|
1
|
+
# CLAUDE.md
|
|
2
|
+
|
|
3
|
+
This file provides guidance to Claude Code (claude.ai/code) when working
|
|
4
|
+
with code in this repository.
|
|
5
|
+
|
|
6
|
+
## Project Overview
|
|
7
|
+
|
|
8
|
+
CurseMol is a terminal-based molecular sketcher built with Python curses and
|
|
9
|
+
RDKit. It's a Python package (~1861 lines) that allows interactive drawing
|
|
10
|
+
and editing of chemical structures in the terminal.
|
|
11
|
+
|
|
12
|
+
## Running the Application
|
|
13
|
+
|
|
14
|
+
```bash
|
|
15
|
+
# Install the package
|
|
16
|
+
uv sync
|
|
17
|
+
|
|
18
|
+
# Run the installed command
|
|
19
|
+
cursemol
|
|
20
|
+
|
|
21
|
+
# Load a SMILES string on startup
|
|
22
|
+
cursemol "CCO"
|
|
23
|
+
|
|
24
|
+
# See all options
|
|
25
|
+
cursemol --help
|
|
26
|
+
```
|
|
27
|
+
|
|
28
|
+
The application outputs the final SMILES string to stdout when you quit (q).
|
|
29
|
+
|
|
30
|
+
## Development Setup
|
|
31
|
+
|
|
32
|
+
```bash
|
|
33
|
+
# Install dependencies and package in editable mode
|
|
34
|
+
uv sync
|
|
35
|
+
|
|
36
|
+
# Format code with yapf (Google style as configured in .style.yapf)
|
|
37
|
+
yapf -i src/cursemol/__init__.py
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
## Architecture
|
|
41
|
+
|
|
42
|
+
### Project Structure
|
|
43
|
+
|
|
44
|
+
The package is organized as follows:
|
|
45
|
+
- `pyproject.toml`: Package configuration using hatchling build backend
|
|
46
|
+
- `src/cursemol/__init__.py`: Main application code (~1861 lines)
|
|
47
|
+
- Entry point: `cursemol` command (configured in pyproject.toml)
|
|
48
|
+
|
|
49
|
+
### Core Data Structures
|
|
50
|
+
|
|
51
|
+
- **State**: Main application state containing the RDKit molecule, scale,
|
|
52
|
+
box (bounding coordinates), y_offset, and SMILES display toggle
|
|
53
|
+
- **UndoHistory**: Manages undo/redo stack by saving/restoring serialized
|
|
54
|
+
molecule states
|
|
55
|
+
- **ScreenDimensions**: Holds screen dimensions (rows, cols, max_y, max_x)
|
|
56
|
+
- **Mode**: Enum for UI modes (NORMAL, MOVE, SELECT, BOND)
|
|
57
|
+
- **capture_rdkit_log**: Context manager for capturing RDKit logging output
|
|
58
|
+
|
|
59
|
+
### Coordinate System
|
|
60
|
+
|
|
61
|
+
The application maps between three coordinate spaces:
|
|
62
|
+
1. **Molecular coordinates**: Actual 3D coordinates from RDKit (Angstroms)
|
|
63
|
+
2. **Screen coordinates**: Terminal cursor position (columns/rows)
|
|
64
|
+
3. **Scaled coordinates**: Adjusted for zoom level and aspect ratio
|
|
65
|
+
|
|
66
|
+
Key constants:
|
|
67
|
+
- `ASPECT_RATIO = 0.4`: Compensates for terminal character width/height ratio
|
|
68
|
+
- `DEFAULT_SCALE = 8.0`: Columns per angstrom
|
|
69
|
+
- `MIN_SCALE/MAX_SCALE`: Zoom limits
|
|
70
|
+
|
|
71
|
+
Functions to convert between coordinate systems:
|
|
72
|
+
- `screen_to_mol_coords()`: cursor position → molecular coordinates
|
|
73
|
+
- `screen_coords_for_atom()`: atom → screen position
|
|
74
|
+
- `recalculate_box_and_offset()`: Centers molecule after modifications
|
|
75
|
+
|
|
76
|
+
### RDKit Integration
|
|
77
|
+
|
|
78
|
+
The application wraps RDKit's molecular editing capabilities:
|
|
79
|
+
- Uses `RWMol` (read-write molecule) for editing operations
|
|
80
|
+
- `AllChem.Compute2DCoords()` for 2D coordinate generation
|
|
81
|
+
- `Chem.WedgeMolBonds()` to assign wedge/dash stereochemistry from 3D coords
|
|
82
|
+
- Stereochemistry detection via `DetectBondStereochemistry()`,
|
|
83
|
+
`AssignChiralTypesFromBondDirs()`, and `AssignStereochemistry()`
|
|
84
|
+
- `Chem.MolToSmiles()` / `Chem.MolFromSmiles()` for serialization
|
|
85
|
+
- `compute_coords_with_fixed_atoms()`: Custom coordinate generation that
|
|
86
|
+
preserves existing atom positions when appending fragments
|
|
87
|
+
|
|
88
|
+
### Bond Representation
|
|
89
|
+
|
|
90
|
+
Bonds are rendered as ASCII characters between atoms:
|
|
91
|
+
- Single bonds: dots (·) or middle dots (·)
|
|
92
|
+
- Double bonds: equals signs (=)
|
|
93
|
+
- Triple bonds: hash marks (#)
|
|
94
|
+
- Wedge bonds: solid bullets (●) pointing from narrow to wide end
|
|
95
|
+
- Dash bonds: hollow bullets (○) pointing from narrow to wide end
|
|
96
|
+
|
|
97
|
+
The `reverse_bond()` function handles stereochemistry direction changes.
|
|
98
|
+
|
|
99
|
+
### State Management
|
|
100
|
+
|
|
101
|
+
All operations that modify the molecule use save/restore pattern:
|
|
102
|
+
1. Save current state to undo history
|
|
103
|
+
2. Perform operation
|
|
104
|
+
3. Recalculate box and offset to keep molecule centered
|
|
105
|
+
|
|
106
|
+
Key editing operations:
|
|
107
|
+
- `insert_or_modify_atom()`: Add/change atoms at cursor
|
|
108
|
+
- `modify_bond()`: Add/change bonds between atoms
|
|
109
|
+
- `delete_at_cursor()`: Remove atoms or bonds
|
|
110
|
+
- `append_smiles_fragment()`: Attach SMILES fragments to atoms or bonds
|
|
111
|
+
- `connect_sidechain_to_bond()`: Special logic for ring formation when
|
|
112
|
+
appending to bonds
|
|
113
|
+
|
|
114
|
+
### Screen Rendering
|
|
115
|
+
|
|
116
|
+
The rendering pipeline:
|
|
117
|
+
1. `fill_screen_buffer()`: Creates arrays of characters and colors
|
|
118
|
+
2. Renders atoms (with element symbols, charges)
|
|
119
|
+
3. Renders bonds using Bresenham line algorithm in `draw_line()`
|
|
120
|
+
4. `render_screen_buffer()`: Writes buffer to screen with colors
|
|
121
|
+
5. Adds status line and optional SMILES display
|
|
122
|
+
|
|
123
|
+
### Application Flow
|
|
124
|
+
|
|
125
|
+
- `main()`: Entry point that parses arguments and initializes the application
|
|
126
|
+
- `setup_tty()`: Ensures proper TTY handling for curses
|
|
127
|
+
- `init_curses()`: Configures curses environment (colors, cursor visibility)
|
|
128
|
+
- `main_loop()`: Main event loop handling keyboard input and screen updates
|
|
129
|
+
- `redraw_screen()`: Coordinates rendering of molecule, UI elements, and messages
|
|
130
|
+
|
|
131
|
+
## Key Implementation Details
|
|
132
|
+
|
|
133
|
+
### Cursor Navigation
|
|
134
|
+
- The cursor can be on empty space, atoms, or bonds
|
|
135
|
+
- `find_atom_at_cursor()`: Locates atom within tolerance
|
|
136
|
+
- `find_nearest_atom()`: Finds closest atom for snapping or bond creation
|
|
137
|
+
- `find_bond_atoms()`: Identifies which bond the cursor is over by checking
|
|
138
|
+
proximity to line segments
|
|
139
|
+
|
|
140
|
+
### Molecule Cleanup
|
|
141
|
+
- Ctrl-L triggers `cleanup_coordinates()` which regenerates all 2D
|
|
142
|
+
coordinates using `Compute2DCoords()`
|
|
143
|
+
- This is useful after manual edits that distort the structure
|
|
144
|
+
|
|
145
|
+
### Area Delete (X key)
|
|
146
|
+
- Implements rectangle selection in screen coordinates
|
|
147
|
+
- `delete_atoms_in_rect()` converts screen rect to molecular coordinates
|
|
148
|
+
and deletes atoms within the rectangle
|
|
149
|
+
|
|
150
|
+
### SMILES Fragment Appending
|
|
151
|
+
When appending to a bond (not an atom), the fragment forms a ring by
|
|
152
|
+
connecting its first and last atoms to the two bond atoms. This allows
|
|
153
|
+
easy ring fusion operations.
|
|
154
|
+
|
|
155
|
+
### UI Helpers
|
|
156
|
+
- `prompt_user_input()`: Generic prompt for text input
|
|
157
|
+
- `enter_smiles()`: Specialized prompt for SMILES strings
|
|
158
|
+
- `enter_element()`: Specialized prompt for element symbols
|
|
159
|
+
- `show_help()`: Displays help screen with keybindings
|
|
160
|
+
- `draw_instructions()`: Shows mode-specific status line
|
|
161
|
+
- `draw_error_message()`: Displays error messages to user
|
cursemol-4.1.0/LICENSE
ADDED
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
BSD 3-Clause License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2024, Schrodinger, LLC - All Rights Reserved
|
|
4
|
+
|
|
5
|
+
Redistribution and use in source and binary forms, with or without
|
|
6
|
+
modification, are permitted provided that the following conditions are met:
|
|
7
|
+
|
|
8
|
+
1. Redistributions of source code must retain the above copyright notice, this
|
|
9
|
+
list of conditions and the following disclaimer.
|
|
10
|
+
|
|
11
|
+
2. Redistributions in binary form must reproduce the above copyright notice,
|
|
12
|
+
this list of conditions and the following disclaimer in the documentation
|
|
13
|
+
and/or other materials provided with the distribution.
|
|
14
|
+
|
|
15
|
+
3. Neither the name of the copyright holder nor the names of its
|
|
16
|
+
contributors may be used to endorse or promote products derived from
|
|
17
|
+
this software without specific prior written permission.
|
|
18
|
+
|
|
19
|
+
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
|
20
|
+
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
|
21
|
+
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
|
22
|
+
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
|
23
|
+
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
|
24
|
+
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
|
25
|
+
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
|
26
|
+
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
|
27
|
+
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
|
28
|
+
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
cursemol-4.1.0/PKG-INFO
ADDED
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: CurseMol
|
|
3
|
+
Version: 4.1.0
|
|
4
|
+
Summary: Molecular sketcher for the terminally committed
|
|
5
|
+
Project-URL: source, https://github.com/i-tub/cursemol
|
|
6
|
+
Author-email: Ivan Tubert-Brohman <ivan.tubert@gmail.com>
|
|
7
|
+
License-File: LICENSE
|
|
8
|
+
Classifier: Development Status :: 4 - Beta
|
|
9
|
+
Classifier: Environment :: Console :: Curses
|
|
10
|
+
Classifier: Intended Audience :: Science/Research
|
|
11
|
+
Classifier: License :: OSI Approved :: BSD License
|
|
12
|
+
Classifier: Natural Language :: English
|
|
13
|
+
Classifier: Operating System :: POSIX
|
|
14
|
+
Classifier: Programming Language :: Python :: 3
|
|
15
|
+
Classifier: Topic :: Scientific/Engineering :: Chemistry
|
|
16
|
+
Requires-Python: >=3.11
|
|
17
|
+
Requires-Dist: rdkit
|
|
18
|
+
Description-Content-Type: text/markdown
|
|
19
|
+
|
|
20
|
+
## CurseMol - Molecular sketcher for the terminally committed
|
|
21
|
+
|
|
22
|
+
Have you ever been working on a terminal with programs that use SMILES for
|
|
23
|
+
input or output, and switching to your GUI sketcher is too annoying? (Not
|
|
24
|
+
to mention reading or writing the SMILES by hand.)
|
|
25
|
+
|
|
26
|
+
Enter CurseMol, the curses-based molecular editor, with keybindings inspired
|
|
27
|
+
by vi! The molecules are depicted using ASCII art (actually, not exactly; a few
|
|
28
|
+
non-ASCII Unicode characters are used, as well.)
|
|
29
|
+
|
|
30
|
+
You can read in a SMILES string or start from a blank canvas, and when you
|
|
31
|
+
exit, the final SMILES is printed to stdout, which can be useful for piping
|
|
32
|
+
directly into other programs.
|
|
33
|
+
|
|
34
|
+

|
|
35
|
+
|
|
36
|
+
```
|
|
37
|
+
Controls:
|
|
38
|
+
h, j, k, l - Move cursor left/down/up/right (arrow keys supported too)
|
|
39
|
+
H, J, K, L - Move cursor faster (10 cells horizontal, 4 cells vertical)
|
|
40
|
+
Space - Snap cursor to nearest atom
|
|
41
|
+
m - Enter move mode (hjkl moves molecule, Esc to exit)
|
|
42
|
+
s - Enter a SMILES string to replace the current molecule
|
|
43
|
+
S - Toggle SMILES display
|
|
44
|
+
i - Insert/modify atom at cursor position
|
|
45
|
+
a - Append atoms from SMILES to atom or bond under cursor
|
|
46
|
+
(appending to a bond forms a ring by connecting the bond
|
|
47
|
+
atoms to the first and last atoms from the SMILES)
|
|
48
|
+
c, n, o - Insert/modify carbon/nitrogen/oxygen atom
|
|
49
|
+
x - Delete atom or bond
|
|
50
|
+
D - Delete fragment (all atoms connected to cursor atom)
|
|
51
|
+
X - Area delete (select rectangle)
|
|
52
|
+
+, - - Increase/decrease formal charge on atom
|
|
53
|
+
<, > - Zoom out/in
|
|
54
|
+
b - Add bond mode (add atom and move it, Enter to accept)
|
|
55
|
+
1, 2, 3 - Add bond or change bond (order 1/2/3) between nearest atoms
|
|
56
|
+
w, d - Add/change to wedge or dash bond (press again to reverse)
|
|
57
|
+
@ - Clear canvas (reset to blank slate)
|
|
58
|
+
u, r - Undo/redo
|
|
59
|
+
Ctrl-L - Clean up (regenerate coordinates)
|
|
60
|
+
? - Show this help
|
|
61
|
+
q - Quit and print SMILES to stdout
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
### Requirements
|
|
65
|
+
|
|
66
|
+
- Python (tested with 3.11)
|
|
67
|
+
- RDKit (tested with 2025.09.6)
|
cursemol-4.1.0/README.md
ADDED
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
## CurseMol - Molecular sketcher for the terminally committed
|
|
2
|
+
|
|
3
|
+
Have you ever been working on a terminal with programs that use SMILES for
|
|
4
|
+
input or output, and switching to your GUI sketcher is too annoying? (Not
|
|
5
|
+
to mention reading or writing the SMILES by hand.)
|
|
6
|
+
|
|
7
|
+
Enter CurseMol, the curses-based molecular editor, with keybindings inspired
|
|
8
|
+
by vi! The molecules are depicted using ASCII art (actually, not exactly; a few
|
|
9
|
+
non-ASCII Unicode characters are used, as well.)
|
|
10
|
+
|
|
11
|
+
You can read in a SMILES string or start from a blank canvas, and when you
|
|
12
|
+
exit, the final SMILES is printed to stdout, which can be useful for piping
|
|
13
|
+
directly into other programs.
|
|
14
|
+
|
|
15
|
+

|
|
16
|
+
|
|
17
|
+
```
|
|
18
|
+
Controls:
|
|
19
|
+
h, j, k, l - Move cursor left/down/up/right (arrow keys supported too)
|
|
20
|
+
H, J, K, L - Move cursor faster (10 cells horizontal, 4 cells vertical)
|
|
21
|
+
Space - Snap cursor to nearest atom
|
|
22
|
+
m - Enter move mode (hjkl moves molecule, Esc to exit)
|
|
23
|
+
s - Enter a SMILES string to replace the current molecule
|
|
24
|
+
S - Toggle SMILES display
|
|
25
|
+
i - Insert/modify atom at cursor position
|
|
26
|
+
a - Append atoms from SMILES to atom or bond under cursor
|
|
27
|
+
(appending to a bond forms a ring by connecting the bond
|
|
28
|
+
atoms to the first and last atoms from the SMILES)
|
|
29
|
+
c, n, o - Insert/modify carbon/nitrogen/oxygen atom
|
|
30
|
+
x - Delete atom or bond
|
|
31
|
+
D - Delete fragment (all atoms connected to cursor atom)
|
|
32
|
+
X - Area delete (select rectangle)
|
|
33
|
+
+, - - Increase/decrease formal charge on atom
|
|
34
|
+
<, > - Zoom out/in
|
|
35
|
+
b - Add bond mode (add atom and move it, Enter to accept)
|
|
36
|
+
1, 2, 3 - Add bond or change bond (order 1/2/3) between nearest atoms
|
|
37
|
+
w, d - Add/change to wedge or dash bond (press again to reverse)
|
|
38
|
+
@ - Clear canvas (reset to blank slate)
|
|
39
|
+
u, r - Undo/redo
|
|
40
|
+
Ctrl-L - Clean up (regenerate coordinates)
|
|
41
|
+
? - Show this help
|
|
42
|
+
q - Quit and print SMILES to stdout
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
### Requirements
|
|
46
|
+
|
|
47
|
+
- Python (tested with 3.11)
|
|
48
|
+
- RDKit (tested with 2025.09.6)
|
|
File without changes
|
cursemol-4.1.0/demo.gif
ADDED
|
Binary file
|
cursemol-4.1.0/l
ADDED
|
@@ -0,0 +1,145 @@
|
|
|
1
|
+
commit 8c157c90bbef1a927b1544c9be4686d112bf08cd
|
|
2
|
+
Author: Ivan Tubert-Brohman <Ivan.Tubert-Brohman@schrodinger.com>
|
|
3
|
+
Date: Fri Mar 27 20:07:19 2026 -0400
|
|
4
|
+
|
|
5
|
+
Support drawing from blank slate
|
|
6
|
+
|
|
7
|
+
commit ef291c59c032394fe570d8cec86af2e329ad0058
|
|
8
|
+
Author: Ivan Tubert-Brohman <Ivan.Tubert-Brohman@schrodinger.com>
|
|
9
|
+
Date: Fri Mar 27 20:03:43 2026 -0400
|
|
10
|
+
|
|
11
|
+
+/- commands
|
|
12
|
+
|
|
13
|
+
commit 8253c4ee6e9a26631e2e8fe19e9884e7c7bb36ad
|
|
14
|
+
Author: Ivan Tubert-Brohman <Ivan.Tubert-Brohman@schrodinger.com>
|
|
15
|
+
Date: Fri Mar 27 20:01:25 2026 -0400
|
|
16
|
+
|
|
17
|
+
Add charges
|
|
18
|
+
|
|
19
|
+
commit 6a3f76d8a4f132017e9d322019c5240ab09f8c92
|
|
20
|
+
Author: Ivan Tubert-Brohman <Ivan.Tubert-Brohman@schrodinger.com>
|
|
21
|
+
Date: Fri Mar 27 19:54:28 2026 -0400
|
|
22
|
+
|
|
23
|
+
CNO commands; strong kekulization
|
|
24
|
+
|
|
25
|
+
commit db6151ca7c5fc8b2622918fca7c6d6911a7b7187
|
|
26
|
+
Author: Ivan Tubert-Brohman <Ivan.Tubert-Brohman@schrodinger.com>
|
|
27
|
+
Date: Fri Mar 27 19:48:35 2026 -0400
|
|
28
|
+
|
|
29
|
+
Delete bond with x
|
|
30
|
+
|
|
31
|
+
commit 565b9bc5524de27822c763923087bd6806ded257
|
|
32
|
+
Author: Ivan Tubert-Brohman <Ivan.Tubert-Brohman@schrodinger.com>
|
|
33
|
+
Date: Fri Mar 27 19:15:09 2026 -0400
|
|
34
|
+
|
|
35
|
+
Cleanup command
|
|
36
|
+
|
|
37
|
+
commit 8af0dfc2ac1c8ce5df4b20f804a1d0487896c339
|
|
38
|
+
Author: Ivan Tubert-Brohman <Ivan.Tubert-Brohman@schrodinger.com>
|
|
39
|
+
Date: Fri Mar 27 19:12:38 2026 -0400
|
|
40
|
+
|
|
41
|
+
Delete atom
|
|
42
|
+
|
|
43
|
+
commit bc088b06dc88c1b6f42f96ad9abe0c0f3f6a9760
|
|
44
|
+
Author: Ivan Tubert-Brohman <Ivan.Tubert-Brohman@schrodinger.com>
|
|
45
|
+
Date: Fri Mar 27 19:09:41 2026 -0400
|
|
46
|
+
|
|
47
|
+
Add yapf
|
|
48
|
+
|
|
49
|
+
commit bc27afc4f2bc6f31f33350070704137fdb1c1aa5
|
|
50
|
+
Author: Ivan Tubert-Brohman <Ivan.Tubert-Brohman@schrodinger.com>
|
|
51
|
+
Date: Fri Mar 27 19:06:15 2026 -0400
|
|
52
|
+
|
|
53
|
+
Print SMILES on exit
|
|
54
|
+
|
|
55
|
+
commit 08e07f6d61fe018bea1e9a618e2224a774116da2
|
|
56
|
+
Author: Ivan Tubert-Brohman <Ivan.Tubert-Brohman@schrodinger.com>
|
|
57
|
+
Date: Fri Mar 27 19:00:31 2026 -0400
|
|
58
|
+
|
|
59
|
+
Silence logger
|
|
60
|
+
|
|
61
|
+
commit 951d354a6cfa38f13a4878b27cbbf83519ea174a
|
|
62
|
+
Author: Ivan Tubert-Brohman <Ivan.Tubert-Brohman@schrodinger.com>
|
|
63
|
+
Date: Fri Mar 27 18:55:55 2026 -0400
|
|
64
|
+
|
|
65
|
+
Catch some exceptions
|
|
66
|
+
|
|
67
|
+
commit 324178f21f049fed2a62ce1dd0e66298e7013c94
|
|
68
|
+
Author: Ivan Tubert-Brohman <Ivan.Tubert-Brohman@schrodinger.com>
|
|
69
|
+
Date: Fri Mar 27 18:51:33 2026 -0400
|
|
70
|
+
|
|
71
|
+
Add bonds
|
|
72
|
+
|
|
73
|
+
commit f69ff9ef1bb267df0953e1c65f101e178569d0a1
|
|
74
|
+
Author: Ivan Tubert-Brohman <Ivan.Tubert-Brohman@schrodinger.com>
|
|
75
|
+
Date: Fri Mar 27 18:43:02 2026 -0400
|
|
76
|
+
|
|
77
|
+
Show SMILES
|
|
78
|
+
|
|
79
|
+
commit c109e38c566fcadd3825949e7f6f102448f3b78c
|
|
80
|
+
Author: Ivan Tubert-Brohman <Ivan.Tubert-Brohman@schrodinger.com>
|
|
81
|
+
Date: Fri Mar 27 18:38:34 2026 -0400
|
|
82
|
+
|
|
83
|
+
Center
|
|
84
|
+
|
|
85
|
+
commit 4e2110934b74bfbd780f8b21485bda57e5868da4
|
|
86
|
+
Author: Ivan Tubert-Brohman <Ivan.Tubert-Brohman@schrodinger.com>
|
|
87
|
+
Date: Fri Mar 27 18:35:34 2026 -0400
|
|
88
|
+
|
|
89
|
+
Add atom
|
|
90
|
+
|
|
91
|
+
commit c505e4a30122ecd5705152111273970c952ecef3
|
|
92
|
+
Author: Ivan Tubert-Brohman <Ivan.Tubert-Brohman@schrodinger.com>
|
|
93
|
+
Date: Fri Mar 27 18:03:30 2026 -0400
|
|
94
|
+
|
|
95
|
+
Refactor
|
|
96
|
+
|
|
97
|
+
commit 768df063496719360c0673489cae3044241c85c7
|
|
98
|
+
Author: Ivan Tubert-Brohman <Ivan.Tubert-Brohman@schrodinger.com>
|
|
99
|
+
Date: Fri Mar 27 18:01:27 2026 -0400
|
|
100
|
+
|
|
101
|
+
Add argparse; remove x
|
|
102
|
+
|
|
103
|
+
commit 5e17acafcc8e535be75c82171791fea5ad01e784
|
|
104
|
+
Author: Ivan Tubert-Brohman <Ivan.Tubert-Brohman@schrodinger.com>
|
|
105
|
+
Date: Fri Mar 27 17:56:53 2026 -0400
|
|
106
|
+
|
|
107
|
+
Do partial redraw
|
|
108
|
+
|
|
109
|
+
commit f4b9a9b30794bb6b05bb359f17c729663fc093f4
|
|
110
|
+
Author: Ivan Tubert-Brohman <Ivan.Tubert-Brohman@schrodinger.com>
|
|
111
|
+
Date: Fri Mar 27 17:51:39 2026 -0400
|
|
112
|
+
|
|
113
|
+
Make sketch persistent
|
|
114
|
+
|
|
115
|
+
commit cf26daa2b09d1c0e930534c5fa8fefebbdc560e7
|
|
116
|
+
Author: Ivan Tubert-Brohman <Ivan.Tubert-Brohman@schrodinger.com>
|
|
117
|
+
Date: Fri Mar 27 17:47:54 2026 -0400
|
|
118
|
+
|
|
119
|
+
First try at sketching
|
|
120
|
+
|
|
121
|
+
commit a9a70f7e3f7ae2fadd941e8a9bf4c48a002b9451
|
|
122
|
+
Author: Ivan Tubert-Brohman <Ivan.Tubert-Brohman@schrodinger.com>
|
|
123
|
+
Date: Fri Mar 27 17:45:50 2026 -0400
|
|
124
|
+
|
|
125
|
+
Add draw_mol() stub
|
|
126
|
+
|
|
127
|
+
commit 6942be59e0535d42bb3e09321070f4ab6e986f82
|
|
128
|
+
Author: Ivan Tubert-Brohman <Ivan.Tubert-Brohman@schrodinger.com>
|
|
129
|
+
Date: Fri Mar 27 17:37:15 2026 -0400
|
|
130
|
+
|
|
131
|
+
Refactor
|
|
132
|
+
|
|
133
|
+
commit 846d78de47e9f62d1df97d33b53a1f965b8d6c33
|
|
134
|
+
Author: Ivan Tubert-Brohman <Ivan.Tubert-Brohman@schrodinger.com>
|
|
135
|
+
Date: Fri Mar 27 17:35:27 2026 -0400
|
|
136
|
+
|
|
137
|
+
Prompt for SMILES
|
|
138
|
+
|
|
139
|
+
commit b1308fa44a021abbfbe0b4becea98348009bb4c1
|
|
140
|
+
Author: Ivan Tubert-Brohman <Ivan.Tubert-Brohman@schrodinger.com>
|
|
141
|
+
Date: Fri Mar 27 17:30:58 2026 -0400
|
|
142
|
+
|
|
143
|
+
Curses hello world
|
|
144
|
+
|
|
145
|
+
Just move around and place Xes.
|
cursemol-4.1.0/notes
ADDED
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
Ideas:
|
|
2
|
+
|
|
3
|
+
How to depict stereo wedges and dashes?
|
|
4
|
+
|
|
5
|
+
Maybe we could change the first bond character, or maybe the first half of the
|
|
6
|
+
bond, to a ^ or v instead of a dot, to signal if the bond goes up or down
|
|
7
|
+
relative to the beginning atom.
|
|
8
|
+
|
|
9
|
+
We could also use bold, reverse, or color. But in any case a tricky part is
|
|
10
|
+
that the bond is directional; we can't simply tag the entire bond.
|
|
11
|
+
|
|
12
|
+
What other characters might we use?
|
|
13
|
+
|
|
14
|
+
From pure ASCII:
|
|
15
|
+
|
|
16
|
+
: second half of dotted bond?
|
|
17
|
+
| second half of solid wedge?
|
|
18
|
+
,
|
|
19
|
+
>
|
|
20
|
+
<
|
|
21
|
+
"
|
|
22
|
+
'
|
|
23
|
+
`
|
|
24
|
+
* (better for dummy atoms)
|
|
25
|
+
~ (better for wiggly bonds)
|
|
26
|
+
|
|
27
|
+
Cvvv...C
|
|
28
|
+
C^^^...C
|
|
29
|
+
|
|
30
|
+
From Unicode maybe arrows?
|
|
31
|
+
|
|
32
|
+
↑
|
|
33
|
+
↓
|
|
34
|
+
|
|
35
|
+
or bullets? Let's go with that (solid bullet / empty bullet / middle dot)
|
|
36
|
+
|
|
37
|
+
TODO:
|
|
38
|
+
|
|
39
|
+
- Add a "fit to screen" command?
|
|
40
|
+
- Improvements to bond selection: make the angle tolerance a function of
|
|
41
|
+
distance.
|
|
42
|
+
- There's a stereochemistry bug! Cleanup can cause epimerization! We need to
|
|
43
|
+
assign stereo before doing cleanup.
|
|
44
|
+
- Capture Ctrl-C?
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
[project]
|
|
2
|
+
name = "CurseMol"
|
|
3
|
+
dynamic = ["version"]
|
|
4
|
+
description = "Molecular sketcher for the terminally committed"
|
|
5
|
+
authors = [
|
|
6
|
+
{ name = "Ivan Tubert-Brohman", email = "ivan.tubert@gmail.com" }
|
|
7
|
+
]
|
|
8
|
+
readme = "README.md"
|
|
9
|
+
requires-python = ">= 3.11"
|
|
10
|
+
dependencies = [
|
|
11
|
+
"rdkit",
|
|
12
|
+
]
|
|
13
|
+
classifiers = [
|
|
14
|
+
"Development Status :: 4 - Beta",
|
|
15
|
+
"Intended Audience :: Science/Research",
|
|
16
|
+
"Topic :: Scientific/Engineering :: Chemistry",
|
|
17
|
+
"Intended Audience :: Science/Research",
|
|
18
|
+
"License :: OSI Approved :: BSD License",
|
|
19
|
+
"Programming Language :: Python :: 3",
|
|
20
|
+
"Operating System :: POSIX",
|
|
21
|
+
"Environment :: Console :: Curses",
|
|
22
|
+
"Natural Language :: English",
|
|
23
|
+
]
|
|
24
|
+
|
|
25
|
+
[project.urls]
|
|
26
|
+
source = "https://github.com/i-tub/cursemol"
|
|
27
|
+
|
|
28
|
+
[project.scripts]
|
|
29
|
+
cursemol = "cursemol:main"
|
|
30
|
+
|
|
31
|
+
[build-system]
|
|
32
|
+
requires = ["hatchling"]
|
|
33
|
+
build-backend = "hatchling.build"
|
|
34
|
+
|
|
35
|
+
[tool.hatch.version]
|
|
36
|
+
path = "src/cursemol/__init__.py"
|
|
Binary file
|