%% hgblistings.sty
%% This file is part of the Hagenberg Thesis package for creating bachelors's and masters's theses
%% Author: Wilhelm Burger (wilbur@ieee.org)
%% GitHub: https://github.com/Digital-Media/HagenbergThesis
%% File encoding: UTF-8

\ProvidesPackage{hgblistings}[2026/10/22]%%AUTO

\RequirePackage{xifthen}
\RequirePackage{textcomp}	%% required for upquote option
\RequirePackage{xcolor}

%% Package options -------------------------------------------------------------

% codestyle=color|mono|classic: style of the code listings (default: color). Usually given as class option
% of hgbthesis, hgbreport or hgbarticle, which pass it on to this package.
\newcommand{\hgb@CodeStyle}{color}
\DeclareKeys[hgblistings]{
	codestyle.code = {%
		\ifthenelse{\equal{#1}{color} \OR \equal{#1}{mono} \OR \equal{#1}{classic}}%
			{\renewcommand{\hgb@CodeStyle}{#1}}%
			{\PackageError{hgblistings}{Unknown value '#1' for option 'codestyle'}%
				{Allowed values are color (default), mono and classic.}}},
}
\ProcessKeyOptions[hgblistings]

%% Colors ----------------------------------------------------------------------

% Syntax colors close to the "Light+" theme of Visual Studio Code (keywords in the color of the algorithms
% in hgbalgo.sty), each with a contrast ratio of at least 4.5:1 against white (WCAG AA). Comments are also set
% in italics, so they do not depend on color alone. Defined in RGB (PDF/A); they can be redefined with
% \definecolor in the preamble of a document.
\definecolor{ListingsKeywordColor}{rgb}{0.00,0.00,0.666}	% keywords (dark blue, same as AlgKeywordColor)
\definecolor{ListingsTypeColor}{HTML}{267F99}				% built-in types and functions (teal)
\definecolor{ListingsStringColor}{HTML}{A31515}				% strings (dark red)
\definecolor{ListingsCommentColor}{HTML}{008000}			% comments (green)
\definecolor{ListingsLineNumberColor}{gray}{0.45}			% line numbers (styles 'color' and 'mono')
\definecolor{ListingsRuleColor}{gray}{0.75}					% rule left of the code (styles 'color' and 'mono')
\definecolor{ListingsBackgroundColor}{gray}{0.95}			% background (style 'classic')

%% Basic settings (all styles) -------------------------------------------------

\RequirePackage{listingsutf8}
\lst@RequireAspects{directives,tex}	% keys 'directivestyle' and 'texcsstyle' are used in the styles below
\lstset{
	inputencoding=utf8,
	extendedchars=true,
	basicstyle=\ttfamily\footnotesize,
	showstringspaces=false,
	columns=flexible,
	breaklines=true,
	tabsize=2,
	numbers=left,
	numbersep=5pt,
	stepnumber=1,
	numberfirstline=true,
	numberblanklines=true,
	texcl=false,		% program comments are not read as LaTeX content
	mathescape=false,	% no math escape by default
	upquote=true,
	keepspaces=true,
}

%% Styles ----------------------------------------------------------------------

% 'classic': previous look (gray box, no syntax highlighting)
\lstdefinestyle{hgbclassic}{
	backgroundcolor=\color{ListingsBackgroundColor},
	frame=none,
	framerule=0.4pt,		% defaults of listings, reset when switching from another style
	framesep=3pt,
	xleftmargin=6mm,
	framexleftmargin=6mm,
	numbersep=5pt,
	numberstyle=\normalfont\scriptsize,
	keywordstyle={},
	keywordstyle={[2]},
	identifierstyle={},
	commentstyle=\normalfont\itshape,
	stringstyle=\ttfamily,
	directivestyle={},
	texcsstyle={},
}

% 'mono': white background with a thin rule left of the code (between line numbers and code), no colors
\lstdefinestyle{hgbmono}{
	backgroundcolor={},
	frame=l,
	framerule=0.8pt,
	rulecolor=\color{ListingsRuleColor},
	xleftmargin=8mm,		% code
	framesep=2mm,			% rule 2mm left of the code
	framexleftmargin=0mm,
	numbersep=4mm,			% line numbers 2mm left of the rule
	numberstyle=\normalfont\scriptsize\color{ListingsLineNumberColor},
	keywordstyle={},
	keywordstyle={[2]},
	identifierstyle={},
	commentstyle=\ttfamily\itshape,
	stringstyle=\ttfamily,
	directivestyle={},
	texcsstyle={},
}

% 'color': like 'mono', with syntax colors
\lstdefinestyle{hgbcolor}{
	style=hgbmono,
	keywordstyle=\color{ListingsKeywordColor},
	keywordstyle={[2]\color{ListingsTypeColor}},
	commentstyle=\color{ListingsCommentColor}\ttfamily\itshape,
	stringstyle=\color{ListingsStringColor}\ttfamily,
	directivestyle=\color{ListingsKeywordColor},
	texcsstyle=*\color{ListingsKeywordColor},
}

% Apply the selected style (can be changed per listing, e.g., \begin{JavaCode}[style=hgbmono]):
\edef\@tempa{\noexpand\lstset{style=hgb\hgb@CodeStyle}}\@tempa

\RequirePackage[utf8]{inputenc}
\lstset{literate=% to allow Umlauts etc. in listed code % utf8-change
{Ö}{{\"O}}1
{Ä}{{\"A}}1
{Ü}{{\"U}}1
{ü}{{\"u}}1
{ä}{{\"a}}1
{ö}{{\"o}}1
{ß}{{\ss}}2
}

%% Language definitions --------------------------------------------------------
%% Keywords of current language versions. Languages that are also defined by listings are extended or replaced
%% by the dialect [hgb]; where possible, it is set as default dialect, so that e.g. language=Java (also in
%% \lstinputlisting) selects [hgb]Java. Keyword classes: 1 = keywords (ListingsKeywordColor),
%% 2 = built-in types, functions and annotations (ListingsTypeColor).

% Bash, stand-alone definition (the definition of listings mixes keywords and common commands such as cat, ps
% and sed); reserved words are keywords, builtins are keywords of class 2; $# and ${#...} start no comments
\lstdefinelanguage[hgb]{bash}{
	morekeywords={break,case,continue,coproc,do,done,elif,else,esac,exit,fi,for,function,if,in,return,select,
		then,time,until,while},
	morekeywords=[2]{alias,bg,bind,builtin,caller,cd,command,compgen,complete,declare,dirs,disown,echo,
		enable,eval,exec,export,false,fc,fg,getopts,hash,help,history,jobs,kill,let,local,logout,mapfile,popd,
		printf,pushd,pwd,read,readarray,readonly,set,shift,shopt,source,test,times,trap,true,type,typeset,
		ulimit,umask,unalias,unset,wait},
	otherkeywords={$\#},
	sensitive,
	morecomment=[l]\#,
	moredelim=[s][]{$\{}{\}},
	morestring=[b]",
	morestring=[d]',
}[keywords,comments,strings]

% C (C23), based on ANSI C
\lstdefinelanguage[hgb]{C}[ANSI]{C}{
	morekeywords={inline,restrict,_Alignas,_Alignof,_Atomic,_BitInt,_Bool,_Complex,_Decimal32,_Decimal64,
		_Decimal128,_Generic,_Imaginary,_Noreturn,_Static_assert,_Thread_local,alignas,alignof,bool,constexpr,
		false,nullptr,static_assert,thread_local,true,typeof,typeof_unqual},
	morekeywords=[2]{FILE,NULL,int8_t,int16_t,int32_t,int64_t,intptr_t,ptrdiff_t,size_t,uint8_t,uint16_t,
		uint32_t,uint64_t,uintptr_t},
}

% C++ (C++23), based on C++11
\lstdefinelanguage[hgb]{C++}[11]{C++}{
	morekeywords={char8_t,co_await,co_return,co_yield,concept,consteval,constinit,final,import,module,
		override,requires},
	morekeywords=[2]{array,cerr,cin,cout,endl,make_shared,make_unique,map,optional,pair,set,shared_ptr,
		size_t,std,string,string_view,tuple,unique_ptr,unordered_map,unordered_set,variant,vector,weak_ptr},
}

% C# (C# 13), based on the C# dialect of listings (a separate language, since C# is a dialect of C there)
\lstdefinelanguage{CSharp}[Sharp]{C}{
	morekeywords={add,and,ascending,async,await,by,descending,dynamic,equals,fixed,from,get,global,group,
		init,into,join,let,managed,nameof,nint,not,notnull,nuint,on,or,orderby,partial,record,remove,required,
		scoped,select,set,stackalloc,unmanaged,unsafe,var,volatile,when,where,with,yield},
	morekeywords=[2]{Action,Console,DateTime,Dictionary,Exception,Func,Guid,HashSet,IEnumerable,IList,
		List,Math,Span,Task,ValueTask},
	morestring=[s]{@"}{"},
	morestring=[b]',
	moredelim=*[directive]\#,
	moredirectives={define,elif,else,endif,endregion,error,if,line,nullable,pragma,region,undef,warning},
}[keywords,comments,strings,directives]

% CSS (current properties incl. flexbox, grid and logical properties); at-rules are keywords of class 2
\lstdefinelanguage{CSS}{
	morekeywords={accent-color,align-content,align-items,align-self,all,animation,animation-delay,
		animation-direction,animation-duration,animation-fill-mode,animation-iteration-count,animation-name,
		animation-play-state,animation-timing-function,aspect-ratio,backdrop-filter,backface-visibility,
		background,background-attachment,background-blend-mode,background-clip,background-color,
		background-image,background-origin,background-position,background-repeat,background-size,block-size,
		border,border-block,border-bottom,border-bottom-color,border-bottom-left-radius,
		border-bottom-right-radius,border-bottom-style,border-bottom-width,border-collapse,border-color,
		border-image,border-inline,border-left,border-left-color,border-left-style,border-left-width,
		border-radius,border-right,border-right-color,border-right-style,border-right-width,border-spacing,
		border-style,border-top,border-top-color,border-top-left-radius,border-top-right-radius,
		border-top-style,border-top-width,border-width,bottom,box-shadow,box-sizing,break-after,break-before,
		break-inside,caption-side,caret-color,clear,clip-path,color,column-count,column-gap,column-rule,
		column-width,columns,container,container-name,container-type,content,counter-increment,counter-reset,
		cursor,direction,display,empty-cells,filter,flex,flex-basis,flex-direction,flex-flow,flex-grow,
		flex-shrink,flex-wrap,float,font,font-family,font-feature-settings,font-size,font-style,font-variant,
		font-weight,gap,grid,grid-area,grid-auto-columns,grid-auto-flow,grid-auto-rows,grid-column,
		grid-column-end,grid-column-start,grid-row,grid-row-end,grid-row-start,grid-template,
		grid-template-areas,grid-template-columns,grid-template-rows,height,hyphens,inline-size,inset,
		isolation,justify-content,justify-items,justify-self,left,letter-spacing,line-height,list-style,
		list-style-image,list-style-position,list-style-type,margin,margin-block,margin-bottom,margin-inline,
		margin-left,margin-right,margin-top,mask,max-block-size,max-height,max-inline-size,max-width,
		min-block-size,min-height,min-inline-size,min-width,mix-blend-mode,object-fit,object-position,
		opacity,order,orphans,outline,outline-color,outline-offset,outline-style,outline-width,overflow,
		overflow-wrap,overflow-x,overflow-y,padding,padding-block,padding-bottom,padding-inline,padding-left,
		padding-right,padding-top,perspective,place-content,place-items,place-self,pointer-events,position,
		quotes,resize,right,rotate,row-gap,scale,scroll-behavior,scroll-margin,scroll-padding,
		scroll-snap-align,scroll-snap-type,tab-size,table-layout,text-align,text-decoration,
		text-decoration-color,text-decoration-line,text-decoration-style,text-indent,text-overflow,
		text-shadow,text-transform,text-underline-offset,top,touch-action,transform,transform-origin,
		transition,transition-delay,transition-duration,transition-property,transition-timing-function,
		translate,user-select,vertical-align,visibility,white-space,widows,width,will-change,word-break,
		word-spacing,writing-mode,z-index},
	morekeywords=[2]{@charset,@container,@counter-style,@font-face,@import,@keyframes,@layer,@media,
		@namespace,@page,@property,@supports,!important},
	alsoletter={-,!},
	sensitive=false,
	morecomment=[s]{/*}{*/},
	morestring=[b]",
	morestring=[b]',
}

% Dart 3 (incl. common Flutter types)
\lstdefinelanguage{Dart}{
	morekeywords={abstract,as,assert,async,await,base,break,case,catch,class,const,continue,covariant,default,
		deferred,do,dynamic,else,enum,export,extends,extension,external,factory,false,final,finally,for,if,
		implements,import,in,interface,is,late,library,mixin,new,null,on,operator,part,required,rethrow,return,
		sealed,static,super,switch,sync,this,throw,true,try,typedef,var,void,when,while,with,yield},
	morekeywords=[2]{bool,BuildContext,double,Duration,Function,Future,int,Iterable,List,Map,Never,Null,num,
		Object,Record,Set,State,StatefulWidget,StatelessWidget,Stream,String,Widget,@immutable,@override,
		@protected},
	sensitive,
	morecomment=[l]//,
	morecomment=[n]{/*}{*/},
	morestring=[s]{"""}{"""},
	morestring=[s]{'''}{'''},
	morestring=[b]",
	morestring=[b]',
}[keywords,comments,strings]

% GLSL 4.60 (OpenGL Shading Language); vector, matrix and sampler types and built-in variables are keywords
% of class 2
\lstdefinelanguage{GLSL}{
	morekeywords={attribute,bool,break,buffer,case,centroid,coherent,const,continue,default,discard,do,double,
		else,false,flat,float,for,highp,if,in,inout,int,invariant,layout,lowp,mediump,noperspective,out,patch,
		precise,precision,readonly,restrict,return,sample,shared,smooth,struct,subroutine,switch,true,uint,
		uniform,varying,void,volatile,while,writeonly},
	morekeywords=[2]{bvec2,bvec3,bvec4,dmat2,dmat3,dmat4,dvec2,dvec3,dvec4,image2D,image3D,imageCube,
		isampler2D,isampler3D,ivec2,ivec3,ivec4,mat2,mat2x3,mat2x4,mat3,mat3x2,mat3x4,mat4,mat4x2,mat4x3,
		sampler1D,sampler2D,sampler2DArray,sampler2DShadow,sampler3D,samplerCube,samplerCubeShadow,usampler2D,
		uvec2,uvec3,uvec4,vec2,vec3,vec4,
		gl_FragColor,gl_FragCoord,gl_FragDepth,gl_FrontFacing,gl_GlobalInvocationID,gl_InstanceID,
		gl_LocalInvocationID,gl_LocalInvocationIndex,gl_NumWorkGroups,gl_PointCoord,gl_PointSize,gl_Position,
		gl_PrimitiveID,gl_VertexID,gl_WorkGroupID,gl_WorkGroupSize},
	sensitive,
	morecomment=[l]//,
	morecomment=[s]{/*}{*/},
	moredelim=*[directive]\#,
	moredirectives={define,elif,else,endif,error,extension,if,ifdef,ifndef,include,line,pragma,undef,version},
}[keywords,comments,directives]

% Go, stand-alone definition (the definition of listings treats predeclared types and functions as keywords)
\lstdefinelanguage[hgb]{Go}{
	morekeywords={break,case,chan,const,continue,default,defer,else,fallthrough,false,for,func,go,goto,if,
		import,interface,iota,map,nil,package,range,return,select,struct,switch,true,type,var},
	morekeywords=[2]{any,append,bool,byte,cap,clear,close,comparable,complex,complex64,complex128,copy,
		delete,error,float32,float64,imag,int,int8,int16,int32,int64,len,make,max,min,new,panic,print,println,
		real,recover,rune,string,uint,uint8,uint16,uint32,uint64,uintptr},
	sensitive,
	morecomment=[l]//,
	morecomment=[s]{/*}{*/},
	morestring=[b]",
	morestring=[b]',
	morestring=[s]{`}{`},
}[keywords,comments,strings]

% HTML5, based on the HTML definition of listings (element and attribute names are keywords, as are the names
% of other elements, e.g., custom elements)
\lstdefinelanguage[hgb]{HTML}[]{HTML}{
	morekeywords={article,aside,audio,bdi,canvas,data,datalist,details,dialog,embed,figcaption,figure,
		footer,header,hgroup,main,mark,menu,meter,nav,output,picture,progress,rp,rt,ruby,search,section,slot,
		source,summary,svg,template,time,track,video,wbr,
		async,autocomplete,autofocus,autoplay,charset,controls,crossorigin,decoding,defer,download,draggable,
		enctype,formaction,hidden,integrity,loading,loop,max,min,muted,pattern,placeholder,poster,preload,
		referrerpolicy,required,role,sizes,spellcheck,srcset,step,tabindex,translate},
	alsoletter={-},
	markfirstintag=true,
}

% Java (Java 21+), stand-alone definition
\lstdefinelanguage[hgb]{Java}{
	morekeywords={abstract,assert,boolean,break,byte,case,catch,char,class,const,continue,default,do,double,
		else,enum,extends,false,final,finally,float,for,goto,if,implements,import,instanceof,int,interface,
		long,native,new,null,package,permits,private,protected,public,record,return,sealed,short,static,
		strictfp,super,switch,synchronized,this,throw,throws,transient,true,try,var,void,volatile,while,yield},
	morekeywords=[2]{ArrayList,Boolean,Byte,Character,Double,Exception,Float,HashMap,HashSet,Integer,
		Iterable,List,Long,Map,Math,Object,Optional,RuntimeException,Set,Short,Stream,String,StringBuilder,
		System,Thread,Void,@Deprecated,@FunctionalInterface,@Override,@SafeVarargs,@SuppressWarnings},
	sensitive,
	morecomment=[l]//,
	morecomment=[s]{/*}{*/},
	morestring=[s]{"""}{"""},
	morestring=[b]",
	morestring=[b]',
}[keywords,comments,strings]

% JavaScript (ECMAScript 2025)
\lstdefinelanguage{JavaScript}{
	morekeywords={as,async,await,break,case,catch,class,const,continue,debugger,default,delete,do,else,
		export,extends,false,finally,for,from,function,if,import,in,instanceof,let,new,null,of,return,static,
		super,switch,this,throw,true,try,typeof,undefined,var,void,while,with,yield,Infinity,NaN},
	morekeywords=[2]{Array,ArrayBuffer,BigInt,Boolean,DataView,Date,Error,Function,Intl,JSON,Map,Math,
		Number,Object,Promise,Proxy,Reflect,RegExp,Set,String,Symbol,TypeError,WeakMap,WeakRef,WeakSet,
		console,document,globalThis,window},
	sensitive,
	morecomment=[l]//,
	morecomment=[s]{/*}{*/},
	morestring=[b]",
	morestring=[b]',
	morestring=[b]`,
}

% JSON (also with comments, e.g., tsconfig.json)
\lstdefinelanguage{JSON}{
	morekeywords={false,null,true},
	sensitive,
	morecomment=[l]//,
	morecomment=[s]{/*}{*/},
	morestring=[b]",
}

% Kotlin 2; soft keywords that are common identifiers (e.g., data, value, get, set) are not keywords
\lstdefinelanguage{Kotlin}{
	morekeywords={abstract,annotation,as,break,by,catch,class,companion,const,constructor,continue,crossinline,
		do,else,enum,external,false,final,finally,for,fun,if,import,in,infix,init,inline,inner,interface,
		internal,is,lateinit,noinline,null,object,open,operator,out,override,package,private,protected,public,
		reified,return,sealed,super,suspend,tailrec,this,throw,true,try,typealias,val,var,vararg,when,where,
		while},
	morekeywords=[2]{Any,Array,Boolean,Byte,Char,Double,Float,Int,List,Long,Map,MutableList,MutableMap,
		MutableSet,Nothing,Pair,Result,Sequence,Set,Short,String,UInt,ULong,Unit,emptyList,listOf,mapOf,
		mutableListOf,mutableMapOf,print,println,setOf,@Composable,@Deprecated,@JvmField,@JvmOverloads,
		@JvmStatic,@Serializable,@Suppress,@Throws,@Volatile},
	sensitive,
	morecomment=[l]//,
	morecomment=[n]{/*}{*/},
	morestring=[s]{"""}{"""},
	morestring=[b]",
	morestring=[b]',
}[keywords,comments,strings]

% LaTeX, based on the LaTeX definition of listings, with commands of common packages and of this package
\lstdefinelanguage[hgb]{TeX}[LaTeX]{TeX}{
	moretexcs={addbibresource,advisor,autoref,boldsymbol,bottomrule,captionof,chapter,cite,citetitle,cmidrule,
		dateofsubmission,DeclareMathOperator,documentclass,eqref,fullcite,graphicspath,href,hypersetup,
		includegraphics,includepdf,label,license,lstinputlisting,lstset,MakeBibliography,mathbb,mathbf,
		mathcal,mathit,mathrm,mathsf,mathtt,midrule,multicolumn,multirow,newcommand,nolinkurl,paragraph,
		parencite,placeofstudy,printbibliography,programname,ref,RequirePackage,section,subsection,
		subsubsection,subtitle,text,textbf,textcite,textit,textsc,textsf,texttt,textwidth,toprule,url,
		usepackage,verb},
}

% MATLAB, stand-alone definition (the definition of listings treats about 900 function names as keywords)
\lstdefinelanguage[hgb]{Matlab}{
	morekeywords={arguments,break,case,catch,classdef,continue,else,elseif,end,enumeration,eps,events,false,
		for,function,global,if,Inf,inf,methods,NaN,nan,otherwise,parfor,persistent,pi,properties,return,spmd,
		switch,true,try,while},
	morekeywords=[2]{abs,cell,disp,double,error,figure,fprintf,hold,isempty,length,linspace,max,mean,min,
		numel,ones,plot,rand,size,sprintf,sqrt,struct,sum,title,xlabel,ylabel,zeros},
	sensitive,
	morecomment=[l]\%,
	morecomment=[s]{\%\{}{\%\}},	% after [l]\%, since the last defined delimiter takes precedence
	morestring=[m]',
	morestring=[m]",
}[keywords,comments,strings]

% Objective-C (current), based on the Objective-C dialect of listings (as a separate language)
\lstdefinelanguage{ObjectiveC}[Objective]{C}{
	morekeywords={@autoreleasepool,@catch,@dynamic,@finally,@import,@optional,@property,@required,
		@synthesize,@throw,@try,BOOL,Class,IMP,NO,SEL,YES,atomic,copy,instancetype,nil,nonatomic,nonnull,
		nullable,readonly,readwrite,retain,strong,unsafe_unretained,weak,__block,__strong,__weak},
	morekeywords=[2]{CGFloat,NSArray,NSDictionary,NSError,NSInteger,NSMutableArray,NSMutableDictionary,
		NSNumber,NSObject,NSString,NSUInteger},
	morestring=[s]{@"}{"},
}

% PHP 8.4, stand-alone definition (the definition of listings contains the function names of PHP 4/5);
% attributes (#[...]) are not treated as comments
\lstdefinelanguage[hgb]{PHP}{
	morekeywords={__halt_compiler,abstract,and,array,as,break,callable,case,catch,class,clone,const,
		continue,declare,default,die,do,echo,else,elseif,empty,enddeclare,endfor,endforeach,endif,endswitch,
		endwhile,enum,eval,exit,extends,false,final,finally,fn,for,foreach,function,global,goto,if,
		implements,include,include_once,instanceof,insteadof,interface,isset,list,match,namespace,new,null,
		or,parent,print,private,protected,public,readonly,require,require_once,return,self,static,switch,
		throw,trait,true,try,unset,use,var,while,xor,yield,FALSE,NULL,TRUE,__CLASS__,__DIR__,__FILE__,
		__FUNCTION__,__LINE__,__METHOD__,__NAMESPACE__,__PROPERTY__,__TRAIT__,$this},
	morekeywords=[2]{bool,float,int,iterable,mixed,never,object,string,void},
	otherkeywords={<?php,<?=,?>},
	sensitive,
	morecomment=[l]//,
	morecomment=[s]{/*}{*/},
	morecomment=[l]\#,
	moredelim=[s][]{\#[}{]},
	morestring=[b]",
	morestring=[b]',
}[keywords,comments,strings]

% Python 3, based on the Python 3 dialect of listings (print is a built-in function, not a keyword)
\lstdefinelanguage[hgb]{Python}[3]{Python}{
	morekeywords=[2]{print},
}

% R, stand-alone definition (the definition of listings treats about 800 function names as keywords)
\lstdefinelanguage[hgb]{R}{
	morekeywords={break,else,FALSE,for,function,if,in,Inf,NA,NA_character_,NA_complex_,NA_integer_,NA_real_,
		NaN,next,NULL,repeat,return,TRUE,while},
	morekeywords=[2]{apply,data.frame,factor,is.na,lapply,length,library,list,matrix,mean,paste,paste0,
		print,require,sapply,seq,stop,sum,vapply,vector,warning},
	sensitive,
	alsoletter={.},
	alsoother={$},
	morecomment=[l]\#,
	morestring=[b]",
	morestring=[b]',
}[keywords,comments,strings]

% Rust (edition 2024); no character literals, since ' also starts lifetimes
\lstdefinelanguage{Rust}{
	morekeywords={as,async,await,break,const,continue,crate,dyn,else,enum,extern,false,fn,for,if,impl,in,let,
		loop,macro_rules,match,mod,move,mut,pub,ref,return,self,Self,static,struct,super,trait,true,type,
		unsafe,use,where,while},
	morekeywords=[2]{Arc,Box,BTreeMap,Cell,Err,HashMap,HashSet,None,Ok,Option,Rc,RefCell,Result,Some,String,
		Vec,bool,char,f32,f64,i8,i16,i32,i64,i128,isize,str,u8,u16,u32,u64,u128,usize},
	sensitive,
	morecomment=[l]//,
	morecomment=[n]{/*}{*/},
	morestring=[b]",
}[keywords,comments,strings]

% Scala 3, based on the Scala 3 dialect of listings
\lstdefinelanguage[hgb]{Scala}[3.0]{Scala}{
	morekeywords={then,using},
}

% SQL, based on the SQL definition of listings (SQL-92), with keywords and types of current database systems
\lstdefinelanguage[hgb]{SQL}[]{SQL}{
	morekeywords={AUTO_INCREMENT,CALL,CONFLICT,DATABASE,DECLARE,DO,EXPLAIN,FETCH,FILTER,FOR,FUNCTION,IF,
		ILIKE,IS,LATERAL,MATCHED,MERGE,NOTHING,OF,OFFSET,OVER,PARTITION,PROCEDURE,REFERENCES,REPLACE,RETURNING,
		RETURNS,SCHEMA,SEQUENCE,TO,TRUNCATE,WINDOW,WITH},
	morekeywords=[2]{BIGINT,BIGSERIAL,BOOL,BOOLEAN,BYTEA,DATETIME,DOUBLE,JSON,JSONB,PRECISION,REAL,SERIAL,
		TEXT,TINYINT,UUID},
}

% Swift 6, stand-alone definition
\lstdefinelanguage[hgb]{Swift}{
	morekeywords={actor,any,Any,as,associatedtype,async,await,borrowing,break,case,catch,class,consuming,
		continue,convenience,default,defer,deinit,didSet,do,dynamic,else,enum,extension,fallthrough,false,
		fileprivate,final,for,func,get,guard,if,import,in,indirect,init,inout,internal,is,lazy,let,macro,
		mutating,nil,nonisolated,nonmutating,open,operator,optional,override,package,precedencegroup,private,
		protocol,public,repeat,required,rethrows,return,self,Self,set,some,static,struct,subscript,super,
		switch,throw,throws,true,try,typealias,unowned,var,weak,where,while,willSet},
	morekeywords=[2]{Array,Bool,Character,Dictionary,Double,Float,Int,Int8,Int16,Int32,Int64,Never,
		Optional,Result,Set,String,UInt,UInt8,UInt16,UInt32,UInt64,Void,@available,@Binding,
		@discardableResult,@Environment,@escaping,@main,@MainActor,@objc,@Observable,@Published,@Sendable,
		@State},
	sensitive,
	morecomment=[l]//,
	morecomment=[n]{/*}{*/},
	morestring=[s]{"""}{"""},
	morestring=[b]",
	moredelim=*[directive]\#,
	moredirectives={available,colorLiteral,else,elseif,endif,fileLiteral,if,imageLiteral,keyPath,selector,
		sourceLocation,unavailable},
}[keywords,comments,strings,directives]

% TypeScript 5, based on JavaScript
\lstdefinelanguage{TypeScript}[]{JavaScript}{
	morekeywords={abstract,accessor,asserts,declare,enum,implements,infer,interface,is,keyof,namespace,
		override,private,protected,public,readonly,satisfies,type,unique},
	morekeywords=[2]{any,bigint,boolean,never,number,object,string,symbol,unknown,Awaited,Exclude,Extract,
		NonNullable,Omit,Partial,Pick,Readonly,Record,Required,ReturnType},
}

% XML, based on the XML definition of listings; all element names are keywords (instead of only those that
% are also keywords of XML, e.g., version)
\lstdefinelanguage[hgb]{XML}[]{XML}{
	markfirstintag=true,
}

% YAML 1.2; only double-quoted strings, since listings continues unterminated strings on the next line and
% apostrophes are common in unquoted values (e.g., name: Don't fail)
\lstdefinelanguage{YAML}{
	morekeywords={false,null,true},
	sensitive=false,
	morecomment=[l]\#,
	morestring=[b]",
}

\lstset{
	defaultdialect=[hgb]bash,
	defaultdialect=[hgb]C,
	defaultdialect=[hgb]C++,
	defaultdialect=[hgb]Go,
	defaultdialect=[hgb]Java,
	defaultdialect=[hgb]Matlab,
	defaultdialect=[hgb]PHP,
	defaultdialect=[hgb]Python,
	defaultdialect=[hgb]R,
	defaultdialect=[hgb]Swift,
}
% Not possible for dialects based on a language without dialect (HTML, Scala, SQL, XML), since the empty base
% dialect would then refer to the default dialect itself; these are selected explicitly in the environments.

%% Code environments -----------------------------------------------------------

% \hgb@NewCodeEnvironment{<environment>}{<language>}: code environment for the given language, with
% LaTeX escapes between /+ and +/ (e.g., for labels of lines), options as optional argument
\newcommand{\hgb@NewCodeEnvironment}[2]{%
	\lstnewenvironment{#1}[1][]{\lstset{language={#2},escapeinside={/+}{+/},##1}}{}%
}

\hgb@NewCodeEnvironment{BashCode}{bash}			% Bash
\hgb@NewCodeEnvironment{CCode}{C}				% C (C23)
\hgb@NewCodeEnvironment{CppCode}{C++}			% C++ (C++23)
\hgb@NewCodeEnvironment{CsCode}{CSharp}			% C#
\hgb@NewCodeEnvironment{CssCode}{CSS}			% CSS
\hgb@NewCodeEnvironment{DartCode}{Dart}			% Dart
\hgb@NewCodeEnvironment{GlslCode}{GLSL}			% GLSL
\hgb@NewCodeEnvironment{GoCode}{Go}				% Go
\hgb@NewCodeEnvironment{HtmlCode}{[hgb]HTML}	% HTML5
\hgb@NewCodeEnvironment{JavaCode}{Java}			% Java
\hgb@NewCodeEnvironment{JsCode}{JavaScript}		% JavaScript
\hgb@NewCodeEnvironment{JsonCode}{JSON}			% JSON
\hgb@NewCodeEnvironment{KotlinCode}{Kotlin}		% Kotlin
\hgb@NewCodeEnvironment{LaTeXCode}{[hgb]TeX}	% LaTeX
\hgb@NewCodeEnvironment{MatlabCode}{Matlab}		% MATLAB
\hgb@NewCodeEnvironment{ObjCCode}{ObjectiveC}	% Objective-C
\hgb@NewCodeEnvironment{PhpCode}{PHP}			% PHP
\hgb@NewCodeEnvironment{PythonCode}{Python}		% Python 3
\hgb@NewCodeEnvironment{RCode}{R}				% R
\hgb@NewCodeEnvironment{RustCode}{Rust}			% Rust
\hgb@NewCodeEnvironment{ScalaCode}{[hgb]Scala}	% Scala 3
\hgb@NewCodeEnvironment{SqlCode}{[hgb]SQL}		% SQL
\hgb@NewCodeEnvironment{SwiftCode}{Swift}		% Swift
\hgb@NewCodeEnvironment{TsCode}{TypeScript}		% TypeScript
\hgb@NewCodeEnvironment{XmlCode}{[hgb]XML}		% XML
\hgb@NewCodeEnvironment{YamlCode}{YAML}			% YAML

% Code environment for generic code (no language, no escapes)
\lstnewenvironment{GenericCode}[1][]
{\lstset{%
	language={},
	keepspaces=true,
	commentstyle={},
	texcl=false,
	escapechar={},
	escapeinside={},
	#1}}
{}


% Disable the lstlisting environment (due to popular abuse)
\newcommand{\@WarnLstlisting}{
\GenericError{}{Package hgblistings Error: The 'lstlisting' environment is disabled}%
{See the error note inserted in the document output for details.}{}%
\begin{quote}
\color{red}\textbf{NOTE:} The \texttt{lstlisting} environment has been deliberately disabled in this setup.
Use \emph{inline code} (breakable and \emph{without} a caption) or create a \emph{float container} with
\texttt{{\textbackslash}begin\{program\} \ldots {\textbackslash}end\{program\}} instead!
See the \texttt{hgbthesis} tutorial for examples.
\end{quote}%
}
\renewenvironment{lstlisting}[0]%
{\@WarnLstlisting\expandafter\comment}%
{\expandafter\endcomment}%
