styles
styles copied to clipboard
Including code snippets in callouts
Not sure if this is the right place to report this, but it doesn't seem to be possible to include code snippets in a callout (or any special blockquote), for example:
> ## Learn to call the **GPU** package from command-line
>
> In this exercise, we'll deal with a Lennard-Jones (LJ) system as described by the
> following input file. You can vary the system size and the length of the run using the
> variables `x`, `y`, `z`, and `t`. For this exercise, let us choose `x = y = z = 60`. Since
> this is a system with `fcc` lattice, the total number of atoms should be 864,000 for
> the chosen values of `x`, `y`, and `z`. Let, `t` = 500.
> We'll call the **GPU** package from the command-line in this case. Can you prepare a
> job submission file for this system such that it enables to use 2 GPUs with 24 MPI ranks.
> Make sure that the neighbor is built on the CPUs and there is a dynamic load balancing
> between the CPUs and the GPUs.
> ```
> {% include /snippets/ep05/in.lj %}
> ```
> {: .code}
>
{: .challenge}
will not render correctly if in.lj
contains multiple lines.
I imagine this is because the snippet is directly inserted including the line breaks. Is there a fix for this?
This comes close to working, but removes the newlines rather than replace them with \n>
...and still wouldn't work in the nested case (like {: .solution}
):
> {% capture mycode %}
{% include /snippets/ep05/in.lj %}
{% endcapture %}{{ mycode | strip_newlines }}
I got it to work but it was pretty tedious:
> {% capture mycode %}
{% include /snippets/ep05/in.lj %}
{% endcapture %}{{ mycode | strip | newline_to_br | replace: '<br />', '<br />> ' | strip_html | strip }}
For a nested blockquote that would be
{% endcapture %}{{ mycode | strip | newline_to_br | replace: '<br />', '<br />> > ' | strip_html | strip }}
If it is somehow possible to create a function for this, a numerical argument would be enough to know how many >
to insert.
What you do here is pretty smart, @ocaisa. I haven't heard of Liquid functions so what you propose might be the best one can do if they want to include code from a file in a callout box. By the way, can't one replace <br />
with >
directly?, e.g.:
{% endcapture %}{{ mycode | strip | newline_to_br | replace: '<br />', '> ' }}
Not as smart as I hoped, I hadn't noticed but it is leaving behind a >
at the end of lines that aren't simply whitespace. I guess it is actually the whitespace lines that are the problem, but this is a bit too hard to figure out, I will have to find another way
Ok, the whitespace was indeed the problem. I got it to work by creating my own liquid plugin:
# Declare module of your plugin under Jekyll module
module Jekyll::CustomFilter
# Each method of the module creates a custom Jekyll filter
def append_to_newline(input, append_string = '')
input.to_s.strip.gsub(/\n/, "\n" + append_string.to_s)
end
end
Liquid::Template.register_filter(Jekyll::CustomFilter)
which is stored in an _plugins
directory relative to the root directory. You can then use this filter with
> ```
> {% capture mycode %}
{% include /snippets/ep05/in.lj %}
{% endcapture %}{{ mycode | append_to_newline: "> " }}
> ```
> {: .code}
I would have liked to simplify this to be able to create { {% include_in_callout /snippets/ep05/in.lj 1 %}}
where 1 indicates the callout depth but I couldn't figure out how to do that (this is my first look at ruby).
If input
is an array of strings, you can do this:
# num -- "depth"
input.map { |line| "> " * num + line}.join("\n")
E.g.
%w[one two three].map{ |line| "> " * 3 + line }.join("\n")
=> "> > > one\n> > > two\n> > > three"
if input
is a string, you'd have to split it first using .split("\n")
:
"one\ntwo\nthree".split("\n").map{ |line| "> " * 3 + line }.join("\n")
=> "> > > one\n> > > two\n> > > three"
I have to note that the code you provided above didn't work for me as expected for some reason. Perhaps it has to do with double empty lines in the python code snippet that I used.
Thanks, that worked for me. For completeness I'll give my final solution. I created _plugins/custom_filters.rb
with the contents
# Declare module of your plugin under Jekyll module
module Jekyll::CustomFilter
# Each method of the module creates a custom Jekyll filter
def multiline_string_in_callout(input, levels_of_indent = 0)
input.split("\n").map{ |line| "> " * levels_of_indent + line }.join("\n")
end
end
Liquid::Template.register_filter(Jekyll::CustomFilter)
Note that for the filter to be picked up, you must restart the server (with make serve
)
I can then use the filter in my lesson with
> ```
{% capture mycode %}
{% include /snippets/ep05/in.lj %}
{% endcapture %}{{ mycode | multiline_string_in_callout: 1 }}
> ```
> {: .code}
Great job! Note, you can capture
code snippets early in the episode, e.g.
{% capture mycode %}
{% include /snippets/ep05/in.lj %}
{% endcapture %}
...
...
> ```
{{ mycode | multiline_string_in_callout: 1 }}
> ```
> {: .code}
@maxim-belkin I leave it to you to decide whether to close this or not, thanks for the help.
Thanks, @ocaisa. I'd like to keep it open for now. It might be beneficial for the community to integrate this into the main template. It'll tie us more to the Shopify Liquid so we'd have to review this carefully.
This is a never-ending story! It turns out that while I could served the site locally, it didn't pick up my plugin when I served on GitHub (or when I tried to use the remote Carpentries theme), so I had to go back and try to do it using standard filters.
I managed to get it working this time but it is very very picky about the syntax:
>
> {% capture mycode %}{% include /snippets/ep05/in.lj %}{% endcapture %}
> {% assign lines_of_code = mycode | newline_to_br | strip_newlines | split: "<br />" %}
> ~~~{% for member in lines_of_code %}
> {{ member }}{% endfor %}
> ~~~
> {: .source}
This is a never-ending story! It turns out that while I could served the site locally, it didn't pick up my plugin when I served on GitHub
Yes, GitHub works in "safe" mode and does not enable plugins. It is possible to workaround this by using GitHub Actions but your solution is nothing short of brilliant, so GitHub Actions can wait!
Great stuff!
and don't forget about using ~~~ instead of ```