Skip to content

Commit e6106f5

Browse files
regex playground is now pip installable
1 parent 95e8b8e commit e6106f5

File tree

4 files changed

+52
-23
lines changed

4 files changed

+52
-23
lines changed

PyRegexPlayground/README.md

+15-9
Original file line numberDiff line numberDiff line change
@@ -2,25 +2,31 @@
22

33
This TUI application is intended as an interactive playground for Python Regular Expressions. The app also includes a comprehensive cheatsheet and several interactive examples.
44

5-
> **Warning**
6-
> Work in progress.
7-
85
# Installation
96

10-
You'll need to install `textual` first. See [Textual documentation](https://textual.textualize.io/getting_started/) for more details about installation. After that, you can clone this repository and run the `pyregex_playground.py` script. Adjust terminal dimensions as needed. Example instructions are shown below, adjust them based on your preferences and OS.
7+
This app is available on PyPI as [regexplayground](https://pypi.org/project/regexplayground/). Example installation instructions are shown below, adjust them based on your preferences and OS.
118

129
```bash
10+
# virtual environment
1311
$ python3 -m venv textual_apps
1412
$ cd textual_apps
1513
$ source bin/activate
16-
$ pip install textual==0.12.1
14+
$ pip install regexplayground
15+
16+
# launch the app
17+
$ regexplayground
18+
```
1719

18-
$ git clone --depth 1 https://github.com/learnbyexample/TUI-apps.git
19-
$ cd TUI-apps/PyRegexPlayground
20-
$ python pyregex_playground.py
20+
To run the app without having to enter the virtual environment again, add this alias to `.bashrc` (or equivalent):
21+
22+
```bash
23+
# you'll have to change the path
24+
alias regexplayground='/path/to/textual_apps/bin/regexplayground'
2125
```
2226

23-
Here are some sample screenshots:
27+
As an alternative, you can install `textual` (see [Textual documentation](https://textual.textualize.io/getting_started/) for more details), clone this repository and run the `pyregex_playground.py` file.
28+
29+
Adjust the terminal dimensions for the widgets to appear properly, for example 84x25 (characters x lines). Here are some sample screenshots:
2430

2531
<p align="center"><img src="./pyregex_finditer.png" alt="Sample screenshot from the Playground screen" /></p>
2632

PyRegexPlayground/app_guide.md

+18-1
Original file line numberDiff line numberDiff line change
@@ -6,10 +6,27 @@ You can type the search pattern in the **Compile** input box and press the **Ent
66

77
The compiled pattern is available via the `pat` variable and you can use `ip` to refer to the input string. You can transform or extract data by typing appropriate expression in the **Action** box. For example, `pat.sub(r'(\g<0>)', ip)` will add parenthesis around the matching portions.
88

9-
The input string is obtained from the `ip.txt` file. You can change contents of this file and press **Ctrl+i** to update the `ip` variable. You'll have to press **Enter** again to update the results for the changed data.
9+
You can skip the Compile box and directly use the Action box too. For example, `[m.span() for m in re.finditer(r'\d+', ip)]` to get the location of all the matching portions.
1010

1111
> **Warning:** There is no safeguard against the commands you have typed. They are treated as if you executed them from a Python program.
1212
13+
### Changing ip
14+
15+
The input string is obtained from the `ip.txt` file. You can change contents of this file and press **Ctrl+p** to update the `ip` variable. You'll have to press **Enter** again to update the results for the changed data.
16+
17+
If you cloned the repo, you'd be able to easily spot the `ip.txt` file in the same directory as the script you are running. If you installed the app via the `pip` command in a virtual environment, you'll have to locate this file first. For example:
18+
19+
```bash
20+
# go to the virtual environment
21+
$ find -name pyregex_playground.py
22+
./lib/python3.8/site-packages/regexplayground/pyregex_playground.py
23+
24+
$ find -name ip.txt
25+
./lib/python3.8/site-packages/regexplayground/ip.txt
26+
```
27+
28+
This convoluted procedure will be simplified in the future by adding a widget for accepting multiline user input.
29+
1330
### Handling errors
1431

1532
Some of the error types are caught. In such cases, the background color of the input boxes will change to red and the error message will be displayed below the corresponding box. Other errors might result in the app crashing.
124 Bytes
Loading

PyRegexPlayground/pyregex_playground.py

+19-13
Original file line numberDiff line numberDiff line change
@@ -13,9 +13,11 @@
1313
import re
1414
from functools import partial
1515
from math import factorial
16+
from pathlib import Path
1617

1718
ERROR_TYPES = (re.error, SyntaxError, TypeError, ValueError,
18-
NameError, AttributeError)
19+
NameError, AttributeError, IndexError)
20+
APP_DIR = Path(__file__).parent.resolve()
1921

2022
class CommentHighlighter(Highlighter):
2123
def highlight(self, text):
@@ -83,7 +85,7 @@ def load_examples(self):
8385
self.v_code_block = []
8486
self.input_collection = []
8587
comment_highlighter = CommentHighlighter()
86-
with open('examples.json') as f:
88+
with open(APP_DIR.joinpath('examples.json')) as f:
8789
md = iter(json.load(f).values())
8890
idx = 0
8991
for info in md:
@@ -115,7 +117,7 @@ def action_reload(self):
115117

116118

117119
class Playground(Screen):
118-
BINDINGS = [Binding('ctrl+i', 'update_ip', 'Update ip', show=True),
120+
BINDINGS = [Binding('ctrl+p', 'update_ip', 'Update ip', show=True),
119121
Binding('f1', 'guide', 'App Guide', show=False),
120122
Binding('f2', 'cheatsheet', 'Cheatsheet', show=False),
121123
Binding('f3', 'examples', 'Interactive Examples', show=False),
@@ -132,6 +134,7 @@ def __init__(self):
132134
self.l_compile_error = Label('')
133135
self.l_action_error = Label('')
134136

137+
self.ip_file = APP_DIR.joinpath('ip.txt')
135138
self.read_data()
136139
self.l_input = Label(classes='playground_ip_op')
137140
self.ip_panel = partial(Panel, title='ip', title_align='center')
@@ -219,39 +222,42 @@ def on_button_pressed(self, event):
219222
self.action_guide()
220223

221224
def read_data(self):
222-
with open('ip.txt') as f:
225+
with open(self.ip_file) as f:
223226
self.data = f.read()
224227

225228
def action_guide(self):
226-
app.push_screen('guide')
229+
self.app.push_screen('guide')
227230

228231
def action_cheatsheet(self):
229-
app.push_screen('cheatsheet')
232+
self.app.push_screen('cheatsheet')
230233

231234
def action_examples(self):
232-
app.push_screen('examples')
235+
self.app.push_screen('examples')
233236

234237
def action_update_ip(self):
235238
self.read_data()
236239
self.l_input.update(self.ip_panel(self.data))
237240

238241
class PyRegexPlayground(App):
239242
SCREENS = {'playground': Playground(),
240-
'guide': ShowMarkdown('app_guide.md'),
241-
'cheatsheet': ShowMarkdown('cheatsheet.md'),
243+
'guide': ShowMarkdown(APP_DIR.joinpath('app_guide.md')),
244+
'cheatsheet': ShowMarkdown(APP_DIR.joinpath('cheatsheet.md')),
242245
'examples': Examples()}
243246
CSS_PATH = 'pyregex_playground.css'
244247
BINDINGS = [('ctrl+t', 'toggle_theme', 'Theme'),
245248
('ctrl+q', 'app.quit', 'Quit')]
246249

247250
def on_mount(self):
248-
self.dark = False
249-
self.push_screen('playground')
251+
self.app.dark = False
252+
self.app.push_screen('playground')
250253

251254
def action_toggle_theme(self):
252-
self.dark ^= True
255+
self.app.dark ^= True
253256

254-
if __name__ == '__main__':
257+
def main():
255258
app = PyRegexPlayground()
256259
app.run()
257260

261+
if __name__ == '__main__':
262+
main()
263+

0 commit comments

Comments
 (0)