Skip to content

Commit

Permalink
add feature
Browse files Browse the repository at this point in the history
  • Loading branch information
Simon Ungar Felding committed Nov 13, 2024
1 parent 20be2fc commit b252d7f
Show file tree
Hide file tree
Showing 3 changed files with 44 additions and 0 deletions.
4 changes: 4 additions & 0 deletions docs/src/markdown/about/changelog.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,9 @@
# Changelog

## 10.13

- **NEW**: Snippets: Snippets can now extract lines that match a regex string.

## 10.12

- **NEW**: Blocks: Blocks extensions no longer considered in beta.
Expand Down
19 changes: 19 additions & 0 deletions docs/src/markdown/extensions/snippets.md
Original file line number Diff line number Diff line change
Expand Up @@ -126,6 +126,25 @@ include.md::3
;--8<--
```

/// new | New 10.13
You can also use regex syntax to match lines, or parts of lines.
///

Regex strings must start and end with a `/`.

Assuming a file like this:
```
# this is the username
username = alice
# this is the group
groups = cool,fun,smart
```

- To extract the line that contains `username =`, use `file.md:/username =/`. This returns `username = alice`.
- To extract parts of a line, use match groups: `file.md:/username = (.*)`. This returns `alice`.
- If you use multiple groups, they are joined together: `file.md:/groups = ([a-z]),([a-z]),([a-z])` returns `cool fun smart`.
- The regex can match multiple lines in a file: `file.md:/=/` returns both lines that contain a `=`, but not the comments in between.

### Snippet Sections

/// new | New 9.7
Expand Down
21 changes: 21 additions & 0 deletions pymdownx/snippets.py
Original file line number Diff line number Diff line change
Expand Up @@ -97,6 +97,23 @@ def __init__(self, config, md):

self.download.cache_clear()

def extract_regex(self, regex, lines):
"""Extract the specified regex from the lines. If the regex contains groups, they will be joined together."""

new_lines = []
regex = re.match(r'^/(.*)/$', regex).group(1) # remove the slashes
for line in lines:
m = re.match(regex, line)
if m and m.groups():
new_lines.append(" ".join(re.match(regex, line).groups())) # join the groups together
elif m:
new_lines.append(line)

if not new_lines and self.check_paths:
raise SnippetMissingError(f"No line matched the regex {regex}")

return self.dedent(new_lines) if self.dedent_subsections else new_lines

def extract_section(self, section, lines):
"""Extract the specified section from the lines."""

Expand Down Expand Up @@ -328,6 +345,8 @@ def parse_snippets(self, lines, file_name=None, is_url=False):
if start is not None or end is not None:
s = slice(start, end)
s_lines = self.dedent(s_lines[s]) if self.dedent_subsections else s_lines[s]
elif re.match(r'^/.*/$', section): # if section is a regex
s_lines = self.extract_regex(section, s_lines)
elif section:
s_lines = self.extract_section(section, s_lines)
else:
Expand All @@ -337,6 +356,8 @@ def parse_snippets(self, lines, file_name=None, is_url=False):
if start is not None or end is not None:
s = slice(start, end)
s_lines = self.dedent(s_lines[s]) if self.dedent_subsections else s_lines[s]
elif re.match(r'^/.*/$', section): # if section is a regex
s_lines = self.extract_regex(section, s_lines)
elif section:
s_lines = self.extract_section(section, s_lines)
except SnippetMissingError:
Expand Down

0 comments on commit b252d7f

Please sign in to comment.