pymdown-extensions icon indicating copy to clipboard operation
pymdown-extensions copied to clipboard

Allow snippets to only show certain user defined lines from the included file

Open mattpitkin opened this issue 2 years ago • 5 comments

Description

When using literalinclude in a rst file you can specify the lines from the included file that are shown, e.g.:

.. literalinclude:: example.py
   :lines: 1,3,5-10,20-

Would it be possible to include something similar for snippets, using, e.g.:

-->8-- "example.py" lines: 1,3,5-10,20-

Benefits

This would allow users to only show required parts of a file, e.g., just show one function from a larger Python file.

Solution Idea

My regular expression knowlegde isn't good enough to know how to add this into RE_ALL_SNIPPETS, but if the line numbers can be read and converted into a list of lines to include (in, say, a variable called includelines), then I assume:

with codecs.open(snippet, 'r', encoding=self.encoding) as f:
    new_lines.extend(
        [space + l2 for l2 in self.parse_snippets([l.rstrip('\r\n') for l in f], snippet)]
    )

could be changed to:

with codecs.open(snippet, 'r', encoding=self.encoding) as f:
    snippetlines = f.readlines()
    new_lines.extend(
        [space + l2 for l2 in self.parse_snippets([snippetlines[i].rstrip('\r\n') for i in includelines], snippet)]
    )

mattpitkin avatar Sep 22 '21 14:09 mattpitkin

Thanks for the feature request. While I can see the usefulness, I haven't really decided yet how much I plan to extend Snippets at this time. See #483. This would probably be related.

I'd have to consider rethinking some of the snippets syntax potentially. The suggested syntax would only work on the inline approach, not the block approach.

Snippets was originally envisioned as a simple, dumb insertion of other text, but that doesn't mean it has to remain that way, but I need to sit down and probably do some thinking about what Snippets would look like moving forward.

@gir-bot remove S: triage @gir-bot add S: needs-decision

facelessuser avatar Sep 25 '21 19:09 facelessuser

I was looking to an answer to this very question.

Previously, I've used docsify, which allows you to select fragments.

I'd love to see this feature here!

adriangb avatar Sep 26 '21 00:09 adriangb

+1 on this feature - would be very useful

RyanGaudion avatar Jul 18 '22 15:07 RyanGaudion

While the exact implementation approach has yet to be decided, I will be looking into this feature. While I still think this approach can be fragile, I think enough people over time have deemed this to be desired enough to warrant implementation.

Just because I approach Snippets usage differently, doesn't mean we can't allow both.

facelessuser avatar Jul 18 '22 15:07 facelessuser

That would be fantastic, mdbook which is used to build the rust book uses this, and works quite well: https://rust-lang.github.io/mdBook/format/mdbook.html#including-portions-of-a-file there was actually a bug once that I was able to fix by changing the line numbers.

The syntax they use is:

{{#include file.rs:2}}
{{#include file.rs::10}}
{{#include file.rs:2:}}
{{#include file.rs:2:10}}

We could do something similar:

--8<-- "file.py:2"
--8<-- "file.py::10"
--8<-- "file.py:2:"
--8<-- "file.py:2:10"

Hope it helps 👍🏻

woile avatar Aug 17 '22 11:08 woile

I'm thinking we'll probably go for some form utilizing colons as suggested above. I hope to get some time to sit down and knock this out soon.

facelessuser avatar Sep 26 '22 21:09 facelessuser

#1822 should resolve this request. Still have a little more testing to do and some documentation to write.

Moving forward:

  • appending :<line start> will return content from the specified line to the end of the file.
  • appending ::<line end> will return content from the start of the file up to (and including) the ending line.
  • appending :<line start>:<line end> will give you the content start at the "start" line up to (and including) the "end" lline.

facelessuser avatar Sep 29 '22 13:09 facelessuser