textual-searchable-selectionlist 0.0.1__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.
- textual_searchable_selectionlist-0.0.1/.editorconfig +21 -0
- textual_searchable_selectionlist-0.0.1/.gitignore +73 -0
- textual_searchable_selectionlist-0.0.1/LICENSE.txt +21 -0
- textual_searchable_selectionlist-0.0.1/PKG-INFO +52 -0
- textual_searchable_selectionlist-0.0.1/README.md +36 -0
- textual_searchable_selectionlist-0.0.1/WARP.md +143 -0
- textual_searchable_selectionlist-0.0.1/admin/__init__.py +5 -0
- textual_searchable_selectionlist-0.0.1/admin/build.py +381 -0
- textual_searchable_selectionlist-0.0.1/admin/lint.py +54 -0
- textual_searchable_selectionlist-0.0.1/admin/pip.py +178 -0
- textual_searchable_selectionlist-0.0.1/admin/requirements/requirements-dev.in +12 -0
- textual_searchable_selectionlist-0.0.1/admin/requirements/requirements-dev.txt +138 -0
- textual_searchable_selectionlist-0.0.1/admin/requirements/requirements.in +1 -0
- textual_searchable_selectionlist-0.0.1/admin/requirements/requirements.txt +25 -0
- textual_searchable_selectionlist-0.0.1/admin/utils.py +160 -0
- textual_searchable_selectionlist-0.0.1/pyproject.toml +84 -0
- textual_searchable_selectionlist-0.0.1/src/textual_searchable_selectionlist/__init__.py +1 -0
- textual_searchable_selectionlist-0.0.1/src/textual_searchable_selectionlist/options.py +40 -0
- textual_searchable_selectionlist-0.0.1/src/textual_searchable_selectionlist/py.typed +2 -0
- textual_searchable_selectionlist-0.0.1/src/textual_searchable_selectionlist/searchable_list_app.py +65 -0
- textual_searchable_selectionlist-0.0.1/src/textual_searchable_selectionlist/searchable_list_widget.py +216 -0
- textual_searchable_selectionlist-0.0.1/src/textual_searchable_selectionlist/select.py +63 -0
- textual_searchable_selectionlist-0.0.1/tests/__init__.py +0 -0
- textual_searchable_selectionlist-0.0.1/tests/manual/__init__.py +0 -0
- textual_searchable_selectionlist-0.0.1/tests/manual/searchable_selection_list_select.py +22 -0
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
# http://editorconfig.org
|
|
2
|
+
|
|
3
|
+
root = true
|
|
4
|
+
|
|
5
|
+
[*]
|
|
6
|
+
indent_style = space
|
|
7
|
+
indent_size = 4
|
|
8
|
+
trim_trailing_whitespace = true
|
|
9
|
+
insert_final_newline = true
|
|
10
|
+
charset = utf-8
|
|
11
|
+
end_of_line = lf
|
|
12
|
+
|
|
13
|
+
[*.md]
|
|
14
|
+
trim_trailing_whitespace = false
|
|
15
|
+
|
|
16
|
+
[*.bat]
|
|
17
|
+
indent_style = tab
|
|
18
|
+
end_of_line = crlf
|
|
19
|
+
|
|
20
|
+
[Makefile]
|
|
21
|
+
indent_style = tab
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
# Byte-compiled / optimized / DLL files
|
|
2
|
+
__pycache__/
|
|
3
|
+
*.py[cod]
|
|
4
|
+
*$py.class
|
|
5
|
+
|
|
6
|
+
# Distribution / packaging
|
|
7
|
+
.Python
|
|
8
|
+
env/
|
|
9
|
+
build/
|
|
10
|
+
develop-eggs/
|
|
11
|
+
dist/
|
|
12
|
+
downloads/
|
|
13
|
+
eggs/
|
|
14
|
+
.eggs/
|
|
15
|
+
lib/
|
|
16
|
+
lib64/
|
|
17
|
+
parts/
|
|
18
|
+
sdist/
|
|
19
|
+
var/
|
|
20
|
+
wheels/
|
|
21
|
+
*.egg-info/
|
|
22
|
+
.installed.cfg
|
|
23
|
+
*.egg
|
|
24
|
+
|
|
25
|
+
# Installer logs
|
|
26
|
+
pip-log.txt
|
|
27
|
+
pip-delete-this-directory.txt
|
|
28
|
+
|
|
29
|
+
# Unit test / coverage reports
|
|
30
|
+
htmlcov/
|
|
31
|
+
.tox/
|
|
32
|
+
.coverage
|
|
33
|
+
.coverage.*
|
|
34
|
+
.cache
|
|
35
|
+
nosetests.xml
|
|
36
|
+
coverage.xml
|
|
37
|
+
*.cover
|
|
38
|
+
.hypothesis/
|
|
39
|
+
.pytest_cache/
|
|
40
|
+
|
|
41
|
+
# PyBuilder
|
|
42
|
+
target/
|
|
43
|
+
|
|
44
|
+
# pyenv
|
|
45
|
+
.python-version
|
|
46
|
+
|
|
47
|
+
# dotenv
|
|
48
|
+
.env
|
|
49
|
+
|
|
50
|
+
# virtualenv
|
|
51
|
+
.venv
|
|
52
|
+
venv/
|
|
53
|
+
ENV/
|
|
54
|
+
|
|
55
|
+
# Spyder project settings
|
|
56
|
+
.spyderproject
|
|
57
|
+
.spyproject
|
|
58
|
+
|
|
59
|
+
# mkdocs documentation
|
|
60
|
+
/site
|
|
61
|
+
|
|
62
|
+
# mypy
|
|
63
|
+
.mypy_cache/
|
|
64
|
+
|
|
65
|
+
# DS Store files
|
|
66
|
+
.DS_Store
|
|
67
|
+
|
|
68
|
+
# IDE settings
|
|
69
|
+
.vscode/
|
|
70
|
+
.idea/
|
|
71
|
+
|
|
72
|
+
# Misc
|
|
73
|
+
release-notes.md
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026, Joao Coelho
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: textual-searchable-selectionlist
|
|
3
|
+
Version: 0.0.1
|
|
4
|
+
Summary: Add search to Textual SelectionList.
|
|
5
|
+
Author: Joao Coelho
|
|
6
|
+
Description-Content-Type: text/markdown
|
|
7
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
8
|
+
Classifier: Framework :: Pytest
|
|
9
|
+
Classifier: Intended Audience :: Developers
|
|
10
|
+
Classifier: Programming Language :: Python
|
|
11
|
+
Classifier: Development Status :: 4 - Beta
|
|
12
|
+
License-File: LICENSE.txt
|
|
13
|
+
Requires-Dist: textual
|
|
14
|
+
Project-URL: Home, https://github.com/joaonc/textual-searchable-selectionlist
|
|
15
|
+
|
|
16
|
+
# Searchable SelectionList
|
|
17
|
+
Add search to Textual's [SelectionList](https://textual.textualize.io/widgets/selection_list/).
|
|
18
|
+
|
|
19
|
+
* Selectable items can be filtered by substring.
|
|
20
|
+
* Select one or multiple items.
|
|
21
|
+
* Search is case-insensitive.
|
|
22
|
+
|
|
23
|
+
## Installation
|
|
24
|
+
```bash
|
|
25
|
+
pip install searchable-selection-list
|
|
26
|
+
```
|
|
27
|
+
|
|
28
|
+
## Usage
|
|
29
|
+
```python
|
|
30
|
+
from textual_searchable_selectionlist.options import SelectionStrategy
|
|
31
|
+
from textual_searchable_selectionlist.select import select, select_enum
|
|
32
|
+
|
|
33
|
+
selected = select(
|
|
34
|
+
['John', 'Jane', 'James'],
|
|
35
|
+
selection_strategy=SelectionStrategy.MULTIPLE,
|
|
36
|
+
search_title='Select people',
|
|
37
|
+
)
|
|
38
|
+
|
|
39
|
+
# Enums
|
|
40
|
+
# class Color(Enum):
|
|
41
|
+
# RED = 'red'
|
|
42
|
+
# GREEN = 'green'
|
|
43
|
+
#
|
|
44
|
+
# selected_colors = select_enum(Color, selection_strategy=SelectionStrategy.ONE)
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
## Testing
|
|
48
|
+
There are currently no automated tests. Manual testing can be done by running:
|
|
49
|
+
```bash
|
|
50
|
+
python tests/manual/searchable_selection_list_select.py
|
|
51
|
+
```
|
|
52
|
+
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
# Searchable SelectionList
|
|
2
|
+
Add search to Textual's [SelectionList](https://textual.textualize.io/widgets/selection_list/).
|
|
3
|
+
|
|
4
|
+
* Selectable items can be filtered by substring.
|
|
5
|
+
* Select one or multiple items.
|
|
6
|
+
* Search is case-insensitive.
|
|
7
|
+
|
|
8
|
+
## Installation
|
|
9
|
+
```bash
|
|
10
|
+
pip install searchable-selection-list
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
## Usage
|
|
14
|
+
```python
|
|
15
|
+
from textual_searchable_selectionlist.options import SelectionStrategy
|
|
16
|
+
from textual_searchable_selectionlist.select import select, select_enum
|
|
17
|
+
|
|
18
|
+
selected = select(
|
|
19
|
+
['John', 'Jane', 'James'],
|
|
20
|
+
selection_strategy=SelectionStrategy.MULTIPLE,
|
|
21
|
+
search_title='Select people',
|
|
22
|
+
)
|
|
23
|
+
|
|
24
|
+
# Enums
|
|
25
|
+
# class Color(Enum):
|
|
26
|
+
# RED = 'red'
|
|
27
|
+
# GREEN = 'green'
|
|
28
|
+
#
|
|
29
|
+
# selected_colors = select_enum(Color, selection_strategy=SelectionStrategy.ONE)
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
## Testing
|
|
33
|
+
There are currently no automated tests. Manual testing can be done by running:
|
|
34
|
+
```bash
|
|
35
|
+
python tests/manual/searchable_selection_list_select.py
|
|
36
|
+
```
|
|
@@ -0,0 +1,143 @@
|
|
|
1
|
+
# WARP.md
|
|
2
|
+
|
|
3
|
+
This file provides guidance to WARP (warp.dev) when working with code in this repository.
|
|
4
|
+
|
|
5
|
+
## Project Overview
|
|
6
|
+
|
|
7
|
+
A Textual widget library that adds search functionality to Textual's SelectionList widget. The widget provides case-insensitive substring filtering, supports single and multiple selection modes, and offers an API for programmatic selection in terminal-based applications.
|
|
8
|
+
|
|
9
|
+
## Development Commands
|
|
10
|
+
|
|
11
|
+
### Task Runner
|
|
12
|
+
This project uses `typer-invoke` to organize development tasks into admin modules. The configuration is in `pyproject.toml` under `[tool.typer-invoke]`.
|
|
13
|
+
|
|
14
|
+
Run tasks using Python module syntax:
|
|
15
|
+
```bash
|
|
16
|
+
python -m admin.lint --help
|
|
17
|
+
python -m admin.build --help
|
|
18
|
+
python -m admin.pip --help
|
|
19
|
+
```
|
|
20
|
+
|
|
21
|
+
### Linting and Formatting
|
|
22
|
+
All linter configurations are in `pyproject.toml`.
|
|
23
|
+
|
|
24
|
+
Run all linters in sequence:
|
|
25
|
+
```bash
|
|
26
|
+
python -m admin.lint all
|
|
27
|
+
```
|
|
28
|
+
|
|
29
|
+
Run individual linters:
|
|
30
|
+
```bash
|
|
31
|
+
python -m admin.lint black .
|
|
32
|
+
python -m admin.lint isort .
|
|
33
|
+
python -m admin.lint flake8 .
|
|
34
|
+
python -m admin.lint mypy .
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
### Building and Publishing
|
|
38
|
+
|
|
39
|
+
Clean build artifacts:
|
|
40
|
+
```bash
|
|
41
|
+
python -m admin.build clean
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
Update version (interactive or with flags):
|
|
45
|
+
```bash
|
|
46
|
+
python -m admin.build version --bump patch
|
|
47
|
+
python -m admin.build version --version 1.2.3
|
|
48
|
+
```
|
|
49
|
+
|
|
50
|
+
Build and publish package:
|
|
51
|
+
```bash
|
|
52
|
+
python -m admin.build publish
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
### Package Management
|
|
56
|
+
|
|
57
|
+
Compile requirements files (uses pip-compile):
|
|
58
|
+
```bash
|
|
59
|
+
python -m admin.pip compile
|
|
60
|
+
python -m admin.pip compile --clean
|
|
61
|
+
```
|
|
62
|
+
|
|
63
|
+
Sync environment with requirements:
|
|
64
|
+
```bash
|
|
65
|
+
python -m admin.pip sync
|
|
66
|
+
```
|
|
67
|
+
|
|
68
|
+
Install requirements:
|
|
69
|
+
```bash
|
|
70
|
+
python -m admin.pip install
|
|
71
|
+
```
|
|
72
|
+
|
|
73
|
+
### Testing
|
|
74
|
+
|
|
75
|
+
There are currently no automated unit tests. Manual testing can be done by running:
|
|
76
|
+
```bash
|
|
77
|
+
python tests/manual/searchable_selection_list_select.py
|
|
78
|
+
```
|
|
79
|
+
|
|
80
|
+
## Code Architecture
|
|
81
|
+
|
|
82
|
+
### Core Components
|
|
83
|
+
|
|
84
|
+
**SearchableListWidget** (`searchable_list_widget.py`)
|
|
85
|
+
- Main widget that combines a search Input with a SelectionList
|
|
86
|
+
- Handles keyboard navigation (arrow keys, enter, escape, ctrl+space/a/d)
|
|
87
|
+
- Implements real-time filtering by disabling non-matching options
|
|
88
|
+
- Generic over SelectionType for type safety
|
|
89
|
+
- Key behavior: when focused on SelectionList, alphanumeric keys are routed to the search input
|
|
90
|
+
|
|
91
|
+
**SearchableListApp** (`searchable_list_app.py`)
|
|
92
|
+
- Textual App wrapper for SearchableListWidget
|
|
93
|
+
- Provides full-screen or inline display modes
|
|
94
|
+
- Returns selected items via app.exit()
|
|
95
|
+
- Handles SelectionStrategy.ALL by immediately exiting with all items
|
|
96
|
+
|
|
97
|
+
**SelectionStrategy** (`options.py`)
|
|
98
|
+
- Enum defining selection modes: MULTIPLE, ONE, ALL, FAIL
|
|
99
|
+
- MULTIPLE/ALL: Allow selecting multiple items
|
|
100
|
+
- ONE: Single selection mode (deselects others when selecting)
|
|
101
|
+
- FAIL: Raises ValueError if multiple selections provided
|
|
102
|
+
|
|
103
|
+
**select() function** (`select.py`)
|
|
104
|
+
- High-level API for quick item selection
|
|
105
|
+
- Returns list of selected items
|
|
106
|
+
- Supports string, tuple, or Selection objects as input
|
|
107
|
+
- Includes select_enum() helper for selecting from Python enums
|
|
108
|
+
|
|
109
|
+
### Module Structure
|
|
110
|
+
```
|
|
111
|
+
src/textual_searchable_selectionlist/
|
|
112
|
+
├── __init__.py # Version info
|
|
113
|
+
├── searchable_list_widget.py # Core widget implementation
|
|
114
|
+
├── searchable_list_app.py # Textual app wrapper
|
|
115
|
+
├── options.py # Selection mode enum and filtering options
|
|
116
|
+
└── select.py # High-level selection API
|
|
117
|
+
|
|
118
|
+
admin/ # Development task modules
|
|
119
|
+
├── __init__.py # Project constants (PROJECT_ROOT, SOURCE_DIR)
|
|
120
|
+
├── utils.py # Shared utilities (run, logger, etc.)
|
|
121
|
+
├── build.py # Build, version, and publish tasks
|
|
122
|
+
├── lint.py # Linting tasks
|
|
123
|
+
├── pip.py # Package management tasks
|
|
124
|
+
└── requirements/ # Requirements files (.in and .txt)
|
|
125
|
+
```
|
|
126
|
+
|
|
127
|
+
### Key Design Patterns
|
|
128
|
+
|
|
129
|
+
**Filtering mechanism**: Items are filtered by setting `option.disabled = not is_match` rather than removing them from the list, preserving indices.
|
|
130
|
+
|
|
131
|
+
**Keyboard routing**: When SelectionList is focused, single alphanumeric keypresses are intercepted and forwarded to the search Input via `input_widget.post_message(event)`.
|
|
132
|
+
|
|
133
|
+
**Callback-based selection**: Widget accepts `selected_callback` that's invoked on Enter key, receiving the list of selected items.
|
|
134
|
+
|
|
135
|
+
**Build system**: Uses flit for building/publishing. Version is tracked in both `pyproject.toml` and `src/textual_searchable_selectionlist/__init__.py`.
|
|
136
|
+
|
|
137
|
+
## Code Style
|
|
138
|
+
|
|
139
|
+
- Follow PEP8 with 100 character line limit (enforced by black)
|
|
140
|
+
- Single quotes for strings, triple double quotes for docstrings
|
|
141
|
+
- Python 3.12+ syntax and type hints (use `str | None` not `Optional[str]`)
|
|
142
|
+
- 4 spaces for indentation
|
|
143
|
+
- Line endings: LF (Unix style, see `.editorconfig`)
|