From 65d64581cc2e264b2121594b733bc0d40f9cb9cc Mon Sep 17 00:00:00 2001 From: Tyler Makaro Date: Thu, 18 Apr 2019 19:30:40 -0700 Subject: [PATCH 1/4] add style_jupyter.tplx --- nbconvert/templates/latex/style_jupyter.tplx | 177 +++++++++++++++++++ 1 file changed, 177 insertions(+) create mode 100644 nbconvert/templates/latex/style_jupyter.tplx diff --git a/nbconvert/templates/latex/style_jupyter.tplx b/nbconvert/templates/latex/style_jupyter.tplx new file mode 100644 index 000000000..066b8dac9 --- /dev/null +++ b/nbconvert/templates/latex/style_jupyter.tplx @@ -0,0 +1,177 @@ +((=- IPython input/output style -=)) +((*- extends 'base.tplx' -*)) + +((*- block packages -*)) + \usepackage[breakable]{tcolorbox} + \tcbset{nobeforeafter} % prevents tcolorboxes being placing in paragraphs + \usepackage{float} + \floatplacement{figure}{H} % forces figures to be placed at the correct location + ((( super() ))) +((*- endblock packages -*)) + +((*- block definitions -*)) + ((( super() ))) +% Pygments definitions + (((- resources.latex.pygments_definitions ))) + + % For linebreaks inside Verbatim environment from package fancyvrb. + \makeatletter + \newbox\Wrappedcontinuationbox + \newbox\Wrappedvisiblespacebox + \newcommand*\Wrappedvisiblespace {\textcolor{red}{\textvisiblespace}} + \newcommand*\Wrappedcontinuationsymbol {\textcolor{red}{\llap{\tiny$\m@th\hookrightarrow$}}} + \newcommand*\Wrappedcontinuationindent {3ex } + \newcommand*\Wrappedafterbreak {\kern\Wrappedcontinuationindent\copy\Wrappedcontinuationbox} + % Take advantage of the already applied Pygments mark-up to insert + % potential linebreaks for TeX processing. + % {, <, #, %, $, ' and ": go to next line. + % _, }, ^, &, >, - and ~: stay at end of broken line. + % Use of \textquotesingle for straight quote. + \newcommand*\Wrappedbreaksatspecials {% + \def\PYGZus{\discretionary{\char`\_}{\Wrappedafterbreak}{\char`\_}}% + \def\PYGZob{\discretionary{}{\Wrappedafterbreak\char`\{}{\char`\{}}% + \def\PYGZcb{\discretionary{\char`\}}{\Wrappedafterbreak}{\char`\}}}% + \def\PYGZca{\discretionary{\char`\^}{\Wrappedafterbreak}{\char`\^}}% + \def\PYGZam{\discretionary{\char`\&}{\Wrappedafterbreak}{\char`\&}}% + \def\PYGZlt{\discretionary{}{\Wrappedafterbreak\char`\<}{\char`\<}}% + \def\PYGZgt{\discretionary{\char`\>}{\Wrappedafterbreak}{\char`\>}}% + \def\PYGZsh{\discretionary{}{\Wrappedafterbreak\char`\#}{\char`\#}}% + \def\PYGZpc{\discretionary{}{\Wrappedafterbreak\char`\%}{\char`\%}}% + \def\PYGZdl{\discretionary{}{\Wrappedafterbreak\char`\$}{\char`\$}}% + \def\PYGZhy{\discretionary{\char`\-}{\Wrappedafterbreak}{\char`\-}}% + \def\PYGZsq{\discretionary{}{\Wrappedafterbreak\textquotesingle}{\textquotesingle}}% + \def\PYGZdq{\discretionary{}{\Wrappedafterbreak\char`\"}{\char`\"}}% + \def\PYGZti{\discretionary{\char`\~}{\Wrappedafterbreak}{\char`\~}}% + } + % Some characters . , ; ? ! / are not pygmentized. + % This macro makes them "active" and they will insert potential linebreaks + \newcommand*\Wrappedbreaksatpunct {% + \lccode`\~`\.\lowercase{\def~}{\discretionary{\hbox{\char`\.}}{\Wrappedafterbreak}{\hbox{\char`\.}}}% + \lccode`\~`\,\lowercase{\def~}{\discretionary{\hbox{\char`\,}}{\Wrappedafterbreak}{\hbox{\char`\,}}}% + \lccode`\~`\;\lowercase{\def~}{\discretionary{\hbox{\char`\;}}{\Wrappedafterbreak}{\hbox{\char`\;}}}% + \lccode`\~`\:\lowercase{\def~}{\discretionary{\hbox{\char`\:}}{\Wrappedafterbreak}{\hbox{\char`\:}}}% + \lccode`\~`\?\lowercase{\def~}{\discretionary{\hbox{\char`\?}}{\Wrappedafterbreak}{\hbox{\char`\?}}}% + \lccode`\~`\!\lowercase{\def~}{\discretionary{\hbox{\char`\!}}{\Wrappedafterbreak}{\hbox{\char`\!}}}% + \lccode`\~`\/\lowercase{\def~}{\discretionary{\hbox{\char`\/}}{\Wrappedafterbreak}{\hbox{\char`\/}}}% + \catcode`\.\active + \catcode`\,\active + \catcode`\;\active + \catcode`\:\active + \catcode`\?\active + \catcode`\!\active + \catcode`\/\active + \lccode`\~`\~ + } + \makeatother + + \let\OriginalVerbatim=\Verbatim + \makeatletter + \renewcommand{\Verbatim}[1][1]{% + %\parskip\z@skip + \sbox\Wrappedcontinuationbox {\Wrappedcontinuationsymbol}% + \sbox\Wrappedvisiblespacebox {\FV@SetupFont\Wrappedvisiblespace}% + \def\FancyVerbFormatLine ##1{\hsize\linewidth + \vtop{\raggedright\hyphenpenalty\z@\exhyphenpenalty\z@ + \doublehyphendemerits\z@\finalhyphendemerits\z@ + \strut ##1\strut}% + }% + % If the linebreak is at a space, the latter will be displayed as visible + % space at end of first line, and a continuation symbol starts next line. + % Stretch/shrink are however usually zero for typewriter font. + \def\FV@Space {% + \nobreak\hskip\z@ plus\fontdimen3\font minus\fontdimen4\font + \discretionary{\copy\Wrappedvisiblespacebox}{\Wrappedafterbreak} + {\kern\fontdimen2\font}% + }% + + % Allow breaks at special characters using \PYG... macros. + \Wrappedbreaksatspecials + % Breaks at punctuation characters . , ; ? ! and / need catcode=\active + \OriginalVerbatim[#1,codes*=\Wrappedbreaksatpunct]% + } + \makeatother + + % Exact colors from NB + ((*- block style_colors *)) + \definecolor{incolor}{HTML}{303F9F} + \definecolor{outcolor}{HTML}{D84315} + \definecolor{cellborder}{HTML}{CFCFCF} + \definecolor{cellbackground}{HTML}{F7F7F7} + ((*- endblock style_colors *)) + + % prompt + ((*- block style_prompt *)) + \newcommand{\prompt}[4]{ + \llap{{\color{#2}[#3]: #4}}\vspace{-1.25em} + } + ((* endblock style_prompt *)) + +((*- endblock definitions -*)) + +%=============================================================================== +% Input +%=============================================================================== + +((* block input scoped *)) + ((( draw_cell(cell.source | highlight_code(strip_verbatim=True), cell, 'In', 'incolor', '\\ ') ))) +((* endblock input *)) + + +%=============================================================================== +% Output +%=============================================================================== + +((*- if charlim is not defined -*)) + ((* set charlim = 80 *)) +((*- endif -*)) + +((* block execute_result scoped *)) + ((*- for type in output.data | filter_data_type -*)) + ((*- if type in ['text/plain']*)) + ((( draw_cell(output.data['text/plain'] | wrap_text(charlim) | escape_latex, cell, 'Out', 'outcolor', '\\ ') ))) + ((* else -*)) + ((( " " ))) + ((( draw_prompt(cell, 'Out', 'outcolor','') )))((( super() ))) + ((*- endif -*)) + ((*- endfor -*)) +((* endblock execute_result *)) + +((* block stream *)) + \begin{Verbatim}[commandchars=\\\{\}] +((( output.text | wrap_text(charlim) | escape_latex | ansi2latex -))) + \end{Verbatim} +((* endblock stream *)) + +%============================================================================== +% Support Macros +%============================================================================== + +% Name: draw_cell +% Purpose: Renders an output/input prompt +((*- if draw_cell is not defined -*)) % Required to allow overriding. +((* macro draw_cell(text, cell, prompt, prompt_color, extra_space) -*)) +((*- if prompt == 'In' -*)) +((*- set style = "breakable, size=fbox, boxrule=1pt, pad at break*=1mm,colback=cellbackground, colframe=cellborder"-*)) +((*- else -*))((*- set style = "breakable, boxrule=.5pt, size=fbox, pad at break*=1mm, opacityfill=0"-*))((*- endif -*)) + +\begin{tcolorbox}[((( style )))] +(((- draw_prompt(cell, prompt, prompt_color, extra_space) ))) +\begin{Verbatim}[commandchars=\\\{\}] +((( text ))) +\end{Verbatim} +\end{tcolorbox} +((*- endmacro *)) +((*- endif -*)) + +% Name: draw_prompt +% Purpose: Renders an output/input prompt +((* macro draw_prompt(cell, prompt, prompt_color, extra_space) -*)) + ((*- if cell.execution_count is defined -*)) + ((*- set execution_count = "" ~ (cell.execution_count | replace(None, " ")) -*)) + ((*- else -*))((*- set execution_count = " " -*))((*- endif *)) + + ((*- if (resources.global_content_filter.include_output_prompt and prompt == 'Out') + or (resources.global_content_filter.include_input_prompt and prompt == 'In' ) *)) +\prompt{(((prompt)))}{(((prompt_color)))}{(((execution_count)))}{(((extra_space)))} + ((*- endif -*)) +((*- endmacro *)) From 4b995a2affb1f790a0f5c9d4831c5e35165558cc Mon Sep 17 00:00:00 2001 From: Tyler Makaro Date: Tue, 23 Apr 2019 10:52:35 -0700 Subject: [PATCH 2/4] make default and spacing adjustments --- nbconvert/templates/latex/article.tplx | 2 +- nbconvert/templates/latex/style_jupyter.tplx | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/nbconvert/templates/latex/article.tplx b/nbconvert/templates/latex/article.tplx index cc2a6a189..7c0f3e673 100644 --- a/nbconvert/templates/latex/article.tplx +++ b/nbconvert/templates/latex/article.tplx @@ -1,7 +1,7 @@ % Default to the notebook output style ((* if not cell_style is defined *)) - ((* set cell_style = 'style_ipython.tplx' *)) + ((* set cell_style = 'style_jupyter.tplx' *)) ((* endif *)) % Inherit from the specified cell style. diff --git a/nbconvert/templates/latex/style_jupyter.tplx b/nbconvert/templates/latex/style_jupyter.tplx index 066b8dac9..fcdfeb957 100644 --- a/nbconvert/templates/latex/style_jupyter.tplx +++ b/nbconvert/templates/latex/style_jupyter.tplx @@ -113,7 +113,7 @@ %=============================================================================== ((* block input scoped *)) - ((( draw_cell(cell.source | highlight_code(strip_verbatim=True), cell, 'In', 'incolor', '\\ ') ))) + ((( draw_cell(cell.source | highlight_code(strip_verbatim=True), cell, 'In', 'incolor', '\\hspace{4pt}') ))) ((* endblock input *)) @@ -128,7 +128,7 @@ ((* block execute_result scoped *)) ((*- for type in output.data | filter_data_type -*)) ((*- if type in ['text/plain']*)) - ((( draw_cell(output.data['text/plain'] | wrap_text(charlim) | escape_latex, cell, 'Out', 'outcolor', '\\ ') ))) + ((( draw_cell(output.data['text/plain'] | wrap_text(charlim) | escape_latex, cell, 'Out', 'outcolor', '\\hspace{3.5pt}') ))) ((* else -*)) ((( " " ))) ((( draw_prompt(cell, 'Out', 'outcolor','') )))((( super() ))) From 28a643fbae9a2731fc2d57903b8fd6a78009cfb3 Mon Sep 17 00:00:00 2001 From: Tyler Makaro Date: Tue, 23 Apr 2019 14:08:35 -0700 Subject: [PATCH 3/4] add tests and change latex comment to jinja comment --- nbconvert/exporters/tests/test_latex.py | 34 ++++++++++++++++++++++++- nbconvert/templates/latex/article.tplx | 4 +-- 2 files changed, 35 insertions(+), 3 deletions(-) diff --git a/nbconvert/exporters/tests/test_latex.py b/nbconvert/exporters/tests/test_latex.py index 6f3b9a9b2..019d07795 100644 --- a/nbconvert/exporters/tests/test_latex.py +++ b/nbconvert/exporters/tests/test_latex.py @@ -114,6 +114,38 @@ def test_prompt_number_color(self): """ (output, resources) = LatexExporter().from_filename( self._get_notebook(nb_name="prompt_numbers.ipynb")) + + in_regex = r"\\prompt\{In\}\{incolor\}\{(\d+|\s*)\}" + out_regex = r"\\prompt\{Out\}\{outcolor\}\{(\d+|\s*)\}" + + ins = ["2", "10", " ", " ", "0"] + outs = ["10"] + + assert re.findall(in_regex, output) == ins + assert re.findall(out_regex, output) == outs + + @onlyif_cmds_exist('pandoc') + def test_prompt_number_color_ipython(self): + """ + Does LatexExporter properly format input and output prompts in color? + + Uses an in memory latex template to load style_ipython as the cell style. + """ + my_loader_tplx = DictLoader({'my_template': + """ + ((* extends 'style_ipython.tplx' *)) + + ((* block docclass *)) + \documentclass[11pt]{article} + ((* endblock docclass *)) + """}) + + class MyExporter(LatexExporter): + template_file = 'my_template' + + (output, resources) = MyExporter(extra_loaders=[my_loader_tplx]).from_filename( + self._get_notebook(nb_name="prompt_numbers.ipynb")) + in_regex = r"In \[\{\\color\{incolor\}(.*)\}\]:" out_regex = r"Out\[\{\\color\{outcolor\}(.*)\}\]:" @@ -122,7 +154,7 @@ def test_prompt_number_color(self): assert re.findall(in_regex, output) == ins assert re.findall(out_regex, output) == outs - + @onlyif_cmds_exist('pandoc') def test_no_prompt_yes_input(self): no_prompt = { diff --git a/nbconvert/templates/latex/article.tplx b/nbconvert/templates/latex/article.tplx index 7c0f3e673..8588c850c 100644 --- a/nbconvert/templates/latex/article.tplx +++ b/nbconvert/templates/latex/article.tplx @@ -1,10 +1,10 @@ -% Default to the notebook output style +((=- Default to the notebook output style -=)) ((* if not cell_style is defined *)) ((* set cell_style = 'style_jupyter.tplx' *)) ((* endif *)) -% Inherit from the specified cell style. +((=- Inherit from the specified cell style. -=)) ((* extends cell_style *)) From b99b758b34f342d6eb098d4a2b710c6e38f56fc4 Mon Sep 17 00:00:00 2001 From: Tyler Makaro Date: Wed, 24 Apr 2019 10:14:02 -0700 Subject: [PATCH 4/4] use newer build environment --- .travis.yml | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/.travis.yml b/.travis.yml index 98462c459..f0f1c99d0 100644 --- a/.travis.yml +++ b/.travis.yml @@ -2,7 +2,7 @@ # https://docs.travis-ci.com/user/trusty-ci-environment/ # needs these two lines: sudo: required -dist: trusty +dist: xenial # required for Python >=3.7 (travis-ci/travis-ci#9069), and defaults to newer texlive install. language: python matrix: @@ -11,7 +11,6 @@ matrix: - python: 3.5 - python: 3.6 - python: 3.7 - dist: xenial # required for Python 3.7 (travis-ci/travis-ci#9069) - python: nightly allow_failures: - python: nightly