Skip to content

Commit d23e0b8

Browse files
committed
* wip
1 parent eb6ca08 commit d23e0b8

File tree

3 files changed

+91
-0
lines changed

3 files changed

+91
-0
lines changed

README.md

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,42 @@
11
# vscode-python-fstring-dsl
22
Syntax highlighting for HTML, SQL, JS, CSS in Python f-strings
3+
4+
## Usage
5+
To trigger the syntax highlight you must wrap your
6+
DSL-string in a specific function (or method) call: `html(...),` `sql(...)`, `js(...)`, `css(...)`. This function may be noop like the Python's `typing.cast()` or do something useful, i.e. trimming whitespaces.
7+
8+
```python
9+
def html(s: str):
10+
return s
11+
```
12+
13+
If the string is template (f-string), the internal f-expressions will be syntax highlighted too.
14+
15+
## Sample
16+
![sample.png](https://raw.githubusercontent.com/jkmnt/vscode-python-fstring-dsl/sample.png)
17+
18+
This sample shows the well-typed server-side Dialog component with
19+
bootsrap styling, htmx magic and text escaping.
20+
21+
22+
## Note
23+
24+
- The syntax matching is naive. It will work only for the simple common cases. If something don't color the way it should, the best solution is to simplify the template.
25+
26+
- This extension deals with the highlighting only, so no Intellisence, hovers, etc.
27+
28+
- f-strings are not very useful with CSS and JS. These languages are brace-heavy - too many braces to be escaped.
29+
30+
- To underline the embedded areas as in the sample above, add following to the VSCode settings.json:
31+
```json
32+
"editor.tokenColorCustomizations": {
33+
"textMateRules": [
34+
{
35+
"scope": "meta.embedded.inline.f-expression",
36+
"settings": {
37+
"fontStyle": "underline",
38+
},
39+
},
40+
]
41+
},
42+
```

sample.png

14.6 KB
Loading

sample.py

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
# stubs
2+
3+
4+
def html(s: str):
5+
return s
6+
7+
8+
def _(s: str):
9+
return s
10+
11+
12+
def e(s: str):
13+
return s
14+
15+
16+
class SafeStr(str):
17+
pass
18+
19+
20+
# actual sample
21+
22+
23+
def Dialog(*, post_url: str, title: str, body: SafeStr, cancel_text: str | None = None, ok_text: str | None = None):
24+
cancel_text = cancel_text or _("Cancel")
25+
ok_text = cancel_text or _("Ok")
26+
27+
return html(
28+
f"""
29+
<div class="modal fade" tabindex="-1">
30+
<div class="modal-dialog modal-md modal-dialog-centered">
31+
<form class="form modal-content"
32+
autocomplete="off"
33+
hx-post="{ post_url }"
34+
hx-select=".modal-content"
35+
hx-swap="outerHTML">
36+
<div class="modal-header">
37+
<h5 class="modal-title">{ e(title) }</h5>
38+
</div>
39+
<div class="modal-body">
40+
{ body }
41+
</div>
42+
<div class="modal-footer">
43+
<button type="button"
44+
class="btn btn-outline-secondary"
45+
data-bs-dismiss="modal">{ e(cancel_text) }</button>
46+
<button type="submit" class="btn btn-primary">{ e(ok_text) }</button>
47+
</div>
48+
</form>
49+
</div>
50+
</div>"""
51+
)

0 commit comments

Comments
 (0)