%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % pyjupyter.sty %% % Python code environment styled for Jupyter-like listings%% % Author: BARA Ouyèté Bright %% % Date: 15/03/2026 %% %Version: 1.2.0 %% %License: LPPL v1.3c %% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% \NeedsTeXFormat{LaTeX2e} \ProvidesPackage{pyjupyter}[2026/03/15 Python Jupyter-style listings] \PassOptionsToPackage{dvipsnames,svgnames,table}{xcolor} \RequirePackage{xcolor} \RequirePackage{listings} \RequirePackage{listingsutf8} \RequirePackage{etoolbox} \RequirePackage{tcolorbox} \tcbuselibrary{listings,skins,breakable,hooks,xparse} \IfFileExists{sourcecodepro.sty}{ \RequirePackage{sourcecodepro} }{ \PackageWarning{pyjupyter}{Package 'sourcecodepro' not found. Using default monospaced font} } \RequirePackage{kvoptions} \SetupKeyvalOptions{family=pyj,prefix=pyj@} \makeatletter \DeclareStringOption[sourcecodepro]{font} \DeclareStringOption[small]{codesize} \ProcessKeyvalOptions* \IfFileExists{sourcecodepro.sty}{\RequirePackage{sourcecodepro}}{} \IfFileExists{beramono.sty}{\RequirePackage{beramono}}{} \IfFileExists{zi4.sty}{\RequirePackage{zi4}}{}%inconsolata font \newcommand{\pyj@selectedfont}{ \def\pyj@temp{sourcecodepro} \ifx\pyj@font\pyj@temp \fontfamily{SourceCodePro-TLF}\selectfont \else \def\pyj@temp{beramono} \ifx\pyj@font\pyj@temp \fontfamily{fvm}\selectfont \else \def\pyj@temp{inconsolata} \ifx\pyj@font\pyj@temp \fontfamily{zi4}\selectfont \else \def\pyj@temp{lmtt} \ifx\pyj@font\pyj@temp \fontfamily{lmtt}\selectfont \else \def\pyj@temp{courier} \ifx\pyj@font\pyj@temp \fontfamily{pcr}\selectfont \else \def\pyj@temp{txtt} \ifx\pyj@font\pyj@temp \fontfamily{txtt}\selectfont \else \ttfamily \fi\fi\fi\fi\fi\fi } \makeatother \lstset{inputencoding=utf8/latin1, extendedchars=true, upquote=true, } \lstdefinestyle{pyjupyter}{ language=Python, basicstyle=\pyj@selectedfont\csname\pyj@codesize\endcsname, alsoletter={+, -, *, /, =, <, >, !, \&, |, **, \^, ~, <<, >>, +=, -=,*=, /=, //=, \%=, **=, \&=, |=, \^=, <<=, >>=}, emph={+, -, *, /, =, <, >, !, \&, |, **, \^, ~, <<, >>, +=, -=,*=, /=, //=, \%=, **=, \&=, |=, \^=, <<=, >>=,==}, emphstyle=\color{violet}, keywordstyle=\color{DarkGreen}\bfseries, keywords={class,def,return,if,else,for,while,in,raise, import,from,as,try,except,with,and,or,not,is, True,False,None,assert,break,continue,del,elif, finally,from,global,import,lambda, nonlocal,pass,yield}, keywordstyle=[2]\color{DarkGreen}, keywords=[2]{print,super,len,range,enumerate,zip, list,dict,set,int,str,float,bool}, keywordstyle=[3]\color{violet}, keywords=[3]{+, -, *, /, =, <, >, !, \&, |, :, **, \^, ~, <<, >>, +=, -=,*=, /=, //=, \%=, **=, \&=, |=, \^=, <<=, >>=}, commentstyle=\color{teal!80!black}\itshape, stringstyle=\color{red!70!black}, showstringspaces=false, escapeinside={@}{@}, breaklines=true, breakatwhitespace=true, tabsize=2, columns=fullflexible, keepspaces=true, upquote=true, morecomment=[s][\color{red!70!black}\itshape]{'''}{'''}, morecomment=[s][\color{red!70!black}\itshape]{"""}{"""} } \tcbset{ numbered/.style={ left=10mm, listing options={ numbers=left, numberstyle=\ttfamily\color{black!60}, numbersep=8pt, style=pyjupyter, } }, startline/.style={listing options app={firstline=#1, firstnumber=#1}}, endline/.style={listing options app={lastline=#1}}, } \newtcblisting{jupyter}[1][]{ enhanced, breakable, listing only, listing options={style=pyjupyter}, colback=gray!5, colframe=gray!30, arc=2pt, boxrule=1pt, boxsep=0.3mm, left=1mm, right=1mm, top=0.5mm, bottom=0.3mm, before=\addvspace{1em}, after=\addvspace{1em}, #1 } \NewDocumentCommand{\inputpythonfile}{O{} m}{ \tcbinputlisting{ enhanced, breakable, listing only, listing engine=listings, listing file={#2}, listing options={ style=pyjupyter}, colback=gray!5, colframe=gray!30, arc=3pt, boxrule=1pt, boxsep=0.3mm, left=1mm, right=1mm, top=0.3mm, bottom=0.3mm, before=\addvspace{1em}, after=\addvspace{1em}, #1 } } \endinput