diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..91924b9 --- /dev/null +++ b/.gitignore @@ -0,0 +1,5 @@ +.old +blog +MestReNova +rustCrates +result diff --git a/NixTeX/assets/acronyms/analytics/default.nix b/NixTeX/assets/acronyms/analytics/default.nix new file mode 100644 index 0000000..aec7c9f --- /dev/null +++ b/NixTeX/assets/acronyms/analytics/default.nix @@ -0,0 +1,184 @@ +{ core, ... } @ libs: +let + inherit(core) library; +in +{ + attenuatedTotalReflectance = { + section = "Analytical"; + text = { + deu = "Abgeschwächte Total\\-reflexion"; + eng = "Attenuated Total Reflectance"; + }; + description = { + deu = '' + von \acrshort{english} \Q{Attenuated Total Reflectance}, + eine Mess\-technik der \acrlong{infrared}\-spektro\-metrie an einer Material\-oberfläche + ''; + }; + data = { + kind = "Default"; + short = "ATR"; + }; + }; + + energyDispersiveXray = { + section = "Analytical"; + text = { + deu = "Energie\\-dispersive Röntgen\\-spektroskopie"; + }; + description = { + deu = '' + von \acrshort{english} \Q{Energy Dispersive X-ray (spectroscopy)} + ''; + }; + data = { + kind = "Default"; + short = "EDX"; + }; + }; + + electroSprayIonisation = { + section = "Analytical"; + text = { + deu = "Elektro\\-spray\\-ionisation"; + end = "Electro\\-spray ionisation"; + }; + description = { + deu = '' + Technik zur Erzeugung von Ionen durch Zerstäubung der Analyt\-lösungen in einem elektrischen Feld + ''; + }; + data = { + kind = "Default"; + short = "ESI"; + }; + }; + + fourierTransformation = { + section = "Analytical"; + text = { + deu = "\\person{Fourier}-Trans\\-formation"; + }; + data = { + kind = "Default"; + short = "FT"; + }; + }; + + gasChromatography = { + section = "Analytical"; + text = { + deu = "Gas\\-chromato\\-graphie"; + }; + data = { + kind = "Default"; + short = "GC"; + }; + }; + + gpc = { + section = "Analytical"; + text = { + deu = "Gel\\-permeations\\-chromato\\-graphie"; + }; + description = { + deu = '' + auch \textit{Größen\-ausschluss\-chromato\-graphie} + ''; + }; + data = { + kind = "Default"; + short = "GPC"; + }; + }; + + highResolutionMassSpectrometry = { + section = "Analytical"; + text = { + deu = "Hoch\\-aufgelöste Massen\\-spektro\\-metrie"; + eng = "High-Resolution Mass Spectrometry"; + }; + data = { + kind = "Default"; + short = "HRMS"; + }; + }; + + massSpectrometry = { + section = "Analytical"; + text = { + deu = "Massen\\-spektro\\-metrie"; + eng = "Mass Spectrometry"; + }; + data = { + kind = "Default"; + short = "MS"; + }; + }; + + ortep = { + section = "Analytical"; + text = { + deu = "Oak Ridge Thermal Ellipsoid Plot Programme"; + }; + description = { + deu = '' + Program zur Darstellung von Kristall\-strukturen + ''; + }; + data = { + kind = "Default"; + short = "ORTEP"; + }; + }; + + pxrd = { + section = "Analytical"; + text = { + deu = "Pulver\\-röntgen\\-diffrakto\\-metrie"; + }; + description = { + deu = '' + von \acrshort{english} \Q{Powder X-Ray Diffraction} + ''; + }; + data = { + kind = "Default"; + short = "PXRD"; + }; + }; + + scanningElectronMicroscope = { + section = "Analytical"; + text = { + deu = "Raster\\-elektronen\\-mikroskopie"; + }; + data = { + kind = "Default"; + short = "REM"; + }; + }; + + timeOfFlightMS = { + section = "Analytical"; + text = { + deu = "Flug\\-zeit\\-massen\\-spektrometrie"; + eng = "Time Of Flight Mass Spetrometry"; + }; + description = { + deu = '' + Variante der \acrfull{massSpectrometry}, + bei der das \acrlong{massToChargeRatio} durch Messung der Flug\-zeit der Ionen, + welche in einem elektrischen Feld beschleunigt worden, + bestimmt wird + ''; + }; + data = { + kind = "Default"; + short = "TOF-MS"; + }; + }; +} +// library.import ./electrochemistry.nix libs +// library.import ./electromagnetic.nix libs +// library.import ./nmr.nix libs \ No newline at end of file diff --git a/NixTeX/assets/acronyms/analytics/electrochemistry.nix b/NixTeX/assets/acronyms/analytics/electrochemistry.nix new file mode 100644 index 0000000..36dd285 --- /dev/null +++ b/NixTeX/assets/acronyms/analytics/electrochemistry.nix @@ -0,0 +1,48 @@ +{ ... }: +{ + cyclicVoltammetry = { + section = "Analytical"; + text = { + deu = "Cyclo\\-voltam\\-metrie"; + }; + description = { + deu = '' + auch \textit{Dreieckspannungsmethode}, Verfahren zur Analytik verschiedene Elektroden\-prozesse + ''; + }; + data = { + kind = "Default"; + short = "CV"; + }; + }; + ottle = { + section = "Analytical"; + text = { + deu = "Optisch transparente elektro\\-chemische Dünn\\-schicht\\-zelle"; + }; + description = { + deu = '' + von \acrshort{english} \Q{Optically Transparent Thin Layer Electrochemical Cell} + ''; + }; + data = { + kind = "Default"; + short = "OTTLE"; + }; + }; + squareWaveVoltammetry = { + section = "Analytical"; + text = { + deu = "Rechteck\\-wellen\\-voltam\\-metrie"; + }; + description = { + deu = '' + von \acrshort{english} \Q{Square\-Wave Voltammetry} + ''; + }; + data = { + kind = "Default"; + short = "SWV"; + }; + }; +} \ No newline at end of file diff --git a/NixTeX/assets/acronyms/analytics/electromagnetic.nix b/NixTeX/assets/acronyms/analytics/electromagnetic.nix new file mode 100644 index 0000000..beede8b --- /dev/null +++ b/NixTeX/assets/acronyms/analytics/electromagnetic.nix @@ -0,0 +1,51 @@ +{ ... }: +{ + infrared = { + section = "Analytical"; + text = { + deu = "Infra\\-rot"; + }; + description = { + deu = '' + Teil des Spektrums elektro\-magnetischer Wellen mit Wellen\-längen + zwischen ''${\Physical{1}{}{millimetre}{}}$ und ''${\Physical{780}{}{nanometre}{}}$ + ''; + }; + data = { + kind = "Default"; + short = "IR"; + }; + }; + ultraviolet = { + section = "Analytical"; + text = { + deu = "Ultra\\-violett"; + }; + description = { + deu = '' + Teil des Spektrums elektro\-magnetischer Wellen mit Wellen\-längen + zwischen ''${\Physical{380}{}{nanometre}{}}$ und ''${\Physical{10}{}{nanometre}{}}$ + ''; + }; + data = { + kind = "Default"; + short = "UV"; + }; + }; + visible = { + section = "Analytical"; + text = { + deu = "Sichtbares Licht"; + }; + description = { + deu = '' + von \acrshort{english} \Q{Visible}, Teil des Spektrums elektro\-magnetischer Wellen mit Wellen\-längen + zwischen ''${\Physical{780}{}{nanometre}{}}$ und ''${\Physical{380}{}{nanometre}{}}$ + ''; + }; + data = { + kind = "Default"; + short = "VIS"; + }; + }; +} \ No newline at end of file diff --git a/NixTeX/assets/acronyms/analytics/nmr.nix b/NixTeX/assets/acronyms/analytics/nmr.nix new file mode 100644 index 0000000..6f6891a --- /dev/null +++ b/NixTeX/assets/acronyms/analytics/nmr.nix @@ -0,0 +1,170 @@ +{ chemistry, ... }: +let + inherit(chemistry) compound; +in +{ + apt = { + section = "Analytical"; + text = { + deu = "Attached Proton Test"; + eng = "Attached Proton Test"; + }; + description = { + deu = '' + Verfahren der \acrshort{nuclearMagneticResonance}-Spektro\-metrie zur Bestimmung aller direkt benachbarter Protonen + \acrshort{forExample} an ${compound.format "Kohlenstoff"}, + liefert zusätzlich zu den Signalen von \acrshort{dept} die \acrshort{quaternary} ${compound.format "Kohlenstoffe"} + ''; + }; + data = { + kind = "Default"; + short = "APT"; + }; + }; + chemShift = { + section = "Variables"; + text = { + deu = "Chemische Verschiebung"; + }; + description = { + deu = '' + in \Newunit{ppm}{}, \acrshort{english} \textit{chemical shift}, + Abszissen\-wert in der \acrshort{nuclearMagneticResonance}-Spektro\-metrie, + Verhältnis der Differenz der Resonanz\-frequenzen der Zentren eines Referenz\-signales und + eines Mess\-signales zum Zentrum der Resonanz\-frequenz des Referenz\-signales + ''; + }; + data = { + kind = "Math"; + short = "\\delta"; + }; + sortedBy = "δ"; + }; + cosy = { + section = "Analytical"; + text = { + deu = "Korrelations\\-spektro\\-metrie"; + }; + description = { + deu = '' + von \acrshort{english} \Q{COrrelation SpectroscopY}, + Verfahren der \acrshort{nuclearMagneticResonance}-Spektro\-metrie zur Bestimmung + von miteinander koppelnder Kerne, meist ${compound.format "Wasserstoff"} + ''; + }; + data = { + kind = "Default"; + short = "COSY"; + }; + }; + dept = { + section = "Analytical"; + text = { + deu = "Verzerrungs\\-freie Verbesserung durch Polarisations\\-transfer"; + eng = "Distortionless Enhancement by Polarisation Transfer"; + }; + description = { + deu = '' + von \acrshort{english} \Q{Distortionless Enhancement by Polarisation Transfer}, + Verfahren der \acrshort{nuclearMagneticResonance}-Spektro\-metrie zur Bestimmung direkt benachbarter Protonen + \acrshort{forExample} an ${compound.format "Kohlenstoff"} + ''; + }; + data = { + kind = "Default"; + short = "DEPT"; + }; + }; + hmbc = { + section = "Analytical"; + text = { + deu = "Hetero\\-nukleare Mehrfach\\-bindungen\\-korrelation"; + }; + description = { + deu = '' + von \acrshort{english} \Q{Heteronuclear Multi Bond Correlation}, + Verfahren der \acrshort{nuclearMagneticResonance}-Spektro\-metrie + zur Zuordnung der Signale verschiedener Kerne, + welche über mehrere Bindungen koppeln, + \acrshort{forExample} \textsuperscript{1}H-\textsuperscript{13}C-Korrelationen, + von \acrshort{english} \Q{Hetero\-nuclear Multiple Bond Correlation} + ''; + }; + data = { + kind = "Default"; + short = "HMBC"; + }; + }; + hsbc = { + section = "Analytical"; + text = { + deu = "Hetero\\-nukleare Einfach\\-bindungen\\-korrelation"; + }; + description = { + deu = '' + von \acrshort{english} \Q{Heteronuclear Single Bond Correlation}, + Verfahren der \acrshort{nuclearMagneticResonance}-Spektro\-metrie + zur Zuordnung der Signale verschiedener Kerne, + welche über eine Bindung koppeln, + \acrshort{forExample} \textsuperscript{1}H-\textsuperscript{13}C-Korrelationen, + von \acrshort{english} \Q{Hetero\-nuclear Single Bond Correlation} + ''; + }; + data = { + kind = "Default"; + short = "HSBC"; + }; + }; + hsqc = { + section = "Analytical"; + text = { + deu = "Hetero\\-nukleare Einzel\\-quanten\\-kohärenz"; + }; + description = { + deu = '' + von \acrshort{english} \Q{Heteronuclear Single Quantum Coherence}, + Verfahren der \acrshort{nuclearMagneticResonance}-Spektro\-metrie + zur Zuordnung der Signale verschiedener Kerne, + welche über eine Bindung verbunden sind, + \acrshort{forExample} \textsuperscript{1}H-\textsuperscript{13}C- und + \textsuperscript{1}H-\textsuperscript{15}N-Korrelationen, + von \acrshort{english} \Q{Hetero\-nuclear Single Quantum Coherence} + ''; + }; + data = { + kind = "Default"; + short = "HSQC"; + }; + }; + noesy = { + section = "Analytical"; + text = { + deu = "Kern-Overhauser-Effekt-Spektro\-metrie"; + }; + description = { + deu = '' + von \acrshort{english} \Q{Nuclear Overhauser Effect Spectro\-Metry}, + Verfahren der \acrshort{nuclearMagneticResonance}-Spektro\-metrie zur Bestimmung benachbarter Kerne über den Raum + ''; + }; + data = { + kind = "Default"; + short = "NOESY"; + }; + }; + nuclearMagneticResonance = { + section = "Analytical"; + text = { + deu = "Kern\\-magnet\\-resonanz"; + }; + description = { + deu = '' + von \acrshort{english} \Q{Nuclear Magnetic Resonance}, auch \Q{Kern\-spin\-resonanz} + ''; + }; + data = { + kind = "Default"; + short = "NMR"; + }; + }; +} \ No newline at end of file diff --git a/NixTeX/assets/acronyms/chemicals/acids.nix b/NixTeX/assets/acronyms/chemicals/acids.nix new file mode 100644 index 0000000..2340663 --- /dev/null +++ b/NixTeX/assets/acronyms/chemicals/acids.nix @@ -0,0 +1,55 @@ +{ chemistry, ... }: +let + inherit(chemistry) compound; +in +{ + dibromoIsocyanuricAcid = { + section = "Substances"; + text = { + deu = { + tex = "${compound.format "Di|brom||iso|cyanur||säure"}"; + }; + }; + description = { + deu = '' + eine ${compound.format "Brom"}ierungs\-reagenz + ''; + }; + data = { + kind = "Chemical"; + short = "DBI"; + }; + }; + tfa = { + section = "Substances"; + text = { + deu = { + tex = "${compound.format "Tri|fluor||essigsäure"}"; + }; + }; + data = { + kind = "Chemical"; + short = "TFA"; + }; + }; + trimesic = { + section = "Substances"; + text = { + deu = { + tex = "${compound.format "Tri|mesin||säure"}"; + }; + }; + description = { + deu = '' + ${compound.format "1,3,5-Benzen||tri|carbonsäure"} sowie deren Salze, Ester, \acrshort{etc} + ''; + }; + data = { + kind = "Chemical"; + short = "'btc'"; + struct = '' + \cheme{\chemfig{R-[:30]CH_3}}{} + ''; + }; + }; +} \ No newline at end of file diff --git a/NixTeX/assets/acronyms/chemicals/amines.nix b/NixTeX/assets/acronyms/chemicals/amines.nix new file mode 100644 index 0000000..2ccdcf7 --- /dev/null +++ b/NixTeX/assets/acronyms/chemicals/amines.nix @@ -0,0 +1,130 @@ +{ chemistry, ... }: +let + inherit(chemistry) compound; +in +{ + dipa = { + section = "Substances"; + text = { + deu = { + tex = "${compound.format "Di|iso|propyl||amin"}"; + }; + }; + description = { + deu = '' + sekundäres ${compound.format "Alkyl||amin"} + ''; + }; + data = { + kind = "Chemical"; + short = "DIPA"; + }; + }; + dipea = { + section = "Substances"; + text = { + deu = { + tex = "${compound.format "Di|iso|propyl||ethyl||amin"}"; + }; + }; + description = { + deu = '' + tertiäres ${compound.format "Alkyl||amin"} + ''; + }; + data = { + kind = "Chemical"; + short = "DIPEA"; + }; + }; + dmf = { + section = "Substances"; + text = { + deu = { + tex = "${compound.format "N,N-Di|methyl||formamid"}"; + }; + }; + description = { + deu = '' + \ch{(H3C)2NCHO}, + ${compound.format "Di|methyl||amid"} der ${compound.format "Ameisen||säure"} + ''; + }; + data = { + kind = "Chemical"; + short = "DMF"; + }; + }; + tbaf = { + section = "Substances"; + text = { + deu = { + tex = "${compound.format "Tetra|butyl||ammonium||fluorid"}"; + }; + }; + description = { + deu = '' + \ch{(H3C(CH2)3)4NF}, + quartäres ${compound.format "Ammonium||halogenid"}, ${compound.format "Fluorid"} von \acrlong{tetraButylAmmonium} + ''; + }; + data = { + kind = "Chemical"; + short = "TBAF"; + }; + }; + tetraButylAmmonium = { + section = "Substances"; + text = { + deu = { + tex = "${compound.format "Tetra|butyl||ammonium"}"; + }; + }; + description = { + deu = '' + \ch{(H3C(CH2)3)4N+}, organisches Kation \acrshort{forExample} für das Leit\-salz \ch{PF6} in der \acrlong{cyclicVoltammetry} + ''; + }; + data = { + kind = "Chemical"; + short = "TBA"; + }; + }; + tmeda = { + section = "Substances"; + text = { + deu = { + tex = "${compound.format "N,N,N',N'-Tetra|methyl||ethylen||di|amin"}"; + }; + }; + description = { + deu = '' + \ch{(H3C)2NC2H4N(CH3)2}, + tertiäres ${compound.format "Alkyl||di|amin"} + ''; + }; + data = { + kind = "Chemical"; + short = "TMEDA"; + struct = '' + \cheme{\chemfig{-[:-30]N(-[::-60])-[::60]-[::-60]-[::60]N(-[::-60])-[::60]}}{} + ''; + }; + }; + triethylamine = { + section = "Substances"; + text = { + deu = "${compound.format "Tri|ethyl||amin"}"; + }; + description = { + deu = '' + \ch{N3}, + tertiäres ${compound.format "Alkyl||amin"} + ''; + }; + data = { + kind = "Chemical"; + short = "N3"; + }; + }; +} \ No newline at end of file diff --git a/NixTeX/assets/acronyms/chemicals/aminoacids.nix b/NixTeX/assets/acronyms/chemicals/aminoacids.nix new file mode 100644 index 0000000..b7a1e89 --- /dev/null +++ b/NixTeX/assets/acronyms/chemicals/aminoacids.nix @@ -0,0 +1,57 @@ +{ chemistry, ... }: +let + inherit(chemistry) compound; +in +{ + glycine = { + section = "Substances"; + text = { + deu = { + tex = "${compound.format "Glycin"}"; + }; + }; + description = { + deu = '' + eine polare alkylische proteinogene Amino\-säure + ''; + }; + data = { + kind = "Chemical"; + short = "Gly"; + }; + }; + phenylalanine = { + section = "Substances"; + text = { + deu = { + tex = "${compound.format "Phenyl||alanin"}"; + }; + }; + description = { + deu = '' + eine unpolare aromatische proteinogene Amino\-säure + ''; + }; + data = { + kind = "Chemical"; + short = "Phe"; + }; + }; + valine = { + section = "Substances"; + text = { + deu = { + tex = "${compound.format "Valin"}"; + }; + }; + description = { + deu = '' + eine unpolare alkylische proteinogene Amino\-säure + ''; + }; + data = { + kind = "Chemical"; + short = "Val"; + }; + }; +} \ No newline at end of file diff --git a/NixTeX/assets/acronyms/chemicals/aromatics.nix b/NixTeX/assets/acronyms/chemicals/aromatics.nix new file mode 100644 index 0000000..7e3d502 --- /dev/null +++ b/NixTeX/assets/acronyms/chemicals/aromatics.nix @@ -0,0 +1,246 @@ +{ chemistry, ... }: +let + inherit(chemistry) compound; +in +{ + "benzo[12b:45b']dithiophene" = { + section = "Substances"; + text = { + deu = { + tex = "${compound.format "Benzo§[1,2-b:4,5-b']§di|thiophen"}"; + }; + }; + description = { + deu = '' + ein tricyclischer Hetero\-aromat + ''; + }; + data = { + kind = "Chemical"; + short = "BDT"; + struct = '' + \cheme{\chemfig{*5(-S-(*5(-S-=-=))=-=)}}{} + ''; + }; + }; + "benzo[12b:45c']dithiophenedione" = { + section = "Substances"; + text = { + deu = { + tex = "${compound.format "Benzo§[1,2-b:4,5-c']§di|thiophen§-4,8-§di|on"}"; + }; + }; + description = { + deu = '' + ein tricyclischer Hetero\-aromat + ''; + }; + data = { + kind = "Chemical"; + short = "BDD"; + struct = '' + \cheme{\chemfig{*5(-S-=(*6(-(=O)-(*5(=-S-=))--(=O)-))-=)}}{} + ''; + }; + }; + benzothiadiazole = { + section = "Substances"; + text = { + deu = { + tex = "${compound.format "2,1,3-Benzo||thia||di|azol"}"; + }; + }; + description = { + deu = '' + ein bicyclischer Hetero\-aromat + ''; + }; + data = { + kind = "Chemical"; + short = "BT"; + struct = '' + \cheme{\chemfig{*6(-(*5(=N-S-N=))--=-=)}}{} + ''; + }; + }; + benzotriazole = { + section = "Substances"; + text = { + deu = { + tex = "${compound.format "Benzo||tri|azol"}"; + }; + }; + description = { + deu = '' + ein bicyclischer Hetero\-aromat + ''; + }; + data = { + kind = "Chemical"; + short = "BTA"; + struct = '' + \cheme{\chemfig{*6(-(*5(=N-N-N=))--=-=)}}{} + ''; + }; + }; + bipy = { + section = "Substances"; + text = { + deu = { + tex = "${compound.format "Bi|pyrridin"}"; + }; + }; + description = { + deu = '' + ein hetero\-aromatisches Biaryl + ''; + }; + data = { + kind = "Chemical"; + short = "'bipy'"; + struct = '' + \cheme{\chemfig{*6(=N-(*6(=N-=-=-))=-=-)}}{} + ''; + }; + }; + bithiophene = { + section = "Substances"; + text = { + deu = { + tex = "${compound.format "2,2'-Bi|thiophen"}"; + }; + }; + description = { + deu = '' + ein hetero\-aromatisches Biaryl + ''; + }; + data = { + kind = "Chemical"; + short = "T2"; + struct = '' + \cheme{\chemfig{*5(-S-(*5(-S-=-=))=-=)}}{} + ''; + }; + }; + carbazole = { + section = "Substances"; + text = { + deu = { + tex = "${compound.format "§9H-§Carbazol"}"; + }; + }; + description = { + deu = '' + ein tricyclischer Hetero\-aromat + ''; + }; + data = { + kind = "Chemical"; + short = "Cbz"; + struct = '' + \cheme{\chemfig{*6(=-(*5(-(*6(-=-=-=^))--\chembelow{N}{H}-))=-=-)}}{} + ''; + }; + }; + dihydroindacenodithiophene = { + section = "Substances"; + text = { + deu = { + tex = "${compound.format "4,9-Di|hydro-s-indaceno§[1,2-b:5,6-b']§di|thiophen"}"; + }; + }; + description = { + deu = '' + ein pentacyclischer Hetero\-aromat + ''; + }; + data = { + kind = "Chemical"; + short = "IDT"; + struct = '' + \cheme{\chemfig{*5(-S-(*5(-(*6(=-(*5(-(-[::-74]R)(-[::-34]R)-(*5(-=-S-=^))--))=-=))--(-[::-74]R)(-[::-34]R)-))=-=)}}{} + ''; + }; + }; + diketopyrrolopyrrole = { + section = "Substances"; + text = { + deu = { + tex = "${compound.format "2,5-Di|hydro||pyrrolo§[3,4-c]§pyrrol§-1,4-§di|on"}"; + }; + }; + description = { + deu = '' + ein bicyclischer Hetero\-aromat + ''; + }; + data = { + kind = "Chemical"; + short = "DPP"; + struct = '' + \cheme{\chemfig{*5(-N(-R)-(=O)-(*5(=-N(-R)-(=O)-))-=)}}{} + ''; + }; + }; + fluorene = { + section = "Substances"; + text = { + deu = { + tex = "${compound.format "Fluoren"}"; + }; + }; + description = { + deu = '' + ein tricyclischer aromatischer ${compound.format "Kohlen||wasserstoff"} + ''; + }; + data = { + kind = "Chemical"; + short = "Fl"; + struct = '' + \cheme{\chemfig{*6(=-(*5(-(*6(-=-=-=^))---))=-=-)}}{} + ''; + }; + }; + "thieno[32b]thiophene" = { + section = "Substances"; + text = { + deu = { + tex = "${compound.format "Thieno§[3,2-b]§thiophen"}"; + }; + }; + description = { + deu = '' + ein bicyclischer Hetero\-aromat + ''; + }; + data = { + kind = "Chemical"; + short = "TT"; + struct = '' + \cheme{\chemfig{*5(-S-(*5(-=-S-))=-=)}}{} + ''; + }; + }; + thiophene = { + section = "Substances"; + text = { + deu = { + tex = "${compound.format "Thiophen"}"; + }; + }; + description = { + deu = '' + ein ${compound.format "schwefel||haltiger"} hetero\-aromatischer Fünf\-ring + ''; + }; + data = { + kind = "Chemical"; + short = "T"; + struct = '' + \cheme{\chemfig{*5(-S-=-=)}}{} + ''; + }; + }; +} \ No newline at end of file diff --git a/NixTeX/assets/acronyms/chemicals/bases.nix b/NixTeX/assets/acronyms/chemicals/bases.nix new file mode 100644 index 0000000..3fc5582 --- /dev/null +++ b/NixTeX/assets/acronyms/chemicals/bases.nix @@ -0,0 +1,104 @@ +{ chemistry, ... }: +let + inherit(chemistry) compound; +in +{ + LiAlH4 = { + section = "Substances"; + text = { + deu = "${compound.format "Lithium||aluminium||hydrid"}"; + }; + data = { + kind = "Chemical"; + short = "LiAlH4"; + struct = '' + \cheme{\chemfig{H-Al^\text{\ominus}(-[::-120]H)(-[::120]H)-[::0]H-[::0,,,,draw=none]Li^\text{\oplus}}}{} + ''; + }; + }; + NaOH = { + section = "Substances"; + text = { + deu = { + tex = "${compound.format "Natrium||hydroxid"}"; + }; + }; + data = { + kind = "Chemical"; + short = "NaOH"; + }; + }; + lda = { + section = "Substances"; + text = { + deu = "${compound.format "Lithium||di|iso|propyl||amid"}"; + }; + data = { + kind = "Chemical"; + short = "LDA"; + }; + }; + nBuLi = { + section = "Substances"; + text = { + deu = { + tex = "${compound.format "n-Butyl||lithium"}"; + }; + }; + description = { + deu = '' + \ch{H3C(CH2)3Li}, + eine ${compound.format "Organo|lithium||verbindung"} + ''; + }; + data = { + kind = "Chemical"; + short = "^nBuLi"; + struct = '' + \cheme{\chemfig{H_3C-[:30]-[:-30]-[:30]-[:-30]Li}}{} + ''; + }; + }; + tBuLi = { + section = "Substances"; + text = { + deu = { + tex = "${compound.format "tert-Butyl||lithium"}"; + }; + }; + description = { + deu = '' + \ch{(H3C)3CLi}, + eine ${compound.format "Organo|lithium||verbindung"} + ''; + }; + data = { + kind = "Chemical"; + short = "^tBuLi"; + struct = '' + \cheme{\chemfig{H_3C-C(-[::-120]H_3C)(-[::120]H_3C)-[::0]Li}}{} + ''; + }; + }; + tBuOK = { + section = "Substances"; + text = { + deu = { + tex = "${compound.format "Kalium-tert-butanolat"}"; + }; + }; + description = { + deu = '' + \ch{H3C(CH2)3OK}, + ein ${compound.format "Kalium||alkoholat"} + ''; + }; + data = { + kind = "Chemical"; + short = "^tBuOK"; + struct = '' + \cheme{\chemfig{H_3C-C(-[::-120]H_3C)(-[::120]H_3C)-O^\text{\ominus}-[::0,,,,draw=none]K^\text{\oplus}}}{} + ''; + }; + }; +} \ No newline at end of file diff --git a/NixTeX/assets/acronyms/chemicals/default.nix b/NixTeX/assets/acronyms/chemicals/default.nix new file mode 100644 index 0000000..4259d2f --- /dev/null +++ b/NixTeX/assets/acronyms/chemicals/default.nix @@ -0,0 +1,140 @@ +{ core, chemistry, ... } @ libs: + let + inherit(core) library; + inherit(chemistry) compound; + in + { + aibn = { + section = "Substances"; + text = { + deu = { + tex = "${compound.format "Azo||bis|iso|butyro||nitril"}"; + }; + }; + data = { + kind = "Chemical"; + short = "AIBN"; + }; + }; + alox = { + section = "Substances"; + text = { + deu = { + tex = "${compound.format "Aluminium(III)-oxid"}"; + }; + }; + description = { + deu = '' + als stationäre Phase der Säulen\-chromato\-graphie + ''; + }; + data = { + kind = "Chemical"; + short = "ALOX"; + }; + }; + bop = { + section = "Substances"; + text = { + deu = { + tex = "${compound.format "Benzo||tri|azol-1-yl||oxy||tris(di|methyl||amino)phosphonium||hexa|fluorido||phosphat"}"; + }; + }; + data = { + kind = "Chemical"; + short = "BOP"; + }; + }; + dbdmh = { + section = "Substances"; + text = { + deu = { + tex = "${compound.format "1,3-Di|brom-5,5-di|methyl||hydantoin"}"; + }; + }; + description = { + deu = '' + eine ${compound.format "Brom"}ierungs\-reagenz + ''; + }; + data = { + kind = "Chemical"; + short = "DBDMH"; + }; + }; + dbpo = { + section = "Substances"; + text = { + deu = { + tex = "${compound.format "Di|benzoyl||per|oxid"}"; + }; + }; + data = { + kind = "Chemical"; + short = "DBPO"; + }; + }; + dead = { + section = "Substances"; + text = { + deu = { + tex = "${compound.format "Azo||di|carbonsäure||di|ethyl||ester"}"; + }; + }; + data = { + kind = "Chemical"; + short = "DEAD"; + }; + }; + diad = { + section = "Substances"; + text = { + deu = { + tex = "${compound.format "Azo||di|carbonsäure||di|iso|propyl||ester"}"; + }; + }; + data = { + kind = "Chemical"; + short = "DIAD"; + }; + }; + naphthalenedianhydride = { + section = "Substances"; + text = { + deu = { + tex = "${compound.format "Naphthalen§-1,4,5,8-tetra|carboxyl§||di|anhydrid"}"; + }; + }; + data = { + kind = "Chemical"; + short = "NDA"; + struct = '' + \cheme{\chemfig{*6(-(*6(-(=O)-O-(=O)-))=(*6(-=-=(*6(-(=O)-O-(=O)-))-))-=-=)}}{} + ''; + }; + }; + phb = { + section = "Substances"; + text = { + deu = { + tex = "${compound.format "4-Hydroxy||benzyl||alkohol"}"; + }; + }; + data = { + kind = "Chemical"; + short = "PHB"; + }; + }; + } + // library.import ./acids.nix libs + // library.import ./amines.nix libs + // library.import ./aminoacids.nix libs + // library.import ./aromatics.nix libs + // library.import ./bases.nix libs + // library.import ./groups.nix libs + // library.import ./ligands.nix libs + // library.import ./meta.nix libs + // library.import ./nucleicacids.nix libs + // library.import ./polymers.nix libs + // library.import ./silanes.nix libs + // library.import ./solvents.nix libs diff --git a/NixTeX/assets/acronyms/chemicals/groups.nix b/NixTeX/assets/acronyms/chemicals/groups.nix new file mode 100644 index 0000000..f65ca70 --- /dev/null +++ b/NixTeX/assets/acronyms/chemicals/groups.nix @@ -0,0 +1,372 @@ +{ chemistry, ... }: +let + inherit(chemistry) compound; +in +{ + "2-octyldodecyl" = { + section = "Substances"; + text = { + deu = { + tex = "${compound.format "2-Octyl||dodecyl||gruppe"}"; + }; + }; + description = { + deu = '' + eine Alkyl\-gruppe + ''; + }; + data = { + kind = "Chemical"; + short = "2-OD"; + struct = '' + \cheme{\chemfig{-[:90]-[::60]-[::-60]-[::60]-[::-60]-[::60]-[::-60]-[::60]-[::-60]-[::60](-[::60]-[::60]-[::60]-[::-60]-[::60]-[::-60]-[::60]-[::-60])-[::-60]-[::60]R}}{} + ''; + }; + }; + acetyl = { + section = "Substances"; + text = { + deu = { + tex = "${compound.format "Acetyl||gruppe"}"; + }; + }; + description = { + deu = '' + \ch{H3CCO}, + eine Acyl\-gruppe + ''; + }; + data = { + kind = "Chemical"; + short = "Ac"; + struct = '' + \cheme{\chemfig{R-[:30](=[::60]O)-[::-60]CH_3}}{} + ''; + }; + }; + benzyl = { + section = "Substances"; + text = { + deu = { + tex = "${compound.format "Benzyl||gruppe"}"; + }; + }; + description = { + deu = '' + \ch{-CH2}, + eine Aryl\-gruppe + ''; + }; + data = { + kind = "Chemical"; + short = "Bzl"; + struct = '' + \cheme{\chemfig{R-[:30]-[::-60]*6(-=-=-=)}}{} + ''; + }; + }; + cyclopentadienyl = { + section = "Substances"; + text = { + deu = { + tex = "${compound.format "Cyclo||pentadienyl||gruppe"}"; + }; + }; + description = { + deu = '' + vom ${compound.format "Cyclo|penta|di|en"}\-anion (\ch{C5H5-}) abgeleitet, + eine Aryl\-gruppe + ''; + }; + data = { + kind = "Chemical"; + short = "Cp"; + struct = '' + \cheme{\chemfig{R-[:30]**5(--(-[::126,0.88,,,,draw=none]\text{\ominus})---)}}{} + ''; + }; + }; + "cyclopentadienyl*" = { + section = "Substances"; + text = { + deu = { + tex = "${compound.format "Tetra|methyl||cyclo||penta|di|enyl||gruppe"}"; + }; + }; + description = { + deu = '' + vom ${compound.format "Penta|methyl||cyclo|penta|di|en"}\-anion (\ch{C5(CH3)5-}) abgeleitet, + eine Aryl\-gruppe + ''; + }; + data = { + kind = "Chemical"; + short = "*"; + }; + }; + dipp = { + section = "Substances"; + text = { + deu = { + tex = "${compound.format "Di|iso|propyl||phenyl||gruppe"}"; + }; + }; + description = { + deu = '' + \ch{-()2}, + eine Aryl\-gruppe + ''; + }; + data = { + kind = "Chemical"; + short = "'dipp'"; + }; + }; + ethyl = { + section = "Substances"; + text = { + deu = { + tex = "${compound.format "Ethyl||gruppe"}"; + }; + }; + description = { + deu = '' + \ch{-CH2CH3}, eine Alkyl\-gruppe + ''; + }; + data = { + kind = "Chemical"; + short = "Et"; + struct = '' + \cheme{\chemfig{R-[:30]-[:-30]CH_3}}{} + ''; + }; + }; + ferrocenyl = { + section = "Substances"; + text = { + deu = { + tex = "${compound.format "Ferrocenyl||gruppe"}"; + }; + }; + description = { + deu = '' + von ${compound.format "Ferrocen"} (\ch{Fe(h5 -C5H5)2}) abgeleitet, eine Metallocyl\-gruppe + ''; + }; + data = { + kind = "Chemical"; + short = "Fc"; + struct = '' + \cheme{\chemname{\chemfig{-[:-303.51,0.4476]-[::303.51,,,,]-[::303.51,0.4476]<[::251.67,0.7741]@{r5}{}>[::329.64,0.7741]-[::205.18,0.7472,,,draw=none]@{r1}{}-[::80,0.70]Fe-[::0,0.85]\ -[::0,0]@{r2}{}-[::85,0.7472,,,draw=none]<[::128.51,0.4476]@{r3}{}-[::56.49,,,,line width=2pt]@{r4}{}(-[::333.245]R)>[::56.49,0.4476]-[::108.33,0.7741]-[::30.36,0.7741]}}{gestaffelt}\chemname{\chemfig{<[:303.51-\rotate,0.4476]@{r15}{}-[:: 56.49,,,,line width=2pt]@{r16}{}>[:: 56.49,0.4476]-[::108.33,0.7741]-[::30.36,0.7741]-[::159.82,0.7472,,,draw=none]@{r11}{}-[::95,0.70]Fe-[:: 0,0.85]\ -[::0,0]@{r12}{}-[::85,0.7472,,,draw=none]<[::128.51,0.4476]@{r13}{}-[:: 56.49,,,,line width=2pt]@{r14}{}(-[::333.245]R)>[:: 56.49,0.4476]-[::108.33,0.7741]-[::30.36,0.7741]}}{ekliptisch}}{\draw[rotate=\rotate] (r1) ellipse (6pt and 2pt);\draw[rotate=\rotate] (r2) ellipse (6pt and 2pt);\draw[-,rotate=\rotate,line width=0.6pt] (r2)\fill[rotate=\rotate] (r3) ellipse (1.3pt and 1pt);\fill[rotate=\rotate] (r4) ellipse (1.3pt and 1pt);\fill[rotate=\rotate] (r5) ellipse (1pt and 1.3pt);\draw[rotate=\rotate] (r11) ellipse (6pt and 2pt);\draw[rotate=\rotate] (r12) ellipse (6pt and 2pt);\draw[-,rotate=\rotate,line width=0.6pt] (r12)\fill[rotate=\rotate] (r13) ellipse (1.3pt and 1pt);\fill[rotate=\rotate] (r14) ellipse (1.3pt and 1pt);\fill[rotate=\rotate] (r15) ellipse (1.3pt and 1pt);\fill[rotate=\rotate] (r16) ellipse (1.3pt and 1pt);} + ''; + }; + }; + fmoc = { + section = "Substances"; + text = { + deu = { + tex = "${compound.format "Fluorenyl||methoxy||carbonyl||gruppe"}"; + }; + }; + description = { + deu = '' + \ch{???}, + Schutz\-gruppe für \acrshort{forExample} ${compound.format "Amine"} + ''; + }; + data = { + kind = "Chemical"; + short = "Fmoc"; + }; + }; + isoPropyl = { + section = "Substances"; + text = { + deu = { + tex = "${compound.format "Iso|propyl||gruppe"}"; + }; + }; + description = { + deu = '' + \ch{-CH(CH3)2}, + eine Alkyl\-gruppe + ''; + }; + data = { + kind = "Chemical"; + short = "^iPr"; + struct = '' + \cheme{\chemfig{R-[:30](-[:30]CH_3)-[:-30]CH_3}}{} + ''; + }; + }; + mesyl = { + section = "Substances"; + text = { + deu = { + tex = "${compound.format "Mesyl||gruppe"}"; + }; + }; + description = { + deu = '' + \ch{-SO2CH3}, + systematisch nach \acrshort{iupac}: ${compound.format "Methan||sulfonyl||gruppe"}, + die Ester und Salze der ${compound.format "Methan||sulfonsäure"} (\ch{MsOH}) werden als ${compound.format "Mesylate"} bezeichnet, + welche als Abgangs\-gruppe für nukleo\-phile Substitutions\-reaktionen + durch Reaktion des ${compound.format "Säure\-chlorides"} mit einem ${compound.format "Alkohol"} + gebildet werden kann + ''; + }; + data = { + kind = "Chemical"; + short = "Ms"; + struct = '' + \cheme{\chemfig{R-[:30]-S(=[::75]O)(=[::45]O)[::-60]CH_3}}{} + ''; + }; + }; + methyl = { + section = "Substances"; + text = { + deu = { + tex = "${compound.format "Methyl||gruppe"}"; + }; + }; + description = { + deu = '' + \ch{-CH3}, eine Alkyl\-gruppe + ''; + }; + data = { + kind = "Chemical"; + short = "Me"; + struct = '' + \cheme{\chemfig{R-[:30]CH_3}}{} + ''; + }; + }; + naphthalenediimide = { + section = "Substances"; + text = { + deu = { + tex = "${compound.format "Naphthalen§-1,4,5,8-tetra|carboxyl§||di|imid"}"; + }; + }; + description = { + deu = '' + von ${compound.format "Naphthalen"} abgeleite, tetrazyklische hetero\-aromatische Gruppe + ''; + }; + data = { + kind = "Chemical"; + short = "NDI"; + struct = '' + \cheme{\chemfig{*6(-(*6(-(=O)-N(-R)-(=O)-))=(*6(-=-=(*6(-(=O)-N(-R)-(=O)-))-))-=-=)}}{} + ''; + }; + }; + phenyl = { + section = "Substances"; + text = { + deu = { + tex = "${compound.format "Phenyl||gruppe"}"; + }; + }; + description = { + deu = '' + von ${compound.format "Benzen"} (\ch{C6H6}) abgeleitet, + einem aromatischen ${compound.format "Kohlen||wasserstoff"}. + ''; + }; + data = { + kind = "Chemical"; + short = "Ph"; + struct = '' + \cheme{\chemfig{R-[:30]*6(-=-=-=)}}{} + ''; + }; + }; + pyrenyl = { + section = "Substances"; + text = { + deu = { + tex = "${compound.format "Pyrenyl||gruppe"}"; + }; + }; + description = { + deu = '' + von ${compound.format "Pyren"} (\ch{C16H10}) abgeleitet, + einem poly\-zyklischen aromatischen ${compound.format "Kohlen||wasserstoff"}. + ''; + }; + data = { + kind = "Chemical"; + short = "Py"; + }; + }; + tosyl = { + section = "Substances"; + text = { + deu = { + tex = "${compound.format "Tosyl||gruppe"}"; + }; + }; + description = { + deu = '' + \ch{-SO2}, + systematisch nach \acrshort{iupac}: ${compound.format "p-Toluen||sulfonyl||gruppe"}, + die Ester und Salze der ${compound.format "p-Toluen||sulfonsäure"} (\ch{TsOH}) werden als ${compound.format "Tosylate"} bezeichnet, + welche als Abgangs\-gruppe für nukleo\-phile Substitutions\-reaktionen + durch Reaktion des ${compound.format "Säure\-chlorides"} mit einem ${compound.format "Alkohol"} + gebildet werden kann + ''; + }; + data = { + kind = "Chemical"; + short = "Ts"; + }; + }; + triflyl = { + section = "Substances"; + text = { + deu = { + tex = "${compound.format "Triflyl||gruppe"}"; + }; + }; + description = { + deu = '' + \ch{-SO2CF3}, + systematisch nach \acrshort{iupac}: ${compound.format "Tri|fluor||methan||sulfonyl||gruppe"}, + die Ester und Salze der ${compound.format "Tri|fluor||methan||sulfonsäure"} (\ch{TfOH}) werden als ${compound.format "Triflate"} bezeichnet, + welche als Abgangs\-gruppe für nukleo\-phile Substitutions\-reaktionen + durch Reaktion des ${compound.format "Säure\-chlorides"} mit einem ${compound.format "Alkohol"} + gebildet werden kann + ''; + }; + data = { + kind = "Chemical"; + short = "Tf"; + }; + }; + trimethylsilyl = { + section = "Substances"; + text = { + deu = { + tex = "${compound.format "Tri|methyl||silyl||gruppe"}"; + }; + }; + description = { + deu = '' + \ch{-Si(CH3)3} + ''; + }; + data = { + kind = "Chemical"; + short = "TMS"; + struct = '' + \cheme{\chemfig{R-Si(-[::-120]H_3C)(-[::120]H_3C)-[::0]CH_3}}{} + ''; + }; + }; +} \ No newline at end of file diff --git a/NixTeX/assets/acronyms/chemicals/ligands.nix b/NixTeX/assets/acronyms/chemicals/ligands.nix new file mode 100644 index 0000000..4f11c9f --- /dev/null +++ b/NixTeX/assets/acronyms/chemicals/ligands.nix @@ -0,0 +1,42 @@ +{ chemistry, ... }: +let + inherit(chemistry) compound; +in +{ + dibenzylideneacetone = { + section = "Substances"; + text = { + deu = { + tex = "${compound.format "Di|benzyliden||aceton"}"; + }; + }; + description = { + deu = '' + \ch{(CH)2CO(CH)2}, + Ligang der Organo\-metall\-chemie + ''; + }; + data = { + kind = "Chemical"; + short = "'dba'"; + }; + }; + dppf = { + section = "Substances"; + text = { + deu = { + tex = "${compound.format "1,1′-Bis(di:phenyl|phosphino)|ferrocen"}"; + }; + }; + description = { + deu = '' + \ch{(P2)2}, + substituiertes ${compound.format "Ferrocen"}, ${compound.format "Di|phosphan"}, Ligang der Organo\-metall\-chemie + ''; + }; + data = { + kind = "Chemical"; + short = "'dppf'"; + }; + }; +} \ No newline at end of file diff --git a/NixTeX/assets/acronyms/chemicals/meta.nix b/NixTeX/assets/acronyms/chemicals/meta.nix new file mode 100644 index 0000000..1326ab7 --- /dev/null +++ b/NixTeX/assets/acronyms/chemicals/meta.nix @@ -0,0 +1,48 @@ +{ chemistry, ... }: +let + inherit(chemistry) compound; +in +{ + metalOrganicFramework = { + section = "Substances"; + text = { + deu = "Metall\\-organische Gerüst\\-verbindung"; + }; + description = { + deu = '' + von \acrshort{english} \Q{Metal Organic Framework} + ''; + }; + data = { + kind = "Chemical"; + short = "MOF"; + }; + }; + nhc = { + section = "Substances"; + text = { + deu = { + tex = "${compound.format "N-hetero||cyclische(s )~Carben(e )"}"; + }; + }; + data = { + kind = "Chemical"; + short = "NHC"; + }; + }; + silanCouplingAgent = { + section = "Substances"; + text = { + deu = "Silan\\-kupplungs\\-mittel"; + }; + description = { + deu = '' + von \acrshort{english} \Q{Silane Coupling Agent} + ''; + }; + data = { + kind = "Default"; + short = "SCA"; + }; + }; +} \ No newline at end of file diff --git a/NixTeX/assets/acronyms/chemicals/nucleicacids.nix b/NixTeX/assets/acronyms/chemicals/nucleicacids.nix new file mode 100644 index 0000000..9d3746c --- /dev/null +++ b/NixTeX/assets/acronyms/chemicals/nucleicacids.nix @@ -0,0 +1,40 @@ +{ chemistry, ... }: +let + inherit(chemistry) compound; +in +{ + dna = { + section = "Substances"; + text = { + deu = { + tex = "${compound.format "Des|oxy||ribo||nuklein||säure"}"; + }; + }; + description = { + deu = '' + eine aus ${compound.format "Des|oxy||ribo||nukleotiden"} aufgebaute ${compound.format "Nuklein||säure"} + ''; + }; + data = { + kind = "Chemical"; + short = "DNA"; + }; + }; + rna = { + section = "Substances"; + text = { + deu = { + tex = "${compound.format "Ribo||nuklein||säure"}"; + }; + }; + description = { + deu = '' + eine aus ${compound.format "Ribo||nukleotiden"} aufgebaute ${compound.format "Nuklein||säure"} + ''; + }; + data = { + kind = "Chemical"; + short = "RNA"; + }; + }; +} \ No newline at end of file diff --git a/NixTeX/assets/acronyms/chemicals/polymers.nix b/NixTeX/assets/acronyms/chemicals/polymers.nix new file mode 100644 index 0000000..c8e79ed --- /dev/null +++ b/NixTeX/assets/acronyms/chemicals/polymers.nix @@ -0,0 +1,182 @@ +{ chemistry, ... }: +let + inherit(chemistry) compound; +in +{ + polyE = { + section = "Substances"; + text = { + deu = { + tex = "${compound.format "Poly||ethylen"}"; + }; + }; + description = { + deu = '' + ein aus ${compound.format "Ethen"} durch Ketten\-polymerisation + hergestellter thermo\-plastischer Kunst\-stoff + ''; + }; + data = { + kind = "Chemical"; + short = "PE"; + }; + }; + polyET = { + section = "Substances"; + text = { + deu = { + tex = "${compound.format "Poly||ethylen||terephthalat"}"; + }; + }; + description = { + deu = '' + ein aus ${compound.format "Terephthal||säure"} und ${compound.format "Ethylen||glycol"} + durch Polykondensations hergestellter thermo\-plastischer Kunst\-stoff + ''; + }; + data = { + kind = "Chemical"; + short = "PET"; + }; + }; + polyMMA = { + section = "Substances"; + text = { + deu = { + tex = "${compound.format "Poly||methyl||methacrylat"}"; + }; + }; + data = { + kind = "Chemical"; + short = "PMMA"; + }; + }; + polyP = { + section = "Substances"; + text = { + deu = { + tex = "${compound.format "Poly||propylen"}"; + }; + }; + data = { + kind = "Chemical"; + short = "PP"; + }; + }; + polyPy = { + section = "Substances"; + text = { + deu = { + tex = "${compound.format "Poly||pyrrol"}"; + }; + }; + description = { + deu = '' + ein leitfähiges Polymer mit ${compound.format "Pyrrol"} als Wiederholungs\-einheit + ''; + }; + data = { + kind = "Chemical"; + short = "PPy"; + }; + }; + polyS = { + section = "Substances"; + text = { + deu = { + tex = "${compound.format "Poly||styren"}"; + }; + }; + description = { + deu = '' + auch \textit{${compound.format "Poly||styrol"}} und \textit{Styropor}, + systematisch nach \acrshort{iupac}: \textit{${compound.format "Poly(1-phenyl||ethylen)"}}, + ein aus ${compound.format "Styren"} (nach \acrshort{iupac}: \textit{${compound.format "Ethenyl||benzen"}}) + durch Ketten\-polymerisation hergestellter thermo\-plastischer Kunst\-stoff + ''; + }; + data = { + kind = "Chemical"; + short = "PS"; + }; + }; + polyT = { + section = "Substances"; + text = { + deu = { + tex = "${compound.format "Poly||thiophen"}"; + }; + }; + description = { + deu = '' + ein leitfähiges Polymer mit \acrlong{thiophene} als Wiederholungs\-einheit + ''; + }; + data = { + kind = "Chemical"; + short = "PT"; + }; + }; + polyTFE = { + section = "Substances"; + text = { + deu = { + tex = "${compound.format "Poly||tetra|fluor||ethylen"}"; + }; + }; + description = { + deu = '' + Trivialname: \textit{Teflon}, + ein aus ${compound.format "Tetra||fluor||ethen"} durch Ketten\-polymerisation + hergestellter thermo\-plastischer Kunst\-stoff + ''; + }; + data = { + kind = "Chemical"; + short = "PTFE"; + }; + }; + polyVA = { + section = "Substances"; + text = { + deu = { + tex = "${compound.format "Poly||vinyl||alkohol"}"; + }; + }; + data = { + kind = "Chemical"; + short = "PVA"; + }; + }; + polyVAC = { + section = "Substances"; + text = { + deu = { + tex = "${compound.format "Poly||vinyl||acetat"}"; + }; + }; + data = { + kind = "Chemical"; + short = "PVAc"; + }; + }; + polyVC = { + section = "Substances"; + text = { + deu = { + tex = "${compound.format "Poly||vinyl||chlorid"}"; + }; + }; + description = { + deu = '' + ein aus ${compound.format "Vinyl||chlorid"} + (nach \acrshort{iupac}: \textit{${compound.format "Chlor||ethen"}}) + durch Ketten\-polymerisation hergestellter thermo\-plastischer Kunst\-stoff + ''; + }; + data = { + kind = "Chemical"; + short = "PVC"; + }; + }; +} \ No newline at end of file diff --git a/NixTeX/assets/acronyms/chemicals/silanes.nix b/NixTeX/assets/acronyms/chemicals/silanes.nix new file mode 100644 index 0000000..5243054 --- /dev/null +++ b/NixTeX/assets/acronyms/chemicals/silanes.nix @@ -0,0 +1,66 @@ +{ chemistry, ... }: +let + inherit(chemistry) compound; +in +{ + odes = { + section = "Substances"; + text = { + deu = { + tex = "${compound.format "n-Octadecyl||tri|ethoxy||silan"}"; + }; + }; + data = { + kind = "Chemical"; + short = "ODES"; + struct = '' + \cheme{\chemfig{Si(-[:-120]O-[:175]-[:-120]H_{3}C)(-[:150]O-[:85]-[:150]H_{3}C)(-[:60]O-[:-5]-[:60]CH_3)(-[:-30]-[:30]-[:-30]-[:30]-[:-30]-[:30]-[:-30]-[:30]-[:-30]-[:30]-[:-30]-[:30]-[:-30]-[:30]-[:-30]-[:30]-[:-30]-[:30]CH_{3})}}{} + ''; + }; + }; + pfotes = { + section = "Substances"; + text = { + deu = { + tex = "${compound.format "1H,1H,2H,2H-Per|fluor||octyl||tri|ethoxy||silan"}"; + }; + }; + data = { + kind = "Chemical"; + short = "PFOTES"; + struct = '' + \cheme{\chemfig{Si(-[:-120]O-[:185]-[:-120]H_{3}C)(-[:150]O-[:95]-[:150]H_{3}C)(-[:60]O-[:5]-[:60]CH_3)(-[:-30]-[:30]-[:-30](-[:-120]F)(-[:-60]F)-[:30](-[:120]F)(-[:60]F)-[:-30](-[:-120]F)(-[:-60]F)-[:30](-[:120]F)(-[:60]F)-[:-30](-[:-120]F)(-[:-60]F)-[:30](-[:30]F)(-[:-30]F)(-[:90]F))}}{} + ''; + }; + }; + tmscl = { + section = "Substances"; + text = { + deu = { + tex = "${compound.format "Chlor||tri|methyl||silan"}"; + }; + }; + data = { + kind = "Chemical"; + short = "TMSCl"; + struct = '' + \cheme{\chemfig{H_3C-Si(-[::-120]H_3C)(-[::120]H_3C)-[::0]Cl}}{} + ''; + }; + }; + tpm = { + section = "Substances"; + text = { + deu = { + tex = "${compound.format "3-(Tri|methoxy||silyl)propyl||methacrylat"}"; + }; + }; + data = { + kind = "Chemical"; + short = "TPM"; + struct = '' + \cheme{\chemfig{H_3CO-Si(-[:90]OCH_3)(-[:-90]OCH_3)(-[:0]-[:-30]-[:30]-[:-30]O-[:30](=[:90]O)-[:-30](-[:-90]CH_3)=[:30]CH_2)}}{} + ''; + }; + }; +} \ No newline at end of file diff --git a/NixTeX/assets/acronyms/chemicals/solvents.nix b/NixTeX/assets/acronyms/chemicals/solvents.nix new file mode 100644 index 0000000..63c54ac --- /dev/null +++ b/NixTeX/assets/acronyms/chemicals/solvents.nix @@ -0,0 +1,292 @@ +{ chemistry, ... }: +let + inherit(chemistry) compound; +in +{ + AcMe = { + section = "Substances"; + text = { + deu = { + tex = "${compound.format "Aceton"}"; + }; + }; + description = { + deu = '' + \ch{H3CCOCH3}, + systematisch nach \acrshort{iupac}: \textit{${compound.format "Propanon"}}, + organisches aprotisch-polares Lösungs\-mittel + ''; + }; + data = { + kind = "Chemical"; + short = ""; + }; + sortedBy = "AcMe"; + }; + CDCl3 = { + section = "Substances"; + text = { + deu = { + tex = "${compound.format "Deuteriertes Chloroform"}"; + }; + }; + description = { + deu = '' + \ch{CDCl3}, Chloroform-d\textsubscript{1}, + systematisch nach \acrshort{iupac}: \textit{${compound.format "deuteriertes Tri|chlor||methan"}}, + organisches, aprotisch-polares Lösungs\-mittel für die \acrshort{nuclearMagneticResonance}-Spektro\-metrie + ''; + }; + data = { + kind = "Chemical"; + short = "CDCl3"; + }; + }; + "1,2-dimethoxyethane" = { + section = "Substances"; + text = { + deu = { + tex = "${compound.format "Ethylen||glycol||di|methyl||ether"}"; + }; + }; + description = { + deu = '' + \ch{O(CH2)2O}, + Trivial\-name: \textit{${compound.format "1,2-Di|methoxy||ethan"}}, + organisches aprotisch-polares Lösungs\-mittel + ''; + }; + data = { + kind = "Chemical"; + short = "1,2-DME"; + }; + }; + Et2O = { + section = "Substances"; + text = { + deu = { + tex = "${compound.format "Di|ethyl||ether"}"; + }; + }; + description = { + deu = '' + \ch{(H3CCH2)2O}, organisches aprotisch-polares Lösungs\-mittel + ''; + }; + data = { + kind = "Chemical"; + short = "2O"; + struct = '' + \cheme{\chemfig{H_3C-[:30]-[:-30]O-[:30]-[:-30]CH_3}}{} + ''; + }; + }; + EtOAc = { + section = "Substances"; + text = { + deu = { + tex = "${compound.format "Essig||säure||ethyl||ester"}"; + }; + }; + description = { + deu = '' + \ch{H3COOCH2CH3}, + nach \acrshort{iupac}: \textit{${compound.format "Ethyl||acetat"}} \acrshort{beziehungsweise} + systematisch: \textit{${compound.format "Ethyl||ethanoat"}}, + organisches aprotisch-polares Lösungs\-mittel + ''; + }; + data = { + kind = "Chemical"; + short = "O"; + }; + sortedBy = "EtOAc"; + }; + EtOH = { + section = "Substances"; + text = { + deu = { + tex = "${compound.format "Ethanol"}"; + }; + }; + description = { + deu = '' + \ch{H3CCH2OH}, organisches protisch-polares Lösungs\-mittel + ''; + }; + data = { + kind = "Chemical"; + short = "OH"; + struct = '' + \cheme{\chemfig{H_3C-[:30]-[:-30]OH}}{} + ''; + }; + }; + MeOH = { + section = "Substances"; + text = { + deu = { + tex = "${compound.format "Methanol"}"; + }; + }; + description = { + deu = '' + \ch{H3COH}, organisches protisch-polares Lösungs\-mittel + ''; + }; + data = { + kind = "Chemical"; + short = "OH"; + }; + }; + dichloromethane = { + section = "Substances"; + text = { + deu = { + tex = "${compound.format "Di|chlor||methan"}"; + }; + }; + description = { + deu = '' + \ch{CH2Cl2}, + Trivial\-name: \textit{${compound.format "Methylen||chlorid"}}, + organisches aprotisch-polares Lösungs\-mittel + ''; + }; + data = { + kind = "Chemical"; + short = "DCM"; + }; + }; + dmf = { + section = "Substances"; + text = { + deu = { + tex = "${compound.format "Di|methyl||formamid"}"; + }; + }; + description = { + deu = '' + \ch{(H3C)2NCHO}, organisches aprotisch-polares Lösungs\-mittel + ''; + }; + data = { + kind = "Chemical"; + short = "DMF"; + }; + }; + dmso = { + section = "Substances"; + text = { + deu = { + tex = "${compound.format "Di|methyl||sulfoxid"}"; + }; + }; + description = { + deu = '' + \ch{(H3C)2SO}, organisches aprotisch-polares Lösungs\-mittel + ''; + }; + data = { + kind = "Chemical"; + short = "DMSO"; + }; + }; + isoPropylOH = { + section = "Substances"; + text = { + deu = { + tex = "${compound.format "Iso|propyl||alkohol"}"; + }; + }; + description = { + deu = '' + \ch{H3C(CHOH)CH3}, + systematisch nach \acrshort{iupac}: \textit{${compound.format "Propan-2-ol"}}, + organisches protisch-polares Lösungs\-mittel + ''; + }; + data = { + kind = "Chemical"; + short = "OH"; + struct = '' + \cheme{\chemfig{H_3C-[:30](-[:30]OH)-[:-30]CH_3}}{} + ''; + }; + }; + orthoDichloroBenzene = { + section = "Substances"; + text = { + deu = { + tex = "${compound.format "1,2-Di|chlor||benzen"}"; + }; + }; + description = { + deu = '' + ${compound.format "o-Di|chlor||benzol"} + ''; + }; + data = { + kind = "Chemical"; + short = "ODCB"; + }; + }; + petrolether = { + section = "Substances"; + text = { + deu = { + tex = "${compound.format "Petrol||ether"}"; + }; + }; + description = { + deu = '' + Gemisch verschieder gesättigter ${compound.format "Kohlen||wasserstoff|e"} mit niedrigem Siedepunkt, + \acrshort{forExample} ${compound.format "Hexan|e"} und ${compound.format "Petan|e"}, + kein Ether (\ch{ROR}) im chemischen Sinne + ''; + }; + data = { + kind = "Chemical"; + short = "PE"; + }; + }; + tetrahydrofuran = { + section = "Substances"; + text = { + deu = { + tex = "${compound.format "Tetra|hydro||furan"}"; + }; + }; + description = { + deu = '' + \ch{C4H8O}, organisches aprotisch-polares Lösungs\-mittel + ''; + }; + data = { + kind = "Chemical"; + short = "THF"; + struct = '' + \cheme{\chemfig{*5(--O---)}}{} + ''; + }; + }; + trichlormethane = { + section = "Substances"; + text = { + deu = { + tex = "${compound.format "Chloroform"}"; + }; + }; + description = { + deu = '' + \ch{CHCl3}, + systematisch nach \acrshort{iupac}: \textit{${compound.format "Tri|chlor||methan"}}, + organisches aprotisch-polares Lösungs\-mittel + ''; + }; + data = { + kind = "Chemical"; + short = "CHCl3"; + }; + }; +} \ No newline at end of file diff --git a/NixTeX/assets/acronyms/constants.nix b/NixTeX/assets/acronyms/constants.nix new file mode 100644 index 0000000..8087bce --- /dev/null +++ b/NixTeX/assets/acronyms/constants.nix @@ -0,0 +1,129 @@ +{ physical, ... }: +let + inherit(physical) formatValue; +in +{ + boltzmannConstant = { + section = "Variables"; + text = { + deu = "\\person{Boltzmann}-Konstante"; + }; + description = { + deu = '' + ''${k_B = \Physical{1.380649}{-23}{joule}{}\Unit{kelvin}{-1}}$, + benannt nach dem österreichischen Physiker \person (1844–1906) + ''; + }; + data = { + kind = "Math"; + short = "k_B"; + value = 1.380649e-23; + unit = [ "joule" { name = "kelvin"; exp = -1; } ]; + }; + }; + elementaryCharge = { + section = "Variables"; + text = { + deu = "Elementar\\-ladung"; + }; + description = { + deu = '' + ''${e = \Physical{1.602176634}{-19}{coulomb}{}}$ + ''; + }; + data = { + kind = "Math"; + short = "e"; + value = 1.602176634e-19; + unit = "coulomb"; + }; + }; + faradayConstant = { + section = "Variables"; + text = { + deu = "\\person{Faraday}-Konstante"; + }; + description = { + deu = '' + ''${F = \Physical{9.648533289}{4}{ampere}{}\Unit{second}{}\Unit{mol}{-1}}$, + benannt nach dem englischen Experimental\-physiker \person{Michael Faraday} (1791–1867) + ''; + }; + data = { + kind = "Math"; + short = "F"; + value = 9.648533289e4; + unit = [ "ampere" { name = "mol"; exp = -1; } ]; + }; + }; + gasConstant = { + section = "Variables"; + text = { + deu = "Gas\\-konstante"; + }; + description = { + deu = '' + ''${R~=~\Physical{8.3144598}{}{joule}{}\Unit{mol}{-1}\Unit{kelvin}{-1}}$ + ''; + }; + data = { + kind = "Math"; + short = "R"; + value = 8.3144598; + unit = [ "joule" { name = "mol"; exp = -1; } { name = "kelvin"; exp = -1; } ]; + }; + }; + planckConstant = { + section = "Variables"; + text = { + deu = "\\person{Planck}sches Wirkungs\\-quantum"; + }; + description = { + deu = '' + ''${h = \Physical{6.62607015}{-34}{joule}{}\Unit{second}{}}$, + benannt nach dem deutschen Physiker \person{Max Planck} (1858–1947) + ''; + }; + data = { + kind = "Math"; + short = "h"; + value = 6.62607015e-34; + unit = [ "joule" "second" ]; + }; + }; + roomTemperature = { + section = "Variables"; + text = { + deu = "Raum\\-temperatur"; + }; + description = { + deu = '' + Eine unspezifizierte Temperatur von ${formatValue { from = 20; till = 30; } "celsius"}, + welche bei Reaktionen erreicht wird, + wenn weder aktiv gekühlt noch aktiv erwärmt wird + ''; + }; + data = { + kind = "Default"; + short = "RT"; + }; + }; + speedOfLight = { + section = "Variables"; + text = { + deu = "Licht\\-geschwindigkeit"; + }; + description = { + deu = '' + ''${c = \Physical{299792458}{}{metre}{}\Unit{second}{-1}}$, + Geschwindigkeit elektro\-magnetischer Wellen im Vakuum + ''; + }; + data = { + kind = "Math"; + short = "c"; + value = 299792458; + unit = [ "metre" { name = "second"; exp = -1; } ]; + }; + }; +} \ No newline at end of file diff --git a/NixTeX/assets/acronyms/default.nix b/NixTeX/assets/acronyms/default.nix new file mode 100644 index 0000000..e524fae --- /dev/null +++ b/NixTeX/assets/acronyms/default.nix @@ -0,0 +1,144 @@ +{ core, chemistry, glossaries, ... } @ libs: + let + inherit(core) library; + inherit(chemistry) compound; + inherit(glossaries) acronyms; + inherit(acronyms) Miscellaneous; + in + { + adhd = Miscellaneous { + description = { + deu = '' + Verhaltens- und emotionalen Störungen mit Beginn in der Kindheit und Jugend, + welche sich durch Probleme mit Aufmerksamkeit, Impulsivität, Selbstregulation und Motivation äußert. + ''; + eng = ""; + }; + long = { + deu = "Aufmerksamkeits\\-defizit-/Hyper\\-aktivitäts\\-störung"; + }; + short = { + deu = "ADHS"; + eng = "ADHD"; + }; + }; + chemicalVaporDeposition = { + section = "Miscellaneous"; + text = { + deu = "Chemische Gas\\-phasen\\-abscheidung"; + }; + description = { + deu = '' + von \acrshort{english} \Q{Chemical Vapor Deposition}, + Beschichtungs\-verfahren, + bei denen Material aus der Gas\-phase auf eine Oberfläche durch eine chemische Reaktion aufgetragen wird + ''; + }; + data = { + kind = "Default"; + short = "CVD"; + }; + }; + concentrated = { + section = "Miscellaneous"; + text = { + deu = "konzentriert"; + }; + description = { + deu = '' + Unverdünnte Lösung einer Substanz, \acrshort{forExample} Säure + ''; + }; + data = { + kind = "Default"; + short = "konz."; + }; + }; + diluted = { + section = "Miscellaneous"; + text = { + deu = "verdünnt"; + }; + description = { + deu = '' + Nicht-\acrlong{concentrated}e Lösung einer Substanz, \acrshort{forExample} Base + ''; + }; + data = { + kind = "Default"; + short = "verd."; + }; + }; + quantitative = { + section = "Miscellaneous"; + text = { + deu = "quantitativ"; + }; + description = { + deu = '' + Vollständiger oder nahezu vollständiger Umsatz + ''; + }; + data = { + kind = "Default"; + short = "quant."; + }; + }; + saturated = { + section = "Miscellaneous"; + text = { + deu = "gesättigt"; + }; + description = { + deu = '' + Maximal unverdünnte Lösung einer Substanz, \acrshort{forExample} Sole + ''; + }; + data = { + kind = "Default"; + short = "ges."; + }; + }; + selfAssembledMonolayer = { + section = "Miscellaneous"; + text = { + deu = "Selbst\\-organisierende Mono\\-schicht"; + eng = "Self-Assembled Mono\\-layer"; + }; + description = { + deu = '' + ''; + }; + data = { + kind = "Default"; + short = "SAM"; + }; + }; + quaternary = { + section = "Miscellaneous"; + text = { + deu = "Quartär"; + }; + description = { + deu = '' + Atom mit vier gebundenen Resten, welche kein ${compound.format "Wasserstoff"} sind, + \acrshort{forExample} \ch{CR4} und \ch{N+R4} + ''; + }; + data = { + kind = "Default"; + short = "quart."; + }; + }; + } + // library.import ./analytics libs + // library.import ./constants.nix libs + // library.import ./chemicals libs + // library.import ./electronics.nix libs + // library.import ./general.nix libs + // library.import ./german.nix libs + // library.import ./physicals.nix libs + // library.import ./prefixes.nix libs + // library.import ./quantum.nix libs + // library.import ./standards.nix libs + // library.import ./units.nix libs diff --git a/NixTeX/assets/acronyms/electronics.nix b/NixTeX/assets/acronyms/electronics.nix new file mode 100644 index 0000000..c4b770f --- /dev/null +++ b/NixTeX/assets/acronyms/electronics.nix @@ -0,0 +1,53 @@ +{ ... }: +{ + organicFET = { + section = "Electronics"; + text = { + deu = "Organischer Feld\\-effekt\\-transistor"; + }; + data = { + kind = "Default"; + short = "OFET"; + }; + }; + organicLED = { + section = "Electronics"; + text = { + deu = "Organische Leucht\\-diode"; + }; + description = { + deu = '' + von \acrshort{english} \Q{Organic Light-Emitting Diode} + ''; + }; + data = { + kind = "Default"; + short = "OLED"; + }; + }; + organicPV = { + section = "Electronics"; + text = { + deu = "Organische Solar\\-zelle"; + }; + description = { + deu = '' + von \acrshort{english} \Q{Organic PhotoVoltaic} + ''; + }; + data = { + kind = "Default"; + short = "OPV"; + }; + }; + organicTEG = { + section = "Electronics"; + text = { + deu = "Organischer thermo\\-elektrischer Generator"; + }; + data = { + kind = "Default"; + short = "OTEG"; + }; + }; +} \ No newline at end of file diff --git a/NixTeX/assets/acronyms/general.nix b/NixTeX/assets/acronyms/general.nix new file mode 100644 index 0000000..5e669f8 --- /dev/null +++ b/NixTeX/assets/acronyms/general.nix @@ -0,0 +1,279 @@ +{ ... }: +{ + english = { + section = "General"; + text = { + deu = "englisch"; + }; + description = { + deu = '' + in englischer Sprache + ''; + }; + data = { + kind = "Default"; + short = "eng."; + }; + }; + etAlia = { + section = "General"; + text = { + deu = "und andere"; + eng = "and others"; + }; + description = { + deu = '' + von \acrshort{latin} \Q{et alii} (m), \Q{et aliae} (f) \acrshort{beziehungsweise} \Q{et alia} (n) + ''; + eng = '' + from \acrshort{latin} \Q{et alii} (m), \Q{et aliae} (f) \acrshort{beziehungsweise} \Q{et alia} (n) + ''; + }; + data = { + kind = "Default"; + short = "et al."; + }; + }; + etc = { + section = "General"; + text = { + deu = "und die Übrigen"; + eng = "and the other things"; + }; + description = { + deu = '' + von \acrshort{latin} \Q{et cetera} + ''; + eng = '' + from \acrshort{latin} \Q{et cetera} + ''; + }; + data = { + kind = "Default"; + short = "etc."; + }; + }; + forExample = { + section = "General"; + text = { + deu = "zum Beispiel"; + eng = "for example"; + }; + description = { + eng = '' + from \acrshort{latin} \Q{exempli gratia} + ''; + }; + data = { + kind = "Default"; + short = { + deu = "z.\\,B."; + eng = "e.g."; + }; + }; + sortedBy = { + deu = "z. B."; + eng = "e.g."; + }; + }; + french = { + section = "General"; + text = { + deu = "französisch"; + }; + description = { + deu = '' + in französischer Sprache + ''; + }; + data = { + kind = "Default"; + short = "frz."; + }; + }; + greek = { + section = "General"; + text = { + deu = "griechisch"; + }; + description = { + deu = '' + in griechischer Sprache + ''; + }; + data = { + kind = "Default"; + short = "gr."; + }; + }; + hebrew = { + section = "General"; + text = { + deu = "hebräisch"; + }; + description = { + deu = '' + Ivrit + ''; + }; + data = { + kind = "Default"; + short = "heb."; + }; + }; + inSilico = { + section = "General"; + text = { + deu = "in Computersimulationen"; + }; + description = { + deu = '' + \acrshort{latin} für \Q{im Silicium} + ''; + }; + data = { + kind = "Default"; + short = "\\textit{in\\,silico}"; + }; + sortedBy = "in silico"; + }; + inSitu = { + section = "General"; + text = { + deu = "im selben Reaktionsgefäß"; + }; + description = { + deu = '' + \acrshort{latin} für \Q{am Ort} + ''; + }; + data = { + kind = "Default"; + short = "\\textit{in\\,situ}"; + }; + sortedBy = "in situ"; + }; + inUtero = { + section = "General"; + text = { + deu = "im Uterus"; + }; + description = { + deu = '' + \acrshort{latin} für \Q{in der Gebärmutter} + ''; + }; + data = { + kind = "Default"; + short = "\\textit{in\\,utero}"; + }; + sortedBy = "in utero"; + }; + inVitro = { + section = "General"; + text = { + deu = "außerhalb eines Organismus"; + }; + description = { + deu = '' + \acrshort{latin} für \Q{im Glas} + ''; + }; + data = { + kind = "Default"; + short = "\\textit{in\\,vitro}"; + }; + sortedBy = "in vitro"; + }; + inVivo = { + section = "General"; + text = { + deu = "in einem Organismus"; + }; + description = { + deu = '' + \acrshort{latin} für \Q{im Lebendigen} + ''; + }; + data = { + kind = "Default"; + short = "\\textit{in\\,vivo}"; + }; + sortedBy = "in vivo"; + }; + latin = { + section = "General"; + text = { + deu = "lateinisch"; + }; + data = { + kind = "Default"; + short = "lat."; + }; + }; + literature = { + section = "General"; + text = { + deu = "Literatur"; + }; + description = { + deu = '' + Literatur\-wert + ''; + }; + data = { + kind = "Default"; + short = "Lit."; + }; + }; + partially = { + section = "General"; + text = { + deu = "zum Teil"; + eng = "partially"; + }; + data = { + kind = "Default"; + short = "z.\\,T."; + }; + sortedBy = "z. T."; + }; + thatMeans = { + section = "General"; + text = { + deu = "das heißt"; + eng = "that is to say"; + }; + description = { + eng = '' + from \acrshort{latin} \Q{id est} + ''; + }; + data = { + kind = "Default"; + short = { + deu = "d.\\,h."; + eng = "i.e."; + }; + }; + sortedBy = { + deu = "d. h."; + eng = "i.e."; + }; + }; + versus = { + section = "General"; + text = { + deu = "gegenüber"; + }; + description = { + deu = '' + von \acrshort{latin} \Q{versus} + ''; + }; + data = { + kind = "Default"; + short = "vs."; + }; + }; +} \ No newline at end of file diff --git a/NixTeX/assets/acronyms/german.nix b/NixTeX/assets/acronyms/german.nix new file mode 100644 index 0000000..73f28cc --- /dev/null +++ b/NixTeX/assets/acronyms/german.nix @@ -0,0 +1,65 @@ +{ ... }: +{ + beziehungsweise = { + section = "General"; + text = { + deu = "beziehungs\\-weise"; + }; + data = { + kind = "Default"; + short = "bzw."; + }; + }; + undSoFort = { + section = "General"; + text = { + deu = "Und so fort"; + }; + data = { + kind = "Default"; + short = "usf."; + }; + }; + undSoWeiter = { + section = "General"; + text = { + deu = "Und so weiter"; + }; + data = { + kind = "Default"; + short = "usw."; + }; + }; + unterAnderem = { + section = "General"; + text = { + deu = "unter anderem"; + }; + data = { + kind = "Default"; + short = "u.\\,a."; + }; + sortedBy = "u. a."; + }; + "unterUmständen" = { + section = "General"; + text = { + deu = "unter Umständen"; + }; + data = { + kind = "Default"; + short = "u.\\,U."; + }; + sortedBy = "u. U."; + }; + vergleiche = { + section = "General"; + text = { + deu = "vergleiche"; + }; + data = { + kind = "Default"; + short = "vergl."; + }; + }; +} \ No newline at end of file diff --git a/NixTeX/assets/acronyms/physicals.nix b/NixTeX/assets/acronyms/physicals.nix new file mode 100644 index 0000000..9aba32b --- /dev/null +++ b/NixTeX/assets/acronyms/physicals.nix @@ -0,0 +1,676 @@ +{ chemistry, ... }: +let + inherit(chemistry) compound; +in +{ + absorptionCoefficient = { + section = "Variables"; + text = { + deu = "Absorptions\\-koeffizient"; + }; + description = { + deu = '' + von \acrshort{latin} \textit{extinctio} \Q{Auslöschung}, + auch \Q{Dämpfungs\-konstante} oder \Q{linearer Schwächungs\-koeffizient}, + in \Newunit{metre}{-1}, + Maß für die Verringerung der Intensität elektro\-magnetischer Strahlung beim Durchgang durch ein Medium + ''; + }; + data = { + kind = "Math"; + short = "\\alpha"; + }; + sortedBy = "α"; + }; + absorptionEdge = { + section = "Variables"; + text = { + deu = "Absorptions\\-kante"; + }; + description = { + deu = '' + in \Newunit{nanometre}{} + ''; + }; + data = { + kind = "Math"; + short = "\\lambda_{min}"; + }; + sortedBy = "λmin"; + }; + absorptionMaximum = { + section = "Variables"; + text = { + deu = "Wellen\\-länge des Absorptions\\-maximums"; + }; + description = { + deu = '' + in \Newunit{nanometre}{} + ''; + }; + data = { + kind = "Math"; + short = "\\lambda_{max}"; + }; + sortedBy = "λmax"; + }; + activationEnergy = { + section = "Variables"; + text = { + deu = "Aktivierungs\\-energie"; + }; + description = { + deu = '' + in \Newunit{joule}{} + ''; + }; + data = { + kind = "Math"; + short = "E_A"; + }; + }; + bandGap = { + section = "Variables"; + text = { + deu = "Band\\-lücke"; + }; + description = { + deu = '' + \acrshort{english} auch \Q{Band-Gap}, in \Newunit{joule}{}, + energetische Differenz zwischen Valenz- und Leitungs\-band eines Fest\-körpers + ''; + }; + data = { + kind = "Math"; + short = "E_g"; + }; + }; + boilingTemperature = { + section = "Variables"; + text = { + deu = "Siede\\-punkt"; + }; + description = { + deu = '' + Koch\-punkt, genauer: Siede\-bereich; Temperatur, + ab der eine Flüssigkeit in den gas\-förmigen Aggregat\-zustand übergeht, + in ''${\Newunit{celsius}{}}$ + ''; + }; + data = { + kind = "Default"; + short = "Kp."; + }; + }; + carnotFactor = { + section = "Variables"; + text = { + deu = "\\person{Carnot}-Wirkungs\\-grad"; + }; + description = { + deu = '' + Maximaler Wirkungs\-grad bei der Umwandlung von thermischer in mechanische Energie, + ''${\acrshort{carnotFactor} = 1-\frac{T_k}{T_w}}$, + benannt nach dem französischen Physiker \person[carnot]{Nicolas Léonard Sadi Carnot} + ''; + }; + data = { + kind = "Math"; + short = "\\eta_C"; + }; + sortedBy = "ηC"; + }; + catalytLoading = { + section = "Variables"; + text = { + deu = "Katalysator\\-beladung"; + }; + description = { + deu = '' + Molares Verhätlsnis von Katalysator zu Substrat + ''; + }; + data = { + kind = "Math"; + short = "R"; + }; + }; + coefficientOfDetermination = { + section = "Variables"; + text = { + deu = "Determinations\\-koeffizient"; + }; + description = { + deu = '' + auch \textit{Bestimmtheits\-maß}, statistische Kenn\-zahl der Anpassungs\-güte einer Regression: + je näher dieser Wert an Eins liegt, desto besser passt ein gewähltes Modell zu den Mess\-werten + ''; + }; + data = { + kind = "Math"; + short = "R^2"; + }; + sortedBy = "R²"; + }; + conversion = { + section = "Variables"; + text = { + deu = "Umsatz"; + }; + description = { + deu = '' + in \Newunit{percent}{} + ''; + }; + data = { + kind = "Math"; + short = "U"; + }; + }; + couplingConstant = { + section = "Variables"; + text = { + deu = "Kopplungs\\-konstante"; + }; + description = { + deu = '' + in \Newunit{hertz}{} + ''; + }; + data = { + kind = "Math"; + short = "J"; + }; + }; + currentDensity = { + section = "Variables"; + text = { + deu = "Elektrische Strom\\-dichte"; + }; + description = { + deu = '' + in \Newunit{microampere}{}\Unit{centimetre}{-2} + ''; + }; + data = { + kind = "Math"; + short = "\\vec{J}"; + }; + sortedBy = "J"; + }; + dcCurrent = { + section = "Variables"; + text = { + deu = "Elektrische Gleich\\-strom"; + }; + description = { + deu = '' + in \Newunit{ampere}{}, Ladungsfluss in einem Leiter + ''; + }; + data = { + kind = "Math"; + short = "I"; + }; + }; + dcVoltage = { + section = "Variables"; + text = { + deu = "Elektrische Gleich\\-spannung"; + }; + description = { + deu = '' + in \Newunit{volt}{}, Differenz zweier elektrischer Potentiale + ''; + }; + data = { + kind = "Math"; + short = "U"; + }; + }; + decompositionTemperature = { + section = "Variables"; + text = { + deu = "Zersetzungs\\-punkt"; + }; + description = { + deu = '' + Temperatur, oberhalb der sich eine Substanz zu anderen Stoffen zersetzt, in ''${\Newunit{celsius}{}}$ + ''; + }; + data = { + kind = "Default"; + short = "Zers."; + }; + }; + degreeOfPolymerisation = { + section = "Variables"; + text = { + deu = "Polymerisatios\\-grad"; + }; + description = { + deu = '' + Verhältnis aus dem \acrfull{numberMeanMolarMass} und + der \acrtext[molarMass]{molaren Masse} ($\acrshort{molarMass}_{n}$) der Wiederholungs\-einheit/Monomer + ''; + }; + data = { + kind = "Math"; + short = "\\bar{X}_n"; + }; + sortedBy = "Xn"; + }; + diameter = { + section = "Variables"; + text = { + deu = "Durchmesser"; + eng = "diameter"; + }; + description = { + deu = '' + größtmögliche Abstand zweier Punkte der Kreis\-linie oder der Kugel\-oberflächen\-punkte + ''; + }; + data = { + kind = "Default"; + short = "ø"; + }; + sortedBy = ""; + }; + diastereomericExcess = { + section = "Variables"; + text = { + deu = "Diastereomeren\\-überschuss"; + }; + description = { + deu = '' + von \acrshort{english} \Q{Diastereomeric Excess}, in \Newunit{percent}{} + ''; + }; + data = { + kind = "Math"; + short = "de"; + }; + }; + electricConductivity = { + section = "Variables"; + text = { + deu = "Elektrische Leitfähigkeit"; + }; + description = { + deu = '' + in \Newunit{siemens}{}\Unit{metre}{-1} + ''; + }; + data = { + kind = "Math"; + short = "\\sigma"; + }; + sortedBy = "σ"; + }; + electrodePotential = { + section = "Variables"; + text = { + deu = "Elektroden\\-potential"; + }; + description = { + deu = '' + in \Newunit{volt}{} + ''; + }; + data = { + kind = "Math"; + short = "E"; + }; + }; + enantiomericExcess = { + section = "Variables"; + text = { + deu = "Enantiomeren\\-überschuss"; + }; + description = { + deu = '' + von \acrshort{english} \Q{Enantiomeric Excess}, in \Newunit{percent}{} + ''; + }; + data = { + kind = "Math"; + short = "ee"; + }; + }; + extinctionCoefficient = { + section = "Variables"; + text = { + deu = "Extinktions\\-koeffizient"; + }; + description = { + deu = '' + von \acrshort{latin} \textit{extinctio} \Q{Auslöschung}, auch \Q{molarer Absorptionskoeffizient}, + in \Newunit{litre}{}\Unit{mol}{-1}\Unit{centimetre}{-1}, + Verhältnis von Extinktion zum Produkt aus Stoff\-mengen\-konzentration und Schicht\-dicke + ''; + }; + data = { + kind = "Math"; + short = "\\varepsilon"; + }; + sortedBy = "ε"; + }; + massMeanMolarMass = { + section = "Variables"; + text = { + deu = "Gewichts\\-mittel der molaren Masse"; + }; + description = { + deu = '' + in \Newunit{gram}{}\Unit{mol}{-1} + ''; + }; + data = { + kind = "Math"; + short = "M_\\omega"; + }; + }; + massToChargeRatio = { + section = "Variables"; + text = { + deu = "Masse-zu-Ladungs-Verhältnis"; + eng = "Mass-to-Charge Ratio"; + }; + description = { + deu = '' + in \Newunit{kilogram}{}\Unit{coulomb}{-1} oder \Newunit{dalton}{}\Unit{elementaryCharge}{-1}, + Verhältnis der Masse eines Teilchen zu seiner Ladung, + eine Größe der \acrlong{massSpectrometry} + ''; + }; + data = { + kind = "Default"; + short = "\\textit{m/z}"; + }; + }; + meltingTemperature = { + section = "Variables"; + text = { + deu = "Schmelz\\-punkt"; + }; + description = { + deu = '' + von \acrshort{english} \Q{Fusion Point}, genauer: Schmelz\-bereich; Temperatur, + ab der ein Fest\-stoff in den flüssigen Aggregat\-zustand übergeht + ''; + }; + data = { + kind = "Default"; + short = "Fp."; + }; + }; + molarMass = { + section = "Variables"; + text = { + deu = "Molare Masse"; + }; + description = { + deu = '' + Masse eines \acrlong{mol}s einer Substanz + ''; + }; + data = { + kind = "Math"; + short = "M"; + }; + }; + nD20 = { + section = "Variables"; + text = { + deu = "Brechungs\\-index"; + }; + description = { + deu = '' + bei ''${\Physical{20}{}{celsius}{}}$ und + einer Wellen\-länge von ''${\Physical{589}{}{nanometre}{}}$ (Natrium-D-Linie + ''; + }; + data = { + kind = "Math"; + short = "n^{20}_D"; + }; + sortedBy = "n20D"; + }; + numberMeanMolarMass = { + section = "Variables"; + text = { + deu = "Zahlen\\-mittel der molaren Masse"; + }; + description = { + deu = '' + in \Newunit{gram}{}\Unit{mol}{-1} + ''; + }; + data = { + kind = "Math"; + short = "M_n"; + }; + }; + pH = { + section = "Variables"; + text = { + deu = "Potential des ${compound.format "Wasserstoffes"}"; + }; + description = { + deu = '' + von \acrshort{latin} \Q{potentia hydrogenii}, + negativer dekadischer Logarithmus der Konzentration von ${compound.format "Oxonium||ionen"} (\ch{H+.'n'}\,Solvent) + ''; + }; + data = { + kind = "Default"; + short = "pH"; + }; + }; + polyDispersity = { + section = "Variables"; + text = { + deu = "Poly\\-dispersität"; + }; + description = { + deu = '' + von \acrshort{latin} \textit{dispergere} \Q{zerstreuen}, + Verhältnis von \acrlong{massMeanMolarMass} zum \acrlong{numberMeanMolarMass} + ''; + }; + data = { + kind = "Default"; + short = "Đ"; + }; + sortedBy = "D"; + }; + ratioOfFronts = { + section = "Variables"; + text = { + deu = "Retentions\\-faktor"; + }; + description = { + deu = '' + Verhältnis von Lauf\-strecke des Analyten zur Lauf\-strecke des Lauf\-mittels + ''; + }; + data = { + kind = "Math"; + short = "R_f"; + }; + sortedBy = "Rf"; + }; + reactionRate = { + section = "Variables"; + text = { + deu = "Reaktions\\-geschwindigkeit"; + }; + description = { + deu = '' + ''${\nu = -\frac{d[Edukt]}{dt}}$ + ''; + }; + data = { + kind = "Math"; + short = "\\nu"; + }; + sortedBy = "ν"; + }; + specialViscosity = { + section = "Variables"; + text = { + deu = "Spezifische Viskosität"; + }; + description = { + }; + data = { + kind = "Math"; + short = "\\eta_{sp}"; + }; + sortedBy = "η"; + }; + sublimationTemperature = { + section = "Variables"; + text = { + deu = "Sublimations\\-punkt"; + }; + description = { + deu = '' + genauer: Sublimations\-bereich; Temperatur, + ab der eine Fest\-stoff in den gas\-förmigen Aggregat\-zustand übergeht + ''; + }; + data = { + kind = "Default"; + short = "Sp."; + }; + }; + tempDegree = { + section = "Variables"; + text = { + deu = "Temperatur"; + }; + description = { + deu = '' + in \Newunit{celsius}{}, veraltet: empirische Temperatur + ''; + }; + data = { + kind = "Math"; + short = "\\vartheta"; + }; + sortedBy = "ϑ"; + }; + temperature = { + section = "Variables"; + text = { + deu = "Absolute Temperatur"; + }; + description = { + deu = '' + in \Newunit{kelvin}{} + ''; + }; + data = { + kind = "Math"; + short = "T"; + }; + }; + time = { + section = "Variables"; + text = { + deu = "Zeit"; + }; + description = { + deu = '' + in \Newunit{second}{}, \Newunit{minute}{}, \Newunit{hour}{}, \acrshort{etc}, von \acrshort{english} \Q{Time} + ''; + }; + data = { + kind = "Math"; + short = "t"; + }; + }; + turnoverFrequency = { + section = "Variables"; + text = { + deu = "Wechsel\\-zahl"; + }; + description = { + deu = '' + in \Newunit{second}{-1}, von \acrshort{english} \Q{Turnover Frequency} + ''; + }; + data = { + kind = "Math"; + short = "TOF"; + }; + }; + turnoverNumber = { + section = "Variables"; + text = { + deu = "katalytische Produktivität"; + }; + description = { + deu = '' + dimensionslos, von \acrshort{english} \Q{Turnover Number} + ''; + }; + data = { + kind = "Math"; + short = "TON"; + }; + }; + waveFrequency = { + section = "Variables"; + text = { + deu = "Wellen\\-frequenz"; + }; + description = { + deu = '' + in \Newunit{hertz}{}, Quotient aus \acrlong{speedOfLight} und \acrlong{waveLength}: + ''${\nu = \frac{\acrshort{speedOfLight}}{\acrshort{waveLength}}}$ + ''; + }; + data = { + kind = "Math"; + short = "\\nu"; + }; + sortedBy = "ν"; + }; + waveLength = { + section = "Variables"; + text = { + deu = "Wellen\\-länge"; + }; + description = { + deu = '' + in \Newunit{nanometre}{-1}, Distanz zweier Punkte gleicher Phase, + \acrshort{forExample} Wellen\-berg zu Wellen\-berg + ''; + }; + data = { + kind = "Math"; + short = "\\lambda"; + }; + sortedBy = "λ"; + }; + waveNumber = { + section = "Variables"; + text = { + deu = "Wellen\\-zahl"; + }; + description = { + deu = '' + in \Newunit{cm-1}{}, Kehr\-wert der \acrlong{waveLength}: + ''${\widetilde{\nu} = \acrshort{waveLength}^{-1}}$ + ''; + }; + data = { + kind = "Math"; + short = "\\widetilde{\\nu}"; + }; + sortedBy = "ν"; + }; +} \ No newline at end of file diff --git a/NixTeX/assets/acronyms/prefixes.nix b/NixTeX/assets/acronyms/prefixes.nix new file mode 100644 index 0000000..058f990 --- /dev/null +++ b/NixTeX/assets/acronyms/prefixes.nix @@ -0,0 +1,91 @@ +{ glossaries, ... }: +let +# inherit(glossaries.acronyms) Prefix; +in +{ + centi = { + section = "Prefixes"; + text = { + deu = "Hunderstel"; + }; + description = { + deu = '' + c-, Faktor: ''${10^{-2}}$, von \acrshort{latin} \Q{centum}: hundert + ''; + }; + data = { + kind = "Default"; + short = "c"; + }; + sortedBy = -2; + bookmarkAs = "centi-"; + }; + kilo = { + section = "Prefixes"; + text = { + deu = "Tausend"; + }; + description = { + deu = '' + k-, Faktor: ''${10^{+3}}$, von \acrshort{greek} \Q{χίλιοι}: Tausend + ''; + }; + data = { + kind = "Default"; + short = "k"; + }; + sortedBy = 3; + bookmarkAs = "kilo-"; + }; + micro = { + section = "Prefixes"; + text = { + deu = "Millionstel"; + }; + description = { + deu = '' + µ-, Faktor: ''${10^{-6}}$, von \acrshort{greek} \Q{μικρός}: klein + ''; + }; + data = { + kind = "Default"; + short = "µ"; + }; + sortedBy = -6; + bookmarkAs = "micro-"; + }; + milli = { + section = "Prefixes"; + text = { + deu = "Tausendstel"; + }; + description = { + deu = '' + m-, Faktor: ''${10^{-3}}$, von \acrshort{latin} \Q{mille}: tausend + ''; + }; + data = { + kind = "Default"; + short = "m"; + }; + sortedBy = -3; + bookmarkAs = "milli-"; + }; + nano = { + section = "Prefixes"; + text = { + deu = "Milliardstel"; + }; + description = { + deu = '' + n-, Faktor: ''${10^{-9}}$, von \acrshort{greek} \Q{νᾶνος}: Zwerg + ''; + }; + data = { + kind = "Default"; + short = "n"; + }; + sortedBy = -9; + bookmarkAs = "nano-"; + }; +} \ No newline at end of file diff --git a/NixTeX/assets/acronyms/quantum.nix b/NixTeX/assets/acronyms/quantum.nix new file mode 100644 index 0000000..d341ecc --- /dev/null +++ b/NixTeX/assets/acronyms/quantum.nix @@ -0,0 +1,57 @@ +{ ... }: +{ + highestOccupiedMO = { + section = "Quantum"; + text = { + deu = "Höchste besetzte Molekül\\-orbital"; + }; + description = { + }; + data = { + kind = "Default"; + short = "HOMO"; + }; + }; + lowestUnoccupiedMO = { + section = "Quantum"; + text = { + deu = "Niedrigste unbesetzte Molekül\\-orbital"; + }; + description = { + }; + data = { + kind = "Default"; + short = "LUMO"; + }; + }; + psept = { + section = "Quantum"; + text = { + deu = "Polyeder\\-skelett\\-elektronen\\-paar\\-theorie"; + }; + description = { + deu = '' + von \acrshort{english} \Q{Polyhedral Skeletal Electron Pair Theory} + ''; + }; + data = { + kind = "Default"; + short = "PSEPT"; + }; + }; + vsepr = { + section = "Quantum"; + text = { + deu = "Modell der Valenz\\-elektronen\\-paar\\-abstoßung"; + }; + description = { + deu = '' + von \acrshort{english} \Q{Valence Shell Electron Pair Repulsion} + ''; + }; + data = { + kind = "Default"; + short = "VSEPR"; + }; + }; +} \ No newline at end of file diff --git a/NixTeX/assets/acronyms/standards.nix b/NixTeX/assets/acronyms/standards.nix new file mode 100644 index 0000000..04a89ad --- /dev/null +++ b/NixTeX/assets/acronyms/standards.nix @@ -0,0 +1,85 @@ +{ ... }: +{ + dinStandard = { + section = "Standards"; + text = { + deu = "Deutsche Industrie\\-norm"; + }; + description = { + deu = '' + vom Deutschen Institut für Normung erarbeitete freiwillige Industrie\-norm + ''; + }; + data = { + kind = "Default"; + short = "DIN"; + }; + }; + icdd = { + section = "Standards"; + text = { + deu = "Inter\\-nationales Zentrum für Beugungs\\-daten"; + eng = "Inter\-national Centre for Diffraction Data"; + }; + description = { + deu = '' + von \acrshort{english} \Q{Inter\-national Centre for Diffraction Data} + \acrshort{beziehungsweise} deren Datenbank für \acrlong{pxrd}\-daten + ''; + }; + data = { + kind = "Default"; + short = "ICDD"; + }; + }; + isoStandard = { + section = "Standards"; + text = { + deu = "Inter\\-nationale Organisation für Normung"; + }; + description = { + deu = '' + Inter\-nationale Vereinigung von Normungs\-organisationen, + welche international geltende Normen festlegen + ''; + }; + data = { + kind = "Default"; + short = "ISO"; + }; + }; + iupac = { + section = "Standards"; + text = { + deu = "Inter\\-nationale Union für reine und angewandte Chemie"; + eng = "International Union of Pure and Applied Chemistry"; + }; + description = { + deu = '' + von \acrshort{english} \Q{International Union of Pure and Applied Chemistry} + ''; + }; + data = { + kind = "Default"; + short = "IUPAC"; + }; + }; + siStandard = { + section = "Standards"; + text = { + deu = "Inter\\-nationales Einheiten\\-system"; + fre = "Système International d’unités"; + }; + description = { + deu = '' + von \acrshort{french} \Q{système international d’unités} + (\acrshort{dinStandard}\,\acrshort{isoStandard}\,1000), + das am weitesten verbreitete Einheiten\-system physikalischer Größen + ''; + }; + data = { + kind = "Default"; + short = "SI"; + }; + }; +} \ No newline at end of file diff --git a/NixTeX/assets/acronyms/units.nix b/NixTeX/assets/acronyms/units.nix new file mode 100644 index 0000000..0592025 --- /dev/null +++ b/NixTeX/assets/acronyms/units.nix @@ -0,0 +1,832 @@ +{ glossaries, ... }: +let + inherit(glossaries.acronyms) Unit Angle; +in +{ + ampere + = Unit "A" + { + title + = { + deu = "Ampere"; + }; + description + = { + deu + = { + about = "der elektrischen Strom\\-stärke"; + person + = { + about = "dem französischen Physiker"; + name = "André-Marie Ampère"; + }; + siBasic = true; + }; + }; + }; + angstroem + = Unit "\\AA" + { + title + = { + deu = "\\AA ngström"; + }; + description + = { + deu + = { + about = "der Länge"; + person + = { + about = "dem schwedischen Astronom und Physiker"; + name = "Anders Jonas Ångström"; + }; + value = { value = { value = 1; exp = -10; }; unit = "metre"; }; + }; + }; + sortedBy = "a"; + }; + bar + = Unit "bar" + { + title + = { + deu = "Bar"; + }; + description + = { + deu + = { + about = "des Druckes"; + foreign + = { + language = "greek"; + text = "βαρύς"; + latin = "barys"; + meaning = "schwer"; + }; + value = { value = { value = 1; exp = 5; }; unit = [ "kilogram" "metre-1" "second-1"]; }; + }; + }; + }; + becquerel + = Unit "Bq" + { + title + = { + deu = "Becquerel"; + }; + description + = { + deu + = { + about = "der Aktivität"; + person + = { + about = "dem französischen Physiker und Ingeneur"; + name = "Henri Becquerel"; + }; + value = { value = 1; unit = "second-1"; }; + }; + }; + }; + candela + = Unit "cd" + { + title + = { + deu = "Candela"; + }; + description + = { + deu + = { + about = "der Licht\\-stärke"; + foreign + = { + language = "latin"; + text = "candela"; + meaning = "Kerze"; + }; + siBasic = true; + }; + }; + }; + celsius + = Unit "°C" + { + title + = { + deu = "Grad Celsius"; + }; + description + = { + deu + = { + about = "der Temperatur"; + description + = '' + ''${\Physical{0}{}{celsius}{} = \Physical{273.15}{}{kelvin}{}}$, + ''${\Physical{100}{}{celsius}{} = \Physical{373.15}{}{kelvin}{}}$ + ''; + person + = { + about = "dem schwedischen Astronom, Mathematiker und Physiker"; + name = "Anders Celsius"; + }; + }; + }; + sortedBy = "c"; + }; + cm-1 + = Unit "cm\\textsuperscript{-1}" + { + title + = { + deu = "Reziproke \\acrtext[centi]{Centi}\\-\\acrtext[metre]{meter}"; + }; + description + = { + deu + = { + about = "der \\acrlong{waveNumber}"; + description + = '' + insbesondere der \acrshort{infrared}-Spektro\-skopie + ''; + value = { value = 100; unit = "metre-1"; }; + }; + }; + sortedBy = "cm-1"; + }; + coulomb + = Unit "C" + { + title + = { + deu = "Coulomb"; + }; + description + = { + deu + = { + about = "der elektrischen Ladung"; + siDerived = true; + person + = { + about = "dem französischen Physiker"; + name = "Charles Augustin de Coulomb"; + }; + value = { value = 1; unit = [ "ampere" "second" ]; }; + }; + }; + }; + countsPerSecond + = Unit "cps" + { + title + = { + deu = "Zähl\\-impulse je Sekunde"; + }; + description + = { + deu + = { + about = "der Zähl\\-rate"; + foreign + = { + language = "english"; + text = "Counts Per Second"; + }; + value = { value = 1; unit = "second-1"; }; + }; + }; + }; + dalton + = Unit "u" + { + title + = { + deu = "Atomare Massen\\-einheit"; + }; + description + = { + deu + = { + about = "der Masse"; + foreign + = { + language = "english"; + text = "Unified atomic mass unit"; + }; + description + = '' + ein Zwölftel der Masse + eines isolierten Atomes des Kohlenstoff\-isotops \textsuperscript{12}C + im Grund\-zustand + ''; + value = { value = { value = 1.66053906660; exp = -27; precision = 11; }; unit = "kilogram"; }; + }; + }; + }; + degree + = Angle "°" + { + title + = { + deu = "Grad"; + }; + description + = { + deu + = { + about = "des Winkels"; + value = { value = "\\frac{\\pi}{180}"; unit = "radian"; }; + }; + }; + }; + electronVolt + = Unit "eV" + { + title + = { + deu = "Elektron\\-volt"; + }; + description + = { + deu + = { + about = "der Energie"; + alternatives = [ "Elektronen\\-volt" ]; + description + = '' + entspricht der kinetischen Energie eines Elektrons, + welches mit \Physical{1}{}{volt}{} beschleunigt wurde + ''; + value + = [ + { value = { value = 1.6022; exp = -19; precision = 4; }; unit = "joule"; } + { value = 1; unit = [ "volt" "elementaryCharge" ]; } + ]; + }; + }; + }; + equivalent + = Unit "eq." + { + title + = { + deu = "Äquivalent"; + }; + description + = { + deu + = { + about = "der relativen Stoff\\-menge"; + foreign + = { + language = "english"; + text = "EQuivalent"; + }; + description + = '' + veraltet auch \textit{Val} + ''; + }; + }; + }; + hertz + = Unit "Hz" + { + title + = { + deu = "Hertz"; + }; + description + = { + deu + = { + about = "der Frequenz"; + person + = { + about = "dem deutschen Physiker"; + name = "Heinrich Hertz"; + }; + value = { value = 1; unit = "second-1"; }; + }; + }; + }; + hour + = Unit "h" + { + title + = { + deu = "Stunden"; + }; + description + = { + deu + = { + about = "der Zeit"; + foreign + = { + language = "english"; + text = "Hours"; + }; + value = { value = 3600; unit = "second"; }; + }; + }; + }; + joule + = Unit "J" + { + title + = { + deu = "Joule"; + }; + description + = { + deu + = { + about = "der Energie"; + person + = { + about = "dem britischen Physiker"; + name = "James Prescott Joule"; + }; + value = { value = 1; unit = [ "kilogram" "metre+2" "second-2" ]; }; + }; + }; + }; + kelvin + = Unit "K" + { + title + = { + deu = "Kelvin"; + }; + description + = { + deu + = { + about = "der absoluten Temperatur"; + siBasic = true; + person + = { + about = "dem britischen Physiker"; + name = "Lord Kelvin"; + }; + }; + }; + }; + kilocalorie + = Unit "kcal" + { + title + = { + deu = "\\acrtext[kilo]{Kilo}\\-kalorie"; + }; + description + = { + deu + = { + about = "der Energie"; + archaic = true; + foreign + = { + language = "latin"; + text = "calor"; + meaning = "Wärme"; + }; + value = { value = { value = 4.1868; exp = 3; precision = 4; }; unit = "joule"; }; + }; + }; + }; + kilogram + = Unit "kg" + { + title + = { + deu = "\\acrtext[kilo]{Kilo}\\-gramm"; + }; + description + = { + deu + = { + about = "der Masse \\acrshort{beziehungsweise} des Gewichtes"; + foreign + = { + language = "greek"; + text = "γράμμα"; + latin = "gramma"; + meaning = "Buchstabe"; + }; + siBasic = true; + }; + }; + }; + litre + = Unit "l" + { + title + = { + deu = "Liter"; + }; + description + = { + deu + = { + about = "des Volumens"; + foreign + = { + language = "greek"; + text = "λίτρα"; + latin = "litra"; + meaning = "Pfund"; + }; + value = { value = { value = 1; exp = -3; }; unit = "metre+3"; }; + }; + }; + }; + metre + = Unit "m" + { + title + = { + deu = "Meter"; + }; + description + = { + deu + = { + about = "der Länge"; + foreign + = { + language = "greek"; + text = "μέτρον"; + latin = "metron"; + meaning = "Maß, Länge"; + }; + siBasic = true; + }; + }; + }; + minute + = Unit "min" + { + title + = { + deu = "Minuten"; + }; + description + = { + deu + = { + about = "der Zeit"; + foreign + = { + language = "latin"; + text = "pars minuta"; + meaning = "verminderter Teil"; + }; + value = { value = 60; unit = "second"; }; + }; + }; + }; + mol + = Unit "mol" + { + title + = { + deu = "Mol"; + }; + description + = { + deu + = { + about = "der Stoff\\-menge"; + foreign + = { + language = "latin"; + text = "molecula"; + meaning = "kleine \\mbox{Masse}"; + }; + siBasic = true; + }; + }; + }; + molar + = Unit "M" + { + title + = { + deu = "Molar"; + }; + description + = { + deu + = { + about = "der Stoff\\-mengen\\-konzentration"; + foreign + = { + language = "latin"; + text = "molecula"; + meaning = "kleine Masse"; + }; + value = { value = 1; unit = [ "mol" "litre-1" ]; }; + }; + }; + }; + newton + = Unit "N" + { + title + = { + deu = "Newton"; + }; + description + = { + deu + = { + about = "der Kraft"; + person + = { + about = "dem englischen Physiker"; + name = "Isaac Newton"; + }; + value = { value = 1; unit = [ "kilogram" "metre" "second-2" ]; }; + }; + }; + }; + ohm + = Unit "\\Omega" + { + title + = { + deu = "Ohm"; + }; + description + = { + deu + = { + about = "des elektrischen Widerstandes"; + person + = { + about = "dem deutschen Physiker"; + name = "Georg Simon Ohm"; + }; + value = { value = 1; unit = [ "kilogram" "metre+2" "ampere-2" "second-3" ]; }; + }; + }; + sortedBy = "O"; + }; + pascal + = Unit "Pa" + { + title + = { + deu = "Pascal"; + }; + description + = { + deu + = { + about = "des Druckes"; + person + = { + about = "dem französischen Mathematiker und Physiker"; + name = "Blaise Pascal"; + }; + value = { value = 1; unit = [ "kilogram" "metre-1" "second-2" ]; }; + }; + }; + }; + percent + = Unit "\\%" + { + title + = { + deu = "Prozent"; + }; + description + = { + deu + = { + about = ""; + pseudoUnit = true; + foreign + = { + language = "latin"; + text = "per centum"; + meaning = "von Hundert"; + }; + value = { value = { value = 1; exp = -2; }; unit = []; }; + }; + }; + }; + permille + = Unit "‰" + { + title + = { + deu = "Promille"; + }; + description + = { + deu + = { + about = ""; + pseudoUnit = true; + foreign + = { + language = "latin"; + text = "per mille"; + meaning = "von Tausend"; + }; + value = { value = { value = 1; exp = -3; }; unit = []; }; + }; + }; + }; + ppm + = Unit "ppm" + { + title + = { + deu = "Millionstel"; + }; + description + = { + deu + = { + about = ""; + pseudoUnit = true; + foreign + = { + language = "english"; + text = "Parts Per Million"; + meaning = "Teile je \\mbox{Million}"; + }; + value = { value = { value = 1; exp = -9; }; unit = []; }; + }; + }; + }; + radian + = Unit "rad" + { + title + = { + deu = "Radiant"; + }; + description + = { + deu + = { + about = "des Winkels"; + foreign + = { + language = "latin"; + text = "radius"; + meaning = "Strahl"; + }; + }; + }; + }; + rpm + = Unit "rpm" + { + title + = { + deu = "Umdrehungen pro Minute"; + }; + description + = { + deu + = { + about = "der Dreh\\-zahl"; + foreign + = { + language = "english"; + text = "Rotations Per Minute"; + }; + value = { value = 1; unit = "minute-1"; }; + }; + }; + }; + second + = Unit "s" + { + title + = { + deu = "Sekunden"; + }; + description + = { + deu + = { + about = "der Zeit"; + foreign + = { + language = "latin"; + text = "pars minuta secunda"; + meaning = "zweiter verminderter Teil"; + }; + description + = '' + das 9.192.631.770-fache der Periodendauer der Strahlung, + die dem Übergang zwischen den beiden Hyper\-fein\-struktur\-niveaus des Grund\-zustandes + von Atomen des Nuklids \textsuperscript{133}Cs entspricht + ''; + siBasic = true; + }; + }; + }; + siemens + = Unit "S" + { + title + = { + deu = "Siemens"; + }; + description + = { + deu + = { + about = "des elektrischen Leit\\-wertes"; + person + = { + about = "dem deutschen Erfinder und Elektro\\-ingenieur"; + name = "Werner von Siemens"; + }; + value = { value = 1; unit = "ohm-1"; }; + }; + }; + }; + torr + = Unit "Torr" + { + title + = { + deu = "Torr"; + }; + description + = { + deu + = { + about = "des Druckes"; + archaic = true; + description + = '' + identisch mit der Milli\-meter\-quecksilber\-säule + ''; + person + = { + about = "dem italienischen Physiker und Mathematiker"; + name = "Evangelista Torricelli"; + }; + value = { value = { value = 1.33322; exp = 2; precision = 5; }; unit = [ "kilogram" "metre-1" "second-2" ]; }; + }; + }; + }; + volt + = Unit "V" + { + title + = { + deu = "Volt"; + }; + description + = { + deu + = { + about = "der elektrischen Spannung"; + person + = { + about = "dem italienischen Physiker"; + name = "Alessandro Volta"; + }; + value = { value = 1; unit = [ "kilogram" "metre+2" "ampere-1" "second-3" ]; }; + }; + }; + }; + watt + = Unit "W" + { + title + = { + deu = "Watt"; + }; + description + = { + deu + = { + about = "der Leistung"; + person + = { + about = "dem schottischen Physiker"; + name = "James Watt"; + }; + value = { value = 1; unit = [ "kilogram" "metre+2" "second-3" ]; }; + }; + }; + }; +} diff --git a/NixTeX/assets/default.nix b/NixTeX/assets/default.nix new file mode 100644 index 0000000..7b6402f --- /dev/null +++ b/NixTeX/assets/default.nix @@ -0,0 +1,9 @@ +{ core, ... } @ libs: + let + inherit(core) library; + in + { + acronyms = library.import ./acronyms libs; + hazardous = library.import ./hazardous.nix libs; + people = library.import ./people libs; + } \ No newline at end of file diff --git a/NixTeX/assets/fluent/default.nix b/NixTeX/assets/fluent/default.nix new file mode 100644 index 0000000..bd76fce --- /dev/null +++ b/NixTeX/assets/fluent/default.nix @@ -0,0 +1,38 @@ +{ core, ... } @ env: +let + inherit(core) error library list string type; + + english = library.import ./english.nix env {}; + german = library.import ./german.nix env english; +in +{ + inherit english german; + translate + = locale: + let + parts = string.match "([a-z]+)(_[A-Z]+)?([.][0-9A-Za-z-]+)?(@.+)?" locale; + getPart = list.get parts; + locale' + = if string.isInstanceOf locale + then + if parts != null + then + { + language = getPart 0; + territory = getPart 1; + codeset = getPart 2; + modifier = getPart 3; + } + else + error.panic "" + else + locale; + translate + = { + "de" = german.translate; + "en" = english.translate; + }.${locale'.language} + or ( error.panic "Unknown language »${locale'.language}«" ); + in + translate locale'; +} \ No newline at end of file diff --git a/NixTeX/assets/fluent/english.nix b/NixTeX/assets/fluent/english.nix new file mode 100644 index 0000000..6928658 --- /dev/null +++ b/NixTeX/assets/fluent/english.nix @@ -0,0 +1,30 @@ +{ mod, ... }: +{ ... } @ default: +let + inherit (mod) error; + + american + = british + // { + "colour" = "color"; + }; + british + = default + // { + "colour" = "colour"; + "today" = "today"; + }; +in +{ + translate + = locale: + snippet: + let + translations + = { + "UK" = british; + }.${locale.territory} + or ( error.panic "Unknown Territory »${locale.territory}«!" ); + in + translations.${snippet} or ( error.panic "Unknown Snippet »${snippet}«!" ); +} \ No newline at end of file diff --git a/NixTeX/assets/fluent/german.nix b/NixTeX/assets/fluent/german.nix new file mode 100644 index 0000000..492a84e --- /dev/null +++ b/NixTeX/assets/fluent/german.nix @@ -0,0 +1,41 @@ +{ core, ... }: +{ ... } @ default: +let + inherit(core) error list string; + + months + = [ + "Januar" "Februar" "März" "April" + "Mai" "Juni" "Juli" "August" + "September" "Oktober" "November" "Dezember" + ]; + monthsAT + = [ + "Jänner" "Februar" "März" "April" + "Mai" "Juni" "Juli" "August" + "September" "Oktober" "November" "Dezember" + ]; + + standard + = default + // { + "formatDate" + = { day, month, year, ... }: + "${string day}. ${list.get months month} ${string year}"; + "colour" = "Farbe"; + "today" = "heute"; + }; +in +{ + translate + = locale: + snippet: + let + translations + = { + "DE" = standard; + }.${locale.territory} + or ( error.panic "Unknown Territory »${locale.territory}«!" ); + in + translations.${snippet} or ( error.panic "Unknown Snippet »${snippet}«!" ); +} \ No newline at end of file diff --git a/NixTeX/assets/hazardous.nix b/NixTeX/assets/hazardous.nix new file mode 100644 index 0000000..1bb66dd --- /dev/null +++ b/NixTeX/assets/hazardous.nix @@ -0,0 +1,3228 @@ +{ ... }: +let + sources + = { + gestis + = '' + @online{gestis, + title = {{GESTIS}-Stoffdatenbank}, + url = {http://gestis.itrust.de/nxt/gateway.dll/gestis_de/000000.xml?f=templates$fn=default.htm$vid=gestisdeu:sdbdeu$3.0}, + urldate = {2019-03-24} + } + ''; + Bromnaphthalene + = '' + @online{ghs_1Bromnaphthalene, + title = {1-Brom-naphthalin – Sigma-Aldrich}, + url = {https://www.sigmaaldrich.com/DE/de/substance/1bromonaphthalene2070790119}, + urldate = {2021-10-19}, + } + ''; + MPTS + = '' + @online{ghs_MPTS, + title = {Trimethoxy-[3-(2-methoxyethoxy)propyl]silane}, + url = {https://pubchem.ncbi.nlm.nih.gov/compound/171723}, + urldate = {2018-12-09}, + } + ''; + TFPTMS + = '' + @online{ghs_TFPTMS, + title = {Trimethoxy(3,3,3-trifluoropropyl)silane – Sigma-Aldrich}, + url = {https://www.sigmaaldrich.com/catalog/product/aldrich/91877}, + urldate = {2018-12-09}, + } + ''; + liquidNitrogen + = '' + @online{ghs_liquidNitrogen, + title= {Stickstoff, tiefgekühlt, flüssig – Linde}, + url = {https://produkte.linde-gas.at/sdb_konform/LIN_10021831DE.pdf}, + urldate = {2020-02-10}, + } + ''; + PFOTES + = '' + @online{ghs_PFOTES, + title = {1H,1H,2H,2H-Perfluorooctyltriethoxysilane 98\% – Sigma-Aldrich}, + url = {https://www.sigmaaldrich.com/catalog/product/aldrich/667420}, + urldate = {2019-01-16}, + } + ''; + }; + hazard + = { + class + = { + explosive = 1; + }; + compatibility + = { + X = 1; + }; + }; + ghs + = { + pictogram + = { + Explosive = 1; + Flame = 2; + OFlame = 3; + Bottle = 4; + Acid = 5; + Skull = 6; + Exclam = 7; + Health = 8; + Pollu = 9; + }; + signal + = { + None = 0; + Warning = 1; + Danger = 2; + }; + }; + nfpa + = { + None = 0; + Asphyxiant = 1; + NoWater = 2; + Oxidiser = 3; + Acid = 4; + Alkaline = 5; + BioHazard = 6; + Cryogenic = 7; + EcoHazard = 8; + Etching = 9; + Explosive = 10; + Hot = 11; + Radioactive = 12; + Toxic = 13; + }; +in +{ + "1,1,2,2-Tetrachlorethane" + = { + name + = { + deu = "1,1,2,2-Tetra|chlor||ethan"; + eng = "1,1,2,2-Tetra|chlor||ethane"; + }; + availability + = { + }; + hazmat + = { + ghs + = { + hazards = [ 310 330 341 351 411 ]; + precautions = [ 260 284 320 361 405 501 ]; + pictograms = [ ghs.pictogram.Skull ghs.pictogram.Health ghs.pictogram.Pollu ]; + signal = ghs.signal.Danger; + }; + kemler = 60; + }; + identifiers + = { + cas = "79-34-5"; + ec = "201-197-8"; + un = 1897; + }; + sources = [ sources.gestis ]; + asof = "2020-02-16"; + }; + "1,1,2-Trichlorethene" + = { + name + = { + deu = "1,1,2-Tri|chlor||ethen"; + eng = "1,1,2-Tri|chlor||ethene"; + }; + availability + = { + }; + hazmat + = { + ghs + = { + hazards = [ 350 341 319 315 336 412 ]; + precautions = [ 201 261 273 280 "305+351+338" "308+313" ]; + pictograms = [ ghs.pictogram.Health ghs.pictogram.Exclam ]; + signal = ghs.signal.Danger; + }; + kemler = 60; + }; + identifiers + = { + cas = "79-01-6"; + ec = "201-167-4"; + un = 1710; + }; + sources = [ sources.gestis ]; + asof = "2020-02-16"; + }; + "1,2-Dichlorethane" + = { + name + = { + deu = "1,2-Di|chlor||ethan"; + eng = "1,2-Di|chlor||ethane"; + }; + availability + = { + }; + hazmat + = { + ghs + = { + hazards = [ 225 350 302 319 335 315 ]; + precautions = [ 201 210 "302+352" "304+340" "305+351+338" "308+313" ]; + pictograms = [ ghs.pictogram.Flame ghs.pictogram.Health ghs.pictogram.Exclam ]; + signal = ghs.signal.Danger; + }; + }; + identifiers + = { + cas = "107-06-2"; + ec = "203-458-1"; + }; + sources = [ sources.gestis ]; + asof = "2020-02-16"; + }; + "1,4-Dioxane" + = { + name + = { + deu = "1,4-Di|oxan"; + eng = "1,4-Di|oxane"; + }; + availability + = { + }; + physical + = { + formula = "C4H8O2"; + density = 1.033; + melting = 11.8; + boiling = 101.1; + nD20 = 1.422; + }; + hazmat + = { + ghs + = { + hazards = [ 225 319 335 351 ]; + euHazards = [ 19 66 ]; + precautions = [ 210 261 "305+351+338" ]; + pictograms = [ ghs.pictogram.Flame ghs.pictogram.Health ghs.pictogram.Exclam ]; + signal = ghs.signal.Danger; + }; + iso7010 + = { + warnings = [ ]; + }; + nfpa + = { + fire = 2; + health = 3; + reaction = 1; + other = nfpa.None; + }; + kemler = 33; + }; + identifiers + = { + cas = "123-91-1"; + ec = "204-661-8"; + un = 1165; + }; + sources = [ sources.gestis ]; + asof = "2020-02-27"; + }; + "1-Bromonaphthalene" + = { + name + = { + deu = "1-Brom||naphthalin"; + eng = "1-Bromo||naphthalene"; + }; + availability + = { + }; + hazmat + = { + ghs + = { + hazards = [ 302 319 ]; + precautions = [ "301+312" 330 "305+351+338" ]; + pictograms = [ ghs.pictogram.Exclam ]; + signal = ghs.signal.Warning; + }; + }; + identifiers + = { + cas = "90-11-9"; + ec = "201-965-2"; + }; + sources = [ sources.Bromnaphthalene ]; + asof = "2020-02-16"; + }; + "1-Butanol" + = { + name + = { + deu = "1-Butanol"; + eng = "1-Butanol"; + }; + availability + = { + }; + physical + = { + formula = "H3C(CH2)3OH"; + density = 0.81; + melting = -89; + boiling = 118; + nD20 = 1.3988; + }; + hazmat + = { + ghs + = { + hazards = [ 226 302 318 315 335 336 ]; + precautions = [ 210 280 "302+352" "304+340" "305+351+338" "308+313" ]; + pictograms = [ ghs.pictogram.Flame ghs.pictogram.Acid ghs.pictogram.Exclam ]; + signal = ghs.signal.Danger; + }; + kemler = 33; + }; + identifiers + = { + cas = "71-36-3"; + ec = "200-751-6"; + un = 1120; + }; + sources = [ sources.gestis ]; + asof = "2020-07-11"; + }; + "1-Propanol" + = { + name + = { + deu = "1-Propanol"; + eng = "1-Propanol"; + }; + availability + = { + }; + hazmat + = { + ghs + = { + hazards = [ "225‐318" 336 ]; + precautions = [ 210 240 280 "305+351+338" 313 "403+233" ]; + pictograms = [ ghs.pictogram.Flame ghs.pictogram.Acid ghs.pictogram.Exclam ]; + signal = ghs.signal.Danger; + }; + kemler = 33; + }; + identifiers + = { + cas = "71-23-8"; + ec = "200-746-9"; + un = 1274; + }; + sources = [ sources.gestis ]; + asof = "2020-02-16"; + }; + "2-Butanol" + = { + name + = { + deu = "2-Butanol"; + eng = "2-Butanol"; + }; + availability + = { + }; + physical + = { + formula = "H3CCH2(CHOH)CH3"; + density = 0.81; + melting = -115; + boiling = 99; + nD20 = 1.3978; + }; + hazmat + = { + ghs + = { + hazards = [ 226 319 335 336 ]; + precautions = [ 210 "304+340" "305+351+338" ]; + pictograms = [ ghs.pictogram.Flame ghs.pictogram.Exclam ]; + signal = ghs.signal.Danger; + }; + kemler = 33; + }; + identifiers + = { + cas = "15892-23-6"; + ec = "240-029-8"; + un = 1120; + }; + sources = [ sources.gestis ]; + asof = "2020-07-11"; + }; + "2-Methyl-1-propanol" + = { + name + = { + deu = "2-Methyl-1-propanol"; + eng = "2-Methyl-1-propanol"; + }; + availability + = { + }; + hazmat + = { + ghs + = { + hazards = [ 226 335 315 318 336 ]; + precautions = [ 210 280 "302+352" "305+351+338" ]; + pictograms = [ ghs.pictogram.Flame ghs.pictogram.Acid ghs.pictogram.Exclam ]; + signal = ghs.signal.Danger; + }; + kemler = 33; + }; + identifiers + = { + cas = "78-83-1"; + ec = "201-148-0"; + un = 1120; + }; + sources = [ sources.gestis ]; + asof = "2020-02-16"; + }; + "2-Propanol" + = { + name + = { + deu = "2-Propanol"; + eng = "2-Propanol"; + }; + availability + = { + }; + hazmat + = { + ghs + = { + hazards = [ "225​" "​319" 336 ]; + precautions = [ 210 233 240 "305+351+338" "403+235" ]; + pictograms = [ ghs.pictogram.Flame ghs.pictogram.Exclam ]; + signal = ghs.signal.Danger; + }; + kemler = 33; + }; + identifiers + = { + cas = "67-63-0"; + ec = "200-661-7"; + un = 1219; + }; + sources = [ sources.gestis ]; + asof = "2020-02-16"; + }; + "2-Propyl acetate" + = { + name + = { + deu = "2-Propyl||acetat"; + eng = "2-Propyl acetate"; + }; + availability + = { + }; + hazmat + = { + ghs + = { + hazards = [ 225 319 336 ]; + euHazards = [ 66 ]; + precautions = [ 210 "305+351+338" { id = "370+378"; dots = { deu = "Löschpulver oder Trockensand"; }; } "403+235" ]; + pictograms = [ ghs.pictogram.Flame ghs.pictogram.Exclam ]; + signal = ghs.signal.Danger; + }; + kemler = 33; + }; + identifiers + = { + cas = "108-21-4"; + ec = "203-561-1"; + un = 1220; + }; + sources = [ sources.gestis ]; + asof = "2020-02-16"; + }; + "3-Methyl-1-butanol" + = { + name + = { + deu = "3-Methyl-1-butanol"; + eng = "3-Methyl-1-butanol"; + }; + availability + = { + }; + hazmat + = { + ghs + = { + hazards = [ 226 332 315 319 335 ]; + euHazards = [ 66 ]; + precautions = [ 210 280 "304+340" "302+352" "332+313" "337+313" ]; + pictograms = [ ghs.pictogram.Flame ghs.pictogram.Exclam ]; + signal = ghs.signal.Warning; + }; + kemler = 33; + }; + identifiers + = { + cas = "123-51-3"; + ec = "204-633-5"; + un = 1105; + }; + sources = [ sources.gestis ]; + asof = "2020-02-16"; + }; + "3-Nitrotoluene" + = { + name + = { + deu = "3-Nitro||toluen"; + eng = "3-Nitro||toluene"; + }; + availability + = { + }; + hazmat + = { + ghs + = { + hazards = [ 302 311 332 373 411 ]; + precautions = [ 280 273 "308+313" "302+352" ]; + pictograms = [ ghs.pictogram.Skull ghs.pictogram.Health ghs.pictogram.Pollu ]; + signal = ghs.signal.Danger; + }; + kemler = 60; + }; + identifiers + = { + cas = "99-08-1"; + ec = "202-728-6"; + un = 3446; + }; + sources = [ sources.gestis ]; + asof = "2020-02-16"; + }; + "Acetic acid" + = { + name + = { + deu = "Ethan||säure"; + eng = "Ethanoic acid"; + }; + availability + = { + }; + hazmat + = { + ghs + = { + hazards = [ 226 290 314 ]; + precautions = [ 210 280 "301+330+331" "305+351+338" "308+313" ]; + pictograms = [ ghs.pictogram.Flame ghs.pictogram.Acid ]; + signal = ghs.signal.Warning; + }; + kemler = 83; + }; + identifiers + = { + cas = "64-19-7"; + ec = "200-580-7"; + un = 2789; + }; + sources = [ sources.gestis ]; + asof = "2020-02-16"; + }; + "Acetone" + = { + name + = { + deu = "Aceton"; + eng = "Acetone"; + }; + availability + = { + }; + physical + = { + formula = "H3CCOCH3"; + density = 0.79; + melting = -95; + boiling = 56; + nD20 = 1.3588; + }; + hazmat + = { + ghs + = { + hazards = [ 225 319 336 ]; + euHazards = [ 66 ]; + precautions = [ 210 240 "305+351+338" "403+233" ]; + pictograms = [ ghs.pictogram.Flame ghs.pictogram.Exclam ]; + signal = ghs.signal.Danger; + }; + iso7010 + = { + warnings = [ ]; + }; + nfpa + = { + fire = 1; + health = 3; + reaction = 0; + other = nfpa.None; + }; + kemler = 33; + }; + identifiers + = { + cas = "67-64-1"; + ec = "200-662-2"; + un = 1090; + }; + sources = [ sources.gestis ]; + asof = "2020-07-22"; + }; + "Acetonitrile" + = { + name + = { + deu = "Aceto||nitril"; + eng = "Aceto||nitrile"; + }; + availability + = { + }; + hazmat + = { + ghs + = { + hazards = [ 225 332 302 312 319 ]; + precautions = [ 210 240 "302+352" "305+351+338" "403+233" ]; + pictograms = [ ghs.pictogram.Flame ghs.pictogram.Exclam ]; + signal = ghs.signal.Danger; + }; + kemler = 33; + }; + identifiers + = { + cas = "75-05-8"; + ec = "200-835-2"; + un = 1648; + }; + sources = [ sources.gestis ]; + asof = "2020-02-16"; + }; + "Ammonia solvated" + = { + name + = { + deu = "Ammoniak, wässrige Lösung"; + eng = "Ammonia, aqueous solution"; + }; + availability + = { + }; + hazmat + = { + ghs + = { + hazards = [ 290 314 335 400 ]; + precautions = [ 260 273 280 "301+330+331" "303+361+353" "305+351+338" ]; + pictograms = [ ghs.pictogram.Acid ghs.pictogram.Exclam ghs.pictogram.Pollu ]; + signal = ghs.signal.Danger; + }; + kemler = 268; + }; + identifiers + = { + cas = "1336-21-6"; + ec = "215-647-6"; + un = 3318; + }; + sources = [ sources.gestis ]; + asof = "2020-02-16"; + }; + "Anthracene" + = { + name + = { + deu = "Anthracen"; + eng = "Anthracene"; + }; + availability + = { + }; + hazmat + = { + ghs + = { + hazards = [ 315 410 ]; + precautions = [ 273 280 "302+352" "332+313" 501 ]; + pictograms = [ ghs.pictogram.Exclam ghs.pictogram.Pollu ]; + signal = ghs.signal.Warning; + }; + }; + identifiers + = { + cas = "120-12-7"; + ec = "204-371-1"; + }; + sources = [ sources.gestis ]; + asof = "2020-02-16"; + }; + "Argon" + = { + name + = { + deu = "Argon"; + eng = "Argon"; + }; + availability + = { + }; + hazmat + = { + ghs + = { + hazards = [ 280 ]; + precautions = [ 403 ]; + pictograms = [ ghs.pictogram.Bottle ]; + signal = ghs.signal.Warning; + }; + kemler = 20; + }; + identifiers + = { + cas = "7440-37-1"; + ec = "231-147-0"; + un = 1006; + }; + sources = [ sources.gestis ]; + asof = "2020-02-16"; + }; + "Benzaldehyde" + = { + name + = { + deu = "Benzaldehyd"; + eng = "Benzaldehyde"; + }; + availability + = { + }; + hazmat + = { + ghs + = { + hazards = [ 302 ]; + precautions = [ 262 ]; + pictograms = [ ghs.pictogram.Exclam ]; + signal = ghs.signal.Warning; + }; + kemler = 90; + }; + identifiers + = { + cas = "100-52-7"; + ec = "202-860-4"; + un = 1990; + }; + sources = [ sources.gestis ]; + asof = "2020-02-16"; + }; + "Benzene" + = { + name + = { + deu = "Benzen"; + eng = "Benzene"; + }; + availability + = { + }; + hazmat + = { + ghs + = { + hazards = [ 225 304 315 319 340 350 372 412 ]; + precautions = [ 201 210 280 "308+313" { id = "370+378"; dots = { deu = "Löschpulver oder Trockensand"; }; } "403+235" ]; + pictograms = [ ghs.pictogram.Flame ghs.pictogram.Health ghs.pictogram.Exclam ]; + signal = ghs.signal.Danger; + }; + kemler = 33; + }; + identifiers + = { + cas = "71-43-2"; + ec = "200-753-7"; + un = 1114; + }; + sources = [ sources.gestis ]; + asof = "2020-02-16"; + }; + "Benzoic acid" + = { + name + = { + deu = "Benzoe||säure"; + eng = "Benzoic acid"; + }; + availability + = { + }; + hazmat + = { + ghs + = { + hazards = [ 315 318 "372:orgDE=inhalativ die Lunge;orgEN=the lungs by inhalation;" ]; + precautions = [ 280 "302+352" "305+351+338" 314 ]; + pictograms = [ ghs.pictogram.Acid ghs.pictogram.Health ]; + signal = ghs.signal.Danger; + }; + }; + identifiers + = { + cas = "65-85-0"; + ec = "200-618-2"; + }; + sources = [ sources.gestis ]; + asof = "2020-02-16"; + }; + "Bromine" + = { + name + = { + deu = "Brom"; + eng = "Bromine"; + }; + availability + = { + }; + hazmat + = { + ghs + = { + hazards = [ 330 314 400 ]; + precautions = [ 210 273 "304+340" "305+351+338" "308+310" "403+233" ]; + pictograms = [ ghs.pictogram.Skull ghs.pictogram.Acid ghs.pictogram.Pollu ]; + signal = ghs.signal.Danger; + }; + kemler = 886; + }; + identifiers + = { + cas = "7726-95-6"; + ec = "231-778-1"; + un = 1744; + }; + sources = [ sources.gestis ]; + asof = "2020-02-16"; + }; + "Butane" + = { + name + = { + deu = "Butan"; + eng = "Butane"; + }; + availability + = { + }; + hazmat + = { + ghs + = { + hazards = [ 220 350 340 280 ]; + precautions = [ 210 202 "308+313" 377 381 405 403 ]; + pictograms = [ ghs.pictogram.Flame ghs.pictogram.Health ghs.pictogram.Bottle ]; + signal = ghs.signal.None; + }; + kemler = 23; + }; + identifiers + = { + cas = "106-99-0"; + ec = "203-450-8"; + un = 1011; + }; + sources = [ sources.gestis ]; + asof = "2020-02-16"; + }; + "Calcium acetylacetonate" + = { + name + = { + deu = "Calcium||acetyl||acetonat"; + eng = "Calcium acetyl||acetonate"; + }; + availability + = { + }; + hazmat + = { + ghs + = { + hazards = [ 302 315 319 335 361 ]; + precautions = [ 261 281 "305+351+338" ]; + pictograms = [ ghs.pictogram.Health ghs.pictogram.Exclam ]; + signal = ghs.signal.Warning; + }; + }; + identifiers + = { + cas = "19372-44-2"; + ec = "243-001-3"; + }; + sources = [ sources.gestis ]; + asof = "2020-02-16"; + }; + "Carbon monooxide insitu" + = { + name + = { + deu = "Kohlenstoff||mono|oxid"; + eng = "Carbon mono|oxide"; + }; + availability + = { + }; + hazmat + = { + ghs + = { + hazards = [ 220 331 "360D" 372 ]; + precautions = [ 202 210 260 "304+340" "308+313" 315 377 381 ]; + pictograms = [ ghs.pictogram.Flame ghs.pictogram.Skull ghs.pictogram.Health ]; + signal = ghs.signal.Danger; + }; + }; + identifiers + = { + cas = "630-08-0"; + ec = "211-128-3"; + }; + sources = [ sources.gestis ]; + asof = "2020-02-16"; + }; + "Chlorbenzene" + = { + name + = { + deu = "Chlor||benzen"; + eng = "Chlor||benzene"; + }; + availability + = { + }; + hazmat + = { + ghs + = { + hazards = [ 226 332 315 411 ]; + precautions = [ 260 262 273 403 ]; + pictograms = [ ghs.pictogram.Flame ghs.pictogram.Exclam ghs.pictogram.Pollu ]; + signal = ghs.signal.Warning; + }; + kemler = 30; + }; + identifiers + = { + cas = "108-90-7"; + ec = "203-628-5"; + un = 1134; + }; + sources = [ sources.gestis ]; + asof = "2020-02-16"; + }; + "Chlorine" + = { + name + = { + deu = "Chlor"; + eng = "Chlorine"; + }; + availability + = { + }; + hazmat + = { + ghs + = { + hazards = [ 270 280 330 315 319 335 400 ]; + euHazards = [ 71 ]; + precautions = [ 260 220 280 244 273 "304+340" "305+351+338" "332+313" "370+376" "302+352" 315 405 403 ]; + pictograms = [ ghs.pictogram.Skull ghs.pictogram.OFlame ghs.pictogram.Bottle ghs.pictogram.Pollu ]; + signal = ghs.signal.Danger; + }; + kemler = 265; + }; + identifiers + = { + cas = "7782-50-5"; + ec = "231-959-5"; + un = 1017; + }; + sources = [ sources.gestis ]; + asof = "2020-02-16"; + }; + "Chlorine (insitu)" + = { + name + = { + deu = "Chlor in situ"; + eng = "Chlorine in situ"; + }; + availability + = { + }; + hazmat + = { + ghs + = { + hazards = [ 270 330 315 319 335 400 ]; + euHazards = [ 71 ]; + precautions = [ 260 220 280 273 "304+340" "305+351+338" "332+313" "370+376" "302+352" 315 405 403 ]; + pictograms = [ ghs.pictogram.Skull ghs.pictogram.OFlame ghs.pictogram.Pollu ]; + signal = ghs.signal.Danger; + }; + }; + identifiers + = { + cas = "7782-50-5"; + ec = "231-959-5"; + }; + sources = [ sources.gestis ]; + asof = "2020-02-16"; + }; + "Copper(I) cyanide" + = { + name + = { + deu = "Kupfer(I)-cyanid"; + eng = "Copper(I)-cyanide"; + }; + availability + = { + }; + physical + = { + formula = "CuCN"; + }; + hazmat + = { + ghs + = { + hazards = [ 300 310 330 410 ]; + euHazards = [ 32 ]; + precautions = [ 260 264 273 280 284 "301+310" ]; + pictograms = [ ghs.pictogram.Skull ghs.pictogram.Pollu ]; + signal = ghs.signal.None; + }; + }; + identifiers + = { + cas = "544-92-3"; + ec = "208-883-6"; + }; + sources = [ sources.gestis ]; + asof = "2020-02-16"; + }; + "Copper(II) sulfate" + = { + name + = { + deu = "Kupfer(II)-sulfat"; + eng = "Copper(II)-sulfate"; + }; + availability + = { + }; + hazmat + = { + ghs + = { + pictograms = [ ghs.pictogram.Acid ghs.pictogram.Exclam ghs.pictogram.Pollu ]; + signal = ghs.signal.None; + }; + kemler = 66; + }; + identifiers + = { + cas = "10257-54-2"; + ec = "231-847-6"; + un = 2775; + }; + sources = [ sources.gestis ]; + asof = "2020-02-16"; + }; + "Copper(II) sulfate pentahydrate" + = { + name + = { + deu = "Kupfer(II)-sulfat||penta|hydrat"; + eng = "Copper(II) sulfate penta|hydrate"; + }; + availability + = { + }; + hazmat + = { + ghs + = { + hazards = [ 302 315 319 410 ]; + precautions = [ 273 "305+351+338" 362 "301+312" "302+352" 501 ]; + pictograms = [ ghs.pictogram.Exclam ghs.pictogram.Pollu ]; + signal = ghs.signal.None; + }; + kemler = 66; + }; + identifiers + = { + cas = "7732-18-5"; + ec = "231-847-6"; + un = 2775; + }; + sources = [ ]; + asof = "2020-02-16"; + }; + "Cyclohexane" + = { + name + = { + deu = "Cyclo|hexan"; + eng = "Cyclo|hexane"; + }; + availability + = { + }; + hazmat + = { + ghs + = { + hazards = [ 225 304 315 336 410 ]; + precautions = [ 210 240 273 "301+310" 331 "302+352" "403+233" ]; + pictograms = [ ghs.pictogram.Flame ghs.pictogram.Health ghs.pictogram.Exclam ghs.pictogram.Pollu ]; + signal = ghs.signal.Danger; + }; + kemler = 33; + }; + identifiers + = { + cas = "110-82-7"; + ec = "203-806-2"; + un = 1145; + }; + sources = [ sources.gestis ]; + asof = "2020-02-16"; + }; + "Cyclopropane" + = { + name + = { + deu = "Cyclo|propan"; + eng = "Cyclo|propane"; + }; + availability + = { + }; + hazmat + = { + ghs + = { + hazards = [ 220 ]; + pictograms = [ ghs.pictogram.Flame ghs.pictogram.Bottle ]; + signal = ghs.signal.Danger; + }; + kemler = 23; + }; + identifiers + = { + cas = "75-19-4"; + ec = "200-847-8"; + un = 1978; + }; + sources = [ sources.gestis ]; + asof = "2020-02-16"; + }; + "Decalin" + = { + name + = { + deu = "Decalin"; + eng = "Decalin"; + }; + availability + = { + }; + hazmat + = { + ghs + = { + hazards = [ 226 331 304 314 411 ]; + precautions = [ 261 273 280 "301+310" "305+351+338" 310 ]; + pictograms = [ ghs.pictogram.Flame ghs.pictogram.Skull ghs.pictogram.Health ghs.pictogram.Acid ghs.pictogram.Pollu ]; + signal = ghs.signal.Danger; + }; + kemler = 30; + }; + identifiers + = { + cas = "91-17-8"; + ec = "202-046-9"; + un = 1147; + }; + sources = [ sources.gestis ]; + asof = "2020-02-16"; + }; + "Dichlormethane" + = { + name + = { + deu = "Di|chlor||methan"; + eng = "Di|chlor||methane"; + }; + label = "acronyms:dcm"; + availability + = { + }; + physical + = { + formula = "CH2Cl2"; + density = 1.33; + melting = -97; + boiling = 40; + nD20 = 1.4242; + }; + hazmat + = { + ghs + = { + hazards = [ 315 319 335 336 351 373 ]; + precautions = [ 261 "305+351+338" ]; + pictograms = [ ghs.pictogram.Health ghs.pictogram.Exclam ]; + signal = ghs.signal.Danger; + }; + nfpa + = { + fire = 1; + health = 2; + reaction = 0; + other = nfpa.None; + }; + kemler = 60; + }; + identifiers + = { + cas = "75-09-2"; + ec = "200-838-9"; + un = 1593; + }; + sources = [ sources.gestis ]; + asof = "2020-03-05"; + }; + "Diethyl ether" + = { + name + = { + deu = "Di|ethyl||ether"; + eng = "Di|ethyl ether"; + }; + availability + = { + }; + physical + = { + formula = "(H3CCH2)2O"; + density = 0.7134; + melting = -116.3; + boiling = 34.6; + nD20 = 1.353; + }; + hazmat + = { + ghs + = { + hazards = [ 224 302 336 ]; + euHazards = [ 19 66 ]; + precautions = [ 210 240 "403+235" ]; + pictograms = [ ghs.pictogram.Flame ghs.pictogram.Exclam ]; + signal = ghs.signal.Danger; + }; + nfpa + = { + fire = 2; + health = 4; + reaction = 1; + other = nfpa.None; + }; + kemler = 33; + }; + identifiers + = { + cas = "60-29-7"; + ec = "200-467-2"; + un = 1155; + }; + sources = [ sources.gestis ]; + asof = "2020-07-11"; + }; + "Dimethyl sulfoxid" + = { + name + = { + deu = "Di|methyl||sulfoxid"; + eng = "Di|methyl sulfoxid"; + }; + availability + = { + }; + hazmat + = { + ghs + = { + signal = ghs.signal.None; + }; + }; + identifiers + = { + cas = "67-68-5"; + ec = "200-664-3"; + }; + sources = [ sources.gestis ]; + asof = "2020-02-16"; + }; + "Dimethylformamide" + = { + name + = { + deu = "N,N-Di|methyl||formamid"; + eng = "N,N-Di|methyl||formamide"; + }; + availability + = { + }; + physical + = { + formula = "(H3C)2NCHO"; + density = 0.95; + melting = -61; + boiling = 153; + nD20 = 1.4305; + }; + hazmat + = { + ghs + = { + hazards = [ 226 312 332 319 "360D" ]; + precautions = [ 201 210 "302+352" "304+340" "305+351+338" "308+313" ]; + pictograms = [ ghs.pictogram.Flame ghs.pictogram.Health ghs.pictogram.Exclam ]; + signal = ghs.signal.Danger; + }; + nfpa + = { + fire = 2; + health = 2; + reaction = 0; + other = nfpa.None; + }; + kemler = 30; + }; + identifiers + = { + cas = "68-12-2"; + ec = "200-679-5"; + un = 2265; + }; + sources = [ sources.gestis ]; + asof = "2020-02-17"; + }; + "Diphenyl ether" + = { + name + = { + deu = "Di|phenyl||ether"; + eng = "Di|phenyl ether"; + }; + availability + = { + }; + hazmat + = { + ghs + = { + hazards = [ 319 411 ]; + precautions = [ 280 273 264 "305+351+338" "337+313" 501 ]; + pictograms = [ ghs.pictogram.Exclam ghs.pictogram.Pollu ]; + signal = ghs.signal.Warning; + }; + }; + identifiers + = { + cas = "101-84-8"; + ec = "202-981-2"; + }; + sources = [ sources.gestis ]; + asof = "2020-02-16"; + }; + "Dry ice" + = { + name + = { + deu = "Trockeneis (festes Kohlenstoff||di|oxid)"; + eng = "Dry ice (solid carbon||di|oxide)"; + }; + availability + = { + }; + hazmat + = { + ghs + = { + hazards = [ 281 ]; + precautions = [ 403 ]; + signal = ghs.signal.Warning; + }; + iso7010 + = { + warnings = [ 10 ]; + }; + }; + identifiers + = { + cas = "124-38-9"; + ec = "204-696-9"; + un = 1845; + }; + sources = [ sources.gestis ]; + asof = "2020-02-16"; + }; + "Ethanol" + = { + name + = { + deu = "Ethanol"; + eng = "Ethanol"; + }; + availability + = { + }; + hazmat + = { + ghs + = { + hazards = [ 225 319 ]; + euHazards = [ 19 66 ]; + precautions = [ 210 240 "305+351+338" "403+233" ]; + pictograms = [ ghs.pictogram.Flame ghs.pictogram.Exclam ]; + signal = ghs.signal.Danger; + }; + kemler = 33; + }; + identifiers + = { + cas = "64-17-5"; + ec = "200-578-6"; + un = 1170; + }; + sources = [ sources.gestis ]; + asof = "2020-02-16"; + }; + "Ethyl acetate" + = { + name + = { + deu = "Ethyl||acetat"; + eng = "Ethyl acetate"; + }; + availability + = { + }; + hazmat + = { + ghs + = { + hazards = [ 225 319 336 ]; + precautions = [ 210 233 240 "305+351+338" "403+235" ]; + pictograms = [ ghs.pictogram.Flame ghs.pictogram.Exclam ]; + signal = ghs.signal.Danger; + }; + kemler = 33; + }; + identifiers + = { + cas = "141-78-6"; + ec = "205-500-4"; + un = 1173; + }; + sources = [ sources.gestis ]; + asof = "2020-02-16"; + }; + "Ethylene glycol" + = { + name + = { + deu = "Ethylen||glycol"; + eng = "Ethylen glycol"; + }; + availability + = { + }; + hazmat + = { + ghs + = { + hazards = [ 302 373 ]; + precautions = [ "301+312" 330 ]; + pictograms = [ ghs.pictogram.Exclam ghs.pictogram.Health ]; + signal = ghs.signal.Warning; + }; + }; + identifiers + = { + cas = "107-21-1"; + ec = "203-473-3"; + }; + sources = [ sources.gestis ]; + asof = "2020-02-16"; + }; + "Fluorescein" + = { + name + = { + deu = "Fluorescein"; + eng = "Fluorescein"; + }; + availability + = { + }; + hazmat + = { + ghs + = { + hazards = [ 319 ]; + precautions = [ "305+351+338" ]; + pictograms = [ ghs.pictogram.Exclam ]; + signal = ghs.signal.Warning; + }; + }; + identifiers + = { + cas = "2321-07-5"; + ec = "219-031-8"; + }; + sources = [ sources.gestis ]; + asof = "2020-02-16"; + }; + "Fumaric acid" + = { + name + = { + deu = "(2E)-But-2-en||di|säure (Fumar||säure)"; + eng = "(2E)-But-2-ene||di|oic acid (Fumaric acid)"; + }; + availability + = { + }; + hazmat + = { + ghs + = { + hazards = [ 319 ]; + precautions = [ "305+351+338" ]; + pictograms = [ ghs.pictogram.Exclam ]; + signal = ghs.signal.Warning; + }; + }; + identifiers + = { + cas = "110-17-8"; + ec = "203-743-0"; + }; + sources = [ sources.gestis ]; + asof = "2020-02-16"; + }; + "Helium" + = { + name + = { + deu = "Helium"; + eng = "Helium"; + }; + availability + = { + }; + hazmat + = { + ghs + = { + hazards = [ 280 ]; + precautions = [ 403 ]; + pictograms = [ ghs.pictogram.Bottle ]; + signal = ghs.signal.Warning; + }; + kemler = 20; + }; + identifiers + = { + cas = "7440-59-7"; + ec = "231-168-5"; + un = 1046; + }; + sources = [ sources.gestis ]; + asof = "2020-02-16"; + }; + "Heptane" + = { + name + = { + deu = "Heptan"; + eng = "Heptane"; + }; + availability + = { + }; + hazmat + = { + ghs + = { + hazards = [ 225 304 315 336 410 ]; + precautions = [ 210 240 273 "301+330+331" "302+352" "403+233" ]; + pictograms = [ ghs.pictogram.Flame ghs.pictogram.Health ghs.pictogram.Exclam ghs.pictogram.Pollu ]; + signal = ghs.signal.Danger; + }; + kemler = 33; + }; + identifiers + = { + cas = "142-82-5"; + ec = "205-563-8"; + un = 1206; + }; + sources = [ sources.gestis ]; + asof = "2020-02-16"; + }; + "Hexane" + = { + name + = { + deu = "Hexan"; + eng = "Hexane"; + }; + availability + = { + }; + physical + = { + formula = "H3C(CH2)4CH3"; + density = 0.66; + melting = -95; + boiling = 69; + nD20 = 1.3727; + }; + hazmat + = { + ghs + = { + hazards = [ 225 304 "361f" 373 315 335 336 411 ]; + precautions = [ 210 240 273 "301+310" 331 "302+352" "403+235" ]; + pictograms = [ ghs.pictogram.Flame ghs.pictogram.Health ghs.pictogram.Exclam ghs.pictogram.Pollu ]; + signal = ghs.signal.Danger; + }; + nfpa + = { + fire = 1; + health = 2; + reaction = 0; + other = nfpa.None; + }; + kemler = 33; + }; + identifiers + = { + cas = "110-54-3"; + ec = "203-777-6"; + un = 1208; + }; + sources = [ sources.gestis ]; + asof = "2020-07-12"; + }; + "Hydrazine monohydrate" + = { + name + = { + deu = "Hydrazin||mono|hydrat"; + eng = "Hydrazine mono|hydrate"; + }; + availability + = { + }; + physical + = { + formula = "H2NNH2.H2O"; + density = 1.03; + melting = -51.7; + boiling = 120.5; + nD20 = 1.47; + }; + hazmat + = { + ghs + = { + hazards = [ 301 311 330 314 317 350 410 ]; + precautions = [ 201 260 273 280 "304+340" 310 "305+351+338" ]; + pictograms = [ ghs.pictogram.Skull ghs.pictogram.Health ghs.pictogram.Acid ghs.pictogram.Pollu ]; + signal = ghs.signal.Danger; + }; + nfpa + = { + fire = 4; + health = 4; + reaction = 3; + other = nfpa.None; + }; + kemler = 86; + }; + identifiers + = { + cas = "7803-57-8"; + ec = "206-114-9"; + un = 2030; + }; + sources = [ sources.gestis ]; + asof = "2020-07-13"; + }; + "Hydrochloric acid" + = { + name + = { + deu = "Salz||säure"; + eng = "Hydro||chloric acid"; + }; + availability + = { + }; + hazmat + = { + ghs + = { + hazards = [ 290 314 335 ]; + precautions = [ 260 280 "303+361+353" "304+340" 310 "305+351+338" ]; + pictograms = [ ghs.pictogram.Acid ghs.pictogram.Exclam ]; + signal = ghs.signal.Danger; + }; + kemler = 80; + }; + identifiers + = { + cas = "7647-01-0"; + ec = "231-595-7"; + un = 1789; + }; + sources = [ sources.gestis ]; + asof = "2020-02-16"; + }; + "Hydrofluoric acid" + = { + name + = { + deu = "Fluss||säure"; + eng = "Hydro||fluoric acid"; + }; + availability + = { + }; + hazmat + = { + ghs + = { + hazards = [ 300 310 330 314 ]; + precautions = [ 260 280 "301+330+331" 310 "303+361+353" "304+340" "305+351+338" ]; + pictograms = [ ghs.pictogram.Skull ghs.pictogram.Acid ]; + signal = ghs.signal.Danger; + }; + kemler = 886; + }; + identifiers + = { + cas = "7664-39-3"; + ec = "231-634-8"; + un = 1790; + }; + sources = [ sources.gestis ]; + asof = "2020-02-16"; + }; + "Hydrogen" + = { + name + = { + deu = "Wasserstoff"; + eng = "Hydrogen"; + }; + availability + = { + }; + hazmat + = { + ghs + = { + hazards = [ 220 280 ]; + precautions = [ 210 377 381 403 ]; + pictograms = [ ghs.pictogram.Flame ghs.pictogram.Bottle ]; + signal = ghs.signal.Danger; + }; + kemler = 23; + }; + identifiers + = { + cas = "1333-74-0"; + ec = "215-605-7"; + un = 1049; + }; + sources = [ sources.gestis ]; + asof = "2020-02-16"; + }; + "Iodine" + = { + name + = { + deu = "Iod"; + eng = "Iodine"; + }; + availability + = { + }; + physical + = { + formula = "I2"; + density = 4.94; + melting = 113.7; + boiling = 184; + }; + hazmat + = { + ghs + = { + hazards = [ 312 332 315 319 335 372 400 ]; + precautions = [ 273 "302+352" "305+351+338" 314 ]; + pictograms = [ ghs.pictogram.Health ghs.pictogram.Exclam ghs.pictogram.Pollu ]; + signal = ghs.signal.Warning; + }; + }; + identifiers + = { + cas = "7553-56-2"; + ec = "231-442-4"; + }; + sources = [ sources.gestis ]; + asof = "2020-07-11"; + }; + "Iron(II) sulfate" + = { + name + = { + deu = "Eisen(II)-sulfat"; + eng = "Iron(II) sulfate"; + }; + availability + = { + }; + hazmat + = { + ghs + = { + hazards = [ 302 319 315 ]; + precautions = [ "305+351+338" ]; + pictograms = [ ghs.pictogram.Exclam ]; + signal = ghs.signal.Warning; + }; + }; + identifiers + = { + cas = "7720-78-7"; + ec = "231-753-5"; + }; + sources = [ sources.gestis ]; + asof = "2020-02-16"; + }; + "Iron(III) chloride" + = { + name + = { + deu = "Eisen(III)-chlorid"; + eng = "Iron(III) chloride"; + }; + availability + = { + }; + hazmat + = { + ghs + = { + hazards = [ 290 302 315 318 317 ]; + precautions = [ 280 "302+352" "305+351+338" ]; + pictograms = [ ghs.pictogram.Acid ghs.pictogram.Exclam ]; + signal = ghs.signal.Danger; + }; + kemler = 80; + }; + identifiers + = { + cas = "7705-08-0"; + ec = "231-729-4"; + un = 1773; + }; + sources = [ sources.gestis ]; + asof = "2020-02-16"; + }; + "MPTS" + = { + name + = { + deu = "3-(Methoxy(poly|ethylenoxy)||propyl)||tri|methoxy||silan"; + eng = ""; + }; + label = "acronym:mpts"; + availability + = { + }; + hazmat + = { + ghs + = { + hazards = [ 315 319 335 ]; + precautions = [ 261 "305+351+338" 280 271 264 "302+352" "304+340" 312 321 "332+313" "337+313" 362 "403+233" 405 501 ]; + pictograms = [ ghs.pictogram.Exclam ]; + signal = ghs.signal.Warning; + }; + }; + identifiers + = { + cas = "65994-07-2"; + ec = ""; + }; + sources = [ sources.MPTS ]; + asof = "2020-02-16"; + }; + "Mesitylene" + = { + name + = { + deu = "Mesitylen"; + eng = "Mesitylene"; + }; + availability + = { + }; + physical + = { + formula = "C9H12"; + density = 0.87; + melting = -45; + boiling = 165; + nD20 = 1.4994; + }; + hazmat + = { + ghs + = { + hazards = [ 226 304 315 319 335 411 ]; + precautions = [ 210 273 "301+310" 331 "302+352" "304+340" 312 ]; + pictograms = [ ghs.pictogram.Flame ghs.pictogram.Health ghs.pictogram.Exclam ghs.pictogram.Pollu ]; + signal = ghs.signal.Danger; + }; + iso7010 + = { + warnings = [ ]; + }; + nfpa + = { + fire = 2; + health = 2; + reaction = 0; + other = nfpa.None; + }; + kemler = 30; + }; + identifiers + = { + cas = "108-67-8"; + ec = "203-604-4 2"; + un = 2325; + }; + sources = [ sources.gestis ]; + asof = "2020-07-24"; + }; + "Methanoic acid" + = { + name + = { + deu = "Methan||säure"; + eng = "Methanoic acid"; + }; + availability + = { + }; + hazmat + = { + ghs + = { + hazards = [ 226 302 314 331 ]; + euHazards = [ 71 ]; + precautions = [ 210 280 "303+361+353" "304+340" 310 "305+351+338" "403+233" ]; + pictograms = [ ghs.pictogram.Flame ghs.pictogram.Skull ghs.pictogram.Acid ]; + signal = ghs.signal.Danger; + }; + kemler = 83; + }; + identifiers + = { + cas = "64-18-6"; + ec = "200-579-1"; + un = 1779; + }; + sources = [ sources.gestis ]; + asof = "2020-02-16"; + }; + "Methanol" + = { + name + = { + deu = "Methanol"; + eng = "Methanol"; + }; + availability + = { + }; + physical + = { + formula = "H3COH"; + density = 0.79; + melting = -98; + boiling = 65; + nD20 = 1.3288; + }; + hazmat + = { + ghs + = { + hazards = [ 225 331 311 301 370 ]; + precautions = [ 210 233 280 "302+352" "304+340" "308+313" "403+235" ]; + pictograms = [ ghs.pictogram.Flame ghs.pictogram.Skull ghs.pictogram.Health ]; + signal = ghs.signal.Danger; + }; + nfpa + = { + fire = 1; + health = 2; + reaction = 0; + other = nfpa.None; + }; + kemler = 336; + }; + identifiers + = { + cas = "67-56-1"; + ec = "200-659-6"; + un = 1230; + }; + sources = [ sources.gestis ]; + asof = "2020-07-12"; + }; + "Nickel(II)-nitrate-hexahydrate" + = { + name + = { + deu = "Nickel(II)-nitrat||hexa|hydrat"; + eng = "Nickel(II) nitrate hexa|hydrate"; + }; + availability + = { + }; + hazmat + = { + ghs + = { + hazards = [ "351i" 341 "360D" 372 272 332 302 315 318 334 317 410 ]; + pictograms = [ ghs.pictogram.OFlame ghs.pictogram.Acid ghs.pictogram.Health ghs.pictogram.Exclam ghs.pictogram.Pollu ]; + signal = ghs.signal.Danger; + }; + kemler = 50; + }; + identifiers + = { + cas = "13478-00-7"; + ec = "238-076-4"; + un = 2725; + }; + sources = [ sources.gestis ]; + asof = "2020-02-16"; + }; + "Nitric acid" + = { + name + = { + deu = "Salpeter||säure"; + eng = "Nitric acid"; + }; + availability + = { + }; + hazmat + = { + ghs + = { + hazards = [ 272 290 314 ]; + euHazards = [ 71 ]; + precautions = [ 280 "301+330+331" "304+340" "305+351+338" 310 ]; + pictograms = [ ghs.pictogram.OFlame ghs.pictogram.Acid ]; + signal = ghs.signal.Danger; + }; + kemler = 885; + }; + identifiers + = { + cas = "7697-37-2"; + ec = "231-714-2"; + un = 2031; + }; + sources = [ sources.gestis ]; + asof = "2020-02-16"; + }; + "Nitrobenzene" + = { + name + = { + deu = "Nitro||benzen"; + eng = "Nitro||benzene"; + }; + availability + = { + }; + hazmat + = { + ghs + = { + hazards = [ "360F" 301 311 331 351 372 412 ]; + precautions = [ 201 273 280 "302+352" "304+340" "308+313" ]; + pictograms = [ ghs.pictogram.Skull ghs.pictogram.Health ]; + signal = ghs.signal.Danger; + }; + }; + identifiers + = { + cas = "98-95-3"; + ec = "202-716-0"; + }; + sources = [ sources.gestis ]; + asof = "2020-02-16"; + }; + "Nitrogen" + = { + name + = { + deu = "Stickstoff"; + eng = "Nitrogen"; + }; + availability + = { + }; + hazmat + = { + ghs + = { + hazards = [ 280 ]; + precautions = [ 403 ]; + pictograms = [ ghs.pictogram.Bottle ]; + signal = ghs.signal.Warning; + }; + kemler = 20; + }; + identifiers + = { + cas = "7727-37-9"; + ec = "231-783-9"; + un = 1066; + }; + sources = [ sources.gestis ]; + asof = "2020-02-16"; + }; + "Nitrogen (liquid)" + = { + name + = { + deu = "Flüssig||stickstoff"; + eng = "Liquid Nitrogen"; + }; + availability + = { + }; + hazmat + = { + ghs + = { + hazards = [ 280 281 ]; + precautions = [ 282 336 315 403 ]; + pictograms = [ ghs.pictogram.Bottle ]; + signal = ghs.signal.Warning; + }; + iso7010 + = { + warnings = [ 10 ]; + }; + kemler = 22; + }; + identifiers + = { + cas = "7727-37-9"; + ec = "231-783-9"; + un = 1977; + }; + sources = [ sources.liquidNitrogen ]; + asof = "2020-02-16"; + }; + "ODES" + = { + name + = { + deu = "n-Octadecyl||tri|ethoxy||silan"; + eng = ""; + }; + label = "acronym:odes"; + availability + = { + }; + hazmat + = { + ghs + = { + hazards = [ 315 319 ]; + precautions = [ "305+351+338" ]; + pictograms = [ ghs.pictogram.Exclam ]; + signal = ghs.signal.Warning; + }; + }; + identifiers + = { + cas = "7399-00-0"; + ec = "230-995-9"; + }; + sources = [ sources.gestis ]; + asof = "2020-02-16"; + }; + "PFOTES" + = { + name + = { + deu = "1H,1H,2H,2H-Per|fluor||octyl||tri|ethoxy||silan"; + eng = "Tri|ethoxy(1H,1H,2H,2H-per|fluoro-1-octyl)silane"; + }; + label = "acronym:pfotes"; + availability + = { + }; + hazmat + = { + ghs + = { + hazards = [ 315 319 335 413 ]; + precautions = [ 280 "305+351+338" 313 ]; + pictograms = [ ghs.pictogram.Exclam ]; + signal = ghs.signal.Warning; + }; + }; + identifiers + = { + cas = "51851-37-7"; + ec = "257-473-3"; + }; + sources = [ sources.PFOTES ]; + asof = "2020-02-16"; + }; + "PMMA" + = { + name + = { + deu = "Poly|methyl||methacrylat"; + eng = "Poly(methyl methacrylate)"; + }; + label = "acronym:pmma"; + availability + = { + }; + hazmat + = { + ghs + = { + signal = ghs.signal.None; + }; + }; + identifiers + = { + cas = "9011-14-7"; + ec = ""; + }; + sources = [ sources.gestis ]; + asof = "2020-02-16"; + }; + "PTFE" + = { + name + = { + deu = "Poly|tetra|fluor||ethylen"; + eng = "Poly(tetra|fluor||ethylene)"; + }; + label = "acronym:ptfe"; + availability + = { + }; + hazmat + = { + ghs + = { + signal = ghs.signal.None; + }; + }; + identifiers + = { + cas = "9002-84-0"; + ec = ""; + }; + sources = [ sources.gestis ]; + asof = "2020-02-16"; + }; + "Petroleum ether" + = { + name + = { + deu = "Petrolether"; + eng = "Petroleum ether"; + }; + availability + = { + }; + physical + = { + density = 0; + melting = 0; + boiling = 0; + decompose = 0; + nD20 = 0; + }; + hazmat + = { + ghs + = { + hazards = [ 225 304 315 336 "361f" 373 411 ]; + precautions = [ 201 210 "301+310" 331 "370+378" 501 ]; + pictograms = [ ghs.pictogram.Flame ghs.pictogram.Health ghs.pictogram.Exclam ghs.pictogram.Pollu ]; + signal = ghs.signal.Danger; + }; + iso7010 + = { + warnings = [ ]; + }; + nfpa + = { + fire = 2; + health = 4; + reaction = 0; + other = nfpa.None; + }; + kemler = 33; + }; + identifiers + = { + cas = "8032-32-4"; + ec = "232-453-7"; + un = 3295; + }; + sources = [ sources.gestis ]; + asof = "2020-07-22"; + }; + "Phenol" + = { + name + = { + deu = "Phenol"; + eng = "Phenol"; + }; + availability + = { + }; + hazmat + = { + ghs + = { + hazards = [ 301 311 331 314 341 373 411 ]; + precautions = [ 260 280 "301+330+331" "303+361+353" "304+340" 310 "305+351+338" ]; + pictograms = [ ghs.pictogram.Skull ghs.pictogram.Acid ghs.pictogram.Health ]; + signal = ghs.signal.Danger; + }; + kemler = 60; + }; + identifiers + = { + cas = "108-95-2"; + ec = "203-632-7"; + un = 1671; + }; + sources = [ sources.gestis ]; + asof = "2020-02-16"; + }; + "Phenolphthalein" + = { + name + = { + deu = "Phenol||phthalein"; + eng = "3,3-Bis(4-hydroxyphenyl)-2-benzofuran-1(3H)-one (Phenol||phthalein)"; + }; + availability + = { + }; + hazmat + = { + ghs + = { + hazards = [ 341 350 "361f" ]; + precautions = [ 201 280 "308+313" ]; + pictograms = [ ghs.pictogram.Health ]; + signal = ghs.signal.Danger; + }; + }; + identifiers + = { + cas = "77-09-8"; + ec = "201-004-7"; + }; + sources = [ sources.gestis ]; + asof = "2020-02-16"; + }; + "Phthalic acid" + = { + name + = { + deu = "Benzen-1,2-di|carbon||säure (o-Phthal||säure)"; + eng = "Benzene-1,2-di|carboxylic acid (o-Phthalic acid)"; + }; + availability + = { + }; + hazmat + = { + ghs + = { + hazards = [ 335 315 319 ]; + precautions = [ 280 "301+330+331" "304+340" "305+351+338" "308+310" ]; + pictograms = [ ghs.pictogram.Exclam ]; + signal = ghs.signal.Warning; + }; + }; + identifiers + = { + cas = "88-99-3"; + ec = "201-873-2"; + }; + sources = [ sources.gestis ]; + asof = "2020-02-16"; + }; + "Pivalic acid" + = { + name + = { + deu = "Pivalin||säure"; + eng = "Pivalic acid"; + }; + availability + = { + }; + hazmat + = { + ghs + = { + hazards = [ 302 312 315 318 ]; + precautions = [ 280 "302+352" "305+351+338" 313 ]; + pictograms = [ ghs.pictogram.Acid ghs.pictogram.Exclam ]; + signal = ghs.signal.Danger; + }; + }; + identifiers + = { + cas = "75-98-9"; + ec = "200-922-5 "; + }; + sources = [ sources.gestis ]; + asof = "2020-02-16"; + }; + "Potassium bromide" + = { + name + = { + deu = "Kalium||bromid"; + eng = "Potassium bromide"; + }; + availability + = { + }; + hazmat + = { + ghs + = { + hazards = [ 319 ]; + precautions = [ "305+351+338" ]; + pictograms = [ ghs.pictogram.Exclam ]; + signal = ghs.signal.Warning; + }; + }; + identifiers + = { + cas = "7758-02-3"; + ec = "231-830-3"; + }; + sources = [ sources.gestis ]; + asof = "2020-02-16"; + }; + "Potassium chloride" + = { + name + = { + deu = "Kalium||chlorid"; + eng = "Potassium chloride"; + }; + availability + = { + }; + hazmat + = { + ghs + = { + signal = ghs.signal.None; + }; + }; + identifiers + = { + cas = "7447-40-7"; + ec = "231-211-8"; + }; + sources = [ sources.gestis ]; + asof = "2020-02-16"; + }; + "Potassium fluoride" + = { + name + = { + deu = "Kalium||fluorid"; + eng = "Potassium fluoride"; + }; + availability + = { + }; + hazmat + = { + ghs + = { + hazards = [ "301+311+331" ]; + precautions = [ 280 "302+352" "304+340" "308+310" ]; + pictograms = [ ghs.pictogram.Skull ]; + signal = ghs.signal.Danger; + }; + kemler = 60; + }; + identifiers + = { + cas = "7789-23-3"; + ec = "232-151-5"; + un = 1812; + }; + sources = [ sources.gestis ]; + asof = "2020-02-16"; + }; + "Potassium hydroxide" + = { + name + = { + deu = "Kalium||hydroxid"; + eng = "Potassium hydroxide"; + }; + availability + = { + }; + hazmat + = { + ghs + = { + hazards = [ 290 302 314 ]; + precautions = [ 280 "301+330+331" "305+351+338" "308+313" ]; + pictograms = [ ghs.pictogram.Acid ghs.pictogram.Exclam ]; + signal = ghs.signal.Danger; + }; + kemler = 80; + }; + identifiers + = { + cas = "1310-58-3"; + ec = "215-181-3"; + un = 1813; + }; + sources = [ sources.gestis ]; + asof = "2020-02-16"; + }; + "Potassium iodide" + = { + name + = { + deu = "Kalium||iodid"; + eng = "Potassium iodid"; + }; + availability + = { + }; + hazmat + = { + ghs + = { + signal = ghs.signal.None; + }; + }; + identifiers + = { + cas = "7681-11-0"; + ec = "231-659-4"; + }; + sources = [ sources.gestis ]; + asof = "2020-02-16"; + }; + "Potassium nitrate" + = { + name + = { + deu = "Kalium||nitrat"; + eng = "Potassium nitrate"; + }; + availability + = { + }; + hazmat + = { + ghs + = { + hazards = [ 272 ]; + precautions = [ 210 221 ]; + pictograms = [ ghs.pictogram.OFlame ]; + signal = ghs.signal.Warning; + }; + kemler = 50; + }; + identifiers + = { + cas = "7757-79-1"; + ec = "231-818-8"; + un = 1486; + }; + sources = [ sources.gestis ]; + asof = "2020-02-16"; + }; + "Potassium persulfate" + = { + name + = { + deu = "Kalium||per|oxodi|sulfat"; + eng = "Potassium per|sulfate"; + }; + availability + = { + }; + hazmat + = { + ghs + = { + hazards = [ 272 302 315 317 319 334 335 ]; + precautions = [ 220 261 280 "305+351+338" "342+311" ]; + pictograms = [ ghs.pictogram.OFlame ghs.pictogram.Health ghs.pictogram.Exclam ]; + signal = ghs.signal.Danger; + }; + kemler = 50; + }; + identifiers + = { + cas = "7727-21-1"; + ec = "231-781-8"; + un = 1492; + }; + sources = [ sources.gestis ]; + asof = "2020-02-16"; + }; + "Potassium sulfate" + = { + name + = { + deu = "Kalium||sulfat"; + eng = "Potassium sulfate"; + }; + availability + = { + }; + hazmat + = { + ghs + = { + signal = ghs.signal.None; + }; + }; + identifiers + = { + cas = "7778-80-5"; + ec = "231-915-5"; + }; + sources = [ sources.gestis ]; + asof = "2020-02-16"; + }; + "Propane-1,2,3-triol" + = { + name + = { + deu = "Propan-1,2,3-tri|ol (Glycerin)"; + eng = "Propane-1,2,3-tri|ol (Glycerol)"; + }; + availability + = { + }; + hazmat + = { + ghs + = { + signal = ghs.signal.None; + }; + }; + identifiers + = { + cas = "56-81-5"; + ec = "200-289-5"; + }; + sources = [ sources.gestis ]; + asof = "2020-02-16"; + }; + "Pyridine" + = { + name + = { + deu = "Pyridin"; + eng = "Pyridine"; + }; + availability + = { + }; + hazmat + = { + ghs + = { + hazards = [ 225 332 302 312 319 315 ]; + precautions = [ 210 280 "305+351+338" ]; + pictograms = [ ghs.pictogram.Flame ghs.pictogram.Exclam ]; + signal = ghs.signal.Danger; + }; + kemler = 33; + }; + identifiers + = { + cas = "110-86-1"; + ec = "203-809-9"; + un = 1282; + }; + sources = [ sources.gestis ]; + asof = "2020-02-16"; + }; + "Rhodamine B" + = { + name + = { + deu = "Rhodamin B"; + eng = "Rhodamine B"; + }; + availability + = { + }; + hazmat + = { + ghs + = { + hazards = [ 318 412 ]; + precautions = [ 260 273 280 "305+351+338" ]; + pictograms = [ ghs.pictogram.Acid ]; + signal = ghs.signal.Danger; + }; + }; + identifiers + = { + cas = "81-88-9"; + ec = "201-383-9"; + }; + sources = [ sources.gestis ]; + asof = "2020-02-16"; + }; + "Salicylic acid" + = { + name + = { + deu = "2-Hydroxy||benzoe||säure (Salicyl||säure)"; + eng = "2-Hydroxy||benzoic acid (Salicylic acid)"; + }; + availability + = { + }; + hazmat + = { + ghs + = { + hazards = [ 302 318 ]; + precautions = [ 270 280 "305+351+338" ]; + pictograms = [ ghs.pictogram.Acid ghs.pictogram.Exclam ]; + signal = ghs.signal.Danger; + }; + }; + identifiers + = { + cas = "69-72-7"; + ec = "200-712-3"; + }; + sources = [ sources.gestis ]; + asof = "2020-02-16"; + }; + "Silver nitrate" + = { + name + = { + deu = "Silber||nitrat"; + eng = "Silver nitrate"; + }; + availability + = { + }; + hazmat + = { + ghs + = { + hazards = [ 272 290 314 410 ]; + precautions = [ 210 220 260 280 "305+351+338" { id = "370+378"; dots = { deu = "Löschpulver oder Trockensand"; }; } 308 310 ]; + pictograms = [ ghs.pictogram.OFlame ghs.pictogram.Acid ghs.pictogram.Pollu ]; + signal = ghs.signal.Danger; + }; + kemler = 50; + }; + identifiers + = { + cas = "7761-88-8"; + ec = "231-853-9"; + un = 1493; + }; + sources = [ sources.gestis ]; + asof = "2020-02-16"; + }; + "Sodium dodecyl sulfate" + = { + name + = { + deu = "Natrium||dodecyl||sulfat"; + eng = "Sodium dodecyl sulfate"; + }; + availability + = { + }; + hazmat + = { + ghs + = { + hazards = [ 228 302 332 315 318 335 412 ]; + precautions = [ 210 261 280 "301+312" "301+330+331" "305+351+338" 310 { id = "370+378"; dots = { deu = "Löschpulver oder Trockensand"; }; } ]; + pictograms = [ ghs.pictogram.Flame ghs.pictogram.Acid ghs.pictogram.Exclam ]; + signal = ghs.signal.Danger; + }; + }; + identifiers + = { + cas = "151-21-3"; + ec = "205-788-1"; + }; + sources = [ sources.gestis ]; + asof = "2020-02-16"; + }; + "Sodium hydroxide" + = { + name + = { + deu = "Natrium||hydroxid"; + eng = "Sodium hydroxide"; + }; + availability + = { + }; + hazmat + = { + ghs + = { + hazards = [ 290 314 ]; + precautions = [ 280 "301+330+331" "305+351+338" "308+313" ]; + pictograms = [ ghs.pictogram.Acid ]; + signal = ghs.signal.Danger; + }; + kemler = 80; + }; + identifiers + = { + cas = "1310-73-2"; + ec = "215-185-5"; + un = 1823; + }; + sources = [ sources.gestis ]; + asof = "2020-02-16"; + }; + "Sodium thiosulfate" + = { + name + = { + deu = "Natrium||thio||sulfat"; + eng = "Sodium thio||sulfate"; + }; + availability + = { + }; + hazmat + = { + ghs + = { + signal = ghs.signal.None; + }; + }; + identifiers + = { + cas = "7772-98-7"; + ec = "231-867-5"; + }; + sources = [ sources.gestis ]; + asof = "2020-02-16"; + }; + "Sulfuric acid" + = { + name + = { + deu = "Schwefel||säure"; + eng = "Sulfuric acid"; + }; + availability + = { + }; + hazmat + = { + ghs + = { + hazards = [ 290 314 ]; + precautions = [ 280 "301+330+331" "305+351+338" 308 310 ]; + pictograms = [ ghs.pictogram.Acid ]; + signal = ghs.signal.Danger; + }; + kemler = 80; + }; + identifiers + = { + cas = "7664-93-9"; + ec = "231-639-5"; + un = 1830; + }; + sources = [ sources.gestis ]; + asof = "2020-02-16"; + }; + "TEOS" + = { + name + = { + deu = "Tetra|ethyl||ortho|silicat"; + eng = "Tetra|ethyl ortho|silicate"; + }; + label = "acronym:teos"; + availability + = { + }; + hazmat + = { + ghs + = { + hazards = [ 226 332 319 335 ]; + precautions = [ 210 261 280 "303+361+353" "304+340" 312 "370+378" "403+235" ]; + pictograms = [ ghs.pictogram.Flame ghs.pictogram.Exclam ]; + signal = ghs.signal.Warning; + }; + kemler = 30; + }; + identifiers + = { + cas = "78-10-4"; + ec = "201-083-8"; + un = 1292; + }; + sources = [ sources.gestis ]; + asof = "2020-02-16"; + }; + "TFPTMS" + = { + name + = { + deu = "Tri|methoxy(3,3,3-tri|fluor||propyl)||silan"; + eng = ""; + }; + label = "acronym:tfptms"; + availability + = { + }; + hazmat + = { + ghs + = { + hazards = [ 226 315 319 335 ]; + precautions = [ 261 "305+351+338" ]; + pictograms = [ ghs.pictogram.Flame ghs.pictogram.Exclam ]; + signal = ghs.signal.Warning; + }; + }; + identifiers + = { + cas = "429-60-7"; + ec = "215-647-6"; + }; + sources = [ sources.TFPTMS ]; + asof = "2020-02-16"; + }; + "TPM" + = { + name + = { + deu = "3-(Tri|methoxy||silyl)||propyl||methacrylat"; + eng = ""; + }; + label = "acronym:tpm"; + availability + = { + }; + hazmat + = { + ghs + = { + signal = ghs.signal.None; + }; + }; + identifiers + = { + cas = "2530-85-0"; + ec = "219-785-8"; + }; + sources = [ sources.gestis ]; + asof = "2020-02-16"; + }; + "Tetrahydrofuran" + = { + name + = { + deu = "Tetra|hydro||furan"; + eng = "Tetra|hydro||furan"; + }; + availability + = { + }; + physical + = { + formula = "C4H8O"; + density = 0.8876; + melting = -108.4; + boiling = 66; + nD20 = 1.4073; + }; + hazmat + = { + ghs + = { + hazards = [ 225 302 319 335 351 ]; + euHazards = [ 19 ]; + precautions = [ 210 280 "301+312" 330 "305+351+338" { dots = "Löschpulver oder Trockensand"; id = "370+378"; } "403+235" ]; + pictograms = [ ghs.pictogram.Flame ghs.pictogram.Exclam ghs.pictogram.Health ]; + signal = ghs.signal.Danger; + }; + iso7010 + = { + warnings = [ 10 ]; + }; + nfpa + = { + fire = 2; + health = 3; + reaction = 1; + other = nfpa.None; + }; + kemler = 33; + }; + identifiers + = { + cas = "109-99-9"; + ec = "203-726-8"; + un = 2056; + }; + sources = [ sources.gestis ]; + asof = "2020-02-23"; + }; + "Toluene" + = { + name + = { + deu = "Toluen"; + eng = "Toluene"; + }; + availability + = { + }; + hazmat + = { + ghs + = { + hazards = [ 225 "361d" 304 373 315 336 ]; + precautions = [ 210 240 "301+310" "301+330+331" "302+352" "308+313" 314 "403+233" ]; + pictograms = [ ghs.pictogram.Flame ghs.pictogram.Health ghs.pictogram.Exclam ]; + signal = ghs.signal.Danger; + }; + kemler = 33; + }; + identifiers + = { + cas = "108-88-3"; + ec = "203-625-9"; + un = 1294; + }; + sources = [ sources.gestis ]; + asof = "2020-02-16"; + }; + "Trichlormethane" + = { + name + = { + deu = "Tri|chlor||methan"; + eng = "Tri|chlor||methane"; + }; + availability + = { + }; + hazmat + = { + ghs + = { + hazards = [ 302 331 315 319 351 "361d" 336 372 ]; + precautions = [ 261 280 "305+351+338" 311 ]; + pictograms = [ ghs.pictogram.Skull ghs.pictogram.Health ]; + signal = ghs.signal.Danger; + }; + kemler = 60; + }; + identifiers + = { + cas = "67-66-3"; + ec = "200-663-8"; + un = 1888; + }; + sources = [ sources.gestis ]; + asof = "2020-02-16"; + }; + "Triphenylphosphane" + = { + name + = { + deu = "Tri|phenyl||phosphan"; + eng = "Tri|phenyl||phosphane"; + }; + availability + = { + }; + physical + = { + formula = "PPh3"; + density = 1.19; + melting = 80; + boiling = 360; + }; + hazmat + = { + ghs + = { + hazards = [ 302 317 373 ]; + precautions = [ 280 "301+312" "301+330+331" "333+313" ]; + pictograms = [ ghs.pictogram.Health ghs.pictogram.Exclam ]; + signal = ghs.signal.Warning; + }; + nfpa + = { + fire = 2; + health = 1; + reaction = 2; + other = nfpa.None; + }; + }; + identifiers + = { + cas = "603-35-0"; + ec = "210-036-0"; + }; + sources = [ sources.gestis ]; + asof = "2020-07-11"; + }; + "Water" + = { + name + = { + deu = "Wasser"; + eng = "Water"; + }; + availability + = { + }; + physical + = { + formula = "H2O"; + density = 1; + melting = 0; + boiling = 100; + nD20 = 1.3325; + }; + hazmat + = { + ghs + = { + signal = ghs.signal.None; + }; + }; + identifiers + = { + cas = "7732-18-5"; + ec = "231-791-2"; + }; + sources = [ sources.gestis ]; + asof = "2020-02-16"; + }; +} diff --git a/NixTeX/assets/people/default.nix b/NixTeX/assets/people/default.nix new file mode 100644 index 0000000..1147ce4 --- /dev/null +++ b/NixTeX/assets/people/default.nix @@ -0,0 +1,4 @@ +{ ... }: +{ + +} \ No newline at end of file diff --git a/NixTeX/default.nix b/NixTeX/default.nix new file mode 100644 index 0000000..8341f55 --- /dev/null +++ b/NixTeX/default.nix @@ -0,0 +1,234 @@ +{ core, fork-awesome, nixpkgs, stdenv, ... } @ libs: + let + inherit(core) debug lambda library list path set string target type; + nixtex = library.import ./source libs; + + collectDependencies#: Dependencies -> Dependencies | ! + = list.fold + ( + { ... } @ state: + { dst, src ? null }: + if src == null || dst == null then state + else if state.${dst} or null == null then state // { ${dst} = src; } + else if state.${dst} == src then state + else if lambda.isInstanceOf state.${dst} + && lambda.isInstanceOf src then state # Cannot compae tasks :c + else + debug.panic "collectDependencies" + "Cannot set ${dst}, because it is already set!" + ) + {}; + + collectDirectories#: { string -> { ... } } -> { string -> null } + = set.fold + ( + { ... } @ directories: + dst: + src: + let + directory = path.getDirectory dst; + in + if directory != "." + then + directories + // { + ${directory} = null; + } + else + directories + ) + {}; + + collectFileSet + = { local ? null, store ? null, ... }: + if local != null + then + path.toStore local + else if store != null + then + store + else + null; + + collectFiles#: { string -> { path: string | path ? null ... } | string } -> [ string ] + = set.fold + ( + files: + dst: + src: + type.matchPrimitiveOrPanic src + { + lambda = files; # Ignore Tasks + path = files ++ [ { src = path.toStore src; inherit dst; } ]; + set + = let + src' = collectFileSet src; + in + if src' != null + then + files ++ [ { src = src'; inherit dst; } ] + else + files; + string + = debug.warn + "collectFiles" + { + text = "I assume, that »${src}« is in the nix-store."; + when = string.getContext src == {}; + } + ( files ++ [ { inherit dst src; } ] ); + } + ) + []; + + collectTasks#: { string -> { cmd: string -> string ? null, ... } | string } -> [ string ] + = set.fold + ( + tasks: + dst: + src: + if set.isInstanceOf src + && src.cmd or null != null + then + tasks ++ [ (src.cmd "$out/${dst}") ] + else if lambda.isInstanceOf src + then + tasks ++ [ (src "$out/${dst}") ] + else + tasks + ) + []; + + toDerivation#: System -> Document -> derivation + = system: + { name, dependencies, ... }: + let + system' = string system; + pkgs = nixpkgs.legacyPackages.${system'}; + + dependencies' = collectDependencies dependencies; + directories + = list.map + (dictionary: "mkdir -p \"$out/${dictionary}\"") + (set.names (collectDirectories dependencies')); + links + = list.map + ({ dst, src }: "ln -s \"${src}\" \"$out/${dst}\"") + (collectFiles dependencies'); + tasks = collectTasks dependencies'; + + builder + = path.toFile "builder.sh" + '' + #!/usr/bin/env bash + source $stdenv/setup + export HOME=$(mktemp -d) + + # ensure that all output directories exist + mkdir -p "$out" + ln -s "$out" ./ + ${string.concatLines directories} + + # link already generated files + ${string.concatLines links} + + # generate some more files + ${string.concatLines tasks} + + mkdir -p "$out/fonts/" + fc-list -f "%{file}\n" | while read fileName + do + base="$(basename "$fileName")" + link="$(echo "$base" | sed "s/ /-/g")" + ln -s "$fileName" "$out/fonts/$link" + done + + # compile document + bash $out/compile-${name}.sh "$out" + ''; + + FONTCONFIG_FILE + = pkgs.makeFontsConf + { + fontDirectories + = with pkgs;#in + [ + #dejavu_fonts + font-awesome + fork-awesome.packages.${system'}.default + #"${ghostscript}/share/ghostscript/fonts" + liberation_ttf + #lmodern + noto-fonts + #noto-fonts-emoji + #noto-fonts-extra + roboto + roboto-mono + roboto-slab + unifont + ]; + }; + in + debug.info "toDerivation" + { + text = "builder"; + data = builder; + } + stdenv.${system'}.mkDerivation + { + inherit name builder; + system = system'; + buildInputs + = with pkgs;#in + [ + exa + fontconfig + ghostscript # for gs + gnuplot + ncurses # for tput + texlive.combined.scheme-full # for lualatex + ]; + inherit FONTCONFIG_FILE; + }; + + mapToDerivations#: System -> [ Document ] -> { string -> derivation } + = system: + documents: + let + toDerivation' = toDerivation system; + in + ( + list.fold + ( + { ... } @ documents': + { name, ... } @ document: + documents' + // { + ${name} = toDerivation' document; + } + ) + {} + documents + ); + + mapToPackages#: [ Document ] -> { ... } -> { string -> derivation } + = documents: + { ... } @ environment: + target.System.mapStdenv + ( + system: + mapToDerivations system + ( + list.map + ( + documentPath: + library.import documentPath ( { inherit core nixtex; } // environment ) "tex" + ) + documents + ) + ); + in + nixtex + // { + inherit mapToDerivations mapToPackages toDerivation; + } diff --git a/NixTeX/dependencies/assets/biblatex/chem-angew.bbx b/NixTeX/dependencies/assets/biblatex/chem-angew.bbx new file mode 100644 index 0000000..a2511d5 --- /dev/null +++ b/NixTeX/dependencies/assets/biblatex/chem-angew.bbx @@ -0,0 +1,715 @@ +%% --------------------------------------------------------------- +%% biblatex-chem --- A set of biblatex implementations of +%% chemistry-related bibliography styles +%% Maintained by Joseph Wright +%% E-mail: joseph.wright@morningstar2.co.uk +%% Released under the LaTeX Project Public License v1.3c or later +%% See http://www.latex-project.org/lppl.txt +%% --------------------------------------------------------------- +%% + +\ProvidesFile{chem-angew.bbx}[2019/12/03 v1.1y biblatex bibliography style] + +% Load the standard style to avoid copy-pasting unnecessary material +\RequireBibliographyStyle{numeric-comp} + +% New options +\newtoggle{bbx:articletitle} +\newtoggle{bbx:chaptertitle} +\newtoggle{bbx:pageranges} +\DeclareBibliographyOption{articletitle}[true]{% + \settoggle{bbx:articletitle}{#1}% +} +\DeclareBibliographyOption{chaptertitle}[true]{% + \settoggle{bbx:chaptertitle}{#1}% +} +\DeclareBibliographyOption{pageranges}[true]{% + \settoggle{bbx:pageranges}{#1}% +} + +\DeclareBibliographyOption{biblabel}{% + \ifstrequal{#1}{plain} + {\DeclareFieldFormat{labelnumberwidth}{##1}} + {% + \ifstrequal{#1}{parens} + {\DeclareFieldFormat{labelnumberwidth}{\mkbibparens{##1}}}% + {% + \ifstrequal{#1}{dot} + {\DeclareFieldFormat{labelnumberwidth}{##1\adddot\midsentence}} + {\DeclareFieldFormat{labelnumberwidth}{\mkbibbrackets{##1}}}% + }% + }% +} + +% Alter settings that carry through from biblatex +\ExecuteBibliographyOptions + { + date = year , + doi = false , + eprint = false , + giveninits = true , + isbn = false , + maxnames = 999 , + maxcitenames = 2 , + pageranges = true , + url = false + } + +% Modify the name format +\@ifpackageloaded{biblatex_legacy} + { + \DeclareNameFormat{default}{% + \usebibmacro{name:first-last}{#1}{#4}{#5}{#7}% + \usebibmacro{name:andothers}% + } + } + { + \DeclareNameFormat{default}{% + \nameparts{#1}% + \usebibmacro{name:given-family} + {\namepartfamily} + {\namepartgiveni} + {\namepartprefix} + {\namepartsuffix}% + \usebibmacro{name:andothers}% + } + } + +% Custom field formats +\DeclareFieldFormat[inproceedings]{booktitle}{#1} +\DeclareFieldFormat{date}{\mkbibbold{#1}} +\DeclareFieldFormat{doi}{% + DOI\space + \ifhyperref + {\href{https://doi.org/#1}{\nolinkurl{#1}}} + {\nolinkurl{#1}}% +} +\DeclareFieldFormat{journaltitle}{\mkbibitalic{#1}\isdot} +\DeclareFieldFormat{labelnumberwidth}{\mkbibbrackets{#1}} +\DeclareFieldFormat[article]{pages}{% + \iftoggle{bbx:pageranges}{#1}{\mkfirstpage{#1}}% +} +\DeclareFieldFormat{removecomma}{\mkbibnocomma{#1}} +\DeclareFieldFormat{title}{„#1“} +\DeclareFieldFormat[patent]{type}{% + \ifbibstring{#1} + {\mkbibitalic{\bibstring{#1}}} + {\mkbibitalic{#1}}% +} +\DeclareFieldFormat{url}{\url{#1}} +\DeclareFieldFormat*{volume}{% + \mkbibitalic{\bibstring{volume}~#1}% +} +\DeclareFieldFormat[article]{volume}{\mkbibitalic{#1}} + +% Simple modifications to punctuation, etc. +\renewcommand*{\begrelateddelim}{\addsemicolon\space}% +\renewcommand*{\finalnamedelim}{% + \ifcurrentname{labelname} + {% + \ifnumgreater{\value{liststop}}{2} + {\finalandcomma} + {}% + \addspace + \bibstring{and}% + \space + } + {\multinamedelim}% +} +\renewcommand*{\intitlepunct}{\addspace} +\ifdef{\mkbibnamesuffix} + {\renewcommand*{\mkbibnamesuffix}} + {\renewcommand*{\mkbibnameaffix}}% + [1]{\addcomma\space#1} +\renewcommand*{\newunitpunct}{\addcomma\addspace} + +% Bibliography strings +\DefineBibliographyStrings{english}{% + chapter = Chapter , + editor = Ed\adddot , + editors = Eds\adddot , + patentus = US Pat\adddot, + volume = Vol\adddot +} + +% Bibliography macros +\renewbibmacro*{byeditor+others}{% + \ifnameundef{editor} + {} + {% + \printtext[parens]{% + \usebibmacro{editorstrg}% + \setunit{\addcolon\addspace}% + \printnames[byeditor]{editor}% + \clearname{editor}% + \newunit + }% + }% + \usebibmacro{byeditorx}% + \usebibmacro{bytranslator+others}% +} + +\renewbibmacro*{byholder}{% + \ifnameundef{holder} + {} + {\printtext[parens]{\printnames{holder}}}% +} + +\renewbibmacro*{date}{% + \iffieldundef{year} + {} + {\printtext[date]{\printdate}}% +} + +\renewbibmacro*{event+venue+date}{% + \printfield{eventtitle}% + \ifboolexpr{ + test {\iffieldundef{venue}} + and + test {\iffieldundef{eventyear}} + } + {} + {% + \printfield{venue}% + \newunit + \printeventdate + \newunit + }% +} + +\renewbibmacro*{institution+location+date}{% + \printlist{institution}% + \newunit + \printlist{location}% + \newunit + \usebibmacro{date}% + \newunit +} + +\renewbibmacro*{journal}{% + \iffieldundef{journaltitle} + {} + {% + \printtext[journaltitle]{% + \printfield[removecomma]{journaltitle}% + \setunit{\subtitlepunct}% + \printfield[removecomma]{journalsubtitle}% + }% + }% +} + +\renewbibmacro*{journal+issuetitle}{% + \usebibmacro{journal}% + \setunit*{\addspace}% + \iffieldundef{series} + {} + {\newunit + \printfield{series}% + \setunit{\addspace}}% + \usebibmacro{date}% + \newunit + \printfield{volume}% + \newunit +} + +\renewbibmacro*{maintitle}{% + \ifboolexpr{ + test {\iffieldundef{maintitle}} + and + test {\iffieldundef{mainsubtitle}} + } + {} + {% + \printtext[maintitle]{% + \printfield[titlecase]{maintitle}% + \setunit{\subtitlepunct}% + \printfield[parens]{mainsubtitle}% + }% + \newunit + }% + \printfield{maintitleaddon}% +} + +\renewbibmacro*{maintitle+booktitle}{% + \iffieldundef{maintitle} + {} + {% + \usebibmacro{maintitle}% + \newunit\newblock + }% + \usebibmacro{booktitle}% + \newunit + \iffieldundef{volume} + {} + {% + \iffieldundef{series} + {% + \printfield{volume}% + \printfield{part}% + } + {}% + }% + \newunit +} + +\renewbibmacro*{maintitle+title}{% + \iffieldsequal{maintitle}{title} + { + \clearfield{maintitle}% + \clearfield{mainsubtitle}% + \clearfield{maintitleaddon}% + } + {% + \iffieldundef{maintitle} + {} + {% + \usebibmacro{maintitle}% + \newunit + }% + }% + \usebibmacro{title}% + \newunit + \iffieldundef{volume} + {} + {% + \iffieldundef{series} + {% + \printfield{volume}% + \printfield{part}% + } + {}% + }% + \newunit + \printfield{edition}% + \newunit +} + +\renewbibmacro*{note+pages}{% + \printfield{note}% + \setunit{\bibpagespunct}% + \printfield{pages}% + \iffieldundef{pages} + {% + \printfield{doi}% + \clearfield{doi}% + }% + {}% +} + +\renewbibmacro*{publisher+location+date}{% + \printlist{publisher}% + \newunit + \printlist{location}% + \newunit + \usebibmacro{date}% + \newunit +} + +\newbibmacro*{related:translatedas}[1]{% + \entrydata{#1}{% + \usebibmacro{journal+issuetitle}% + \newunit + \usebibmacro{byeditor+others}% + \newunit + \usebibmacro{note+pages}% + \newunit\newblock + \iftoggle{bbx:isbn} + {\printfield{issn}} + {}% + \newunit\newblock + \usebibmacro{doi+eprint+url}% + }% +} + +% Specialised functions for manipulating data, where the biblatex +% kernel does not provide a suitable function. +\newcommand*\mkbibnocomma[1]{% + \in@{,}{#1}% + \ifin@ + \expandafter\bbx@no@comma + \else + \expandafter\@firstofone + \fi + {#1}% +} +\newcommand*\bbx@no@comma[1]{% + \bbx@no@comma@aux#1,\@nil,% +} +\newcommand\bbx@no@comma@aux{} +\def\bbx@no@comma@aux#1,{% + \ifx\@nil#1\else #1\expandafter\bbx@no@comma@aux\fi +} + +% New bibliography drivers, using the required order of fields. These +% are mainly copied from standard.bbx then modified. +\DeclareBibliographyDriver{article}{% + \usebibmacro{bibindex}% + \usebibmacro{begentry}% + \usebibmacro{author/translator+others}% + \setunit{\labelnamepunct}\newblock + \usebibmacro{title}% + \newunit + \usebibmacro{byauthor}% + \newunit\newblock + \usebibmacro{bytranslator+others}% + \newunit\newblock + \printfield{version}% + \newunit\newblock + \usebibmacro{journal+issuetitle}% + \newunit + \usebibmacro{byeditor+others}% + \newunit + \usebibmacro{note+pages}% + \newunit\newblock + \iftoggle{bbx:isbn} + {\printfield{issn}} + {}% + \newunit\newblock + \usebibmacro{doi+eprint+url} + \newunit\newblock + \usebibmacro{addendum+pubstate}% + \setunit{\bibpagerefpunct}\newblock + \usebibmacro{pageref}% + \newunit\newblock + \iftoggle{bbx:related} + {\usebibmacro{related:init}% + \usebibmacro{related}} + {}% + \usebibmacro{finentry}% +} + +\DeclareBibliographyDriver{book}{% + \usebibmacro{bibindex}% + \usebibmacro{begentry}% + \usebibmacro{author/translator+others}% + \setunit{\labelnamepunct}\newblock + \usebibmacro{maintitle+title}% + \newunit + \usebibmacro{byauthor}% + \newunit\newblock + \usebibmacro{byeditor+others}% + \newunit\newblock + \newunit + \printfield{volumes}% + \newunit\newblock + \printfield{note}% + \newunit\newblock + \usebibmacro{publisher+location+date}% + \newunit\newblock + \usebibmacro{chapter+pages}% + \newunit + \printfield{pagetotal}% + \newunit\newblock + \printfield{isbn}% + \newunit\newblock + \usebibmacro{doi+eprint+url}% + \newunit\newblock + \usebibmacro{addendum+pubstate}% + \setunit{\bibpagerefpunct}\newblock + \usebibmacro{pageref}% + \newunit\newblock + \iftoggle{bbx:related} + {\usebibmacro{related:init}% + \usebibmacro{related}} + {}% + \usebibmacro{finentry}% +} + +\DeclareBibliographyDriver{collection}{% + \usebibmacro{bibindex}% + \usebibmacro{begentry}% + \usebibmacro{maintitle+title}% + \newunit + \usebibmacro{byeditor+others}% + \newunit\newblock + \printfield{volumes}% + \newunit\newblock + \printfield{note}% + \newunit\newblock + \usebibmacro{publisher+location+date}% + \newunit\newblock + \usebibmacro{chapter+pages}% + \newunit + \printfield{pagetotal}% + \newunit\newblock + \printfield{isbn}% + \newunit\newblock + \usebibmacro{doi+eprint+url}% + \newunit\newblock + \usebibmacro{addendum+pubstate}% + \setunit{\bibpagerefpunct}\newblock + \usebibmacro{pageref}% + \newunit\newblock + \iftoggle{bbx:related} + {\usebibmacro{related:init}% + \usebibmacro{related}} + {}% + \usebibmacro{finentry}% +} + +\DeclareBibliographyDriver{inbook}{% + \usebibmacro{bibindex}% + \usebibmacro{begentry}% + \usebibmacro{author/translator+others}% + \setunit{\labelnamepunct}\newblock + \usebibmacro{byauthor}% + \newunit + \usebibmacro{title}% + \setunit{\addspace}% + \usebibmacro{in:}% + \usebibmacro{bybookauthor}% + \setunit*{\newunitpunct}\newblock + \usebibmacro{maintitle+booktitle}% + \newunit\newblock + \usebibmacro{byeditor+others}% + \newunit\newblock + \printfield{volumes}% + \newunit\newblock + \usebibmacro{series+number}% + \newunit\newblock + \printfield{note}% + \newunit\newblock + \usebibmacro{publisher+location+date}% + \newunit\newblock + \usebibmacro{chapter+pages}% + \newunit\newblock + \printfield{isbn}% + \newunit\newblock + \usebibmacro{doi+eprint+url}% + \newunit\newblock + \usebibmacro{addendum+pubstate}% + \setunit{\bibpagerefpunct}\newblock + \usebibmacro{pageref}% + \newunit\newblock + \iftoggle{bbx:related} + {\usebibmacro{related:init}% + \usebibmacro{related}} + {}% + \usebibmacro{finentry}% +} + +\DeclareBibliographyDriver{incollection}{% + \usebibmacro{bibindex}% + \usebibmacro{begentry}% + \usebibmacro{author/translator+others}% + \setunit{\labelnamepunct}\newblock + \usebibmacro{byauthor}% + \newunit + \usebibmacro{title}% + \setunit{\addspace}% + \usebibmacro{in:}% + \usebibmacro{maintitle+booktitle}% + \newunit\newblock + \usebibmacro{byeditor+others}% + \newunit\newblock + \printfield{volumes}% + \newunit\newblock + \usebibmacro{series+number}% + \newunit\newblock + \printfield{note}% + \newunit\newblock + \usebibmacro{publisher+location+date}% + \newunit\newblock + \usebibmacro{chapter+pages}% + \newunit\newblock + \printfield{isbn}% + \newunit\newblock + \usebibmacro{doi+eprint+url}% + \newunit\newblock + \usebibmacro{addendum+pubstate}% + \setunit{\bibpagerefpunct}\newblock + \usebibmacro{pageref}% + \newunit\newblock + \iftoggle{bbx:related} + {\usebibmacro{related:init}% + \usebibmacro{related}} + {}% + \usebibmacro{finentry}% +} + +\DeclareBibliographyDriver{inproceedings}{% + \usebibmacro{bibindex}% + \usebibmacro{begentry}% + \usebibmacro{author/translator+others}% + \setunit{\labelnamepunct}\newblock + \usebibmacro{byauthor}% + \setunit{\addspace}% + \usebibmacro{in:}% + \usebibmacro{maintitle+booktitle}% + \newunit\newblock + \usebibmacro{event+venue+date}% + \newunit\newblock + \usebibmacro{byeditor+others}% + \newunit\newblock + \printfield{volumes}% + \newunit\newblock + \printfield{note}% + \newunit\newblock + \printlist{organization}% + \newunit + \usebibmacro{publisher+location+date}% + \newunit\newblock + \usebibmacro{chapter+pages}% + \newunit\newblock + \printfield{isbn}% + \newunit\newblock + \usebibmacro{doi+eprint+url}% + \newunit\newblock + \usebibmacro{addendum+pubstate}% + \setunit{\bibpagerefpunct}\newblock + \usebibmacro{pageref}% + \newunit\newblock + \iftoggle{bbx:related} + {\usebibmacro{related:init}% + \usebibmacro{related}} + {}% + \usebibmacro{finentry}% +} + +\DeclareBibliographyDriver{manual}{% + \usebibmacro{bibindex}% + \usebibmacro{begentry}% + \usebibmacro{author/editor}% + \setunit{\labelnamepunct}\newblock + \usebibmacro{title}% + \newunit + \usebibmacro{byauthor}% + \newunit\newblock + \usebibmacro{byeditor}% + \newunit\newblock + \usebibmacro{series+number}% + \newunit\newblock + \printfield{type}% + \newunit + \printfield{version}% + \newunit + \printfield{note}% + \newunit\newblock + \printlist{organization}% + \newunit + \usebibmacro{publisher+location+date}% + \newunit\newblock + \usebibmacro{chapter+pages}% + \newunit + \printfield{pagetotal}% + \newunit\newblock + \printfield{isbn}% + \newunit\newblock + \usebibmacro{doi+eprint+url}% + \newunit\newblock + \usebibmacro{addendum+pubstate}% + \setunit{\bibpagerefpunct}\newblock + \usebibmacro{pageref}% + \newunit\newblock + \iftoggle{bbx:related} + {\usebibmacro{related:init}% + \usebibmacro{related}} + {}% + \usebibmacro{finentry}% +} + +\DeclareBibliographyDriver{patent}{% + \usebibmacro{bibindex}% + \usebibmacro{begentry}% + \usebibmacro{author}% + \setunit*{\addspace}% + \usebibmacro{byholder}% + \setunit{\labelnamepunct}\newblock + \usebibmacro{byauthor}% + \newunit\newblock + \printfield{type}% + \newunit + \printfield{number}% + \iflistundef{location} + {} + {\setunit*{\addspace}% + \printtext[parens]{% + \printlist[][-\value{listtotal}]{location}}}% + \newunit\newblock + \printfield{note}% + \newunit\newblock + \usebibmacro{date}% + \newunit\newblock + \usebibmacro{doi+eprint+url}% + \newunit\newblock + \usebibmacro{addendum+pubstate}% + \setunit{\bibpagerefpunct}\newblock + \usebibmacro{pageref}% + \newunit\newblock + \iftoggle{bbx:related} + {\usebibmacro{related:init}% + \usebibmacro{related}} + {}% + \usebibmacro{finentry}% +} + +\DeclareBibliographyDriver{thesis}{% + \usebibmacro{bibindex}% + \usebibmacro{begentry}% + \usebibmacro{author}% + \setunit{\labelnamepunct}\newblock + \usebibmacro{title}% + \newunit + \usebibmacro{byauthor}% + \newunit\newblock + \printfield{note}% + \newunit\newblock + \printfield{type}% + \newunit + \usebibmacro{institution+location+date}% + \newunit\newblock + \usebibmacro{chapter+pages}% + \newunit + \printfield{pagetotal}% + \newunit\newblock + \printfield{isbn}% + \newunit\newblock + \usebibmacro{doi+eprint+url}% + \newunit\newblock + \usebibmacro{addendum+pubstate}% + \setunit{\bibpagerefpunct}\newblock + \usebibmacro{pageref}% + \newunit\newblock + \iftoggle{bbx:related} + {\usebibmacro{related:init}% + \usebibmacro{related}} + {}% + \usebibmacro{finentry}% +} + +%% +%% Copyright (C) 2010-2014,2016-2019 by +%% Joseph Wright +%% +%% It may be distributed and/or modified under the conditions of +%% the LaTeX Project Public License (LPPL), either version 1.3c of +%% this license or (at your option) any later version. The latest +%% version of this license is in the file: +%% +%% http://www.latex-project.org/lppl.txt +%% +%% This work is "maintained" (as per LPPL maintenance status) by +%% Joseph Wright. +%% +%% This work consists of the files biblatex-chem.bib, +%% biblatex-chem.tex, +%% biblatex-chem-acs.tex, +%% biblatex-chem-angew.tex, +%% biblatex-chem-biochem.tex, +%% biblatex-chem-rsc.tex, +%% chem-acs.bbx, +%% chem-acs.cbx, +%% chem-angew.bbx, +%% chem-angew.cbx, +%% chem-biochem.bbx, +%% chem-biochem.cbx, +%% chem-rsc.bbx and +%% chem-rsc.cbx, +%% and the derived files biblatex-chem.pdf, +%% biblatex-chem-acs.pdf, +%% biblatex-chem-angew.pdf, +%% biblatex-chem-biochem.pdf and +%% biblatex-chem-rsc.pdf. +%% +%% +%% End of file `chem-angew.bbx'. diff --git a/NixTeX/dependencies/assets/biblatex/chem-angew.cbx b/NixTeX/dependencies/assets/biblatex/chem-angew.cbx new file mode 100644 index 0000000..1a93d1c --- /dev/null +++ b/NixTeX/dependencies/assets/biblatex/chem-angew.cbx @@ -0,0 +1,75 @@ +%% --------------------------------------------------------------- +%% biblatex-chem --- A set of biblatex implementations of +%% chemistry-related bibliography styles +%% Maintained by Joseph Wright +%% E-mail: joseph.wright@morningstar2.co.uk +%% Released under the LaTeX Project Public License v1.3c or later +%% See http://www.latex-project.org/lppl.txt +%% --------------------------------------------------------------- +%% + +\ProvidesFile{chem-angew.cbx}[2019/12/03 v1.1y biblatex citation style] + +\RequireCitationStyle{numeric-comp} + +\ExecuteBibliographyOptions + { + autocite = superscript, + autopunct = true , + sorting = none + } + +\newcommand*\mkbibsuperbracket[1]{% + \mkbibsuperscript{\mkbibbrackets{#1}}% +} + +\DeclareCiteCommand{\supercite}[\mkbibsuperbracket] + {\usebibmacro{cite:init}% + \let\multicitedelim=\supercitedelim + \iffieldundef{prenote} + {} + {\BibliographyWarning{Ignoring prenote argument}}% + \iffieldundef{postnote} + {} + {\BibliographyWarning{Ignoring postnote argument}}} + {\usebibmacro{citeindex}% + \usebibmacro{cite:comp}} + {} + {\usebibmacro{cite:dump}} + +%% +%% Copyright (C) 2010-2014,2016-2019 by +%% Joseph Wright +%% +%% It may be distributed and/or modified under the conditions of +%% the LaTeX Project Public License (LPPL), either version 1.3c of +%% this license or (at your option) any later version. The latest +%% version of this license is in the file: +%% +%% http://www.latex-project.org/lppl.txt +%% +%% This work is "maintained" (as per LPPL maintenance status) by +%% Joseph Wright. +%% +%% This work consists of the files biblatex-chem.bib, +%% biblatex-chem.tex, +%% biblatex-chem-acs.tex, +%% biblatex-chem-angew.tex, +%% biblatex-chem-biochem.tex, +%% biblatex-chem-rsc.tex, +%% chem-acs.bbx, +%% chem-acs.cbx, +%% chem-angew.bbx, +%% chem-angew.cbx, +%% chem-biochem.bbx, +%% chem-biochem.cbx, +%% chem-rsc.bbx and +%% chem-rsc.cbx, +%% and the derived files biblatex-chem.pdf, +%% biblatex-chem-acs.pdf, +%% biblatex-chem-angew.pdf, +%% biblatex-chem-biochem.pdf and +%% biblatex-chem-rsc.pdf. +%% +%% +%% End of file `chem-angew.cbx'. diff --git a/NixTeX/dependencies/assets/pictograms/dsd/C.pdf b/NixTeX/dependencies/assets/pictograms/dsd/C.pdf new file mode 100644 index 0000000..d99d67a Binary files /dev/null and b/NixTeX/dependencies/assets/pictograms/dsd/C.pdf differ diff --git a/NixTeX/dependencies/assets/pictograms/dsd/C.svg b/NixTeX/dependencies/assets/pictograms/dsd/C.svg new file mode 100644 index 0000000..ead02b9 --- /dev/null +++ b/NixTeX/dependencies/assets/pictograms/dsd/C.svg @@ -0,0 +1,58 @@ + + + + + SVG drawing + This was produced by version 4.1 of GNU libplot, a free library for exporting 2-D vector graphics. + + + + + + + + + + + + diff --git a/NixTeX/dependencies/assets/pictograms/dsd/E.pdf b/NixTeX/dependencies/assets/pictograms/dsd/E.pdf new file mode 100644 index 0000000..867305c Binary files /dev/null and b/NixTeX/dependencies/assets/pictograms/dsd/E.pdf differ diff --git a/NixTeX/dependencies/assets/pictograms/dsd/E.svg b/NixTeX/dependencies/assets/pictograms/dsd/E.svg new file mode 100644 index 0000000..d43f815 --- /dev/null +++ b/NixTeX/dependencies/assets/pictograms/dsd/E.svg @@ -0,0 +1,92 @@ + + + + + SVG drawing + This was produced by version 4.1 of GNU libplot, a free library for exporting 2-D vector graphics. + + + + + + + + + + + + + + + + + + + + diff --git a/NixTeX/dependencies/assets/pictograms/dsd/F+.pdf b/NixTeX/dependencies/assets/pictograms/dsd/F+.pdf new file mode 100644 index 0000000..b01d1cb Binary files /dev/null and b/NixTeX/dependencies/assets/pictograms/dsd/F+.pdf differ diff --git a/NixTeX/dependencies/assets/pictograms/dsd/F+.svg b/NixTeX/dependencies/assets/pictograms/dsd/F+.svg new file mode 100644 index 0000000..4ebc8be --- /dev/null +++ b/NixTeX/dependencies/assets/pictograms/dsd/F+.svg @@ -0,0 +1,57 @@ + + + + + SVG drawing + This was produced by version 4.1 of GNU libplot, a free library for exporting 2-D vector graphics. + + + + + + + + + + diff --git a/NixTeX/dependencies/assets/pictograms/dsd/F.pdf b/NixTeX/dependencies/assets/pictograms/dsd/F.pdf new file mode 100644 index 0000000..f6af51a --- /dev/null +++ b/NixTeX/dependencies/assets/pictograms/dsd/F.pdf @@ -0,0 +1,73 @@ +%PDF-1.5 +% +4 0 obj +<< /Length 5 0 R + /Filter /FlateDecode +>> +stream +xeM5 ȺRClٲABbQb- >NFwǎ{h<=_/&{b|[+Z^l˿~W|Z\O3}X!*|M/}k59˗?ʇ;Emjy2p1,^G7^cUI$ZYE. RUWдƠE4,V8\6q:R>F7e~'keQ^ }S^, yn=,6r1M}`>hVc&'ЬK6nYcۗm|wٛ$χO~AhLh_)F+fm.b + -6j*wpqIQFO.t%(a}ΉƪDq 2`U )pfjGmOAQ+Tܻ5rF$H + %ɒXO*ÅF'mXNE q@ *(Zfu=d_\!,(]i + n'Heg9YAe⁴f TH!g@L9` 91~AM1~6l؅< hACt`y rCR[Uq&&aHHJBbYHBBa#Uf[…+"2xH"Zdrl#K˙29:b^hP8 1f, g-1ePly;H.ظ1,׌Ğ1;g646ԢI}Ƣ@%U|TSk!ѨB7U J{E4D?#GTYcRAB=U +h}kk^M,g/PXx>̐ؕpr +9:ã62$.r#ml Cb!VP `8q:REV&i?_ f3<1JUƙnDI)^b13Bc;Auf2c_M0㡌 X> + >> +>> +endobj +2 0 obj +<< /Type /Page % 1 + /Parent 1 0 R + /MediaBox [ 0 0 500 500 ] + /Contents 4 0 R + /Group << + /Type /Group + /S /Transparency + /I true + /CS /DeviceRGB + >> + /Resources 3 0 R +>> +endobj +1 0 obj +<< /Type /Pages + /Kids [ 2 0 R ] + /Count 1 +>> +endobj +6 0 obj +<< /Producer (cairo 1.16.0 (https://cairographics.org)) + /CreationDate (19700101000001+00') +>> +endobj +7 0 obj +<< /Type /Catalog + /Pages 1 0 R +>> +endobj +xref +0 8 +0000000000 65535 f +0000001430 00000 n +0000001212 00000 n +0000001140 00000 n +0000000015 00000 n +0000001117 00000 n +0000001495 00000 n +0000001607 00000 n +trailer +<< /Size 8 + /Root 7 0 R + /Info 6 0 R +>> +startxref +1659 +%%EOF diff --git a/NixTeX/dependencies/assets/pictograms/dsd/F.svg b/NixTeX/dependencies/assets/pictograms/dsd/F.svg new file mode 100644 index 0000000..0a7d581 --- /dev/null +++ b/NixTeX/dependencies/assets/pictograms/dsd/F.svg @@ -0,0 +1,40 @@ + + + + + SVG drawing + This was produced by version 4.1 of GNU libplot, a free library for exporting 2-D vector graphics. + + + + + + + diff --git a/NixTeX/dependencies/assets/pictograms/dsd/N.pdf b/NixTeX/dependencies/assets/pictograms/dsd/N.pdf new file mode 100644 index 0000000..6432107 Binary files /dev/null and b/NixTeX/dependencies/assets/pictograms/dsd/N.pdf differ diff --git a/NixTeX/dependencies/assets/pictograms/dsd/N.svg b/NixTeX/dependencies/assets/pictograms/dsd/N.svg new file mode 100644 index 0000000..e25fe8e --- /dev/null +++ b/NixTeX/dependencies/assets/pictograms/dsd/N.svg @@ -0,0 +1,26 @@ + + + + + SVG drawing + This was produced by version 4.1 of GNU libplot, a free library for exporting 2-D vector graphics. + + + diff --git a/NixTeX/dependencies/assets/pictograms/dsd/O.pdf b/NixTeX/dependencies/assets/pictograms/dsd/O.pdf new file mode 100644 index 0000000..8582022 Binary files /dev/null and b/NixTeX/dependencies/assets/pictograms/dsd/O.pdf differ diff --git a/NixTeX/dependencies/assets/pictograms/dsd/O.svg b/NixTeX/dependencies/assets/pictograms/dsd/O.svg new file mode 100644 index 0000000..1580c52 --- /dev/null +++ b/NixTeX/dependencies/assets/pictograms/dsd/O.svg @@ -0,0 +1,26 @@ + + + + + SVG drawing + This was produced by version 4.1 of GNU libplot, a free library for exporting 2-D vector graphics. + + + diff --git a/NixTeX/dependencies/assets/pictograms/dsd/T+.pdf b/NixTeX/dependencies/assets/pictograms/dsd/T+.pdf new file mode 100644 index 0000000..66bfdd5 Binary files /dev/null and b/NixTeX/dependencies/assets/pictograms/dsd/T+.pdf differ diff --git a/NixTeX/dependencies/assets/pictograms/dsd/T+.svg b/NixTeX/dependencies/assets/pictograms/dsd/T+.svg new file mode 100644 index 0000000..74a7efc --- /dev/null +++ b/NixTeX/dependencies/assets/pictograms/dsd/T+.svg @@ -0,0 +1,30 @@ + + + + + SVG drawing + This was produced by version 4.1 of GNU libplot, a free library for exporting 2-D vector graphics. + + + + diff --git a/NixTeX/dependencies/assets/pictograms/dsd/T.pdf b/NixTeX/dependencies/assets/pictograms/dsd/T.pdf new file mode 100644 index 0000000..76bbcb5 Binary files /dev/null and b/NixTeX/dependencies/assets/pictograms/dsd/T.pdf differ diff --git a/NixTeX/dependencies/assets/pictograms/dsd/T.svg b/NixTeX/dependencies/assets/pictograms/dsd/T.svg new file mode 100644 index 0000000..dd71b4f --- /dev/null +++ b/NixTeX/dependencies/assets/pictograms/dsd/T.svg @@ -0,0 +1,15 @@ + + + + + \ No newline at end of file diff --git a/NixTeX/dependencies/assets/pictograms/dsd/Xi.pdf b/NixTeX/dependencies/assets/pictograms/dsd/Xi.pdf new file mode 100644 index 0000000..caf2db0 Binary files /dev/null and b/NixTeX/dependencies/assets/pictograms/dsd/Xi.pdf differ diff --git a/NixTeX/dependencies/assets/pictograms/dsd/Xi.svg b/NixTeX/dependencies/assets/pictograms/dsd/Xi.svg new file mode 100644 index 0000000..54c47c1 --- /dev/null +++ b/NixTeX/dependencies/assets/pictograms/dsd/Xi.svg @@ -0,0 +1,31 @@ + + + + + SVG drawing + This was produced by version 4.1 of GNU libplot, a free library for exporting 2-D vector graphics. + + + + diff --git a/NixTeX/dependencies/assets/pictograms/dsd/Xn.pdf b/NixTeX/dependencies/assets/pictograms/dsd/Xn.pdf new file mode 100644 index 0000000..646fff5 Binary files /dev/null and b/NixTeX/dependencies/assets/pictograms/dsd/Xn.pdf differ diff --git a/NixTeX/dependencies/assets/pictograms/dsd/Xn.svg b/NixTeX/dependencies/assets/pictograms/dsd/Xn.svg new file mode 100644 index 0000000..03acd3a --- /dev/null +++ b/NixTeX/dependencies/assets/pictograms/dsd/Xn.svg @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/NixTeX/dependencies/assets/pictograms/ghs/01.pdf b/NixTeX/dependencies/assets/pictograms/ghs/01.pdf new file mode 100644 index 0000000..cb9606e Binary files /dev/null and b/NixTeX/dependencies/assets/pictograms/ghs/01.pdf differ diff --git a/NixTeX/dependencies/assets/pictograms/ghs/01.svg b/NixTeX/dependencies/assets/pictograms/ghs/01.svg new file mode 100644 index 0000000..aed05d8 --- /dev/null +++ b/NixTeX/dependencies/assets/pictograms/ghs/01.svg @@ -0,0 +1,72 @@ + + + + + + + + image/svg+xml + + + + + + + + + + + diff --git a/NixTeX/dependencies/assets/pictograms/ghs/02.pdf b/NixTeX/dependencies/assets/pictograms/ghs/02.pdf new file mode 100644 index 0000000..efe13ff Binary files /dev/null and b/NixTeX/dependencies/assets/pictograms/ghs/02.pdf differ diff --git a/NixTeX/dependencies/assets/pictograms/ghs/02.svg b/NixTeX/dependencies/assets/pictograms/ghs/02.svg new file mode 100644 index 0000000..939b191 --- /dev/null +++ b/NixTeX/dependencies/assets/pictograms/ghs/02.svg @@ -0,0 +1,72 @@ + + + + + + + + image/svg+xml + + + + + + + + + + + diff --git a/NixTeX/dependencies/assets/pictograms/ghs/03.pdf b/NixTeX/dependencies/assets/pictograms/ghs/03.pdf new file mode 100644 index 0000000..d83bc7f Binary files /dev/null and b/NixTeX/dependencies/assets/pictograms/ghs/03.pdf differ diff --git a/NixTeX/dependencies/assets/pictograms/ghs/03.svg b/NixTeX/dependencies/assets/pictograms/ghs/03.svg new file mode 100644 index 0000000..b6482b8 --- /dev/null +++ b/NixTeX/dependencies/assets/pictograms/ghs/03.svg @@ -0,0 +1,72 @@ + + + + + + + + image/svg+xml + + + + + + + + + + + diff --git a/NixTeX/dependencies/assets/pictograms/ghs/04.pdf b/NixTeX/dependencies/assets/pictograms/ghs/04.pdf new file mode 100644 index 0000000..8a4a9d9 --- /dev/null +++ b/NixTeX/dependencies/assets/pictograms/ghs/04.pdf @@ -0,0 +1,72 @@ +%PDF-1.5 +% +4 0 obj +<< /Length 5 0 R + /Filter /FlateDecode +>> +stream +xmK7 } +] >B0,셓8`4DX,q >_kv}/ӟ}R",}Y涾㴯<Խ'빚'fM}jyK{~qIfYD5;<^'^cɂnPr2/q,NoXsчm8ty7]?8t. Gӻ +N:pH86+fxSg`VYZqP[zۯ>Wa}5 +ƻKr麫ַu8>ZEQ_xf*Wn+Z`Diez{5ٻo,/WHE4%``jר-e4e/esO5YhCV:hiRe@ʶO+9n>hױbWeɬz,T*<[ef@twKt ! N:TE>4ФjNE$E/"Nm:O'-wg5ClV89굙FlӕlV}"Fv\t2JAfyؓi~F +`_hy%A?B3+]]H$ +^LѠ#Tc񊀋&Mab5čAmiRЩq2oKAض;d*S=prdR@~,;QCպգl|J]aݨ}wʓ`}Pfu*ԣOOD෦(@\#dJ(U+zrV/smT>Crnpm˻4JL~$mNi6r>>׿`j +endstream +endobj +5 0 obj + 864 +endobj +3 0 obj +<< + /ExtGState << + /a0 << /CA 1 /ca 1 >> + >> +>> +endobj +2 0 obj +<< /Type /Page % 1 + /Parent 1 0 R + /MediaBox [ 0 0 708 708 ] + /Contents 4 0 R + /Group << + /Type /Group + /S /Transparency + /I true + /CS /DeviceRGB + >> + /Resources 3 0 R +>> +endobj +1 0 obj +<< /Type /Pages + /Kids [ 2 0 R ] + /Count 1 +>> +endobj +6 0 obj +<< /Producer (cairo 1.16.0 (https://cairographics.org)) + /CreationDate (19700101000001+00') +>> +endobj +7 0 obj +<< /Type /Catalog + /Pages 1 0 R +>> +endobj +xref +0 8 +0000000000 65535 f +0000001268 00000 n +0000001050 00000 n +0000000978 00000 n +0000000015 00000 n +0000000956 00000 n +0000001333 00000 n +0000001445 00000 n +trailer +<< /Size 8 + /Root 7 0 R + /Info 6 0 R +>> +startxref +1497 +%%EOF diff --git a/NixTeX/dependencies/assets/pictograms/ghs/04.svg b/NixTeX/dependencies/assets/pictograms/ghs/04.svg new file mode 100644 index 0000000..cc15baf --- /dev/null +++ b/NixTeX/dependencies/assets/pictograms/ghs/04.svg @@ -0,0 +1,72 @@ + + + + + + + + image/svg+xml + + + + + + + + + + + diff --git a/NixTeX/dependencies/assets/pictograms/ghs/05.pdf b/NixTeX/dependencies/assets/pictograms/ghs/05.pdf new file mode 100644 index 0000000..3dfd45c Binary files /dev/null and b/NixTeX/dependencies/assets/pictograms/ghs/05.pdf differ diff --git a/NixTeX/dependencies/assets/pictograms/ghs/05.svg b/NixTeX/dependencies/assets/pictograms/ghs/05.svg new file mode 100644 index 0000000..15e63b1 --- /dev/null +++ b/NixTeX/dependencies/assets/pictograms/ghs/05.svg @@ -0,0 +1,158 @@ + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/NixTeX/dependencies/assets/pictograms/ghs/06.pdf b/NixTeX/dependencies/assets/pictograms/ghs/06.pdf new file mode 100644 index 0000000..d18a1d4 Binary files /dev/null and b/NixTeX/dependencies/assets/pictograms/ghs/06.pdf differ diff --git a/NixTeX/dependencies/assets/pictograms/ghs/06.svg b/NixTeX/dependencies/assets/pictograms/ghs/06.svg new file mode 100644 index 0000000..531cbb7 --- /dev/null +++ b/NixTeX/dependencies/assets/pictograms/ghs/06.svg @@ -0,0 +1,69 @@ + + + + + + image/svg+xml + + + + + + + + + + + diff --git a/NixTeX/dependencies/assets/pictograms/ghs/07.pdf b/NixTeX/dependencies/assets/pictograms/ghs/07.pdf new file mode 100644 index 0000000..2b7c64e Binary files /dev/null and b/NixTeX/dependencies/assets/pictograms/ghs/07.pdf differ diff --git a/NixTeX/dependencies/assets/pictograms/ghs/07.svg b/NixTeX/dependencies/assets/pictograms/ghs/07.svg new file mode 100644 index 0000000..4e97ea2 --- /dev/null +++ b/NixTeX/dependencies/assets/pictograms/ghs/07.svg @@ -0,0 +1,70 @@ + + + + + + image/svg+xml + + + + + + + + + + + diff --git a/NixTeX/dependencies/assets/pictograms/ghs/08.pdf b/NixTeX/dependencies/assets/pictograms/ghs/08.pdf new file mode 100644 index 0000000..a5063f8 Binary files /dev/null and b/NixTeX/dependencies/assets/pictograms/ghs/08.pdf differ diff --git a/NixTeX/dependencies/assets/pictograms/ghs/08.svg b/NixTeX/dependencies/assets/pictograms/ghs/08.svg new file mode 100644 index 0000000..ce0289a --- /dev/null +++ b/NixTeX/dependencies/assets/pictograms/ghs/08.svg @@ -0,0 +1,69 @@ + + + + + + image/svg+xml + + + + + + + + + + + diff --git a/NixTeX/dependencies/assets/pictograms/ghs/09.pdf b/NixTeX/dependencies/assets/pictograms/ghs/09.pdf new file mode 100644 index 0000000..cd32f8c Binary files /dev/null and b/NixTeX/dependencies/assets/pictograms/ghs/09.pdf differ diff --git a/NixTeX/dependencies/assets/pictograms/ghs/09.svg b/NixTeX/dependencies/assets/pictograms/ghs/09.svg new file mode 100644 index 0000000..f91882b --- /dev/null +++ b/NixTeX/dependencies/assets/pictograms/ghs/09.svg @@ -0,0 +1,90 @@ + + + + + + image/svg+xml + + + + + + + + + + + + + + + + diff --git a/NixTeX/dependencies/assets/pictograms/iso7010/warnings/001.pdf b/NixTeX/dependencies/assets/pictograms/iso7010/warnings/001.pdf new file mode 100644 index 0000000..a33262b Binary files /dev/null and b/NixTeX/dependencies/assets/pictograms/iso7010/warnings/001.pdf differ diff --git a/NixTeX/dependencies/assets/pictograms/iso7010/warnings/001.svg b/NixTeX/dependencies/assets/pictograms/iso7010/warnings/001.svg new file mode 100644 index 0000000..fbd16ff --- /dev/null +++ b/NixTeX/dependencies/assets/pictograms/iso7010/warnings/001.svg @@ -0,0 +1,50 @@ + + + + + + + + image/svg+xml + + + + + + + + + + + + + diff --git a/NixTeX/dependencies/assets/pictograms/iso7010/warnings/002.pdf b/NixTeX/dependencies/assets/pictograms/iso7010/warnings/002.pdf new file mode 100644 index 0000000..de32d0c Binary files /dev/null and b/NixTeX/dependencies/assets/pictograms/iso7010/warnings/002.pdf differ diff --git a/NixTeX/dependencies/assets/pictograms/iso7010/warnings/002.svg b/NixTeX/dependencies/assets/pictograms/iso7010/warnings/002.svg new file mode 100644 index 0000000..b6c4a6b --- /dev/null +++ b/NixTeX/dependencies/assets/pictograms/iso7010/warnings/002.svg @@ -0,0 +1,224 @@ + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/NixTeX/dependencies/assets/pictograms/iso7010/warnings/003.pdf b/NixTeX/dependencies/assets/pictograms/iso7010/warnings/003.pdf new file mode 100644 index 0000000..a5f8df8 Binary files /dev/null and b/NixTeX/dependencies/assets/pictograms/iso7010/warnings/003.pdf differ diff --git a/NixTeX/dependencies/assets/pictograms/iso7010/warnings/003.svg b/NixTeX/dependencies/assets/pictograms/iso7010/warnings/003.svg new file mode 100644 index 0000000..72de742 --- /dev/null +++ b/NixTeX/dependencies/assets/pictograms/iso7010/warnings/003.svg @@ -0,0 +1,39 @@ + + + + + + + + image/svg+xml + + + + + + + + + + diff --git a/NixTeX/dependencies/assets/pictograms/iso7010/warnings/004.pdf b/NixTeX/dependencies/assets/pictograms/iso7010/warnings/004.pdf new file mode 100644 index 0000000..623c7fb Binary files /dev/null and b/NixTeX/dependencies/assets/pictograms/iso7010/warnings/004.pdf differ diff --git a/NixTeX/dependencies/assets/pictograms/iso7010/warnings/004.svg b/NixTeX/dependencies/assets/pictograms/iso7010/warnings/004.svg new file mode 100644 index 0000000..3935c56 --- /dev/null +++ b/NixTeX/dependencies/assets/pictograms/iso7010/warnings/004.svg @@ -0,0 +1,155 @@ + + + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/NixTeX/dependencies/assets/pictograms/iso7010/warnings/005.pdf b/NixTeX/dependencies/assets/pictograms/iso7010/warnings/005.pdf new file mode 100644 index 0000000..b6d81e1 Binary files /dev/null and b/NixTeX/dependencies/assets/pictograms/iso7010/warnings/005.pdf differ diff --git a/NixTeX/dependencies/assets/pictograms/iso7010/warnings/005.svg b/NixTeX/dependencies/assets/pictograms/iso7010/warnings/005.svg new file mode 100644 index 0000000..c034aa7 --- /dev/null +++ b/NixTeX/dependencies/assets/pictograms/iso7010/warnings/005.svg @@ -0,0 +1,26 @@ + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + + + + diff --git a/NixTeX/dependencies/assets/pictograms/iso7010/warnings/006.pdf b/NixTeX/dependencies/assets/pictograms/iso7010/warnings/006.pdf new file mode 100644 index 0000000..1d3072e Binary files /dev/null and b/NixTeX/dependencies/assets/pictograms/iso7010/warnings/006.pdf differ diff --git a/NixTeX/dependencies/assets/pictograms/iso7010/warnings/006.svg b/NixTeX/dependencies/assets/pictograms/iso7010/warnings/006.svg new file mode 100644 index 0000000..6c8b3c8 --- /dev/null +++ b/NixTeX/dependencies/assets/pictograms/iso7010/warnings/006.svg @@ -0,0 +1,23 @@ + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + diff --git a/NixTeX/dependencies/assets/pictograms/iso7010/warnings/007.pdf b/NixTeX/dependencies/assets/pictograms/iso7010/warnings/007.pdf new file mode 100644 index 0000000..4eddf2b Binary files /dev/null and b/NixTeX/dependencies/assets/pictograms/iso7010/warnings/007.pdf differ diff --git a/NixTeX/dependencies/assets/pictograms/iso7010/warnings/007.svg b/NixTeX/dependencies/assets/pictograms/iso7010/warnings/007.svg new file mode 100644 index 0000000..5eb4d53 --- /dev/null +++ b/NixTeX/dependencies/assets/pictograms/iso7010/warnings/007.svg @@ -0,0 +1,19 @@ + + + + + + image/svg+xml + + + + + + + + + + + + + diff --git a/NixTeX/dependencies/assets/pictograms/iso7010/warnings/008.pdf b/NixTeX/dependencies/assets/pictograms/iso7010/warnings/008.pdf new file mode 100644 index 0000000..4c5c77d Binary files /dev/null and b/NixTeX/dependencies/assets/pictograms/iso7010/warnings/008.pdf differ diff --git a/NixTeX/dependencies/assets/pictograms/iso7010/warnings/008.svg b/NixTeX/dependencies/assets/pictograms/iso7010/warnings/008.svg new file mode 100644 index 0000000..3bdcccd --- /dev/null +++ b/NixTeX/dependencies/assets/pictograms/iso7010/warnings/008.svg @@ -0,0 +1,19 @@ + + + + + + image/svg+xml + + + + + + + + + + + + + diff --git a/NixTeX/dependencies/assets/pictograms/iso7010/warnings/009.pdf b/NixTeX/dependencies/assets/pictograms/iso7010/warnings/009.pdf new file mode 100644 index 0000000..1694d8d Binary files /dev/null and b/NixTeX/dependencies/assets/pictograms/iso7010/warnings/009.pdf differ diff --git a/NixTeX/dependencies/assets/pictograms/iso7010/warnings/009.svg b/NixTeX/dependencies/assets/pictograms/iso7010/warnings/009.svg new file mode 100644 index 0000000..0f703aa --- /dev/null +++ b/NixTeX/dependencies/assets/pictograms/iso7010/warnings/009.svg @@ -0,0 +1,53 @@ + + + + + + + + image/svg+xml + + + + + + + + + + + + + + diff --git a/NixTeX/dependencies/assets/pictograms/iso7010/warnings/010.pdf b/NixTeX/dependencies/assets/pictograms/iso7010/warnings/010.pdf new file mode 100644 index 0000000..78723f6 Binary files /dev/null and b/NixTeX/dependencies/assets/pictograms/iso7010/warnings/010.pdf differ diff --git a/NixTeX/dependencies/assets/pictograms/iso7010/warnings/010.svg b/NixTeX/dependencies/assets/pictograms/iso7010/warnings/010.svg new file mode 100644 index 0000000..93518c4 --- /dev/null +++ b/NixTeX/dependencies/assets/pictograms/iso7010/warnings/010.svg @@ -0,0 +1,15 @@ + + + + + + image/svg+xml + + + + + + + + + diff --git a/NixTeX/dependencies/assets/pictograms/iso7010/warnings/011.pdf b/NixTeX/dependencies/assets/pictograms/iso7010/warnings/011.pdf new file mode 100644 index 0000000..ad3cd6a Binary files /dev/null and b/NixTeX/dependencies/assets/pictograms/iso7010/warnings/011.pdf differ diff --git a/NixTeX/dependencies/assets/pictograms/iso7010/warnings/011.svg b/NixTeX/dependencies/assets/pictograms/iso7010/warnings/011.svg new file mode 100644 index 0000000..5a21c02 --- /dev/null +++ b/NixTeX/dependencies/assets/pictograms/iso7010/warnings/011.svg @@ -0,0 +1,17 @@ + + + + + + image/svg+xml + + + + + + + + + + + diff --git a/NixTeX/dependencies/assets/pictograms/iso7010/warnings/012.pdf b/NixTeX/dependencies/assets/pictograms/iso7010/warnings/012.pdf new file mode 100644 index 0000000..ea792fb Binary files /dev/null and b/NixTeX/dependencies/assets/pictograms/iso7010/warnings/012.pdf differ diff --git a/NixTeX/dependencies/assets/pictograms/iso7010/warnings/012.svg b/NixTeX/dependencies/assets/pictograms/iso7010/warnings/012.svg new file mode 100644 index 0000000..b68f7c4 --- /dev/null +++ b/NixTeX/dependencies/assets/pictograms/iso7010/warnings/012.svg @@ -0,0 +1,98 @@ + + + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + + + diff --git a/NixTeX/dependencies/assets/pictograms/iso7010/warnings/013.pdf b/NixTeX/dependencies/assets/pictograms/iso7010/warnings/013.pdf new file mode 100644 index 0000000..2943557 Binary files /dev/null and b/NixTeX/dependencies/assets/pictograms/iso7010/warnings/013.pdf differ diff --git a/NixTeX/dependencies/assets/pictograms/iso7010/warnings/013.svg b/NixTeX/dependencies/assets/pictograms/iso7010/warnings/013.svg new file mode 100644 index 0000000..5821de7 --- /dev/null +++ b/NixTeX/dependencies/assets/pictograms/iso7010/warnings/013.svg @@ -0,0 +1,79 @@ + + + + + + + + + + image/svg+xml + + + + + + + + + + + diff --git a/NixTeX/dependencies/assets/pictograms/iso7010/warnings/014.pdf b/NixTeX/dependencies/assets/pictograms/iso7010/warnings/014.pdf new file mode 100644 index 0000000..5a4741f Binary files /dev/null and b/NixTeX/dependencies/assets/pictograms/iso7010/warnings/014.pdf differ diff --git a/NixTeX/dependencies/assets/pictograms/iso7010/warnings/014.svg b/NixTeX/dependencies/assets/pictograms/iso7010/warnings/014.svg new file mode 100644 index 0000000..b5ee1b5 --- /dev/null +++ b/NixTeX/dependencies/assets/pictograms/iso7010/warnings/014.svg @@ -0,0 +1,20 @@ + + + + + + image/svg+xml + + + + + + + + + + + + + + diff --git a/NixTeX/dependencies/assets/pictograms/iso7010/warnings/015.pdf b/NixTeX/dependencies/assets/pictograms/iso7010/warnings/015.pdf new file mode 100644 index 0000000..cbd7a03 Binary files /dev/null and b/NixTeX/dependencies/assets/pictograms/iso7010/warnings/015.pdf differ diff --git a/NixTeX/dependencies/assets/pictograms/iso7010/warnings/015.svg b/NixTeX/dependencies/assets/pictograms/iso7010/warnings/015.svg new file mode 100644 index 0000000..2f16606 --- /dev/null +++ b/NixTeX/dependencies/assets/pictograms/iso7010/warnings/015.svg @@ -0,0 +1,43 @@ + + + + + + + + image/svg+xml + + + + + + + + + + + + diff --git a/NixTeX/dependencies/assets/pictograms/iso7010/warnings/016.pdf b/NixTeX/dependencies/assets/pictograms/iso7010/warnings/016.pdf new file mode 100644 index 0000000..fe62269 Binary files /dev/null and b/NixTeX/dependencies/assets/pictograms/iso7010/warnings/016.pdf differ diff --git a/NixTeX/dependencies/assets/pictograms/iso7010/warnings/016.svg b/NixTeX/dependencies/assets/pictograms/iso7010/warnings/016.svg new file mode 100644 index 0000000..ddf248e --- /dev/null +++ b/NixTeX/dependencies/assets/pictograms/iso7010/warnings/016.svg @@ -0,0 +1,23 @@ + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + diff --git a/NixTeX/dependencies/assets/pictograms/iso7010/warnings/017.pdf b/NixTeX/dependencies/assets/pictograms/iso7010/warnings/017.pdf new file mode 100644 index 0000000..606c10c Binary files /dev/null and b/NixTeX/dependencies/assets/pictograms/iso7010/warnings/017.pdf differ diff --git a/NixTeX/dependencies/assets/pictograms/iso7010/warnings/017.svg b/NixTeX/dependencies/assets/pictograms/iso7010/warnings/017.svg new file mode 100644 index 0000000..0462951 --- /dev/null +++ b/NixTeX/dependencies/assets/pictograms/iso7010/warnings/017.svg @@ -0,0 +1,18 @@ + + + + + + image/svg+xml + + + + + + + + + + + + diff --git a/NixTeX/dependencies/assets/pictograms/iso7010/warnings/018.pdf b/NixTeX/dependencies/assets/pictograms/iso7010/warnings/018.pdf new file mode 100644 index 0000000..c25bf87 Binary files /dev/null and b/NixTeX/dependencies/assets/pictograms/iso7010/warnings/018.pdf differ diff --git a/NixTeX/dependencies/assets/pictograms/iso7010/warnings/018.svg b/NixTeX/dependencies/assets/pictograms/iso7010/warnings/018.svg new file mode 100644 index 0000000..0500117 --- /dev/null +++ b/NixTeX/dependencies/assets/pictograms/iso7010/warnings/018.svg @@ -0,0 +1,15 @@ + + + + + + image/svg+xml + + + + + + + + + diff --git a/NixTeX/dependencies/assets/pictograms/iso7010/warnings/019.pdf b/NixTeX/dependencies/assets/pictograms/iso7010/warnings/019.pdf new file mode 100644 index 0000000..ffdbffb Binary files /dev/null and b/NixTeX/dependencies/assets/pictograms/iso7010/warnings/019.pdf differ diff --git a/NixTeX/dependencies/assets/pictograms/iso7010/warnings/019.svg b/NixTeX/dependencies/assets/pictograms/iso7010/warnings/019.svg new file mode 100644 index 0000000..7ead965 --- /dev/null +++ b/NixTeX/dependencies/assets/pictograms/iso7010/warnings/019.svg @@ -0,0 +1,68 @@ + + + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + + + diff --git a/NixTeX/dependencies/assets/pictograms/iso7010/warnings/020.pdf b/NixTeX/dependencies/assets/pictograms/iso7010/warnings/020.pdf new file mode 100644 index 0000000..020f2a7 Binary files /dev/null and b/NixTeX/dependencies/assets/pictograms/iso7010/warnings/020.pdf differ diff --git a/NixTeX/dependencies/assets/pictograms/iso7010/warnings/020.svg b/NixTeX/dependencies/assets/pictograms/iso7010/warnings/020.svg new file mode 100644 index 0000000..951dbd2 --- /dev/null +++ b/NixTeX/dependencies/assets/pictograms/iso7010/warnings/020.svg @@ -0,0 +1,99 @@ + + + + + + + + + + image/svg+xml + + + + + + + + + + + + + + diff --git a/NixTeX/dependencies/assets/pictograms/iso7010/warnings/021.pdf b/NixTeX/dependencies/assets/pictograms/iso7010/warnings/021.pdf new file mode 100644 index 0000000..0c307f0 Binary files /dev/null and b/NixTeX/dependencies/assets/pictograms/iso7010/warnings/021.pdf differ diff --git a/NixTeX/dependencies/assets/pictograms/iso7010/warnings/021.svg b/NixTeX/dependencies/assets/pictograms/iso7010/warnings/021.svg new file mode 100644 index 0000000..85c1776 --- /dev/null +++ b/NixTeX/dependencies/assets/pictograms/iso7010/warnings/021.svg @@ -0,0 +1,40 @@ + + + + + + + + image/svg+xml + + + + + + + + + + diff --git a/NixTeX/dependencies/assets/pictograms/iso7010/warnings/022.pdf b/NixTeX/dependencies/assets/pictograms/iso7010/warnings/022.pdf new file mode 100644 index 0000000..91333f6 Binary files /dev/null and b/NixTeX/dependencies/assets/pictograms/iso7010/warnings/022.pdf differ diff --git a/NixTeX/dependencies/assets/pictograms/iso7010/warnings/022.svg b/NixTeX/dependencies/assets/pictograms/iso7010/warnings/022.svg new file mode 100644 index 0000000..0a95162 --- /dev/null +++ b/NixTeX/dependencies/assets/pictograms/iso7010/warnings/022.svg @@ -0,0 +1,115 @@ + + + + + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + diff --git a/NixTeX/dependencies/assets/pictograms/iso7010/warnings/023.pdf b/NixTeX/dependencies/assets/pictograms/iso7010/warnings/023.pdf new file mode 100644 index 0000000..8c42c77 Binary files /dev/null and b/NixTeX/dependencies/assets/pictograms/iso7010/warnings/023.pdf differ diff --git a/NixTeX/dependencies/assets/pictograms/iso7010/warnings/023.svg b/NixTeX/dependencies/assets/pictograms/iso7010/warnings/023.svg new file mode 100644 index 0000000..4caeb15 --- /dev/null +++ b/NixTeX/dependencies/assets/pictograms/iso7010/warnings/023.svg @@ -0,0 +1,30 @@ + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/NixTeX/dependencies/assets/pictograms/iso7010/warnings/024.pdf b/NixTeX/dependencies/assets/pictograms/iso7010/warnings/024.pdf new file mode 100644 index 0000000..08ec6fd Binary files /dev/null and b/NixTeX/dependencies/assets/pictograms/iso7010/warnings/024.pdf differ diff --git a/NixTeX/dependencies/assets/pictograms/iso7010/warnings/024.svg b/NixTeX/dependencies/assets/pictograms/iso7010/warnings/024.svg new file mode 100644 index 0000000..cf29c58 --- /dev/null +++ b/NixTeX/dependencies/assets/pictograms/iso7010/warnings/024.svg @@ -0,0 +1,15 @@ + + + + + + image/svg+xml + + + + + + + + + diff --git a/NixTeX/dependencies/assets/pictograms/iso7010/warnings/025.pdf b/NixTeX/dependencies/assets/pictograms/iso7010/warnings/025.pdf new file mode 100644 index 0000000..cc885e3 Binary files /dev/null and b/NixTeX/dependencies/assets/pictograms/iso7010/warnings/025.pdf differ diff --git a/NixTeX/dependencies/assets/pictograms/iso7010/warnings/025.svg b/NixTeX/dependencies/assets/pictograms/iso7010/warnings/025.svg new file mode 100644 index 0000000..ba5a608 --- /dev/null +++ b/NixTeX/dependencies/assets/pictograms/iso7010/warnings/025.svg @@ -0,0 +1,20 @@ + + + + + + image/svg+xml + + + + + + + + + + + + + + diff --git a/NixTeX/dependencies/assets/pictograms/iso7010/warnings/026.pdf b/NixTeX/dependencies/assets/pictograms/iso7010/warnings/026.pdf new file mode 100644 index 0000000..6bc4cb5 Binary files /dev/null and b/NixTeX/dependencies/assets/pictograms/iso7010/warnings/026.pdf differ diff --git a/NixTeX/dependencies/assets/pictograms/iso7010/warnings/026.svg b/NixTeX/dependencies/assets/pictograms/iso7010/warnings/026.svg new file mode 100644 index 0000000..f01c986 --- /dev/null +++ b/NixTeX/dependencies/assets/pictograms/iso7010/warnings/026.svg @@ -0,0 +1,72 @@ + + + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + + + + diff --git a/NixTeX/dependencies/assets/pictograms/iso7010/warnings/027.pdf b/NixTeX/dependencies/assets/pictograms/iso7010/warnings/027.pdf new file mode 100644 index 0000000..03d2543 Binary files /dev/null and b/NixTeX/dependencies/assets/pictograms/iso7010/warnings/027.pdf differ diff --git a/NixTeX/dependencies/assets/pictograms/iso7010/warnings/027.svg b/NixTeX/dependencies/assets/pictograms/iso7010/warnings/027.svg new file mode 100644 index 0000000..988387c --- /dev/null +++ b/NixTeX/dependencies/assets/pictograms/iso7010/warnings/027.svg @@ -0,0 +1,19 @@ + + + + + + image/svg+xml + + + + + + + + + + + + + diff --git a/NixTeX/dependencies/assets/pictograms/iso7010/warnings/028.pdf b/NixTeX/dependencies/assets/pictograms/iso7010/warnings/028.pdf new file mode 100644 index 0000000..e7b6e83 Binary files /dev/null and b/NixTeX/dependencies/assets/pictograms/iso7010/warnings/028.pdf differ diff --git a/NixTeX/dependencies/assets/pictograms/iso7010/warnings/028.svg b/NixTeX/dependencies/assets/pictograms/iso7010/warnings/028.svg new file mode 100644 index 0000000..dbacb36 --- /dev/null +++ b/NixTeX/dependencies/assets/pictograms/iso7010/warnings/028.svg @@ -0,0 +1,102 @@ + + + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + + + + + + diff --git a/NixTeX/dependencies/assets/pictograms/iso7010/warnings/029.pdf b/NixTeX/dependencies/assets/pictograms/iso7010/warnings/029.pdf new file mode 100644 index 0000000..c1128e1 Binary files /dev/null and b/NixTeX/dependencies/assets/pictograms/iso7010/warnings/029.pdf differ diff --git a/NixTeX/dependencies/assets/pictograms/iso7010/warnings/029.svg b/NixTeX/dependencies/assets/pictograms/iso7010/warnings/029.svg new file mode 100644 index 0000000..48d4a9c --- /dev/null +++ b/NixTeX/dependencies/assets/pictograms/iso7010/warnings/029.svg @@ -0,0 +1,67 @@ + + + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + + + diff --git a/NixTeX/dependencies/assets/pictograms/iso7010/warnings/035.pdf b/NixTeX/dependencies/assets/pictograms/iso7010/warnings/035.pdf new file mode 100644 index 0000000..6fedb33 Binary files /dev/null and b/NixTeX/dependencies/assets/pictograms/iso7010/warnings/035.pdf differ diff --git a/NixTeX/dependencies/assets/pictograms/iso7010/warnings/035.svg b/NixTeX/dependencies/assets/pictograms/iso7010/warnings/035.svg new file mode 100644 index 0000000..b622109 --- /dev/null +++ b/NixTeX/dependencies/assets/pictograms/iso7010/warnings/035.svg @@ -0,0 +1,2 @@ + +image/svg+xml diff --git a/NixTeX/dependencies/assets/pictograms/iso7010/warnings/039.pdf b/NixTeX/dependencies/assets/pictograms/iso7010/warnings/039.pdf new file mode 100644 index 0000000..b627a72 Binary files /dev/null and b/NixTeX/dependencies/assets/pictograms/iso7010/warnings/039.pdf differ diff --git a/NixTeX/dependencies/assets/pictograms/iso7010/warnings/039.svg b/NixTeX/dependencies/assets/pictograms/iso7010/warnings/039.svg new file mode 100644 index 0000000..bdea442 --- /dev/null +++ b/NixTeX/dependencies/assets/pictograms/iso7010/warnings/039.svg @@ -0,0 +1,105 @@ + + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + + diff --git a/NixTeX/dependencies/assets/pictograms/other/corrosive.pdf b/NixTeX/dependencies/assets/pictograms/other/corrosive.pdf new file mode 100644 index 0000000..348df81 Binary files /dev/null and b/NixTeX/dependencies/assets/pictograms/other/corrosive.pdf differ diff --git a/NixTeX/dependencies/assets/pictograms/other/corrosive_inverted.pdf b/NixTeX/dependencies/assets/pictograms/other/corrosive_inverted.pdf new file mode 100644 index 0000000..f1cd635 Binary files /dev/null and b/NixTeX/dependencies/assets/pictograms/other/corrosive_inverted.pdf differ diff --git a/NixTeX/dependencies/assets/pictograms/other/ecoHazard.pdf b/NixTeX/dependencies/assets/pictograms/other/ecoHazard.pdf new file mode 100644 index 0000000..320e44a Binary files /dev/null and b/NixTeX/dependencies/assets/pictograms/other/ecoHazard.pdf differ diff --git a/NixTeX/dependencies/assets/pictograms/other/ecoHazard_inverted.pdf b/NixTeX/dependencies/assets/pictograms/other/ecoHazard_inverted.pdf new file mode 100644 index 0000000..97e507b --- /dev/null +++ b/NixTeX/dependencies/assets/pictograms/other/ecoHazard_inverted.pdf @@ -0,0 +1,73 @@ +%PDF-1.5 +% +4 0 obj +<< /Length 5 0 R + /Filter /FlateDecode +>> +stream +xmUM$5 W`b'N^8,Ԉ]{i4+ ?)ؚvoE+~~{_)]fV_jV(TU`_hh}֖ak~>S2 wm$/tM9Ne=6>& Qu!τ-1>z-.+{tlyQl{2+ݭ.:/Qzpڢj {l~ g:Qt〯!R+D=f$WlV]uA HMimٸfHר6ץ ZodΎcd +UnO]h~=GSenblɺO@M}iSfob88M]e,YPf z}|9MNMtAWF5uCʯ-Y}t4+4j:iR{X( V'P.>ŠLtYӓ%oXY\$Dn~8Rhn#:F*ӨL4>8Rx~> + >> +>> +endobj +2 0 obj +<< /Type /Page % 1 + /Parent 1 0 R + /MediaBox [ 0 0 219.6866 219.276978 ] + /Contents 4 0 R + /Group << + /Type /Group + /S /Transparency + /I true + /CS /DeviceRGB + >> + /Resources 3 0 R +>> +endobj +1 0 obj +<< /Type /Pages + /Kids [ 2 0 R ] + /Count 1 +>> +endobj +6 0 obj +<< /Producer (cairo 1.16.0 (https://cairographics.org)) + /CreationDate (D:20200712050140+02'00) +>> +endobj +7 0 obj +<< /Type /Catalog + /Pages 1 0 R +>> +endobj +xref +0 8 +0000000000 65535 f +0000001445 00000 n +0000001215 00000 n +0000001143 00000 n +0000000015 00000 n +0000001120 00000 n +0000001510 00000 n +0000001626 00000 n +trailer +<< /Size 8 + /Root 7 0 R + /Info 6 0 R +>> +startxref +1678 +%%EOF diff --git a/NixTeX/dependencies/assets/pictograms/other/explosive.pdf b/NixTeX/dependencies/assets/pictograms/other/explosive.pdf new file mode 100644 index 0000000..3df2c2f Binary files /dev/null and b/NixTeX/dependencies/assets/pictograms/other/explosive.pdf differ diff --git a/NixTeX/dependencies/assets/pictograms/other/explosive_inverted.pdf b/NixTeX/dependencies/assets/pictograms/other/explosive_inverted.pdf new file mode 100644 index 0000000..4f6eb74 Binary files /dev/null and b/NixTeX/dependencies/assets/pictograms/other/explosive_inverted.pdf differ diff --git a/NixTeX/dependencies/assets/pictograms/other/flammable.pdf b/NixTeX/dependencies/assets/pictograms/other/flammable.pdf new file mode 100644 index 0000000..7efea0b Binary files /dev/null and b/NixTeX/dependencies/assets/pictograms/other/flammable.pdf differ diff --git a/NixTeX/dependencies/assets/pictograms/other/flammable_inverted.pdf b/NixTeX/dependencies/assets/pictograms/other/flammable_inverted.pdf new file mode 100644 index 0000000..9559a68 Binary files /dev/null and b/NixTeX/dependencies/assets/pictograms/other/flammable_inverted.pdf differ diff --git a/NixTeX/dependencies/assets/pictograms/other/gasBottle.pdf b/NixTeX/dependencies/assets/pictograms/other/gasBottle.pdf new file mode 100644 index 0000000..d409cab Binary files /dev/null and b/NixTeX/dependencies/assets/pictograms/other/gasBottle.pdf differ diff --git a/NixTeX/dependencies/assets/pictograms/other/gasBottle_inverted.pdf b/NixTeX/dependencies/assets/pictograms/other/gasBottle_inverted.pdf new file mode 100644 index 0000000..dea6503 Binary files /dev/null and b/NixTeX/dependencies/assets/pictograms/other/gasBottle_inverted.pdf differ diff --git a/NixTeX/dependencies/assets/pictograms/other/lithiumCells.pdf b/NixTeX/dependencies/assets/pictograms/other/lithiumCells.pdf new file mode 100644 index 0000000..4954857 Binary files /dev/null and b/NixTeX/dependencies/assets/pictograms/other/lithiumCells.pdf differ diff --git a/NixTeX/dependencies/assets/pictograms/other/oxidiser.pdf b/NixTeX/dependencies/assets/pictograms/other/oxidiser.pdf new file mode 100644 index 0000000..90de71e Binary files /dev/null and b/NixTeX/dependencies/assets/pictograms/other/oxidiser.pdf differ diff --git a/NixTeX/dependencies/assets/pictograms/other/oxidiser_inverted.pdf b/NixTeX/dependencies/assets/pictograms/other/oxidiser_inverted.pdf new file mode 100644 index 0000000..1b593c8 Binary files /dev/null and b/NixTeX/dependencies/assets/pictograms/other/oxidiser_inverted.pdf differ diff --git a/NixTeX/dependencies/assets/pictograms/other/skull.pdf b/NixTeX/dependencies/assets/pictograms/other/skull.pdf new file mode 100644 index 0000000..51ae3ad Binary files /dev/null and b/NixTeX/dependencies/assets/pictograms/other/skull.pdf differ diff --git a/NixTeX/dependencies/assets/pictograms/other/skull_inverted.pdf b/NixTeX/dependencies/assets/pictograms/other/skull_inverted.pdf new file mode 100644 index 0000000..e0adfd4 Binary files /dev/null and b/NixTeX/dependencies/assets/pictograms/other/skull_inverted.pdf differ diff --git a/NixTeX/dependencies/source/bibliography/citation.tex b/NixTeX/dependencies/source/bibliography/citation.tex new file mode 100644 index 0000000..910977b --- /dev/null +++ b/NixTeX/dependencies/source/bibliography/citation.tex @@ -0,0 +1,14 @@ +\directlua{includeCode("bibliography/citation")} +\newtotcounter{citenum} +\AtEveryBibitem{\stepcounter{citenum}} +\def\@ResetSymbols{} + +\let\@cite=\cite +\renewcommand{\cite}[2][]{\textsuperscript{\mbox{\ifthenelse{\equal{#2}{}}{\href{https://xkcd.com/285/}{[\todo{citation needed}]}}{\@cite[#1]{#2}}}}} +\newcommand{\citeHere}[1]{\directlua{citations.clear([[#1]])}} +\renewcommand{\footcite}[1]{\footnote{\fullcite{#1}}} +\newcommand{\loadReferences}[2][]{\directlua{citations.load([[#1]],[[#2]])}} + +\def\referenceMyself{???} +\newcommand{\setSelfReference}[2]{\def\referenceMyself{\underline{#2, \directlua{tex.print(([[#1]]):sub(1,1))}.}}} + diff --git a/NixTeX/dependencies/source/chemfig.tex b/NixTeX/dependencies/source/chemfig.tex new file mode 100644 index 0000000..9bac19a --- /dev/null +++ b/NixTeX/dependencies/source/chemfig.tex @@ -0,0 +1,2674 @@ +\csname CFloadonce\endcsname +\let\CFloadonce\endinput +% +\ifdefined\CFfromsty\else + \immediate\write -1 {% + Package: \CFname\space\CFdate\space\space v\CFver\space\space + Draw molecule with an easy syntax (CT)}% +\fi + +% +\begingroup + \def\X#1{\catcode\number`#1=\number\catcode`#1\relax} + \xdef\CFrestorecatcode{\X\[\X\]\X\:\X\(\X\)\X\,\X\-\X\=\X\~\X\!\X\?\X\<\X\>\X\;\X\*\X\|\X\@\X\ \X\_}% +\endgroup +\catcode`\[12 \catcode`\]12 \catcode`\:12 \catcode`\(12 +\catcode`\)12 \catcode`\,12 \catcode`\-12 \catcode`\=12 +\catcode`\~12 \catcode`\!12 \catcode`\?12 \catcode`\<12 +\catcode`\>12 \catcode`\;12 \catcode`\*12 \catcode`\|12 +\catcode`\@12 \catcode`\#6 \catcode`\ 10 \catcode`\_11 + +% +\def\CF_error#1{\errmessage{Package \CFname\space Error: #1.}} +\def\CF_warning#1{\immediate\write-1{Package \CFname\space Warning: #1^^J}} +\def\CF_checkprimitive#1#2{% + \begingroup + \edef\__tempa{\meaning#1}\edef\__tempb{\string#1}\expandafter + \endgroup + \ifx\__tempa\__tempb\else + \CF_error{#2}% + \def\CF_temp{\CFrestorecatcode\endinput}% + \expandafter\CF_temp + \fi +} +\CF_checkprimitive\eTeXversion{You are not using an eTeX engine, \CFname\space cannot work.} +\CF_checkprimitive\expanded{the \string\expanded\space primitive is not provided by your TeX engine, \CFname\space cannot work.} + +% +\input simplekv.tex + +% +\unless\ifdefined\tikzpicture + \begingroup\def\CFtemp{\endgroup\input tikz.tex\relax}% + \expandafter\CFtemp +\fi +\usetikzlibrary{arrows.meta} + +% +\newcount\CF_cntatomgroup +\newcount\CF_cntgroup +\newcount\CF_cntatom +\newcount\CF_cntcycle +\newcount\CF_cntcyclebonds +\newcount\CF_cntcompound + +\newif\ifCF_incycle +\newif\ifCF_cyclearc +\newif\ifCF_definesubmol +\newif\ifCF_adjustnamedp +\newif\ifCF_macrofixedbondlength +\newif\ifCF_compound_is_chemfig + +\newdimen\CF_dim +\newdimen\CF_arrowsize +\newdimen\CF_zero \CF_zero=0pt + +\newbox\CF_box +\newbox\CF_boxstuff +\newbox\CF_testbox +\newbox\CF_chargebox + +\newtoks\CF_substtoks + +% +\let\CF_begintikzpicture\tikzpicture +\let\CF_endtikzpicture \endtikzpicture +\def\CF_quark{\CF_quark} +\def\CF_execfirst#1#2{#1} +\def\CF_execsecond#1#2{#2} +\def\CF_id#1{#1} +\def\CF_gobarg#1{} +\def\CF_gobtwoargs#1#2{} +\def\CF_firsttonil#1#2\_nil{#1} +\def\CF_sanitizelastitem#1,\empty#2\_nil{#1} +\def\CF_gobtikzinstruction#1;{} +\def\CF_makeother#1{\catcode`#1=12\relax} +\def\CF_lettoken#1#2{\let#1= #2}\CF_lettoken\CF_sptoken{ } +\def\CF_ifx#1#2{\ifx#1#2\expandafter\CF_execfirst\else\expandafter\CF_execsecond\fi} +\def\CF_ifempty#1{\ifx\empty#1\empty\expandafter\CF_execfirst\else\expandafter\CF_execsecond\fi} +\def\CF_ifnum#1{\ifnum#1\expandafter\CF_execfirst\else\expandafter\CF_execsecond\fi} +\def\CF_ifinsidetikz{\ifdefined\pgfpictureid\expandafter\CF_execfirst\else\expandafter\CF_execsecond\fi} +\def\CF_ifzerodim#1{% + \setbox\CF_testbox\hbox{\pgfinterruptpicture\printatom{#1}\endpgfinterruptpicture}% + \CF_ifnum{1\ifdim\wd\CF_testbox=\CF_zero0\fi\ifdim\ht\CF_testbox=\CF_zero0\fi\ifdim\dp\CF_testbox=\CF_zero0\fi=1000 } +} +\def\CF_doifempty#1{\ifx\empty#1\empty\expandafter\CF_id\else\expandafter\CF_gobarg\fi} +\def\CF_doifnotempty#1{\ifx\empty#1\empty\expandafter\CF_gobarg\else\expandafter\CF_id\fi} +\def\CF_gobtonil#1\_nil{} +\def\CF_striplastsp#1{% + \long\def\CF_stripsp##1##2{\expanded{\CF_stripsp_i\_marksp##1\__nil\_marksp#1\_marksp\_nil{##2}}}% + \long\def\CF_stripsp_i##1\_marksp#1##2\_marksp##3\_nil{\CF_stripsp_ii##3##1##2\__nil#1\__nil\_nil}% + \long\def\CF_stripsp_ii##1#1\__nil##2\_nil{\CF_stripsp_iii##1##2\_nil}% + \long\def\CF_stripsp_iii##1##2\__nil##3\_nil##4{\unexpanded{##4{##2}}}% + \long\def\CF_striplastsp##1##2{\expanded{\CF_striplastsp_i\_marksp##1\__nil#1\__nil\_nil{##2}}}% + \long\def\CF_striplastsp_i##1#1\__nil##2\_nil{\CF_stripsp_iii##1\__nil\_nil}% +}\CF_striplastsp{ } +\edef\CFhash{\string#} +\begingroup + \catcode`\_8 + \expandafter\gdef\csname CF\string_underscore\endcsname{_} +\endgroup +\def\CF_threeea{\expandafter\expandafter\expandafter} +\def\CF_exptwomacroargs#1#2#3{\CF_expsecond{\CF_expsecond#1{#2}}{#3}} +\def\CF_expthreemacroargs#1#2#3#4{\CF_expsecond{\CF_exptwomacroargs#1{#2}{#3}}{#4}} +\def\CF_swaparg#1#2{#2{#1}} +\def\CF_expsecond#1#2{\expandafter\CF_swaparg\expandafter{#2}{#1}}% +\def\CF_eexpsecond#1#2{\expandafter\expandafter\expandafter\CF_swaparg\expandafter\expandafter\expandafter{#2}{#1}}% +\def\CF_swapunbrace#1#2{#2#1} +\def\CF_expafter#1#2{\expandafter\CF_swapunbrace\expandafter{#2}{#1}}% +\def\CF_eexpafter#1#2{\expandafter\expandafter\expandafter\CF_swapunbrace\expandafter\expandafter\expandafter{#2}{#1}}% +\def\CF_addtomacro#1#2{\CF_expsecond{\def#1}{#1#2}} +\def\CF_eaddtomacro#1#2{\CF_expsecond{\CF_addtomacro#1}{#2}} +\def\CF_preaddtomacro#1#2{\CF_expsecond{\CF_preaddtomacroa#1{#2}}#1} +\def\CF_preaddtomacroa#1#2#3{\def#1{#2#3}} +\def\CF_addtotoks#1#2{#1\expandafter{\the#1#2}} +\def\CF_eaddtotoks#1#2{\expandafter\CF_addtotoks\expandafter#1\expandafter{#2}} +\def\CF_assigntonil#1#2\_nil{\def#1{#2}} +\def\CF_edefaddtomacro#1#2{\CF_expsecond{\CF_addtomacro#1}{\expanded{#2}}} +\def\CF_ifnextchar#1#2#3{% + \let\CF_ifnextchartok=#1% + \def\CF_ifnextcharcodetrue{#2}% + \def\CF_ifnextcharcodefalse{#3}% + \futurelet\CF_temptok\CF_ifnextchara +} +\def\CF_ifnextchara{% + \CF_ifx\CF_temptok\CF_sptoken + {\CF_ifnextcharb + } + {\CF_ifx\CF_temptok\CF_ifnextchartok + \CF_ifnextcharcodetrue + \CF_ifnextcharcodefalse + }% +} +\expandafter\def\expandafter\CF_ifnextcharb\space{\futurelet\CF_temptok\CF_ifnextchara} +\def\CF_ifstar#1{\CF_ifnextchar*{\CF_execfirst{#1}}} +\def\CF_testopt#1#2{\CF_ifnextchar[{#1}{#1[{#2}]}} +\def\CF_ifinteger#1{% + \begingroup + \afterassignment\CF_afterinteger + \CF_cntcyclebonds0#1\relax +} +\def\CF_afterinteger#1\relax{% + \endgroup + \CF_ifempty{#1}% +} +\def\CF_iffirsttokmatch#1#2{% + \futurelet\CF_toksa\CF_gobtonil#1\relax\_nil + \futurelet\CF_toksb\CF_gobtonil#2\relax\_nil + \CF_ifx\CF_toksa\CF_toksb +} +\def\CF_iffirsttokin#1{% + \futurelet\CF_toksa\CF_gobtonil#1\relax\_nil + \CF_iffirsttokina +} +\def\CF_iffirsttokina#1{% + \CF_ifempty{#1} + {\CF_execsecond + } + {\futurelet\CF_toksb\CF_gobtonil#1\relax\_nil + \CF_ifx\CF_toksa\CF_toksb + {\CF_execfirst} + {\CF_expsecond\CF_iffirsttokina{\CF_gobarg#1}}% + }% +} +\def\CF_ifinstr#1#2{% + \def\CF_ifinstra##1#2##2\_nil{% + \ifx\empty##2\empty + \expandafter\CF_execsecond + \else + \expandafter\CF_execfirst + \fi}% + \CF_ifinstra#1\__nil#2\_nil +} +\def\CF_afterspace#1 #2\_nil{#2} + +% +\def\CF_ifstartwith#1#2{% + \CF_ifempty{#1}% + {\CF_execsecond + } + {\def\CF_startwithcode{#1}% + \def\CF_startwithpattern{#2}% + \CF_ifstartwitha + }% +} +\def\CF_ifstartwitha{% + \CF_grabfirstarg\CF_startwithcode\CF_firstargcode + \CF_grabfirstarg\CF_startwithpattern\CF_firstargpattern + \CF_ifx\CF_firstargcode\CF_firstargpattern + {\CF_expsecond\CF_ifempty\CF_startwithpattern + {\CF_execfirst + } + {\CF_expsecond\CF_ifempty\CF_startwithcode + \CF_execsecond + \CF_ifstartwitha + }% + } + {\CF_execsecond + }% +} +\def\CF_grabfirstarg#1#2{% + \CF_ifx#1\empty + {\let#2\empty + } + {\def\CF_grabmacro{#2}% + \CF_expsecond\CF_ifbracefirst#1% + {\expandafter\CF_grabbracearg#1\_nil#1} + {\CF_expafter{\futurelet\CF_nexttok\CF_grabfirstarga}#1\_nil#1}% + }% +} +\def\CF_grabfirstarga{% + \CF_ifx\CF_nexttok\CF_sptoken + \CF_grabspacearg + \CF_grabnormalarg +} +\def\CF_grabbracearg#1{% + \expandafter\def\CF_grabmacro{{#1}}% + \CF_grabargassigntonil\relax +} +\expandafter\def\expandafter\CF_grabspacearg\space{% + \expandafter\def\CF_grabmacro{ }% + \CF_grabargassigntonil\relax +} +\def\CF_grabnormalarg#1{% + \expandafter\def\CF_grabmacro{#1}% + \CF_grabargassigntonil\relax +} +\def\CF_grabargassigntonil#1\_nil#2{\CF_expsecond{\def#2}{\CF_gobarg#1}} +\def\CF_ifbracefirst#1{\CF_ifnum{\catcode\CF_threeea`\expandafter\CF_firsttonil\detokenize{#1.}\_nil=1 }} +\def\CF_substonly#1#2{% + \def\CF_atendsubstitute{\edef#2{\the\CF_substtoks}}% + \let\CF_substnogroups\CF_substnogrouponly + \CF_ifnum{#1>0 } + {\let\CF_testifx\empty + \foreach\CF_x in {1,...,#1} + {\xdef\CF_testifx{\unexpanded\expandafter{\CF_testifx}\unexpanded\expandafter{\expandafter\ifx\CF_x\CF_nexttok1\fi}}}% + \let\CF_testif\empty + \foreach\CF_x in {1,...,#1} + {\xdef\CF_testif{\unexpanded\expandafter{\CF_testif}\unexpanded\expandafter{\expandafter\if\CF_x\CF_nexttok1\fi}}}% + \CF_expsecond\CF_substi#2% + } + {\CF_substall#2% + }% +} +\def\CF_substnogrouponly{% + \CF_exptwomacroargs\CF_ifstartwith\CF_substcode\CF_substsubst + {\CF_grabfirstarg\CF_substcode\CF_temp + \CF_expafter{\futurelet\CF_nexttok\CF_gobtonil}\CF_substcode\relax\_nil + \CF_ifnum{0\CF_testifx=1 }% + {\edef\CF_nexttok{\CF_threeea\CF_firsttonil\expandafter\string\CF_substcode\_nil}% + \CF_ifnum{0\CF_testif=1 } + {\CF_eaddtotoks\CF_substtoks\CF_temp + \CF_grabfirstarg\CF_substcode\CF_temp + \CF_eaddtotoks\CF_substtoks\CF_temp + } + {\CF_eaddtotoks\CF_substtoks\CF_substpattern + }% + } + {\CF_eaddtotoks\CF_substtoks\CF_substpattern + }% + \CF_substgroups + } + {\CF_expsecond\CF_ifempty\CF_substcode + {\CF_atendsubstitute + } + {\CF_grabfirstarg\CF_substcode\CF_substauxarg + \CF_eaddtotoks\CF_substtoks\CF_substauxarg + \CF_substgroups + }% + }% +} +\def\CF_substall#1{% + \def\CF_atendsubstitute{\edef#1{\the\CF_substtoks}}% + \let\CF_substnogroups\CF_substnogroupall + \CF_expsecond\CF_substi#1% +} +\def\CF_substnogroupall{% + \CF_exptwomacroargs\CF_ifstartwith\CF_substcode\CF_substsubst + {\CF_eaddtotoks\CF_substtoks\CF_substpattern + \CF_grabfirstarg\CF_substcode\CF_temp + \CF_substgroups + } + {\CF_expsecond\CF_ifempty\CF_substcode + {\CF_atendsubstitute + } + {\CF_grabfirstarg\CF_substcode\CF_substauxarg + \CF_eaddtotoks\CF_substtoks\CF_substauxarg + \CF_substgroups + }% + }% +} +\def\CF_substi#1#2#3{% + \def\CF_substcode{#1}\def\CF_substsubst{#2}\def\CF_substpattern{#3}% + \CF_substtoks={}% + \CF_substgroups +} + +\def\CF_substgroups{% + \CF_expsecond\CF_ifbracefirst\CF_substcode + {\CF_grabfirstarg\CF_substcode\CF_substauxarg + \begingroup + \def\CF_atendsubstitute{% + \expandafter\endgroup\expandafter\CF_addtotoks\expandafter\CF_substtoks\expandafter{\expandafter{\the\CF_substtoks}}% + \CF_substgroups + }% + \CF_substtoks{}% + \expandafter\def\expandafter\CF_substcode\CF_substauxarg + \CF_substgroups + }% + {\CF_substnogroups + }% +} + +% +\def\CF_defifempty#1#2#3{\CF_ifempty{#2}{\def#1{#3}}{\def#1{#2}}} +\defKV[chemfig]{% + atom style = \def\CF_atomstyle {#1}, + chemfig style = \def\CF_chemfigstyle {#1}, + cram width = \CF_defifempty\CF_crambasewidth {#1}{1.5ex}, + cram dash width = \CF_defifempty\CF_cramdashlength {#1}{1pt}, + cram dash sep = \CF_defifempty\CF_cramdashsep {#1}{2pt}, + atom sep = \CF_defifempty\CF_atomsep {#1}{3em}, + bond offset = \CF_defifempty\CF_bondoffset {#1}{2pt}, + double bond sep = \CF_defifempty\CF_doublesep {#1}{2pt}, + angle increment = \CF_defifempty\CF_angleincrement {#1}{45}, + node style = \def\CF_nodestyle {#1}, + bond style = \def\CF_bondstyle {#1}, + cycle radius coeff = \CF_defifempty\CF_cycleradiuscoeff {#1}{0.75}, + stack sep = \CF_defifempty\CF_stacksep {#1}{1.5pt}, + compound style = \def\CF_defaultcompoundstyle {#1}, + compound sep = \CF_defifempty\CF_compoundsep {#1}{5em}, + arrow offset = \CF_defifempty\CF_arrowoffset {#1}{1em}, + arrow angle = \CF_defifempty\CF_arrowangle {#1}{0}, + arrow coeff = \CF_defifempty\CF_arrowlength {#1}{1}, + arrow style = \def\CF_defaultarrowstyle {#1}, + arrow double sep = \CF_defifempty\CF_arrowdoublesep {#1}{2pt}, + arrow double coeff = \CF_defifempty\CF_arrowdoubleposstart{#1}{0.6}, + arrow label sep = \CF_defifempty\CF_arrowlabelsep {#1}{3pt}, + arrow head = \CF_defifempty\CF_arrowhead {#1}{-CF}, + + sep left = \CF_defifempty\CF_signspaceante {#1}{0.5em}, + + sep right = \CF_defifempty\CF_signspacepost {#1}{0.5em}, + + vshift = \CF_defifempty\CF_signvshift {#1}{0pt} +} +\def\setchemfig{\setKV[chemfig]} +\def\resetchemfig{\restoreKV[chemfig]} +\setKVdefault[chemfig]{% + atom style = {},% + chemfig style = {},% + bond join = false, + fixed length = false, + cram rectangle = false, + cram width = 1.5ex, + cram dash width = 1pt, + cram dash sep = 2pt, + atom sep = 3em, + bond offset = 2pt, + double bond sep = 2pt, + angle increment = 45, + node style = {}, + bond style = {}, + cycle radius coeff = 0.75, + stack sep = 1.5pt, + autoreset cntcycle = true, + show cntcycle = false, + debug =false, + scheme debug = false, + compound style = {}, + compound sep = 5em, + arrow offset = 1em, + arrow angle = 0, + arrow coeff = 1, + arrow style = {}, + arrow double sep = 2pt, + arrow double coeff = 0.6, + arrow double harpoon= true, + arrow label sep = 3pt, + arrow head = -CF, + + sep left = 0.5em, + + sep right = 0.5em, + + vshift = 0pt, +}% + +% +% +% +\def\CF_sanitizecatcode{% + \CF_makeother\[\CF_makeother\]\CF_makeother\:\CF_makeother\(\CF_makeother\)% + \CF_makeother\,\CF_makeother\-\CF_makeother\=\CF_makeother\~\CF_makeother\!% + \CF_makeother\?\CF_makeother\<\CF_makeother\>\CF_makeother\;\CF_makeother\*% + \CF_makeother\|\CF_makeother\#\CF_makeother\@% +} + +\def\printatom#1{\ifmmode\rm#1\else$\rm#1$\fi} + +\def\CF_nodecontent{\CF_expsecond\printatom{\csname atom_\number\CF_cntatom\endcsname\CF_nodestrut}} + +\def\chemskipalign{% + \CF_doifempty\CF_bondoutcontentsaved% + {\global\let\CF_bondoutcontentsaved\CF_bondoutcontent}% + \let\CF_nodestrut\empty +} + +\def\definesubmol{\CF_definesubmoltrue\def_submol} +\def\redefinesubmol{\CF_definesubmolfalse\def_submol} + +\def\def_submol#1{% + \CF_cntatomgroup=0 % + \def\CF_temp{#1}% + \futurelet\CF_toksa\CF_submoltestnxttok +} + +\def\CF_submoltestnxttok{% + \if[\noexpand\CF_toksa\expandafter\CF_execfirst\else\expandafter\CF_execsecond\fi + {\begingroup\CF_sanitizecatcode\CF_expsecond\CF_submolgrabopt{\CF_temp}% + } + {\afterassignment\CF_submoltestnxttoka% + \CF_cntatomgroup=0% + }% +} + +\def\CF_submoltestnxttoka{\futurelet\CF_toksa\CF_submoltestnxttokb} + +\def\CF_submoltestnxttokb{% + \if[\noexpand\CF_toksa\expandafter\CF_execfirst\else\expandafter\CF_execsecond\fi + {\begingroup\CF_sanitizecatcode\CF_expsecond\CF_submolgrabopt{\CF_temp}} + {\CF_expsecond{\def_submola}\CF_temp{}}% +} + +\def\CF_submolgrabopt#1[#2]#{\endgroup\def_submola{#1}{#2}} + +\def\def_submola#1{% + \CF_ifnum{0\CF_ifnum{\CF_cntatomgroup<0 }1{\CF_ifnum{\CF_cntatomgroup>9 }10}>0 } + {\CF_error{Invalid number of arguments in submol \detokenize\expandafter{\string#1}. Defining it with 0 argument}% + \CF_cntatomgroup=0 + } + {}% + \ifcat\relax\expandafter\noexpand\CF_firsttonil#1\_nil\expandafter\CF_execfirst\else\expandafter\CF_execsecond\fi% + {\expandafter\ifdefined\CF_firsttonil#1\_nil + \ifCF_definesubmol + \CF_warning{the submol \expandafter\string\CF_firsttonil#1\_nil\space is already defined, the previous definition is lost}% + \fi + \fi + \begingroup + \CF_sanitizecatcode + \def_submolb{#1}% + } + {\ifcsname CF__#1\endcsname + \ifCF_definesubmol + \CF_warning{the submol "#1" is already defined, the previous definition is lost}% + \fi + \fi + \begingroup + \CF_sanitizecatcode + \expandafter\def_submolb\csname CF__#1\endcsname + }% +} + +\def\def_submolb#1#2#3{% + \def\CF_tempa{#2}\CF_doifnotempty{#2}{\CF_expsecond{\CF_expsecond\CF_substonly{\number\CF_cntatomgroup}\CF_tempa}{\CFhash}{\CFhash}}% + \def\CF_tempb{#3}\CF_expsecond{\CF_expsecond\CF_substonly{\number\CF_cntatomgroup}\CF_tempb}{\CFhash}{\CFhash}% + \CF_expsecond{\CF_expsecond{\def_submolc{#1}}\CF_tempa}\CF_tempb +} + +\def\def_submolc#1#2#3{% + \endgroup + \begingroup + \global\toks0{\gdef\CFthesubmol}% + \CF_ifnum{\CF_cntatomgroup>0 } + {\foreach\CF_x in {1,...,\CF_cntatomgroup}{% + \global\toks0\expandafter{\expanded{\the\toks0\CFhash\CF_x}}% + }% + } + {}% + \CF_sanitizecatcode \catcode`\#6 \endlinechar-1 \everyeof{\noexpand}% + \CF_ifempty{#2}% + {\scantokens\expandafter{\the\toks0{\empty#3}}% + }% + {\scantokens\expandafter{% + \the\toks0{% + \expanded{% + \csname CF_exec% + \ifdim\csname CF_currentangle\endcsname pt>90pt + \ifdim\csname CF_currentangle\endcsname pt<270pt + first% + \else + second% + \fi + \else + second% + \fi + \endcsname + {\unexpanded{#2}}{\unexpanded{#3}}% + }% + }% + }% + }% + \endgroup + \let#1\CFthesubmol +} + +\def\CF_seeknode#1#2#3{% + \let#2\empty + \def#3{#1}% + \CF_iffirsttokmatch{#1}{ }% + {\CF_expsecond\CF_seeknodea{\romannumeral-`\.\noexpand#1}#2#3}% + {\CF_seeknodea{#1}#2#3}% +} + +\def\CF_seeknodea#1#2#3{% + \CF_ifempty{#1}% + {\let#3\empty + } + {\futurelet\CF_toksa\CF_gobtonil#1\relax\_nil + \CF_ifx\CF_toksa\CF_sptoken + {\CF_addtomacro#2{ }% + \CF_expsecond\CF_seeknodea{\CF_afterspace#1\_nil}#2#3% + }% + {\CF_ifx\CF_toksa\bgroup + {\CF_eaddtomacro#2{\expandafter{\CF_firsttonil#1\_nil}}% + \CF_expsecond\CF_seeknodea{\CF_gobarg#1}#2#3% + }% + {\CF_ifx!\CF_toksa% + {\def\CF_seeksubmloltemp{#1}% + \CF_seeksubmola + \CF_expsecond\CF_seeknodea\CF_seeksubmloltemp#2#3% + } + {\CF_iffirsttokina{-=(*<>~}% + {\def#3{#1}% + }% + {\CF_eaddtomacro#2{\CF_firsttonil#1\_nil}% + \CF_expsecond\CF_seeknodea{\CF_gobarg#1}#2#3% + }% + } + }% + }% + }% +} + +% +% +\def\CF_assignbondcode#1#2{% + \futurelet\CF_toksa\CF_gobtonil#1\_nil + \edef#2{% + \ifx-\CF_toksa1\else + \ifx=\CF_toksa2\else + \ifx~\CF_toksa3\else + \ifx>\CF_toksa4\else + \ifx<\CF_toksa5\else0% + \fi\fi\fi\fi\fi}% + \ifnum#2>3 % + \CF_expafter{\futurelet\CF_toksa\CF_gobtonil}{\CF_gobarg#1\_nil}% + \CF_ifx:\CF_toksa + {\edef#2{\number\numexpr#2+2}% + }% + {\CF_ifx|\CF_toksa% + {\edef#2{\number\numexpr#2+4}} + {}% + }% + \fi +} + +\def\CF_grabbondoffseta#1,#2\_nil{% + \def\CF_startoffset{#1}\def\CF_endoffset{#2}% +} + +\def\CF_grabbondoffset#1(#2)#3\_nil{% + \CF_doifnotempty{#2}% + {\CF_ifinstr{#2},% + {\CF_grabbondoffseta#2\_nil}% + {\def\CF_startoffset{#2}}% + }% + \def\CF_remainafterbond{#3}% +} + +\def\CF_analysebond#1#2{% + \CF_assignbondcode{#1}#2% + \CF_expsecond{\def\CF_remainafterbond}{\CF_gobarg#1}% + \let\CF_doublebondtype\CF_zero + \ifnum#2=2 % + \CF_expafter{\futurelet\CF_toksa\CF_gobtonil}{\CF_gobarg#1\_nil}% + \CF_ifx^\CF_toksa + {\def\CF_doublebondtype{1}% + \CF_expsecond{\def\CF_remainafterbond}{\CF_gobtwoargs#1}% + } + {\expandafter\ifx\CF_underscore\CF_toksa + \def\CF_doublebondtype{2}% + \CF_expsecond{\def\CF_remainafterbond}{\CF_gobtwoargs#1}% + \fi + }% + \else + \ifnum#2>5 % + \CF_expsecond{\def\CF_remainafterbond}{\CF_gobtwoargs#1}% + \fi + \fi + \CF_expsecond\CF_iffirsttokmatch\CF_remainafterbond\CFhash + {\CF_eexpsecond\CF_iffirsttokmatch{\expandafter\CF_gobarg\CF_remainafterbond.}(% + {\expandafter\CF_grabbondoffset\CF_remainafterbond\_nil} + {}% + }% + {}% + \CF_expsecond\CF_iffirsttokmatch\CF_remainafterbond @% + {\expandafter\CF_grabmovearg\CF_remainafterbond\_nil}% + {}% + \CF_expsecond\CF_iffirsttokmatch{\CF_remainafterbond}[% + {\expandafter\CF_analyseoptarg\CF_remainafterbond\_nil\CF_remainafterbond + }% + {\let\CF_currentstringangle\CF_defaultstringangle + \let\CF_currentlength\CF_defaultlength + \let\CF_currentfromatom\CF_defaultfromatom + \let\CF_currenttoatom\CF_defaulttoatom + \let\CF_currenttikz\CF_defaulttikz + \let\CF_movebondname\empty + }% + \ifCF_incycle + \pgfmathsetmacro\CF_cycleincrementangle{360/\CF_cyclenum+\CF_initcycleangle}% + \edef\CF_currentstringangle{::+\CF_cycleincrementangle}% + \def\CF_initcycleangle{0}% + \let\CF_currentlength\CF_defaultlength% + \fi + \CF_expsecond\CF_setbondangle{\CF_currentstringangle}\CF_currentangle +} + +\def\CF_setbondangle#1#2{% + \CF_ifempty{#1}% + {\let#2\CF_defaultangle + } + {\if:\expandafter\noexpand\CF_firsttonil#1\_nil + \if:\CF_threeea\noexpand\expandafter\CF_firsttonil\CF_gobarg#1\_nil + \pgfmathsetmacro#2{\CF_previousangle+\expandafter\CF_gobarg\CF_gobarg#1}% + \else + \pgfmathsetmacro#2{\CF_gobarg#1}% + \fi + \else + \pgfmathsetmacro#2{#1*\CF_angleincrement}% + \fi% + \ifdim\ifdim#2pt<0pt -\fi#2pt>360pt + \pgfmathsetmacro#2{#2-360*floor(#2/360)}% + \fi% + \ifdim#2pt<0pt + \pgfmathsetmacro#2{#2+360}% + \fi + }% +} + +\def\CF_analysemovearg#1,#2\_nil#3{% + \def#3{#1}\def\CF_movebondcoeff{#2}% +} + +% +% +\def\CF_grabmovearg @#1#2\_nil{% + \CF_ifinstr{#1},% + {\CF_analysemovearg#1\_nil\CF_movebondname}% + {\def\CF_movebondname{#1}\def\CF_movebondcoeff{0.5}}% + \def\CF_remainoptarg{#2}% +} + +\def\CF_testemptyandassign#1#2#3{% + \CF_ifempty{#2} + {\let#1#3} + {\def#1{#2}}% +} + +\def\CF_parseoptlist#1,#2,#3,#4,#5\_nil{% + \CF_testemptyandassign\CF_currentstringangle{#1}\CF_defaultstringangle + \CF_testemptyandassign\CF_currentlength {#2}\CF_defaultlength + \CF_testemptyandassign\CF_currentfromatom {#3}\CF_defaultfromatom + \CF_testemptyandassign\CF_currenttoatom {#4}\CF_defaulttoatom + \CF_expsecond{\CF_testemptyandassign\CF_currenttikz}{\CF_sanitizelastitem#5,\empty\_nil}\CF_defaulttikz +}% + +\def\CF_analyseoptarg[#1]{% + \CF_doifnotempty{#1}% + {\CF_iffirsttokmatch{#1}{@}% + {\CF_grabmovearg#1\_nil + } + {\let\CF_movebondname\empty + \def\CF_remainoptarg{#1}% + }% + \expandafter\CF_parseoptlist\CF_remainoptarg,\empty,\empty,\empty,\empty\_nil + }% + \CF_analyseoptarga\relax +} + +\def\CF_analyseoptarga#1\_nil#2{% + \CF_expsecond{\def#2}{\CF_gobarg#1}% +} + +\def\CF_seeksubmol#1#2{% + \def\CF_seeksubmloltemp{#1}% + \CF_seeksubmola + \let#2\CF_seeksubmloltemp +} + +\def\CF_seeksubmola{% + \CF_expsecond{\def\CF_seeksubmloltemp}{\romannumeral-`\.\expandafter\noexpand\CF_seeksubmloltemp}% + \CF_expsecond\CF_iffirsttokmatch{\CF_seeksubmloltemp}!% + {\CF_eexpsecond{\def\CF_seeksubmloltemp}{\expandafter\CF_gobarg\CF_seeksubmloltemp}% + \CF_ifx\empty\CF_seeksubmloltemp + {\CF_error{no submol name found after "!"}} + {}% + \ifcat\relax\CF_threeea\noexpand\expandafter\CF_firsttonil\CF_seeksubmloltemp*\_nil + \expandafter\CF_seeksubmolb\CF_seeksubmloltemp\_nil + \else + \expandafter\CF_seeksubmolc\CF_seeksubmloltemp\_nil + \fi + \CF_seeksubmola + }% + {}% +} + +\def\CF_seeksubmolb#1{\CF_seeksubmold#1\relax} + +\def\CF_seeksubmolc#1{\expandafter\CF_seeksubmold\csname CF__#1\endcsname\relax}% + +\def\CF_seeksubmold#1#2\_nil{% + \CF_expsecond{\CF_eexpsecond{\def\CF_seeksubmloltemp}}{\expandafter#1\CF_gobarg#2}% +} + +\def\CF_insertemptygroup#1{% + \CF_expsecond{\def#1}{\expandafter{\expandafter}#1}% +} + +\def\chemfig{\CF_testopt\CF_chemfiga{}} + +\def\CF_chemfiga[#1]{% + \begingroup + \CF_sanitizecatcode + \CF_exptwomacroargs\CF_chemfigb\CF_begintikzpicture\CF_endtikzpicture[#1]% +} + +\def\CF_chemfigb#1#2[#3]#4{% + \endgroup + \begingroup + \setchemfig{#3}% + \CF_ifinsidetikz + {\pgfinterruptpicture + \let\CF_atendofchemfig\endpgfinterruptpicture + } + {\let\CF_atendofchemfig\relax + }% + \expanded{% + \unexpanded{#1}[% + remember picture,% + every node/.style={% + anchor=base,% + inner sep=0pt,% + outer sep=0pt,% + minimum size=0pt,% + \unexpanded\expandafter{\CF_atomstyle}% + },% + baseline,% + \unexpanded\expandafter{\CF_chemfigstyle}% + ]% + }% + \begingroup% + \let\CF_hooklist\empty + \ifboolKV[chemfig]{fixed length} + {\CF_macrofixedbondlengthtrue} + {\CF_macrofixedbondlengthfalse}% + \ifboolKV[chemfig]{bond join} + {\let\CF_drawaxisbond\CF_drawaxisbondjoin} + {\let\CF_drawaxisbond\CF_drawaxisbondnojoin}% + \ifboolKV[chemfig]{cram rectangle} + {\let\CF_clipcramornot\CF_gobtikzinstruction} + {\let\CF_clipcramornot\clip}% + \CF_incyclefalse + \CF_cntgroup0 + \ifboolKV[chemfig]{autoreset cntcycle} + {\global\CF_cntcycle0 } + {}% + \let\CF_lastaction\CF_zero% + \let\CF_startoffset\empty + \let\CF_endoffset\empty + \let\CF_bondoutcontentsaved\empty + \def\CF_cycleanglecorrection{180/\CF_cyclenum}% + \def\CF_defaultangle{0}% + \def\CF_defaultstringangle{:0}% + \def\CF_defaultlength{1}% + \let\CF_defaultfromatom\empty% + \let\CF_defaulttoatom\empty% + \let\CF_defaulttikz\empty + \let\CF_previousbondangle\empty + \let\CF_joinbond\CF_zero + \let\CF_previoustikz\empty + \everyeof{\_nil}\endlinechar-1 + \CF_sanitizecatcode + \expandafter\CF_assigntonil\expandafter\CF_molecule\scantokens{#4}% + \CF_expsecond{\CF_substall\CF_molecule}\CFhash\CFhash + \CF_expsecond\CF_chemfigc{\CF_molecule}% + % + #2% + \CF_atendofchemfig + \endgroup + \let\CF_flipstate\CF_zero +} + +\def\CF_chemfigc#1{% + \ifnum\CF_lastaction=3 + \ifCF_incycle + \def\CF_defaultangle{0}% + \else + \ifnum\CF_cntcyclebonds=0 % + \pgfmathsetmacro\CF_defaultangle{\CF_previousangle+180+\CF_cycleanglecorrection}% + \else + \pgfmathsetmacro\CF_defaultangle{\CF_previousangle-90+180/\CF_cyclenum}% + \fi + \fi + \let\CF_defaultstringangle\empty + \fi + \let\CF_currentangle\CF_defaultangle + \def\CF_molecule{#1}% + \CF_expsecond\CF_seeksubmol\CF_molecule\CF_molecule% + \if[\CF_threeea\noexpand\expandafter\CF_firsttonil\CF_molecule\_nil + \expandafter\CF_analyseoptarg\CF_molecule\_nil\CF_molecule + \CF_expsecond\CF_setbondangle{\CF_currentstringangle}\CF_currentangle + \let\CF_defaultangle\CF_currentangle + \let\CF_previousangle\CF_currentangle + \CF_doifnotempty\CF_currentstringangle{\let\CF_defaultangle\CF_currentangle}% + \CF_doifnotempty\CF_currentlength {\let\CF_defaultlength\CF_currentlength}% + \CF_doifnotempty\CF_currentfromatom {\let\CF_defaultfromatom\CF_currentfromatom}% + \CF_doifnotempty\CF_currenttoatom {\let\CF_defaulttoatom\CF_currenttoatom}% + \CF_doifnotempty\CF_currenttikz {\let\CF_defaulttikz\CF_currenttikz}% + \CF_expsecond\CF_seeksubmol\CF_molecule\CF_molecule + \fi + \edef\CF_defaultstringangle{:\CF_defaultangle}% + \let\CF_currentlength\CF_defaultlength + \let\CF_currentfromatom\CF_defaultfromatom + \let\CF_currenttoatom\CF_defaulttoatom + \let\CF_currenttikz\CF_defaulttikz + \ifCF_incycle% + \let\CF_currentangle\CF_previousangle + \pgfmathsetmacro\CF_cyclearcinitangle{\CF_currentangle+\CF_initcycleangle+180/\CF_cyclenum+90}% + \pgfmathsetmacro\CF_centeroffset{\CF_currentlength*\CF_atomsep/(2*sin(180/\CF_cyclenum))}% + \node[at=(\CF_bondoutnode),shift=(\CF_cyclearcinitangle:\CF_centeroffset pt),anchor=center](cyclecenter\number\CF_cntcycle){};% + \ifboolKV[chemfig]{show cntcycle} + {\node[at=(cyclecenter\number\CF_cntcycle),anchor=center,overlay]{\tiny\number\CF_cntcycle};} + {}% + \ifCF_cyclearc% + \pgfmathsetmacro\CF_cyclearcradius{\CF_cycleradiuscoeff*\CF_currentlength*\CF_atomsep/(2*tan(180/\CF_cyclenum))}% + \node[at=(cyclecenter\number\CF_cntcycle),shift=(\CF_cyclearcstartangle:\CF_cyclearcradius pt)](initarc){};% + \CF_expafter{\draw[}\CF_cyclearcdirecttikz](initarc) arc (\CF_cyclearcstartangle:\CF_cyclearcendangle:\CF_cyclearcradius pt);% + \fi + \else + \let\CF_currentangle\CF_defaultangle + \fi + \ifnum\CF_lastaction=0 + \let\CF_previousangle\CF_defaultangle + \node(CF_node){}; + \CF_expsecond\CF_iffirsttokin{\CF_molecule}{-=(*~?<>}% + {\CF_insertemptygroup\CF_molecule}% + {}% + \fi + \CF_chemfigd +} + +\def\CF_chemfigd{% + \let\CF_nextaction\CF_chemfigd% + \CF_ifx\CF_molecule\empty + {\let\CF_nextaction\endgroup + } + {\CF_expsecond\CF_seeknode{\CF_molecule}\CF_currentatomgroup\CF_molecule + \CF_ifx\empty\CF_currentatomgroup% + {\def\CF_bondoutnode{% + n\CF_lastgroupnumber-% + \ifx\CF_currentfromatom\empty + \ifdim\CF_currentangle pt<90pt + \number\CF_cntatomgroup + \else + \ifdim\CF_currentangle pt>270pt + \number\CF_cntatomgroup + \else + 1% + \fi + \fi + \else + \CF_currentfromatom + \fi}% + \CF_expafter{\futurelet\CF_toksa\CF_gobtonil}{\CF_molecule\relax\_nil}% + \CF_iffirsttokina{-=<>~}% + {\ifnum\CF_lastaction=2 % + \CF_insertemptygroup\CF_molecule% + \edef\CF_bondoutnode{\CF_bondoutnode}% + \else + \ifCF_incycle + \advance\CF_cntcyclebonds1 + \fi + \CF_expsecond\CF_analysebond{\CF_molecule}\CF_bondtype + \edef\CF_bondoutnode{\CF_bondoutnode}% + \let\CF_molecule\CF_remainafterbond + \ifCF_incycle + \ifnum\CF_cntcyclebonds=\CF_cyclenum\relax + \CF_threeea\CF_execfirst + \else + \ifnum\CF_cntcyclebonds=1 + \let\CF_cyclefirsttikz\CF_currenttikz + \CF_doifnotempty\CF_startoffset{\let\CF_cyclejoinlast\CF_zero}% + \fi + \CF_threeea\CF_execsecond + \fi + \else + \expandafter\CF_execsecond + \fi + {\let\CF_nextaction\endgroup + \CF_drawbond\CF_bondtype{\CF_bondoutnode}{\CF_hookcycle}\CF_previousatomgroup\CF_hookatomgroup + }% + {\node[at=(\CF_bondoutnode\ifCF_incycle\else\ifCF_macrofixedbondlength.\CF_currentangle\fi\fi),shift=(\ifcase\CF_flipstate\or180-\or-\fi\CF_currentangle:\CF_currentlength*\CF_atomsep)](CF_node){}; + \let\CF_previousangle\CF_currentangle + \def\CF_lastaction{2}% + }% + \fi + \ifcat\relax\detokenize\expandafter{\romannumeral-`\.\expandafter\noexpand\CF_molecule}\relax + % + \CF_insertemptygroup\CF_molecule + \fi + }% + {\edef\CF_bondoutnode{\CF_bondoutnode}% + \CF_ifx(\CF_toksa% + {\ifnum\CF_lastaction=2 % + \CF_insertemptygroup\CF_molecule + \else + \CF_expsecond\CF_grabsubmol{\CF_molecule}% + \begingroup + \ifCF_incycle\def\CF_lastaction{3}\fi% + \CF_incyclefalse + \aftergroup\CF_chemfigd + \def\CF_nextaction{\CF_expsecond\CF_chemfigc{\CF_molinparen}}% + \fi + }% + {\CF_ifx\CF_molecule\empty + {\let\CF_nextaction\endgroup + } + {% + \CF_ifx*\CF_toksa% + {\ifnum\CF_lastaction=2 + \CF_insertemptygroup\CF_molecule% + \else + \ifCF_incycle + \def\CF_lastaction{3}% + \fi% + \ifnum\CF_lastaction=3 + \let\CF_lastcyclenum\CF_cyclenum + \fi + \CF_eexpsecond\CF_iffirsttokmatch{\expandafter\CF_gobarg\CF_molecule}*% + {\CF_eexpsecond{\def\CF_molecule}{\expandafter\CF_gobarg\CF_molecule}% + \CF_eexpsecond\CF_iffirsttokmatch{\expandafter\CF_gobarg\CF_molecule}[% + {\expandafter\CF_cycleparsepreamblewithoptarg\CF_molecule\_nil% + }% + {\def\CF_cyclearcstartangle{0}\def\CF_cyclearcendangle{360}% + \let\CF_cyclearcdirecttikz\empty + \expandafter\CF_cycleparsepreamble\CF_molecule\_nil% + }% + \CF_cyclearctrue + }% + {\expandafter\CF_cycleparsepreamble\CF_molecule\_nil% + \CF_cyclearcfalse + }% + \CF_cntcyclebonds0 + \edef\CF_hookcycle{\CF_bondoutnode}% + \let\CF_hookatomgroup\CF_previousatomgroup + \CF_ifzerodim\CF_hookatomgroup + {\def\CF_cyclejoinlast{1}}% + {\def\CF_cyclejoinlast{0}}% + \CF_incycletrue + \global\advance\CF_cntcycle1 + \ifnum\CF_lastaction=3 + \pgfmathsetmacro\CF_initcycleangle{360/\CF_lastcyclenum-180}% + \else + \pgfmathsetmacro\CF_initcycleangle{-180/\CF_cyclenum-90+\CF_cycleanglecorrection}% + \fi + \aftergroup\CF_chemfigd + \def\CF_nextaction{\CF_expsecond\CF_chemfigc{\CF_molinparen}}% + \fi + }% + {\CF_error{something went wrong here: \detokenize\expandafter{\CF_molecule}^^JIf you think it's a bug, please, send a Minimal Example to the author}% + }% + }% + }% + }% + }% + {\CF_expthreemacroargs\CF_drawatomgroup\CF_currentangle\CF_currenttoatom\CF_currentatomgroup + }% + }% + \CF_nextaction +} + +\def\CF_cycleparsepreamble*#1#2\_nil{% + \ifnum#1<3 + \CF_error{a cycle must be at least a triangle.^^JThe number following "*" must be 3 or more}% + \fi + \def\CF_molecule{#2}% + \CF_expsecond\CF_grabsubmol{\CF_molecule}% + \begingroup + \def\CF_cyclenum{#1}% +} + +\def\CF_cycleparsepreamblewithoptarg*[#1]#2#3\_nil{% + \CF_cycleparseoptarg#1,\empty,\empty,\empty\_nil + \CF_cycleparsepreamble*#2#3\_nil +} + +\def\CF_cycleparseoptarg#1,#2,#3\_nil{% + \CF_ifempty{#1} + {\def\CF_cyclearcstartangle{0}} + {\def\CF_cyclearcstartangle{#1}}% + \CF_ifempty{#2} + {\def\CF_cyclearcendangle{360}} + {\def\CF_cyclearcendangle{#2}}% + \CF_expsecond{\def\CF_cyclearcdirecttikz}{\CF_sanitizelastitem#3,\empty\_nil}% +} + +\def\CF_grabsubmol#1{% + \begingroup + \catcode`(1 \catcode`)2 + \CF_threeea + \endgroup + \expandafter\CF_grabsubmola\scantokens{\relax#1}% +} + +\def\CF_grabsubmola#1\_nil{% + \expandafter\CF_assigntonil\expandafter\CF_molecule\scantokens\CF_threeea{\expandafter\CF_gobarg \CF_gobarg#1}% + \expandafter\CF_assigntonil\expandafter\CF_molinparen\scantokens\CF_threeea{\expandafter\CF_firsttonil\CF_gobarg#1\_nil}% +} + +\def\CF_ifcarisupperletter#1{% + \ifcat\relax\noexpand#1% + \let\CF_next\CF_execsecond% + \else + \ifnum`#1<`A + \let\CF_next\CF_execsecond + \else + \ifnum`#1>`Z + \let\CF_next\CF_execsecond + \else + \let\CF_next\CF_execfirst + \fi + \fi + \fi + \CF_next +} + +% +% +\def\CF_createnormnodes#1#2#3#4{% + \CF_doifnotempty{#3} + {\node[shape=coordinate,at=(#1),xshift=#3*\CF_normx,yshift=#3*\CF_normy](#11){}; + \node[shape=coordinate,at=(#1),xshift=-#3*\CF_normx,yshift=-#3*\CF_normy](#12){}; + }% + \CF_doifnotempty{#4} + {\node[shape=coordinate,at=(#2),xshift=#4*\CF_normx,yshift=#4*\CF_normy](#21){}; + \node[shape=coordinate,at=(#2),xshift=-#4*\CF_normx,yshift=-#4*\CF_normy](#22){}; + }% +} + +\def\CF_distancebetweenpoints#1#2#3#4#5{% + \pgfextractx\CF_dim{\pgfpointanchor{#1}{#2}}\edef\CF_dimax{\the\CF_dim}% + \pgfextracty\CF_dim{\pgfpointanchor{#1}{#2}}\edef\CF_dimay{\the\CF_dim}% + \pgfextractx\CF_dim{\pgfpointanchor{#3}{#4}}\edef\CF_dimbx{\the\CF_dim}% + \pgfextracty\CF_dim{\pgfpointanchor{#3}{#4}}\edef\CF_dimby{\the\CF_dim}% + \pgfmathsetmacro#5{veclen(\CF_dimbx-\CF_dimax,\CF_dimby-\CF_dimay)}% +} + +\def\CF_computenodevect#1#2{% + \CF_distancebetweenpoints{#1}{center}{#2}{center}\CF_vectorlen + \pgfmathsetmacro\CF_normx{(\CF_dimay-\CF_dimby)/\CF_vectorlen}% + \pgfmathsetmacro\CF_normy{(\CF_dimbx-\CF_dimax)/\CF_vectorlen}% +} + +\def\CF_setoffset#1#2{% + \CF_doifempty#1{% + \CF_ifzerodim{#2} + {\def#1{0pt}} + {\edef#1{\CF_bondoffset}}% + }% +} + +\def\CF_drawbond#1#2#3#4#5{% + \CF_setoffset\CF_startoffset#4% + \CF_setoffset\CF_endoffset#5% + \let\CF_currentbondstyle\CF_bondstyle + \CF_doifnotempty\CF_currenttikz{\CF_eaddtomacro\CF_currentbondstyle{\expandafter,\CF_currenttikz}}% + \path(#2)--(#3)coordinate[pos=0](#2@)coordinate[pos=1](#3@);% + \CF_computenodevect{#2@}{#3@}% + \pgfmathsetmacro\CF_startcoeff{\CF_startoffset/\CF_vectorlen}% + \pgfmathsetmacro\CF_endcoeff{1-\CF_endoffset/\CF_vectorlen}% + \path(#2@)--(#3@)coordinate[pos=\CF_startcoeff](#2@@)coordinate[pos=\CF_endcoeff](#3@@);% + \CF_doifnotempty\CF_movebondname% + {\path(#2@@)--(#3@@)coordinate[overlay,pos=\CF_movebondcoeff](\CF_movebondname); + \let\CF_movebondname\empty + }% + \ifcase#1\relax + \CF_error{unknown bond type, this error should not occur^^JIf you think it's a bug, send a Minimal Example to the author}% + \or% + \CF_drawaxisbond{#2}{#3}% + \or% + \ifCF_incycle + \ifnum\CF_doublebondtype=0 + \def\CF_doublebondtype{1}% + \fi + \ifnum\CF_flipstate>0 + \def\CF_doublebondtype{2}% + \fi + \pgfmathsetmacro\CF_doublebondlengthcorrection{\CF_doublesep*tan(180/\CF_cyclenum)}% + \fi + \ifcase\CF_doublebondtype + \CF_createnormnodes{#2@@}{#3@@}{\CF_doublesep/2}{\CF_doublesep/2}% + \CF_drawbonda(#2@@1)--(#3@@1); + \CF_drawbonda(#2@@2)--(#3@@2); + \let\CF_joinbond\CF_zero + \or + \CF_createnormnodes{#2@@}{#3@@}\CF_doublesep\CF_doublesep + \CF_drawaxisbond{#2}{#3}% + \begingroup% + \ifCF_incycle + \ifdim\CF_startoffset=0pt + \CF_edefaddtomacro\CF_currentbondstyle{,shorten <=\CF_doublebondlengthcorrection pt}% + \fi + \ifdim\CF_endoffset=0pt + \CF_edefaddtomacro\CF_currentbondstyle{,shorten >=\CF_doublebondlengthcorrection pt}% + \fi + \fi + \CF_drawbonda(#2@@1)--(#3@@1); + \endgroup + \or + \CF_createnormnodes{#2@@}{#3@@}\CF_doublesep\CF_doublesep + \CF_drawaxisbond{#2}{#3}% + \begingroup% + \ifCF_incycle + \ifdim\CF_startoffset=0pt + \CF_edefaddtomacro\CF_currentbondstyle{,shorten \ifnum\CF_flipstate=0 <=-\else>=\fi\CF_doublebondlengthcorrection pt}% + \fi + \ifdim\CF_endoffset=0pt + \CF_edefaddtomacro\CF_currentbondstyle{,shorten \ifnum\CF_flipstate=0 >=-\else<=\fi\CF_doublebondlengthcorrection pt}% + \fi + \fi + \CF_drawbonda(#2@@2)--(#3@@2); + \endgroup + \fi + \or% + \CF_createnormnodes{#2@@}{#3@@}\CF_doublesep\CF_doublesep + \CF_drawaxisbond{#2}{#3}% + \CF_drawbonda(#2@@1)--(#3@@1); + \CF_drawbonda(#2@@2)--(#3@@2); + \or% + \CF_createnormnodes{#2@@}{#3@@}{\CF_crambasewidth/2}{}% + \CF_expafter{\filldraw[}\CF_currentbondstyle,line join=bevel](#2@@1)--(#2@@2)--(#3@@)--cycle; + \let\CF_joinbond\CF_zero + \or% + \CF_createnormnodes{#3@@}{#2@@}{\CF_crambasewidth/2}{}% + \CF_expafter{\filldraw[}\CF_currentbondstyle,line join=bevel](#3@@1)--(#3@@2)--(#2@@)--cycle; + \let\CF_joinbond\CF_zero + \or% + \scope + \CF_createnormnodes{#2@@}{#3@@}{\CF_crambasewidth/2}{}% + \CF_clipcramornot(#2@@1)--(#2@@2)--(#3@@)--(#2@@1); + \CF_expafter{\draw[}\CF_currentbondstyle,dash pattern=on \CF_cramdashlength off \CF_cramdashsep,line width=\CF_crambasewidth](#2@@)--(#3@@); + \endscope + \let\CF_joinbond\CF_zero + \or% + \scope + \CF_createnormnodes{#3@@}{#2@@}{\CF_crambasewidth/2}{}% + \CF_clipcramornot(#3@@1)--(#3@@2)--(#2@@)--(#3@@1); + \CF_expafter{\draw[}\CF_currentbondstyle,dash pattern=on \CF_cramdashlength off \CF_cramdashsep,line width=\CF_crambasewidth](#3@@)--(#2@@); + \endscope + \let\CF_joinbond\CF_zero + \or% + \CF_createnormnodes{#2@@}{#3@@}{\CF_crambasewidth/2}{}% + \CF_expafter{\draw[}\CF_currentbondstyle,line join=bevel](#2@@1)--(#2@@2)--(#3@@)--cycle; + \let\CF_joinbond\CF_zero + \or% + \CF_createnormnodes{#3@@}{#2@@}{\CF_crambasewidth/2}{}% + \CF_expafter{\draw[}\CF_currentbondstyle,line join=bevel](#3@@1)--(#3@@2)--(#2@@)--cycle; + \let\CF_joinbond\CF_zero + \else + \CF_error{unknown bond type, this error should not occur^^JIf you think it's a bug, send a Minimal Example to the author}% + \fi + \let\CF_startoffset\empty + \let\CF_endoffset\empty + \let\CF_previoustikz\CF_currenttikz + \let\CF_previousbondangle\CF_previousangle + \def\CF_previousbond{#1}% +} + +\def\CF_drawaxisbondnojoin#1#2{\CF_drawbonda(#1@@)--(#2@@);} + +\def\CF_drawaxisbondjoin#1#2{% + \ifCF_incycle\ifnum\CF_cntcyclebonds=\CF_cyclenum\relax + \let\CF_nexttikz\CF_cyclefirsttikz + \fi\fi + \ifnum\CF_joinbond=0 + \ifCF_incycle + \ifnum\CF_cntcyclebonds=\CF_cyclenum\relax + \ifnum\CF_cyclejoinlast=1 + \CF_drawbonda(#1@@)--(#2@@)--% + ([shift=(\CF_previousbondangle+2*\CF_cycleincrementangle:.5\pgflinewidth)]#2@@); + \else + \CF_drawbonda(#1@@)--(#2@@); + \fi + \else + \CF_drawbonda(#1@@)--(#2@@); + \fi + \else + \CF_drawbonda(#1@@)--(#2@@); + \fi + \def\CF_joinbond{1}% + \else + \CF_ifx\CF_previoustikz\CF_currenttikz + {\def\CF_joinbond{1}% + \CF_ifzerodim\CF_previousatomgroup + {\CF_ifx\CF_previousbondangle\empty% + {\CF_drawbonda(#1@@)--(#2@@); + } + {\ifdim\CF_startoffset=0pt + \ifCF_incycle + \ifnum\CF_cntcyclebonds=\CF_cyclenum\relax + \ifnum\CF_cyclejoinlast=1 + \CF_ifx\CF_cyclefirsttikz\CF_currenttikz + {\CF_drawbonda([shift=(\CF_previousbondangle:-.5\pgflinewidth)]#1@@)--(#1@@)--(#2@@)--% + ([shift=(\CF_previousbondangle+2*\CF_cycleincrementangle:.5\pgflinewidth)]#2@@); + } + {\CF_drawbonda([shift=(\CF_previousbondangle:-.5\pgflinewidth)]#1@@)--(#1@@)--(#2@@); + }% + \else + \CF_drawbonda([shift=(\CF_previousbondangle:-.5\pgflinewidth)]#1@@)--(#1@@)--(#2@@); + \fi + \else + \CF_drawbonda([shift=(\CF_previousbondangle:-.5\pgflinewidth)]#1@@)--(#1@@)--(#2@@); + \fi + \else + \CF_drawbonda([shift=(\CF_previousbondangle:-.5\pgflinewidth)]#1@@)--(#1@@)--(#2@@); + \fi + \else + \CF_drawbonda(#1@@)--(#2@@); + \fi + }% + } + {\CF_drawbonda(#1@@)--(#2@@);}% + } + {\ifCF_incycle + \ifnum\CF_cntcyclebonds=\CF_cyclenum\relax + \ifnum\CF_cyclejoinlast=1 + \CF_ifx\CF_nexttikz\CF_currenttikz + {\CF_drawbonda(#1@@)--(#2@@)--([shift=(\CF_previousbondangle+2*\CF_cycleincrementangle:.5\pgflinewidth)]#2@@);}% + {\CF_drawbonda(#1@@)--(#2@@);}% + \else + \CF_drawbonda(#1@@)--(#2@@); + \fi + \else + \CF_drawbonda(#1@@)--(#2@@); + \fi + \else + \CF_drawbonda(#1@@)--(#2@@); + \fi + }% + \fi + \ifdim\CF_endoffset=0pt \else + \let\CF_joinbond\CF_zero + \fi +} + +\def\CF_drawbonda{\CF_expafter{\draw[}\CF_currentbondstyle]} + +\def\CF_hookdrawall{% + \CF_doifnotempty\CF_hookdrawlist + {\expandafter\CF_hookdrawfirst\CF_hookdrawlist\_nil% + \CF_hookdrawall + }% +} + +\def\CF_hookdrawfirst[#1,#2,#3]#4#5#6#7#8\_nil{% + \def\CF_hookdrawlist{#8}% + \begingroup + \let\CF_joinbond\CF_zero + \def\CF_currenttikz{#3}% + \def\CF_hookstartcontent{#6}\def\CF_hookendcontent{#7}% + \CF_ifinteger{#2}% + {\CF_drawbond{#2}{#4}{#5}\CF_hookstartcontent\CF_hookendcontent + }% + {\CF_assignbondcode{#2}\CF_bondcurrentnum + \CF_drawbond\CF_bondcurrentnum{#4}{#5}\CF_hookstartcontent\CF_hookendcontent + }% + \endgroup +} + +\def\CF_extractatom#1-#2\_nil{#2}% + +\def\CF_gobblemovearg @#1#2\_nil#3{% + \expandafter\def\csname atom_\number\CF_cntatom\endcsname{#2}% + \CF_ifinstr{#1},% + {\CF_analysemovearg#1\_nil#3\let\CF_movebondcoeff\empty}% + {\def#3{#1}}% + \CF_doifempty{#2}{\let\CF_nodestrut\empty}% +}% + +\def\hflipnext{\def\CF_flipstate{1}} + +\def\vflipnext{\def\CF_flipstate{2}} +\let\CF_flipstate\CF_zero + +\def\CF_drawatomgroup#1#2#3{% + \expandafter\let\expandafter\CF_bondoutcontent% + \csname + \ifdefined\CF_bondoutnode + atom_\expandafter\CF_extractatom\CF_bondoutnode\_nil + \else + empty% + \fi + \endcsname + \global\advance\CF_cntgroup1 + \let\CF_currentatom\empty + \global\let\CF_hookdrawlist\empty + \CF_cntatomgroup0 % + \CF_iffirsttokmatch{#3}? + {\CF_drawatomgroupa{{}#3}} + {\CF_drawatomgroupa{#3}}% + \def\CF_currentatomgroup{#3}% + \CF_removemovearg\CF_currentatomgroup% + \CF_ifinstr{#3}?% + {\CF_removehook\CF_currentatomgroup + \ifcat\relax\detokenize\expandafter{\romannumeral-`\.\expandafter\noexpand\CF_currentatomgroup}\relax + \let\CF_currentatomgroup\empty + \fi + }% + {}% + \CF_doifnotempty{#2} + {\ifnum#2<1 + \CF_warning{no atom found at position #2, pershaps you mispelled the optional argument of the bond.}% + \else + \ifnum#2>\CF_cntatomgroup + \CF_error{no atom found at position #2, pershaps you mispelled the optional argument of the bond.}% + \fi + \fi + }% + \edef\CF_hookatomnumber{% + \CF_ifempty{#2} + {\ifdim#1pt>90pt + \ifdim#1pt<270pt + \number\CF_cntatomgroup + \else + 1% + \fi + \else + 1% + \fi + } + {#2% + }% + }% + \CF_cntatom\CF_hookatomnumber + \CF_ifzerodim\CF_currentatomgroup + {\let\CF_nodestrut\empty + } + {\CF_ifx\empty\CF_bondoutcontentsaved + {\def\CF_nodestrut{\vphantom\CF_bondoutcontent}}% + {\def\CF_nodestrut{\vphantom\CF_bondoutcontentsaved}}% + }% + \edef\CF_optstring{anchor=\ifnum\CF_lastaction=0 base\else\ifCF_incycle center\else\ifCF_macrofixedbondlength 180+#1\else center\fi\fi\fi,at=(CF_node),\CF_nodestyle}% + \loop + \unless\ifnum\CF_cntatom>\CF_cntatomgroup + \CF_eexpafter + {\futurelet\CF_toksa} + {\expandafter\expandafter\expandafter\CF_gobtonil\csname atom_\number\CF_cntatom\endcsname\_nil}% + \CF_ifx @\CF_toksa% + {\CF_threeea\CF_gobblemovearg\csname atom_\number\CF_cntatom\endcsname\_nil\CF_moveatomname + \CF_expafter{\node[}\CF_optstring,overlay](\CF_moveatomname){\phantom{\CF_nodecontent}};% + \let\CF_moveatomname\empty + } + {}% + \ifboolKV[chemfig]{debug} + {\CF_expafter{\node[}\CF_optstring,draw=gray](n\number\CF_cntgroup-\number\CF_cntatom){\CF_nodecontent};% + \CF_show_debug_atom + } + {\CF_expafter{\node[}\CF_optstring](n\number\CF_cntgroup-\number\CF_cntatom){\CF_nodecontent};% + }% + \let\CF_nodestrut\empty + \advance\CF_cntatom1 + \edef\CF_optstring{anchor=base \ifnum\CF_flipstate=1 east\else west\fi,at=(n\number\CF_cntgroup-\number\numexpr\CF_cntatom-1.base \ifnum\CF_flipstate=1 west\else east\fi),\CF_nodestyle}% + \repeat + \CF_cntatom\CF_hookatomnumber + \ifnum\CF_lastaction=2 % + \gdef\CF_cycleanglecorrection{0}% + \CF_drawbond\CF_bondtype{\CF_bondoutnode}{n\number\CF_cntgroup-\number\CF_cntatom}\CF_previousatomgroup\CF_currentatomgroup + \fi + \def\CF_lastaction{1}% + \loop + \ifnum\CF_cntatom>1 + \advance\CF_cntatom-1 + \edef\CF_optstring{anchor=base \ifnum\CF_flipstate=1 west\else east\fi,at=(n\number\CF_cntgroup-\number\numexpr\CF_cntatom+1.base \ifnum\CF_flipstate=1 east\else west\fi),\CF_nodestyle}% + \CF_eexpafter + {\futurelet\CF_toksa} + {\expandafter\expandafter\expandafter\CF_gobtonil\csname atom_\number\CF_cntatom\endcsname\_nil}% + \CF_ifx @\CF_toksa% + {\CF_threeea\CF_gobblemovearg\csname atom_\number\CF_cntatom\endcsname\_nil\CF_moveatomname + \CF_expafter{\node[}\CF_optstring,overlay](\CF_moveatomname){\phantom{\CF_nodecontent}};% + \let\CF_moveatomname\empty + } + {}% + \ifboolKV[chemfig]{debug} + {\CF_expafter{\node[}\CF_optstring,draw=gray](n\number\CF_cntgroup-\number\CF_cntatom){\CF_nodecontent};% + \CF_show_debug_atom + } + {\CF_expafter{\node[}\CF_optstring](n\number\CF_cntgroup-\number\CF_cntatom){\CF_nodecontent};% + }% + \repeat + \ifboolKV[chemfig]{debug} + \CF_show_debug_atomgroup + {}% + \CF_hookdrawall + \edef\CF_lastgroupnumber{\number\CF_cntgroup}% + \let\CF_previousatomgroup\CF_currentatomgroup +} + +\def\CF_show_debug_atom{% + \node[at=(n\number\CF_cntgroup-\number\CF_cntatom.south),anchor=north,outer sep=1pt,overlay]{$\scriptscriptstyle\color{gray}\number\CF_cntatom$};% +} + +\def\CF_show_debug_atomgroup{% + \draw[red,overlay] ([xshift=-.5pt,yshift=.5pt]n\number\CF_cntgroup-1.north west) rectangle ([xshift=.5pt,yshift=-.5pt]n\number\CF_cntgroup-\number\CF_cntatomgroup.south east);% + \path (n\number\CF_cntgroup-1.north west) -- (n\number\CF_cntgroup-\number\CF_cntatomgroup.north east) + node [midway,yshift=1pt,overlay] {$\scriptscriptstyle\color{red}\number\CF_cntgroup$}; +} + +\def\CF_keepmovearg @#1#2\_nil{\def\CF_currentatom{@{#1}}} + +\def\CF_drawatomgroupa#1{% + \CF_ifempty{#1} + {\expandafter\let\csname atom_\number\CF_cntatomgroup\endcsname\CF_currentatom + } + {\advance\CF_cntatomgroup1 + \futurelet\CF_toksa\CF_gobtonil#1\_nil + \CF_ifx @\CF_toksa + {\CF_keepmovearg#1\_nil + \CF_removemovearga#1\_nil\CF_aftermovearg + \CF_expsecond\CF_drawatomgroupb{\CF_aftermovearg}% + }% + {\let\CF_currentatom\empty + \CF_drawatomgroupb{#1}% + }% + }% +} + +\def\CF_drawatomgroupb#1{% + \CF_ifempty{#1} + {\expandafter\let\csname atom_\number\CF_cntatomgroup\endcsname\CF_currentatom + } + {\futurelet\CF_toksa\CF_gobtonil#1\_nil + \CF_ifx\bgroup\CF_toksa + {\CF_eaddtomacro\CF_currentatom{\expandafter{\CF_firsttonil#1\_nil}}% + \CF_expsecond\CF_drawatomgroupba{\CF_gobarg#1}% + }% + {\CF_ifx\CF_sptoken\CF_toksa + {\CF_addtomacro\CF_currentatom{ }% + \CF_expsecond\CF_drawatomgroupba{\CF_afterspace#1\_nil}% + }% + {\CF_eaddtomacro\CF_currentatom{\CF_firsttonil#1\_nil}% + \CF_expsecond\CF_drawatomgroupba{\CF_gobarg#1}% + }% + }% + }% +} + +% +\def\CF_removemovearg#1{% + \CF_expsecond\CF_ifinstr{#1}@% + {\expandafter\CF_removemovearga#1\_nil#1% + \CF_removemovearg#1% + }% + {}% +} + +% +\def\CF_removemovearga#1\_nil#2{% + \def\CF_removemoveargb##1@{% + \CF_expsecond{\def#2}{\CF_gobarg##1}% + \CF_removemoveargc\relax + }% + \def\CF_removemoveargc##1\_nil{\CF_eaddtomacro#2{\CF_gobtwoargs##1}}% + \CF_removemoveargb\relax#1\_nil +} + +\def\CF_drawatomgroupba#1{% + \CF_ifempty{#1} + {\expandafter\let\csname atom_\number\CF_cntatomgroup\endcsname\CF_currentatom + \let\CF_currentatom\empty + } + {\futurelet\CF_toksa\CF_gobtonil#1\_nil + \CF_ifx @\CF_toksa + {\expandafter\let\csname atom_\number\CF_cntatomgroup\endcsname\CF_currentatom + \let\CF_currentatom\empty + \CF_drawatomgroupa{#1}% + }% + {\CF_ifx|\CF_toksa + {\expandafter\let\csname atom_\number\CF_cntatomgroup\endcsname\CF_currentatom + \let\CF_currentatom\empty + \CF_expsecond\CF_drawatomgroupa{\CF_gobarg#1}% + }% + {\CF_ifx\CF_sptoken\CF_toksa + {\CF_addtomacro\CF_currentatom{ }% + \CF_expsecond\CF_drawatomgroupba{\CF_afterspace#1\_nil}% + }% + {\CF_ifx\bgroup\CF_toksa + {\CF_eaddtomacro\CF_currentatom{\expandafter{\CF_firsttonil#1\_nil}}% + \CF_expsecond\CF_drawatomgroupba{\CF_gobarg#1}% + }% + {\CF_expsecond\CF_ifcarisupperletter{\CF_firsttonil#1\_nil}% + {\expandafter\let\csname atom_\number\CF_cntatomgroup\endcsname\CF_currentatom + \let\CF_currentatom\empty + \CF_drawatomgroupa{#1}% + }% + {\CF_ifx?\CF_toksa + {\CF_expsecond\CF_iffirsttokmatch{\CF_gobarg#1}[% + {\expandafter\CF_graboptarg\CF_gobarg#1\_nil\CF_afterhook}% + {\CF_expafter{\CF_graboptarg[]}{\CF_gobarg#1}\_nil\CF_afterhook}% + \CF_exptwomacroargs\CF_ifinstr{\CF_hooklist}{\expandafter(\CF_hookcurrentname)}% + {\CF_expsecond\CF_hookparselist{\CF_hookcurrentname}% + \CF_edefaddtomacro\CF_hookdrawlist{% + [\CF_hookcurrentname,\CF_hookcurrentlink,\CF_hookcurrenttikz]{\CF_hooksavedcoord}{n\number\CF_cntgroup-\number\CF_cntatomgroup}}% + \CF_eaddtomacro\CF_hookdrawlist{\expandafter{\CF_hooksavedcontent}}% + \CF_eaddtomacro\CF_hookdrawlist{\expandafter{\CF_currentatom}}% + \global\let\CF_hookdrawlist\CF_hookdrawlist + }% + {\CF_edefaddtomacro\CF_hooklist{(\CF_hookcurrentname)|n\number\CF_cntgroup-\number\CF_cntatomgroup|}% + \CF_eaddtomacro\CF_hooklist{\CF_currentatom|}% + \global\let\CF_hooklist\CF_hooklist + }% + \CF_expsecond\CF_drawatomgroupba{\CF_afterhook}% + }% + {\CF_eaddtomacro\CF_currentatom{\CF_firsttonil#1\_nil}% + \CF_expsecond\CF_drawatomgroupba{\CF_gobarg#1}% + }% + }% + }% + }% + }% + }% + }% +} + +\def\CF_kookdefaultname{a} +\def\CF_hookdefaultlink{-} +\def\CF_hookdefaulttikz{} + +\def\CF_hookparseoptarg#1,#2,#3\_nil{% + \CF_testemptyandassign\CF_hookcurrentname{#1}\CF_kookdefaultname + \CF_testemptyandassign\CF_hookcurrentlink{#2}\CF_hookdefaultlink + \CF_testemptyandassign\CF_hookcurrenttikz{#3}\CF_hookdefaulttikz +} + +\def\CF_graboptarg[#1]#2\_nil#3{% + \CF_hookparseoptarg#1,,\_nil + \def#3{#2}% +} + +\def\CF_hookparselist#1{% + \def\CF_hookparselista##1(#1)|##2|##3|##4\_nil{\def\CF_hooksavedcoord{##2}\def\CF_hooksavedcontent{##3}}% + \expandafter\CF_hookparselista\CF_hooklist\_nil +} + +\def\CF_removehook#1{% + \CF_expsecond\CF_ifinstr{#1}?% + {\CF_expafter{\CF_removehooka\relax}#1\_nil#1% + \CF_removehook#1% + } + {}% +} + +\def\CF_removehooka#1?#2\_nil#3{% + \CF_iffirsttokmatch{#2}[% + {\CF_removehookb#1?#2\_nil#3} + {\CF_expsecond{\def#3}{\CF_gobarg#1#2}}% +} + +\def\CF_removehookb#1?[#2]#3\_nil#4{\CF_expsecond{\def#4}{\CF_gobarg#1#3}} + +\defKV[charge]{% + .radius = \CF_defifempty\CF_dotradius {#1}{0.15ex}, + :sep = \CF_defifempty\CF_dotsep {#1}{0.3em}, + .style = \CF_defifempty\CF_dotstyle {#1}{fill=black}, + "length = \CF_defifempty\CF_rectlength{#1}{1.5ex}, + "width = \CF_defifempty\CF_rectwidth {#1}{.3ex} +} +\def\setcharge#{\setKV[charge]} +\def\resetcharge{\restoreKV[charge]} +\setKVdefault[charge]{% + debug = false,% + macro atom = \printatom,% + circle = false,% + macro charge = ,% + extra sep = 1.5pt,% + overlay = true,% + shortcuts = true,% + lewisautorot = true,% + .radius = 0.15ex,% + :sep = 0.3em,% + .style = {fill=black},% + "length = 1.5ex,% + "width = .3ex,% + "style = {black,line width=0.4pt},% + |style = {black,line width=0.4pt},% +}% +\def\chargedot{\CF_testopt\chargedot_a{}} +\def\chargedot_a[#1]{% + \begingroup + \setKV[charge]{#1}% + \CF_expafter{\tikz\draw[}{\CF_dotstyle}](0,0)circle(\CF_dotradius);% + \endgroup +} +\def\chargeddot{\CF_testopt\chargeddot_a{}} +\def\chargeddot_a[#1]{% + \begingroup + \setKV[charge]{#1}% + \ifboolKV[charge]{lewisautorot} + {\pgfmathsetmacro\CF_lewisrot{90+\chargeangle}} + {\def\CF_lewisrot{0}}% + \pgfmathsetmacro\CF_halfsep{\CF_dotsep/2}% + \tikzpicture[anchor=center,rotate=\CF_lewisrot]% + \CF_expafter{\draw[}{\CF_dotstyle}]% + (-\CF_halfsep pt,0)circle(\CF_dotradius)% + (\CF_halfsep pt,0)circle(\CF_dotradius);% + \endtikzpicture + \endgroup +} +\def\chargerect{\CF_testopt\chargerect_a{}} +\def\chargerect_a[#1]{% + \begingroup + \setKV[charge]{#1}% + \ifboolKV[charge]{lewisautorot} + {\pgfmathsetmacro\CF_lewisrot{90+\chargeangle}} + {\def\CF_lewisrot{0}}% + \pgfmathsetmacro\CF_halfwidth{\CF_rectwidth/2}% + \pgfmathsetmacro\CF_halflength{\CF_rectlength/2}% + \tikzpicture[anchor=center,rotate=\CF_lewisrot]% + \CF_eexpafter{\draw[}{\useKV[charge]{"style}}](-\CF_halflength pt,-\CF_halfwidth pt)rectangle(\CF_halflength pt,\CF_halfwidth pt);% + \endtikzpicture + \endgroup +} +\def\chargeline{\CF_testopt\chargeline_a{}} +\def\chargeline_a[#1]{% + \begingroup + \setKV[charge]{#1}% + \ifboolKV[charge]{lewisautorot} + {\pgfmathsetmacro\CF_lewisrot{90+\chargeangle}} + {\def\CF_lewisrot{0}}% + \pgfmathsetmacro\CF_halflength{\CF_rectlength/2}% + \tikzpicture[anchor=center,rotate=\CF_lewisrot]% + \CF_eexpafter{\draw[}{\useKV[charge]{|style}}](-\CF_halflength pt,0)--(\CF_halflength pt,0);% + \endtikzpicture + \endgroup +} +\def\CF_enableshortcuts{% + \let\CF_saveddot \.\let\.\chargedot + \let\CF_savedddot\:\let\:\chargeddot + \let\CF_savedrect\"\let\"\chargerect + \let\CF_savedline\|\let\|\chargeline + \let\enableshortcuts\relax + \let\disableshortcuts\CF_disableshortcuts +} +\def\CF_disableshortcuts{% + \let\.\CF_saveddot + \let\:\CF_savedddot + \let\"\CF_savedrect + \let\|\CF_savedline + \let\enableshortcuts\CF_enableshortcuts + \let\disableshortcuts\relax +} +\def\charge{% + \begingroup + \catcode`\: 12 + \charge_a{true}% +} +\def\Charge{% + \begingroup + \catcode`\: 12 + \charge_a{false}% +} +\def\charge_a#1#2{% + \CF_testopt{\charge_b{#1}}{}#2\_nil +} +\def\charge_b#1[#2]#3\_nil{% + \charge_c{#1}[#2]{#3}% +} +\def\charge_c#1[#2]#3#4{% + \setcharge{overlay=#1,#2}% + \setbox\CF_chargebox\hbox{\useKV[charge]{macro atom}{#4}}% + \CF_ifinsidetikz + {\pgfinterruptpicture + \let\CF_atendofcharge\endpgfinterruptpicture + } + {\let\CF_atendofcharge\relax + }% + \expanded{\noexpand + \tikzpicture[every node/.style={% + \ifboolKV[charge]{debug}{draw=red,}{}% + anchor=base,% + inner sep=0pt,% + outer sep=0pt,% + minimum size=0pt},% + baseline]}% + \expanded{\noexpand + \node[% + \ifboolKV[charge]{circle}{circle,}{}% + \ifboolKV[charge]{debug}{draw=green,}{}% + anchor=base% + ]}% + (atombox)at(0,0)% + {\copy\CF_chargebox};% + \expanded{\noexpand + \node[% + \ifboolKV[charge]{circle}{circle,}{}% + \ifboolKV[charge]{debug}{draw=blue,}{}% + anchor=base,% + inner sep=\useKV[charge]{extra sep},% + overlay% + ]}% + (atom)at(0,0){% + \vrule width0pt height\ht\CF_chargebox depth\dp\CF_chargebox + \vrule width\wd\CF_chargebox height\CF_zero depth\CF_zero};% + \let\enableshortcuts\relax + \let\disableshortcuts\relax + \ifboolKV[charge]{shortcuts}\CF_enableshortcuts{}% + \charge_d#3,\CF_quark=% + \endtikzpicture + \CF_atendofcharge + \endgroup +} +\def\charge_d#1={% + \CF_ifx\CF_quark{#1}% + {} + {\CF_striplastsp{#1}\charge_e=}% +} +\def\charge_e#1={% + \CF_ifinstr{#1}[ + {\charge_f#1=} + {\charge_f#1[]=}% +} +\def\charge_f#1[#2]={% + \CF_ifinstr{#1}: + {\charge_g#1[#2]=} + {\charge_g#1:0pt[#2]=}% +} +\def\charge_g#1:#2[#3]=#4,{% + \CF_stripsp{#1}\CF_ifinteger + {\pgfmathsetmacro\chargeangle{mod(#1,360)}% + } + {\pgfmathanglebetweenpoints{\pgfpointanchor{atom}{center}}{\CF_stripsp{#1}{\pgfpointanchor{atom}}}% + \let\chargeangle\pgfmathresult% + }% + \edef\CF_offset{\the\dimexpr#2+0pt}% + \CF_stripsp{#1}{\CF_distancebetweenpoints{atom}{center}{atom}}\CF_chargedistance + \CF_eexpafter{\node[anchor=center,}{\ifboolKV[charge]{overlay}{overlay,}{}}#3]% + at([shift=(\chargeangle:\CF_chargedistance pt+\CF_offset)]atom.center){\useKV[charge]{macro charge}{#4}};% + \charge_d +} + +\def\Chembelow{\begingroup\let\CF_temp\CF_gobarg\CF_chembelowa} + +\def\chembelow{\begingroup\let\CF_temp\CF_id\CF_chembelowa} + +\def\CF_chembelowa{\CF_testopt\CF_chembelowb\CF_stacksep} + +\def\CF_chembelowb[#1]#2#3{% + \setbox\CF_box\hbox{\printatom{#2}}% + \expandafter\vtop\CF_temp{to\ht\CF_box}{% + \offinterlineskip + \hbox{\printatom{#2}}% + \kern#1\relax + \hbox to\wd\CF_box{\hss\printatom{#3}\hss}% + \CF_temp\vss + }% + \endgroup +} + +\def\Chemabove{\begingroup\let\CF_temp\CF_gobarg\CF_chemabovea} + +\def\chemabove{\begingroup\let\CF_temp\CF_id\CF_chemabovea} + +\def\CF_chemabovea{\CF_testopt\CF_chemaboveb\CF_stacksep} + +\def\CF_chemaboveb[#1]#2#3{% + \setbox\CF_box\hbox{\printatom{#2}}% + \expandafter\vbox\CF_temp{to\ht\CF_box}{% + \offinterlineskip + \CF_temp\vss + \hbox to\wd\CF_box{\hss\printatom{#3}\hss}% + \kern#1\relax + \hbox{\printatom{#2}}% + }% + \endgroup +} + +\def\chemmove{\CF_testopt\CF_chemmove{}} + +\def\CF_chemmove[#1]#2{% + \CF_doifnotempty{#2}% + {\expandafter\tikzpicture\expanded{[overlay,remember picture,-CF\CF_ifempty{#1}{}{,\unexpanded{#1}}]}% + #2% + \endtikzpicture + }% +} + +\def\chemnameinit#1{% + \setbox\CF_boxstuff\hbox{#1}% + \xdef\CF_dpmax{\the\dp\CF_boxstuff}% +} +\let\CF_dpmax\CF_zero + +\def\CF_parsemolname#1\\#2\_nil{% + \hbox to\CF_wdstuffbox{\hss#1\hss}% + \CF_doifnotempty{#2}{\CF_parsemolname#2\_nil}% +} + +\def\chemname{% + \CF_ifstar + {\CF_adjustnamedpfalse\CF_chemnamea} + {\CF_adjustnamedptrue \CF_chemnamea}% +} + +\def\CF_chemnamea{\CF_testopt\CF_chemnameb{1.5ex}} + +\def\CF_chemnameb[#1]#2#3{% + \setbox\CF_boxstuff\hbox{#2}% + \edef\CF_wdstuffbox{\the\wd\CF_boxstuff}\edef\CF_dpstuffbox{\the\dp\CF_boxstuff}% + \leavevmode + \ifdim\CF_dpmax<\CF_dpstuffbox\global\let\CF_dpmax\CF_dpstuffbox\fi + \vtop{% + \box\CF_boxstuff + \nointerlineskip + \kern\dimexpr#1\ifCF_adjustnamedp+\CF_dpmax-\CF_dpstuffbox\fi\relax + \CF_parsemolname#3\\\_nil + }% +} + +% +% +% +\let\CF_schemenest\CF_zero + +\def\CF_subscheme{\CF_testopt\CF_subschemea{}} +\def\CF_subschemea[#1]{\CF_testopt{\CF_subschemeb[#1]}{text}} +\def\CF_subschemeb[#1][#2]#3{\schemestart[#1][#2]#3\schemestop} + +\def\chemleft#1#2\chemright#3{% + \leavevmode + \begingroup + \setbox0\hbox{$\vcenter{\hbox{}}$}\edef\CF_delimmathht{\the\ht0}% + \setbox0\hbox{#2}\edef\CF_delimdim{\the\dimexpr(\ht0+\dp0)/2}% + \edef\CF_delimshift{\the\dimexpr(\ht0-\dp0)/2-\CF_delimmathht}% + \raise\CF_delimshift\hbox{$\left#1\vrule height\CF_delimdim depth\CF_delimdim width0pt\right.$}\box0 + \raise\CF_delimshift\hbox{$\left.\vrule height\CF_delimdim depth\CF_delimdim width0pt\right#3$}% + \endgroup +} + +\def\chemright#1{% + \CF_warning{"\string\chemright\string#1" ignored! No \string\chemleft\space previously found.}% +} + +\def\chemup#1#2\chemdown#3{% + \begingroup + \setbox0\hbox{\printatom{#2}}\edef\CF_delimdim{\the\dimexpr\wd0/2}% + \tikzpicture[every node/.style={inner sep=0pt,outer sep=0pt,minimum size=0pt},baseline]% + \node[anchor=base west](chem@stuff){\box0};% + \node[at=(chem@stuff.north),anchor=east,rotate=-90]{$\left#1\vrule height\CF_delimdim depth\CF_delimdim width0pt\right.$};% + \node[at=(chem@stuff.south),anchor=west,rotate=-90]{$\left.\vrule height\CF_delimdim depth\CF_delimdim width0pt\right#3$};% + \endtikzpicture + \endgroup +} + +\def\chemdown#1{% + \CF_warning{"\string\chemdown\string#1" ignored! No \string\chemup\space previously found.}% +} + +\def\CF_setstyle#1,#2,#3\_nil#4#5#6{% + \def#4{#1}\let#5\empty\let#6\empty + \CF_iffirsttokmatch\CF_quark{#2\relax} + {}% + {\def#5{#2}% + \CF_iffirsttokmatch\CF_quark{#3\relax} + {}% + {\CF_setstylea#3\_nil#6}% + }% +} +\def\CF_setstylea#1,\CF_quark#2\_nil#3{\def#3{#1}} + +\def\CF_and{\futurelet\CF_toksa\CF_anda} + +\def\CF_anda{% + \CF_ifx\CF_toksa\bgroup + {\CF_andb} + {\CF_andb{}}% +} + +\def\CF_andb#1{% + \CF_setstyle#1,\CF_quark,\CF_quark\_nil\CF_signspaceante_\CF_signspacepost_\CF_signvshift_ + \CF_doifnotempty\CF_signspaceante_{\let\CF_signspaceante\CF_signspaceante_}% + \CF_doifnotempty\CF_signspacepost_{\let\CF_signspacepost\CF_signspacepost_}% + \CF_doifnotempty\CF_signvshift_{\let\CF_signvshift\CF_signvshift_}% + \raise\CF_signvshift\hbox{\kern\CF_signspaceante$+$\kern\CF_signspacepost}% +} + +\def\schemestart{% + \begingroup + \xdef\CF_schemenest{\number\numexpr\CF_schemenest+1}% + \CF_testopt\CF_schemestarta{}% +} + +\def\CF_schemestarta[#1]{% + \CF_setstyle#1,\CF_quark,\CF_quark\_nil\CF_arrowangle_\CF_arrowlength_\CF_arrowstyle_ + \CF_doifnotempty\CF_arrowangle_{\let\CF_arrowangle\CF_arrowangle_}% + \CF_doifnotempty\CF_arrowlength_{\let\CF_arrowlength\CF_arrowlength_}% + \CF_eexpsecond{\def\CF_arrowtip}{\expandafter\CF_gobarg\CF_arrowhead}% + \CF_expsecond{\CF_preaddtomacro\CF_defaultarrowstyle}{\CF_arrowhead,}% + \let\CF_arrowstyle\CF_defaultarrowstyle + \CF_doifnotempty\CF_arrowstyle_{\CF_eaddtomacro\CF_arrowstyle{\expandafter,\CF_arrowstyle_}}% + \pgfmathsetmacro\CF_arrowdoublesep{\CF_arrowdoublesep/2}% + \pgfmathsetmacro\CF_arrowdoubleposstart{(1-\CF_arrowdoubleposstart)/2}% + \pgfmathsetmacro\CF_arrowdoubleposend{1-\CF_arrowdoubleposstart}% + \ifboolKV[chemfig]{scheme debug} + {\tikzpicture[every node/.style={draw,anchor=base,inner sep=0pt,outer sep=0pt,minimum size=1.5pt},baseline,remember picture]} + {\tikzpicture[every node/.style={anchor=base,inner sep=0pt,outer sep=0pt,minimum size=0pt},baseline,remember picture]}% + \let\merge\CF_merge + \expandafter\let\csname+\endcsname\CF_and + \let\arrow\CF_arrow + \let\schemestop\CF_schemestop + \let\subscheme\CF_subscheme + \CF_testopt{\CF_schemestartb}{text}% +} + +\def\CF_schemestartb[#1]{% + \ifnum\CF_schemenest=1 % + \CF_cntcompound0 + \fi + \edef\CF_currentnodename{c\number\CF_cntcompound}% + \let\CF_nextnodename\empty + \let\CF_nextnodestyle\empty + \let\CF_directarrowlist\empty + \ifboolKV[chemfig]{scheme debug} + {\node[fill,green](\CF_currentnodename){};} + {\node(\CF_currentnodename){};}% + \def\CF_nextnodeanchor{#1}% + \CF_doifempty\CF_nextnodeanchor{\def\CF_nextnodeanchor{text}}% + \let\CF_compound\empty + \CF_schemestartc +} + +\def\CF_schemestartc{% + \futurelet\CF_toksa\CF_schemestarte +} + +\expandafter\def\expandafter\CF_schemestartd\space{\futurelet\CF_toksa\CF_schemestarte} + +\def\CF_schemestarte{% + \CF_iffirsttokina{\arrow\schemestop\merge}% + {} + {\CF_ifx\CF_toksa\bgroup + {\ifCF_compound_is_chemfig% + \edef\CF_restore_hashcatcode{\catcode\number`\#=\number\catcode`\# \relax}% + \catcode`\#12 % + \fi + \CF_addnextarg + } + {\CF_ifx\CF_toksa\CF_sptoken + {\CF_addtomacro\CF_compound{ }% + \CF_schemestartd + } + {\CF_ifx\CF_toksa\chemfig + \CF_compound_is_chemfigtrue% + {}% + \afterassignment\CF_schemestartc + \CF_addtomacro\CF_compound + }% + }% + }% +} + +\def\CF_addnextarg#1{% + \CF_addtomacro\CF_compound{{#1}}% + \ifCF_compound_is_chemfig% + \CF_restore_hashcatcode + \CF_compound_is_chemfigfalse% + \fi + \CF_schemestartc +} + +\def\CF_displaycompound#1#2{% + \CF_doifnotempty\CF_compound + {\global\advance\CF_cntcompound1 + \CF_ifx\CF_defaultcompoundstyle\empty + {\let\CF_currentnodestyle\empty} + {\CF_expsecond{\def\CF_currentnodestyle}{\CF_defaultcompoundstyle,}}% + \CF_addtomacro\CF_currentnodestyle{anchor=\CF_nextnodeanchor,at=(\CF_currentnodename)}% + \CF_ifempty{#2}% + {\CF_doifnotempty\CF_nextnodestyle + {\CF_eaddtomacro\CF_currentnodestyle{\expandafter,\CF_nextnodestyle}}% + } + {\CF_doifnotempty\CF_nextnodestyle + {\CF_warning{two styles for the same node, first style "\CF_nextnodestyle" ignored}% + }% + \CF_addtomacro\CF_currentnodestyle{,#2}% + }% + \CF_ifempty{#1} + {\edef\CF_temp{% + \CF_ifempty\CF_nextnodename + {c\number\CF_cntcompound} + {\CF_nextnodename}% + }% + } + {\CF_doifnotempty\CF_nextnodename + {\CF_warning{two names for the same node, first name "\CF_nextnodename" ignored}% + }% + \edef\CF_temp{#1}% + }% + \CF_expafter{\node[}\CF_currentnodestyle](\CF_temp){\CF_compound};% + \ifboolKV[chemfig]{scheme debug}% + {\node[draw=none,anchor=270,at=(\CF_temp.90),fill=green!60,overlay,opacity=0.5]{\scriptsize\bfseries\CF_temp};% + } + {}% + \let\CF_currentnodename\CF_temp + }% +} + +\def\CF_schemestop{% + \CF_displaycompound{}{}% + \CF_directarrowlist + \endtikzpicture + \xdef\CF_schemenest{\number\numexpr\CF_schemenest-1}% + \endgroup +} + +\def\CF_analysearrowarg#1{\CF_analysearrowarga#1[]\_nil} + +\def\CF_analysearrowarga#1[#2]#3\_nil{% + \CF_ifinstr{#1}. + {\CF_addtomacro\CF_temp{#1[#2]}} + {\CF_addtomacro\CF_temp{#1.[#2]}}% +} + +\def\CF_arrow{% + \CF_ifnextchar(% + {\CF_arrowa + } + {\CF_ifnextchar\bgroup + {\CF_arrowb(.[]--.[])} + {\CF_arrowb(.[]--.[]){}}% + }% +} + +\def\CF_arrowa(#1--#2){% + \def\CF_temp{(}% + \CF_analysearrowarg{#1}% + \CF_addtomacro\CF_temp{--}% + \CF_analysearrowarg{#2}% + \CF_addtomacro\CF_temp)% + \CF_ifnextchar\bgroup + {\expandafter\CF_arrowb\CF_temp} + {\expandafter\CF_arrowb\CF_temp{}}% +} + +\def\CF_arrowb(#1.#2[#3]--#4.#5[#6])#7{% + \def\CF_currentarrowtype{#7}% + \CF_doifempty\CF_currentarrowtype{\def\CF_currentarrowtype{->}}% + \CF_testopt{\CF_arrowc(#1.#2[#3]--#4.#5[#6])}{}% +} + +\def\CF_arrowc(#1.#2[#3]--#4.#5[#6])[#7]{% + \def\CF_temp{\CF_arrowe(#1.#2[#3]--#4.#5[#6])}% + \CF_arrowd#7,\empty,\empty\_nil +} + +\def\CF_arrowd#1,#2,#3\_nil{% + \CF_addtomacro\CF_temp{{#1}}% + \CF_eaddtomacro\CF_temp{\expandafter{#2}}% + \expandafter\CF_eaddtomacro\expandafter\CF_temp\expandafter{\expandafter\expandafter\expandafter{\expandafter\CF_sanitizelastitem#3,\empty\_nil}}% + \CF_temp +} + +% +% +\def\CF_arrowe(#1.#2[#3]--#4.#5[#6])#7#8#9{% + \let\CF_arrowcurrentstyle\CF_arrowstyle + \if @\expandafter\CF_firsttonil\detokenize{#1.}\_nil% + \if @\expandafter\CF_firsttonil\detokenize{#4.}\_nil + \CF_eaddtomacro\CF_directarrowlist{\expandafter\CF_directarrow\expandafter{\CF_currentarrowtype}{#1}{#2}{#4}{#5}{#9}}% + \let\CF_nextaction\CF_schemestartc + \else + \CF_doifnotempty\CF_arrowcurrentstyle{\CF_addtomacro\CF_arrowcurrentstyle,}% + \CF_doifnotempty{#9}{\CF_addtomacro\CF_arrowcurrentstyle{#9,}}% + \CF_displaycompound{}{#3}% + \def\CF_nextnodename{#4}% + \CF_expsecond{\def\CF_currentnodename}{\CF_gobarg#1}% + \let\CF_arrowstartname\CF_currentnodename + \let\CF_arrowendname\CF_nextnodename + \CF_arrowf{#7}{#8}{#2}{#5}% + \def\CF_nextnodestyle{#6}% + \fi + \else + \CF_doifnotempty\CF_arrowcurrentstyle{\CF_addtomacro\CF_arrowcurrentstyle,}% + \CF_doifnotempty{#9}{\CF_addtomacro\CF_arrowcurrentstyle{#9,}}% + \if @\expandafter\CF_firsttonil\detokenize{#2.}\_nil + \CF_error{syntax "(--@)" is not allowed}% + \else + \CF_displaycompound{#1}{#3}% + \edef\CF_arrowstartname{% + \CF_ifempty{#1} + \CF_currentnodename + {#1}% + \CF_doifnotempty{#2}{.#2}% + }% + \CF_arrowf{#7}{#8}{#2}{#5}% + \def\CF_nextnodename{#4}% + \def\CF_nextnodestyle{#6}% + \fi + \fi + \CF_arrowgobspaces% +} + +\def\CF_arrowgobspaces{\futurelet\CF_toksa\CF_arrowgobspacesa} + +\def\CF_arrowgobspacesa{% + \CF_ifx\CF_sptoken\CF_toksa + \CF_arrowgobspacesb + \CF_nextaction +} + +\expandafter\def\expandafter\CF_arrowgobspacesb\space{\futurelet\CF_toksa\CF_arrowgobspacesa} + +\def\CF_arrowf#1#2#3#4{% + \def\CF_nextaction{\let\CF_compound\empty\CF_schemestartc}% + \def\CF_arrowcurrentangle{#1}\CF_doifempty\CF_arrowcurrentangle{\let\CF_arrowcurrentangle\CF_arrowangle}% + \def\CF_currentarrowlength{#2}\CF_doifempty\CF_currentarrowlength{\let\CF_currentarrowlength\CF_arrowlength}% + \node[at=(\CF_currentnodename.\CF_ifempty{#3}\CF_arrowcurrentangle{#3}),shift=(\CF_arrowcurrentangle:\CF_currentarrowlength*\CF_compoundsep),cyan,fill](end@arrow@i@\number\CF_schemenest){};% + \edef\CF_arrowendname{end@arrow@i@\number\CF_schemenest\CF_doifnotempty{#4}{.#4}}% + \ifboolKV[chemfig]{scheme debug} + {\node[at=(\CF_currentnodename.\CF_ifempty{#3}\CF_arrowcurrentangle{#3}),shift=(\CF_arrowcurrentangle:\CF_arrowoffset),red,fill](start@arrow){};% + \node[at=(\CF_currentnodename.\CF_ifempty{#3}\CF_arrowcurrentangle{#3}),shift=(\CF_arrowcurrentangle:\CF_currentarrowlength*\CF_compoundsep-\CF_arrowoffset),red,fill](end@arrow){};% + } + {\node[at=(\CF_currentnodename.\CF_ifempty{#3}\CF_arrowcurrentangle{#3}),shift=(\CF_arrowcurrentangle:\CF_arrowoffset)](start@arrow){};% + \node[at=(\CF_currentnodename.\CF_ifempty{#3}\CF_arrowcurrentangle{#3}),shift=(\CF_arrowcurrentangle:\CF_currentarrowlength*\CF_compoundsep-\CF_arrowoffset)](end@arrow){};% + }% + \def\CF_arrowstartnode{start@arrow}\def\CF_arrowendnode{end@arrow}% + \csname\expandafter\CF_grabarrowname\CF_currentarrowtype[\_nil\CF_threeea\endcsname + \expandafter\CF_grabarrowargs\CF_currentarrowtype[]\_nil[][][][][][][][]\_nil + \def\CF_currentnodename{end@arrow@i@\number\CF_schemenest}% + \edef\CF_nextnodeanchor{\CF_ifempty{#4}{180+\CF_arrowcurrentangle}{#4}}% +} + +% +% +\def\CF_directarrow#1#2#3#4#5#6{% + \CF_expsecond{\def\CF_arrowstartname}{\CF_gobarg#2}% + \CF_expsecond{\def\CF_arrowendname}{\CF_gobarg#4}% + \path[sloped,allow upside down](\CF_gobarg#2\ifx\empty#3\empty\else.#3\fi)--(\CF_gobarg#4\ifx\empty#5\empty\else.#5\fi)% + coordinate[pos=0,xshift=\CF_arrowoffset](start@direct@arrow)% + coordinate[pos=1,xshift=-\CF_arrowoffset](end@direct@arrow);% + \def\CF_arrowstartnode{start@direct@arrow}% + \def\CF_arrowendnode{end@direct@arrow}% + \pgfmathanglebetweenpoints + {\pgfpointanchor{\CF_gobarg#2}{\ifx\empty#3\empty center\else#3\fi}}% + {\pgfpointanchor{\CF_gobarg#4}{\ifx\empty#5\empty center\else#5\fi}}% + \let\CF_arrowcurrentangle\pgfmathresult + \CF_doifnotempty{#6}{\CF_addtomacro\CF_arrowcurrentstyle{#6,}}% + \csname\CF_grabarrowname#1[]\_nil\expandafter\endcsname\CF_grabarrowargs#1[]\_nil[][][][][][][][]\_nil +} + +\def\CF_mergegrabchardir#1[#2][#3]#4\_nil{% + \CF_expafter{\futurelet\CF_toksa\CF_gobtonil}{\CF_firsttonil#1>\_nil}\_nil + \ifx>\CF_toksa + \def\CF_mergeangle{0}\def\CF_mergeextreme{xmax}\def\CF_mergesign{+}% + \else + \ifx<\CF_toksa + \def\CF_mergeangle{180}\def\CF_mergeextreme{xmin}\def\CF_mergesign{-}% + \else + \ifx^\CF_toksa + \def\CF_mergeangle{90}\def\CF_mergeextreme{ymax}\def\CF_mergesign{+}% + \else + \ifx v\CF_toksa + \def\CF_mergeangle{-90}\def\CF_mergeextreme{ymin}\def\CF_mergesign{-}% + \fi\fi\fi\fi + \def\CF_mergelabelup{#2}\def\CF_mergelabeldo{#3}% +} + +\def\CF_merge#1({% + \CF_mergegrabchardir#1[][]\_nil + \CF_mergea(% +} + +\def\CF_mergea#1--(#2){\CF_testopt{\CF_mergeb#1--(#2)}{}} + +\def\CF_mergeb#1--(#2)[#3]{% + \CF_displaycompound{}{}% + \CF_parsemergeopt#3,\CF_quark,\CF_quark,\CF_quark\_nil + \def\CF_mergexmax{-16383.99999pt}\let\CF_mergeymax\CF_mergexmax + \def\CF_mergexmin{16383.99999pt}\let\CF_mergeymin\CF_mergexmin + \CF_mergeparsenodelist#1(\relax)% + \pgfmathsetmacro\CF_mergeextremeresult{\csname CF_merge\CF_mergeextreme\endcsname\CF_mergesign\CF_mergefromcoeff*\CF_compoundsep}% + \CF_mergec#1(\relax)% + \CF_expsecond{\def\CF_temp}{\expandafter[\CF_mergestyle,shorten <=0,shorten >=0,-]}% + \if x\expandafter\CF_firsttonil\CF_mergeextreme\_nil + \CF_addtomacro\CF_temp{(\CF_mergeextremeresult pt,\CF_mergeymax)--(\CF_mergeextremeresult pt,\CF_mergeymin)}% + \else + \CF_addtomacro\CF_temp{(\CF_mergexmin,\CF_mergeextremeresult pt)--(\CF_mergexmax,\CF_mergeextremeresult pt)}% + \fi + \expandafter\draw\CF_temp node[pos=\CF_mergesplitcoeff](merge@point){}% + node[at=(merge@point),shift=(\CF_mergeangle:\CF_compoundsep*\CF_mergetocoeff-\CF_arrowoffset)](end@merge){}% + node[at=(merge@point),shift=(\CF_mergeangle:\CF_compoundsep*\CF_mergetocoeff)](end@merge@i){};% + \let\CF_arrowcurrentangle\CF_mergeangle + \CF_expafter{\draw[}\CF_mergestyle,shorten <=0](merge@point)--(end@merge)% + \expandafter\CF_arrowdisplaylabela\expandafter{\CF_mergelabelup}{.5}+\expandafter\CF_arrowdisplaylabela\expandafter{\CF_mergelabeldo}{.5}-;% + \def\CF_currentnodename{end@merge@i}% + \let\CF_temp\empty + \CF_analysearrowarg{#2}% + \expandafter\CF_merged\CF_temp\_nil +} + +\def\CF_mergec(#1){% + \if\relax\expandafter\noexpand\CF_firsttonil#1\_nil + \else + \CF_ifdot{#1}% + {\edef\merge_currentnodename{\CF_beforedot#1\_nil}% + \edef\merge_currentanchor{\CF_afterdot#1\_nil}% + }% + {\def\merge_currentnodename{#1}% + \let\merge_currentanchor\CF_mergeangle + }% + \if x\expandafter\CF_firsttonil\CF_mergeextreme\_nil + \pgfextracty\CF_dim{\pgfpointanchor\merge_currentnodename\merge_currentanchor}% + \CF_expafter{\draw[}\CF_mergestyle,shorten >=0,-]([shift=(\CF_mergeangle:\CF_arrowoffset)]\merge_currentnodename.\merge_currentanchor)--(\CF_mergeextremeresult pt,\CF_dim);% + \else + \pgfextractx\CF_dim{\pgfpointanchor\merge_currentnodename\merge_currentanchor}% + \CF_expafter{\draw[}\CF_mergestyle,shorten >=0,-]([shift=(\CF_mergeangle:\CF_arrowoffset)]\merge_currentnodename.\merge_currentanchor)--(\CF_dim,\CF_mergeextremeresult pt);% + \fi + \expandafter\CF_mergec + \fi +} + +\def\CF_merged#1.#2[#3]\_nil{% + \def\CF_nextnodename{#1}% + \edef\CF_nextnodeanchor{% + \CF_ifempty{#2} + {180+\CF_mergeangle} + {#2}% + }% + \def\CF_nextnodestyle{#3}% + \let\CF_compound\empty + \CF_schemestartc +} + +\def\CF_parsemergeopt#1,#2,#3,#4\_nil{% + \CF_ifempty{#1} + {\def\CF_mergefromcoeff{0.5}} + {\def\CF_mergefromcoeff{#1}}% + \def\CF_mergetocoeff{0.5}% + \def\CF_mergesplitcoeff{0.5}% + \CF_expsecond{\def\CF_mergestyle}{\CF_arrowhead}% + \CF_iffirsttokmatch\CF_quark{#2\relax} + {} + {\CF_ifempty{#2} + {\def\CF_mergetocoeff{0.5}} + {\def\CF_mergetocoeff{#2}}% + \CF_iffirsttokmatch\CF_quark{#3\relax} + {} + {\CF_ifempty{#3} + {\def\CF_mergesplitcoeff{0.5}} + {\def\CF_mergesplitcoeff{#3}}% + \CF_iffirsttokmatch\CF_quark{#4\relax} + {} + {\CF_parsemergeopta#4\_nil}% + }% + }% +} + +\def\CF_parsemergeopta#1,\CF_quark#2\_nil{% + \CF_ifempty{#1} + {} + {\CF_addtomacro\CF_mergestyle{,#1}}% +} + +\def\CF_mergeparsenodelist(#1){% + \if\relax\expandafter\noexpand\CF_firsttonil#1\_nil + \else + \CF_ifdot{#1}% + {\edef\merge_currentnodename{\CF_beforedot#1\_nil}\edef\merge_currentanchor{\CF_afterdot#1\_nil}}% + {\def\merge_currentnodename{#1}\let\merge_currentanchor\CF_mergeangle}% + \pgfextractx\CF_dim{\pgfpointanchor\merge_currentnodename\merge_currentanchor}% + \ifdim\CF_dim>\CF_mergexmax + \edef\CF_mergexmax{\the\CF_dim}% + \fi + \ifdim\CF_dim<\CF_mergexmin + \edef\CF_mergexmin{\the\CF_dim}% + \fi + \pgfextracty\CF_dim{\pgfpointanchor\merge_currentnodename\merge_currentanchor}% + \ifdim\CF_dim>\CF_mergeymax + \edef\CF_mergeymax{\the\CF_dim}% + \fi + \ifdim\CF_dim<\CF_mergeymin + \edef\CF_mergeymin{\the\CF_dim}% + \fi + \expandafter\CF_mergeparsenodelist + \fi +} + +\def\CF_grabarrowname#1[#2\_nil{\detokenize{CF_arrow(#1)}} +\def\CF_grabarrowargs#1[#2\_nil{[#2} + +\def\CF_makeparametertext#1{% + \toks0{}% + \CF_cntgroup#1\relax + \CF_makeparametertexta1% +} + +\def\CF_makeparametertexta#1{% + \unless\ifnum#1>\CF_cntgroup + \toks0\expandafter{\the\toks0[###1]}% + \expandafter\CF_makeparametertexta\expandafter{\number\numexpr#1+1\expandafter}% + \fi +} + +% +\def\definearrow#1#2#3{% + \begingroup + \CF_makeparametertext{#1}% + \expandafter\endgroup + \expandafter\def\csname\detokenize{CF_arrow(#2)}\expandafter\endcsname\the\toks0{#3\CF_gobtonil}% +} + +\def\CF_ifdot#1{\CF_ifdota#1.\_nil} +\def\CF_ifdota#1.#2\_nil{\ifx\empty#2\empty\expandafter\CF_execsecond\else\expandafter\CF_execfirst\fi} +\def\CF_beforedot#1.#2\_nil{#1} +\def\CF_afterdot#1.#2\_nil{#2} + +\def\CF_rotatenode*#1#2\_nil{% + \CF_ifdot{#1} + {\CF_beforedot#1\_nil} + {#1}% +} +\def\CF_anchornode*#1#2\_nil#3{% + \CF_ifdot{#1} + {\CF_afterdot#1\_nil} + {\CF_arrowcurrentangle-#390-#1}% +} + +% +% +\def\CF_arrowdisplaylabel#1#2#3#4#5#6#7#8{% + \CF_doifnotempty{#1#5} + {\path(#4)--(#8)\CF_arrowdisplaylabela{#1}{#2}{#3}\CF_arrowdisplaylabela{#5}{#6}{#7};}% +} + +\def\CF_arrowdisplaylabela#1#2#3{% + \CF_doifnotempty{#1} + {\if*\expandafter\CF_firsttonil\detokenize{#1}\_nil + \ifboolKV[chemfig]{scheme debug} + {node[pos=#2,sloped,yshift=#3\CF_arrowlabelsep,draw,fill,cyan](shifted@node){}% + node[draw,rotate=\CF_rotatenode#1\_nil,anchor=\CF_anchornode#1\_nil#3,at=(shifted@node)]{\expandafter\CF_gobarg\CF_gobarg#1}% + } + {node[pos=#2,sloped,yshift=#3\CF_arrowlabelsep](shifted@node){}% + node[rotate=\CF_rotatenode#1\_nil,anchor=\CF_anchornode#1\_nil#3,at=(shifted@node)]{\expandafter\CF_gobarg\CF_gobarg#1}% + }% + \else + \ifboolKV[chemfig]{scheme debug} + {node[pos=#2,sloped,yshift=#3\CF_arrowlabelsep,draw,fill,cyan](shifted@node){}% + node[draw,pos=#2,anchor=-#390,sloped,yshift=#3\CF_arrowlabelsep]{#1}% + } + {node[pos=#2,anchor=-#390,sloped,yshift=#3\CF_arrowlabelsep]{#1}% + } + \fi + }% +} + +% +\def\CF_arrowshiftnodes#1{% + \unless\ifdim\CF_ifempty{#1}\CF_zero{#1}=0pt + \expanded{% + \noexpand\path(\CF_arrowstartnode)--(\CF_arrowendnode)% + node[pos=0,sloped,yshift=#1](\CF_arrowstartnode1){}node[pos=1,sloped,yshift=#1](\CF_arrowendnode1){};}% + \edef\CF_arrowstartnode{\CF_arrowstartnode1}\edef\CF_arrowendnode{\CF_arrowendnode1}% + \fi +} + +\definearrow3{->}{% + \CF_arrowshiftnodes{#3}% + \CF_expafter{\draw[}\CF_arrowcurrentstyle](\CF_arrowstartnode)--(\CF_arrowendnode);% + \CF_arrowdisplaylabel{#1}{0.5}+\CF_arrowstartnode{#2}{0.5}-\CF_arrowendnode +} + +\definearrow3{<-}{% + \CF_arrowshiftnodes{#3}% + \CF_expafter{\draw[}\CF_arrowcurrentstyle](\CF_arrowendnode)--(\CF_arrowstartnode);% + \CF_arrowdisplaylabel{#1}{0.5}+\CF_arrowstartnode{#2}{0.5}-\CF_arrowendnode +} + +\definearrow5{-/>}{% + \CF_arrowshiftnodes{#3}% + \CF_expafter{\draw[}\CF_arrowcurrentstyle](\CF_arrowstartnode)--(\CF_arrowendnode)% + coordinate[midway,shift=(\CF_arrowcurrentangle:-1pt)](midway@i)% + coordinate[midway,shift=(\CF_arrowcurrentangle:1pt)](midway@ii)% + coordinate[at=(midway@i),shift=(\CF_ifempty{#4}{225}{#4+180}+\CF_arrowcurrentangle:\CF_ifempty{#5}{5pt}{#5})](line@start)% + coordinate[at=(midway@i),shift=(\CF_ifempty{#4}{45}{#4}+\CF_arrowcurrentangle:\CF_ifempty{#5}{5pt}{#5})](line@end)% + coordinate[at=(midway@ii),shift=(\CF_ifempty{#4}{225}{#4+180}+\CF_arrowcurrentangle:\CF_ifempty{#5}{5pt}{#5})](line@start@i)% + coordinate[at=(midway@ii),shift=(\CF_ifempty{#4}{45}{#4}+\CF_arrowcurrentangle:\CF_ifempty{#5}{5pt}{#5})](line@end@i); + \draw(line@start)--(line@end);% + \draw(line@start@i)--(line@end@i);% + \CF_arrowdisplaylabel{#1}{0.5}+\CF_arrowstartnode{#2}{0.5}-\CF_arrowendnode +} + +\definearrow3{<->}{% + \CF_arrowshiftnodes{#3}% + \CF_expafter{\draw[}\CF_arrowcurrentstyle,\CF_arrowtip-\CF_arrowtip](\CF_arrowstartnode)--(\CF_arrowendnode);% + \CF_arrowdisplaylabel{#1}{0.5}+\CF_arrowstartnode{#2}{0.5}-\CF_arrowendnode +} + +\definearrow3{<=>}{% + \CF_arrowshiftnodes{#3}% + \path[allow upside down](\CF_arrowstartnode)--(\CF_arrowendnode)% + node[pos=0,sloped,yshift=\CF_arrowdoublesep](\CF_arrowstartnode @u0){}% + node[pos=0,sloped,yshift=-\CF_arrowdoublesep](\CF_arrowstartnode @d0){}% + node[pos=1,sloped,yshift=\CF_arrowdoublesep](\CF_arrowstartnode @u1){}% + node[pos=1,sloped,yshift=-\CF_arrowdoublesep](\CF_arrowstartnode @d1){};% + \begingroup + \ifboolKV[chemfig]{arrow double harpoon} + {\pgfarrowharpoontrue} + {}% + \CF_expafter{\draw[}\CF_arrowcurrentstyle](\CF_arrowstartnode @u0)--(\CF_arrowstartnode @u1);% + \CF_expafter{\draw[}\CF_arrowcurrentstyle](\CF_arrowstartnode @d1)--(\CF_arrowstartnode @d0);% + \endgroup + \CF_arrowdisplaylabel{#1}{0.5}+\CF_arrowstartnode{#2}{0.5}-\CF_arrowendnode% +} + +\definearrow3{<->>}{% + \CF_arrowshiftnodes{#3}% + \path[allow upside down](\CF_arrowstartnode)--(\CF_arrowendnode)% + node[pos=0,sloped,yshift=1pt](\CF_arrowstartnode @u0){}% + node[pos=\CF_arrowdoubleposstart,sloped,yshift=-1pt](\CF_arrowstartnode @d0){}% + node[pos=1,sloped,yshift=1pt](\CF_arrowstartnode @u1){}% + node[pos=\CF_arrowdoubleposend,sloped,yshift=-1pt](\CF_arrowstartnode @d1){};% + \begingroup + \ifboolKV[chemfig]{arrow double harpoon} + {\pgfarrowharpoontrue} + {}% + \CF_expafter{\draw[}\CF_arrowcurrentstyle](\CF_arrowstartnode @u0)--(\CF_arrowstartnode @u1);% + \CF_expafter{\draw[}\CF_arrowcurrentstyle](\CF_arrowstartnode @d1)--(\CF_arrowstartnode @d0);% + \endgroup + \CF_arrowdisplaylabel{#1}{0.5}+\CF_arrowstartnode{#2}{0.5}-\CF_arrowendnode% +} + +\definearrow3{<<->}{% + \path[allow upside down](\CF_arrowstartnode)--(\CF_arrowendnode)% + node[pos=\CF_arrowdoubleposstart,sloped,yshift=1pt](\CF_arrowstartnode @u0){}% + node[pos=0,sloped,yshift=-1pt](\CF_arrowstartnode @d0){}% + node[pos=\CF_arrowdoubleposend,sloped,yshift=1pt](\CF_arrowstartnode @u1){}% + node[pos=1,sloped,yshift=-1pt](\CF_arrowstartnode @d1){};% + \begingroup + \ifboolKV[chemfig]{arrow double harpoon} + {\pgfarrowharpoontrue} + {}% + \CF_expafter{\draw[}\CF_arrowcurrentstyle](\CF_arrowstartnode @u0)--(\CF_arrowstartnode @u1);% + \CF_expafter{\draw[}\CF_arrowcurrentstyle](\CF_arrowstartnode @d1)--(\CF_arrowstartnode @d0);% + \endgroup + \CF_arrowdisplaylabel{#1}{0.5}+\CF_arrowstartnode{#2}{0.5}-\CF_arrowendnode +} + +\definearrow30{% + \CF_arrowshiftnodes{#3}% + \CF_arrowdisplaylabel{#1}{0.5}+\CF_arrowstartnode{#2}{0.5}-\CF_arrowendnode +} + +\definearrow5{-U>}{% + \CF_arrowshiftnodes{#3}% + \CF_expafter{\draw[}\CF_arrowcurrentstyle](\CF_arrowstartnode)--(\CF_arrowendnode)node[midway](Uarrow@arctangent){};% + \CF_ifempty{#4} + {\def\CF_Uarrowradius{0.333}} + {\def\CF_Uarrowradius{#4}}% + \CF_ifempty{#5}% + {\def\CF_Uarrowabsangle{60}} + {\pgfmathsetmacro\CF_Uarrowabsangle{abs(#5)}}% + \expandafter\draw\expanded{[\CF_ifempty{#1}{draw=none}{\unexpanded\expandafter{\CF_arrowcurrentstyle}},-]}(Uarrow@arctangent)% + arc[radius=\CF_compoundsep*\CF_currentarrowlength*\CF_Uarrowradius,start angle=\CF_arrowcurrentangle-90,delta angle=-\CF_Uarrowabsangle]node(Uarrow@start){}; + \expandafter\draw\expanded{[\CF_ifempty{#2}{draw=none}{\unexpanded\expandafter{\CF_arrowcurrentstyle}}]}(Uarrow@arctangent)% + arc[radius=\CF_compoundsep*\CF_currentarrowlength*\CF_Uarrowradius,start angle=\CF_arrowcurrentangle-90,delta angle=\CF_Uarrowabsangle]node(Uarrow@end){}; + \pgfmathsetmacro\CF_temp{\CF_Uarrowradius*cos(\CF_arrowcurrentangle)<0?"-":"+"}% + \ifdim\CF_Uarrowradius pt>0pt + \CF_arrowdisplaylabel{#1}{0}\CF_temp{Uarrow@start}{#2}{1}\CF_temp{Uarrow@end}% + \else + \CF_arrowdisplaylabel{#2}{0}\CF_temp{Uarrow@start}{#1}{1}\CF_temp{Uarrow@end}% + \fi +} + +\def\CF_grabdelim#1#2#3\_CFnil{\def\CF_leftdelim{#1}\def\CF_rightdelim{#2}} +\defKV[CFdelimiters]{% + delimiters = \CF_grabdelim#1()\_CFnil, + height = \def\CF_delimheight{#1}, + depth = \CF_expsecond{\CF_defifempty\CF_delimdepth{#1}}{\CF_delimheight}, + open xshift = \edef\CF_leftdelimxshift{\the\dimexpr#1}, + close xshift = \edef\CF_rightdelimxshift{\CF_ifempty{#1}{-\CF_leftdelimxshift}{-\the\dimexpr#1}} +} +\setKVdefault[CFdelimiters]{% + delimiters = (), + height = 10pt, + depth = , + open xshift = 0pt, + close xshift = , + h align = true, + auto rotate = false, + rotate = 0, + indice = n +}% +\def\polymerdelim{\CF_ifnextchar[{\CF_polymerdelima}{\CF_polymerdelima[]}} +\def\CF_polymerdelima[#1]#2#3{% + \restoreKV[CFdelimiters]% + \CF_doifnotempty{#1}{\setKV[CFdelimiters]{#1}}% + \edef\CF_delimhalfdim{\the\dimexpr(\CF_delimheight+\CF_delimdepth)/2}% + \edef\CF_delimvshift {\the\dimexpr(\CF_delimheight-\CF_delimdepth)/2}% + \chemmove{% + \nulldelimiterspace0pt + \pgfextractx\CF_dim{\pgfpointanchor{#2}{center}}\edef\CF_leftdelimx{\the\CF_dim}% + \pgfextracty\CF_dim{\pgfpointanchor{#2}{center}}\edef\CF_leftdelimy{\the\CF_dim}% + \pgfextractx\CF_dim{\pgfpointanchor{#3}{center}}\edef\CF_rightdelimx{\the\CF_dim}% + \pgfextracty\CF_dim{\pgfpointanchor{#3}{center}}\edef\CF_rightdelimy{\the\CF_dim}% + \def\CF_autorotate{0}% + \ifboolKV[CFdelimiters]{h align} + {\let\CF_rightdelimy\CF_leftdelimy + } + {% + \ifboolKV[CFdelimiters]{auto rotate} + {\pgfmathatantwo{\CF_rightdelimy-\CF_leftdelimy}{\CF_rightdelimx-\CF_leftdelimx}% + \let\CF_autorotate\pgfmathresult + } + {\CF_eexpsecond\CF_ifempty{\useKV[CFdelimiters]{rotate}} + {} + {\edef\CF_autorotate{\useKV[CFdelimiters]{rotate}}}% + }% + }% + \node[at={(\CF_leftdelimx+\CF_leftdelimxshift,\CF_leftdelimy+\CF_delimvshift)},rotate=\CF_autorotate] + {$\left\CF_leftdelim\vrule height\CF_delimhalfdim depth\CF_delimhalfdim width0pt\right.$};% + \node[at={(\CF_rightdelimx+\CF_rightdelimxshift,\CF_rightdelimy+\CF_delimvshift)},rotate=\CF_autorotate] + {$\left.\vrule height\CF_delimhalfdim depth\CF_delimhalfdim width0pt\right\CF_rightdelim + \CF_eexpsecond\CF_doifnotempty{\useKV[CFdelimiters]{indice}} + {\CF_underscore{\rlap{$\scriptstyle\useKV[CFdelimiters]{indice}$}}} + $}; + }% +} + +\catcode`\@11 +\pgfdeclarearrow{% + name = CF,% + defaults = {% + length = 3pt 5 1,% + width' = 0pt .8,% + inset' = 0pt .5,% + line width = 0pt 1 1,% + round% + },% + setup code = {% + % + \pgf@x\pgfarrowlength + \advance\pgf@x by-\pgfarrowinset + \pgf@x.25\pgf@x + \ifdim\pgf@x<\pgfarrowlinewidth\pgfarrowlinewidth\pgf@x\fi + % + \pgfmathdivide@{\pgf@sys@tonumber\pgfarrowlength}{\pgf@sys@tonumber\pgfarrowwidth}% + \let\pgf@temp@quot\pgfmathresult% + \pgf@x\pgfmathresult pt% + \pgf@x\pgfmathresult\pgf@x% + \pgf@x4\pgf@x% + \advance\pgf@x by1pt% + \pgfmathsqrt@{\pgf@sys@tonumber\pgf@x}% + \pgf@xc\pgfmathresult\pgfarrowlinewidth% + \pgf@xc.5\pgf@xc + \pgf@xa\pgf@temp@quot\pgfarrowlinewidth% + % + \pgf@ya.5\pgfarrowwidth% + \csname pgfmathatan2@\endcsname{\pgfmath@tonumber\pgfarrowlength}{\pgfmath@tonumber\pgf@ya}% + \pgf@yb\pgfmathresult pt% + \csname pgfmathatan2@\endcsname{\pgfmath@tonumber\pgfarrowinset}{\pgfmath@tonumber\pgf@ya}% + \pgf@ya\pgfmathresult pt% + \advance\pgf@yb by-\pgf@ya% + \pgf@yb.5\pgf@yb% + \pgfmathtan@{\pgf@sys@tonumber\pgf@yb}% + \pgfmathreciprocal@{\pgfmathresult}% + \pgf@yc\pgfmathresult\pgfarrowlinewidth% + \pgf@yc.5\pgf@yc% + \advance\pgf@ya by\pgf@yb% + \pgfmathsincos@{\pgf@sys@tonumber\pgf@ya}% + \pgf@ya\pgfmathresulty\pgf@yc% + \pgf@yb\pgfmathresultx\pgf@yc% + \ifdim\pgfarrowinset=0pt + \pgf@ya.5\pgfarrowlinewidth% + \fi + % + \pgfmathdivide@{\pgf@sys@tonumber\pgfarrowinset}{\pgf@sys@tonumber\pgfarrowwidth}% + \let\pgf@temp@quot\pgfmathresult% + \pgf@x\pgfmathresult pt% + \pgf@x\pgfmathresult\pgf@x% + \pgf@x4\pgf@x% + \advance\pgf@x by1pt% + \pgfmathsqrt@{\pgf@sys@tonumber\pgf@x}% + \pgf@yc\pgfmathresult\pgfarrowlinewidth% + \pgf@yc.5\pgf@yc% + % + \pgfutil@tempdima\pgfarrowlength% + \advance\pgfutil@tempdima by-\pgf@xc% + \advance\pgfutil@tempdima by-\pgf@ya% + \pgfutil@tempdimb.5\pgfarrowwidth% + \advance\pgfutil@tempdimb by-\pgf@yb% + % + \ifpgfarrowroundjoin + \pgfarrowssetbackend{\pgf@ya\advance\pgf@x by-.5\pgfarrowlinewidth}% + \else + \pgfarrowssetbackend{0pt} + \fi + \ifpgfarrowharpoon + \pgfarrowssetlineend{\pgfarrowinset\advance\pgf@x by\pgf@yc\advance\pgf@x by.5\pgfarrowlinewidth}% + \else + \pgfarrowssetlineend{\pgfarrowinset\advance\pgf@x by\pgf@yc\advance\pgf@x by-.25\pgfarrowlinewidth}% + \ifpgfarrowreversed + \ifdim\pgfinnerlinewidth>0pt + \pgfarrowssetlineend{\pgfarrowinset}% + \else + \pgfarrowssetlineend{\pgfutil@tempdima\advance\pgf@x by\pgf@ya\advance\pgf@x by-.25\pgfarrowlinewidth}% + \fi + \fi + \fi + \ifpgfarrowroundjoin + \pgfarrowssettipend{\pgfutil@tempdima\advance\pgf@x by\pgf@ya\advance\pgf@x by.5\pgfarrowlinewidth}% + \else + \pgfarrowssettipend{\pgfarrowlength\ifpgfarrowharpoon\advance\pgf@x by\pgf@xa\fi}% + \fi + % + \pgfarrowshullpoint{\pgfarrowlength\ifpgfarrowroundjoin\else\ifpgfarrowharpoon\advance\pgf@x by\pgf@xa\fi\fi}{\ifpgfarrowharpoon-.5\pgfarrowlinewidth\else0pt\fi}% + \pgfarrowsupperhullpoint{0pt}{.5\pgfarrowwidth}% + \pgfarrowshullpoint{\pgfarrowinset}{\ifpgfarrowharpoon-.5\pgfarrowlinewidth\else 0pt\fi}% + % + \pgfarrowssetvisualbackend{\pgfarrowinset}% + \advance\pgfarrowinset by\pgf@yc% + % + \pgfarrowssavethe\pgfutil@tempdima + \pgfarrowssavethe\pgfutil@tempdimb + \pgfarrowssavethe\pgfarrowlinewidth + \pgfarrowssavethe\pgf@ya + \pgfarrowssavethe\pgfarrowinset + },% + drawing code = {% + \pgfsetdash{}{0pt}% + \ifpgfarrowroundjoin\pgfsetroundjoin\else\pgfsetmiterjoin\fi + \ifdim\pgfarrowlinewidth=\pgflinewidth\else\pgfsetlinewidth{\pgfarrowlinewidth}\fi + \pgfpathmoveto{\pgfqpoint{\pgfutil@tempdima\advance\pgf@x by\pgf@ya}{0pt}}% + \pgfpathlineto{\pgfqpoint{\pgf@ya}{\pgfutil@tempdimb}}% + \pgfpathlineto{\pgfqpoint{\pgfarrowinset}{0pt}}% + \ifpgfarrowharpoon \else + \pgfpathlineto{\pgfqpoint{\pgf@ya}{-\pgfutil@tempdimb}}% + \fi + \pgfpathclose + \ifpgfarrowopen\pgfusepathqstroke\else\ifdim\pgfarrowlinewidth>0pt \pgfusepathqfillstroke\else\pgfusepathqfill\fi\fi + },% + parameters = {% + \the\pgfarrowlinewidth,% + \the\pgfarrowlength,% + \the\pgfarrowwidth,% + \the\pgfarrowinset,% + \ifpgfarrowharpoon h\fi% + \ifpgfarrowopen o\fi% + \ifpgfarrowroundjoin j\fi% + }% +} +\CFrestorecatcode +\endinput diff --git a/NixTeX/dependencies/source/chemfig/chemfig-lewis.tex b/NixTeX/dependencies/source/chemfig/chemfig-lewis.tex new file mode 100644 index 0000000..d713eec --- /dev/null +++ b/NixTeX/dependencies/source/chemfig/chemfig-lewis.tex @@ -0,0 +1,129 @@ +\ifdefined\CFname\else + \errmessage{Chemfig is not loaded, lewis cannot work}% + \expandafter\endinput +\fi + +\csname lewisloadonce\endcsname +\let\lewisloadonce\endinput + +\begingroup + \def\X#1{\catcode\number`#1=\number\catcode`#1\relax} + \xdef\CFrestorecatcode{\X\[\X\]\X\:\X\(\X\)\X\,\X\-\X\=\X\~\X\!\X\?\X\<\X\>\X\;\X\*\X\|\X\@\X\ \X\_}% +\endgroup + +\catcode`\[12 \catcode`\]12 \catcode`\:12 \catcode`\(12 +\catcode`\)12 \catcode`\,12 \catcode`\-12 \catcode`\=12 +\catcode`\~12 \catcode`\!12 \catcode`\?12 \catcode`\<12 +\catcode`\>12 \catcode`\;12 \catcode`\*12 \catcode`\|12 +\catcode`\@12 \catcode`\#6 \catcode`\ 10 \catcode`\_11 + +\newif\ifCF_lewisoverlay +\newbox\CF_boxlewis + +\defKV[chemfig]{% + lewis | width = \CF_defifempty\CF_lewiswidthdouble {#1}{0.3ex}, + lewis sep = \CF_defifempty\CF_lewisoffset {#1}{0.4ex}, + lewis length = \CF_defifempty\CF_lewislength {#1}{1.5ex}, + lewis style = \def\CF_lewisstyle {#1}, + lewis dist = \CF_defifempty\CF_lewisdist {#1}{0.3em}, + lewis radius = \CF_defifempty\CF_lewisradius {#1}{0.15ex}, + lewis diag coeff = \CF_defifempty\CF_lewisdiagcoeff {#1}{1} + } +\setKVdefault[chemfig]{% + lewis | width = 0.3ex, + lewis sep = 0.4ex, + lewis length = 1.5ex, + lewis style = {}, + lewis dist = 0.3em, + lewis radius = 0.15ex, + lewis diag coeff = 1 + } + +\def\Lewis{% + \CF_lewisoverlayfalse + \CF_testopt\CF_lewisa{}% +} + +\def\lewis{% + \CF_lewisoverlaytrue + \CF_testopt\CF_lewisa{}% +} + +\def\CF_lewisa[#1]{% + \begingroup + \CF_doifnotempty{#1}{\setchemfig{#1}}% + \ifCF_lewisoverlay + \CF_addtomacro\CF_lewisstyle{,overlay}% + \fi + \CF_lewisb +} + +\def\CF_lewisb#1{% + \CF_lewisc#1\_nil + \endgroup +} + +\def\CF_lewisc#1,#2\_nil{% + \setbox\CF_boxlewis\hbox{\printatom{#2}}% mettre en dehors de tikzpicture (si \printatom ne passe pas en mode math) + \CF_ifinsidetikz + {\pgfinterruptpicture + \let\CF_atendoflewis\endpgfinterruptpicture + } + {\let\CF_atendoflewis\relax + }% + \tikzpicture[every node/.style={anchor=base,inner sep=0pt,outer sep=0pt,minimum size=0pt},baseline]% + \CF_makeother;\CF_makeother:% + \node(CF_lewis@anchor){}; + \def\CF_lewisremainpos{#1}% + \let\CF_lewispreviouspos\empty + \loop + \unless\ifx\CF_lewisremainpos\empty + \edef\CF_lewiscurrentpos{\expandafter\CF_firsttonil\CF_lewisremainpos\_nil}% + \edef\CF_lewisremainpos{\expandafter\CF_gobarg\CF_lewisremainpos}% + \pgfmathsetmacro\CF_lewisx{\wd\CF_boxlewis/2+\ifcase\CF_lewiscurrentpos\space1\or1\or0\or-1\or-1\or-1\or0\or1\fi*(\wd\CF_boxlewis/2)}% + \pgfmathsetmacro\CF_lewisy{\ht\CF_boxlewis/2+\ifcase\CF_lewiscurrentpos\space0\or1\or1\or1\or0\or-1\or-1\or-1\fi*(\ht\CF_boxlewis/2\ifnum\CF_lewiscurrentpos>4 +\dp\CF_boxlewis\fi)}% + \edef\CF_lewisxoffset{\ifcase\CF_lewiscurrentpos\space1\or0.70711\or0\or-0.70711\or-1\or-0.70711\or0\or0.70711\fi}% + \edef\CF_lewisyoffset{\ifcase\CF_lewiscurrentpos\space0\or0.70711\or1\or0.70711\or0\or-0.70711\or-1\or-0.70711\fi}% + \ifodd\CF_lewiscurrentpos\relax + \pgfmathsetmacro\CF_lewiscurrentoffset{\CF_lewisoffset*\CF_lewisdiagcoeff}%% + \else + \let\CF_lewiscurrentoffset\CF_lewisoffset + \fi + \if.\expandafter\CF_firsttonil\CF_lewisremainpos\relax\_nil + \edef\CF_lewisremainpos{\expandafter\CF_gobarg\CF_lewisremainpos}% + \CF_expafter{\draw[fill,black,}{\CF_lewisstyle]}% + (\CF_lewisx pt+\CF_lewisxoffset*\CF_lewiscurrentoffset,\CF_lewisy pt+\CF_lewisyoffset*\CF_lewiscurrentoffset)circle(\CF_lewisradius);% + \else + \if|\expandafter\CF_firsttonil\CF_lewisremainpos\relax\_nil + \edef\CF_lewisremainpos{\expandafter\CF_gobarg\CF_lewisremainpos}% + \pgfmathsetmacro\CF_lewisx{\CF_lewisx pt+\CF_lewisxoffset*\CF_lewiscurrentoffset}% + \pgfmathsetmacro\CF_lewisy{\CF_lewisy pt+\CF_lewisyoffset*\CF_lewiscurrentoffset}% + \CF_expafter{\draw[}\CF_lewisstyle]% + (\CF_lewisx pt+\CF_lewislength*\CF_lewisyoffset/2 pt,\CF_lewisy-\CF_lewislength*\CF_lewisxoffset/2 pt)-- + (\CF_lewisx pt+\CF_lewislength*\CF_lewisyoffset/2 pt+\CF_lewisxoffset*\CF_lewiswidthdouble,\CF_lewisy-\CF_lewislength*\CF_lewisxoffset/2 pt+\CF_lewisyoffset*\CF_lewiswidthdouble)-- + (\CF_lewisx pt-\CF_lewislength*\CF_lewisyoffset/2 pt+\CF_lewisxoffset*\CF_lewiswidthdouble,\CF_lewisy+\CF_lewislength*\CF_lewisxoffset/2 pt+\CF_lewisyoffset*\CF_lewiswidthdouble)-- + (\CF_lewisx pt-\CF_lewislength*\CF_lewisyoffset/2 pt,\CF_lewisy+\CF_lewislength*\CF_lewisxoffset/2 pt)--cycle;% + \else + \if:\expandafter\CF_firsttonil\CF_lewisremainpos\relax\_nil + \edef\CF_lewisremainpos{\expandafter\CF_gobarg\CF_lewisremainpos}% + \pgfmathsetmacro\CF_lewisx{\CF_lewisx pt+\CF_lewisxoffset*\CF_lewiscurrentoffset}% + \pgfmathsetmacro\CF_lewisy{\CF_lewisy pt+\CF_lewisyoffset*\CF_lewiscurrentoffset}% + \CF_expafter{\draw[fill,black,}{\CF_lewisstyle]}% + (\CF_lewisx pt+\CF_lewisdist*\CF_lewisyoffset/2 pt,\CF_lewisy-\CF_lewisdist*\CF_lewisxoffset/2 pt)circle(\CF_lewisradius)% + (\CF_lewisx pt-\CF_lewisdist*\CF_lewisyoffset/2 pt,\CF_lewisy+\CF_lewisdist*\CF_lewisxoffset/2 pt)circle(\CF_lewisradius);% + \else + \pgfmathsetmacro\CF_lewisx{\CF_lewisx pt+\CF_lewisxoffset*\CF_lewiscurrentoffset}% + \pgfmathsetmacro\CF_lewisy{\CF_lewisy pt+\CF_lewisyoffset*\CF_lewiscurrentoffset}% + \CF_expafter{\draw[}\CF_lewisstyle]% + (\CF_lewisx pt+\CF_lewislength*\CF_lewisyoffset/2 pt,\CF_lewisy-\CF_lewislength*\CF_lewisxoffset/2 pt)--% + (\CF_lewisx pt-\CF_lewislength*\CF_lewisyoffset/2 pt,\CF_lewisy+\CF_lewislength*\CF_lewisxoffset/2 pt);% + \fi + \fi + \fi + \repeat + \node[anchor=base west]at(CF_lewis@anchor){\box\CF_boxlewis};% + \endtikzpicture + \CF_atendoflewis +} +\CFrestorecatcode +\endinput \ No newline at end of file diff --git a/NixTeX/dependencies/source/chemfig/chemfig.sty b/NixTeX/dependencies/source/chemfig/chemfig.sty new file mode 100644 index 0000000..bb97937 --- /dev/null +++ b/NixTeX/dependencies/source/chemfig/chemfig.sty @@ -0,0 +1,8 @@ +\RequirePackage{tikz} +\def\CFfromsty{} +\input{\directlua{tex.print(source.."source/chemfig/chemfig")}} +\ProvidesPackage\CFname[\CFdate\space v\CFver\space Draw molecule with an easy syntax (CT)] +\def\printatom#1{\ensuremath{\text{#1}}}% \printatom pour LaTeX. +\expandafter\def\csname CF\string_begintikzpicture\endcsname{\begin{tikzpicture}}% +\expandafter\def\csname CF\string_endtikzpicture\endcsname{\end{tikzpicture}}% +\endinput \ No newline at end of file diff --git a/NixTeX/dependencies/source/chemfig/chemfig.tex b/NixTeX/dependencies/source/chemfig/chemfig.tex new file mode 100644 index 0000000..51aa26d --- /dev/null +++ b/NixTeX/dependencies/source/chemfig/chemfig.tex @@ -0,0 +1,3058 @@ +% !TeX encoding = ISO-8859-1 +% Ce fichier contient le code de l'extension "chemfig" +% +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% % +\def\CFname {chemfig} % +\def\CFver {1.6a} % +% % +\def\CFdate {2021/02/28} % +% % +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% +%____________________________________________________________________ +% Author : Christian Tellechea | +% Status : Maintained | +% Email : unbonpetit@netc.fr | +% Package URL: https://www.ctan.org/pkg/chemfig | +% Bug tracker: https://framagit.org/unbonpetit/chemfig/issues | +% Repository : https://framagit.org/unbonpetit/chemfig/tree/master | +% Copyright : Christian Tellechea 2010-2021 | +% Licence : Released under the LaTeX Project Public License v1.3c | +% or later, see http://www.latex-project.org/lppl.txt | +% Files : 1) chemfig.tex | +% 2) chemfig.sty | +% 3) README | +% 4) chemfig_doc_fr.tex | +% 5) chemfig_doc_fr.pdf | +% 6) chemfig_doc_en.tex | +% 7) chemfig_doc_fr.pdf | +% 8) chemfig-lewis.tex | +%-------------------------------------------------------------------- + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%%% P R � A L A B L E %%% +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +\csname CFloadonce\endcsname +\let\CFloadonce\endinput +%-------------------------- Annonce package -------------------------- +\ifdefined\CFfromsty\else + \immediate\write -1 {% + Package: \CFname\space\CFdate\space\space v\CFver\space\space + Draw molecule with an easy syntax (CT)}% +\fi + +%-------------------------- R�gime catcodes -------------------------- +\begingroup + \def\X#1{\catcode\number`#1=\number\catcode`#1\relax} + \xdef\CFrestorecatcode{\X\[\X\]\X\:\X\(\X\)\X\,\X\-\X\=\X\~\X\!\X\?\X\<\X\>\X\;\X\*\X\|\X\@\X\ \X\_}% +\endgroup +\catcode`\[12 \catcode`\]12 \catcode`\:12 \catcode`\(12 +\catcode`\)12 \catcode`\,12 \catcode`\-12 \catcode`\=12 +\catcode`\~12 \catcode`\!12 \catcode`\?12 \catcode`\<12 +\catcode`\>12 \catcode`\;12 \catcode`\*12 \catcode`\|12 +\catcode`\@12 \catcode`\#6 \catcode`\ 10 \catcode`\_11 + +%-------------------- V�rification des pr�requis --------------------- +\def\CF_error#1{\errmessage{Package \CFname\space Error: #1.}} +\def\CF_warning#1{\immediate\write-1{Package \CFname\space Warning: #1^^J}} +\def\CF_checkprimitive#1#2{% V�rifie que #1 est une primitive et sinon, �met le message #2 et ex�cute \endinput + \begingroup + \edef\__tempa{\meaning#1}\edef\__tempb{\string#1}\expandafter + \endgroup + \ifx\__tempa\__tempb\else + \CF_error{#2}% + \def\CF_temp{\CFrestorecatcode\endinput}% + \expandafter\CF_temp + \fi +} +\CF_checkprimitive\eTeXversion{You are not using an eTeX engine, \CFname\space cannot work.} +\CF_checkprimitive\expanded{the \string\expanded\space primitive is not provided by your TeX engine, \CFname\space cannot work.} + +%------------------------ Chargement simplekv ------------------------ +\input simplekv.tex + +%-------------------------- Chargement tikz -------------------------- +\unless\ifdefined\tikzpicture + \begingroup\def\CFtemp{\endgroup\input tikz.tex\relax}% + \expandafter\CFtemp +\fi +\usetikzlibrary{arrows.meta} + +%--------------------------- Allocations ----------------------------- +\newcount\CF_cntatomgroup +\newcount\CF_cntgroup +\newcount\CF_cntatom +\newcount\CF_cntcycle +\newcount\CF_cntcyclebonds +\newcount\CF_cntcompound + +\newif\ifCF_incycle +\newif\ifCF_cyclearc +\newif\ifCF_definesubmol +\newif\ifCF_adjustnamedp +\newif\ifCF_macrofixedbondlength +\newif\ifCF_compound_is_chemfig + +\newdimen\CF_dim +\newdimen\CF_arrowsize +\newdimen\CF_zero \CF_zero=0pt + +\newbox\CF_box +\newbox\CF_boxstuff +\newbox\CF_testbox +\newbox\CF_chargebox + +\newtoks\CF_substtoks + +%-------------------------- Petites macros --------------------------- +\let\CF_begintikzpicture\tikzpicture +\let\CF_endtikzpicture \endtikzpicture +\def\CF_quark{\CF_quark} +\def\CF_execfirst#1#2{#1} +\def\CF_execsecond#1#2{#2} +\def\CF_id#1{#1} +\def\CF_gobarg#1{} +\def\CF_gobtwoargs#1#2{} +\def\CF_firsttonil#1#2\_nil{#1} +\def\CF_sanitizelastitem#1,\empty#2\_nil{#1} +\def\CF_gobtikzinstruction#1;{} +\def\CF_makeother#1{\catcode`#1=12\relax} +\def\CF_lettoken#1#2{\let#1= #2}\CF_lettoken\CF_sptoken{ } +\def\CF_ifx#1#2{\ifx#1#2\expandafter\CF_execfirst\else\expandafter\CF_execsecond\fi} +\def\CF_ifempty#1{\ifx\empty#1\empty\expandafter\CF_execfirst\else\expandafter\CF_execsecond\fi} +\def\CF_ifnum#1{\ifnum#1\expandafter\CF_execfirst\else\expandafter\CF_execsecond\fi} +\def\CF_ifinsidetikz{\ifdefined\pgfpictureid\expandafter\CF_execfirst\else\expandafter\CF_execsecond\fi} +\def\CF_ifzerodim#1{% + \setbox\CF_testbox\hbox{\pgfinterruptpicture\printatom{#1}\endpgfinterruptpicture}% bugfix 1.53 + \CF_ifnum{1\ifdim\wd\CF_testbox=\CF_zero0\fi\ifdim\ht\CF_testbox=\CF_zero0\fi\ifdim\dp\CF_testbox=\CF_zero0\fi=1000 } +} +\def\CF_doifempty#1{\ifx\empty#1\empty\expandafter\CF_id\else\expandafter\CF_gobarg\fi} +\def\CF_doifnotempty#1{\ifx\empty#1\empty\expandafter\CF_gobarg\else\expandafter\CF_id\fi} +\def\CF_gobtonil#1\_nil{} +\def\CF_striplastsp#1{% + \long\def\CF_stripsp##1##2{\expanded{\CF_stripsp_i\_marksp##1\__nil\_marksp#1\_marksp\_nil{##2}}}% + \long\def\CF_stripsp_i##1\_marksp#1##2\_marksp##3\_nil{\CF_stripsp_ii##3##1##2\__nil#1\__nil\_nil}% + \long\def\CF_stripsp_ii##1#1\__nil##2\_nil{\CF_stripsp_iii##1##2\_nil}% + \long\def\CF_stripsp_iii##1##2\__nil##3\_nil##4{\unexpanded{##4{##2}}}% + \long\def\CF_striplastsp##1##2{\expanded{\CF_striplastsp_i\_marksp##1\__nil#1\__nil\_nil{##2}}}% + \long\def\CF_striplastsp_i##1#1\__nil##2\_nil{\CF_stripsp_iii##1\__nil\_nil}% +}\CF_striplastsp{ } +\edef\CFhash{\string#} +\begingroup + \catcode`\_8 + \expandafter\gdef\csname CF\string_underscore\endcsname{_} +\endgroup +\def\CF_threeea{\expandafter\expandafter\expandafter} +\def\CF_exptwomacroargs#1#2#3{\CF_expsecond{\CF_expsecond#1{#2}}{#3}} +\def\CF_expthreemacroargs#1#2#3#4{\CF_expsecond{\CF_exptwomacroargs#1{#2}{#3}}{#4}} +\def\CF_swaparg#1#2{#2{#1}} +\def\CF_expsecond#1#2{\expandafter\CF_swaparg\expandafter{#2}{#1}}% \CF_expsecond<{arg1>}{} donne "{*}" +\def\CF_eexpsecond#1#2{\expandafter\expandafter\expandafter\CF_swaparg\expandafter\expandafter\expandafter{#2}{#1}}% \CF_eexpsecond{}{} donne "{**}" +\def\CF_swapunbrace#1#2{#2#1} +\def\CF_expafter#1#2{\expandafter\CF_swapunbrace\expandafter{#2}{#1}}% \CF_expafter{}{} donne "*" +\def\CF_eexpafter#1#2{\expandafter\expandafter\expandafter\CF_swapunbrace\expandafter\expandafter\expandafter{#2}{#1}}% \CF_eexpafter{}{} donne "**" +\def\CF_addtomacro#1#2{\CF_expsecond{\def#1}{#1#2}} +\def\CF_eaddtomacro#1#2{\CF_expsecond{\CF_addtomacro#1}{#2}} +\def\CF_preaddtomacro#1#2{\CF_expsecond{\CF_preaddtomacroa#1{#2}}#1} +\def\CF_preaddtomacroa#1#2#3{\def#1{#2#3}} +\def\CF_addtotoks#1#2{#1\expandafter{\the#1#2}} +\def\CF_eaddtotoks#1#2{\expandafter\CF_addtotoks\expandafter#1\expandafter{#2}} +\def\CF_assigntonil#1#2\_nil{\def#1{#2}} +\def\CF_edefaddtomacro#1#2{\CF_expsecond{\CF_addtomacro#1}{\expanded{#2}}} +\def\CF_ifnextchar#1#2#3{% + \let\CF_ifnextchartok=#1% <- espace ind�sirable, bugfix v1.31 + \def\CF_ifnextcharcodetrue{#2}% + \def\CF_ifnextcharcodefalse{#3}% + \futurelet\CF_temptok\CF_ifnextchara +} +\def\CF_ifnextchara{% + \CF_ifx\CF_temptok\CF_sptoken + {\CF_ifnextcharb + } + {\CF_ifx\CF_temptok\CF_ifnextchartok + \CF_ifnextcharcodetrue + \CF_ifnextcharcodefalse + }% +} +\expandafter\def\expandafter\CF_ifnextcharb\space{\futurelet\CF_temptok\CF_ifnextchara} +\def\CF_ifstar#1{\CF_ifnextchar*{\CF_execfirst{#1}}} +\def\CF_testopt#1#2{\CF_ifnextchar[{#1}{#1[{#2}]}} +\def\CF_ifinteger#1{% + \begingroup + \afterassignment\CF_afterinteger + \CF_cntcyclebonds0#1\relax +} +\def\CF_afterinteger#1\relax{% + \endgroup + \CF_ifempty{#1}% +} +\def\CF_iffirsttokmatch#1#2{% est ce que #1 et #2 commencent par les m�mes tokens ? + \futurelet\CF_toksa\CF_gobtonil#1\relax\_nil + \futurelet\CF_toksb\CF_gobtonil#2\relax\_nil + \CF_ifx\CF_toksa\CF_toksb +} +\def\CF_iffirsttokin#1{% teste si le token qui commence #1 appartient aux tokens mis dans #2 + \futurelet\CF_toksa\CF_gobtonil#1\relax\_nil + \CF_iffirsttokina +} +\def\CF_iffirsttokina#1{% + \CF_ifempty{#1} + {\CF_execsecond + } + {\futurelet\CF_toksb\CF_gobtonil#1\relax\_nil + \CF_ifx\CF_toksa\CF_toksb + {\CF_execfirst} + {\CF_expsecond\CF_iffirsttokina{\CF_gobarg#1}}% + }% +} +\def\CF_ifinstr#1#2{% + \def\CF_ifinstra##1#2##2\_nil{% + \ifx\empty##2\empty + \expandafter\CF_execsecond + \else + \expandafter\CF_execfirst + \fi}% + \CF_ifinstra#1\__nil#2\_nil +} +\def\CF_afterspace#1 #2\_nil{#2} + +%--------------------------- Substitution ---------------------------- +\def\CF_ifstartwith#1#2{% #1= #2= + \CF_ifempty{#1}% + {\CF_execsecond + } + {\def\CF_startwithcode{#1}% + \def\CF_startwithpattern{#2}% + \CF_ifstartwitha + }% +} +\def\CF_ifstartwitha{% + \CF_grabfirstarg\CF_startwithcode\CF_firstargcode + \CF_grabfirstarg\CF_startwithpattern\CF_firstargpattern + \CF_ifx\CF_firstargcode\CF_firstargpattern + {\CF_expsecond\CF_ifempty\CF_startwithpattern + {\CF_execfirst + } + {\CF_expsecond\CF_ifempty\CF_startwithcode + \CF_execsecond + \CF_ifstartwitha + }% + } + {\CF_execsecond + }% +} +\def\CF_grabfirstarg#1#2{% + \CF_ifx#1\empty + {\let#2\empty + } + {\def\CF_grabmacro{#2}% + \CF_expsecond\CF_ifbracefirst#1% + {\expandafter\CF_grabbracearg#1\_nil#1} + {\CF_expafter{\futurelet\CF_nexttok\CF_grabfirstarga}#1\_nil#1}% + }% +} +\def\CF_grabfirstarga{% + \CF_ifx\CF_nexttok\CF_sptoken + \CF_grabspacearg + \CF_grabnormalarg +} +\def\CF_grabbracearg#1{% + \expandafter\def\CF_grabmacro{{#1}}% + \CF_grabargassigntonil\relax +} +\expandafter\def\expandafter\CF_grabspacearg\space{% + \expandafter\def\CF_grabmacro{ }% + \CF_grabargassigntonil\relax +} +\def\CF_grabnormalarg#1{% + \expandafter\def\CF_grabmacro{#1}% + \CF_grabargassigntonil\relax +} +\def\CF_grabargassigntonil#1\_nil#2{\CF_expsecond{\def#2}{\CF_gobarg#1}} +\def\CF_ifbracefirst#1{\CF_ifnum{\catcode\CF_threeea`\expandafter\CF_firsttonil\detokenize{#1.}\_nil=1 }} +\def\CF_substonly#1#2{% #1=entier maxi>0 #2=macro : dans la sc#1, remplace tous les par sauf lorsque le motif est suivi d'un caract�re >#1 + \def\CF_atendsubstitute{\edef#2{\the\CF_substtoks}}% macro ex�cut�e � la fin + \let\CF_substnogroups\CF_substnogrouponly + \CF_ifnum{#1>0 } + {\let\CF_testifx\empty + \foreach\CF_x in {1,...,#1} + {\xdef\CF_testifx{\unexpanded\expandafter{\CF_testifx}\unexpanded\expandafter{\expandafter\ifx\CF_x\CF_nexttok1\fi}}}% + \let\CF_testif\empty + \foreach\CF_x in {1,...,#1} + {\xdef\CF_testif{\unexpanded\expandafter{\CF_testif}\unexpanded\expandafter{\expandafter\if\CF_x\CF_nexttok1\fi}}}% + \CF_expsecond\CF_substi#2% + } + {\CF_substall#2% + }% +} +\def\CF_substnogrouponly{% + \CF_exptwomacroargs\CF_ifstartwith\CF_substcode\CF_substsubst + {\CF_grabfirstarg\CF_substcode\CF_temp + \CF_expafter{\futurelet\CF_nexttok\CF_gobtonil}\CF_substcode\relax\_nil + \CF_ifnum{0\CF_testifx=1 }% si le prochain token est \let-�gal � 1...#1 + {\edef\CF_nexttok{\CF_threeea\CF_firsttonil\expandafter\string\CF_substcode\_nil}% le d�tok�niser + \CF_ifnum{0\CF_testif=1 } + {\CF_eaddtotoks\CF_substtoks\CF_temp + \CF_grabfirstarg\CF_substcode\CF_temp + \CF_eaddtotoks\CF_substtoks\CF_temp + } + {\CF_eaddtotoks\CF_substtoks\CF_substpattern + }% + } + {\CF_eaddtotoks\CF_substtoks\CF_substpattern + }% + \CF_substgroups + } + {\CF_expsecond\CF_ifempty\CF_substcode + {\CF_atendsubstitute + } + {\CF_grabfirstarg\CF_substcode\CF_substauxarg + \CF_eaddtotoks\CF_substtoks\CF_substauxarg + \CF_substgroups + }% + }% +} +\def\CF_substall#1{% #1=macro + \def\CF_atendsubstitute{\edef#1{\the\CF_substtoks}}% macro ex�cut�e � la fin + \let\CF_substnogroups\CF_substnogroupall + \CF_expsecond\CF_substi#1% +} +\def\CF_substnogroupall{% + \CF_exptwomacroargs\CF_ifstartwith\CF_substcode\CF_substsubst + {\CF_eaddtotoks\CF_substtoks\CF_substpattern + \CF_grabfirstarg\CF_substcode\CF_temp + \CF_substgroups + } + {\CF_expsecond\CF_ifempty\CF_substcode + {\CF_atendsubstitute + } + {\CF_grabfirstarg\CF_substcode\CF_substauxarg + \CF_eaddtotoks\CF_substtoks\CF_substauxarg + \CF_substgroups + }% + }% +} +\def\CF_substi#1#2#3{% #1= #2= #3= + \def\CF_substcode{#1}\def\CF_substsubst{#2}\def\CF_substpattern{#3}% + \CF_substtoks={}% + \CF_substgroups +} + +\def\CF_substgroups{% + \CF_expsecond\CF_ifbracefirst\CF_substcode + {\CF_grabfirstarg\CF_substcode\CF_substauxarg + \begingroup + \def\CF_atendsubstitute{% + \expandafter\endgroup\expandafter\CF_addtotoks\expandafter\CF_substtoks\expandafter{\expandafter{\the\CF_substtoks}}% + \CF_substgroups + }% + \CF_substtoks{}% initialiser � vide + \expandafter\def\expandafter\CF_substcode\CF_substauxarg + \CF_substgroups + }% + {\CF_substnogroups + }% +} + +%---------------------------- Param�tres ----------------------------- +\def\CF_defifempty#1#2#3{\CF_ifempty{#2}{\def#1{#3}}{\def#1{#2}}} +\defKV[chemfig]{% + atom style = \def\CF_atomstyle {#1}, + chemfig style = \def\CF_chemfigstyle {#1}, + cram width = \CF_defifempty\CF_crambasewidth {#1}{1.5ex}, + cram dash width = \CF_defifempty\CF_cramdashlength {#1}{1pt}, + cram dash sep = \CF_defifempty\CF_cramdashsep {#1}{2pt}, + atom sep = \CF_defifempty\CF_atomsep {#1}{3em}, + bond offset = \CF_defifempty\CF_bondoffset {#1}{2pt}, + double bond sep = \CF_defifempty\CF_doublesep {#1}{2pt}, + angle increment = \CF_defifempty\CF_angleincrement {#1}{45}, + node style = \def\CF_nodestyle {#1}, + bond style = \def\CF_bondstyle {#1}, + cycle radius coeff = \CF_defifempty\CF_cycleradiuscoeff {#1}{0.75}, + stack sep = \CF_defifempty\CF_stacksep {#1}{1.5pt}, + compound style = \def\CF_defaultcompoundstyle {#1}, + compound sep = \CF_defifempty\CF_compoundsep {#1}{5em}, + arrow offset = \CF_defifempty\CF_arrowoffset {#1}{1em}, + arrow angle = \CF_defifempty\CF_arrowangle {#1}{0}, + arrow coeff = \CF_defifempty\CF_arrowlength {#1}{1}, + arrow style = \def\CF_defaultarrowstyle {#1}, + arrow double sep = \CF_defifempty\CF_arrowdoublesep {#1}{2pt}, + arrow double coeff = \CF_defifempty\CF_arrowdoubleposstart{#1}{0.6}, + arrow label sep = \CF_defifempty\CF_arrowlabelsep {#1}{3pt}, + arrow head = \CF_defifempty\CF_arrowhead {#1}{-CF}, + + sep left = \CF_defifempty\CF_signspaceante {#1}{0.5em}, + + sep right = \CF_defifempty\CF_signspacepost {#1}{0.5em}, + + vshift = \CF_defifempty\CF_signvshift {#1}{0pt} +} +\def\setchemfig{\setKV[chemfig]} +\def\resetchemfig{\restoreKV[chemfig]} +\setKVdefault[chemfig]{% + atom style = {},% code tikz mis � la fin de every node/.style + chemfig style = {},% code tikz mis � la fin de l'arugment optionnel de \tikzpicture + bond join = false, + fixed length = false, + cram rectangle = false, + cram width = 1.5ex, + cram dash width = 1pt, + cram dash sep = 2pt, + atom sep = 3em, + bond offset = 2pt, + double bond sep = 2pt, + angle increment = 45, + node style = {}, + bond style = {}, + cycle radius coeff = 0.75, + stack sep = 1.5pt, + autoreset cntcycle = true, + show cntcycle = false, + debug =false, + scheme debug = false, + compound style = {}, + compound sep = 5em, + arrow offset = 1em, + arrow angle = 0, + arrow coeff = 1, + arrow style = {}, + arrow double sep = 2pt, + arrow double coeff = 0.6, + arrow double harpoon= true, + arrow label sep = 3pt, + arrow head = -CF, + + sep left = 0.5em, + + sep right = 0.5em, + + vshift = 0pt, +}% + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%%% D E S S I N M O L � C U L E S %%% +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +\def\CF_sanitizecatcode{% + \CF_makeother\[\CF_makeother\]\CF_makeother\:\CF_makeother\(\CF_makeother\)% + \CF_makeother\,\CF_makeother\-\CF_makeother\=\CF_makeother\~\CF_makeother\!% + \CF_makeother\?\CF_makeother\<\CF_makeother\>\CF_makeother\;\CF_makeother\*% + \CF_makeother\|\CF_makeother\#\CF_makeother\@% +} + +\def\printatom#1{\ifmmode\rm#1\else$\rm#1$\fi} + +\def\CF_nodecontent{\CF_expsecond\printatom{\csname atom_\number\CF_cntatom\endcsname\CF_nodestrut}} + +\def\chemskipalign{% + \CF_doifempty\CF_bondoutcontentsaved% sauf si un \chemskipalign a �t� fait � l'atome pr�c�dent + {\global\let\CF_bondoutcontentsaved\CF_bondoutcontent}% sauvegarder l'atome d'o� vient la liaison + \let\CF_nodestrut\empty +} + +\def\definesubmol{\CF_definesubmoltrue\def_submol} +\def\redefinesubmol{\CF_definesubmolfalse\def_submol} + +\def\def_submol#1{% + \CF_cntatomgroup=0 % nombre d'arguments suppos� + \def\CF_temp{#1}% nom + \futurelet\CF_toksa\CF_submoltestnxttok +} + +\def\CF_submoltestnxttok{% + \if[\noexpand\CF_toksa\expandafter\CF_execfirst\else\expandafter\CF_execsecond\fi + {\begingroup\CF_sanitizecatcode\CF_expsecond\CF_submolgrabopt{\CF_temp}% + } + {\afterassignment\CF_submoltestnxttoka% pas d'argument entre crochet + \CF_cntatomgroup=0% cherche le nombre d'arguments �ventuels + }% +} + +\def\CF_submoltestnxttoka{\futurelet\CF_toksa\CF_submoltestnxttokb} + +\def\CF_submoltestnxttokb{% + \if[\noexpand\CF_toksa\expandafter\CF_execfirst\else\expandafter\CF_execsecond\fi + {\begingroup\CF_sanitizecatcode\CF_expsecond\CF_submolgrabopt{\CF_temp}} + {\CF_expsecond{\def_submola}\CF_temp{}}% +} + +\def\CF_submolgrabopt#1[#2]#{\endgroup\def_submola{#1}{#2}} + +\def\def_submola#1{% #1 nom + \CF_ifnum{0\CF_ifnum{\CF_cntatomgroup<0 }1{\CF_ifnum{\CF_cntatomgroup>9 }10}>0 } + {\CF_error{Invalid number of arguments in submol \detokenize\expandafter{\string#1}. Defining it with 0 argument}% + \CF_cntatomgroup=0 + } + {}% + \ifcat\relax\expandafter\noexpand\CF_firsttonil#1\_nil\expandafter\CF_execfirst\else\expandafter\CF_execsecond\fi% si #1 est une s�quence de contr�le + {\expandafter\ifdefined\CF_firsttonil#1\_nil + \ifCF_definesubmol + \CF_warning{the submol \expandafter\string\CF_firsttonil#1\_nil\space is already defined, the previous definition is lost}% + \fi + \fi + \begingroup + \CF_sanitizecatcode + \def_submolb{#1}% + } + {\ifcsname CF__#1\endcsname + \ifCF_definesubmol + \CF_warning{the submol "#1" is already defined, the previous definition is lost}% + \fi + \fi + \begingroup + \CF_sanitizecatcode + \expandafter\def_submolb\csname CF__#1\endcsname + }% +} + +\def\def_submolb#1#2#3{% #1 nom sous forme de macro, #2 = code si liaison arrive de droite , #3 = code si liaison arrive de gauche, \CF_cntatomgroup = nombre d'arguments + \def\CF_tempa{#2}\CF_doifnotempty{#2}{\CF_expsecond{\CF_expsecond\CF_substonly{\number\CF_cntatomgroup}\CF_tempa}{\CFhash}{\CFhash}}% + \def\CF_tempb{#3}\CF_expsecond{\CF_expsecond\CF_substonly{\number\CF_cntatomgroup}\CF_tempb}{\CFhash}{\CFhash}% + \CF_expsecond{\CF_expsecond{\def_submolc{#1}}\CF_tempa}\CF_tempb +} + +\def\def_submolc#1#2#3{% #1 nom sous forme de macro, #2 = code si liaison arrive de droite , #3 = code si liaison arrive de gauche, \CF_cntatomgroup = nombre d'arguments + \endgroup + \begingroup + \global\toks0{\gdef\CFthesubmol}% + \CF_ifnum{\CF_cntatomgroup>0 } + {\foreach\CF_x in {1,...,\CF_cntatomgroup}{% + \global\toks0\expandafter{\expanded{\the\toks0\CFhash\CF_x}}% + }% + } + {}% + \CF_sanitizecatcode \catcode`\#6 \endlinechar-1 \everyeof{\noexpand}% + \CF_ifempty{#2}% + {\scantokens\expandafter{\the\toks0{\empty#3}}% + }% + {\scantokens\expandafter{% + \the\toks0{% + \expanded{% bugfix 1.52 + \csname CF_exec% + \ifdim\csname CF_currentangle\endcsname pt>90pt + \ifdim\csname CF_currentangle\endcsname pt<270pt + first% + \else + second% + \fi + \else + second% + \fi + \endcsname + {\unexpanded{#2}}{\unexpanded{#3}}% + }% + }% + }% + }% + \endgroup + \let#1\CFthesubmol +} + +\def\CF_seeknode#1#2#3{% cherche un noeud au d�but de #1 l'assigne dans la sc #2 et met le reste dans #3 + \let#2\empty + \def#3{#1}% + \CF_iffirsttokmatch{#1}{ }% + {\CF_expsecond\CF_seeknodea{\romannumeral-`\.\noexpand#1}#2#3}% ignore les espaces au d�but du groupe d'atome + {\CF_seeknodea{#1}#2#3}% +} + +\def\CF_seeknodea#1#2#3{% + \CF_ifempty{#1}% + {\let#3\empty + } + {\futurelet\CF_toksa\CF_gobtonil#1\relax\_nil + \CF_ifx\CF_toksa\CF_sptoken + {\CF_addtomacro#2{ }% + \CF_expsecond\CF_seeknodea{\CF_afterspace#1\_nil}#2#3% + }% + {\CF_ifx\CF_toksa\bgroup + {\CF_eaddtomacro#2{\expandafter{\CF_firsttonil#1\_nil}}% + \CF_expsecond\CF_seeknodea{\CF_gobarg#1}#2#3% + }% + {\CF_ifx!\CF_toksa% Bugfix v1.5 + {\def\CF_seeksubmloltemp{#1}% + \CF_seeksubmola + \CF_expsecond\CF_seeknodea\CF_seeksubmloltemp#2#3% + } + {\CF_iffirsttokina{-=(*<>~}% + {\def#3{#1}% + }% + {\CF_eaddtomacro#2{\CF_firsttonil#1\_nil}% + \CF_expsecond\CF_seeknodea{\CF_gobarg#1}#2#3% + }% + } + }% + }% + }% +} + +% on sait que #1 commence par -,=,~,<,>. On analyse cette liaison +% #2 re�oit le type de liaisons (1 pour -, 2 pour =, 3 pour ~) +\def\CF_assignbondcode#1#2{% + \futurelet\CF_toksa\CF_gobtonil#1\_nil + \edef#2{% + \ifx-\CF_toksa1\else + \ifx=\CF_toksa2\else + \ifx~\CF_toksa3\else + \ifx>\CF_toksa4\else + \ifx<\CF_toksa5\else0% si 0 --> il y a une erreur non due � l'utilisateur + \fi\fi\fi\fi\fi}% + \ifnum#2>3 % si c'est une liaison de Cram + \CF_expafter{\futurelet\CF_toksa\CF_gobtonil}{\CF_gobarg#1\_nil}% chope le caract�re suivant + \CF_ifx:\CF_toksa + {\edef#2{\number\numexpr#2+2}% si c 'est un ":", signe du pointill�, ajoute 2 + }% + {\CF_ifx|\CF_toksa% si c 'est un "|", signe du triangle �vid�, ajouter 4 + {\edef#2{\number\numexpr#2+4}} + {}% + }% + \fi +} + +\def\CF_grabbondoffseta#1,#2\_nil{% + \def\CF_startoffset{#1}\def\CF_endoffset{#2}% +} + +\def\CF_grabbondoffset#1(#2)#3\_nil{% + \CF_doifnotempty{#2}% + {\CF_ifinstr{#2},% + {\CF_grabbondoffseta#2\_nil}% + {\def\CF_startoffset{#2}}% + }% + \def\CF_remainafterbond{#3}% +} + +\def\CF_analysebond#1#2{% + \CF_assignbondcode{#1}#2% + \CF_expsecond{\def\CF_remainafterbond}{\CF_gobarg#1}%mange le premier signe de la liaison + \let\CF_doublebondtype\CF_zero + \ifnum#2=2 % si c'est une double liaison, regarde s'il y a un + ou - derri�re + \CF_expafter{\futurelet\CF_toksa\CF_gobtonil}{\CF_gobarg#1\_nil}% + \CF_ifx^\CF_toksa + {\def\CF_doublebondtype{1}% + \CF_expsecond{\def\CF_remainafterbond}{\CF_gobtwoargs#1}% mange le "^" + } + {\expandafter\ifx\CF_underscore\CF_toksa + \def\CF_doublebondtype{2}% + \CF_expsecond{\def\CF_remainafterbond}{\CF_gobtwoargs#1}% mange le "_" + \fi + }% + \else + \ifnum#2>5 % si c'est une laision de Cram pointill�e ou triangle �vid� + \CF_expsecond{\def\CF_remainafterbond}{\CF_gobtwoargs#1}% mange un caract�re de plus + \fi + \fi + \CF_expsecond\CF_iffirsttokmatch\CF_remainafterbond\CFhash + {\CF_eexpsecond\CF_iffirsttokmatch{\expandafter\CF_gobarg\CF_remainafterbond.}(%si parenth�se juste apr�s + {\expandafter\CF_grabbondoffset\CF_remainafterbond\_nil} + {}% + }% + {}% + \CF_expsecond\CF_iffirsttokmatch\CF_remainafterbond @% + {\expandafter\CF_grabmovearg\CF_remainafterbond\_nil}% + {}% + \CF_expsecond\CF_iffirsttokmatch{\CF_remainafterbond}[% + {\expandafter\CF_analyseoptarg\CF_remainafterbond\_nil\CF_remainafterbond + }% + {\let\CF_currentstringangle\CF_defaultstringangle + \let\CF_currentlength\CF_defaultlength + \let\CF_currentfromatom\CF_defaultfromatom + \let\CF_currenttoatom\CF_defaulttoatom + \let\CF_currenttikz\CF_defaulttikz + \let\CF_movebondname\empty + }% + \ifCF_incycle + \pgfmathsetmacro\CF_cycleincrementangle{360/\CF_cyclenum+\CF_initcycleangle}% + \edef\CF_currentstringangle{::+\CF_cycleincrementangle}% + \def\CF_initcycleangle{0}% + \let\CF_currentlength\CF_defaultlength% et on ignore la longueur de liaison sp�cifi�e + \fi + \CF_expsecond\CF_setbondangle{\CF_currentstringangle}\CF_currentangle +} + +\def\CF_setbondangle#1#2{% le code de la direction est contenu dans #1, en sortie, #2 contient l'angle + \CF_ifempty{#1}% + {\let#2\CF_defaultangle + } + {\if:\expandafter\noexpand\CF_firsttonil#1\_nil + \if:\CF_threeea\noexpand\expandafter\CF_firsttonil\CF_gobarg#1\_nil + \pgfmathsetmacro#2{\CF_previousangle+\expandafter\CF_gobarg\CF_gobarg#1}% + \else + \pgfmathsetmacro#2{\CF_gobarg#1}% + \fi + \else + \pgfmathsetmacro#2{#1*\CF_angleincrement}% + \fi% puis normalise l'angle entre 0 et 360 + \ifdim\ifdim#2pt<0pt -\fi#2pt>360pt + \pgfmathsetmacro#2{#2-360*floor(#2/360)}% + \fi% si |#2|>360 + \ifdim#2pt<0pt + \pgfmathsetmacro#2{#2+360}% + \fi + }% +} + +\def\CF_analysemovearg#1,#2\_nil#3{% + \def#3{#1}\def\CF_movebondcoeff{#2}% +} + +% Argument limit�s l�gitimes ici car #2 (qui est ce qui suit "@{}" dans l'argument optionnel) ne DOIT PAS +% commencer par une accolade. +\def\CF_grabmovearg @#1#2\_nil{% + \CF_ifinstr{#1},% + {\CF_analysemovearg#1\_nil\CF_movebondname}% + {\def\CF_movebondname{#1}\def\CF_movebondcoeff{0.5}}% + \def\CF_remainoptarg{#2}% +} + +\def\CF_testemptyandassign#1#2#3{% + \CF_ifempty{#2} + {\let#1#3} + {\def#1{#2}}% +} + +\def\CF_parseoptlist#1,#2,#3,#4,#5\_nil{% + \CF_testemptyandassign\CF_currentstringangle{#1}\CF_defaultstringangle + \CF_testemptyandassign\CF_currentlength {#2}\CF_defaultlength + \CF_testemptyandassign\CF_currentfromatom {#3}\CF_defaultfromatom + \CF_testemptyandassign\CF_currenttoatom {#4}\CF_defaulttoatom + \CF_expsecond{\CF_testemptyandassign\CF_currenttikz}{\CF_sanitizelastitem#5,\empty\_nil}\CF_defaulttikz +}% + +\def\CF_analyseoptarg[#1]{% + \CF_doifnotempty{#1}% + {\CF_iffirsttokmatch{#1}{@}% + {\CF_grabmovearg#1\_nil + } + {\let\CF_movebondname\empty + \def\CF_remainoptarg{#1}% + }% + \expandafter\CF_parseoptlist\CF_remainoptarg,\empty,\empty,\empty,\empty\_nil + }% + \CF_analyseoptarga\relax +} + +\def\CF_analyseoptarga#1\_nil#2{% + \CF_expsecond{\def#2}{\CF_gobarg#1}% +} + +\def\CF_seeksubmol#1#2{% cherche et remplace ! au d�but de #1. #1=code #2=macro recevant le r�sultat + \def\CF_seeksubmloltemp{#1}% + \CF_seeksubmola + \let#2\CF_seeksubmloltemp +} + +\def\CF_seeksubmola{% + \CF_expsecond{\def\CF_seeksubmloltemp}{\romannumeral-`\.\expandafter\noexpand\CF_seeksubmloltemp}% + \CF_expsecond\CF_iffirsttokmatch{\CF_seeksubmloltemp}!% + {\CF_eexpsecond{\def\CF_seeksubmloltemp}{\expandafter\CF_gobarg\CF_seeksubmloltemp}% enl�ve le "!" + \CF_ifx\empty\CF_seeksubmloltemp + {\CF_error{no submol name found after "!"}} + {}% + \ifcat\relax\CF_threeea\noexpand\expandafter\CF_firsttonil\CF_seeksubmloltemp*\_nil + \expandafter\CF_seeksubmolb\CF_seeksubmloltemp\_nil + \else + \expandafter\CF_seeksubmolc\CF_seeksubmloltemp\_nil + \fi + \CF_seeksubmola + }% + {}% +} + +\def\CF_seeksubmolb#1{\CF_seeksubmold#1\relax} + +\def\CF_seeksubmolc#1{\expandafter\CF_seeksubmold\csname CF__#1\endcsname\relax}% nom de la sous mol�cule + +\def\CF_seeksubmold#1#2\_nil{%#1=macro de la sous mol�cule #2=reste du code commen�ant par \relax + \CF_expsecond{\CF_eexpsecond{\def\CF_seeksubmloltemp}}{\expandafter#1\CF_gobarg#2}% supprime le \relax puis ajoute la macro au d�but et la 2-d�veloppe +} + +\def\CF_insertemptygroup#1{% ins�re {} au d�but de la sc #1 + \CF_expsecond{\def#1}{\expandafter{\expandafter}#1}% +} + +\def\chemfig{\CF_testopt\CF_chemfiga{}} + +\def\CF_chemfiga[#1]{% + \begingroup + \CF_sanitizecatcode + \CF_exptwomacroargs\CF_chemfigb\CF_begintikzpicture\CF_endtikzpicture[#1]% +} + +\def\CF_chemfigb#1#2[#3]#4{% + \endgroup + \begingroup + \setchemfig{#3}% + \CF_ifinsidetikz + {\pgfinterruptpicture + \let\CF_atendofchemfig\endpgfinterruptpicture + } + {\let\CF_atendofchemfig\relax + }% + \expanded{% d�but du tikzpicture + \unexpanded{#1}[% + remember picture,% + every node/.style={% + anchor=base,% + inner sep=0pt,% + outer sep=0pt,% + minimum size=0pt,% + \unexpanded\expandafter{\CF_atomstyle}% + },% + baseline,% + \unexpanded\expandafter{\CF_chemfigstyle}% + ]% + }% + \begingroup% \endgroup rajout� en sortie de trac� par \CF_chemfigd + \let\CF_hooklist\empty + \ifboolKV[chemfig]{fixed length} + {\CF_macrofixedbondlengthtrue} + {\CF_macrofixedbondlengthfalse}% + \ifboolKV[chemfig]{bond join} + {\let\CF_drawaxisbond\CF_drawaxisbondjoin} + {\let\CF_drawaxisbond\CF_drawaxisbondnojoin}% + \ifboolKV[chemfig]{cram rectangle} + {\let\CF_clipcramornot\CF_gobtikzinstruction} + {\let\CF_clipcramornot\clip}% + \CF_incyclefalse + \CF_cntgroup0 + \ifboolKV[chemfig]{autoreset cntcycle} + {\global\CF_cntcycle0 } + {}% + \let\CF_lastaction\CF_zero% 0=d�but du dessin 1=trac� d'un noeud 2=trac� d'une liaison + \let\CF_startoffset\empty + \let\CF_endoffset\empty + \let\CF_bondoutcontentsaved\empty + \def\CF_cycleanglecorrection{180/\CF_cyclenum}% + \def\CF_defaultangle{0}% + \def\CF_defaultstringangle{:0}% angle pris par d�faut si le champ est vide + \def\CF_defaultlength{1}% + \let\CF_defaultfromatom\empty% numero de l'atome d'o� partent les liaisons par d�faut + \let\CF_defaulttoatom\empty% num�ro de l'atome o� arrivent les laisons par d�faut + \let\CF_defaulttikz\empty + \let\CF_previousbondangle\empty + \let\CF_joinbond\CF_zero + \let\CF_previoustikz\empty + \everyeof{\_nil}\endlinechar-1 + \CF_sanitizecatcode + \expandafter\CF_assigntonil\expandafter\CF_molecule\scantokens{#4}% + \CF_expsecond{\CF_substall\CF_molecule}\CFhash\CFhash + \CF_expsecond\CF_chemfigc{\CF_molecule}% + %\endgroup <-- rajout� par \CF_chemfigd + #2% fin du tikzpicture + \CF_atendofchemfig + \endgroup + \let\CF_flipstate\CF_zero +} + +\def\CF_chemfigc#1{% #1 est le code de la mol�cule + \ifnum\CF_lastaction=3 + \ifCF_incycle + \def\CF_defaultangle{0}% + \else + \ifnum\CF_cntcyclebonds=0 % si c'est le d�but d'un cycle + \pgfmathsetmacro\CF_defaultangle{\CF_previousangle+180+\CF_cycleanglecorrection}% on met la liaison � +180� + correction + \else + \pgfmathsetmacro\CF_defaultangle{\CF_previousangle-90+180/\CF_cyclenum}% sinon � la bissectrice du sommet du cycle + \fi + \fi + \let\CF_defaultstringangle\empty + \fi + \let\CF_currentangle\CF_defaultangle + \def\CF_molecule{#1}% + \CF_expsecond\CF_seeksubmol\CF_molecule\CF_molecule% alias en premier ? + \if[\CF_threeea\noexpand\expandafter\CF_firsttonil\CF_molecule\_nil + \expandafter\CF_analyseoptarg\CF_molecule\_nil\CF_molecule + \CF_expsecond\CF_setbondangle{\CF_currentstringangle}\CF_currentangle + \let\CF_defaultangle\CF_currentangle + \let\CF_previousangle\CF_currentangle + \CF_doifnotempty\CF_currentstringangle{\let\CF_defaultangle\CF_currentangle}% + \CF_doifnotempty\CF_currentlength {\let\CF_defaultlength\CF_currentlength}% + \CF_doifnotempty\CF_currentfromatom {\let\CF_defaultfromatom\CF_currentfromatom}% + \CF_doifnotempty\CF_currenttoatom {\let\CF_defaulttoatom\CF_currenttoatom}% + \CF_doifnotempty\CF_currenttikz {\let\CF_defaulttikz\CF_currenttikz}% + \CF_expsecond\CF_seeksubmol\CF_molecule\CF_molecule + \fi + \edef\CF_defaultstringangle{:\CF_defaultangle}% + \let\CF_currentlength\CF_defaultlength + \let\CF_currentfromatom\CF_defaultfromatom + \let\CF_currenttoatom\CF_defaulttoatom + \let\CF_currenttikz\CF_defaulttikz + \ifCF_incycle% si on commence un cycle + \let\CF_currentangle\CF_previousangle + \pgfmathsetmacro\CF_cyclearcinitangle{\CF_currentangle+\CF_initcycleangle+180/\CF_cyclenum+90}% + \pgfmathsetmacro\CF_centeroffset{\CF_currentlength*\CF_atomsep/(2*sin(180/\CF_cyclenum))}% + \node[at=(\CF_bondoutnode),shift=(\CF_cyclearcinitangle:\CF_centeroffset pt),anchor=center](cyclecenter\number\CF_cntcycle){};% le centre du cycle + \ifboolKV[chemfig]{show cntcycle} + {\node[at=(cyclecenter\number\CF_cntcycle),anchor=center,overlay]{\tiny\number\CF_cntcycle};} + {}% + \ifCF_cyclearc% on doit tracer l'arc de cercle dans le cycle ? + \pgfmathsetmacro\CF_cyclearcradius{\CF_cycleradiuscoeff*\CF_currentlength*\CF_atomsep/(2*tan(180/\CF_cyclenum))}% + \node[at=(cyclecenter\number\CF_cntcycle),shift=(\CF_cyclearcstartangle:\CF_cyclearcradius pt)](initarc){};% le d�but de l'arc + \CF_expafter{\draw[}\CF_cyclearcdirecttikz](initarc) arc (\CF_cyclearcstartangle:\CF_cyclearcendangle:\CF_cyclearcradius pt);% + \fi + \else + \let\CF_currentangle\CF_defaultangle + \fi + \ifnum\CF_lastaction=0 + \let\CF_previousangle\CF_defaultangle + \node(CF_node){}; + \CF_expsecond\CF_iffirsttokin{\CF_molecule}{-=(*~?<>}% + {\CF_insertemptygroup\CF_molecule}% + {}% + \fi + \CF_chemfigd +} + +\def\CF_chemfigd{% + \let\CF_nextaction\CF_chemfigd% � priori, on reboucle + \CF_ifx\CF_molecule\empty + {\let\CF_nextaction\endgroup + } + {\CF_expsecond\CF_seeknode{\CF_molecule}\CF_currentatomgroup\CF_molecule + \CF_ifx\empty\CF_currentatomgroup% pas de noeud pour commencer ? + {\def\CF_bondoutnode{% + n\CF_lastgroupnumber-% + \ifx\CF_currentfromatom\empty + \ifdim\CF_currentangle pt<90pt + \number\CF_cntatomgroup + \else + \ifdim\CF_currentangle pt>270pt + \number\CF_cntatomgroup + \else + 1% + \fi + \fi + \else + \CF_currentfromatom + \fi}% + \CF_expafter{\futurelet\CF_toksa\CF_gobtonil}{\CF_molecule\relax\_nil}% + \CF_iffirsttokina{-=<>~}% la suite est une liaison + {\ifnum\CF_lastaction=2 % c'est la deuxi�me liaison cons�cutive ? + \CF_insertemptygroup\CF_molecule% ins�re un groupe vide + \edef\CF_bondoutnode{\CF_bondoutnode}% + \else + \ifCF_incycle + \advance\CF_cntcyclebonds1 + \fi + \CF_expsecond\CF_analysebond{\CF_molecule}\CF_bondtype + \edef\CF_bondoutnode{\CF_bondoutnode}% + \let\CF_molecule\CF_remainafterbond + \ifCF_incycle + \ifnum\CF_cntcyclebonds=\CF_cyclenum\relax + \CF_threeea\CF_execfirst + \else + \ifnum\CF_cntcyclebonds=1 + \let\CF_cyclefirsttikz\CF_currenttikz + \CF_doifnotempty\CF_startoffset{\let\CF_cyclejoinlast\CF_zero}% + \fi + \CF_threeea\CF_execsecond + \fi + \else + \expandafter\CF_execsecond + \fi + {\let\CF_nextaction\endgroup + \CF_drawbond\CF_bondtype{\CF_bondoutnode}{\CF_hookcycle}\CF_previousatomgroup\CF_hookatomgroup + }% + {\node[at=(\CF_bondoutnode\ifCF_incycle\else\ifCF_macrofixedbondlength.\CF_currentangle\fi\fi),shift=(\ifcase\CF_flipstate\or180-\or-\fi\CF_currentangle:\CF_currentlength*\CF_atomsep)](CF_node){}; + \let\CF_previousangle\CF_currentangle + \def\CF_lastaction{2}% + }% + \fi + \ifcat\relax\detokenize\expandafter{\romannumeral-`\.\expandafter\noexpand\CF_molecule}\relax + % s'il ne reste plus rien apr�s la liaison (sans tenir compte de l'espace devant)-> ins�re un groupe vide + \CF_insertemptygroup\CF_molecule + \fi + }% + {\edef\CF_bondoutnode{\CF_bondoutnode}% �value le l'atome de d�part de liaison + \CF_ifx(\CF_toksa% une parenth�se pour commencer ? + {\ifnum\CF_lastaction=2 % il y avait une liaison juste avant ? + \CF_insertemptygroup\CF_molecule + \else + \CF_expsecond\CF_grabsubmol{\CF_molecule}% + \begingroup + \ifCF_incycle\def\CF_lastaction{3}\fi% on �tait dans un cycle + \CF_incyclefalse + \aftergroup\CF_chemfigd + \def\CF_nextaction{\CF_expsecond\CF_chemfigc{\CF_molinparen}}% + \fi + }% + {\CF_ifx\CF_molecule\empty + {\let\CF_nextaction\endgroup + } + {% ce qui reste apr�s le noeud courant n'est pas vide, ne commence pas par "-=~", ni par une parenth�se + \CF_ifx*\CF_toksa% un cycle ? + {\ifnum\CF_lastaction=2 + \CF_insertemptygroup\CF_molecule% ins�re un groupe vide + \else + \ifCF_incycle + \def\CF_lastaction{3}% + \fi% on �tait dans un cycle + \ifnum\CF_lastaction=3 + \let\CF_lastcyclenum\CF_cyclenum + \fi + \CF_eexpsecond\CF_iffirsttokmatch{\expandafter\CF_gobarg\CF_molecule}*% + {\CF_eexpsecond{\def\CF_molecule}{\expandafter\CF_gobarg\CF_molecule}% enl�ve la 1er �toile + \CF_eexpsecond\CF_iffirsttokmatch{\expandafter\CF_gobarg\CF_molecule}[% un crochet ensuite ? + {\expandafter\CF_cycleparsepreamblewithoptarg\CF_molecule\_nil% \begingroup inclus + }% + {\def\CF_cyclearcstartangle{0}\def\CF_cyclearcendangle{360}% + \let\CF_cyclearcdirecttikz\empty + \expandafter\CF_cycleparsepreamble\CF_molecule\_nil% \begingroup inclus + }% + \CF_cyclearctrue + }% + {\expandafter\CF_cycleparsepreamble\CF_molecule\_nil% \begingroup inclus + \CF_cyclearcfalse + }% + \CF_cntcyclebonds0 + \edef\CF_hookcycle{\CF_bondoutnode}% + \let\CF_hookatomgroup\CF_previousatomgroup + \CF_ifzerodim\CF_hookatomgroup + {\def\CF_cyclejoinlast{1}}% joindre le dernier + {\def\CF_cyclejoinlast{0}}% + \CF_incycletrue + \global\advance\CF_cntcycle1 + \ifnum\CF_lastaction=3 + \pgfmathsetmacro\CF_initcycleangle{360/\CF_lastcyclenum-180}% c'est un cycle dans un cycle + \else + \pgfmathsetmacro\CF_initcycleangle{-180/\CF_cyclenum-90+\CF_cycleanglecorrection}% + \fi + \aftergroup\CF_chemfigd + \def\CF_nextaction{\CF_expsecond\CF_chemfigc{\CF_molinparen}}% + \fi + }% + {\CF_error{something went wrong here: \detokenize\expandafter{\CF_molecule}^^JIf you think it's a bug, please, send a Minimal Example to the author}% + }% + }% + }% + }% + }% + {\CF_expthreemacroargs\CF_drawatomgroup\CF_currentangle\CF_currenttoatom\CF_currentatomgroup + }% + }% + \CF_nextaction +} + +\def\CF_cycleparsepreamble*#1#2\_nil{% + \ifnum#1<3 + \CF_error{a cycle must be at least a triangle.^^JThe number following "*" must be 3 or more}% + \fi + \def\CF_molecule{#2}% + \CF_expsecond\CF_grabsubmol{\CF_molecule}% + \begingroup + \def\CF_cyclenum{#1}% +} + +\def\CF_cycleparsepreamblewithoptarg*[#1]#2#3\_nil{% + \CF_cycleparseoptarg#1,\empty,\empty,\empty\_nil + \CF_cycleparsepreamble*#2#3\_nil +} + +\def\CF_cycleparseoptarg#1,#2,#3\_nil{% + \CF_ifempty{#1} + {\def\CF_cyclearcstartangle{0}} + {\def\CF_cyclearcstartangle{#1}}% + \CF_ifempty{#2} + {\def\CF_cyclearcendangle{360}} + {\def\CF_cyclearcendangle{#2}}% + \CF_expsecond{\def\CF_cyclearcdirecttikz}{\CF_sanitizelastitem#3,\empty\_nil}% +} + +\def\CF_grabsubmol#1{% + \begingroup + \catcode`(1 \catcode`)2 + \CF_threeea + \endgroup + \expandafter\CF_grabsubmola\scantokens{\relax#1}% +} + +\def\CF_grabsubmola#1\_nil{% + \expandafter\CF_assigntonil\expandafter\CF_molecule\scantokens\CF_threeea{\expandafter\CF_gobarg \CF_gobarg#1}% + \expandafter\CF_assigntonil\expandafter\CF_molinparen\scantokens\CF_threeea{\expandafter\CF_firsttonil\CF_gobarg#1\_nil}% +} + +\def\CF_ifcarisupperletter#1{% + \ifcat\relax\noexpand#1% + \let\CF_next\CF_execsecond% faux si c'est une sc + \else + \ifnum`#1<`A + \let\CF_next\CF_execsecond + \else + \ifnum`#1>`Z + \let\CF_next\CF_execsecond + \else + \let\CF_next\CF_execfirst + \fi + \fi + \fi + \CF_next +} + +% Cr�� 4 noeuds au dessus et au dessous des noeuds #1 et #2 +% � une distance de #3 du noeud #1 et #4 du noeud #2 +\def\CF_createnormnodes#1#2#3#4{% + \CF_doifnotempty{#3} + {\node[shape=coordinate,at=(#1),xshift=#3*\CF_normx,yshift=#3*\CF_normy](#11){}; + \node[shape=coordinate,at=(#1),xshift=-#3*\CF_normx,yshift=-#3*\CF_normy](#12){}; + }% + \CF_doifnotempty{#4} + {\node[shape=coordinate,at=(#2),xshift=#4*\CF_normx,yshift=#4*\CF_normy](#21){}; + \node[shape=coordinate,at=(#2),xshift=-#4*\CF_normx,yshift=-#4*\CF_normy](#22){}; + }% +} + +\def\CF_distancebetweenpoints#1#2#3#4#5{% + \pgfextractx\CF_dim{\pgfpointanchor{#1}{#2}}\edef\CF_dimax{\the\CF_dim}% + \pgfextracty\CF_dim{\pgfpointanchor{#1}{#2}}\edef\CF_dimay{\the\CF_dim}% + \pgfextractx\CF_dim{\pgfpointanchor{#3}{#4}}\edef\CF_dimbx{\the\CF_dim}% + \pgfextracty\CF_dim{\pgfpointanchor{#3}{#4}}\edef\CF_dimby{\the\CF_dim}% + \pgfmathsetmacro#5{veclen(\CF_dimbx-\CF_dimax,\CF_dimby-\CF_dimay)}% +} + +\def\CF_computenodevect#1#2{% + \CF_distancebetweenpoints{#1}{center}{#2}{center}\CF_vectorlen + \ifthenelse{\equal{\CF_vectorlen}{0.0}}{% + %\directlua{log.warn("CF_computenodevect", [[#1]]..","..[[#2]])} + \pgfmathsetmacro\CF_normx{0.0}% + \pgfmathsetmacro\CF_normy{0.0}% + }{% + \pgfmathsetmacro\CF_normx{(\CF_dimay-\CF_dimby)/\CF_vectorlen}% + \pgfmathsetmacro\CF_normy{(\CF_dimbx-\CF_dimax)/\CF_vectorlen}% + }% +} + +\def\CF_setoffset#1#2{% + \CF_doifempty#1{% + \CF_ifzerodim{#2} + {\def#1{0pt}} + {\edef#1{\CF_bondoffset}}% + }% +} + +\def\CF_drawbond#1#2#3#4#5{% #1=type de liaison #2 et #3:nom de noeuds de d�but et fin #4 et #5: contenu des atomes de d�but et fin + \CF_setoffset\CF_startoffset#4% + \CF_setoffset\CF_endoffset#5% + \let\CF_currentbondstyle\CF_bondstyle + \CF_doifnotempty\CF_currenttikz{\CF_eaddtomacro\CF_currentbondstyle{\expandafter,\CF_currenttikz}}% + \path(#2)--(#3)coordinate[pos=0](#2@)coordinate[pos=1](#3@);% + \CF_computenodevect{#2@}{#3@}% + \ifthenelse{\equal{\CF_vectorlen}{0.0}}{% + %\directlua{log.warn("CF_drawbond", [[\CF_startoffset]]..","..[[1-\CF_endoffset]])} + \pgfmathsetmacro\CF_startcoeff{\CF_startoffset}% + \pgfmathsetmacro\CF_endcoeff{1-\CF_endoffset}% + }{% + \pgfmathsetmacro\CF_startcoeff{\CF_startoffset/\CF_vectorlen}% + \pgfmathsetmacro\CF_endcoeff{1-\CF_endoffset/\CF_vectorlen}% + }% + \path(#2@)--(#3@)coordinate[pos=\CF_startcoeff](#2@@)coordinate[pos=\CF_endcoeff](#3@@);% + \CF_doifnotempty\CF_movebondname% on doit poser un noeud sur la liaison + {\path(#2@@)--(#3@@)coordinate[overlay,pos=\CF_movebondcoeff](\CF_movebondname); + \let\CF_movebondname\empty + }% + \ifcase#1\relax + \CF_error{unknown bond type, this error should not occur^^JIf you think it's a bug, send a Minimal Example to the author}% + \or% 1 = liaison simple + \CF_drawaxisbond{#2}{#3}% trace la liaison simple dans l'axe + \or% 2 = liaison double + \ifCF_incycle + \ifnum\CF_doublebondtype=0 + \def\CF_doublebondtype{1}% + \fi + \ifnum\CF_flipstate>0 + \def\CF_doublebondtype{2}% + \fi + \pgfmathsetmacro\CF_doublebondlengthcorrection{\CF_doublesep*tan(180/\CF_cyclenum)}% + \fi + \ifcase\CF_doublebondtype + \CF_createnormnodes{#2@@}{#3@@}{\CF_doublesep/2}{\CF_doublesep/2}% + \CF_drawbonda(#2@@1)--(#3@@1); + \CF_drawbonda(#2@@2)--(#3@@2); + \let\CF_joinbond\CF_zero + \or + \CF_createnormnodes{#2@@}{#3@@}\CF_doublesep\CF_doublesep + \CF_drawaxisbond{#2}{#3}% trace la liaison simple dans l'axe\CF_drawbonda(#2@@)--(#3@@); + \begingroup% ajuste �ventuellement les longueurs des liaisons doubles + \ifCF_incycle + \ifdim\CF_startoffset=0pt + \CF_edefaddtomacro\CF_currentbondstyle{,shorten <=\CF_doublebondlengthcorrection pt}% + \fi + \ifdim\CF_endoffset=0pt + \CF_edefaddtomacro\CF_currentbondstyle{,shorten >=\CF_doublebondlengthcorrection pt}% + \fi + \fi + \CF_drawbonda(#2@@1)--(#3@@1); + \endgroup + \or + \CF_createnormnodes{#2@@}{#3@@}\CF_doublesep\CF_doublesep + \CF_drawaxisbond{#2}{#3}% trace la liaison simple dans l'axe\CF_drawbonda(#2@@)--(#3@@); + \begingroup% ajuste �ventuellement les longueurs des liaisons doubles + \ifCF_incycle + \ifdim\CF_startoffset=0pt + \CF_edefaddtomacro\CF_currentbondstyle{,shorten \ifnum\CF_flipstate=0 <=-\else>=\fi\CF_doublebondlengthcorrection pt}% + \fi + \ifdim\CF_endoffset=0pt + \CF_edefaddtomacro\CF_currentbondstyle{,shorten \ifnum\CF_flipstate=0 >=-\else<=\fi\CF_doublebondlengthcorrection pt}% + \fi + \fi + \CF_drawbonda(#2@@2)--(#3@@2); + \endgroup + \fi + \or% 3 = liaison triple + \CF_createnormnodes{#2@@}{#3@@}\CF_doublesep\CF_doublesep + \CF_drawaxisbond{#2}{#3}% trace la liaison simple dans l'axe\CF_drawbonda(#2@@)--(#3@@); + \CF_drawbonda(#2@@1)--(#3@@1); + \CF_drawbonda(#2@@2)--(#3@@2); + \or% 4 = liaison Cram pleine de #2 vers #3 + \CF_createnormnodes{#2@@}{#3@@}{\CF_crambasewidth/2}{}% + \CF_expafter{\filldraw[}\CF_currentbondstyle,line join=bevel](#2@@1)--(#2@@2)--(#3@@)--cycle; + \let\CF_joinbond\CF_zero + \or% 5 = liaison Cram creuse de #3 vers #2 + \CF_createnormnodes{#3@@}{#2@@}{\CF_crambasewidth/2}{}% + \CF_expafter{\filldraw[}\CF_currentbondstyle,line join=bevel](#3@@1)--(#3@@2)--(#2@@)--cycle; + \let\CF_joinbond\CF_zero + \or% 6 = liaison Cram pointill�e de #2 vers #3 + \scope + \CF_createnormnodes{#2@@}{#3@@}{\CF_crambasewidth/2}{}% + \CF_clipcramornot(#2@@1)--(#2@@2)--(#3@@)--(#2@@1); + \CF_expafter{\draw[}\CF_currentbondstyle,dash pattern=on \CF_cramdashlength off \CF_cramdashsep,line width=\CF_crambasewidth](#2@@)--(#3@@); + \endscope + \let\CF_joinbond\CF_zero + \or% 7 = liaison Cram pointill�e de #3 vers #2 + \scope + \CF_createnormnodes{#3@@}{#2@@}{\CF_crambasewidth/2}{}% + \CF_clipcramornot(#3@@1)--(#3@@2)--(#2@@)--(#3@@1); + \CF_expafter{\draw[}\CF_currentbondstyle,dash pattern=on \CF_cramdashlength off \CF_cramdashsep,line width=\CF_crambasewidth](#3@@)--(#2@@); + \endscope + \let\CF_joinbond\CF_zero + \or% 8 = liaison cram rectangle �vid� de #2 vers #3 + \CF_createnormnodes{#2@@}{#3@@}{\CF_crambasewidth/2}{}% + \CF_expafter{\draw[}\CF_currentbondstyle,line join=bevel](#2@@1)--(#2@@2)--(#3@@)--cycle; + \let\CF_joinbond\CF_zero + \or% 9 = liaison cram rectangle �vid� de #3 vers #1 + \CF_createnormnodes{#3@@}{#2@@}{\CF_crambasewidth/2}{}% + \CF_expafter{\draw[}\CF_currentbondstyle,line join=bevel](#3@@1)--(#3@@2)--(#2@@)--cycle; + \let\CF_joinbond\CF_zero + \else + \CF_error{unknown bond type, this error should not occur^^JIf you think it's a bug, send a Minimal Example to the author}% + \fi + \let\CF_startoffset\empty + \let\CF_endoffset\empty + \let\CF_previoustikz\CF_currenttikz + \let\CF_previousbondangle\CF_previousangle + \def\CF_previousbond{#1}% +} + +\def\CF_drawaxisbondnojoin#1#2{\CF_drawbonda(#1@@)--(#2@@);} + +\def\CF_drawaxisbondjoin#1#2{% dessine une liaison simple dans l'axe avec raccord r�trograde + \ifCF_incycle\ifnum\CF_cntcyclebonds=\CF_cyclenum\relax + \let\CF_nexttikz\CF_cyclefirsttikz + \fi\fi + \ifnum\CF_joinbond=0 + \ifCF_incycle + \ifnum\CF_cntcyclebonds=\CF_cyclenum\relax + \ifnum\CF_cyclejoinlast=1 + \CF_drawbonda(#1@@)--(#2@@)--% + ([shift=(\CF_previousbondangle+2*\CF_cycleincrementangle:.5\pgflinewidth)]#2@@); + \else + \CF_drawbonda(#1@@)--(#2@@); + \fi + \else + \CF_drawbonda(#1@@)--(#2@@); + \fi + \else + \CF_drawbonda(#1@@)--(#2@@); + \fi + \def\CF_joinbond{1}% + \else + \CF_ifx\CF_previoustikz\CF_currenttikz + {\def\CF_joinbond{1}% + \CF_ifzerodim\CF_previousatomgroup + {\CF_ifx\CF_previousbondangle\empty% si d�but mol�cule + {\CF_drawbonda(#1@@)--(#2@@); + } + {\ifdim\CF_startoffset=0pt + \ifCF_incycle + \ifnum\CF_cntcyclebonds=\CF_cyclenum\relax + \ifnum\CF_cyclejoinlast=1 + \CF_ifx\CF_cyclefirsttikz\CF_currenttikz + {\CF_drawbonda([shift=(\CF_previousbondangle:-.5\pgflinewidth)]#1@@)--(#1@@)--(#2@@)--% + ([shift=(\CF_previousbondangle+2*\CF_cycleincrementangle:.5\pgflinewidth)]#2@@); + } + {\CF_drawbonda([shift=(\CF_previousbondangle:-.5\pgflinewidth)]#1@@)--(#1@@)--(#2@@); + }% + \else + \CF_drawbonda([shift=(\CF_previousbondangle:-.5\pgflinewidth)]#1@@)--(#1@@)--(#2@@); + \fi + \else + \CF_drawbonda([shift=(\CF_previousbondangle:-.5\pgflinewidth)]#1@@)--(#1@@)--(#2@@); + \fi + \else + \CF_drawbonda([shift=(\CF_previousbondangle:-.5\pgflinewidth)]#1@@)--(#1@@)--(#2@@); + \fi + \else + \CF_drawbonda(#1@@)--(#2@@); + \fi + }% + } + {\CF_drawbonda(#1@@)--(#2@@);}% + } + {\ifCF_incycle + \ifnum\CF_cntcyclebonds=\CF_cyclenum\relax + \ifnum\CF_cyclejoinlast=1 + \CF_ifx\CF_nexttikz\CF_currenttikz + {\CF_drawbonda(#1@@)--(#2@@)--([shift=(\CF_previousbondangle+2*\CF_cycleincrementangle:.5\pgflinewidth)]#2@@);}% + {\CF_drawbonda(#1@@)--(#2@@);}% + \else + \CF_drawbonda(#1@@)--(#2@@); + \fi + \else + \CF_drawbonda(#1@@)--(#2@@); + \fi + \else + \CF_drawbonda(#1@@)--(#2@@); + \fi + }% + \fi + \ifdim\CF_endoffset=0pt \else + \let\CF_joinbond\CF_zero + \fi +} + +\def\CF_drawbonda{\CF_expafter{\draw[}\CF_currentbondstyle]} + +\def\CF_hookdrawall{% dessine tous les crochets contenus dans la sc \CF_hookdraw + \CF_doifnotempty\CF_hookdrawlist + {\expandafter\CF_hookdrawfirst\CF_hookdrawlist\_nil% trace un lien de crochet � crochet + \CF_hookdrawall + }% +} + +\def\CF_hookdrawfirst[#1,#2,#3]#4#5#6#7#8\_nil{% + \def\CF_hookdrawlist{#8}% + \begingroup + \let\CF_joinbond\CF_zero + \def\CF_currenttikz{#3}% + \def\CF_hookstartcontent{#6}\def\CF_hookendcontent{#7}% + \CF_ifinteger{#2}% + {\CF_drawbond{#2}{#4}{#5}\CF_hookstartcontent\CF_hookendcontent + }% + {\CF_assignbondcode{#2}\CF_bondcurrentnum + \CF_drawbond\CF_bondcurrentnum{#4}{#5}\CF_hookstartcontent\CF_hookendcontent + }% + \endgroup +} + +\def\CF_extractatom#1-#2\_nil{#2}% transforme le bound@outnode en n� de l'atome + +\def\CF_gobblemovearg @#1#2\_nil#3{% + \expandafter\def\csname atom_\number\CF_cntatom\endcsname{#2}% + \CF_ifinstr{#1},% + {\CF_analysemovearg#1\_nil#3\let\CF_movebondcoeff\empty}% + {\def#3{#1}}% + \CF_doifempty{#2}{\let\CF_nodestrut\empty}% +}% + +\def\hflipnext{\def\CF_flipstate{1}} + +\def\vflipnext{\def\CF_flipstate{2}} +\let\CF_flipstate\CF_zero + +\def\CF_drawatomgroup#1#2#3{% #1=angle d'arriv�e de la liaison #2=numero atome sur lequel arrive la liaison #3=groupe d'atomes + \expandafter\let\expandafter\CF_bondoutcontent% assigne le contenu de l'atome d'o� part la liaison + \csname + \ifdefined\CF_bondoutnode + atom_\expandafter\CF_extractatom\CF_bondoutnode\_nil + \else + empty% + \fi + \endcsname + \global\advance\CF_cntgroup1 + \let\CF_currentatom\empty + \global\let\CF_hookdrawlist\empty + \CF_cntatomgroup0 % est le nombre d'atome dans le groupe que va calculer \CF_drawatomgroupa + \CF_iffirsttokmatch{#3}? + {\CF_drawatomgroupa{{}#3}} + {\CF_drawatomgroupa{#3}}% + \def\CF_currentatomgroup{#3}% + \CF_removemovearg\CF_currentatomgroup% enl�ve les "@{}" + \CF_ifinstr{#3}?% + {\CF_removehook\CF_currentatomgroup + \ifcat\relax\detokenize\expandafter{\romannumeral-`\.\expandafter\noexpand\CF_currentatomgroup}\relax + \let\CF_currentatomgroup\empty + \fi + }% + {}% + \CF_doifnotempty{#2} + {\ifnum#2<1 + \CF_warning{no atom found at position #2, pershaps you mispelled the optional argument of the bond.}% + \else + \ifnum#2>\CF_cntatomgroup + \CF_error{no atom found at position #2, pershaps you mispelled the optional argument of the bond.}% + \fi + \fi + }% + \edef\CF_hookatomnumber{% + \CF_ifempty{#2} + {\ifdim#1pt>90pt + \ifdim#1pt<270pt + \number\CF_cntatomgroup + \else + 1% + \fi + \else + 1% + \fi + } + {#2% + }% + }% + \CF_cntatom\CF_hookatomnumber + \CF_ifzerodim\CF_currentatomgroup + {\let\CF_nodestrut\empty + } + {\CF_ifx\empty\CF_bondoutcontentsaved + {\def\CF_nodestrut{\vphantom\CF_bondoutcontent}}% + {\def\CF_nodestrut{\vphantom\CF_bondoutcontentsaved}}% + }% + \edef\CF_optstring{anchor=\ifnum\CF_lastaction=0 base\else\ifCF_incycle center\else\ifCF_macrofixedbondlength 180+#1\else center\fi\fi\fi,at=(CF_node),\CF_nodestyle}% premier atome de la mol�cule affich� + \loop + \unless\ifnum\CF_cntatom>\CF_cntatomgroup + \CF_eexpafter + {\futurelet\CF_toksa} + {\expandafter\expandafter\expandafter\CF_gobtonil\csname atom_\number\CF_cntatom\endcsname\_nil}% + \CF_ifx @\CF_toksa% l'atome courant commence par un "@" + {\CF_threeea\CF_gobblemovearg\csname atom_\number\CF_cntatom\endcsname\_nil\CF_moveatomname + \CF_expafter{\node[}\CF_optstring,overlay](\CF_moveatomname){\phantom{\CF_nodecontent}};% + \let\CF_moveatomname\empty + } + {}% + \ifboolKV[chemfig]{debug} + {\CF_expafter{\node[}\CF_optstring,draw=gray](n\number\CF_cntgroup-\number\CF_cntatom){\CF_nodecontent};% + \CF_show_debug_atom + } + {\CF_expafter{\node[}\CF_optstring](n\number\CF_cntgroup-\number\CF_cntatom){\CF_nodecontent};% + }% + \let\CF_nodestrut\empty + \advance\CF_cntatom1 + \edef\CF_optstring{anchor=base \ifnum\CF_flipstate=1 east\else west\fi,at=(n\number\CF_cntgroup-\number\numexpr\CF_cntatom-1.base \ifnum\CF_flipstate=1 west\else east\fi),\CF_nodestyle}% + \repeat + \CF_cntatom\CF_hookatomnumber + \ifnum\CF_lastaction=2 % s'il faut tracer une liaison + \gdef\CF_cycleanglecorrection{0}% alors c'est qu'un cycle ne peut pas commencer la mol�cule : annulation de la correction d'angle + \CF_drawbond\CF_bondtype{\CF_bondoutnode}{n\number\CF_cntgroup-\number\CF_cntatom}\CF_previousatomgroup\CF_currentatomgroup + \fi + \def\CF_lastaction{1}% met la derni�re action � 1 : affichage d'un noeud + \loop + \ifnum\CF_cntatom>1 + \advance\CF_cntatom-1 + \edef\CF_optstring{anchor=base \ifnum\CF_flipstate=1 west\else east\fi,at=(n\number\CF_cntgroup-\number\numexpr\CF_cntatom+1.base \ifnum\CF_flipstate=1 east\else west\fi),\CF_nodestyle}% + \CF_eexpafter + {\futurelet\CF_toksa} + {\expandafter\expandafter\expandafter\CF_gobtonil\csname atom_\number\CF_cntatom\endcsname\_nil}% + \CF_ifx @\CF_toksa% l'atome courant commence par un "@" + {\CF_threeea\CF_gobblemovearg\csname atom_\number\CF_cntatom\endcsname\_nil\CF_moveatomname + \CF_expafter{\node[}\CF_optstring,overlay](\CF_moveatomname){\phantom{\CF_nodecontent}};% + \let\CF_moveatomname\empty + } + {}% + \ifboolKV[chemfig]{debug} + {\CF_expafter{\node[}\CF_optstring,draw=gray](n\number\CF_cntgroup-\number\CF_cntatom){\CF_nodecontent};% + \CF_show_debug_atom + } + {\CF_expafter{\node[}\CF_optstring](n\number\CF_cntgroup-\number\CF_cntatom){\CF_nodecontent};% + }% + \repeat + \ifboolKV[chemfig]{debug} + \CF_show_debug_atomgroup + {}% + \CF_hookdrawall + \edef\CF_lastgroupnumber{\number\CF_cntgroup}% + \let\CF_previousatomgroup\CF_currentatomgroup +} + +\def\CF_show_debug_atom{% + \node[at=(n\number\CF_cntgroup-\number\CF_cntatom.south),anchor=north,outer sep=1pt,overlay]{$\scriptscriptstyle\color{gray}\number\CF_cntatom$};% +} + +\def\CF_show_debug_atomgroup{% + \draw[red,overlay] ([xshift=-.5pt,yshift=.5pt]n\number\CF_cntgroup-1.north west) rectangle ([xshift=.5pt,yshift=-.5pt]n\number\CF_cntgroup-\number\CF_cntatomgroup.south east);% + \path (n\number\CF_cntgroup-1.north west) -- (n\number\CF_cntgroup-\number\CF_cntatomgroup.north east) + node [midway,yshift=1pt,overlay] {$\scriptscriptstyle\color{red}\number\CF_cntgroup$}; +} + +\def\CF_keepmovearg @#1#2\_nil{\def\CF_currentatom{@{#1}}} + +\def\CF_drawatomgroupa#1{% transforme #1 en un groupe d'atomes + \CF_ifempty{#1} + {\expandafter\let\csname atom_\number\CF_cntatomgroup\endcsname\CF_currentatom + } + {\advance\CF_cntatomgroup1 + \futurelet\CF_toksa\CF_gobtonil#1\_nil + \CF_ifx @\CF_toksa + {\CF_keepmovearg#1\_nil + \CF_removemovearga#1\_nil\CF_aftermovearg + \CF_expsecond\CF_drawatomgroupb{\CF_aftermovearg}% + }% + {\let\CF_currentatom\empty + \CF_drawatomgroupb{#1}% + }% + }% +} + +\def\CF_drawatomgroupb#1{% + \CF_ifempty{#1} + {\expandafter\let\csname atom_\number\CF_cntatomgroup\endcsname\CF_currentatom + } + {\futurelet\CF_toksa\CF_gobtonil#1\_nil + \CF_ifx\bgroup\CF_toksa + {\CF_eaddtomacro\CF_currentatom{\expandafter{\CF_firsttonil#1\_nil}}% + \CF_expsecond\CF_drawatomgroupba{\CF_gobarg#1}% + }% + {\CF_ifx\CF_sptoken\CF_toksa + {\CF_addtomacro\CF_currentatom{ }% + \CF_expsecond\CF_drawatomgroupba{\CF_afterspace#1\_nil}% + }% + {\CF_eaddtomacro\CF_currentatom{\CF_firsttonil#1\_nil}% + \CF_expsecond\CF_drawatomgroupba{\CF_gobarg#1}% + }% + }% + }% +} + +% enl�ve tous les "@{nom}" de la sc #1 +\def\CF_removemovearg#1{% + \CF_expsecond\CF_ifinstr{#1}@% + {\expandafter\CF_removemovearga#1\_nil#1% + \CF_removemovearg#1% + }% + {}% +} + +% enl�ve le premier "@{}" de l'argument et l'assigne � #2 +\def\CF_removemovearga#1\_nil#2{% + \def\CF_removemoveargb##1@{% + \CF_expsecond{\def#2}{\CF_gobarg##1}% mange le \relax + \CF_removemoveargc\relax + }% + \def\CF_removemoveargc##1\_nil{\CF_eaddtomacro#2{\CF_gobtwoargs##1}}% mange le \relax et le + \CF_removemoveargb\relax#1\_nil +} + +\def\CF_drawatomgroupba#1{% transforme #1 en un groupe d'atomes + \CF_ifempty{#1} + {\expandafter\let\csname atom_\number\CF_cntatomgroup\endcsname\CF_currentatom + \let\CF_currentatom\empty + } + {\futurelet\CF_toksa\CF_gobtonil#1\_nil + \CF_ifx @\CF_toksa + {\expandafter\let\csname atom_\number\CF_cntatomgroup\endcsname\CF_currentatom + \let\CF_currentatom\empty + \CF_drawatomgroupa{#1}% + }% + {\CF_ifx|\CF_toksa + {\expandafter\let\csname atom_\number\CF_cntatomgroup\endcsname\CF_currentatom + \let\CF_currentatom\empty + \CF_expsecond\CF_drawatomgroupa{\CF_gobarg#1}% + }% + {\CF_ifx\CF_sptoken\CF_toksa + {\CF_addtomacro\CF_currentatom{ }% + \CF_expsecond\CF_drawatomgroupba{\CF_afterspace#1\_nil}% + }% + {\CF_ifx\bgroup\CF_toksa + {\CF_eaddtomacro\CF_currentatom{\expandafter{\CF_firsttonil#1\_nil}}% + \CF_expsecond\CF_drawatomgroupba{\CF_gobarg#1}% + }% + {\CF_expsecond\CF_ifcarisupperletter{\CF_firsttonil#1\_nil}% + {\expandafter\let\csname atom_\number\CF_cntatomgroup\endcsname\CF_currentatom + \let\CF_currentatom\empty + \CF_drawatomgroupa{#1}% + }% + {\CF_ifx?\CF_toksa + {\CF_expsecond\CF_iffirsttokmatch{\CF_gobarg#1}[% un crochet apr�s le "?" + {\expandafter\CF_graboptarg\CF_gobarg#1\_nil\CF_afterhook}% + {\CF_expafter{\CF_graboptarg[]}{\CF_gobarg#1}\_nil\CF_afterhook}% + \CF_exptwomacroargs\CF_ifinstr{\CF_hooklist}{\expandafter(\CF_hookcurrentname)}% crochet d�j� d�fini ? + {\CF_expsecond\CF_hookparselist{\CF_hookcurrentname}% chercher les caract�ristiques du crochet sauvegard� + \CF_edefaddtomacro\CF_hookdrawlist{% + [\CF_hookcurrentname,\CF_hookcurrentlink,\CF_hookcurrenttikz]{\CF_hooksavedcoord}{n\number\CF_cntgroup-\number\CF_cntatomgroup}}% + \CF_eaddtomacro\CF_hookdrawlist{\expandafter{\CF_hooksavedcontent}}% + \CF_eaddtomacro\CF_hookdrawlist{\expandafter{\CF_currentatom}}% ajoute les 4 arguments � la liste des crochets � tracer + \global\let\CF_hookdrawlist\CF_hookdrawlist + }% + {\CF_edefaddtomacro\CF_hooklist{(\CF_hookcurrentname)|n\number\CF_cntgroup-\number\CF_cntatomgroup|}% + \CF_eaddtomacro\CF_hooklist{\CF_currentatom|}% + \global\let\CF_hooklist\CF_hooklist + }% + \CF_expsecond\CF_drawatomgroupba{\CF_afterhook}% + }% + {\CF_eaddtomacro\CF_currentatom{\CF_firsttonil#1\_nil}% + \CF_expsecond\CF_drawatomgroupba{\CF_gobarg#1}% + }% + }% + }% + }% + }% + }% + }% +} + +\def\CF_kookdefaultname{a} +\def\CF_hookdefaultlink{-} +\def\CF_hookdefaulttikz{} + +\def\CF_hookparseoptarg#1,#2,#3\_nil{% + \CF_testemptyandassign\CF_hookcurrentname{#1}\CF_kookdefaultname + \CF_testemptyandassign\CF_hookcurrentlink{#2}\CF_hookdefaultlink + \CF_testemptyandassign\CF_hookcurrenttikz{#3}\CF_hookdefaulttikz +} + +\def\CF_graboptarg[#1]#2\_nil#3{% + \CF_hookparseoptarg#1,,\_nil + \def#3{#2}% +} + +\def\CF_hookparselist#1{% #1 est le nom du noeud � retrouver + \def\CF_hookparselista##1(#1)|##2|##3|##4\_nil{\def\CF_hooksavedcoord{##2}\def\CF_hooksavedcontent{##3}}% + \expandafter\CF_hookparselista\CF_hooklist\_nil +} + +\def\CF_removehook#1{% + \CF_expsecond\CF_ifinstr{#1}?% + {\CF_expafter{\CF_removehooka\relax}#1\_nil#1% + \CF_removehook#1% + } + {}% +} + +\def\CF_removehooka#1?#2\_nil#3{% + \CF_iffirsttokmatch{#2}[% + {\CF_removehookb#1?#2\_nil#3} + {\CF_expsecond{\def#3}{\CF_gobarg#1#2}}% +} + +\def\CF_removehookb#1?[#2]#3\_nil#4{\CF_expsecond{\def#4}{\CF_gobarg#1#3}} + +\defKV[charge]{% + .radius = \CF_defifempty\CF_dotradius {#1}{0.15ex}, + :sep = \CF_defifempty\CF_dotsep {#1}{0.3em}, + .style = \CF_defifempty\CF_dotstyle {#1}{fill=black}, + "length = \CF_defifempty\CF_rectlength{#1}{1.5ex}, + "width = \CF_defifempty\CF_rectwidth {#1}{.3ex} +} +\def\setcharge#{\setKV[charge]} +\def\resetcharge{\restoreKV[charge]} +\setKVdefault[charge]{% + debug = false,% trace les contours des noeuds + macro atom = \printatom,%macro qui prendra comme argument l'atome recevant la charge + circle = false,% false => noeud atome = rectangle + macro charge = ,% macro attendue (\printatom ou \ensuremath, par exemple) qui prendra comme argument la charge + extra sep = 1.5pt,% s�paration additionnelle entre le noeud (cercle ou rectangle) et la position des charges + overlay = true,% charges en "surimpression" + shortcuts = true,% raccourcis \. \: \| et \" actifs pour Lewis + lewisautorot = true,% rotation auto charge Lewis + .radius = 0.15ex,% rayon du point + :sep = 0.3em,% s�paration des deux points + .style = {fill=black},% style des points + "length = 1.5ex,% longueur rectangle + "width = .3ex,% largeur rectangle + "style = {black,line width=0.4pt},% style rectangle + |style = {black,line width=0.4pt},% style ligne +}% +\def\chargedot{\CF_testopt\chargedot_a{}} +\def\chargedot_a[#1]{% + \begingroup + \setKV[charge]{#1}% + \CF_expafter{\tikz\draw[}{\CF_dotstyle}](0,0)circle(\CF_dotradius);% + \endgroup +} +\def\chargeddot{\CF_testopt\chargeddot_a{}} +\def\chargeddot_a[#1]{% + \begingroup + \setKV[charge]{#1}% + \ifboolKV[charge]{lewisautorot} + {\pgfmathsetmacro\CF_lewisrot{90+\chargeangle}} + {\def\CF_lewisrot{0}}% + \pgfmathsetmacro\CF_halfsep{\CF_dotsep/2}% + \tikzpicture[anchor=center,rotate=\CF_lewisrot]% + \CF_expafter{\draw[}{\CF_dotstyle}]% + (-\CF_halfsep pt,0)circle(\CF_dotradius)% + (\CF_halfsep pt,0)circle(\CF_dotradius);% + \endtikzpicture + \endgroup +} +\def\chargerect{\CF_testopt\chargerect_a{}} +\def\chargerect_a[#1]{% + \begingroup + \setKV[charge]{#1}% + \ifboolKV[charge]{lewisautorot} + {\pgfmathsetmacro\CF_lewisrot{90+\chargeangle}} + {\def\CF_lewisrot{0}}% + \pgfmathsetmacro\CF_halfwidth{\CF_rectwidth/2}% + \pgfmathsetmacro\CF_halflength{\CF_rectlength/2}% + \tikzpicture[anchor=center,rotate=\CF_lewisrot]% + \CF_eexpafter{\draw[}{\useKV[charge]{"style}}](-\CF_halflength pt,-\CF_halfwidth pt)rectangle(\CF_halflength pt,\CF_halfwidth pt);% bugfix 1.51 + \endtikzpicture + \endgroup +} +\def\chargeline{\CF_testopt\chargeline_a{}} +\def\chargeline_a[#1]{% + \begingroup + \setKV[charge]{#1}% + \ifboolKV[charge]{lewisautorot} + {\pgfmathsetmacro\CF_lewisrot{90+\chargeangle}} + {\def\CF_lewisrot{0}}% + \pgfmathsetmacro\CF_halflength{\CF_rectlength/2}% + \tikzpicture[anchor=center,rotate=\CF_lewisrot]% + \CF_eexpafter{\draw[}{\useKV[charge]{|style}}](-\CF_halflength pt,0)--(\CF_halflength pt,0);% bugfix 1.51 + \endtikzpicture + \endgroup +} +\def\CF_enableshortcuts{% + \let\CF_saveddot \.\let\.\chargedot + \let\CF_savedddot\:\let\:\chargeddot + \let\CF_savedrect\"\let\"\chargerect + \let\CF_savedline\|\let\|\chargeline + \let\enableshortcuts\relax + \let\disableshortcuts\CF_disableshortcuts +} +\def\CF_disableshortcuts{% + \let\.\CF_saveddot + \let\:\CF_savedddot + \let\"\CF_savedrect + \let\|\CF_savedline + \let\enableshortcuts\CF_enableshortcuts + \let\disableshortcuts\relax +} +\def\charge{% + \begingroup + \catcode`\: 12 + \charge_a{true}% +} +\def\Charge{% + \begingroup + \catcode`\: 12 + \charge_a{false}% +} +\def\charge_a#1#2{% #1=TF #2=liste emplacements + \CF_testopt{\charge_b{#1}}{}#2\_nil +} +\def\charge_b#1[#2]#3\_nil{% + \charge_c{#1}[#2]{#3}% +} +\def\charge_c#1[#2]#3#4{% #1=TF pour overlay, #2= r�glages, #3=liste d'emplacements, #4=atome + \setcharge{overlay=#1,#2}% + \setbox\CF_chargebox\hbox{\useKV[charge]{macro atom}{#4}}% + \CF_ifinsidetikz + {\pgfinterruptpicture + \let\CF_atendofcharge\endpgfinterruptpicture + } + {\let\CF_atendofcharge\relax + }% + \expanded{\noexpand + \tikzpicture[every node/.style={% + \ifboolKV[charge]{debug}{draw=red,}{}% + anchor=base,% + inner sep=0pt,% + outer sep=0pt,% + minimum size=0pt},% + baseline]}% + \expanded{\noexpand + \node[% + \ifboolKV[charge]{circle}{circle,}{}% + \ifboolKV[charge]{debug}{draw=green,}{}% + anchor=base% + ]}% + (atombox)at(0,0)% + {\copy\CF_chargebox};% noeud contenant l'atome + \expanded{\noexpand + \node[% + \ifboolKV[charge]{circle}{circle,}{}% + \ifboolKV[charge]{debug}{draw=blue,}{}% + anchor=base,% + inner sep=\useKV[charge]{extra sep},% + overlay% + ]}% + (atom)at(0,0){% + \vrule width0pt height\ht\CF_chargebox depth\dp\CF_chargebox + \vrule width\wd\CF_chargebox height\CF_zero depth\CF_zero};% noeud pour placer les charges + \let\enableshortcuts\relax + \let\disableshortcuts\relax + \ifboolKV[charge]{shortcuts}\CF_enableshortcuts{}% l'atome n'est _PAS_ concern� par les racourcis + \charge_d#3,\CF_quark=% + \endtikzpicture + \CF_atendofcharge + \endgroup +} +\def\charge_d#1={% + \CF_ifx\CF_quark{#1}% + {} + {\CF_striplastsp{#1}\charge_e=}% bugfix 1.54 +} +\def\charge_e#1={% + \CF_ifinstr{#1}[ + {\charge_f#1=} + {\charge_f#1[]=}% +} +\def\charge_f#1[#2]={% + \CF_ifinstr{#1}: + {\charge_g#1[#2]=} + {\charge_g#1:0pt[#2]=}% +} +\def\charge_g#1:#2[#3]=#4,{% #1=angle, #2=offset, #3=code tikz charge, #4=charge + \CF_stripsp{#1}\CF_ifinteger + {\pgfmathsetmacro\chargeangle{mod(#1,360)}% + } + {\pgfmathanglebetweenpoints{\pgfpointanchor{atom}{center}}{\CF_stripsp{#1}{\pgfpointanchor{atom}}}% + \let\chargeangle\pgfmathresult% incorrect si (atom.center==atom.#1) && (extra sep==0) TODO: mettre un warning ? + }% + \edef\CF_offset{\the\dimexpr#2+0pt}% + \CF_stripsp{#1}{\CF_distancebetweenpoints{atom}{center}{atom}}\CF_chargedistance + \CF_eexpafter{\node[anchor=center,}{\ifboolKV[charge]{overlay}{overlay,}{}}#3]% + at([shift=(\chargeangle:\CF_chargedistance pt+\CF_offset)]atom.center){\useKV[charge]{macro charge}{#4}};% + \charge_d +} + +\def\Chembelow{\begingroup\let\CF_temp\CF_gobarg\CF_chembelowa} + +\def\chembelow{\begingroup\let\CF_temp\CF_id\CF_chembelowa} + +\def\CF_chembelowa{\CF_testopt\CF_chembelowb\CF_stacksep} + +\def\CF_chembelowb[#1]#2#3{% + \setbox\CF_box\hbox{\printatom{#2}}% + \expandafter\vtop\CF_temp{to\ht\CF_box}{% + \offinterlineskip + \hbox{\printatom{#2}}% + \kern#1\relax + \hbox to\wd\CF_box{\hss\printatom{#3}\hss}% + \CF_temp\vss + }% + \endgroup +} + +\def\Chemabove{\begingroup\let\CF_temp\CF_gobarg\CF_chemabovea} + +\def\chemabove{\begingroup\let\CF_temp\CF_id\CF_chemabovea} + +\def\CF_chemabovea{\CF_testopt\CF_chemaboveb\CF_stacksep} + +\def\CF_chemaboveb[#1]#2#3{% + \setbox\CF_box\hbox{\printatom{#2}}% + \expandafter\vbox\CF_temp{to\ht\CF_box}{% + \offinterlineskip + \CF_temp\vss + \hbox to\wd\CF_box{\hss\printatom{#3}\hss}% + \kern#1\relax + \hbox{\printatom{#2}}% + }% + \endgroup +} + +\def\chemmove{\CF_testopt\CF_chemmove{}} + +\def\CF_chemmove[#1]#2{% + \CF_doifnotempty{#2}% + {\expandafter\tikzpicture\expanded{[overlay,remember picture,-CF\CF_ifempty{#1}{}{,\unexpanded{#1}}]}% + #2% + \endtikzpicture + }% +} + +\def\chemnameinit#1{% + \setbox\CF_boxstuff\hbox{#1}% + \xdef\CF_dpmax{\the\dp\CF_boxstuff}% +} +\let\CF_dpmax\CF_zero + +\def\CF_parsemolname#1\\#2\_nil{% + \hbox to\CF_wdstuffbox{\hss#1\hss}% + \CF_doifnotempty{#2}{\CF_parsemolname#2\_nil}% +} + +\def\chemname{% + \CF_ifstar + {\CF_adjustnamedpfalse\CF_chemnamea} + {\CF_adjustnamedptrue \CF_chemnamea}% +} + +\def\CF_chemnamea{\CF_testopt\CF_chemnameb{1.5ex}} + +\def\CF_chemnameb[#1]#2#3{% + \setbox\CF_boxstuff\hbox{#2}% + \edef\CF_wdstuffbox{\the\wd\CF_boxstuff}\edef\CF_dpstuffbox{\the\dp\CF_boxstuff}% + \leavevmode + \ifdim\CF_dpmax<\CF_dpstuffbox\global\let\CF_dpmax\CF_dpstuffbox\fi + \vtop{% + \box\CF_boxstuff + \nointerlineskip + \kern\dimexpr#1\ifCF_adjustnamedp+\CF_dpmax-\CF_dpstuffbox\fi\relax + \CF_parsemolname#3\\\_nil + }% +} + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%%% S C H � M A S R � A C T I O N N E L S %%% +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +\let\CF_schemenest\CF_zero + +\def\CF_subscheme{\CF_testopt\CF_subschemea{}} +\def\CF_subschemea[#1]{\CF_testopt{\CF_subschemeb[#1]}{text}} +\def\CF_subschemeb[#1][#2]#3{\schemestart[#1][#2]#3\schemestop} + +\def\chemleft#1#2\chemright#3{% + \leavevmode + \begingroup + \setbox0\hbox{$\vcenter{\hbox{}}$}\edef\CF_delimmathht{\the\ht0}% + \setbox0\hbox{#2}\edef\CF_delimdim{\the\dimexpr(\ht0+\dp0)/2}% + \edef\CF_delimshift{\the\dimexpr(\ht0-\dp0)/2-\CF_delimmathht}% + \raise\CF_delimshift\hbox{$\left#1\vrule height\CF_delimdim depth\CF_delimdim width0pt\right.$}\box0 + \raise\CF_delimshift\hbox{$\left.\vrule height\CF_delimdim depth\CF_delimdim width0pt\right#3$}% + \endgroup +} + +\def\chemright#1{% + \CF_warning{"\string\chemright\string#1" ignored! No \string\chemleft\space previously found.}% +} + +\def\chemup#1#2\chemdown#3{% + \begingroup + \setbox0\hbox{\printatom{#2}}\edef\CF_delimdim{\the\dimexpr\wd0/2}% + \tikzpicture[every node/.style={inner sep=0pt,outer sep=0pt,minimum size=0pt},baseline]% + \node[anchor=base west](chem@stuff){\box0};% + \node[at=(chem@stuff.north),anchor=east,rotate=-90]{$\left#1\vrule height\CF_delimdim depth\CF_delimdim width0pt\right.$};% + \node[at=(chem@stuff.south),anchor=west,rotate=-90]{$\left.\vrule height\CF_delimdim depth\CF_delimdim width0pt\right#3$};% + \endtikzpicture + \endgroup +} + +\def\chemdown#1{% + \CF_warning{"\string\chemdown\string#1" ignored! No \string\chemup\space previously found.}% +} + +\def\CF_setstyle#1,#2,#3\_nil#4#5#6{% + \def#4{#1}\let#5\empty\let#6\empty + \CF_iffirsttokmatch\CF_quark{#2\relax} + {}% + {\def#5{#2}% + \CF_iffirsttokmatch\CF_quark{#3\relax} + {}% + {\CF_setstylea#3\_nil#6}% + }% +} +\def\CF_setstylea#1,\CF_quark#2\_nil#3{\def#3{#1}} + +\def\CF_and{\futurelet\CF_toksa\CF_anda} + +\def\CF_anda{% + \CF_ifx\CF_toksa\bgroup + {\CF_andb} + {\CF_andb{}}% +} + +\def\CF_andb#1{% + \CF_setstyle#1,\CF_quark,\CF_quark\_nil\CF_signspaceante_\CF_signspacepost_\CF_signvshift_ + \CF_doifnotempty\CF_signspaceante_{\let\CF_signspaceante\CF_signspaceante_}% + \CF_doifnotempty\CF_signspacepost_{\let\CF_signspacepost\CF_signspacepost_}% + \CF_doifnotempty\CF_signvshift_{\let\CF_signvshift\CF_signvshift_}% + \raise\CF_signvshift\hbox{\kern\CF_signspaceante$+$\kern\CF_signspacepost}% +} + +\def\schemestart{% + \begingroup + \xdef\CF_schemenest{\number\numexpr\CF_schemenest+1}% + \CF_testopt\CF_schemestarta{}% +} + +\def\CF_schemestarta[#1]{% + \CF_setstyle#1,\CF_quark,\CF_quark\_nil\CF_arrowangle_\CF_arrowlength_\CF_arrowstyle_ + \CF_doifnotempty\CF_arrowangle_{\let\CF_arrowangle\CF_arrowangle_}% + \CF_doifnotempty\CF_arrowlength_{\let\CF_arrowlength\CF_arrowlength_}% + \CF_eexpsecond{\def\CF_arrowtip}{\expandafter\CF_gobarg\CF_arrowhead}% + \CF_expsecond{\CF_preaddtomacro\CF_defaultarrowstyle}{\CF_arrowhead,}% + \let\CF_arrowstyle\CF_defaultarrowstyle + \CF_doifnotempty\CF_arrowstyle_{\CF_eaddtomacro\CF_arrowstyle{\expandafter,\CF_arrowstyle_}}% + \pgfmathsetmacro\CF_arrowdoublesep{\CF_arrowdoublesep/2}% + \pgfmathsetmacro\CF_arrowdoubleposstart{(1-\CF_arrowdoubleposstart)/2}% + \pgfmathsetmacro\CF_arrowdoubleposend{1-\CF_arrowdoubleposstart}% + \ifboolKV[chemfig]{scheme debug} + {\tikzpicture[every node/.style={draw,anchor=base,inner sep=0pt,outer sep=0pt,minimum size=1.5pt},baseline,remember picture]} + {\tikzpicture[every node/.style={anchor=base,inner sep=0pt,outer sep=0pt,minimum size=0pt},baseline,remember picture]}% + \let\merge\CF_merge + \expandafter\let\csname+\endcsname\CF_and + \let\arrow\CF_arrow + \let\schemestop\CF_schemestop + \let\subscheme\CF_subscheme + \CF_testopt{\CF_schemestartb}{text}% +} + +\def\CF_schemestartb[#1]{% + \ifnum\CF_schemenest=1 % la commande n'est pas imbriqu�e ? + \CF_cntcompound0 + \fi + \edef\CF_currentnodename{c\number\CF_cntcompound}% + \let\CF_nextnodename\empty + \let\CF_nextnodestyle\empty + \let\CF_directarrowlist\empty + \ifboolKV[chemfig]{scheme debug} + {\node[fill,green](\CF_currentnodename){};} + {\node(\CF_currentnodename){};}% + \def\CF_nextnodeanchor{#1}% + \CF_doifempty\CF_nextnodeanchor{\def\CF_nextnodeanchor{text}}% + \let\CF_compound\empty + \CF_schemestartc +} + +\def\CF_schemestartc{% + \futurelet\CF_toksa\CF_schemestarte +} + +\expandafter\def\expandafter\CF_schemestartd\space{\futurelet\CF_toksa\CF_schemestarte} + +\def\CF_schemestarte{% ... et l'examine : + \CF_iffirsttokina{\arrow\schemestop\merge}% + {} + {\CF_ifx\CF_toksa\bgroup + {\ifCF_compound_is_chemfig% bugfix 1.6 + \edef\CF_restore_hashcatcode{\catcode\number`\#=\number\catcode`\# \relax}% + \catcode`\#12 % TODO ou carr�ment mettre # � 12 dans tout l'environnement ? + \fi + \CF_addnextarg + } + {\CF_ifx\CF_toksa\CF_sptoken + {\CF_addtomacro\CF_compound{ }% + \CF_schemestartd + } + {\CF_ifx\CF_toksa\chemfig + \CF_compound_is_chemfigtrue% mettre le flag � vrai + {}% + \afterassignment\CF_schemestartc + \CF_addtomacro\CF_compound + }% + }% + }% +} + +\def\CF_addnextarg#1{% + \CF_addtomacro\CF_compound{{#1}}% + \ifCF_compound_is_chemfig% bugfix 1.6 + \CF_restore_hashcatcode + \CF_compound_is_chemfigfalse% mettre le flag � faux + \fi + \CF_schemestartc +} + +\def\CF_displaycompound#1#2{% #1 = nom et #2 = style + \CF_doifnotempty\CF_compound + {\global\advance\CF_cntcompound1 + \CF_ifx\CF_defaultcompoundstyle\empty + {\let\CF_currentnodestyle\empty} + {\CF_expsecond{\def\CF_currentnodestyle}{\CF_defaultcompoundstyle,}}% + \CF_addtomacro\CF_currentnodestyle{anchor=\CF_nextnodeanchor,at=(\CF_currentnodename)}% + \CF_ifempty{#2}% + {\CF_doifnotempty\CF_nextnodestyle + {\CF_eaddtomacro\CF_currentnodestyle{\expandafter,\CF_nextnodestyle}}% + } + {\CF_doifnotempty\CF_nextnodestyle + {\CF_warning{two styles for the same node, first style "\CF_nextnodestyle" ignored}% + }% + \CF_addtomacro\CF_currentnodestyle{,#2}% + }% + \CF_ifempty{#1} + {\edef\CF_temp{% + \CF_ifempty\CF_nextnodename + {c\number\CF_cntcompound} + {\CF_nextnodename}% + }% + } + {\CF_doifnotempty\CF_nextnodename + {\CF_warning{two names for the same node, first name "\CF_nextnodename" ignored}% + }% + \edef\CF_temp{#1}% + }% + \CF_expafter{\node[}\CF_currentnodestyle](\CF_temp){\CF_compound};% + \ifboolKV[chemfig]{scheme debug}% + {\node[draw=none,anchor=270,at=(\CF_temp.90),fill=green!60,overlay,opacity=0.5]{\scriptsize\bfseries\CF_temp};% + } + {}% + \let\CF_currentnodename\CF_temp + }% +} + +\def\CF_schemestop{% + \CF_displaycompound{}{}% + \CF_directarrowlist + \endtikzpicture + \xdef\CF_schemenest{\number\numexpr\CF_schemenest-1}% + \endgroup +} + +\def\CF_analysearrowarg#1{\CF_analysearrowarga#1[]\_nil} + +\def\CF_analysearrowarga#1[#2]#3\_nil{% + \CF_ifinstr{#1}. + {\CF_addtomacro\CF_temp{#1[#2]}} + {\CF_addtomacro\CF_temp{#1.[#2]}}% +} + +\def\CF_arrow{% + \CF_ifnextchar(% + {\CF_arrowa + } + {\CF_ifnextchar\bgroup + {\CF_arrowb(.[]--.[])} + {\CF_arrowb(.[]--.[]){}}% + }% +} + +\def\CF_arrowa(#1--#2){% + \def\CF_temp{(}% + \CF_analysearrowarg{#1}% + \CF_addtomacro\CF_temp{--}% + \CF_analysearrowarg{#2}% + \CF_addtomacro\CF_temp)% + \CF_ifnextchar\bgroup + {\expandafter\CF_arrowb\CF_temp} + {\expandafter\CF_arrowb\CF_temp{}}% +} + +\def\CF_arrowb(#1.#2[#3]--#4.#5[#6])#7{% + \def\CF_currentarrowtype{#7}% nom de la fl�che + \CF_doifempty\CF_currentarrowtype{\def\CF_currentarrowtype{->}}% + \CF_testopt{\CF_arrowc(#1.#2[#3]--#4.#5[#6])}{}% +} + +\def\CF_arrowc(#1.#2[#3]--#4.#5[#6])[#7]{% + \def\CF_temp{\CF_arrowe(#1.#2[#3]--#4.#5[#6])}% + \CF_arrowd#7,\empty,\empty\_nil +} + +\def\CF_arrowd#1,#2,#3\_nil{% + \CF_addtomacro\CF_temp{{#1}}% + \CF_eaddtomacro\CF_temp{\expandafter{#2}}% + \expandafter\CF_eaddtomacro\expandafter\CF_temp\expandafter{\expandafter\expandafter\expandafter{\expandafter\CF_sanitizelastitem#3,\empty\_nil}}% + \CF_temp +} + +% #1, #4 : nom des nodes #2, #5 : ancres des nodes #3, #6 : styles des nodes +% #7 : angle fl�che #8 : longueur fl�che #9 : style tikz de la fl�che +\def\CF_arrowe(#1.#2[#3]--#4.#5[#6])#7#8#9{% + \let\CF_arrowcurrentstyle\CF_arrowstyle + \if @\expandafter\CF_firsttonil\detokenize{#1.}\_nil% si #1 commence par @ + \if @\expandafter\CF_firsttonil\detokenize{#4.}\_nil + \CF_eaddtomacro\CF_directarrowlist{\expandafter\CF_directarrow\expandafter{\CF_currentarrowtype}{#1}{#2}{#4}{#5}{#9}}% + \let\CF_nextaction\CF_schemestartc + \else + \CF_doifnotempty\CF_arrowcurrentstyle{\CF_addtomacro\CF_arrowcurrentstyle,}% + \CF_doifnotempty{#9}{\CF_addtomacro\CF_arrowcurrentstyle{#9,}}% + \CF_displaycompound{}{#3}% + \def\CF_nextnodename{#4}% + \CF_expsecond{\def\CF_currentnodename}{\CF_gobarg#1}% + \let\CF_arrowstartname\CF_currentnodename + \let\CF_arrowendname\CF_nextnodename + \CF_arrowf{#7}{#8}{#2}{#5}% + \def\CF_nextnodestyle{#6}% + \fi + \else + \CF_doifnotempty\CF_arrowcurrentstyle{\CF_addtomacro\CF_arrowcurrentstyle,}% + \CF_doifnotempty{#9}{\CF_addtomacro\CF_arrowcurrentstyle{#9,}}% + \if @\expandafter\CF_firsttonil\detokenize{#2.}\_nil + \CF_error{syntax "(--@)" is not allowed}% + \else + \CF_displaycompound{#1}{#3}% + \edef\CF_arrowstartname{% + \CF_ifempty{#1} + \CF_currentnodename + {#1}% + \CF_doifnotempty{#2}{.#2}% + }% + \CF_arrowf{#7}{#8}{#2}{#5}% + \def\CF_nextnodename{#4}% + \def\CF_nextnodestyle{#6}% + \fi + \fi + \CF_arrowgobspaces% mange les espaces puis ex�cute \CF_nextaction +} + +\def\CF_arrowgobspaces{\futurelet\CF_toksa\CF_arrowgobspacesa} + +\def\CF_arrowgobspacesa{% + \CF_ifx\CF_sptoken\CF_toksa + \CF_arrowgobspacesb + \CF_nextaction +} + +\expandafter\def\expandafter\CF_arrowgobspacesb\space{\futurelet\CF_toksa\CF_arrowgobspacesa} + +\def\CF_arrowf#1#2#3#4{% #1=angle #2=longueur #3=ancre d�part #4=ancre arriv�e + \def\CF_nextaction{\let\CF_compound\empty\CF_schemestartc}% + \def\CF_arrowcurrentangle{#1}\CF_doifempty\CF_arrowcurrentangle{\let\CF_arrowcurrentangle\CF_arrowangle}% + \def\CF_currentarrowlength{#2}\CF_doifempty\CF_currentarrowlength{\let\CF_currentarrowlength\CF_arrowlength}% + \node[at=(\CF_currentnodename.\CF_ifempty{#3}\CF_arrowcurrentangle{#3}),shift=(\CF_arrowcurrentangle:\CF_currentarrowlength*\CF_compoundsep),cyan,fill](end@arrow@i@\number\CF_schemenest){};% + \edef\CF_arrowendname{end@arrow@i@\number\CF_schemenest\CF_doifnotempty{#4}{.#4}}% + \ifboolKV[chemfig]{scheme debug} + {\node[at=(\CF_currentnodename.\CF_ifempty{#3}\CF_arrowcurrentangle{#3}),shift=(\CF_arrowcurrentangle:\CF_arrowoffset),red,fill](start@arrow){};% + \node[at=(\CF_currentnodename.\CF_ifempty{#3}\CF_arrowcurrentangle{#3}),shift=(\CF_arrowcurrentangle:\CF_currentarrowlength*\CF_compoundsep-\CF_arrowoffset),red,fill](end@arrow){};% + } + {\node[at=(\CF_currentnodename.\CF_ifempty{#3}\CF_arrowcurrentangle{#3}),shift=(\CF_arrowcurrentangle:\CF_arrowoffset)](start@arrow){};% + \node[at=(\CF_currentnodename.\CF_ifempty{#3}\CF_arrowcurrentangle{#3}),shift=(\CF_arrowcurrentangle:\CF_currentarrowlength*\CF_compoundsep-\CF_arrowoffset)](end@arrow){};% + }% + \def\CF_arrowstartnode{start@arrow}\def\CF_arrowendnode{end@arrow}% + \csname\expandafter\CF_grabarrowname\CF_currentarrowtype[\_nil\CF_threeea\endcsname + \expandafter\CF_grabarrowargs\CF_currentarrowtype[]\_nil[][][][][][][][]\_nil + \def\CF_currentnodename{end@arrow@i@\number\CF_schemenest}% + \edef\CF_nextnodeanchor{\CF_ifempty{#4}{180+\CF_arrowcurrentangle}{#4}}% +} + +% trace un fl�che initi�e par (@nom--@nom) +% #1=type de fl�che #2=nom depart #3=ancre d�part #4=nom arriv�e #5=ancre arriv�e #6=style fl�che +\def\CF_directarrow#1#2#3#4#5#6{% + \CF_expsecond{\def\CF_arrowstartname}{\CF_gobarg#2}% + \CF_expsecond{\def\CF_arrowendname}{\CF_gobarg#4}% + \path[sloped,allow upside down](\CF_gobarg#2\ifx\empty#3\empty\else.#3\fi)--(\CF_gobarg#4\ifx\empty#5\empty\else.#5\fi)% + coordinate[pos=0,xshift=\CF_arrowoffset](start@direct@arrow)% + coordinate[pos=1,xshift=-\CF_arrowoffset](end@direct@arrow);% + \def\CF_arrowstartnode{start@direct@arrow}% + \def\CF_arrowendnode{end@direct@arrow}% + \pgfmathanglebetweenpoints + {\pgfpointanchor{\CF_gobarg#2}{\ifx\empty#3\empty center\else#3\fi}}% Ne pas utiliser \CF_ifempty ici !!! + {\pgfpointanchor{\CF_gobarg#4}{\ifx\empty#5\empty center\else#5\fi}}% + \let\CF_arrowcurrentangle\pgfmathresult + \CF_doifnotempty{#6}{\CF_addtomacro\CF_arrowcurrentstyle{#6,}}% + \csname\CF_grabarrowname#1[]\_nil\expandafter\endcsname\CF_grabarrowargs#1[]\_nil[][][][][][][][]\_nil +} + +\def\CF_mergegrabchardir#1[#2][#3]#4\_nil{% + \CF_expafter{\futurelet\CF_toksa\CF_gobtonil}{\CF_firsttonil#1>\_nil}\_nil + \ifx>\CF_toksa + \def\CF_mergeangle{0}\def\CF_mergeextreme{xmax}\def\CF_mergesign{+}% + \else + \ifx<\CF_toksa + \def\CF_mergeangle{180}\def\CF_mergeextreme{xmin}\def\CF_mergesign{-}% + \else + \ifx^\CF_toksa + \def\CF_mergeangle{90}\def\CF_mergeextreme{ymax}\def\CF_mergesign{+}% + \else + \ifx v\CF_toksa + \def\CF_mergeangle{-90}\def\CF_mergeextreme{ymin}\def\CF_mergesign{-}% + \fi\fi\fi\fi + \def\CF_mergelabelup{#2}\def\CF_mergelabeldo{#3}% +} + +\def\CF_merge#1({% + \CF_mergegrabchardir#1[][]\_nil + \CF_mergea(% +} + +\def\CF_mergea#1--(#2){\CF_testopt{\CF_mergeb#1--(#2)}{}} + +\def\CF_mergeb#1--(#2)[#3]{% + \CF_displaycompound{}{}% + \CF_parsemergeopt#3,\CF_quark,\CF_quark,\CF_quark\_nil + \def\CF_mergexmax{-16383.99999pt}\let\CF_mergeymax\CF_mergexmax + \def\CF_mergexmin{16383.99999pt}\let\CF_mergeymin\CF_mergexmin + \CF_mergeparsenodelist#1(\relax)% calcule les maxi des positions + \pgfmathsetmacro\CF_mergeextremeresult{\csname CF_merge\CF_mergeextreme\endcsname\CF_mergesign\CF_mergefromcoeff*\CF_compoundsep}% + \CF_mergec#1(\relax)% trace les lignes entre les noeuds pr�c�dents et la ligne de jonction + \CF_expsecond{\def\CF_temp}{\expandafter[\CF_mergestyle,shorten <=0,shorten >=0,-]}% + \if x\expandafter\CF_firsttonil\CF_mergeextreme\_nil + \CF_addtomacro\CF_temp{(\CF_mergeextremeresult pt,\CF_mergeymax)--(\CF_mergeextremeresult pt,\CF_mergeymin)}% + \else + \CF_addtomacro\CF_temp{(\CF_mergexmin,\CF_mergeextremeresult pt)--(\CF_mergexmax,\CF_mergeextremeresult pt)}% + \fi + \expandafter\draw\CF_temp node[pos=\CF_mergesplitcoeff](merge@point){}% trace la ligne de jonction + node[at=(merge@point),shift=(\CF_mergeangle:\CF_compoundsep*\CF_mergetocoeff-\CF_arrowoffset)](end@merge){}% + node[at=(merge@point),shift=(\CF_mergeangle:\CF_compoundsep*\CF_mergetocoeff)](end@merge@i){};% + \let\CF_arrowcurrentangle\CF_mergeangle + \CF_expafter{\draw[}\CF_mergestyle,shorten <=0](merge@point)--(end@merge)% + \expandafter\CF_arrowdisplaylabela\expandafter{\CF_mergelabelup}{.5}+\expandafter\CF_arrowdisplaylabela\expandafter{\CF_mergelabeldo}{.5}-;% + \def\CF_currentnodename{end@merge@i}% + \let\CF_temp\empty + \CF_analysearrowarg{#2}% + \expandafter\CF_merged\CF_temp\_nil +} + +\def\CF_mergec(#1){% + \if\relax\expandafter\noexpand\CF_firsttonil#1\_nil + \else + \CF_ifdot{#1}% + {\edef\merge_currentnodename{\CF_beforedot#1\_nil}% + \edef\merge_currentanchor{\CF_afterdot#1\_nil}% + }% + {\def\merge_currentnodename{#1}% + \let\merge_currentanchor\CF_mergeangle + }% + \if x\expandafter\CF_firsttonil\CF_mergeextreme\_nil + \pgfextracty\CF_dim{\pgfpointanchor\merge_currentnodename\merge_currentanchor}% + \CF_expafter{\draw[}\CF_mergestyle,shorten >=0,-]([shift=(\CF_mergeangle:\CF_arrowoffset)]\merge_currentnodename.\merge_currentanchor)--(\CF_mergeextremeresult pt,\CF_dim);% + \else + \pgfextractx\CF_dim{\pgfpointanchor\merge_currentnodename\merge_currentanchor}% + \CF_expafter{\draw[}\CF_mergestyle,shorten >=0,-]([shift=(\CF_mergeangle:\CF_arrowoffset)]\merge_currentnodename.\merge_currentanchor)--(\CF_dim,\CF_mergeextremeresult pt);% + \fi + \expandafter\CF_mergec + \fi +} + +\def\CF_merged#1.#2[#3]\_nil{% + \def\CF_nextnodename{#1}% + \edef\CF_nextnodeanchor{% + \CF_ifempty{#2} + {180+\CF_mergeangle} + {#2}% + }% + \def\CF_nextnodestyle{#3}% + \let\CF_compound\empty + \CF_schemestartc +} + +\def\CF_parsemergeopt#1,#2,#3,#4\_nil{% + \CF_ifempty{#1} + {\def\CF_mergefromcoeff{0.5}} + {\def\CF_mergefromcoeff{#1}}% + \def\CF_mergetocoeff{0.5}% + \def\CF_mergesplitcoeff{0.5}% + \CF_expsecond{\def\CF_mergestyle}{\CF_arrowhead}% + \CF_iffirsttokmatch\CF_quark{#2\relax} + {} + {\CF_ifempty{#2} + {\def\CF_mergetocoeff{0.5}} + {\def\CF_mergetocoeff{#2}}% + \CF_iffirsttokmatch\CF_quark{#3\relax} + {} + {\CF_ifempty{#3} + {\def\CF_mergesplitcoeff{0.5}} + {\def\CF_mergesplitcoeff{#3}}% + \CF_iffirsttokmatch\CF_quark{#4\relax} + {} + {\CF_parsemergeopta#4\_nil}% + }% + }% +} + +\def\CF_parsemergeopta#1,\CF_quark#2\_nil{% + \CF_ifempty{#1} + {} + {\CF_addtomacro\CF_mergestyle{,#1}}% +} + +\def\CF_mergeparsenodelist(#1){% + \if\relax\expandafter\noexpand\CF_firsttonil#1\_nil + \else + \CF_ifdot{#1}% + {\edef\merge_currentnodename{\CF_beforedot#1\_nil}\edef\merge_currentanchor{\CF_afterdot#1\_nil}}% + {\def\merge_currentnodename{#1}\let\merge_currentanchor\CF_mergeangle}% + \pgfextractx\CF_dim{\pgfpointanchor\merge_currentnodename\merge_currentanchor}% + \ifdim\CF_dim>\CF_mergexmax + \edef\CF_mergexmax{\the\CF_dim}% + \fi + \ifdim\CF_dim<\CF_mergexmin + \edef\CF_mergexmin{\the\CF_dim}% + \fi + \pgfextracty\CF_dim{\pgfpointanchor\merge_currentnodename\merge_currentanchor}% + \ifdim\CF_dim>\CF_mergeymax + \edef\CF_mergeymax{\the\CF_dim}% + \fi + \ifdim\CF_dim<\CF_mergeymin + \edef\CF_mergeymin{\the\CF_dim}% + \fi + \expandafter\CF_mergeparsenodelist + \fi +} + +\def\CF_grabarrowname#1[#2\_nil{\detokenize{CF_arrow(#1)}} +\def\CF_grabarrowargs#1[#2\_nil{[#2} + +\def\CF_makeparametertext#1{% + \toks0{}% + \CF_cntgroup#1\relax + \CF_makeparametertexta1% +} + +\def\CF_makeparametertexta#1{% + \unless\ifnum#1>\CF_cntgroup + \toks0\expandafter{\the\toks0[###1]}% + \expandafter\CF_makeparametertexta\expandafter{\number\numexpr#1+1\expandafter}% + \fi +} + +% #1 est le nombre d'arguments optionnels, #2 est le nom et #3 le code +\def\definearrow#1#2#3{% + \begingroup + \CF_makeparametertext{#1}% + \expandafter\endgroup + \expandafter\def\csname\detokenize{CF_arrow(#2)}\expandafter\endcsname\the\toks0{#3\CF_gobtonil}% +} + +\def\CF_ifdot#1{\CF_ifdota#1.\_nil} +\def\CF_ifdota#1.#2\_nil{\ifx\empty#2\empty\expandafter\CF_execsecond\else\expandafter\CF_execfirst\fi} +\def\CF_beforedot#1.#2\_nil{#1} +\def\CF_afterdot#1.#2\_nil{#2} + +\def\CF_rotatenode*#1#2\_nil{% + \CF_ifdot{#1} + {\CF_beforedot#1\_nil} + {#1}% +} +\def\CF_anchornode*#1#2\_nil#3{% + \CF_ifdot{#1} + {\CF_afterdot#1\_nil} + {\CF_arrowcurrentangle-#390-#1}% +} + +% #1 = label #2 = position #3 = + ou - (au dessus ou au dessous) #4 : nom du noeud de d�part +% #5 = label #6 = position #7 = + ou - (au dessus ou au dessous) #8 : nom du noeud de fin +\def\CF_arrowdisplaylabel#1#2#3#4#5#6#7#8{% + \CF_doifnotempty{#1#5} + {\path(#4)--(#8)\CF_arrowdisplaylabela{#1}{#2}{#3}\CF_arrowdisplaylabela{#5}{#6}{#7};}% +} + +\def\CF_arrowdisplaylabela#1#2#3{% + \CF_doifnotempty{#1} + {\if*\expandafter\CF_firsttonil\detokenize{#1}\_nil + \ifboolKV[chemfig]{scheme debug} + {node[pos=#2,sloped,yshift=#3\CF_arrowlabelsep,draw,fill,cyan](shifted@node){}% + node[draw,rotate=\CF_rotatenode#1\_nil,anchor=\CF_anchornode#1\_nil#3,at=(shifted@node)]{\expandafter\CF_gobarg\CF_gobarg#1}% + } + {node[pos=#2,sloped,yshift=#3\CF_arrowlabelsep](shifted@node){}% + node[rotate=\CF_rotatenode#1\_nil,anchor=\CF_anchornode#1\_nil#3,at=(shifted@node)]{\expandafter\CF_gobarg\CF_gobarg#1}% + }% + \else + \ifboolKV[chemfig]{scheme debug} + {node[pos=#2,sloped,yshift=#3\CF_arrowlabelsep,draw,fill,cyan](shifted@node){}% + node[draw,pos=#2,anchor=-#390,sloped,yshift=#3\CF_arrowlabelsep]{#1}% + } + {node[pos=#2,anchor=-#390,sloped,yshift=#3\CF_arrowlabelsep]{#1}% + } + \fi + }% +} + +% pose des noeuds d�cal�s de la dimension #1 � (\CF_arrowstartnode) et (\CF_arrowendnode) +\def\CF_arrowshiftnodes#1{% + \unless\ifdim\CF_ifempty{#1}\CF_zero{#1}=0pt + \expanded{% + \noexpand\path(\CF_arrowstartnode)--(\CF_arrowendnode)% + node[pos=0,sloped,yshift=#1](\CF_arrowstartnode1){}node[pos=1,sloped,yshift=#1](\CF_arrowendnode1){};}% + \edef\CF_arrowstartnode{\CF_arrowstartnode1}\edef\CF_arrowendnode{\CF_arrowendnode1}% + \fi +} + +\definearrow3{->}{% + \CF_arrowshiftnodes{#3}% + \CF_expafter{\draw[}\CF_arrowcurrentstyle](\CF_arrowstartnode)--(\CF_arrowendnode);% + \CF_arrowdisplaylabel{#1}{0.5}+\CF_arrowstartnode{#2}{0.5}-\CF_arrowendnode +} + +\definearrow3{<-}{% + \CF_arrowshiftnodes{#3}% + \CF_expafter{\draw[}\CF_arrowcurrentstyle](\CF_arrowendnode)--(\CF_arrowstartnode);% + \CF_arrowdisplaylabel{#1}{0.5}+\CF_arrowstartnode{#2}{0.5}-\CF_arrowendnode +} + +\definearrow5{-/>}{% + \CF_arrowshiftnodes{#3}% + \CF_expafter{\draw[}\CF_arrowcurrentstyle](\CF_arrowstartnode)--(\CF_arrowendnode)% + coordinate[midway,shift=(\CF_arrowcurrentangle:-1pt)](midway@i)% + coordinate[midway,shift=(\CF_arrowcurrentangle:1pt)](midway@ii)% + coordinate[at=(midway@i),shift=(\CF_ifempty{#4}{225}{#4+180}+\CF_arrowcurrentangle:\CF_ifempty{#5}{5pt}{#5})](line@start)% + coordinate[at=(midway@i),shift=(\CF_ifempty{#4}{45}{#4}+\CF_arrowcurrentangle:\CF_ifempty{#5}{5pt}{#5})](line@end)% + coordinate[at=(midway@ii),shift=(\CF_ifempty{#4}{225}{#4+180}+\CF_arrowcurrentangle:\CF_ifempty{#5}{5pt}{#5})](line@start@i)% + coordinate[at=(midway@ii),shift=(\CF_ifempty{#4}{45}{#4}+\CF_arrowcurrentangle:\CF_ifempty{#5}{5pt}{#5})](line@end@i); + \draw(line@start)--(line@end);% + \draw(line@start@i)--(line@end@i);% + \CF_arrowdisplaylabel{#1}{0.5}+\CF_arrowstartnode{#2}{0.5}-\CF_arrowendnode +} + +\definearrow3{<->}{% + \CF_arrowshiftnodes{#3}% + \CF_expafter{\draw[}\CF_arrowcurrentstyle,\CF_arrowtip-\CF_arrowtip](\CF_arrowstartnode)--(\CF_arrowendnode);% + \CF_arrowdisplaylabel{#1}{0.5}+\CF_arrowstartnode{#2}{0.5}-\CF_arrowendnode +} + +\definearrow3{<=>}{% + \CF_arrowshiftnodes{#3}% + \path[allow upside down](\CF_arrowstartnode)--(\CF_arrowendnode)% + node[pos=0,sloped,yshift=\CF_arrowdoublesep](\CF_arrowstartnode @u0){}% + node[pos=0,sloped,yshift=-\CF_arrowdoublesep](\CF_arrowstartnode @d0){}% + node[pos=1,sloped,yshift=\CF_arrowdoublesep](\CF_arrowstartnode @u1){}% + node[pos=1,sloped,yshift=-\CF_arrowdoublesep](\CF_arrowstartnode @d1){};% + \begingroup + \ifboolKV[chemfig]{arrow double harpoon} + {\pgfarrowharpoontrue} + {}% + \CF_expafter{\draw[}\CF_arrowcurrentstyle](\CF_arrowstartnode @u0)--(\CF_arrowstartnode @u1);% + \CF_expafter{\draw[}\CF_arrowcurrentstyle](\CF_arrowstartnode @d1)--(\CF_arrowstartnode @d0);% + \endgroup + \CF_arrowdisplaylabel{#1}{0.5}+\CF_arrowstartnode{#2}{0.5}-\CF_arrowendnode% +} + +\definearrow3{<->>}{% + \CF_arrowshiftnodes{#3}% + \path[allow upside down](\CF_arrowstartnode)--(\CF_arrowendnode)% + node[pos=0,sloped,yshift=1pt](\CF_arrowstartnode @u0){}% + node[pos=\CF_arrowdoubleposstart,sloped,yshift=-1pt](\CF_arrowstartnode @d0){}% + node[pos=1,sloped,yshift=1pt](\CF_arrowstartnode @u1){}% + node[pos=\CF_arrowdoubleposend,sloped,yshift=-1pt](\CF_arrowstartnode @d1){};% + \begingroup + \ifboolKV[chemfig]{arrow double harpoon} + {\pgfarrowharpoontrue} + {}% + \CF_expafter{\draw[}\CF_arrowcurrentstyle](\CF_arrowstartnode @u0)--(\CF_arrowstartnode @u1);% + \CF_expafter{\draw[}\CF_arrowcurrentstyle](\CF_arrowstartnode @d1)--(\CF_arrowstartnode @d0);% + \endgroup + \CF_arrowdisplaylabel{#1}{0.5}+\CF_arrowstartnode{#2}{0.5}-\CF_arrowendnode% +} + +\definearrow3{<<->}{% + \path[allow upside down](\CF_arrowstartnode)--(\CF_arrowendnode)% + node[pos=\CF_arrowdoubleposstart,sloped,yshift=1pt](\CF_arrowstartnode @u0){}% + node[pos=0,sloped,yshift=-1pt](\CF_arrowstartnode @d0){}% + node[pos=\CF_arrowdoubleposend,sloped,yshift=1pt](\CF_arrowstartnode @u1){}% + node[pos=1,sloped,yshift=-1pt](\CF_arrowstartnode @d1){};% + \begingroup + \ifboolKV[chemfig]{arrow double harpoon} + {\pgfarrowharpoontrue} + {}% + \CF_expafter{\draw[}\CF_arrowcurrentstyle](\CF_arrowstartnode @u0)--(\CF_arrowstartnode @u1);% + \CF_expafter{\draw[}\CF_arrowcurrentstyle](\CF_arrowstartnode @d1)--(\CF_arrowstartnode @d0);% + \endgroup + \CF_arrowdisplaylabel{#1}{0.5}+\CF_arrowstartnode{#2}{0.5}-\CF_arrowendnode +} + +\definearrow30{% + \CF_arrowshiftnodes{#3}% + \CF_arrowdisplaylabel{#1}{0.5}+\CF_arrowstartnode{#2}{0.5}-\CF_arrowendnode +} + +\definearrow5{-U>}{% + \CF_arrowshiftnodes{#3}% + \CF_expafter{\draw[}\CF_arrowcurrentstyle](\CF_arrowstartnode)--(\CF_arrowendnode)node[midway](Uarrow@arctangent){};% + \CF_ifempty{#4} + {\def\CF_Uarrowradius{0.333}} + {\def\CF_Uarrowradius{#4}}% + \CF_ifempty{#5}% + {\def\CF_Uarrowabsangle{60}} + {\pgfmathsetmacro\CF_Uarrowabsangle{abs(#5)}}% ne prendre en compte que la valeur absolue de l'angle + \expandafter\draw\expanded{[\CF_ifempty{#1}{draw=none}{\unexpanded\expandafter{\CF_arrowcurrentstyle}},-]}(Uarrow@arctangent)% + arc[radius=\CF_compoundsep*\CF_currentarrowlength*\CF_Uarrowradius,start angle=\CF_arrowcurrentangle-90,delta angle=-\CF_Uarrowabsangle]node(Uarrow@start){}; + \expandafter\draw\expanded{[\CF_ifempty{#2}{draw=none}{\unexpanded\expandafter{\CF_arrowcurrentstyle}}]}(Uarrow@arctangent)% + arc[radius=\CF_compoundsep*\CF_currentarrowlength*\CF_Uarrowradius,start angle=\CF_arrowcurrentangle-90,delta angle=\CF_Uarrowabsangle]node(Uarrow@end){}; + \pgfmathsetmacro\CF_temp{\CF_Uarrowradius*cos(\CF_arrowcurrentangle)<0?"-":"+"}% + \ifdim\CF_Uarrowradius pt>0pt + \CF_arrowdisplaylabel{#1}{0}\CF_temp{Uarrow@start}{#2}{1}\CF_temp{Uarrow@end}% + \else + \CF_arrowdisplaylabel{#2}{0}\CF_temp{Uarrow@start}{#1}{1}\CF_temp{Uarrow@end}% + \fi +} + +\def\CF_grabdelim#1#2#3\_CFnil{\def\CF_leftdelim{#1}\def\CF_rightdelim{#2}} +\defKV[CFdelimiters]{% + delimiters = \CF_grabdelim#1()\_CFnil, + height = \def\CF_delimheight{#1}, + depth = \CF_expsecond{\CF_defifempty\CF_delimdepth{#1}}{\CF_delimheight}, + open xshift = \edef\CF_leftdelimxshift{\the\dimexpr#1}, + close xshift = \edef\CF_rightdelimxshift{\CF_ifempty{#1}{-\CF_leftdelimxshift}{-\the\dimexpr#1}} +} +\setKVdefault[CFdelimiters]{% + delimiters = (), + height = 10pt, + depth = , + open xshift = 0pt, + close xshift = , + h align = true, + auto rotate = false, + rotate = 0, + indice = n +}% +\def\polymerdelim{\CF_ifnextchar[{\CF_polymerdelima}{\CF_polymerdelima[]}} +\def\CF_polymerdelima[#1]#2#3{% + \restoreKV[CFdelimiters]% + \CF_doifnotempty{#1}{\setKV[CFdelimiters]{#1}}% + \edef\CF_delimhalfdim{\the\dimexpr(\CF_delimheight+\CF_delimdepth)/2}% + \edef\CF_delimvshift {\the\dimexpr(\CF_delimheight-\CF_delimdepth)/2}% + \chemmove{% + \nulldelimiterspace0pt + \pgfextractx\CF_dim{\pgfpointanchor{#2}{center}}\edef\CF_leftdelimx{\the\CF_dim}% + \pgfextracty\CF_dim{\pgfpointanchor{#2}{center}}\edef\CF_leftdelimy{\the\CF_dim}% + \pgfextractx\CF_dim{\pgfpointanchor{#3}{center}}\edef\CF_rightdelimx{\the\CF_dim}% + \pgfextracty\CF_dim{\pgfpointanchor{#3}{center}}\edef\CF_rightdelimy{\the\CF_dim}% + \def\CF_autorotate{0}% + \ifboolKV[CFdelimiters]{h align} + {\let\CF_rightdelimy\CF_leftdelimy + } + {% + \ifboolKV[CFdelimiters]{auto rotate} + {\pgfmathatantwo{\CF_rightdelimy-\CF_leftdelimy}{\CF_rightdelimx-\CF_leftdelimx}% + \let\CF_autorotate\pgfmathresult + } + {\CF_eexpsecond\CF_ifempty{\useKV[CFdelimiters]{rotate}} + {} + {\edef\CF_autorotate{\useKV[CFdelimiters]{rotate}}}% + }% + }% + \node[at={(\CF_leftdelimx+\CF_leftdelimxshift,\CF_leftdelimy+\CF_delimvshift)},rotate=\CF_autorotate] + {$\left\CF_leftdelim\vrule height\CF_delimhalfdim depth\CF_delimhalfdim width0pt\right.$};% + \node[at={(\CF_rightdelimx+\CF_rightdelimxshift,\CF_rightdelimy+\CF_delimvshift)},rotate=\CF_autorotate] + {$\left.\vrule height\CF_delimhalfdim depth\CF_delimhalfdim width0pt\right\CF_rightdelim + \CF_eexpsecond\CF_doifnotempty{\useKV[CFdelimiters]{indice}} + {\CF_underscore{\rlap{$\scriptstyle\useKV[CFdelimiters]{indice}$}}} + $}; + }% +} + +\catcode`\@11 +\pgfdeclarearrow{% + name = CF,% + defaults = {% + length = 3pt 5 1,% + width' = 0pt .8,% + inset' = 0pt .5,% + line width = 0pt 1 1,% + round% + },% + setup code = {% + % Cap the line width at 1/4th distance from inset to tip + \pgf@x\pgfarrowlength + \advance\pgf@x by-\pgfarrowinset + \pgf@x.25\pgf@x + \ifdim\pgf@x<\pgfarrowlinewidth\pgfarrowlinewidth\pgf@x\fi + % Compute front miter length: + \pgfmathdivide@{\pgf@sys@tonumber\pgfarrowlength}{\pgf@sys@tonumber\pgfarrowwidth}% + \let\pgf@temp@quot\pgfmathresult% + \pgf@x\pgfmathresult pt% + \pgf@x\pgfmathresult\pgf@x% + \pgf@x4\pgf@x% + \advance\pgf@x by1pt% + \pgfmathsqrt@{\pgf@sys@tonumber\pgf@x}% + \pgf@xc\pgfmathresult\pgfarrowlinewidth% xc is front miter + \pgf@xc.5\pgf@xc + \pgf@xa\pgf@temp@quot\pgfarrowlinewidth% xa is extra harpoon miter + % Compute back miter length: + \pgf@ya.5\pgfarrowwidth% + \csname pgfmathatan2@\endcsname{\pgfmath@tonumber\pgfarrowlength}{\pgfmath@tonumber\pgf@ya}% + \pgf@yb\pgfmathresult pt% + \csname pgfmathatan2@\endcsname{\pgfmath@tonumber\pgfarrowinset}{\pgfmath@tonumber\pgf@ya}% + \pgf@ya\pgfmathresult pt% + \advance\pgf@yb by-\pgf@ya% + \pgf@yb.5\pgf@yb% half angle in yb + \pgfmathtan@{\pgf@sys@tonumber\pgf@yb}% + \pgfmathreciprocal@{\pgfmathresult}% + \pgf@yc\pgfmathresult\pgfarrowlinewidth% + \pgf@yc.5\pgf@yc% + \advance\pgf@ya by\pgf@yb% + \pgfmathsincos@{\pgf@sys@tonumber\pgf@ya}% + \pgf@ya\pgfmathresulty\pgf@yc% ya is the back miter + \pgf@yb\pgfmathresultx\pgf@yc% yb is the top miter + \ifdim\pgfarrowinset=0pt + \pgf@ya.5\pgfarrowlinewidth% easy: back miter is half linewidth + \fi + % Compute inset miter length: + \pgfmathdivide@{\pgf@sys@tonumber\pgfarrowinset}{\pgf@sys@tonumber\pgfarrowwidth}% + \let\pgf@temp@quot\pgfmathresult% + \pgf@x\pgfmathresult pt% + \pgf@x\pgfmathresult\pgf@x% + \pgf@x4\pgf@x%\pgf@ya + \advance\pgf@x by1pt% + \pgfmathsqrt@{\pgf@sys@tonumber\pgf@x}% + \pgf@yc\pgfmathresult\pgfarrowlinewidth% yc is inset miter + \pgf@yc.5\pgf@yc% + % Inner length (pgfutil@tempdima) is now arrowlength - front miter - back miter + \pgfutil@tempdima\pgfarrowlength% + \advance\pgfutil@tempdima by-\pgf@xc% + \advance\pgfutil@tempdima by-\pgf@ya% + \pgfutil@tempdimb.5\pgfarrowwidth% + \advance\pgfutil@tempdimb by-\pgf@yb% + % harpoon miter correction + \ifpgfarrowroundjoin + \pgfarrowssetbackend{\pgf@ya\advance\pgf@x by-.5\pgfarrowlinewidth}% + \else + \pgfarrowssetbackend{0pt} + \fi + \ifpgfarrowharpoon + \pgfarrowssetlineend{\pgfarrowinset\advance\pgf@x by\pgf@yc\advance\pgf@x by.5\pgfarrowlinewidth}% + \else + \pgfarrowssetlineend{\pgfarrowinset\advance\pgf@x by\pgf@yc\advance\pgf@x by-.25\pgfarrowlinewidth}% + \ifpgfarrowreversed + \ifdim\pgfinnerlinewidth>0pt + \pgfarrowssetlineend{\pgfarrowinset}% + \else + \pgfarrowssetlineend{\pgfutil@tempdima\advance\pgf@x by\pgf@ya\advance\pgf@x by-.25\pgfarrowlinewidth}% + \fi + \fi + \fi + \ifpgfarrowroundjoin + \pgfarrowssettipend{\pgfutil@tempdima\advance\pgf@x by\pgf@ya\advance\pgf@x by.5\pgfarrowlinewidth}% + \else + \pgfarrowssettipend{\pgfarrowlength\ifpgfarrowharpoon\advance\pgf@x by\pgf@xa\fi}% + \fi + % The hull: + \pgfarrowshullpoint{\pgfarrowlength\ifpgfarrowroundjoin\else\ifpgfarrowharpoon\advance\pgf@x by\pgf@xa\fi\fi}{\ifpgfarrowharpoon-.5\pgfarrowlinewidth\else0pt\fi}% + \pgfarrowsupperhullpoint{0pt}{.5\pgfarrowwidth}% + \pgfarrowshullpoint{\pgfarrowinset}{\ifpgfarrowharpoon-.5\pgfarrowlinewidth\else 0pt\fi}% + % Adjust inset + \pgfarrowssetvisualbackend{\pgfarrowinset}% + \advance\pgfarrowinset by\pgf@yc% + % The following are needed in the code: + \pgfarrowssavethe\pgfutil@tempdima + \pgfarrowssavethe\pgfutil@tempdimb + \pgfarrowssavethe\pgfarrowlinewidth + \pgfarrowssavethe\pgf@ya + \pgfarrowssavethe\pgfarrowinset + },% + drawing code = {% + \pgfsetdash{}{0pt}% + \ifpgfarrowroundjoin\pgfsetroundjoin\else\pgfsetmiterjoin\fi + \ifdim\pgfarrowlinewidth=\pgflinewidth\else\pgfsetlinewidth{\pgfarrowlinewidth}\fi + \pgfpathmoveto{\pgfqpoint{\pgfutil@tempdima\advance\pgf@x by\pgf@ya}{0pt}}% + \pgfpathlineto{\pgfqpoint{\pgf@ya}{\pgfutil@tempdimb}}% + \pgfpathlineto{\pgfqpoint{\pgfarrowinset}{0pt}}% + \ifpgfarrowharpoon \else + \pgfpathlineto{\pgfqpoint{\pgf@ya}{-\pgfutil@tempdimb}}% + \fi + \pgfpathclose + \ifpgfarrowopen\pgfusepathqstroke\else\ifdim\pgfarrowlinewidth>0pt \pgfusepathqfillstroke\else\pgfusepathqfill\fi\fi + },% + parameters = {% + \the\pgfarrowlinewidth,% + \the\pgfarrowlength,% + \the\pgfarrowwidth,% + \the\pgfarrowinset,% + \ifpgfarrowharpoon h\fi% + \ifpgfarrowopen o\fi% + \ifpgfarrowroundjoin j\fi% + }% +} +\CFrestorecatcode +\endinput + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%%% H I S T O R I Q U E %%% +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +v0.1 2010/06/23 + - Premi�re version publique sur le CTAN +---------------------------------------------------------------------- +v0.2 2010/08/31 + - Ajout de la documentation en anglais. + - Correction de bugs. + - \printatom est d�sormais une macro publique. + - Les espaces sont permis dans les mol�cules. Ils seront + ignor�s par d�faut puisque les atomes sont compos�s en + mode math par \printatom + - Une paire de Lewis peut �tre repr�sent�e ":". + - Dans les cycles, une correction de la longueur du trait + d�port� des liaisons doubles est fait de telle sorte que si + l'on �crit \chemfig{*5(=====)}, on obtient deux polygones + r�guliers concentriques. + - La s�quence de contr�le \setnodestyle permet de sp�cifier + le style des n?uds dessin�s par tikz. +---------------------------------------------------------------------- +v0.3 2010/11/21 + - Am�lioration de \definesubmol qui accepte les s�quences de + contr�le. On peut aussi choisir un alias dont la substitution + est diff�rente selon l'orientation de la liaison qui lui + arrive dessus. + - Le caract�re "|" force la fin d'un atome. Si on �crit + "D|ef" alors, chemfig verra deux atomes "D" et "ef". + - Le caract�re "#" est reconnu lorsqu'il suit un caract�re de + liaison. Il doit �tre suivi d'un argument entre parenth�ses + qui contient l'offset de d�but et de fin qui s'appliqueront + � cette liaison. + - La macro \chemfig admet un argument optionnel qui sera pass� + � l'environnement tikzpicture dans lequel elle est dessin�e + - Mise en place de la repr�sentation des m�canismes + r�actionnels avec la syntaxe "@{}" devant un atome o� + "@{,}" au tout d�but de l'argument d'une liaison. + Cette syntaxe permet de placer un n?ud (au sens de tikz) qui + deviendra l'extr�mit� des fl�ches des m�canismes. + Le trac� des fl�ches est faite par la macro \chemmove dont + l'argument optionnel devient celui de l'environnement + tikzpicture dans lequel sont faites les fl�ches. + - Pour le m�canisme d'alignement vertical via le \vphantom, la + commande \chemskipalign permet d'ignorer le groupe d'atomes + dans lequel elle est �crite. + - La commande \chemname permet d'afficher un nom sous une + mol�cule. la commande \chemnameinit initialise la plus grande + profondeur rencontr�e. + - La commande \lewis a �t� modifi�e de telle sorte que les + dessins des d�corations soient proportionnels � la taille + de la police. +---------------------------------------------------------------------- +v0.3a 2011/01/08 + - Correction d'un bug dans l'argument optionnel de \definesubmol + lorsque celui-ci comporte des crochets. + - Mise � jour du manuel en anglais. + - Ajout de \vflipnext et \hflipnext pour retourner + horizontalement ou verticalement la prochaine mol�cule. +---------------------------------------------------------------------- +v0.4 2011/03/07 + - chemfig est d�sormais �crit en plain-etex et donc + utilisable par d'autres formats que LaTeX. + - Un peu plus de rigueur avec les catcodes des caract�res + sp�ciaux, notamment lorsque la commande \chemfig se trouve + dans l'argument de \chemmove, \chemabove, \chembelow, \chemrel. + TODO : faut-il \scantoker l'argument de \chemfig pour �tre + d�finitivement d�barrass� de ces histoires de catcode ??? + - Correction d'un bug dans le calcul de l'angle des liaisons +---------------------------------------------------------------------- +v0.4a 2011/04/10 + - Correction d'un bug concernant l'argument optionnel en d�but + de mol�cule. +---------------------------------------------------------------------- +v0.4b 2011/04/24 + - l'argument de \chemfig est tok�nis� avec \scantokens ce qui + rend caduc tout souci de code de cat�gorie, � part #. + - la commande \setbondstyle permet de d�finir le style des + liaisons. + - correction de l'affichage incorrect des doubles liaisons dans + les cycles apr�s les commandes \hflipnext et \vflipnext + - correction d'un bug lorsqu'un alias commence une mol�cule +---------------------------------------------------------------------- +v1.0 2011/06/15 + - les sch�mas r�actionnels sont d�sormais disponibles. + - \Chemabove et \Chembelow modifient la boite englobante. + - \Lewis modifie la boite englobante + - les macros \chemleft, \chemright, \chemup et \chemdown + affichent des d�limiteurs extensibles � gauche, � droite, + au dessus et au dessous d'un mat�riel. +---------------------------------------------------------------------- +v1.0a 2011/09/18 + - les macros \Lewis et \lewis admettent un argument optionnel + - la macro \setlewisdist r�gle la distance entre les 2 + �lectrons +---------------------------------------------------------------------- +v1.0b 2011/11/29 + - la commande \merge est d�sormais prot�g�e entre + \schemestart et \schemestop contre des d�finitions par d'autres + packages. + - \box0 est utilis� au lieu du maladroit \unhbox0 +---------------------------------------------------------------------- +v1.0c 2011/11/30 + - la macro \+ n'est plus explicitement �crite + - v�rifie que eTeX est le moteur utilis� +---------------------------------------------------------------------- +v1.0d 2011/12/19 + - les cercles des cycles �taient trac�s au mauvais moment. La + longueur de la liaison qui les pr�c�dait influait sur le + rayon du cercle : \chemfig{-[,0.5]**6(------)} donnait un bug + � l'affichage. +---------------------------------------------------------------------- +v1.0e 2012/01/13 + - la gestion des espaces dans les groupes d'atomes est + d�sormais plus rigoureuse. Plusieurs bugs ont �t� + corrig� +---------------------------------------------------------------------- +v1.0f 2012/02/24 + - correction d'un bug avec \definesubmol, les catcodes n'�taient + pas correctement g�r�s. +---------------------------------------------------------------------- +v1.0g 2012/11/16 + - correction d'un bug dans \CF_directarrow pour faire prendre en + compte le style des fl�che par d�faut + - correction d'un bug dans \CF_lewisc : la boite *doit* �tre + compos�e en dehors de l'environnement tikzpicture pour + �viter nullfont si jamais \printatom ne passe pas en mode + math. + - correction d'un bug dans \CF_chemfigc : si une longueur par + d�faut est modifi�e par [,] au d�but d'une mol�cule + et si des cycles �taient emboit�s, cette longueur n'�tait + pas appliqu�e aux sous-cycles. + - r�-�criture des macros \chemabove et \chembemow pour + prendre en compte le bug (d�sormais corrig�) dans luatex. + - nouvelle macro \setstacksep qui d�finit l'espacement par + d�faut dans les macros \chemabove et \chembelow. +---------------------------------------------------------------------- +v1.0h 2013/11/28 + - \chemname admet maintenant une version �toil� qui ne tient + pas compte des profondeurs pr�c�dentes. + - \CF_dpmax est g�r� globalement. + - correction d'un bug dans "-U>" : le style de la fl�che + n'�tait pris en compte pour l'arc. + - correction d'un bug dans \CF_directarrow : l'angle de la + fl�che n'�tait pas calcul� +---------------------------------------------------------------------- +v1.1 2015/02/13 + - correction d'un bug dans \CF_seeksubmol : la macro + \CF_molecule est d�pouill� de son �ventuel espace + en premi�re position. + - correction d'un bug dans \CF_arrowf : le nom du prochain + n?ud courant "end@arrow@i" �tait erron� dans le cas o� une + fl�che contenait un sous sch�ma. Ce nom doit d�pendre de + \CF_schemenest. + - la jonction entre deux liaisons cons�cutives dans l'axe peut + �tre activ� avec \enablebondjoin et d�sactiv� avec + \disablebondjoin (pr�f�rable, �tat par d�faut). + - \chemfig suivi d'une "*" demande � ce que les liaisons aient + une longueur invariable : la distance inter-atome devient donc + variable. Cette fonctionnalit� est d�sactiv� dans les + cycles afin que les polygones soient r�guliers. + \enablefixedbondlength permet cette fonctionnalit� pour + toutes les macros \chemfig (m�me non �toil�e) tandis que + \disablefixedbondlength le d�sactive. +---------------------------------------------------------------------- +v1.1a 2015/02/23 + - correction d'un bug dans \CF_grabbondoffset. Si \chemfig est + dans l'argument d'une macro, les # sont doubl�s par l'action + de \scantokens de la macro \CF_chemfigb et il faut un + argument d�limit� avant "(" pour absorber tous les #. +---------------------------------------------------------------------- +v1.2 2015/10/08 + - correction d'un bug dans le trac� des liaisons de Cram. + - cr�ation de \setangleincrement. + - chargement de "arrows.meta" et d�finition de la fl�che "CF" + bas�e sur "Stealth" et d�finie avec \pgfdeclarearrow. + Les anciennes fl�ches "CF_full" et "CF_half" sont + abandonn�es puisque d�finies avec \pgfarrowsdeclare. + - fl�che "-U>" corrig�e : le placement des labels est + maintenant correct dans tous les cas. Ainsi : + -U>[][][][r][a] + place le label pr�s du d�but de la fl�che, quels que + soient les signes du rayon r et de l'angle a. + - \chemrel, \setchemrel et \chemsign sont supprim�es. + - compatibilit�, avec les limitations d'usage, avec la + librairie "externalize" : le \begin{tikzpicture} voit + d�sormais le \end{tikzpicture} correspondant dans la macro + \CF_chemfigb. +---------------------------------------------------------------------- +v1.2a 2015/10/21 + - erreur de copier-coller dans le code: une adresse url �tait + malencontreusement pr�sente en plein milieu d'une ligne de + code +---------------------------------------------------------------------- +v1.2b 2015/11/15 + - bug dans \CF_seeksubmol qui laissait "*" dans le flux de + lecture de TeX. Un message d'erreur est �galement ajout� + en cas de "!" en fin de traitement. + - correction d'un bug dans \CF_setbondangle o� l'angle [<:a>] + n'�tait pas �valu� par \pgfmathsetmacro. +---------------------------------------------------------------------- +v1.2c 2015/11/20 + - Correction d'un bug dans \CF_setbondangle : l'angle renvoy� + pouvait �tre n�gatif + - Correction d'un bug dans \CF_directarrow : la macro \CF_ifempty + n'est pas correctement d�velopp�e dans l'argument de + \pgfpointanchor +---------------------------------------------------------------------- +v1.2d 2015/12/01 + - correction d'un bug dans la fl�che "-U" + - la version �toil�e de \setcrambond dessine les liaisons de + Cram en pointill�s sous forme de trait large et non pas sous + forme de triangle. +---------------------------------------------------------------------- +v1.2e 2017/05/20 + - la macro contenant la d�finition d'une fl�che est + d�sormais "\CF_arrow()", ainsi la macro \0 n'est plus + d�finie par \definearrow + - remerciements rajout�s apr�s une suppression indue, pour ne + froisser aucune susceptibilit� +---------------------------------------------------------------------- +v1.3 2018/03/08 + - tous les param�tres sont d�sormais pass�s via \setchemfig qui + fait appel � "simplekv". Par cons�quent, _toutes_ les macros qui + r�glaient des param�tres deviennent obsol�tes, � savoir : + \setcrambond, \setatomsep, \setbondoffset, \setdoublesep, + \setangleincrement, \enablefixedbondlength, + \disablefixedbondlength, \setnodestyle, \setbondstyle, + \setlewis, \setlewisdist, \setstacksep, \setcompoundstyle, + \setarrowdefault, \setandsign, \setarrowoffset, + \setcompoundsep, \setarrowlabelsep, \enablebondjoin, + \disablebondjoin et \schemedebug. + et ces macros seront *supprim�es* dans une future version. + - la version �toil�e "\chemfig*" et les deux arguments optionnels + de la macro "\chemfig[][]" sont �galement optionnels et seront + *supprim�*s dans une future version afin d'acc�der � la syntaxe + \chemfig[cl�s=valeurs]{code} + - 6 nouveaux param�tres : "lewis radius", "arrow double sep", + "arrow double coeff", "arrow double harpoon", "cycle radius + coeff", "arrow head". + - correction d'un bug dans \CF_parsemergeopt qui dans certains + cas, envoyait vers l'affichage des caract�res + - petit toilettage du code + - macro \polymerdelim (non document�e) exp�rimentale et encore + en phase de tests + - suppression d'un registre d'�criture de fichier +---------------------------------------------------------------------- +v1.31 2018/04/05 + - correction d'un espace ind�sirable dans \CF_ifnextchar +---------------------------------------------------------------------- +v1.32 2018/08/23 + - d�finition de \printatom, \CF_begintikzpicture et + \CF_endtikzpicture dans le fichier t-chemfig.tex +---------------------------------------------------------------------- +v1.33 2018/10/31 + - les macros d�finies par \definesubmol peuvent d�sormais avoir un ou + plusieurs arguments + - macro \polymerdelim document�e +---------------------------------------------------------------------- +v1.34 2019/02/23 + - bug dans la fl�che "<->" corrig� +---------------------------------------------------------------------- +v1.4 2019/04/18 + - corrections de nombreux bugs + - caract�re priv� "_" et non plus "@" -> modifications � pr�voir + notamment dans la doc avec les codes sp�cifiques aux fl�ches, �a + risque de couiner sur tex.stackexchange.com + - anciennes macros abandonn�es et d�sormais ind�finies : + \setcrambond, \setatomsep, \setbondoffset, \setdoublesep, + \setangleincrement, \enablefixedbondlength, + \disablefixedbondlength, \setnodestyle, \setbondstyle, + \setlewis, \setlewisdist, \setstacksep, \setcompoundstyle, + \setarrowdefault, \setandsign, \setarrowoffset, + \setcompoundsep, \setarrowlabelsep, \enablebondjoin, + \disablebondjoin et \schemedebug + - l'ancienne syntaxe \chemfig[][]{} est abandonn�e et n'est plus + accept�e, d�sormais c'est + \chemfig[=]{} + - l'ancienne syntaxe \lewis[] ou \Lewis[] n'est + plus accept�e au profit de \lewis[=] +---------------------------------------------------------------------- +v1.41 2019/05/21 + - utilisation de la nouvelle primitive \expanded + - nouvelle cl� "h align" (true par d�faut) pour les d�limiteurs + de \polymerdelim. Lorsque � false, les d�limiteurs ne sont + plus align�s horizontalement mais positionn�s aux noeuds demand�s + - nouvelle cl� "auto rotate" qui n'a de sens que si h align=false : + les d�limiteurs sont automatiquement inclin�s + - nouvelle cl� "rotate" qui n'a de sens que si halign=false ET + auto rotate=false : l'inclinaison des d�limiteurs peut �tre + choisie +---------------------------------------------------------------------- +v1.5 2020/03/05 + - nouvelles macros \charge et \Charge. Les macros \lewis et \Lewis + sont obsol�tes et amen�es � disparaitre � moyen terme (au moins + 9 mois), soit fin 2020 + - prise en compte de la dimension d'un groupe d'atome pour tracer + des liaisons jointives + - bug corrig� dans \CF_seeknode + - ajout d'une section dans le manuel (placement des atomes) +---------------------------------------------------------------------- +v1.51 2020/04/06 + - bug corrig� dans \chargerect_a et \chargeline_a +---------------------------------------------------------------------- +v1.52 2020/04/14 + - bug : d�finition corrig�e de \CFthesubmol dans \def_submolc pour + qu'elle se d�veloppe en 1 coup seulement +---------------------------------------------------------------------- +v1.53 2020/04/27 + - mise � jour en fonction des nouvelles fonctionnalit�s de + l'extension simplekv + - bug : \CF_ifzerodim interrompt maintenant le trac� dans la \hbox +---------------------------------------------------------------------- +v1.54 2020/05/21 + - chemfig ne peut plus fonctionner sans \expanded + - bug : un signe "=" laiss� par erreur dans le flux +---------------------------------------------------------------------- +v1.55 2020/06/15 + - chemfig est incompatible avec conTeXt, vu que ce moteur red�finit + des primitives telles que \expanded, \unexpanded et peut �tre + d'autres. +---------------------------------------------------------------------- +v1.56 2020/07/13 + - le centre des cycles est d�sormais accessible via un noeud + sp�cifique pour chacun d'eux. +---------------------------------------------------------------------- +v1.6 2021/02/26 + - les macros des formules de Lewis sont retir�es et plac�es dans + le fichier s�par� "lewis.tex" que l'utilisateur peut charger + s'il le souhaite + - ajout d'une cl� pour le trousseau [chemfig] + - � l'int�rieur d'un sch�ma, le token '#' est permis dans + l'argument de \chemfig +---------------------------------------------------------------------- +v1.6a 2021/02/28 + - le fichier lewis.tex a �t� renomm� chemfig-lewis.tex diff --git a/NixTeX/dependencies/source/chemistry/chem.tex b/NixTeX/dependencies/source/chemistry/chem.tex new file mode 100644 index 0000000..4432447 --- /dev/null +++ b/NixTeX/dependencies/source/chemistry/chem.tex @@ -0,0 +1,7 @@ +\directlua{includeCode("chemistry/chem")} +\inputCode{chemistry/compounds} +\inputCode{chemistry/figures} +\inputCode{chemistry/substances} + +\newcommand{\ch}[1]{\directlua{chem.printSimple([[#1]])}} + diff --git a/NixTeX/dependencies/source/chemistry/compounds.tex b/NixTeX/dependencies/source/chemistry/compounds.tex new file mode 100644 index 0000000..3cbd1bc --- /dev/null +++ b/NixTeX/dependencies/source/chemistry/compounds.tex @@ -0,0 +1 @@ +\directlua{includeCode("chemistry/compounds")} diff --git a/NixTeX/dependencies/source/chemistry/elements.tex b/NixTeX/dependencies/source/chemistry/elements.tex new file mode 100644 index 0000000..5f1f3c8 --- /dev/null +++ b/NixTeX/dependencies/source/chemistry/elements.tex @@ -0,0 +1,75 @@ +\directlua{includeCode("chemistry/elements")} + +\def\printPeriodicTable{\unchapter[90]{Periodensystem der Elemente} +{{% +% \newlength{\newtextheight}% + \setlength{\newtextheight}{\textheight}% + \addtolength{\newtextheight}{\footskip}% + \newgeometry + { + top = (\paperheight-\textheight+\headheight+\headsep+\footskip)/2 - 1in - 1.04765pt, + textheight = \newtextheight, + footskip = 0cm, + }% + \newcommand{\x}[1]{\directlua{chem.elements.printEntry([[##1]])}}% + \let\m=\multicolumn% + \def\fieldLegend{ + Ordnungszahl\hfill Atommasse\newline + \mbox{}\hfill\textbf{\small Symbol}\hfill\mbox{}\newline + \mbox{}\hfill{\fontsize{5}{6}\selectfont Name}\hfill\mbox{}\newline + Elektronegativität\hfill Aggregatzustand + }% + \newcommand{\s}[1]{\newline\textbf{\footnotesize ##1}}% + \def\colourLegend{\multirow{2}{*}{\parbox{2\linewidth}{\directlua{chem.elements.printColours()}}}}% + \def\aboutAsterisk{Ein Asterisk (*) am Symbol zeigt Radio\-aktivität aller Isotope an.}% + \setlength{\tabcolsep}{\widthof{\,}}% + \begin{table} + \robfamily% + \labelTable{PSE}% + \centering% + \tiny% + \begin{adjustbox}{angle=90} + \begin{tabularx} + {\textheightleft} + {|Z|Z|Z|Z|Z|Z|Z|Z|Z|Z|Z|Z|Z|Z|Z|Z|Z|Z|} + \toprule + \m{18}{c}{}\\[0.1\normalbaselineskip] + \m{18}{c}{\normalsize\textbf{Periodensystem der chemischen Elemente}}\\[1.1\normalbaselineskip] + \midrule + \m{1}{c}{\normalsize\textbf{1}} & \m{1}{c}{\normalsize\textbf{2}} & \m{1}{c}{\normalsize\textbf{3}} & \m{1}{c}{\normalsize\textbf{4}} & + \m{1}{c}{\normalsize\textbf{5}} & \m{1}{c}{\normalsize\textbf{6}} & \m{1}{c}{\normalsize\textbf{7}} & \m{1}{c}{\normalsize\textbf{8}} & + \m{1}{c}{\normalsize\textbf{9}} & \m{1}{c}{\normalsize\textbf{10}} & \m{1}{c}{\normalsize\textbf{11}} & \m{1}{c}{\normalsize\textbf{12}} & + \m{1}{c}{\normalsize\textbf{13}} & \m{1}{c}{\normalsize\textbf{14}} & \m{1}{c}{\normalsize\textbf{15}} & \m{1}{c}{\normalsize\textbf{16}} & + \m{1}{c}{\normalsize\textbf{17}} & \m{1}{c}{\normalsize\textbf{18}} \\ + \m{18}{l}{}\\[-.9\normalbaselineskip] + \cmidrule(l{.3em}r{.3em}){1-1}\cmidrule(l{.3em}r{.3em}){4-6}\cmidrule(l{.3em}r{.3em}){18-18} + \x{H} & \m{2}{l|}{} & \m{3}{p{3.2\TX@col@width}|}{\fieldLegend} & \m{1}{l}{} & \m{2}{X}{\colourLegend} & \m{8}{l|}{} & \x{He} \\ + \cmidrule(l{.3em}r{.3em}){1-2}\cmidrule(l{.3em}r{.3em}){4-6}\cmidrule(l{.3em}r{.3em}){13-18} + \x{Li} & \x{Be} & \m{1}{l}{} & \m{3}{p{3.2\TX@col@width}}{\aboutAsterisk} & \m{6}{l|}{} & \x{B} & \x{C} & \x{N} & \x{O} & \x{F} & \x{Ne} \\ + \cmidrule(l{.3em}r{.3em}){1-2}\cmidrule(l{.3em}r{.3em}){13-18} + \x{Na} & \x{Mg} & \m{10}{l|}{} & \x{Al} & \x{Si} & \x{P} & \x{S} & \x{Cl} & \x{Ar} \\ + \cmidrule(l{.3em}r{.3em}){1-18} + \x{K} & \x{Ca} & \x{Sc} & \x{Ti} & \x{V} & \x{Cr} & \x{Mn} & \x{Fe} & \x{Co} & \x{Ni} & \x{Cu} & \x{Zn} & \x{Ga} & \x{Ge} & \x{As} & \x{Se} & \x{Br} & \x{Kr} \\ + \cmidrule(l{.3em}r{.3em}){1-18} + \x{Rb} & \x{Sr} & \x{Y} & \x{Zr} & \x{Nb} & \x{Mo} & \x{Tc} & \x{Ru} & \x{Rh} & \x{Pd} & \x{Ag} & \x{Cd} & \x{In} & \x{Sn} & \x{Sb} & \x{Te} & \x{I} & \x{Xe} \\ + \cmidrule(l{.3em}r{.3em}){1-18} + \x{Cs} & \x{Ba} & \s{*} & \x{Hf} & \x{Ta} & \x{W} & \x{Re} & \x{Os} & \x{Ir} & \x{Pt} & \x{Au} & \x{Hg} & \x{Tl} & \x{Pb} & \x{Bi} & \x{Po} & \x{At} & \x{Rn} \\ + \cmidrule(l{.3em}r{.3em}){1-18} + \x{Fr} & \x{Ra} & \s{**} & \x{Rf} & \x{Db} & \x{Sg} & \x{Bh} & \x{Hs} & \x{Mt} & \x{Ds} & \x{Rg} & \x{Cn} & \x{Nh} & \x{Fl} & \x{Mc} & \x{Lv} & \x{Ts} & \x{Og} \\ + \cmidrule(l{.3em}r{.3em}){1-18} + \m{18}{l}{}\\[-.9\normalbaselineskip] + \cmidrule(l{.3em}r{.3em}){3-17} + \m{1}{c}{}&\m{1}{Z|}{\s{*}} & \x{La} & \x{Ce} & \x{Pr} & \x{Nd} & \x{Pm} & \x{Sm} & \x{Eu} & \x{Gd} & \x{Tb} & \x{Dy} & \x{Ho} & \x{Er} & \x{Tm} & \x{Yb} & \x{Lu} \\ + \cmidrule(l{.3em}r{.3em}){3-17} + \m{1}{c}{}&\m{1}{Z|}{\s{**}} & \x{Ac} & \x{Th} & \x{Pa} & \x{U} & \x{Np} & \x{Pu} & \x{Am} & \x{Cm} & \x{Bk} & \x{Cf} & \x{Es} & \x{Fm} & \x{Md} & \x{No} & \x{Lr} \\ + \cmidrule(l{.3em}r{.3em}){3-17} + \bottomrule + \end{tabularx}% + \end{adjustbox}% + \end{table}% + \restoregeometry% +}}} + +\def\@LinkToPSE{false} +\def\enablePSE {\def\@LinkToPSE{true}} +\def\disablePSE {\def\@LinkToPSE{false}} diff --git a/NixTeX/dependencies/source/chemistry/figures.tex b/NixTeX/dependencies/source/chemistry/figures.tex new file mode 100644 index 0000000..5eb4085 --- /dev/null +++ b/NixTeX/dependencies/source/chemistry/figures.tex @@ -0,0 +1,357 @@ +\definesubmol\nobond{-[,0.2,,,draw=none]} +\def\hammond{\text{\textit{\ddag}}} +\def\rotate{0} +\newcommand{\setpolymerdelim}[2] +{% + \def\delimleft{#1}% + \def\delimright{#2}% +} +\setpolymerdelim[] +\newcommand{\reaction}[2]{\arrow{->[\tiny\begin{tabular}{@{}l@{\,}l@{}}#1\end{tabular}][\tiny\begin{tabular}{@{}l@{\,}l@{}}#2\end{tabular}]}} + +\let\@chemfig=\chemfig +\let\@chemmove=\chemmove +\renewcommand{\chemfig}[1]{{\@ResetSymbols\@chemfig{#1}}} +\renewcommand{\chemmove}[1]{{\@ResetSymbols\@chemmove{#1}}} + +\def\@WrapChemSide{o} +\def\@WrappedOrScheme{wrapped} +\def\enableWrapped{\def\@WrappedOrScheme{wrapped}} +\def\disableWrapped{\def\@WrappedOrScheme{scheme}} +\newcommand{\initAngle}[2]{[:#2]} +\def\MayHorizontalChem{\quad} +\def\@WrappendEnvironment{\renewcommand{\initAngle}[2]{[:##1]}\def\MayHorizontalChem{\arrow{0}[-90,0.1]}} +\def\@Cheme@DefaultScale{1.5} +\newcommand{\chemeDefaultScale}[1][1.5]{\def\@Cheme@DefaultScale{#1}} + +\definesubmol\nobond{[,0.2,,,draw=none]} +%\definesubmol\numAtom{-[,0.4,,,draw=none]\scriptstyle} +\newcommand{\NumAtom}[2]{} +\newcommand{\numAtom}[1]{\NumAtom{,0.4}{#1}} +\newcommand{\numAtomWith}[2]{\NumAtom{::#1,0.4}{#2}} +\def\numAtoms{\renewcommand{\NumAtom}[2]{-[##1,,,draw=none]{##2}}} + +\setchemfig +{ + atom sep = 14.4pt, + double bond sep = 2.6pt, + bond style = {line width=0.6pt}, + cram rectangle = false, + cram width = 2.0pt, + cram dash width = 0.6pt, + cram dash sep = 1.0pt, + bond offset = 1.6pt, + bond join = true, + lewis length = 1.0ex, + compound sep = 5.0em, + arrow offset = 5.0pt, + scheme debug = false, +} +\renewcommand*\printatom[1]{{\scriptsize\ensuremath{\mathsf{#1}}}} + +%\AtBeginDocument +%{ +% \RenewDocumentCommand\ch{O{}m}{\directlua +% { +% if chLevel == 0 +% then +% tex.print +% ( +% bs.."csname chemformula_ch:nn"..bs.."endcsname {#1}" +% ) +% end +% chLevel = chLevel + 1 +% }{#2}\directlua +% { +% chLevel = chLevel - 1 +% }} +%} + +\tikzset +{ + onehalf/.style args={#1} + { + draw=none, + decoration= + { + markings, + mark=at position 0 with + { + \coordinate (CF@startdeloc) at (0,\dimexpr#1\CF@double@sep/2) coordinate (CF@startaxis) at (0,\dimexpr-#1\CF@double@sep/2); + }, + mark=at position 1 with + { + \coordinate (CF@enddeloc) at (0,\dimexpr#1\CF@double@sep/2) coordinate (CF@endaxis) at (0,\dimexpr-#1\CF@double@sep/2); + \draw[dash pattern=on 2pt off 1.5pt] (CF@startdeloc)--(CF@enddeloc); + \draw (CF@startaxis)--(CF@endaxis); + } + }, + postaction={decorate} + } +} + +\newcommand{\arrowText}[1]{\begin{tabular}{@{}c@{\,}l@{}}#1\end{tabular}} +\newcommand{\cheme}[3][\@Cheme@DefaultScale] +{%sorry for this pun :D + \scalebox{#1}% + {% + %\setchemfig{scheme debug=true}% + \schemestart#2\schemestop% + \chemmove{#3}% + }% + \chemnameinit{}% +} +%\newcommand{\chem}[3][\@Cheme@DefaultScale] +%{ +% \begin{subfigure}[b]{\linewidth} +% \centering +% \cheme[#1]{#2}{#3} +% \end{subfigure} +%} +\newcommand{\thecchem}[5] +{ + %1 – float + %2 – short caption + %3 – content + %4 – long caption + %5 – label + \begin{scheme}[#1] + \centering + #3 + \ifthenelse{\isempty{#4}} + {} + { + \ifthenelse{\isempty{#2}} + {\caption[\nolink{#4}]{\adjustCaption{#4}}} + {\caption[\nolink{#2}]{\adjustCaption{#4}}} + } + \labelScheme{#5} + \end{scheme} +} +\newcommand{\thelchem}[5] +{ + %1 – float + %2 – short caption + %3 – content + %4 – long caption + %5 – label + \begin{scheme}[#1] + #3 + \ifthenelse{\isempty{#4}} + {} + { + \ifthenelse{\isempty{#2}} + {\caption[\nolink{#4}]{\adjustCaption{#4}}} + {\caption[\nolink{#2}]{\adjustCaption{#4}}} + } + \labelScheme{#5} + \end{scheme} +} +\newcommand{\cchem}[1][]{\thecchem{!htbp}{#1}} +\newcommand{\hchem}[1][]{\thecchem{H}{#1}} +\newcommand{\lchem}[1][]{\thelchem{H}{#1}} + +\newcommand{\thesubchem}[5] +{ + %1 – float + %2 – relative width + %3 – content + %4 – long caption + %5 – beamer settings + \begin{subfigure}[#1]{#2}% + \centering% + \ifthenelse{\isempty{#5}}% + {% + \cheme#3% + \ifthenelse{\isempty{#4}}{}{\caption[\nolink{#4}]{\adjustCaption{#4}}}% + }% + {% + \uncover#5% + {% + \cheme#3% + \ifthenelse{\isempty{#4}}{}{\caption[\nolink{#4}]{\adjustCaption{#4}}}% + }% + }% + \end{subfigure}% +} +\newcommand{\subchem}[4][b]{\thesubchem{#1}{#2}{#3}{#4}{}} + +\newcommand{\Wrapchem}[3][] +{{ + \@WrappendEnvironment% + %\begin{samepage} + \ifthenelse{\equal{#1}{}} + {\begin{wrapfigure}{\@WrapChemSide}{\widthof{\cheme{#2}{}}}\cheme{#2}{}\end{wrapfigure}} + {\begin{wrapfigure}{\@WrapChemSide}{#1\linewidth}\centering\cheme{#2}{}\end{wrapfigure}}% + #3\par + %\end{samepage} +}} +\newcommand{\wrapchem}[3][]{\Wrapchem[#1]{\chemfig{#2}}{#3}} + +\newcommand{\MayWrapchem}[5][] +{% + \ifthenelse{\equal{\@WrappedOrScheme}{wrapped}}% + {\Wrapchem[#1]{#2}{#5}}% + {\hchem{\cheme{#2}{}}{#3}{#4}#5\par}% +} +\newcommand{\MayRefchem}[1] +{% + \ifthenelse{\equal{\@WrappedOrScheme}{wrapped}}% + {}% + { (\refScheme{#1})}% +} + +\def\makebraces(#1,#2)#3#4#5% +{% + % 1 – Offset 1 + % 2 – Offset 2 + % 3 – Index + % 4 – Left Node + % 5 – Right Node + %\edef\delimhalfdim{\the\dimexpr(#1+#2)/2}% + %\edef\delimvshift{\the\dimexpr(#1-#2)/2}% + %\node[at=(#4),yshift=(\delimvshift)] + %{$\left\delimleft\vrule height\delimhalfdim depth\delimhalfdim width0pt\right.$};% + %\node[at=(#5),yshift=(\delimvshift)]% + %{$\left.\vrule height\delimhalfdim depth\delimhalfdim width0pt\right\delimright_{\rlap{$\scriptstyle#3$}}$};% + \polymerdelim[delimiters ={[]}, height = 5pt, depth = 10pt, indice = #3]{#4}{#5}% +} +\def\Makebraces(#1,#2)#3#4#5% +{% + % 1 – Offset 1 + % 2 – Offset 2 + % 3 – Index + % 4 – Left Node + % 5 – Right Node + \edef\delimhalfdim{\the\dimexpr(#1+#2)/2}% + \edef\delimvshift{\the\dimexpr(#1-#2)/2}% + \node[at=(#4),yshift=(\delimvshift)] + {$\left\delimleft\vrule height\delimhalfdim depth\delimhalfdim width0pt\right.$};% + \node[at=(#5),yshift=(\delimvshift)]% + {$\left.\vrule height\delimhalfdim depth\delimhalfdim width0pt\right\delimright^{\rlap{$\scriptstyle#3$}}$};% +} + +\catcode`\_11 +\definearrow3{s>}{% +\ifx\empty#1\empty + \expandafter\draw\expandafter[\CF_arrowcurrentstyle,-CF](\CF_arrowstartnode)--(\CF_arrowendnode);% +\else + \def\curvedarrow_style{shorten <=\CF_arrowoffset,shorten >=\CF_arrowoffset,}% + \CF_eaddtomacro\curvedarrow_style\CF_arrowcurrentstyle + \expandafter\draw\expandafter[\curvedarrow_style,-CF](\CF_arrowstartname)..controls#1..(\CF_arrowendname); + \ifx\empty#2\empty\else + abc + \fi +\fi +} +\definearrow7{-u>}{% + \CF_arrowshiftnodes{#3}% + \CF_expafter{\draw[}\CF_arrowcurrentstyle](\CF_arrowstartnode)--(\CF_arrowendnode)node[midway](Uarrow@arctangent){};% + \CF_ifempty{#4} + {\def\CF_Uarrowradius{0.333}} + {\def\CF_Uarrowradius{#4}}% + \CF_ifempty{#5}% + {\def\CF_Uarrowabsangle{60}} + {\pgfmathsetmacro\CF_Uarrowabsangle{abs(#5)}} + \expandafter\draw\expanded{[\CF_ifempty{#1}{draw=none}{\unexpanded\expandafter{\CF_arrowcurrentstyle}},-]}(Uarrow@arctangent)% + arc[radius=\CF_compoundsep*\CF_currentarrowlength*\CF_Uarrowradius,start angle=\CF_arrowcurrentangle+90,delta angle=\CF_Uarrowabsangle]node(Uarrow@start){}; + \expandafter\draw\expanded{[\CF_ifempty{#2}{draw=none}{\unexpanded\expandafter{\CF_arrowcurrentstyle}}]}(Uarrow@arctangent)% + arc[radius=\CF_compoundsep*\CF_currentarrowlength*\CF_Uarrowradius,start angle=\CF_arrowcurrentangle+90,delta angle=-\CF_Uarrowabsangle]node(Uarrow@end){}; + \pgfmathsetmacro\CF_temp{\CF_Uarrowradius*cos(\CF_arrowcurrentangle)<0?"+":"-"}% + \ifdim\CF_Uarrowradius pt>0pt + \CF_arrowdisplaylabel{#1}{0}\CF_temp{Uarrow@start}{#2}{1}\CF_temp{Uarrow@end}% + \else + \CF_arrowdisplaylabel{#2}{0}\CF_temp{Uarrow@start}{#1}{1}\CF_temp{Uarrow@end}% + \fi% + \CF_arrowdisplaylabel{#6}{0.5}+\CF_arrowstartnode{#7}{0.5}-\CF_arrowendnode +} +\definearrow7{-U>}{% + \CF_arrowshiftnodes{#3}% + \CF_expafter{\draw[}\CF_arrowcurrentstyle](\CF_arrowstartnode)--(\CF_arrowendnode)node[midway](Uarrow@arctangent){};% + \CF_ifempty{#4} + {\def\CF_Uarrowradius{0.333}} + {\def\CF_Uarrowradius{#4}}% + \CF_ifempty{#5}% + {\def\CF_Uarrowabsangle{60}} + {\pgfmathsetmacro\CF_Uarrowabsangle{abs(#5)}}% ne prendre en compte que la valeur absolue de l'angle + \expandafter\draw\expanded{[\CF_ifempty{#1}{draw=none}{\unexpanded\expandafter{\CF_arrowcurrentstyle}},-]}(Uarrow@arctangent)% + arc[radius=\CF_compoundsep*\CF_currentarrowlength*\CF_Uarrowradius,start angle=\CF_arrowcurrentangle-90,delta angle=-\CF_Uarrowabsangle]node(Uarrow@start){}; + \expandafter\draw\expanded{[\CF_ifempty{#2}{draw=none}{\unexpanded\expandafter{\CF_arrowcurrentstyle}}]}(Uarrow@arctangent)% + arc[radius=\CF_compoundsep*\CF_currentarrowlength*\CF_Uarrowradius,start angle=\CF_arrowcurrentangle-90,delta angle=\CF_Uarrowabsangle]node(Uarrow@end){}; + \pgfmathsetmacro\CF_temp{\CF_Uarrowradius*cos(\CF_arrowcurrentangle)<0?"-":"+"}% + \ifdim\CF_Uarrowradius pt>0pt + \CF_arrowdisplaylabel{#1}{0}\CF_temp{Uarrow@start}{#2}{1}\CF_temp{Uarrow@end}% + \else + \CF_arrowdisplaylabel{#2}{0}\CF_temp{Uarrow@start}{#1}{1}\CF_temp{Uarrow@end}% + \fi% + \CF_arrowdisplaylabel{#6}{0.5}+\CF_arrowstartnode{#7}{0.5}-\CF_arrowendnode +} +\catcode`\_8 + +% From https://tex.stackexchange.com/questions/260884/chemfig-how-to-do-these-wavy-markings +\pgfdeclaredecoration{complete sines}{initial}{ + \state{initial}[ + width=+0pt, + next state=sine, + persistent precomputation={ + \pgfmathsetmacro\matchinglength{ + \pgfdecoratedinputsegmentlength / + int(\pgfdecoratedinputsegmentlength/\pgfdecorationsegmentlength) + } + \setlength{\pgfdecorationsegmentlength}{\matchinglength pt} + }]{} + \state{sine}[width=\pgfdecorationsegmentlength]{ + \pgfpathsine{ + \pgfpoint + {0.125\pgfdecorationsegmentlength} + {0.25\pgfdecorationsegmentamplitude} + } + \pgfpathcosine{ + \pgfpoint + {0.125\pgfdecorationsegmentlength} + {-0.25\pgfdecorationsegmentamplitude} + } + \pgfpathsine{ + \pgfpoint + {0.125\pgfdecorationsegmentlength} + {-0.25\pgfdecorationsegmentamplitude} + } + \pgfpathcosine{ + \pgfpoint + {0.125\pgfdecorationsegmentlength} + {0.25\pgfdecorationsegmentamplitude} + } + } + \state{final}{} +} +\tikzset{wv/.style={decorate,decoration=complete sines}} +\definesubmol{chainRest}2{#1[#2,.5]((-[::90,1,,,wv])-[::-90,1,,,wv])} +\definesubmol{chainStart}2{[#2](-[::90,1,,,wv])(-[::-90,1,,,wv])#1[,.5]} +\definesubmol{weakBond}2{-[#1,#2,,,dash pattern=on 2pt off 2pt]} + + +%ferrocene +%\wrapchem +%{ +% -[:\rotate-303.51,0.4476]%(-[::96.755]4')% +% -[::303.51,,,,]%(-[::26.755]5')% +% -[::303.51,0.4476]%(-[::35.835]1')% +% <[::251.67,0.7741]@{r5}{}%(-[::74.820]2')% +% >[::329.64,0.7741]%(-[::35.835]3')% +% -[::205.18,0.7472,,,draw=none]@{r1}{}-[::80,0.70]% +% Fe +% -[:: 0,0.85]\ -[::0,0]@{r2}{}-[::85,0.7472,,,draw=none] +% <[::128.51,0.4476]@{r3}{}%(-[::263.245]3)% +% -[:: 56.49,,,,line width=2pt]@{r4}{}%(-[::333.245]2)% +% >[:: 56.49,0.4476]%(-[::324.165]1)% +% -[::108.33,0.7741]%(-[::285.180]5)% +% -[::30.36,0.7741]%(-[::334.255]4) +%} +%{ +% \draw[rotate=\rotate] (r1) ellipse (6pt and 2pt); +% \draw[rotate=\rotate] (r2) ellipse (6pt and 2pt); +% \draw[-,rotate=\rotate,line width=0.6pt] (r2) -- ++(270:2pt); +% \fill[rotate=\rotate] (r3) ellipse (1.3pt and 1pt); +% \fill[rotate=\rotate] (r4) ellipse (1.3pt and 1pt); +% \fill[rotate=\rotate] (r5) ellipse (1pt and 1.3pt); +%} diff --git a/NixTeX/dependencies/source/chemistry/substances.tex b/NixTeX/dependencies/source/chemistry/substances.tex new file mode 100644 index 0000000..50a4dc9 --- /dev/null +++ b/NixTeX/dependencies/source/chemistry/substances.tex @@ -0,0 +1 @@ +\directlua{includeCode("chemistry/substances")} diff --git a/NixTeX/dependencies/source/dashed_lines.tex b/NixTeX/dependencies/source/dashed_lines.tex new file mode 100644 index 0000000..d43a419 --- /dev/null +++ b/NixTeX/dependencies/source/dashed_lines.tex @@ -0,0 +1,19 @@ +\newlength\replength +\newcommand\repfrac{.33} +\newcommand\dashfrac[1]{\renewcommand\repfrac{#1}} +\setlength\replength{1.5pt} +\newcommand\rulewidth{.6pt} +\newcommand\tdashfill[1][\repfrac]{\cleaders\hbox to \replength{% + \smash{\rule[\arraystretch\ht\strutbox]{\repfrac\replength}{\rulewidth}}}\hfill} +\newcommand\tabdashline{% + \makebox[0pt][r]{\makebox[\tabcolsep]{\tdashfill\hfil}}\tdashfill\hfil% + \makebox[0pt][l]{\makebox[\tabcolsep]{\tdashfill\hfil}}% + \\[-\arraystretch\dimexpr\ht\strutbox+\dp\strutbox\relax]% +} +\newcommand\tdotfill[1][\repfrac]{\cleaders\hbox to \replength{% + \smash{\raisebox{\arraystretch\dimexpr\ht\strutbox-.1ex\relax}{.}}}\hfill} +\newcommand\tabdotline{% + \makebox[0pt][r]{\makebox[\tabcolsep]{\tdotfill\hfil}}\tdotfill\hfil% + \makebox[0pt][l]{\makebox[\tabcolsep]{\tdotfill\hfil}}% + \\[-\arraystretch\dimexpr\ht\strutbox+\dp\strutbox\relax]% +} \ No newline at end of file diff --git a/NixTeX/dependencies/source/dependencies.tex b/NixTeX/dependencies/source/dependencies.tex new file mode 100644 index 0000000..143c881 --- /dev/null +++ b/NixTeX/dependencies/source/dependencies.tex @@ -0,0 +1,80 @@ +\usepackage[subfolder]{gnuplottex} +\usepackage{adjustbox} +\usepackage{amsfonts} +\usepackage{amsmath} +\usepackage{amssymb} +\usepackage[bidi=basic]{babel} +\usepackage{booktabs} +\usepackage{\directlua{tex.print(source.."source/chemfig/chemfig")}} +\usepackage[outline]{contour} +\usepackage[babel]{csquotes} +\usepackage{dcolumn} +\usepackage{enumitem} % better enumeration +\usepackage{eso-pic} % for background images +\usepackage{etaremune} % reverse enumeration +\usepackage{etoolbox} +\usepackage{float} +\usepackage{fontenc} +\usepackage{fontspec} +%\usepackage{gensymb} +\usepackage{graphicx} +\usepackage{hyperref} +\usepackage{iflang} +\usepackage{layouts} +\usepackage{listings} +\usepackage{listingsutf8} +\usepackage{longtable}[=v4.13]%!!!!! +\usepackage{letltxmacro} +\usepackage{lineno} +\usepackage{luacolor, lua-ul} +\output\expandafter{\expandafter\LuaULResetUnderline\expandafter*\the\output} %error in lua-ul +\usepackage{microtype} +\usepackage{multicol} +\usepackage{multirow} +\usepackage{newfloat} +\usepackage{pdfcomment} +\usepackage{pdfpages} +\usepackage{pgf} +\usepackage{pgfpages} +\usepackage{pgfplots} +\usepackage{placeins} +\usepackage{qrcode} +\usepackage{ragged2e} +\usepackage[figuresright]{rotating} +\usepackage{setspace} +\usepackage[opentype]{sourcesanspro} +\usepackage{tabto} +\usepackage{tabu} +\usepackage{tabularx} +\usepackage[skins]{tcolorbox} +\usepackage{textalpha} +\usepackage{tikz} +\usepackage{totcount} +\usepackage{transparent} +\usepackage{trimspaces} +\usepackage{wrapfig} +\usepackage{xifthen} +\usepackage{xcolor} +\usepackage{xparse} +\usepackage{subcaption} +\usepackage{unicode-math} + +% After pdfcomment! +\usepackage{lastpage} + +\usepackage +[ + articletitle = true, + backend = biber, + doi = true, + seconds = true, + sorting = none, + style = {\biblatexStyle}, + urldate = iso, +]{biblatex} +\usepackage +[ + font=small, + labelfont=bf +]{caption}[2008/08/24] +\usepackage{geometry} diff --git a/NixTeX/dependencies/source/document.tex b/NixTeX/dependencies/source/document.tex new file mode 100644 index 0000000..f1056bd --- /dev/null +++ b/NixTeX/dependencies/source/document.tex @@ -0,0 +1,133 @@ +\directlua{includeCode("document")} +\setlength{\stockheight}{29.7cm} + +\ifdefined\part + \let\@oldPart=\part + \let\part=\undefined + \NewDocumentCommand\part{soom} + {% + \logInfo{Part} + {% + Title: #4\MessageBreak + Star?: \IfBooleanTF#1{true}{false} + \IfNoValueTF{#2}{}{\MessageBreak Header: #2} + \IfNoValueTF{#3}{}{\MessageBreak TOC: #3} + }% + \FloatBarrier% + \IfBooleanTF#1 + {\IfNoValueTF{#2}{\@oldPart*{#4}}{\IfNoValueTF{#3}{\@oldPart*[#2]{#4}}{\@oldPart*[#2][#3]{#4}}}} + {\IfNoValueTF{#2}{\@oldPart{#4}}{\IfNoValueTF{#3}{\@oldPart[#2]{#4}}{\@oldPart[#2][#3]{#4}}}}% + } +\fi + +\ifdefined\chapter + \let\@oldChapter=\chapter + \let\chapter=\undefined + \NewDocumentCommand\chapter{soom} + {% + \logTrace{Chapter} + {% + Title: #4\MessageBreak + Star?: \IfBooleanTF#1{true}{false} + \IfNoValueTF{#2}{}{\MessageBreak Header: #2} + \IfNoValueTF{#3}{}{\MessageBreak TOC: #3} + }% + \FloatBarrier% + \IfBooleanTF#1 + {\IfNoValueTF{#2}{\@oldChapter*{#4}}{\IfNoValueTF{#3}{\@oldChapter*[#2]{#4}}{\@oldChapter*[#2][#3]{#4}}}} + {\IfNoValueTF{#2}{\@oldChapter{#4}}{\IfNoValueTF{#3}{\@oldChapter[#2]{#4}}{\@oldChapter[#2][#3]{#4}}}}% + } +\fi + +\ifdefined\section + \let\@oldSection=\section + \let\section=\undefined + \NewDocumentCommand\section{soom} + {% + \logTrace{Section} + {% + Title: #4\MessageBreak + Star?: \IfBooleanTF#1{true}{false} + \IfNoValueTF{#2}{}{\MessageBreak Header: #2} + \IfNoValueTF{#3}{}{\MessageBreak TOC: #3} + }% + \FloatBarrier% + \IfBooleanTF#1 + {\IfNoValueTF{#2}{\@oldPart*{#4}}{\IfNoValueTF{#3}{\@oldPart*[#2]{#4}}{\@oldPart*[#2][#3]{#4}}}} + {\IfNoValueTF{#2}{\@oldPart{#4}}{\IfNoValueTF{#3}{\@oldPart[#2]{#4}}{\@oldPart[#2][#3]{#4}}}}% + } +\fi + +\ifdefined\subsection + \let\@oldSubSection=\subsection + \let\subsection=\undefined + \NewDocumentCommand\subsection{soom} + {% + \logTrace{SubSection} + {% + Title: #4\MessageBreak + Star?: \IfBooleanTF#1{true}{false} + \IfNoValueTF{#2}{}{\MessageBreak Header: #2} + \IfNoValueTF{#3}{}{\MessageBreak TOC: #3} + }% + \FloatBarrier% + \IfBooleanTF#1 + {\IfNoValueTF{#2}{\@oldSubSection*{#4}}{\IfNoValueTF{#3}{\@oldSubSection*[#2]{#4}}{\@oldSubSection*[#2][#3]{#4}}}} + {\IfNoValueTF{#2}{\@oldSubSection{#4}}{\IfNoValueTF{#3}{\@oldSubSection[#2]{#4}}{\@oldSubSection[#2][#3]{#4}}}}% + } +\fi + +\ifdefined\subsubsection + \let\@oldSubSubSection=\subsubsection + \let\subsubsection=\undefined + \NewDocumentCommand\subsubsection{soom} + {% + \logTrace{SubSubSection} + {% + Title: #4\MessageBreak + Star?: \IfBooleanTF#1{true}{false} + \IfNoValueTF{#2}{}{\MessageBreak Header: #2} + \IfNoValueTF{#3}{}{\MessageBreak TOC: #3} + }% + \FloatBarrier% + \IfBooleanTF#1 + {\IfNoValueTF{#2}{\@oldSubSubSection*{#4}}{\IfNoValueTF{#3}{\@oldSubSubSection*[#2]{#4}}{\@oldSubSubSection*[#2][#3]{#4}}}} + {\IfNoValueTF{#2}{\@oldSubSubSection{#4}}{\IfNoValueTF{#3}{\@oldSubSubSection[#2]{#4}}{\@oldSubSubSection[#2][#3]{#4}}}}% + } +\fi + +\ifdefined\paragraph + \let\@oldParagraph=\paragraph + \let\paragraph=\undefined + \NewDocumentCommand\paragraph{soom} + {% + \logTrace{Paragraph} + {% + Title: #4\MessageBreak + Star?: \IfBooleanTF#1{true}{false} + \IfNoValueTF{#2}{}{\MessageBreak Header: #2} + \IfNoValueTF{#3}{}{\MessageBreak TOC: #3} + }% + \IfBooleanTF#1 + {\IfNoValueTF{#2}{\@oldParagraph*{#4}}{\IfNoValueTF{#3}{\@oldParagraph*[#2]{#4}}{\@oldParagraph*[#2][#3]{#4}}}} + {\IfNoValueTF{#2}{\@oldParagraph{#4}}{\IfNoValueTF{#3}{\@oldParagraph[#2]{#4}}{\@oldParagraph[#2][#3]{#4}}}}% + } +\fi + +\ifdefined\subparagraph + \let\@oldSubParagraph=\subparagraph + \let\subparagraph=\undefined + \NewDocumentCommand\subparagraph{soom} + {% + \logTrace{SubParagraph} + {% + Title: #4\MessageBreak + Star?: \IfBooleanTF#1{true}{false} + \IfNoValueTF{#2}{}{\MessageBreak Header: #2} + \IfNoValueTF{#3}{}{\MessageBreak TOC: #3} + }% + \IfBooleanTF#1 + {\IfNoValueTF{#2}{\@oldSubParagraph*{#4}}{\IfNoValueTF{#3}{\@oldSubParagraph*[#2]{#4}}{\@oldSubParagraph*[#2][#3]{#4}}}} + {\IfNoValueTF{#2}{\@oldSubParagraph{#4}}{\IfNoValueTF{#3}{\@oldSubParagraph[#2]{#4}}{\@oldSubParagraph[#2][#3]{#4}}}}% + } +\fi diff --git a/NixTeX/dependencies/source/floats/appendix.tex b/NixTeX/dependencies/source/floats/appendix.tex new file mode 100644 index 0000000..f205ca5 --- /dev/null +++ b/NixTeX/dependencies/source/floats/appendix.tex @@ -0,0 +1,118 @@ +\newcommand{\appendGnuplot}[4][]{\appendFigure{#2}{\begin{adjustbox}% + {#1,min width=\textwidth,min totalheight=\textheightleft,max width=\textwidth,max totalheight=\textheightleft}\agnuplot#3{}{}{}{}\end{adjustbox}}{#4}}% +\newcommand{\AppendGnuplot}[4][]{\AppendFigure{#2}{\begin{adjustbox}% + {#1,min width=\textwidth,min totalheight=\textheightleft,max width=\textwidth,max totalheight=\textheightleft}\agnuplot#3{}{}{}{}\end{adjustbox}}{#4}}% +\newcommand{\appendGnuplotSideways}[4][]{\appendFigureSideways{#2}{\begin{adjustbox}% + {#1,min width=\textheightleft,min totalheight=\textwidth,,max totalheight=\textwidth}\agnuplot#3{}{}{}{}\end{adjustbox}}{#4}}% +\newcommand{\AppendGnuplotSideways}[4][]{\AppendFigureSideways{#2}{\begin{adjustbox}% + {#1,min width=\textheightleft,min totalheight=\textwidth,max width=\textheightleft,max totalheight=\textwidth}\agnuplot#3{}{}{}{}\end{adjustbox}}{#4}}% +\newcommand{\appendPDF}[4][]{\appendFigure{#2}{\directlua{markFileAsUsed([[#3]])}% + \includegraphics[#1,width=\textwidth,height=\textheight,keepaspectratio]{#3}}{#4}}% +\newcommand{\AppendPDF}[4][]{\AppendFigure{#2}{\directlua{markFileAsUsed([[#3]])}% + \includegraphics[#1,width=\textwidth,height=.96\textheight,keepaspectratio]{#3}}{#4}}% +\newcommand{\appendPDFsideways}[4][]{\appendFigureSideways{#2}{\directlua{markFileAsUsed([[#3]])}% + \includegraphics[#1,width=\textwidth,height=\textheight,keepaspectratio,angle=-90]{#3}}{#4}}% +\newcommand{\AppendPDFsideways}[4][]{\AppendFigureSideways{#2}{\directlua{markFileAsUsed([[#3]])}% + \includegraphics[#1,width=\textwidth,height=.96\textheight,keepaspectratio,angle=-90]{#3}}{#4}}% + +\gdef\@rotatedPage{false} +\newcommand{\@RotatePages}[1]{\ifthenelse{\equal{\directlua{tex.print(neverRotatePages)}}{true}}{}{\global\pdfpageattr\expandafter{\the\pdfpageattr/Rotate #1}}} +%\newcommand{\@RotatePages}[1]{} +\def\rotatePages {\ifthenelse{\equal{\@rotatedPage}{true}}{}{\@RotatePages{90}\gdef\@rotatedPage{true}}} +\def\unrotatePages{\ifthenelse{\equal{\@rotatedPage}{true}}{\@RotatePages{0}\gdef\@rotatedPage{false}}{}} + +\ifthenelse{\isundefined{\chapter}} + {\ifthenelse{\isundefined{\section}} + {\newcounter{ctrAppendix}} + {\newcounter{ctrAppendix}[section]}} + { + \newcounter{ctrAppendix}[chapter] + \renewcommand*\thectrAppendix{\thechapter.\arabic{ctrAppendix}}% + } + +\def\@CaptionedAppendix{false} +\def\enableCaptionedAppendix{\def\@CaptionedAppendix{true}} +\def\disableCaptionedAppendix{\def\@CaptionedAppendix{false}} + +\newcommand{\@MaybeCaptioned}[2] +{% + \begin{figure}[H]% + %\centering% + \ifthenelse{\equal{\@CaptionedAppendix}{true}}% + {% + \scalebox{.95}{#2} + \caption{#1}% + }% + {#2}% + \end{figure}% +} +\newcommand{\@MaybeCaptionedRotated}[2] +{\vfill\rotatebox{90}{\parbox[c][\textwidth][c]{0px}{\@MaybeCaptioned{#1}{#2}}}} + +\newcommand{\appendFigure}[3]% +{% + %1 – title% + %2 – content% + %3 – label% + \clearpage% + \unrotatePages% + \refstepcounter{ctrAppendix}% + \ifthenelse{\isempty{#1}}{}{\expandafter\subsubsection{#1}}% + \labelAppendix{#3}% + \expandafter\belowpdfbookmark{\nolink{#1}}{page:\thepage}% + \expandafter\addxcontentsline{toc}{section}{\nolink{#1}}% + \@MaybeCaptioned{#1}{#2}% +}% + +\newcommand{\appendFigureSideways}[3]% +{% + %1 – title% + %2 – content% + %3 – label% + \clearpage% + \rotatePages% + \refstepcounter{ctrAppendix}% + \ifthenelse{\isempty{#1}}{}{\expandafter\subsubsection{#1}}% + \labelAppendix{#3}% + \expandafter\belowpdfbookmark{\nolink{#1}}{page:\thepage}% + \expandafter\addxcontentsline{toc}{section}{\nolink{#1}}% + \@MaybeCaptionedRotated{#1}{#2}% + %\leavevmode\unrotatePages% +}% + +\newcommand{\AppendFigure}[3]% +{% + %1 – title% + %2 – content% + %3 – label% + %\newpage% + %\clearpage% + %\refstepcounter{ctrAppendix} + %\ifthenelse{\isempty{#3}}% + % {}% + % {\label{#3}}% + \unrotatePages% + \expandafter\subsubsection*{#1}% + %\expandafter\belowpdfbookmark{\nolink{#1}}{page:\thepage}% + %\expandafter\addxcontentsline{toc}{section}{\nolink{#1}}% + \@MaybeCaptioned{#1}{#2}% +}% + +\newcommand{\AppendFigureSideways}[3]% +{% + %1 – title% + %2 – content% + %3 – label% + %\newpage% + %\clearpage% + %\refstepcounter{ctrAppendix} + %\ifthenelse{\isempty{#3}}% + % {}% + % {\label{#3}}% + \rotatePages% + \expandafter\subsubsection*{#1}% + %\expandafter\belowpdfbookmark{\nolink{#1}}{page:\thepage}% + %\expandafter\addxcontentsline{toc}{section}{\nolink{#1}}% + \@MaybeCaptionedRotated{#1}{#2}% + %\leavevmode\unrotatePages% +}% diff --git a/NixTeX/dependencies/source/floats/enumerations.tex b/NixTeX/dependencies/source/floats/enumerations.tex new file mode 100644 index 0000000..5c78503 --- /dev/null +++ b/NixTeX/dependencies/source/floats/enumerations.tex @@ -0,0 +1,94 @@ +\directlua{includeCode("floats/enumerations")} +\newcommand{\enumeration}[2][] +{ + \ifthenelse{\isempty{#1}} + { + \begin{enumerate} + #2 + \end{enumerate} + } + { + \begin{enumerate}[#1] + #2 + \end{enumerate} + } +} +\newcommand{\renumeration}[2][] +{ + \ifthenelse{\isempty{#1}} + { + \begin{etaremune} + #2 + \end{etaremune} + } + { + \begin{etaremune}[#1] + #2 + \end{etaremune} + } +} +\newcommand{\itemisation}[2][] +{ + \ifthenelse{\isempty{#1}} + { + \begin{itemize} + #2 + \end{itemize} + } + { + \begin{enumerate}[#1] + #2 + \end{enumerate} + } +} +\def\@ItemList{true} +\def\enableItemList{\def\@ItemList{true}} +\def\disableItemList{\def\@ItemList{false}} +\def\mayComma{,} +\def\mayPeriod{.} +\def\mayUppercase#1{\ifthenelse{\equal{\@ItemList}{true}}{#1}{\directlua{tex.print(([[#1]]):upper())}}} +\def\semicolonOrPeriod{\ifthenelse{\equal{\@ItemList}{true}}{:}{.}} +\def\noComma{} +\def\noPeriod{} +\def\@period{.} + +\def\@EnumItem {\directlua{enumerations.item()}\@EnumItemNext}% +\def\EnumArabic {\directlua{enumerations.arabic()}} +\def\EnumAlphaL {\directlua{enumerations.alphaLower()}} +\def\EnumAlphaU {\directlua{enumerations.alphaUpper()}} +\def\EnumRomanL {\directlua{enumerations.romanLower()}} +\def\EnumRomanU {\directlua{enumerations.romanUpper()}} + +\newcommand{\@EnumInit}[1] +{% + \edef\@EnumItemNext{\directlua{enumerations.init([[\detokenize{#1}]])}}% + \def\mayComma{}% + \def\mayPeriod{}% +} +\newcommand{\itemlist}[2][] +{ + \ifthenelse{\equal{\@ItemList}{true}} + {\itemisation[#1]{#2}} + {{% + \@EnumInit{#1}% + \def\noComma{\def\item{\def\item{, \@EnumItem~}\@EnumItem~} }% + \def\noPeriod{\def\@period{}}% + \noComma\trim@post@space{#2}\@period% + }} +} +\newcommand{\Itemlist}[2][] +{ + \ifthenelse{\equal{\@ItemList}{true}} + {\itemisation[#1]{#2}} + {{% + \@EnumInit{#1}% + \def\noPeriod{\def\item{\def\item{ \@EnumItem~}\@EnumItem~} }% + \noPeriod\trim@post@space{#2}% + }} +} +\newcommand{\descriptions}[1] +{ + \begin{description} + #1 + \end{description} +} diff --git a/NixTeX/dependencies/source/floats/equations.tex b/NixTeX/dependencies/source/floats/equations.tex new file mode 100644 index 0000000..f67909f --- /dev/null +++ b/NixTeX/dependencies/source/floats/equations.tex @@ -0,0 +1,65 @@ +\directlua{includeCode("floats/equations")} + +%\setmathfont[]{Roboto-Light} + +\newcommand{\Newunit }[3][]{\ensuremath{\ifthenelse{\isempty{#1}}{}{10^{#1}\,}\text{\directlua{tex.print(unit2string([[#2]], false))}}\ifthenelse{\isempty{#3}}{}{{}^{#3}}}} +\newcommand{\Physical }[5][]{\directlua{physical([[#1]],[[#2]],[[#3]],[[#4]],[[#5]])}} +\newcommand{\Unit }[2]{\directlua{unit([[#1]],[[#2]],true)}} + +%\texorpdfstring{\ensuremath{\text{·\directlua{tex.print(unit2string([[#1]], false))}}\directlua{if not ([[#2]] == [[]]) then tex.print([[{}^{]]..bs..[[text{#2}}]]) end}}}{·\directlua{tex.print(unit2string([[#1]], false))}\^{\text{#2}}}} + +\newcommand{\defineVar}[2]{\ensuremath{#1 & ....\text{#2} \nonumber}} +\newcommand{\assignVar}[2]{\ensuremath{#1 & = #2 \nonumber}} +\newcommand{\assign }[3][]{\ensuremath{\ifthenelse{\equal{#1}{}}{}{\labelEquation{#1}}#2 & = #3}} +\newcommand{\explainVar}[1]{\defineVar{\acrshort{#1}}{\acrlong{#1}}} + +\newcommand{\equations}[1] +{ + \begin{align} + #1 + \end{align} +} + +\newcommand{\calculations}[1] +{ + \begin{align*} + #1 + \end{align*} +} + +\def\defaultdecimals{4} +\newcommand{\putlua}[2][\defaultdecimals]{\directlua{tex.print(string.format(string.char(37).."."..[[#1]].."f", #2))}} + +\let\oldr@@t\r@@t +\def\r@@t#1#2{% +\setbox0=\hbox{$\oldr@@t#1{#2\,}$}\dimen0=\ht0 +\advance\dimen0-0.2\ht0 +\setbox2=\hbox{\vrule height\ht0 depth -\dimen0}% +{\box0\lower0.4pt\box2}} +\LetLtxMacro{\oldsqrt}{\sqrt} +\renewcommand*{\sqrt}[2][\ ]{\oldsqrt[#1]{#2}} + +\AtBeginDocument{\renewcommand{\d}{\mathrm{d}}} + +%\newcommand{\physical }[5][]{\ifthenelse{\isempty{#1}}{\directlua{fun = load("return "..[[#2]]) if ( fun == nil ) then tex.print([[2]]) else tex.print(fun()) end}}{\directlua{tex.print(string.format(string.char(37).."."..[[#1]].."f", load("return "..[[#2]])()))}}\ensuremath{\ifthenelse{\isempty{#3}}{}{\cdot10^{#3}}\ifthenelse{\isempty{#4}}{}{\,\text{#4}\ifthenelse{\isempty{#5}}{}{{}^{#5}}}}} +%\newcommand{\newunit }[3][]{\ensuremath{\ifthenelse{\isempty{#1}}{}{10^{#1}\,}\text{#2}\ifthenelse{\isempty{#3}}{}{{}^{#3}}}} +%\newcommand{\unit }[2]{\ensuremath{\cdot\text{#1}\ifthenelse{\isempty{#2}}{}{{}^{#2}}}} +%{\texorpdfstring{\ensuremath{\cdot\text{\directlua{tex.print(unit2string([[#1]], false))}}\ifthenelse{\isempty{#2}}{}{{}^{#2}}}}{·\directlua{tex.print(unit2string([[#1]], false))}#2}} +%\newcommand{\UNIT }[2]{\ensuremath{\cdot\text{\directlua{tex.print(unit2string([[#1]], false))}}^{#2}}} +% \ifthenelse +% {\isempty{#2}} +% {123} +% {123} +% %{\ensuremath{\cdot\text{\acrshort{#1}}}} +% %{\ensuremath{\cdot\text{\acrshort{#1}}}} +%\input{\source/tex/square_roots.def} +% New definition of square root: +% it renames \sqrt as \oldsqrt +%\let\oldsqrt\sqrt +% it defines the new \sqrt in terms of the old one +%\def\sqrt{\mathpalette\DHLhksqrt} +%\def\DHLhksqrt#1#2{% +%\setbox0=\hbox{$#1\oldsqrt{#2\,}$}\dimen0=\ht0 +%\advance\dimen0-0.2\ht0 +%\setbox2=\hbox{\vrule height\ht0 depth -\dimen0}% +%{\box0\lower0.4pt\box2}} diff --git a/NixTeX/dependencies/source/floats/figures.tex b/NixTeX/dependencies/source/floats/figures.tex new file mode 100644 index 0000000..7d2e0f3 --- /dev/null +++ b/NixTeX/dependencies/source/floats/figures.tex @@ -0,0 +1,226 @@ +\newcommand{\cfigure }[1][]{\thecfigure{!htbp}{}{#1}}% +\newcommand{\hfigure }[1][]{\thecfigure{H}{}{#1}}% +\newcommand{\cFigure }[1][]{\Thecfigure{!htbp}{}{#1}}% +\newcommand{\hFigure }[1][]{\Thecfigure{H}{}{#1}}% +\newcommand{\cscheme }[1][]{\thecscheme{!htbp}{}{#1}}% +\newcommand{\hscheme }[1][]{\thecscheme{H}{}{#1}}% +\newcommand{\cScheme }[1][]{\Thecscheme{!htbp}{}{#1}}% +\newcommand{\hScheme }[1][]{\Thecscheme{H}{}{#1}}% +\newcommand{\subfig}[4][b]{\thesubfig{#1}{#2}{#3}{#4}{}}% +\newcommand{\Subfig}[4][b]{\theSubfig{#1}{#2}{#3}{#4}{}}% +\newcommand{\SubFig}[4][b]{\theSubFig{#1}{#2}{#3}{#4}{}}% +\newcommand{\wrapfig}[6][0.3]{\thewrapfig{#1}{#2}{#3}{#4}{#5}{#6}{}}% + +\def\WrapFigSide{o} + +\newcommand{\thecfigure}[7] +{ + %1 – float + %2 – beamer overlay + %3 – short caption + %4 – config + %5 – content + %6 – long caption + %7 – label + \begin{figure}[#1] + \robfamily + %\directlua{print() print([[figure]]) print([[float: #1]]) print([[tlabel: #7]])}% + \centering% + \ifthenelse{\isempty{#2}}% + {% + \ifthenelse{\equal{#5}{}}% + {#4}% + {% + \directlua{markFileAsUsed([[#5]])}% + \ifthenelse{\isempty{#4}}% + {\includegraphics{#5}}% + {\includegraphics[#4]{#5}}% + }% + \ifthenelse{\isempty{#6}}% + {}% + {% + \ifthenelse{\isempty{#3}}% + {\caption[\nolink{#6}]{\adjustCaption{#6}}}% + {\caption[\nolink{#3}]{\adjustCaption{#6}}}% + }% + }% + {% + \uncover#2% + {% + \ifthenelse{\equal{#5}{}}% + {#4}% + {% + \directlua{markFileAsUsed([[#5]])}% + \uncoverincludegraphics[#4]{#5}{#2}% + }% + \ifthenelse{\isempty{#6}}% + {}% + {% + \ifthenelse{\isempty{#3}}% + {\caption[\nolink{#6}]{\adjustCaption{#6}}}% + {\caption[\nolink{#3}]{\adjustCaption{#6}}}% + }% + }% + }% + \labelFigure{#7}% + \end{figure}% +} + +\newcommand{\Thecfigure}[7] +{ + %1 – float + %2 – beamer overlay + %3 – short caption + %4 – config + %5 – content + %6 – long caption + %7 – label + \begin{figure}[#1]% + \robfamily + %\directlua{print() print([[label: #7]])}% + \centering% + \ifthenelse{\equal{#5}{}}% + {#4}% + {% + \directlua{markFileAsUsed([[#5]])}% + \ifthenelse{\isempty{#4}}% + {\includegraphics{#5}}% + {\includegraphics[#4]{#5}}% + }% + \ifthenelse{\isempty{#6}}% + {}% + {% + \caption*{\adjustCaption{#6}}% + }% + \labelFigure{#7}% + \end{figure}% +} + +\newcommand{\thesubfig}[5] +{ + \begin{subfigure}[#1]{\widthof{\includegraphics[#2]{#3}}}% + \directlua{markFileAsUsed([[#3]])}% + \centering% + \ifthenelse{\isempty{#5}}% + {% + \includegraphics[width=\textwidth]{#3}% + \caption[\nolink{#4}]{\adjustCaption{#4}}% + }% + {% + \uncover#5% + {% + \uncoverincludegraphics[width=\textwidth]{#3}{#5}% + \caption[\nolink{#4}]{\adjustCaption{#4}}% + }% + }% + \end{subfigure}% +} + +\newcommand{\theSubfig}[5]% +{% + \begin{subfigure}[#1]{\widthof{\includegraphics[#2]{#3}}}% + \directlua{markFileAsUsed([[#3]])}% + \centering% + \ifthenelse{\isempty{#5}}% + {% + \includegraphics[width=\textwidth]{#3}% + \caption*{\adjustCaption{#4}}% + }% + {% + \uncover#5% + {% + \uncoverincludegraphics[width=\textwidth]{#3}{#5}% + \caption*{\adjustCaption{#4}}% + }% + }% + \end{subfigure}% +} + +\newcommand{\theSubFig}[5] +{ + \begin{subfigure}[#1]{#2} + \directlua{markFileAsUsed([[#3]])}% + \centering% + \ifthenelse{\isempty{#5}}% + {% + \includegraphics[width=\textwidth]{#3}% + \caption*{\adjustCaption{#4}}% + }% + {% + \uncover#5% + {% + \uncoverincludegraphics[width=\textwidth]{#3}{#5}% + \caption*{\adjustCaption{#4}}% + }% + }% + \end{subfigure}% +} + +\newcommand{\thewrapfig}[7] +{ + %1 – relative width + %2 – short caption + %3 – config + %4 – content + %5 – long caption + %6 – label + %7 – beamer overlay + \begin{wrapfigure}{\WrapFigSide}{#1\linewidth}% + %\directlua{print() print([[figure]]) print([[float: #1]]) print([[tlabel: #6]])}% + \centering% + \ifthenelse{\isempty{#7}}% + {% + \ifthenelse{\equal{#4}{}}% + {#3}% + {% + \directlua{markFileAsUsed([[#4]])}% + \ifthenelse{\isempty{#3}}% + {\includegraphics{#4}}% + {\includegraphics[#3]{#4}}% + }% + \ifthenelse{\isempty{#5}}% + {}% + {% + \ifthenelse{\isempty{#2}}% + {\caption[\nolink{#5}]{\adjustCaption{#5}}}% + {\caption[\nolink{#2}]{\adjustCaption{#5}}}% + }% + }% + {% + \uncover#7% + {% + \ifthenelse{\equal{#4}{}}% + {#3}% + {% + \directlua{markFileAsUsed([[#4]])}% + \uncoverincludegraphics[#3]{#4}% + }% + \ifthenelse{\isempty{#5}}% + {}% + {% + \ifthenelse{\isempty{#2}}% + {\caption[\nolink{#5}]{\adjustCaption{#5}}}% + {\caption[\nolink{#2}]{\adjustCaption{#5}}}% + }% + }% + }% + \labelFigure{#6}% + \end{wrapfigure}% +} + +% for beamer +\def\uncovergraphicsopacity{0.9} +\def\uncovergraphicsbackground{white} +\newcommand{\uncoverincludegraphics}[3][] +{ + \alt#3 + { + \ifthenelse{\isempty{#1}}{\includegraphics{#2}}{\includegraphics[#1]{#2}} + } + { + \begin{tikzpicture} + \node[anchor=south west,inner sep=0] (B) at (4,0) {\ifthenelse{\isempty{#1}}{\includegraphics{#2}}{\includegraphics[#1]{#2}}}; + \fill [draw=none, fill=\uncovergraphicsbackground, fill opacity=\uncovergraphicsopacity] (B.north west) -- (B.north east) -- (B.south east) -- (B.south west) -- (B.north west) -- cycle; + \end{tikzpicture} + } +} diff --git a/NixTeX/dependencies/source/floats/floats.tex b/NixTeX/dependencies/source/floats/floats.tex new file mode 100644 index 0000000..d444691 --- /dev/null +++ b/NixTeX/dependencies/source/floats/floats.tex @@ -0,0 +1,10 @@ +\directlua{includeCode("floats/floats")} +\pgfplotsset{compat=1.17} + +\newcommand{\adjustCaption}[1]{\noWordBreaks{#1}} +\inputCode{floats/appendix} +\inputCode{floats/enumerations} +\inputCode{floats/equations} +\inputCode{floats/figures} +\inputCode{floats/labels} +\inputCode{floats/tables} diff --git a/NixTeX/dependencies/source/floats/gnuplot.tex b/NixTeX/dependencies/source/floats/gnuplot.tex new file mode 100644 index 0000000..4c47dc3 --- /dev/null +++ b/NixTeX/dependencies/source/floats/gnuplot.tex @@ -0,0 +1,71 @@ +\directlua{includeCode("floats/gnuplot")} +\newcommand{\cgnuplot}[1][]{\@gnuplot{!htbp}{}{#1}}% +\newcommand{\hgnuplot}[1][]{\@gnuplot{H}{}{#1}}% +\newcommand{\subgnuplot}[6][b]{\@subgnuplot{#1}{#2}{#3}{#4}{#5}{#6}{}}% +\newcommand{\Subgnuplot}[6][b]{\@Subgnuplot{#1}{#2}{#3}{#4}{#5}{#6}{}}% +\newcommand{\subGnuplot}[7][b]{\@subGnuplot{#1}{#2}{#3}{#4}{#5}{#6}{#7}{}}% +\newcommand{\SubGnuplot}[7][b]{\@SubGnuplot{#1}{#2}{#3}{#4}{#5}{#6}{#7}{}}% + +\newcommand{\agnuplot}[4]{\directlua{gnuplot.draw([[#1]],[[#2]],[[#3]],[[#4]])}} +\newcommand{\@gnuplot}[8]% +{% + %1 – float + %2 – beamer overlay + %3 – short caption + %4 – config + %5 – path + %6 – content + %7 – long caption + %8 – label + \begin{figure}[#1]% + \robfamily% + \centering% + \directlua{gnuplot.draw([[#4]],[[#5]],[[#6]],[[#2]])}% + \ifthenelse{\isempty{#7}}% + {}% + {% + \ifthenelse{\isempty{#3}}% + {\caption[\nolink{#7}]{\adjustCaption{#7}}}% + {\caption[\nolink{#3}]{\adjustCaption{#7}}}% + }% + \labelFigure{#8}% + \end{figure}% +} + +\newcommand{\@subgnuplot}[7] +{ + \begin{subfigure}[#1]{#2}% + \centering% + %\directlua{print([[»»\noexpand#5««]])}% + \agnuplot{#3 size \directlua{tex.print(convert([[\the\linewidth]], "cm")..[[,]]..convert([[\the\linewidth]], "cm"))}}{#4}{#5}{#7}% + \ifthenelse{\equal{#6}{}}{}{\caption[\nolink{#6}]{\adjustCaption{#6}}}% + \end{subfigure}% +} + +\newcommand{\@Subgnuplot}[7] +{ + \begin{subfigure}[#1]{#2}% + \centering% + \agnuplot{#3 size \directlua{tex.print(convert([[\the\linewidth]], "cm")..[[,]]..convert([[\the\linewidth]], "cm"))}}{#4}{#5}{#7}% + \ifthenelse{\equal{#6}{}}{}{\caption*{\adjustCaption{#6}}}% + \end{subfigure}% +} + +\newcommand{\@subGnuplot}[8] +{ + \begin{subfigure}[#1]{#2}% + \centering% + %\directlua{print([[»»\noexpand#5««]])}% + \agnuplot{#4 size \directlua{tex.print(convert([[\the\linewidth]], "cm")..[[,]]..convert([[\the\linewidth]], "cm", [[#3]]))}}{#5}{#6}{#8}% + \ifthenelse{\equal{#7}{}}{}{\caption[\nolink{#7}]{\adjustCaption{#7}}}% + \end{subfigure}% +} + +\newcommand{\@SubGnuplot}[8] +{ + \begin{subfigure}[#1]{#2}% + \centering% + \agnuplot{#4 size \directlua{tex.print(convert([[\the\linewidth]], "cm")..[[,]]..convert([[\the\linewidth]], "cm", [[#3]]))}}{#5}{#6}{#8}% + \ifthenelse{\equal{#7}{}}{}{\caption*{\adjustCaption{#7}}}% + \end{subfigure}% +} diff --git a/NixTeX/dependencies/source/floats/labels.tex b/NixTeX/dependencies/source/floats/labels.tex new file mode 100644 index 0000000..a0ad296 --- /dev/null +++ b/NixTeX/dependencies/source/floats/labels.tex @@ -0,0 +1,31 @@ +\directlua{includeCode("floats/labels")} + +\newcommand{\refAppendix }[1]{\directlua{labels.reference (labels.appendices, [[#1]])}} +\newcommand{\refEquation }[1]{\directlua{labels.reference (labels.equations, [[#1]])}} +\newcommand{\refFigure }[1]{\directlua{labels.reference (labels.figures, [[#1]])}} +\newcommand{\refScheme }[1]{\directlua{labels.reference (labels.schemes, [[#1]])}} +\newcommand{\refTable }[1]{\directlua{labels.reference (labels.tables, [[#1]])}} + +\newcommand{\refPart }[1]{\directlua{labels.reference (labels.parts, [[#1]])}} +\newcommand{\refChapter }[1]{\directlua{labels.reference (labels.chapters, [[#1]])}} +\newcommand{\refSection }[1]{\directlua{labels.reference (labels.sections, [[#1]])}} +\newcommand{\refSubsection }[1]{\directlua{labels.reference (labels.subsections, [[#1]])}} +\newcommand{\refSubsubsection }[1]{\directlua{labels.reference (labels.subsubsections, [[#1]])}} +\newcommand{\refParagraph }[1]{\directlua{labels.reference (labels.paragraphs, [[#1]])}} +\newcommand{\refSubparagraph }[1]{\directlua{labels.reference (labels.subparagraphs, [[#1]])}} +\newcommand{\refSentence }[1]{\directlua{labels.reference (labels.sentences, [[#1]])}} + +\newcommand{\labelAppendix }[1]{\directlua{labels.declare (labels.appendices, [[#1]])}} +\newcommand{\labelEquation }[1]{\directlua{labels.declare (labels.equations, [[#1]], true)}} +\newcommand{\labelFigure }[1]{\directlua{labels.declare (labels.figures, [[#1]])}} +\newcommand{\labelScheme }[1]{\directlua{labels.declare (labels.schemes, [[#1]])}} +\newcommand{\labelTable }[1]{\directlua{labels.declare (labels.tables, [[#1]])}} + +\newcommand{\labelPart }[1]{\directlua{labels.declare (labels.parts, [[#1]])}} +\newcommand{\labelChapter }[1]{\directlua{labels.declare (labels.chapters, [[#1]])}} +\newcommand{\labelSection }[1]{\directlua{labels.declare (labels.sections, [[#1]])}} +\newcommand{\labelSubsection }[1]{\directlua{labels.declare (labels.subsections, [[#1]])}} +\newcommand{\labelSubsubsection }[1]{\directlua{labels.declare (labels.subsubsections, [[#1]])}} +\newcommand{\labelParagraph }[1]{\directlua{labels.declare (labels.paragraphs, [[#1]])}} +\newcommand{\labelSentence }[1]{\directlua{labels.declare (labels.sentences, [[#1]])}} +\newcommand{\labelSubparagraph }[1]{\directlua{labels.declare (labels.subparagraphs, [[#1]])}} diff --git a/NixTeX/dependencies/source/floats/tables.tex b/NixTeX/dependencies/source/floats/tables.tex new file mode 100644 index 0000000..e78807a --- /dev/null +++ b/NixTeX/dependencies/source/floats/tables.tex @@ -0,0 +1,232 @@ +% special rules +\newlength\oriarrayrulewidth +\newcount\orilowpenalty +\newcommand\Midrule% +{% + \noalign% + {% + \global\oriarrayrulewidth\arrayrulewidth\relax% + \global\orilowpenalty\@lowpenalty\relax% + \global\@lowpenalty=\numexpr-10000\relax% + \global\arrayrulewidth\lightrulewidth\relax% + }% + \hline% + \noalign% + {% + \global\@lowpenalty=\orilowpenalty\relax% + \global\arrayrulewidth\oriarrayrulewidth\relax% + }% +} +\newcommand{\raisedrule}[2][0em]{\leaders\hbox{\rule[#1]{1pt}{#2}}\hfill} + +% special table columns +\newcolumntype{d}[1]{D{.}{\cdot}{#1}} +\newcolumntype{L}[1]{>{\raggedright\let\newline\\\arraybackslash\hspace{0pt}}m{#1}} +\newcolumntype{C}[1]{>{\centering\let\newline\\\arraybackslash\hspace{0pt}}m{#1}} +\newcolumntype{R}[1]{>{\raggedleft\let\newline\\\arraybackslash\hspace{0pt}}m{#1}} +\newcolumntype{P}{>{\raggedright\let\newline\\\arraybackslash\hspace{0pt}}X} +\newcolumntype{Z}{>{\centering\let\newline\\\arraybackslash\hspace{0pt}}X} +\newcolumntype{T}[3]{>{\textfont0=\the\font\DC@{#1}{#2}{#3}}c<{\DC@end}} +\newcolumntype{.}{T{.}{.}{-1}} +\newcommand{\thead}[1]{\multicolumn{1}{c}{#1}} +\newcommand{\Thead}[1]{\multicolumn{1}{c|}{#1}} +\newcommand{\tHead}[1]{\multicolumn{1}{@{}c@{}}{#1}} +\newcommand{\THead}[1]{\multicolumn{1}{@{}c@{}|@{}}{#1}} + +% notes for tables +\newcommand{\tblNote}[2][]{\directlua{tableNote([[#1]], [[#2]])}} +\newcommand{\theNote}[1]{\directlua{theNote([[#1]])}} +\newcommand{\aNote}[1]{\directlua{if (tblNoteText=="") then else tblNoteText=tblNoteText..[[; ]] end tblNoteText=tblNoteText..[[#1]] end}} + +% make font size in a table smaller +\newcommand{\smallTable}{\directlua{tblSmall = true}} +\newcommand{\normalTable}{\directlua{tblSmall = false}} + +\newcommand{\ctable }[1][]{\@ctable {h}{#1}}%(short caption, config, body, long caption, label) +\newcommand{\htable }[1][]{\@ctable {H}{#1}}%(short caption, config, body, long caption, label) + +\newcommand{\@ctable}[6] +{ + %1 – float + %2 – short caption + %3 – config + %4 – body + %5 – long caption + %6 – label + \directlua + { + tblNotes = 0 + tblNamedNotes = {} + tblNoteText = [[]] + if tblSmall == true + then + end + } + \begin{table}[#1]% + \robfamily% + \centering% + {% + \directlua + { + if tblSmall == true + then + tex.print([[\noexpand\footnotesize]]) + end + }% + \ifthenelse{\isempty{#5}}% + {}% + {% + \ifthenelse{\isempty{#2}}% + {\caption[\nolink{#5}]{\adjustCaption{#5}}}% + {\caption[\nolink{#2}]{\adjustCaption{#5}}}% + }% + \labelTable{#6}% + \ifthenelse{\isempty{#3}}% + {\begin{tabular}{l*{255}{c}}}% + {\begin{tabular}{#3}}% + \toprule% + #4% + \bottomrule% + \end{tabular}% + }% + {% + \directlua + { + if not ( tblNoteText == [[]] ) + then + tex.print(bs..[[begin{flushleft}]]..bs..[[small]]..tblNoteText..[[.]]..bs..[[end{flushleft}]]) + end + }% + }% + \end{table}% +} + +\newcommand{\ltable}[9][] +{ + %1 – short caption + %2 – config + %3 – first header + %4 – other header + %5 – body + %6 – other footer + %7 – final footer + %8 – long caption + %9 – label + \directlua + { + tblNotes = 0 + tblNamedNotes = {} + tblNoteText = [[]] + if tblSmall == true + then + end + }% + \ifthenelse{\isempty{#3}}% + {\def\tableHeadFirst{}}% + {\def\tableHeadFirst{#3\midrule}}% + \ifthenelse{\isempty{#4}}% + {\def\tableHeadOther{}}% + {\def\tableHeadOther{#4\midrule}}% + \ifthenelse{\isempty{#6}}% + {\def\tableFootOther{}}% + {\def\tableFootOther{\midrule#6}}% + \ifthenelse{\isempty{#7}}% + {\def\tableFootFinal{}}% + {\def\tableFootFinal{\midrule#7}}% + \ifthenelse{\isempty{#9}}% + {% + %\directlua{print([[table »#1« needs label!]]) unlabeledTab = unlabeledTab + 1}% + \def\tableLabel{}% + }% + {% + \def\tableLabel{\labelTable{#9}}% + }% + \ifthenelse{\isempty{#8}}% + {% + \def\tableCaptionFirst{\tableLabel}% + \def\tableCaptionOther{}% + }% + {% + \ifthenelse{\isempty{#1}}% + {\def\tableCaptionFirst{\caption[\nolink{#8}]{\adjustCaption{#8}\tableLabel}\\}}% + {\def\tableCaptionFirst{\caption[\nolink{#1}]{\adjustCaption{#8}\tableLabel}\\}}% + \def\tableCaptionOther{\caption[]{\adjustCaption{#8 (Fortsetzung)}}\\} % + }% + \begin{center}% + \ifthenelse{\isempty{#2}}% + {\begin{longtable}{l*{255}{c}}}% + {\begin{longtable}{#2}}% + \tableCaptionFirst% + \toprule% + \tableHeadFirst% + \endfirsthead% + \tableCaptionOther% + \toprule% + \tableHeadOther% + \endhead% + \tableFootOther% + \bottomrule% + \endfoot% + \tableFootFinal% + \bottomrule% + \endlastfoot% + #5% + %{% + % \directlua + % { + % if not ( tblNoteText == [[]] ) + % then + % tex.print(bs..[[begin{flushleft}]]..bs..[[small]]..tblNoteText..[[.]]..bs..[[end{flushleft}]]) + % end + % }% + %}% + \end{longtable}% + \end{center}% +} + +\newcommand{\LTable}[2] +{ + %1 – config + %2 – body + \directlua + { + tblNotes = 0 + tblNamedNotes = {} + tblNoteText = [[]] + if tblSmall == true + then + end + }% + %\begin{center}% + \ifthenelse{\isempty{#1}}% + {\begin{longtable}{l*{255}{c}}}% + {\begin{longtable}{#1}}% + \directlua + { + if tblSmall == true + then + tex.print([[\noexpand\footnotesize]]) + end + }% + \toprule% + \endfirsthead% + \toprule% + \endhead% + \bottomrule% + \endfoot% + \bottomrule% + \endlastfoot% + #2 + %{% + % \directlua + % { + % if not ( tblNoteText == [[]] ) + % then + % tex.print(bs..[[begin{flushleft}]]..bs..[[small]]..tblNoteText..[[.]]..bs..[[end{flushleft}]]) + % end + % }% + %}% + \end{longtable}% + %\end{center}% +}% +% tex.print(bs..[[newline{]]..bs..[[centering]]..bs..[[mbox[][l]{]]..bs..[[small]]..tblNoteText..[[.}}]])% diff --git a/NixTeX/dependencies/source/fonts.tex b/NixTeX/dependencies/source/fonts.tex new file mode 100644 index 0000000..a5e046c --- /dev/null +++ b/NixTeX/dependencies/source/fonts.tex @@ -0,0 +1,11 @@ +\usepackage{fontspec} +\setmainfont{Roboto}[] +\setsansfont{Roboto}[] +\setmonofont{Roboto Mono}[] + +\usepackage[ngerman,bidi=basic]{babel} +\def\arabic{\foreignlanguage{arabic}} +\def\hebrew{\foreignlanguage{hebrew}} + +\usepackage{fontawesome} +\usepackage{fontenc} diff --git a/NixTeX/dependencies/source/geometry.tex b/NixTeX/dependencies/source/geometry.tex new file mode 100644 index 0000000..a2de1fd --- /dev/null +++ b/NixTeX/dependencies/source/geometry.tex @@ -0,0 +1,9 @@ +\newdimen\spaceleft +\def\textheightleft{\dimexpr\textheight-\pagetotal\relax} +\setlength{\parindent}{0pt} +\newlength{\newtextheight} +\newlength{\heightOfBox} + +\def\relativetextheightleft{\numexpr12*\textheightleft/\textheight\relax} +\def\clearPageOnLastQuarter{\ifnum\relativetextheightleft<4\ifnum\textheight>\pagetotal\clearpage\fi\fi} +\def\clearPageOnLastThird{\ifnum\relativetextheightleft<5\ifnum\textheight>\pagetotal\clearpage\fi\fi} \ No newline at end of file diff --git a/NixTeX/dependencies/source/glossaries/glossaries.tex b/NixTeX/dependencies/source/glossaries/glossaries.tex new file mode 100644 index 0000000..ccf97bf --- /dev/null +++ b/NixTeX/dependencies/source/glossaries/glossaries.tex @@ -0,0 +1,33 @@ +\directlua{includeCode("glossaries/glossaries")} +\let\numColumns\LT@cols +\newcommand{\printAcronyms} [1][single-line]{\directlua{ acronyms.printList ( [[#1]] )}} +\newcommand{\printPeople } [1][people] {\directlua{ people.printList ( [[#1]] )}} + +\newcommand{\acruse } [1] {\directlua{acronyms.use([[#1]])}} +\newcommand{\acrtext } [2][] {\directlua{ acronyms.printText ( [[#1]], [[\detokenize{#2}]] )}} +\newcommand{\acrshort } [1] {\directlua{ acronyms.printShortText ( [[#1]] )}} +\newcommand{\acrchem } [1] {\directlua{ acronyms.printChemical ( [[#1]] )}} +\newcommand{\acrlong } [1] {\expandafter\directlua{ acronyms.printLongText ( [[#1]] )}} +\newcommand{\acrfull } [1] {\directlua{ acronyms.printFullText ( [[#1]] )}} +\newcommand{\acrdesc } [1] {\directlua{ acronyms.printDescription ( [[#1]] )}} +\newcommand{\Acrtext } [2] {\directlua{ acronyms.printText ( [[#1]], [[#2]], [[#2]], true )}} +\newcommand{\Acrshort } [1] {\directlua{ acronyms.printShortText ( [[#1]], true )}} +\newcommand{\Acrlong } [1] {\directlua{ acronyms.printLongText ( [[#1]], true )}} +\newcommand{\Acrfull } [1] {\directlua{ acronyms.printFullText ( [[#1]], true )}} +\newcommand{\Acrdesc } [1] {\directlua{ acronyms.printDescription ( [[#1]], true )}} +\newcommand{\acrexplain } [1] {\directlua{ acronyms.printExplanation ( [[#1]] )}} +\newcommand{\person } [2][] {\directlua{ people.print ( [[#1]], [[#2]] )}} + +\newcommand*{\loadAcronyms} [1] {\directlua{ dofile ( [[#1]] )}} +\def\afteracronyms{} + +% Some parts of the Name might be usefull inside the acronym-table but not in the text itself. +\newcommand{\AcrOptional}[1]{} + +\newcommand{\acrWithOptional}[1] +{{% + \renewcommand{\AcrOptional}[1]{\-#1} + #1% +}} + +\def\underlineAcronyms{\directlua{acronyms.underline=true}} diff --git a/NixTeX/dependencies/source/hazardous/adr.tex b/NixTeX/dependencies/source/hazardous/adr.tex new file mode 100644 index 0000000..c4761b0 --- /dev/null +++ b/NixTeX/dependencies/source/hazardous/adr.tex @@ -0,0 +1,435 @@ +\directlua{includeCode("hazardous/adr")} + +\newlength{\@ADRpictogramRadius} +\newlength{\@ADRpictogramStep} + +\definecolor{adrBlack} {RGB}{ 0, 0, 0} +\definecolor{adrBlue} {RGB}{ 0,146,221} +\definecolor{adrGreen} {RGB}{ 75,176, 51} +\definecolor{adrOrange} {RGB}{252,126, 12} +\definecolor{adrPlate} {RGB}{254,153, 0} +\definecolor{adrRed} {RGB}{239, 46, 51} +\definecolor{adrWhite} {RGB}{255,255,255} +\definecolor{adrYellow} {RGB}{245,240, 20} + +\def\@AdrColour {adrBlack} +\def\@AdrLowerBright {} +\def\@AdrLowerColour {} +\def\@AdrLowerInner {} +\def\@AdrLowerPattern {} +\def\@AdrUpperBright {} +\def\@AdrUpperColour {} +\def\@AdrUpperInner {} +\def\@AdrUpperPattern {} + +\def\adrInverted{\makeatletter\def\@AdrColour{adrWhite}\makeatother} +\def\adrNormal {\makeatletter\def\@AdrColour{adrBlack}\makeatother} + +\newcommand{\adrPlate}[3][1cm] +{{% + \resizebox{#1}{!}% + {% + \fontsize{14cm}{14cm}\selectfont% + \begin{tikzpicture}[every node/.style={inner sep=0,outer sep=0}]% + \fill [ black ] ( 0.00cm, 0.00cm ) rectangle ( 40.00cm, 30.00cm );% + \fill [ adrPlate ] ( 1.50cm, 1.50cm ) rectangle ( 38.50cm, 14.25cm );% + \fill [ adrPlate ] ( 1.50cm, 15.75cm ) rectangle ( 38.50cm, 28.50cm );% + \node at ( 20cm, 7.5cm ) {\textbf{#3}};% + \node at ( 20cm, 22.5cm ) {\textbf{#2}};% + \end{tikzpicture}% + }% +}} + +\newcommand{\adrPictogram}[9][1cm] +{{% + % 1 – width and height + % 2 – upper half colour or pattern + % 3 – lower half colour or pattern + % 4 – inner half colour (adrBlack, adrWhite or adrYellow) + % 5 – pictogram + % 6 – class + % 7 – subclass + % 8 – compatibility group + % 9 – text + \setlength{\@ADRpictogramRadius}{70.71067811865476pt}% + \setlength{\@ADRpictogramStep}{10.878565864408424pt}% + % Upper Half + \def\@AdrUpperBright {false}% + \def\@AdrUpperColour {\@AdrColour}% + \def\@PictogramInverted {false}% + \ifequal{#2}{adrWhite} {\def\@AdrUpperColour{adrBlack}\def\@AdrUpperBright{true}}% + \ifequal{#2}{adrYellow} {\def\@AdrUpperColour{adrBlack}\def\@AdrUpperBright{true}}% + \ifequal{\@AdrUpperColour}{adrWhite} {\def\@PictogramInverted{true}}% + % Lower Half + \def\@AdrLowerBright {false}% + \def\@AdrLowerColour {\@AdrColour}% + \ifequal{#3}{} {\def\@AdrLowerColour{\@AdrUpperColour}\def\@AdrLowerBright{\@AdrUpperBright}}% + \ifequal{#3}{adrWhite} {\def\@AdrLowerColour{adrBlack}\def\@AdrLowerBright{true}}% + \ifequal{#3}{adrYellow} {\def\@AdrLowerColour{adrBlack}\def\@AdrLowerBright{true}}% + % Inner Half + \def\@AdrLowerInner {}% + \def\@AdrUpperInner {}% + \ifequal{#4}{adrBlack} {\def\@AdrLowerColour{adrWhite}\def\@AdrLowerInner{#4}}% + \ifequal{#4}{adrWhite} {\def\@AdrLowerColour{adrBlack}\def\@AdrUpperInner{#4}}% + \ifequal{#4}{adrYellow} {\def\@AdrLowerColour{adrBlack}\def\@AdrUpperInner{#4}}% + \ifequal{#4}{adrBlackStripes} + {% + \def\@AdrUpperPattern{adrBlack}% + \def\@AdrUpperColour{adrBlack}% + \def\@AdrUpperBright{true}% + }% + \ifequal{#4}{adrRedStripes} + {% + \def\@AdrLowerPattern{adrRed}% + \def\@AdrLowerColour{adrBlack}% + \def\@AdrLowerBright{true}% + \def\@AdrUpperPattern{adrRed}% + \def\@AdrUpperColour{adrBlack}% + \def\@AdrUpperBright{true}% + }% + % Resize Pictogram to given size. + \resizebox{#1}{!}% + {% + \begin{tikzpicture}[line width=1pt] + \clip (0,0) rectangle (2\@ADRpictogramRadius, 2\@ADRpictogramRadius); + \fill + [ #2 ] ( 0\@ADRpictogramRadius, 1\@ADRpictogramRadius ) + -- ( 1\@ADRpictogramRadius, 2\@ADRpictogramRadius ) + -- ( 2\@ADRpictogramRadius, 1\@ADRpictogramRadius ) + -- ( 1\@ADRpictogramRadius, 0\@ADRpictogramRadius ) + -- cycle; + \ifnotempty{#3} + { + \fill + [ #3 ] ( 0\@ADRpictogramRadius, 1\@ADRpictogramRadius ) + -- ( 2\@ADRpictogramRadius, 1\@ADRpictogramRadius ) + -- ( 1\@ADRpictogramRadius, 0\@ADRpictogramRadius ) + -- cycle; + } + \ifnotempty{\@AdrUpperPattern} + { + \fill + [ \@AdrUpperPattern ] ( 0\@ADRpictogramStep, 6.5\@ADRpictogramStep ) + -- ( 1\@ADRpictogramStep, 6.5\@ADRpictogramStep ) + -- ( 1\@ADRpictogramStep, 7.5\@ADRpictogramStep ) + -- cycle; + \fill + [ \@AdrUpperPattern ] ( 2\@ADRpictogramStep, 6.5\@ADRpictogramStep ) + -- ( 3\@ADRpictogramStep, 6.5\@ADRpictogramStep ) + -- ( 3\@ADRpictogramStep, 9.5\@ADRpictogramStep ) + -- ( 2\@ADRpictogramStep, 8.5\@ADRpictogramStep ) + -- cycle; + \fill + [ \@AdrUpperPattern ] ( 4\@ADRpictogramStep, 6.5\@ADRpictogramStep ) + -- ( 5\@ADRpictogramStep, 6.5\@ADRpictogramStep ) + -- ( 5\@ADRpictogramStep, 11.5\@ADRpictogramStep ) + -- ( 4\@ADRpictogramStep, 10.5\@ADRpictogramStep ) + -- cycle; + \fill + [ \@AdrUpperPattern ] ( 6.0\@ADRpictogramStep, 6.5\@ADRpictogramStep ) + -- ( 7.0\@ADRpictogramStep, 6.5\@ADRpictogramStep ) + -- ( 7.0\@ADRpictogramStep, 12.5\@ADRpictogramStep ) + -- ( 6.5\@ADRpictogramStep, 13.0\@ADRpictogramStep ) + -- ( 6.0\@ADRpictogramStep, 12.5\@ADRpictogramStep ) + -- cycle; + \fill + [ \@AdrUpperPattern ] ( 8\@ADRpictogramStep, 6.5\@ADRpictogramStep ) + -- ( 9\@ADRpictogramStep, 6.5\@ADRpictogramStep ) + -- ( 9\@ADRpictogramStep, 10.5\@ADRpictogramStep ) + -- ( 8\@ADRpictogramStep, 11.5\@ADRpictogramStep ) + -- cycle; + \fill + [ \@AdrUpperPattern ] ( 10\@ADRpictogramStep, 6.5\@ADRpictogramStep ) + -- ( 11\@ADRpictogramStep, 6.5\@ADRpictogramStep ) + -- ( 11\@ADRpictogramStep, 8.5\@ADRpictogramStep ) + -- ( 10\@ADRpictogramStep, 9.5\@ADRpictogramStep ) + -- cycle; + \fill + [ \@AdrUpperPattern ] ( 12\@ADRpictogramStep, 6.5\@ADRpictogramStep ) + -- ( 13\@ADRpictogramStep, 6.5\@ADRpictogramStep ) + -- ( 12\@ADRpictogramStep, 7.5\@ADRpictogramStep ) + -- cycle; + } + \ifnotempty{\@AdrLowerPattern} + { + \fill + [ \@AdrLowerPattern ] ( 0\@ADRpictogramStep, 6.5\@ADRpictogramStep ) + -- ( 1\@ADRpictogramStep, 6.5\@ADRpictogramStep ) + -- ( 1\@ADRpictogramStep, 5.5\@ADRpictogramStep ) + -- cycle; + \fill + [ \@AdrLowerPattern ] ( 2\@ADRpictogramStep, 6.5\@ADRpictogramStep ) + -- ( 3\@ADRpictogramStep, 6.5\@ADRpictogramStep ) + -- ( 3\@ADRpictogramStep, 3.5\@ADRpictogramStep ) + -- ( 2\@ADRpictogramStep, 4.5\@ADRpictogramStep ) + -- cycle; + \fill + [ \@AdrLowerPattern ] ( 4\@ADRpictogramStep, 6.5\@ADRpictogramStep ) + -- ( 5\@ADRpictogramStep, 6.5\@ADRpictogramStep ) + -- ( 5\@ADRpictogramStep, 1.5\@ADRpictogramStep ) + -- ( 4\@ADRpictogramStep, 2.5\@ADRpictogramStep ) + -- cycle; + \fill + [ \@AdrLowerPattern ] ( 6.0\@ADRpictogramStep, 6.5\@ADRpictogramStep ) + -- ( 7.0\@ADRpictogramStep, 6.5\@ADRpictogramStep ) + -- ( 7.0\@ADRpictogramStep, 0.5\@ADRpictogramStep ) + -- ( 6.5\@ADRpictogramStep, 0.0\@ADRpictogramStep ) + -- ( 6.0\@ADRpictogramStep, 0.5\@ADRpictogramStep ) + -- cycle; + \fill + [ \@AdrLowerPattern ] ( 8\@ADRpictogramStep, 6.5\@ADRpictogramStep ) + -- ( 9\@ADRpictogramStep, 6.5\@ADRpictogramStep ) + -- ( 9\@ADRpictogramStep, 2.5\@ADRpictogramStep ) + -- ( 8\@ADRpictogramStep, 1.5\@ADRpictogramStep ) + -- cycle; + \fill + [ \@AdrLowerPattern ] ( 10\@ADRpictogramStep, 6.5\@ADRpictogramStep ) + -- ( 11\@ADRpictogramStep, 6.5\@ADRpictogramStep ) + -- ( 11\@ADRpictogramStep, 4.5\@ADRpictogramStep ) + -- ( 10\@ADRpictogramStep, 3.5\@ADRpictogramStep ) + -- cycle; + \fill + [ \@AdrLowerPattern ] ( 12\@ADRpictogramStep, 6.5\@ADRpictogramStep ) + -- ( 13\@ADRpictogramStep, 6.5\@ADRpictogramStep ) + -- ( 12\@ADRpictogramStep, 5.5\@ADRpictogramStep ) + -- cycle; + } + \ifnotempty{\@AdrUpperInner} + { + \fill + [ \@AdrUpperInner ] ( 0\@ADRpictogramRadius+5pt, 1\@ADRpictogramRadius ) + -- ( 1\@ADRpictogramRadius, 2\@ADRpictogramRadius-5pt ) + -- ( 2\@ADRpictogramRadius-5pt, 1\@ADRpictogramRadius ) + -- cycle; + \draw + [ adrBlack ] ( 0\@ADRpictogramRadius+5pt, 1\@ADRpictogramRadius ) + -- ( 2\@ADRpictogramRadius-5pt, 1\@ADRpictogramRadius ); + } + \ifnotequal{\@AdrUpperPattern}{\@AdrLowerPattern} + { + \draw + [ adrBlack ] ( 0\@ADRpictogramRadius+5pt, 1\@ADRpictogramRadius ) + -- ( 2\@ADRpictogramRadius-5pt, 1\@ADRpictogramRadius ); + } + \ifnotempty{\@AdrLowerInner} + { + \fill + [ \@AdrLowerInner ] ( 0\@ADRpictogramRadius+5pt, 1\@ADRpictogramRadius ) + -- ( 1\@ADRpictogramRadius, 0\@ADRpictogramRadius+5pt ) + -- ( 2\@ADRpictogramRadius-5pt, 1\@ADRpictogramRadius ) + -- cycle; + } + \ifthenelse{\equal{\@AdrLowerBright}{true}} + { + \ifthenelse{\equal{\@AdrUpperBright}{true}} + { + % Upper and lower half need a dashed line. + \draw + [ + adrBlack, + dash pattern={on 6.25pt off 4.166666666666667pt}, + ] ( 0\@ADRpictogramRadius, 1\@ADRpictogramRadius ) + -- ( 1\@ADRpictogramRadius, 2\@ADRpictogramRadius ); + \draw + [ + adrBlack, + dash pattern={on 6.25pt off 4.166666666666667pt}, + ] ( 1\@ADRpictogramRadius, 2\@ADRpictogramRadius ) + -- ( 2\@ADRpictogramRadius, 1\@ADRpictogramRadius ); + \draw + [ + adrBlack, + dash pattern={on 6.25pt off 4.166666666666667pt}, + ] ( 2\@ADRpictogramRadius, 1\@ADRpictogramRadius ) + -- ( 1\@ADRpictogramRadius, 0\@ADRpictogramRadius ); + \draw + [ + adrBlack, + dash pattern={on 6.25pt off 4.166666666666667pt}, + ] ( 1\@ADRpictogramRadius, 0\@ADRpictogramRadius ) + -- ( 0\@ADRpictogramRadius, 1\@ADRpictogramRadius ); + % Therefore the solid line must be black. + \draw + [ adrBlack ] ( 0\@ADRpictogramRadius+5pt, 1\@ADRpictogramRadius ) + -- ( 1\@ADRpictogramRadius, 2\@ADRpictogramRadius-5pt ) + -- ( 2\@ADRpictogramRadius-5pt, 1\@ADRpictogramRadius ) + -- ( 1\@ADRpictogramRadius, 0\@ADRpictogramRadius+5pt ) + -- cycle; + } + { + % Only lower half needs a dashed line. + \draw + [ + adrBlack, + dash pattern={on 6.25pt off 4.166666666666667pt}, + ] ( 0\@ADRpictogramRadius, 1\@ADRpictogramRadius ) + -- ( 1\@ADRpictogramRadius, 0\@ADRpictogramRadius ); + \draw + [ + adrBlack, + dash pattern={on 6.25pt off 4.166666666666667pt}, + ] ( 1\@ADRpictogramRadius, 0\@ADRpictogramRadius ) + -- ( 2\@ADRpictogramRadius, 1\@ADRpictogramRadius ); + % Therefore the solid line must be black. + \draw + [ adrBlack ] ( 0\@ADRpictogramRadius+5pt, 1\@ADRpictogramRadius ) + -- ( 1\@ADRpictogramRadius, 2\@ADRpictogramRadius-5pt ) + -- ( 2\@ADRpictogramRadius-5pt, 1\@ADRpictogramRadius ) + -- ( 1\@ADRpictogramRadius, 0\@ADRpictogramRadius+5pt ) + -- cycle; + } + } + { + \ifthenelse{\equal{\@AdrUpperBright}{true}} + { + % Only upper half needs a dashed line. + \draw + [ + adrBlack, + dash pattern={on 6.25pt off 4.166666666666667pt}, + ] ( 0\@ADRpictogramRadius, 1\@ADRpictogramRadius ) + -- ( 1\@ADRpictogramRadius, 2\@ADRpictogramRadius ); + \draw + [ + adrBlack, + dash pattern={on 6.25pt off 4.166666666666667pt}, + ] ( 1\@ADRpictogramRadius, 2\@ADRpictogramRadius ) + -- ( 2\@ADRpictogramRadius, 1\@ADRpictogramRadius ); + % Therefore the solid line must be black. + \draw + [ adrBlack ] ( 0\@ADRpictogramRadius+5pt, 1\@ADRpictogramRadius ) + -- ( 1\@ADRpictogramRadius, 2\@ADRpictogramRadius-5pt ) + -- ( 2\@ADRpictogramRadius-5pt, 1\@ADRpictogramRadius ) + -- ( 1\@ADRpictogramRadius, 0\@ADRpictogramRadius+5pt ) + -- cycle; + } + { + % No half need a dashed line. + % Solid line could be white or black. + \draw + [ \@AdrColour ] ( 0\@ADRpictogramRadius+5pt, 1\@ADRpictogramRadius ) + -- ( 1\@ADRpictogramRadius, 2\@ADRpictogramRadius-5pt ) + -- ( 2\@ADRpictogramRadius-5pt, 1\@ADRpictogramRadius ) + -- ( 1\@ADRpictogramRadius, 0\@ADRpictogramRadius+5pt ) + -- cycle; + } + } + \node + [ + text centered, + text width = 2.00\@ADRpictogramRadius, + ] at ( 1\@ADRpictogramRadius, 1.40\@ADRpictogramRadius ) + {{\color{\@AdrUpperColour}\fontsize{50pt}{50pt}\selectfont #5}}; + \node + [ + text centered, + text depth = 0.45\@ADRpictogramRadius, + text height = 0.50\@ADRpictogramRadius, + text width = 2.00\@ADRpictogramRadius, + ] at ( 1\@ADRpictogramRadius, 0.85\@ADRpictogramRadius ) {\color{\@AdrLowerColour}\large #9}; + \node at ( 1\@ADRpictogramRadius, 0.35\@ADRpictogramRadius ) {\color{\@AdrLowerColour}\Large #6}; + \node at ( 1\@ADRpictogramRadius, 0.55\@ADRpictogramRadius ) {\color{\@AdrLowerColour}\small #8}; + \node at ( 1\@ADRpictogramRadius, 0.70\@ADRpictogramRadius ) {\color{\@AdrLowerColour}\small #7}; + \end{tikzpicture}% + }% +}} + +\newcommand{\adrExplosive }[3][1cm] + {\adrPictogram[#1]{adrOrange} {} {} {\fontsize{45pt}{45pt}\selectfont\pictogramExplosive} {1} {1.#2~} {#3} + {\LARGE EXPLOSIVE}} +\newcommand{\adrLessExplosive }[3][1cm] + {\adrPictogram[#1]{adrOrange} {} {} {\fontsize{35pt}{35pt}\selectfont\textbf{1.#2}} {1} {} {#3} + {\LARGE EXPLOSIVE}} +\newcommand{\adrFlammableGas }[1][1cm] + {\adrPictogram[#1]{adrRed} {} {} {\fontsize{50pt}{50pt}\selectfont\pictogramFlammable} {2} {} {} + {\LARGE FLAMMABLE\\\LARGE GAS}} +\newcommand{\adrNonFlammableGas }[1][1cm] + {\adrPictogram[#1]{adrGreen} {} {} {\fontsize{20pt}{20pt}\selectfont\pictogramGasBottle} {2} {} {} + {NON-FLAMMABLE\\\LARGE GAS}} +\newcommand{\adrPoisonGas }[1][1cm] + {\adrPictogram[#1]{adrWhite} {} {} {\fontsize{45pt}{45pt}\selectfont\pictogramSkull} {2} {} {} + {\Huge POISON\\GAS}} +\newcommand{\adrFlammableLiquid }[1][1cm] + {\adrPictogram[#1]{adrRed} {} {} {\fontsize{50pt}{50pt}\selectfont\pictogramFlammable} {3} {} {} + {\LARGE FLAMMABLE\\\large LIQUID}} +\newcommand{\adrFlammableSolid }[1][1cm] + {\adrPictogram[#1]{adrWhite} {} {adrRedStripes} {\fontsize{50pt}{50pt}\selectfont\pictogramFlammable} {4} {} {} + {\LARGE FLAMMABLE\\\LARGE SOLID}} +\newcommand{\adrSpontaneouslyCombustible }[1][1cm] + {\adrPictogram[#1]{adrWhite} {adrRed} {} {\fontsize{50pt}{50pt}\selectfont\pictogramFlammable} {4} {} {} + {\large SPONTANEOUSLY\\\normalsize COMBUSTIBLE}} +\newcommand{\adrDangerousWhenWet }[1][1cm] + {\adrPictogram[#1]{adrBlue} {} {} {\fontsize{50pt}{50pt}\selectfont\pictogramFlammable} {4} {} {} + {\LARGE DANGEROUS\\\large WHEN WET}} +\newcommand{\adrOxidiser }[1][1cm] + {\adrPictogram[#1]{adrYellow} {} {} {\fontsize{50pt}{50pt}\selectfont\pictogramOxidiser} {5.1} {} {} + {\\[-.8\normalbaselineskip]\Huge OXIDISER}} +\newcommand{\adrPeroxide }[1][1cm] + {\adrPictogram[#1]{adrRed} {adrYellow} {} {\fontsize{50pt}{50pt}\selectfont\pictogramFlammable} {5.2} {} {} + {\large ORGANIC\\\LARGE PEROXID}} +\newcommand{\adrToxic }[1][1cm] + {\adrPictogram[#1]{adrWhite} {} {} {\fontsize{50pt}{50pt}\selectfont\pictogramSkull} {6} {} {} + {\Huge TOXIC}} +\newcommand{\adrInfectious }[1][1cm] + {\adrPictogram[#1]{adrWhite} {} {} {\fontsize{60pt}{60pt}\selectfont\DejaVuSans^^^^2623} {6} {} {} + {% + \\[-1.3\normalbaselineskip]% + \normalsize INFECTIOUS SUBSTANCE\\% + \tiny IN CASE OF DAMAGE OR LEAKAGE\\IMMEDIATELY NOTIFY\\PUBLIC HEALTH AUTHORITY\\% + }} +\newcommand{\adrRadioactiveI }[3][1cm] + {\adrPictogram[#1]{adrWhite} {} {adrWhite} {\fontsize{70pt}{70pt}\selectfont\Radioactivity} {7} {} {} + {% + \large RADIOACTIVE \textbf{\color{adrRed}\selectfont I}\\% + \tiny CONTENTS: #2\\% + ACTIVITY: \Physical#3{}{}{}{}\\[-.9\normalbaselineskip]% + }} +\newcommand{\adrRadioactiveII }[4][1cm] + {\adrPictogram[#1]{adrWhite} {} {adrYellow} {\fontsize{70pt}{70pt}\selectfont\Radioactivity} {7} {} {} + {% + \large RADIOACTIVE \textbf{\color{adrRed}\selectfont II}\\% + \tiny CONTENTS: #2\\% + ACTIVITY: \Physical#3{}{}{}{}\\[-.9\normalbaselineskip]% + \setlength{\fboxsep}{0pt}% + \fbox{\parbox[][.08\linewidth][b]{.37\linewidth} + {% + \centering% + \fontsize{8pt}{8pt}\selectfont #4\\% + \fontsize{5pt}{5pt}\selectfont TRANSPORT INDEX}% + }% + }} +\newcommand{\adrRadioactiveIII }[4][1cm] + {\adrPictogram[#1]{adrWhite} {} {adrYellow} {\fontsize{70pt}{70pt}\selectfont\Radioactivity} {7} {} {} + {% + \large RADIOACTIVE \textbf{\color{adrRed}\selectfont III}\\% + \tiny CONTENTS: #2\\% + ACTIVITY: \Physical#3{}{}{}{}\\[-.9\normalbaselineskip]% + \setlength{\fboxsep}{0pt}% + \fbox{\parbox[][.08\linewidth][b]{.37\linewidth} + {% + \centering% + \fontsize{8pt}{8pt}\selectfont #4\\% + \fontsize{5pt}{5pt}\selectfont TRANSPORT INDEX}% + }% + }} +\newcommand{\adrFissile }[2][1cm] + {\adrPictogram[#1]{adrWhite} {} {adrWhite} {~\\[.4\normalbaselineskip]\Huge FISSILE\\} {7} {} {} + {% + ~\\[-.5\normalbaselineskip]% + \setlength{\fboxsep}{0pt}% + \fbox{\parbox[][.2\linewidth][b]{.45\linewidth} + {% + \centering% + \fontsize{15pt}{15pt}\selectfont #2\\% + \fontsize{7pt}{7pt}\selectfont CRITICALITY\\ SAFETY INDEX}% + }% + }} +\newcommand{\adrCorrosive }[1][1cm] + {\adrPictogram[#1]{adrWhite} {} {adrBlack} {\fontsize{30pt}{30pt}\selectfont\pictogramCorrosive\,} {8} {} {} + {\\[-.5\normalbaselineskip]\Large CORROSIVE}} +\newcommand{\adrOther }[1][1cm] + {\adrPictogram[#1]{adrWhite} {} {adrBlackStripes} {} {\underline{9}} + {}{}{}} +\newcommand{\adrLithiumCells }[1][1cm] + {\adrPictogram[#1]{adrWhite} {} {adrBlackStripes} {} {\underline{9}} + {\fontsize{30pt}{30pt}\selectfont\pictogramLithiumCells}{}{}} diff --git a/NixTeX/dependencies/source/hazardous/ghs.tex b/NixTeX/dependencies/source/hazardous/ghs.tex new file mode 100644 index 0000000..31d2690 --- /dev/null +++ b/NixTeX/dependencies/source/hazardous/ghs.tex @@ -0,0 +1,2 @@ +\directlua{includeCode("hazardous/ghs/ghs")} +\newcommand{\ghsPictogram}[2][]{\makeatletter\directlua{tex.print(ghsNamedPictogram([[#2]], [[#1]]))}\makeatother} diff --git a/NixTeX/dependencies/source/hazardous/hazardous.tex b/NixTeX/dependencies/source/hazardous/hazardous.tex new file mode 100644 index 0000000..f409260 --- /dev/null +++ b/NixTeX/dependencies/source/hazardous/hazardous.tex @@ -0,0 +1,180 @@ +\inputCode{hazardous/adr} +\inputCode{hazardous/ghs/ghs} +\inputCode{hazardous/nfpa} +\directlua{includeCode("hazardous/hazardous")} +\addbibresource{\source/assets/bibliography/hazardous.bib} + +\newlength{\@HazardousLength} +\setlength{\@HazardousLength} {\linewidth} +\newlength{\@HazardousPictogramSep} +\setlength{\@HazardousPictogramSep} {0.1em} +\newlength{\@HazardousPictogramSize} +\setlength{\@HazardousPictogramSize} {3.0cm} + +\def\@HazardousColumns {1} +\def\@HazardousOrientation {} +\def\@HazardousScale {1} +\def\@HazardousUsage {} +\newcommand{\@HazardousConfig}[4] +{% + \ifthenelse{\isempty{#1}}% + {\def\@HazardousOrientation {left}}% + {\def\@HazardousOrientation {#1}}% + \ifthenelse{\isempty{#2}}% + {\def\@HazardousColumns {1}}% + {\def\@HazardousColumns {#2}}% + \ifthenelse{\isempty{#3}}% + {\def\@HazardousScale {1}}% + {\def\@HazardousScale {#3}}% + \ifthenelse{\isempty{#4}}% + {\setlength{\@HazardousLength} {\linewidth}}% + {\setlength{\@HazardousLength} {#4}}% +} + +\newcommand{\@Hazardous}[6] +{{\unskip% + %1 – citations? + %2 – substance + %3 – amount + %4 – purity + %5 – manufacturer + %6 – usage + \directlua + { + if [[#1]] == "true" + then + citations = true + elseif [[#1]] == "false" + then + citations = false + else% + citations = not noCitations + end + hazardousData = getHazardous ( [[#2]] ) + }% + \framebox[\@HazardousLength]% + {% + \scalebox{\@HazardousScale}% + {% + \setlength{\@HazardousLength}{1pt*\ratio{\@HazardousLength}{\@HazardousScale pt}}% + \def\@HazardousContent% + {% + \def\@HazardousUsage{}% + \ifnotempty{#6}% + {% + \def\@HazardousUsage% + {% + \midrule[1pt] \\[-1.5\normalbaselineskip]% + \multicolumn{4}{@{}l@{}}{\parbox[t][][c]{\linewidth}{\scriptsize #6}} \\% + }% + }% + {\LARGE\textbf{\directlua{hazardousTitle(hazardousData)}}} \newline% + \begin{tabularx}{\linewidth}{@{}l@{}X@{}l@{}R{45pt}@{}}% + \footnotesize\directlua{hazardousUFIorECtitle(hazardousData)} &% + \footnotesize\directlua{hazardousUFIorECident(hazardousData)} &% + \footnotesize\textbf{\directlua{hazardousUFIorCAStitle(hazardousData)}} &% + \footnotesize\hfill\directlua{hazardousUFIorCASident(hazardousData)} \\% + \multicolumn{3}{@{}p{\linewidth-45pt}@{}}% + {% + \scriptsize% + \ifthenelse{\isempty{#4}}% + {\directlua { hazardousPhysicals ( false, hazardousData ) }}% + {#4\directlua { hazardousPhysicals ( true, hazardousData ) }}% + } &% + \textbf{#3} \\% + \midrule[1pt] \\[-1.5\normalbaselineskip]% + \multicolumn{4}{@{}l@{}}{\parbox[t][][c]{\linewidth} + {\noWordBreaks\scriptsize\directlua{hazardousStatements(hazardousData)}}} \\% + \midrule[1pt] \\[-1.5\normalbaselineskip]% + \multicolumn{4}{@{}l@{}}{\parbox[t][][c]{\linewidth}{\scriptsize #5}} \\% + \@HazardousUsage% + \end{tabularx}% + }% + \fourCases[\@HazardousOrientation] + {top} + {% + \begin{tabularx}% + {\@HazardousLength}% + {X}% + \multicolumn{1}{Z}% + {% + \mbox{}\newline% + \directlua{hazardousPictograms(hazardousData,[[\@HazardousColumns]])}\mbox{}\newline[0.5\normalbaselineskip]% + {\LARGE\directlua{hazardousSignal(hazardousData)}}% + } \\% + \midrule[1pt]% + \@HazardousContent \\% + \end{tabularx}% + }% + {down} + {% + \begin{tabularx}% + {\@HazardousLength}% + {X}% + \@HazardousContent \\% + \midrule[1pt]% + \multicolumn{1}{Z}% + {% + \mbox{}\newline% + \directlua{hazardousPictograms(hazardousData,[[\@HazardousColumns]])}\mbox{}\newline[0.5\normalbaselineskip]% + {\LARGE\directlua{hazardousSignal(hazardousData)}}% + } \\% + \end{tabularx}% + }% + {left} + {% + \begin{tabularx}% + {\@HazardousLength}% + {@{\hspace{\@HazardousPictogramSep}}C{\@HazardousColumns\@HazardousPictogramSize+\@HazardousColumns\@HazardousPictogramSep}@{}!{\vrule width 1pt}X}% + \parbox[t][][s]{\linewidth} + { + \centering% + ~\newline[-.7\normalbaselineskip] + \directlua{hazardousPictograms(hazardousData,[[\@HazardousColumns]])}\newline + {\LARGE ~}\newline[0.5\normalbaselineskip] + } &% + \@HazardousContent \\[-\normalbaselineskip]% + {\LARGE\directlua{hazardousSignal(hazardousData)}}& \\% + \end{tabularx}% + }% + {right} + {% + \begin{tabularx}% + {\@HazardousLength}% + {X!{\vrule width 1pt}@{\hspace{\@HazardousPictogramSep}}C{\@HazardousColumns\@HazardousPictogramSize+\@HazardousColumns\@HazardousPictogramSep}@{}}% + \@HazardousContent &% + \parbox[t][][s]{\linewidth} + { + \centering% + ~\newline[-.7\normalbaselineskip] + \directlua{hazardousPictograms(hazardousData,[[\@HazardousColumns]])}\newline + {\LARGE ~}\newline[0.5\normalbaselineskip] + } \\[-\normalbaselineskip]% + &{\LARGE\directlua{hazardousSignal(hazardousData)}} \\% + \end{tabularx}% + }% + }% + }\hspace{0pt}% +}} + +% frontend for use in protocols +\newcommand{\hazardous}[2][] +{% + %1 – config + %2 – substance + \@HazardousConfig #1{}{}{}% + \@Hazardous {true}{#2}{}{}{}{}% +} + +% frontend for use in labels +\newcommand{\Hazardous}[6][] +{% + %1 – config + %2 – substance + %3 – amount + %4 – purity + %5 – manufacturer + %6 – usage + \@HazardousConfig#1{}{}{}% + \@Hazardous{false}{#2}{#3}{#4}{#5}{#6}\relax% +} diff --git a/NixTeX/dependencies/source/hazardous/nfpa.tex b/NixTeX/dependencies/source/hazardous/nfpa.tex new file mode 100644 index 0000000..3134f4c --- /dev/null +++ b/NixTeX/dependencies/source/hazardous/nfpa.tex @@ -0,0 +1,66 @@ +\directlua{includeCode("hazardous/nfpa")} + +\definecolor{nfpaFire} {RGB}{255, 102, 102} +\definecolor{nfpaHealth} {RGB}{102, 145, 255} +\definecolor{nfpaReaction} {RGB}{252, 255, 102} +\definecolor{nfpaOther} {RGB}{252, 255, 255} + +% official +\def\nfpaAsphyxiant{\Large SA} +\def\nfpaNoWater{\LARGE\Sout[2pt]{\hspace{0.1em}W\hspace{0.1em}}} +\def\nfpaOxidiser{\Large OX} + +% inofficial +\def\nfpaAcid{\large ACID} +\def\nfpaAlkaline{\large ALK} +\def\nfpaBioHazard{\Huge\DejaVuSans^^^^2623} +\def\nfpaCorrosive{\large COR} +\def\nfpaCryogenic{\Huge\DejaVuSans^^^^2744} +\def\nfpaEcoHazard +{% + \begin{tikzpicture}% + \node [ white ] at ( 0, 0 ) {\large ECO}; + \node at ( 0, 0 ) {\includegraphics[height=1.5em]{\source/assets/pictograms/other/ecoHazard.pdf}}; + \end{tikzpicture}% +} +\def\nfpaEtching +{% + \begin{tikzpicture}% + \node [ white ] at ( 0, 0 ) {\large COR}; + \node at ( 0, 0 ) {\includegraphics[height=1em]{\source/assets/pictograms/other/corrosive.pdf}}; + \end{tikzpicture}% +} +\def\nfpaExplosive +{% + \begin{tikzpicture}% + \node [ white ] at ( 0, 0 ) {\large EXP}; + \node at ( 0, 0 ) {\includegraphics[height=1.5em]{\source/assets/pictograms/other/explosive.pdf}}; + \end{tikzpicture}% +} +\def\nfpaHot{\LARGE\FontAwesomeSolid^^^^f2c8} +\def\nfpaRadioactiv{\radioactivity} +\def\nfpaToxic{\Huge\DejaVuSans^^^^2620} + +\newcommand{\nfpaDiamond}[5][2cm] +{% + % 1 – size + % 2 – fire hazars + % 3 – health hazards + % 4 – reaction hazards + % 5 – other hazards + \resizebox{#1}{!}% + {% + \begin{tikzpicture}[rotate=225]% + \contourlength{0.05em}% + \fill [ nfpaFire ] ( 0, 0 ) rectangle ( 1, 1 );% + \fill [ nfpaHealth ] ( 1, 0 ) rectangle ( 2, 1 );% + \fill [ nfpaReaction ] ( 0, 1 ) rectangle ( 1, 2 );% + \fill [ nfpaOther ] ( 1, 1 ) rectangle ( 2, 2 );% + \draw ( 0, 2 ) grid ( 2, 0 );% + \node at ( 0.5, 0.5 ) {\contour{nfpaOther}{\huge#2}};% + \node at ( 1.5, 0.5 ) {\contour{nfpaOther}{\huge#3}};% + \node at ( 0.5, 1.5 ) {\contour{nfpaOther}{\huge#4}};% + \node at ( 1.5, 1.5 ) {#5};% + \end{tikzpicture}\relax% + }% +} diff --git a/NixTeX/dependencies/source/letter.tex b/NixTeX/dependencies/source/letter.tex new file mode 100644 index 0000000..e8ece6d --- /dev/null +++ b/NixTeX/dependencies/source/letter.tex @@ -0,0 +1,285 @@ +\makeatletter +% Variables in Alphanumeric Order +\def\@LetterEnclosureBody {} +\def\@LetterEnclosureList {} +\def\@LetterEnclosureTitle {} +\def\@LetterAfter {} +\def\@LetterBefore {} +\def\@LetterClosing {} +\def\@LetterConfigurations {} +\def\@LetterContent {} +\def\@LetterCopies {} +\def\@LetterDate {} +\def\@LetterOpening {} +\def\@LetterReceiverCountry {} +\def\@LetterReceiverFirstName {} +\def\@LetterReceiverInstituteLong {} +\def\@LetterReceiverInstituteShort {} +\def\@LetterReceiverLastName {} +\def\@LetterReceiverMunicipality {} +\def\@LetterReceiverPostalCode {} +\def\@LetterReceiverStreet {} +\def\@LetterReceiverStreetExtra {} +\def\@LetterReceiverStreetNumber {} +\def\@LetterReceiverTitle {} +\def\@LetterSenderCountry {} +\def\@LetterSenderEMail {} +\def\@LetterSenderFax {} +\def\@LetterSenderFirstName {} +\def\@LetterSenderHomepage {} +\def\@LetterSenderKey {} +\def\@LetterSenderLastName {} +\def\@LetterSenderLogo {} +\def\@LetterSenderMobile {} +\def\@LetterSenderMunicipality {} +\def\@LetterSenderNickName {} +\def\@LetterSenderPostalCode {} +\def\@LetterSenderStreet {} +\def\@LetterSenderStreetExtra {} +\def\@LetterSenderStreetNumber {} +\def\@LetterSenderTelephone {} +\def\@LetterSenderTitle {} +\def\@LetterSignature {} +\def\@LetterSubject {} +\def\@LetterStyle {} +\def\@LetterType {} + +% Frontend +\newcommand{\makeLetter }[1] +{ + % load letter style + \@for\tmp:=\@LetterStyle\do {\input{\source/styles/letter/\tmp.tex}} + + \constPDF + {\@LetterSenderFirstName\ \@LetterSenderLastName} + {\@LetterSubject vom \@LetterDate} + {\@LetterType} + {} + {} + {} + + % Positons, Lengths, Alingments, etc. + \MSonehalfspacing + \newgeometry + { + textwidth = 16.5cm, + left = 2.5cm, + } + \@setplength{lochpos}{1.0cm} + \@setplength{locwidth}{7.5cm} + \newlength{\@signatureHeight} + \newlength{\@signaturePadding} + \newlength{\@signatureBefore} + \setlength{\@signatureHeight}{1.2cm} + \setlength{\@signaturePadding}{.3\normalbaselineskip} + \setlength{\@signatureBefore}{\@signatureHeight+\normalbaselineskip} + + % Input Variables are set now, lets use them + % set pdf metadata + \KOMAoptions + { + foldmarks = H, + subject = titled, + } + \setkomavar{backaddress} + { + \@LetterSenderFirstName\ \@LetterSenderLastName\\ + \@LetterSenderStreet~\@LetterSenderStreetNumber\\ + \ifnotempty{\@LetterSenderStreetExtra}{\@LetterSenderStreetExtra\\} + \ifnotempty{\@LetterSenderCountry\,}\@LetterSenderPostalCode~\@LetterSenderMunicipality + } + \setkomavar{backaddressseparator} {\,·\,} + \setkomavar{date} {\@LetterDate} + \setkomavar{location} + {{ + \scriptsize + \ifthenelse{\equal{}{\@LetterSenderStreetExtra}} + {\def\@fromExtra{}} + {\def\@fromExtra{\multicolumn{3}{l}{\@LetterSenderStreetExtra}\\}} + \begin{tabular}{r@{}ll} + \multicolumn{3}{l}{\@LetterSenderFirstName\ \@LetterSenderLastName} \\ + \multicolumn{3}{l}{\@LetterSenderStreet~\@LetterSenderStreetNumber} \\ + \@fromExtra + \multicolumn{3}{l}{\ifnotempty{\@LetterSenderCountry\,}\@LetterSenderPostalCode~\@LetterSenderMunicipality} \\ + \ifnotempty{\@LetterSenderTelephone} {\phoneicon\, & \IfLanguageName{ngerman}{Telefon}{Telephone}: & \@LetterSenderTelephone \\} + \ifnotempty{\@LetterSenderFax} {\faxicon\, & \IfLanguageName{ngerman}{Fax}{Telefax}: & \@LetterSenderFax \\} + \ifnotempty{\@LetterSenderMobile} {\mobileicon\, & \IfLanguageName{ngerman}{Mobil}{Mobile Phone}: & \@LetterSenderMobile \\} + \ifnotempty{\@LetterSenderEMail} {\emailicon\, & E-Mail: & \emaillink{\@LetterSenderEMail} \\} + \ifnotempty{\@LetterSenderKey} {\keyicon\, & PGP: & \httpslink{\@LetterSenderKey} \\} + \ifnotempty{\@LetterSenderHomepage} {\homepageicon\, & Homepage: & \httpslink{\@LetterSenderHomepage} \\} + \end{tabular} + }} + \ifnotempty{\@LetterSenderLogo} + { + \KOMAoptions{fromlogo=true} + \setkomavar{fromlogo} {\includegraphics[width=0.23\linewidth]{\@LetterSenderLogo}} + } + \setkomavar{place} {\@LetterSenderMunicipality} + \setkomavar{signature} + { + \ifnotempty{\@LetterSignature} + { + \\[-\@signatureBefore] + \includegraphics[height=\@signatureHeight]{\@LetterSignature}\\[-\@signaturePadding] + } + \@LetterSenderFirstName~\@LetterSenderLastName + } + \setkomavar{subject} []{\@LetterSubject} + + % set default values of variables of other modules + \@ResumeFromLetter + + % some custom configuration, might override defaults + \@LetterConfigurations + + \begin{document} + % cover letter + \noWordBreaks + \addsectiontocentry{}{Anschreiben} + \def\@institute {} + \ifnotempty{\@LetterReceiverInstituteLong} + {\def\@institute {\@LetterReceiverInstituteLong\\}} + \def\@lastName {} + \ifnotempty{\@LetterReceiverLastName} + {\def\@lastName { \@LetterReceiverLastName}} + \def\@streetExtra {} + \ifnotempty{\@LetterReceiverStreetExtra} + {\def\@streetExtra {\@LetterReceiverStreetExtra\\}} + \def\@country {} + \ifnotempty{\@LetterReceiverCountry} + {\def\@country {\@LetterReceiverCountry\,}} + \begin{letter} + { + \@institute + \@LetterReceiverFirstName\@lastName\\ + \@LetterReceiverStreet~\@LetterReceiverStreetNumber\\ + \@streetExtra + \@country\@LetterReceiverPostalCode~\@LetterReceiverMunicipality + } + \@LetterBefore + \opening{\@LetterOpening\IfLanguageName{ngerman}{,}{.}} + \@LetterContent\par + \closing{\@LetterClosing} + \vfill + \ifnotempty{\@LetterEnclosureList} + { + \setkomavar*{enclseparator}{\@LetterEnclosureTitle} + \encl{\@LetterEnclosureList} + } + \ifnotempty{\@LetterCopies} + { + \cc{\@LetterCopies} + } + \@LetterAfter + \end{letter} + + % main matter + #1 + + % enclosure, e.g. documents + \ifempty{\@LetterEnclosureBody} + {% + \clearpage% + \markboth{}{}% + \thispagestyle {empty}% + \mbox{}% + \cleardoublepage% + \mbox{}% + \phantomsection% + \mbox{}\\[-\normalbaselineskip]\nopagebreak% + \addsectiontocentry{} {\@LetterEnclosureTitle}% + \unskip\ignorespaces\@LetterEnclosureBody% + }% + \end{document} +} + +%% Set Enclosure +\newcommand{\theEnclosure }[3][\IfLanguageNeme{ngerman}{Anlage}{Enclosure}] +{ + \def\@LetterEnclosureTitle {#1} + \def\@LetterEnclosureList {#2} + \def\@LetterEnclosureBody {#3} +} + +\newcommand{\enclosureSection }[2]% +{% + \phantomsection% + \mbox{}\\[-\normalbaselineskip]\nopagebreak% + \addsubsectiontocentry{} {#1}% + \markleft {#1}% + \ignorespaces#2\clearpage% +}% + +%% Set Receiver +\newcommand{\theReceiver }[5][] +{ + \def\@LetterReceiverInstituteShort {#1} + \def\@LetterReceiverInstituteLong {#2} + \theReceiverName #3{}{}{} + \theReceiverStreet #4{}{} + \theReceiverCity #5{}{} +} + +\newcommand{\theReceiverCity }[3][] +{ + \def\@LetterReceiverCountry {#1} + \def\@LetterReceiverPostalCode {#2} + \def\@LetterReceiverMunicipality {#3} +} + +\newcommand{\theReceiverName }[3][] +{ + \def\@LetterReceiverTitle {#1} + \def\@LetterReceiverFirstName {#2} + \def\@LetterReceiverLastName {#3} +} + +\newcommand{\theReceiverStreet }[3][] +{ + \def\@LetterReceiverStreetExtra {#1} + \def\@LetterReceiverStreet {#2} + \def\@LetterReceiverStreetNumber {#3} +} + +%% Set Sender +\newcommand{\theSender }[9][] +{ + \def\@LetterSenderLogo {#1} + \theSenderName #2{}{}{} + \theSenderStreet #3{}{} + \theSenderCity #4{}{} + \def\@LetterSenderTelephone {#5} + \def\@LetterSenderFax {#6} + \def\@LetterSenderMobile {#7} + \theSenderEMail #8{} + \def\@LetterSenderHomepage {#9} +} + +\newcommand{\theSenderCity }[3][] +{ + \def\@LetterSenderCountry {#1} + \def\@LetterSenderPostalCode {#2} + \def\@LetterSenderMunicipality {#3} +} + +\newcommand{\theSenderEMail }[2][] +{ + \def\@LetterSenderKey {#1} + \def\@LetterSenderEMail {#2} +} + +\newcommand{\theSenderName }[4][] +{ + \def\@LetterSenderTitle {#1} + \def\@LetterSenderFirstName {#2} + \def\@LetterSenderLastName {#3} + \def\@LetterSenderNickName {#4} +} + +\newcommand{\theSenderStreet }[3][] +{ + \def\@LetterSenderStreetExtra {#1} + \def\@LetterSenderStreet {#2} + \def\@LetterSenderStreetNumber {#3} +} +\makeatother diff --git a/NixTeX/dependencies/source/links.tex b/NixTeX/dependencies/source/links.tex new file mode 100644 index 0000000..c73d811 --- /dev/null +++ b/NixTeX/dependencies/source/links.tex @@ -0,0 +1,21 @@ +\def\thelastpage{\pageref{LastPage}} + +\newcommand{\Emaillink}[2]{\mbox{\href{mailto:#1}{#2}}} +\newcommand{\Httplink }[2]{\mbox{\href{http://#1}{#2}}} +\newcommand{\Httpslink}[2]{\mbox{\href{https://#1}{#2}}} + +\newcommand{\emaillink}[2][]{\mbox{\Emaillink{#2}{#1\nolinkurl{#2}}}} +\newcommand{\httplink }[2][]{\mbox{\Httplink {#2}{#1\nolinkurl{#2}}}} +\newcommand{\httpslink}[2][]{\mbox{\Httpslink{#2}{#1\nolinkurl{#2}}}} + +\newcommand{\nolink}[1]{\directlua{hazLink=false}#1\directlua{hazLink=true}} +\newcommand{\iflink}[2]{\directlua{ + if hazLink + then + tex.print([[#1]]) + else + tex.print([[#2]]) + end +}} + +\newcommand{\linkdest}[1]{\Hy@raisedlink{\hypertarget{#1}{}}} diff --git a/NixTeX/dependencies/source/logging.tex b/NixTeX/dependencies/source/logging.tex new file mode 100644 index 0000000..4060736 --- /dev/null +++ b/NixTeX/dependencies/source/logging.tex @@ -0,0 +1,33 @@ +\def\MessageBreak{\directlua{tex.print(newline)}}% + +\newcommand{\logHelp } [1] {\directlua { log.help ( [[#1]] ) }} +\newcommand{\logDebug } [2] {\directlua { log.debug ( [[#1]], [[#2]] ) }} +\newcommand{\logError } [2] {\directlua { log.error ( [[#1]], [[#2]] ) }} +\newcommand{\logFatal } [2] {\directlua { log.fatal ( [[#1]], [[#2]] ) }} +\newcommand{\logInfo } [2] {\directlua { log.info ( [[#1]], [[#2]] ) }} +\newcommand{\logTrace } [2] {\directlua { log.trace ( [[#1]], [[#2]] ) }} +\newcommand{\logWarn } [2] {} + +\def\logBreak {\directlua{log.stepping=true}} +\def\logUnbreak {\directlua{log.stepping=false}} + +\newcommand{\todo}[1]{\directlua{log.todo([[#1]])}\textbf{<{\color{red} ToDo: »#1«}>}} + +% Hook LaTeX Output +\let\oldMessage=\message +\let\@oldError=\errmessage + +\newcommand{\@HookInfo}[2]{\logInfo{#1}{#2. }} +\newcommand{\@HookWarn}[2]{\logWarn{#1}{#2. }} +\newcommand{\@HookError}[2]{\logError{#1}{#2. }\@oldError{}} + +\renewcommand{\@latex@warning }[1]{\logWarn {LaTeX} {#1. }} +\renewcommand{\message }[1]{\logInfo {LaTeX/message} {#1. }} +\renewcommand{\ClassInfo }[2]{\logInfo {Class #1} {#2. }} +\renewcommand{\ClassWarning }[2]{\logWarn {Class #1} {#2. }} +\renewcommand{\ClassError }[3]{\logError {Class #1} {#2. }} +\renewcommand{\PackageInfo }[2]{\logInfo {Package #1} {#2. }} +\renewcommand{\PackageWarning }[2]{\logWarn {Package #1} {#2. }} +\renewcommand{\PackageError }[3]{\logError {Package #1} {#2. }} +\renewcommand{\typeout }[1]{\logInfo {LaTeX/typeout} {#1. }} +\renewcommand{\wlog }[1]{\logTrace {LaTeX/wlog} {#1. }} diff --git a/NixTeX/dependencies/source/lua/bibliography/citation.lua b/NixTeX/dependencies/source/lua/bibliography/citation.lua new file mode 100644 index 0000000..b75a637 --- /dev/null +++ b/NixTeX/dependencies/source/lua/bibliography/citation.lua @@ -0,0 +1,68 @@ +citations += { + remembered = "", + } +function citations.load ( directory, list, auto ) + if directory + and directory ~= "" + then + directory = "references/" .. directory .. "/" + else + directory = "references/" + end + +-- local references = {} +-- if auto +-- then +-- for file in io.popen ( "ls '" .. directory .. "'"):lines() +-- do +-- if file:sub(-4) == ".bib" +-- then +-- print("»"..file:sub(1,-5).."«") +-- end +-- end +-- end + + for index, reference in ipairs ( list:split ( ) ) + do + reference = reference:gsub ( "%s+", "" ) + if reference ~= "" + then + local fileName = directory .. reference .. ".bib" + markFileAsUsed ( fileName ) + tex.print ( "\\addbibresource{" .. fileName .. "}" ) + end + end +end + +function citations.claim ( references, next ) + local short = next:gsub ( "%s", "" ) + if short == "," + or short == ";" + or short == "." + or short == ":" + or short == "?" + or short == "!" + then + tex.print(short.."\\citeHere{"..references.."} ") + else + tex.print("\\citeHere{"..references.."} "..next) + end +end + +function citations.remember ( citation ) + citations.remembered = citations.remembered .. "," .. citation +end + +function citations.clear ( other ) + local references = ( other or "" ) .. citations.remembered + if references ~= "" + then + if references:sub ( 1, 1 ) == "," + then + references = references:sub ( 2 ) + end + tex.print ( "\\makeatletter\\@citeInstant{" .. references .. "}\\makeatother" ) + end + citations.remembered = "" +end diff --git a/NixTeX/dependencies/source/lua/buildFiles.lua b/NixTeX/dependencies/source/lua/buildFiles.lua new file mode 100644 index 0000000..c38f5a0 --- /dev/null +++ b/NixTeX/dependencies/source/lua/buildFiles.lua @@ -0,0 +1,33 @@ +buildFiles += { + counter = 0, + } + +function buildFiles.create ( extension, part ) + local name = buildFiles.name ( extension, part ) + return io.open ( name, "w" ), name +end + +function buildFiles.modify ( extension, part ) + local name = buildFiles.name ( extension, part ) + return io.open ( name, "w+" ), name +end + +function buildFiles.name ( extension, part ) + part = tostring ( part or "" ) + if part ~= "" + then + part = "-" .. part + end + return buildDirectory .. jobname .. part .. "." .. extension +end + +function buildFiles.open ( extension, part ) + local name = buildFiles.name ( extension, part ) + return io.open ( name, "r" ), name +end + +function buildFiles.register ( ) + buildFiles.counter = buildFiles.counter + 1 + return tostring ( buildFiles.counter ) +end diff --git a/NixTeX/dependencies/source/lua/chemistry/chem.lua b/NixTeX/dependencies/source/lua/chemistry/chem.lua new file mode 100644 index 0000000..6967ff1 --- /dev/null +++ b/NixTeX/dependencies/source/lua/chemistry/chem.lua @@ -0,0 +1,747 @@ +--chLevel = 0 +chem = { } +includeCode ( "chemistry/spectra" ) +includeCode ( "chemistry/xray" ) + +local CouldBe += { + -- Default. + Default = 0x00, + -- After » « no sub/superscript shall follow. + Normal = 0x01, + -- After »)« a subscript value might follow. + SubScript = 0x02, + -- After »]« a superscript value might follow. + SuperScript = 0x03, + } + +local Special += { + [ "i" ] = "\\textit{i}", + [ "m" ] = "\\textit{m}", + [ "o" ] = "\\textit{o}", + [ "p" ] = "\\textit{p}", + } + +local Greek += { + [ "a" ] = "α", + [ "b" ] = "β", + [ "c" ] = "ψ", + [ "d" ] = "δ", + [ "e" ] = "ε", + [ "f" ] = "φ", + [ "g" ] = "γ", + [ "h" ] = "η", + [ "i" ] = "ι", + [ "j" ] = "ξ", + [ "k" ] = "κ", + [ "l" ] = "λ", + [ "m" ] = "μ", + [ "n" ] = "ν", + [ "o" ] = "ο", + [ "p" ] = "π", + [ "q" ] = "ϑ", + [ "r" ] = "ρ", + [ "s" ] = "σ", + [ "t" ] = "τ", + [ "u" ] = "θ", + [ "v" ] = "ω", + [ "w" ] = "ς", + [ "x" ] = "χ", + [ "y" ] = "ζ", + [ "z" ] = "υ", + } + +local Operators += { + [ "+" ] = { "~+~", " + ", "+" }, + [ "-" ] = { "-", "-", "−" }, + [ "*" ] = { "·", "·", "·" }, + } + +local PseudoAcronyms += { + [ "=" ] = { "", "⇌", }, + [ "-" ] = { "", "↔", }, + } + +local States += { + -- Default and Initial State. + Default = 0x00, + -- Starting with »_«. + SubScript = 0x01, + -- Starting with »_(«. + SubScriptGroup = 0x02, + -- Starting with a number immediately after a token. + SubScriptNumber = 0x03, + -- Starting with »^«. + SuperScript = 0x04, + -- Starting with »^(«. + SuperScriptGroup = 0x05, + -- Starting with »+« or »-« immediately after a token. + SuperScriptNumber = 0x06, + -- Starting with »[«: Put text as it is, without parsing. + Text = 0x07, + -- Replace »« with the short-form of »acronym«. + Acronym = 0x08, + Special = 0x09, + } + +States.Script = States.SubScript +States.ScriptGroup = States.SubScriptGroup +States.Ignore = States.Text + +local SubScripts += { + [ "0" ] = "₀", + [ "1" ] = "₁", + [ "2" ] = "₂", + [ "3" ] = "₃", + [ "4" ] = "₄", + [ "5" ] = "₅", + [ "6" ] = "₆", + [ "7" ] = "₇", + [ "8" ] = "₈", + [ "9" ] = "₉", + [ "a" ] = "ₐ", + [ "e" ] = "ₑ", + [ "h" ] = "ₕ", + [ "i" ] = "ᵢ", + [ "j" ] = "ⱼ", + [ "k" ] = "ₖ", + [ "l" ] = "ₗ", + [ "m" ] = "ₘ", + [ "n" ] = "ₙ", + [ "o" ] = "ₒ", + [ "p" ] = "ₚ", + [ "r" ] = "ᵣ", + [ "s" ] = "ₛ", + [ "t" ] = "ₜ", + [ "u" ] = "ᵤ", + [ "v" ] = "ᵥ", + [ "x" ] = "ₓ", + } + +local SuperScripts += { + [ "0" ] = "⁰", + [ "1" ] = "¹", + [ "2" ] = "²", + [ "3" ] = "³", + [ "4" ] = "⁴", + [ "5" ] = "⁵", + [ "6" ] = "⁶", + [ "7" ] = "⁷", + [ "8" ] = "⁸", + [ "9" ] = "⁹", + [ "+" ] = "⁺", + [ "−" ] = "⁻", + [ "a" ] = "ᵃ", + [ "b" ] = "ᵇ", + [ "c" ] = "ᶜ", + [ "d" ] = "ᵈ", + [ "e" ] = "ᵉ", + [ "f" ] = "ᶠ", + [ "g" ] = "ᵍ", + [ "h" ] = "ʰ", + [ "i" ] = "ⁱ", + [ "j" ] = "ʲ", + [ "k" ] = "ᵏ", + [ "l" ] = "ˡ", + [ "m" ] = "ᵐ", + [ "n" ] = "ⁿ", + [ "o" ] = "ᵒ", + [ "p" ] = "ᵖ", + [ "r" ] = "ʳ", + [ "s" ] = "ˢ", + [ "t" ] = "ᵗ", + [ "u" ] = "ᵘ", + [ "v" ] = "ᵛ", + [ "w" ] = "ʷ", + [ "x" ] = "ˣ", + [ "y" ] = "ʸ", + [ "z" ] = "ᶻ", + } + +local function subScriptChar ( char, state ) + local entry = SubScripts [ char ] + if entry + then + state.pdfString = state.pdfString .. entry + else + state.pdfString = state.pdfString .. "_" .. char + end + state.texString = state.texString .. "\\textsubscript{" .. char .. "}" + return state +end + +local function subScriptText ( char, state ) + local entry = SubScripts [ char ] + if entry + then + state.pdfString = state.pdfString .. entry + else + state.pdfString = state.pdfString .. char + end + state.temp = state.temp .. char + return state +end + +local function superScriptChar ( char, state ) + local entry = SubScripts [ char ] + if entry + then + state.pdfString = state.pdfString .. entry + else + state.pdfString = state.pdfString .. "^" .. char + end + state.texString = state.texString .. "\\textsuperscript{" .. char .. "}" + return state +end + +local function superScriptText ( char, state ) + local entry = SuperScripts [ char ] + if entry + then + state.pdfString = state.pdfString .. entry + else + state.pdfString = state.pdfString .. char + end + state.temp = state.temp .. char + return state +end + +-- Parse the Default state. +local function parseDefault ( char, state ) + if char >= "0" + and char <= "9" + then + if state.couldBe == CouldBe.Normal + then + state.texString = state.texString .. char + state.pdfString = state.pdfString .. char + state.kind = States.Default + else + state.temp = char + state.pdfString = state.pdfString .. SubScripts [ char ] + state.kind = States.SubScriptNumber + state.couldBe = CouldBe.Default + end + elseif char >= "A" + and char <= "Z" + then + state.texString = state.texString .. char + state.pdfString = state.pdfString .. char + state.kind = States.Default + state.couldBe = CouldBe.Default + elseif char >= "a" + and char <= "z" + then + if state.couldBe == CouldBe.Normal + then + state.texString = state.texString .. Greek [ char ] + state.pdfString = state.pdfString .. Greek [ char ] + state.kind = States.SuperScriptNumber + elseif state.couldBe == CouldBe.SubScript + then + state = subScriptChar ( char, state ) + elseif state.couldBe == CouldBe.SuperScript + then + state = superScriptChar ( char, state ) + else + state.texString = state.texString .. char + state.pdfString = state.pdfString .. char + state.kind = States.Default + end + state.couldBe = CouldBe.Default + elseif char == "+" + or char == "-" + or char == "*" + then + if state.couldBe == CouldBe.Normal + then + state.texString = state.texString .. Operators [ char ] [ 1 ] + state.pdfString = state.pdfString .. Operators [ char ] [ 2 ] + state.kind = States.Default + else + state.temp = Operators [ char ] [ 3 ] + state.pdfString = state.pdfString .. ( SuperScripts [ char ] or char ) + state.kind = States.SuperScriptNumber + end + state.couldBe = CouldBe.Default + elseif char == "." + then + state.texString = state.texString .. "•" + state.pdfString = state.pdfString .. "•" + state.kind = States.Default + state.couldBe = CouldBe.Normal + elseif char == "/" + then + if state.italic + then + state.texString = state.texString .. "}" + state.italic = false + else + state.texString = state.texString .. "\\textit{" + state.italic = true + end + elseif char == "(" + then + state.depth = state.depth + 1 + local index = state.maximum [ state.index ] + if state.depth == index + then + char = "(" + elseif state.depth == index - 1 + then + char = "[" + else + char = "\\{" + end + state.texString = state.texString .. char + state.pdfString = state.pdfString .. char + state.kind = States.Default + state.couldBe = CouldBe.Normal + elseif char == ")" + then + local index = state.maximum [ state.index ] + if state.depth == index + then + char = ")" + elseif state.depth == index - 1 + then + char = "]" + else + char = "\\}" + end + if state.depth == 0 + then + state.index = state.index + 1 + end + state.texString = state.texString .. char + state.pdfString = state.pdfString .. char + state.depth = state.depth - 1 + state.kind = States.Default + state.couldBe = CouldBe.SubScript + elseif char == "<" + then + state.temp = "" + state.kind = States.Acronym + state.couldBe = CouldBe.Default + elseif char == "_" + then + state.kind = States.SubScript + state.couldBe = CouldBe.Default + elseif char == "^" + then + state.kind = States.SuperScript + state.couldBe = CouldBe.SubScript + elseif char == "\"" + or char == "'" + then + state.temp = char + state.kind = States.Text + state.couldBe = CouldBe.Normal + elseif char == " " + then + if state.last == "," + then + state.texString = state.texString .. " " + state.pdfString = state.pdfString .. " " + end + state.kind = States.Default + state.couldBe = CouldBe.Normal + elseif char == "=" + or char == "," + then + state.texString = state.texString .. char + state.pdfString = state.pdfString .. char + state.kind = States.Default + state.couldBe = CouldBe.Normal + elseif char == "§" + then + state.texString = state.texString .. "$\\equiv$" + state.pdfString = state.pdfString .. "≡" + state.kind = States.Default + state.couldBe = CouldBe.Normal + elseif char == "@" + then + state.kind = States.Special + state.couldBe = CouldBe.Normal + else + log.fatal + ( + { "nextState", "Default", }, + "Unexpected Character: »" .. char .. "«" + ) + end + return state +end + +-- Go to next State. +local function nextState ( char, state ) + if state.kind == States.Default + -- (Default, SubScript, SubScriptNumber, SuperScript, SuperScriptNumber, Text, Acronym ) + then + state = parseDefault ( char, state ) + elseif state.kind == States.SubScript + -- (SubScriptGroup, Default) + then + if char == "(" + then + state.temp = "" + state.kind = States.SubScriptGroup + else + state = subScriptChar ( char, state ) + state.kind = States.Default + end + elseif state.kind == States.SubScriptGroup + -- (SubScriptGroup, Default) + then + if char == ")" + then + if state.count == 0 + then + state.texString = state.texString .. "\\textsubscript{" .. state.temp .. "}" + state.kind = States.Default + else + state.count = state.count - 1 + state.temp = state.temp .. ")" + state.pdfString = state.pdfString .. "₎" + end + elseif char == "(" + then + state.count = state.count + 1 + state.temp = state.temp .. "(" + state.pdfString = state.pdfString .. "₍" + else + state = subScriptText ( char, state ) + end + elseif state.kind == States.SubScriptNumber + -- (SubScriptNumber, Default) + then + if char >= "0" + and char <= "9" + then + state.temp = state.temp .. char + state.pdfString = state.pdfString .. SubScripts [ char ] + else + if state.temp ~= "" + then + state.texString = state.texString .. "\\textsubscript{" .. state.temp .. "}" + state.temp = "" + end + state = parseDefault ( char, state ) + end + elseif state.kind == States.SuperScript + -- (SuperScriptGroup, Default) + then + if char == "(" + then + state.temp = "" + state.kind = States.SuperScriptGroup + else + state = superScriptChar ( char, state ) + state.kind = States.Default + end + elseif state.kind == States.SuperScriptGroup + -- (SuperScriptGroup, Default) + then + if char == ")" + then + if state.count == 0 + then + state.texString = state.texString .. "\\textsuperscript{" .. state.temp .. "}" + state.kind = States.Default + else + state.count = state.count - 1 + state.temp = state.temp .. ")" + state.pdfString = state.pdfString .. "⁾" + end + elseif char == "(" + then + state.count = state.count + 1 + state.temp = state.temp .. "(" + state.pdfString = state.pdfString .. "⁽" + else + state = superScriptText ( char, state ) + end + elseif state.kind == States.SuperScriptNumber + -- (SuperScriptNumber, Default) + then + if char >= "0" + and char <= "9" + then + state.temp = state.temp .. char + state.pdfString = state.pdfString .. SuperScripts [ char ] + elseif char == "+" + and state.temp == "+" + then + state.temp = "{\\oplus}" + elseif char == "-" + and state.temp == "−" + then + state.temp = "{\\ominus}" + else + if state.temp ~= "" + then + state.texString = state.texString .. "\\textsuperscript{" .. state.temp .. "}" + state.temp = "" + end + state = parseDefault ( char, state ) + end + elseif state.kind == States.Text + -- (Text, Default) + then + if char == state.temp + then + state.kind = States.Default + else + state.texString = state.texString .. char + state.pdfString = state.pdfString .. char + end + elseif state.kind == States.Acronym + -- (Acronym, Default) + then + if char == ">" + then + local entry = PseudoAcronyms [ state.temp ] + if entry + then + state.texString = state.texString .. entry [ 1 ] + state.pdfString = state.pdfString .. entry [ 2 ] + else + local entry = acronyms.getEntry ( state.temp, state.lazy ) + if entry + then + state.texString = state.texString .. entry.short [ 1 ] + state.pdfString = state.pdfString .. entry.short [ 2 ] + elseif state.lazy + then + state.texString = state.texString .. "\\acrshort{" .. state.temp .. "}" + state.pdfString = state.pdfString .. "\\acrshort{" .. state.temp .. "}" + else + state.texString = state.texString .. "¿¿" .. state.temp .. "??" + state.pdfString = state.pdfString .. "¿¿" .. state.temp .. "??" + end + end + state.kind = States.Default + else + state.temp = state.temp .. char + end + elseif state.kind == States.Special + -- (Default) + then + state.texString = state.texString .. Special [ char ] + state.pdfString = state.texString .. Special [ char ] + state.kind = States.Default + else + log.fatal + ( + "nextState", + "Invalid State: " .. tostring ( state.kind ) + ) + end + state.last = char + return state +end + +-- Go to prepare state. +local function prepare ( char, state ) + if state.kind == States.Default + -- (Default, SubScript, SubScriptNumber, SuperScript, SuperScriptNumber, Text, Acronym ) + then + if ( char >= "0" and char <= "9" ) + or char == " " + or char == "+" + or char == "-" + or char == "*" + or char == "/" + or char == "." + or char == "=" + or char == "§" + or char == "," + or char == "@" + then + state.kind = States.Default + elseif ( char >= "A" and char <= "Z" ) + or ( char >= "a" and char <= "z" ) + then + state.sortBy = state.sortBy .. char + state.kind = States.Default + elseif char == "(" + then + state.sortBy = state.sortBy + state.depth = state.depth + 1 + state.kind = States.Default + elseif char == ")" + then + state.sortBy = state.sortBy + if state.depth > state.maximum [ #state.maximum ] + then + state.maximum [ #state.maximum ] + = state.depth + end + state.depth = state.depth - 1 + if state.depth == 0 + then + table.insert ( state.maximum, 0 ) + end + state.kind = States.Default + elseif char == "<" + then + state.temp = "" + state.kind = States.Acronym + elseif char == "_" + or char == "^" + then + state.kind = States.Script + elseif char == "\"" + or char == "'" + then + state.temp = char + state.kind = States.Ignore + else + log.fatal + ( + { "prepare", "Default", }, + "Unexpected Character: »" .. char .. "«" + ) + end + elseif state.kind == States.Script + -- (ScriptGroup, Default) + then + if char == "(" + then + state.kind = States.ScriptGroup + else + state.kind = States.Default + end + elseif state.kind == States.ScriptGroup + -- (ScriptGroup, Default) + then + if char == ")" + then + if state.count == 0 + then + state.kind = States.Default + else + state.count = state.count - 1 + end + elseif char == "(" + then + state.count = state.count + 1 + end + elseif state.kind == States.Acronym + -- (Acronym, Default) + then + if char == ">" + then + local entry = PseudoAcronyms [ state.temp ] + if entry + then + state.sortBy = state.sortBy .. entry [ 2 ] + else + local entry = acronyms.getEntry ( state.temp, true ) + if entry + then + state.sortBy + = state.sortBy + .. entry.short [ 2 ]:gsub ( "[0-9 +%-*/.=§,@()\128-\255]", "" ) + else + state.sortBy = state.sortBy .. "<" .. state.temp .. ">" + end + end + state.kind = States.Default + else + state.temp = state.temp .. char + end + elseif state.kind == States.Ignore + -- (Ignore, Default) + then + if char == state.temp + then + state.kind = States.Default + else + state.sortBy = state.sortBy .. char + end + else + log.fatal + ( + "prepare", + "Invalid State: " .. tostring ( state.kind ) + ) + end + return state +end + +-- Frontend +function chem.parseSimple ( formula, lazy ) + log.debug("chem.parseSimple", "parse: »" .. formula .. "«") + local state + = { + kind = States.Default, + temp = "", + maximum = { 0 }, + depth = 0, + count = 0, + sortBy = "", + } + for char in formula:utf8split ( ) + do + state = prepare ( char, state ) + end + local state + = { + kind = States.Default, + temp = "", + couldBe = CouldBe.Normal, + maximum = state.maximum, + index = 1, + depth = 0, + count = 0, + italic = false, + texString = "", + pdfString = "", + sortBy = state.sortBy, + lazy = lazy, + last = "", + } + for char in formula:utf8split ( ) + do + --log.debug("nextState", "state: »" .. tostring ( state.kind ) .. "«, char: "..char) + state = nextState ( char, state ) + end + if state.italic + then + state.texString = state.texString .. "}" + state.italic = false + end + if state.kind == States.Default + then + -- just fine + elseif state.kind == States.SubScriptNumber + then + state.texString = state.texString .. "\\textsubscript{" .. state.temp .. "}" + elseif state.kind == States.SuperScriptNumber + then + state.texString = state.texString .. "\\textsuperscript{" .. state.temp .. "}" + else + log.fatal + ( + "chem.parseSimple", + "Invalid Final Parser State: " .. tostring ( state.kind ) + ) + end + --log.debug("chem.parseSimple", "got »"..state.texString.."«|»"..state.pdfString.."«") + return "\\mbox{"..state.texString.."}", + state.pdfString, + state.sortBy.."\a"..state.pdfString +end + +function chem.printSimple ( formula ) + local texString, pdfString = chem.parseSimple ( formula ) + tex.print ( "\\texorpdfstring{{" .. texString .. "}}{{" .. pdfString .. "}}" ) +end diff --git a/NixTeX/dependencies/source/lua/chemistry/compounds.lua b/NixTeX/dependencies/source/lua/chemistry/compounds.lua new file mode 100644 index 0000000..5dc96e0 --- /dev/null +++ b/NixTeX/dependencies/source/lua/chemistry/compounds.lua @@ -0,0 +1,506 @@ +chem.compounds = {} + +--- +chem.compounds.knownWords += {} + +--- Common Errors, that shall be detected and a warning should be emitted. +--- All entries are lower case. +chem.compounds.knownErrors += { + [ "etyl" ] = "ethyl", + [ "metyl" ] = "methyl", + [ "penyl" ] = "phenyl", + } + +--- Parts of compounds with an entry in the list of acronyms. +--- All entries are lower case. +chem.compounds.knownAcronyms += { + [ "acetyl" ] = "acetyl", + [ "bithiophen" ] = "bithiophene", + [ "dibenzylideneaceton" ] = "dibenzylideneacetone", + [ "ethyl" ] = "ethyl", + [ "cyclopentadienyl" ] = "cyclopentadienyl", + [ "ferrocen" ] = "ferrocenyl", + [ "ferrocenyl" ] = "ferrocenyl", + [ "isopropyl" ] = "isoPropyl", + [ "mesyl" ] = "mesyl", + [ "mesylat" ] = "mesyl", + [ "tosyl" ] = "tosyl", + [ "tosylat" ] = "tosyl", + [ "triflyl" ] = "triflyl", + [ "triflat" ] = "triflyl", + [ "methyl" ] = "methyl", + [ "phenyl" ] = "phenyl", + } + +--- Known Prefixes (…- or -…-) that should be formated. +--- All entries are case-sensitive. +chem.compounds.knownPrefixes += { + [ "(+)" ] = { "(\\plus)", "(+)", }, + [ "(-)" ] = { "(\\minus)", "(−)", }, + [ "(D)" ] = { "\\textsc{D}", "ᴅ", }, + [ "(E)" ] = { "(\\textit{E})", "(𝘌)", }, + [ "(L)" ] = { "\\textsc{L}", "ʟ", }, + [ "(M)" ] = { "(\\textit{M})", "(𝘔)", }, + [ "(P)" ] = { "(\\textit{P})", "(𝘗)", }, + [ "(R)" ] = { "(\\textit{R})", "(𝘙)", }, + [ "(S)" ] = { "(\\textit{S})", "(𝘚)", }, + [ "(Z)" ] = { "(\\textit{Z})", "(𝘡)", }, + [ "a" ] = { "α", "α", }, + [ "alt" ] = { "\\textit{alt}", "𝘢𝘭𝘵", }, + [ "b" ] = { "β", "β", }, + [ "cis" ] = { "\\textit{cis}", "𝘤𝘪𝘴", }, + [ "d" ] = { "δ", "δ", }, + [ "e" ] = { "ε", "ε", }, + [ "fac" ] = { "\\textit{fac}", "𝘧𝘢𝘤", }, + [ "g" ] = { "γ", "γ", }, + [ "h" ] = { "η", "η", "super"}, + [ "i" ] = { "\\textit{i}", "𝘪", }, + [ "iso" ] = { "\\textit{iso}", "𝘪𝘴𝘰", }, + [ "ipso" ] = { "\\textit{ipso}", "𝘪𝘱𝘴𝘰", }, + [ "k" ] = { "κ", "κ", "super"}, + [ "l" ] = { "λ", "λ", }, + [ "m" ] = { "\\textit{m}", "𝘮", }, + [ "mer" ] = { "\\textit{mer}", "𝘮𝘦𝘳", }, + [ "meso" ] = { "\\textit{meso}", "𝘮𝘦𝘴𝘰", }, + [ "mu" ] = { "µ", "μ", "sub"}, + [ "n" ] = { "\\textit{n}", "𝘯", }, + [ "neo" ] = { "\\textit{neo}", "𝘯𝘦𝘰", }, + [ "o" ] = { "\\textit{o}", "𝘰", }, + [ "p" ] = { "\\textit{p}", "𝘱", }, + [ "sec" ] = { "\\textit{sec}", "𝘴𝘦𝘤", }, + [ "tert" ] = { "\\textit{tert}", "𝘵𝘦𝘳𝘵", }, + [ "trans" ] = { "\\textit{trans}", "𝘵𝘳𝘢𝘯𝘴", }, + [ "w" ] = { "ω", "ω", }, + } + +for index, element in ipairs({ + "H", "D", "T", "He", + "Li", "Be", "B", "C", "N", "O", "F", "Ne", + "Na", "Mg", "Al", "Si", "P", "S", "Cl", "Ar", + "K", "Ca", "Sc", "Ti", "V", "Cr", "Mn", "Fe", "Co", "Ni", "Cu", "Zn", "Ga", "Ge", "As", "Se", "Br", "Kr", + "Rb", "Sr", "Y", "Zr", "Nb", "Mo", "Tc", "Ru", "Rh", "Pd", "Ag", "Cd", "In", "Sn", "Sb", "Te", "I", "Xe", + "Cs", "Ba", "La", "Hf", "Ta", "W", "Re", "Os", "Ir", "Pt", "Au", "Hg", "Tl", "Pb", "Bi", "Po", "At", "Rn" +}) +do + chem.compounds.knownPrefixes[element] = { "\\textit{"..element.."}", element } +end + +chem.compounds.someOptionals += { + [ "gruppe" ] = "Group", + } + +local function parsePrefixes ( prefixes, detailed, replaceOptionals ) + local texStringOuter = "" + local pdfStringOuter = "" + + -- iterate over prefixes »a-b-c-« + for prefix in prefixes:gmatch ( "([^-]*)-" ) + do + log.debug("parsePrefixes", "outer: "..prefix) + local preprefix = "" + if prefix:sub ( 1, 2 ) == "§" + then + prefix = prefix:sub ( 3 ) + if detailed + then + preprefix = "}" + detailed = false + else + preprefix = "\\detailed{" + detailed = true + end + end + local suffix = "" + if prefix:sub ( -2 ) == "§" + then + prefix = prefix:sub ( 1, -3 ) + if detailed + then + suffix = "}" + detailed = false + else + suffix = "\\detailed{" + detailed = true + end + end + + local texStringInner = "" + local pdfStringInner = "" + for prefix in prefix:gmatch ( "([^,]*)" ) + do + log.debug("parsePrefixes", "inner: "..prefix) + local realPrefix, primes = prefix:match ( "([^']+)([']+)" ) + if primes + then + local length = #primes + primes = ( "⁗" ):rep ( math.floor ( length / 4 ) ) + length = length % 4 + primes = primes .. ( "‴" ):rep ( math.floor ( length / 3 ) ) + length = length % 3 + primes = primes .. ( "″" ):rep ( math.floor ( length / 2 ) ) + length = length % 2 + primes = primes .. ( "′" ):rep ( length ) + else + primes = "" + end + + local texPrefix = "" + local pdfPrefix = "" + realPrefix = realPrefix or prefix + local head, foot = realPrefix:match ( "([^|]+)|([^|]+)" ) + if foot + then + texPrefix = head + pdfPrefix = head + realPrefix = foot + end + + local position, atom = realPrefix:match ( "^(%d*)([A-Z][a-z]?)$" ) + if position + then + if atom == "E" or atom == "Z" + then + pdfPrefix = pdfPrefix .. "(" .. position .. atom .. ")" + texPrefix = texPrefix .. "\\textit{(" .. position .. atom .. ")}" + else + pdfPrefix = pdfPrefix .. position .. atom + texPrefix = texPrefix .. position .. "\\textit{" .. atom .. "}" + end + else + local acronym = chem.compounds.knownAcronyms [ realPrefix:lower ( ) ] + if acronym + then + if acronyms.list [ acronym ] + then + log.info + ( + "parsePrefixes", + "Acronym: »"..tostring(acronym).."«", + "Foot: »"..tostring(realPrefix).."«" + ) + texPrefix = texPrefix .. acronyms.getLink ( acronym, realPrefix ) + else + texPrefix = texPrefix .. acronyms.getLinkUnchecked ( acronym, realPrefix ) + acronyms.mind [ acronym ] = true + end + elseif chem.compounds.knownErrors [ realPrefix:lower ( ) ] + then + texPrefix = texPrefix .. realPrefix + log.error + ( + "parsePrefixes", + "Found known error »" .. realPrefix:lower ( ) .. "«, did you mean »" + .. compounds.knownErrors [ realPrefix:lower ( ) ] .. "«?" + ) + else + local first = true + for realPrefix in realPrefix:gmatch ( "([^:]*)" ) + do + if not first + then + texPrefix = texPrefix .. ":" + pdfPrefix = pdfPrefix .. ":" + end + first = false + local prefix, number = realPrefix:match ( "^(.+)([0-9]+)$" ) + local replace = nil + if number + then + replace = chem.compounds.knownPrefixes [ prefix ] + else + replace = chem.compounds.knownPrefixes [ realPrefix ] + end + if replace + then + if number + then + texPrefix = texPrefix .. replace [ 1 ] .. "\\text" .. replace [ 3 ] .. "script{" .. number .. "}" + pdfPrefix = pdfPrefix .. replace [ 2 ] .. number + else + texPrefix = texPrefix .. replace [ 1 ] + pdfPrefix = pdfPrefix .. replace [ 2 ] + end + else + texPrefix = texPrefix .. realPrefix + pdfPrefix = pdfPrefix .. realPrefix + end + end + end + end + + texStringInner = texStringInner .. "," .. texPrefix .. primes + pdfStringInner = pdfStringInner .. "," .. pdfPrefix .. primes + end + texStringOuter = texStringOuter .. preprefix .. texStringInner:sub ( 2 ) .. suffix .. "-" + --texStringOuter = texStringOuter .. preprefix .. texStringInner:sub ( 2 ) .. suffix .. "-\\penalty0\\hskip0pt\\relax{}" + pdfStringOuter = pdfStringOuter .. pdfStringInner:sub ( 2 ) .. "-" + end + + return texStringOuter, pdfStringOuter, detailed +end + +function splitString(input, delimiter) + print(input) + print(delimiter) + log.debug("string:split", "Input: »"..input.."« ("..delimiter..")") + local result = { } + local from = 1 + local delim_from, delim_to = string.find( input, delimiter, from ) + while delim_from do + local substring = string.sub( input, from , delim_from-1 ) + log.trace("string:split", "Add: »"..substring.."«") + table.insert( result, substring ) + from = delim_to + 1 + delim_from, delim_to = string.find( input, delimiter, from ) + end + local substring = string.sub( input, from ) + log.trace("string:split", "Add': »"..substring.."«") + table.insert( result, substring ) + return result +end + +function chem.compounds.parse ( name, replaceOptionals ) + log.debug("chem.compounds.parse", "Input: »"..name.."«") + local texStringOuter = { } + local pdfStringOuter = { } + local name + = name + :gsub ( "([({])", "|%1|" ) + :gsub ( "([})])", "|%1||" ) + :gsub ( "([%[])", "|[" ) + :gsub ( "([%]])", "]||" ) + :gsub ( "([|][|][-])", "|-" ) + local detailed = false + + for index,part in ipairs(splitString(name, "[|][|]")) + do + log.trace("chem.compounds.parse", "part: »"..part.."«") + local texStringInner = { } + local pdfStringInner = { } + for index, component in ipairs(splitString(part, "[|]")) + do + local attribute = component:match ( "^%[(.-)%]$" ) + if attribute + then + log.trace("chem.compounds.parse", "attribute: »"..attribute.."«") + local texAttribute = "" + local pdfAttribute = "" + local letter = "" + local primes = 0 + for character in attribute:utf8split ( ) + do + if character == "'" + then + if letter ~= "" + then + texAttribute = texAttribute .. "\\textit{" .. letter .. "}" + letter = "" + end + primes = primes + 1 + else + if primes > 0 + then + local aux = "" + aux = ( "⁗" ):rep ( math.floor ( primes / 4 ) ) + primes = primes % 4 + aux = aux .. ( "‴" ):rep ( math.floor ( primes / 3 ) ) + primes = primes % 3 + aux = aux .. ( "″" ):rep ( math.floor ( primes / 2 ) ) + primes = primes % 2 + aux = aux .. ( "′" ):rep ( primes ) + primes = 0 + texAttribute = texAttribute .. aux + pdfAttribute = pdfAttribute .. aux + end + if ( character >= "A" and character <= "Z" ) + or ( character >= "a" and character <= "z" ) + then + letter = letter .. character + pdfAttribute = pdfAttribute .. character + else + if letter ~= "" + then + texAttribute = texAttribute .. "\\textit{" .. letter .. "}" + letter = "" + end + texAttribute = texAttribute .. character + pdfAttribute = pdfAttribute .. character + end + end + end + if primes > 0 + then + local aux = "" + aux = ( "⁗" ):rep ( math.floor ( primes / 4 ) ) + primes = primes % 4 + aux = aux .. ( "‴" ):rep ( math.floor ( primes / 3 ) ) + primes = primes % 3 + aux = aux .. ( "″" ):rep ( math.floor ( primes / 2 ) ) + primes = primes % 2 + aux = aux .. ( "′" ):rep ( primes ) + primes = 0 + texAttribute = texAttribute .. aux + pdfAttribute = pdfAttribute .. aux + elseif letter ~= "" + then + texAttribute = texAttribute .. "\\textit{" .. letter .. "}" + letter = "" + end + + table.insert + ( + texStringInner, + "[" .. texAttribute .. "]" + ) + + table.insert + ( + pdfStringInner, + "[" .. pdfAttribute .. "]" + ) + else + local texPrefixes = "" + local pdfPrefixes = "" + local prefixes, rest = component:match ( "^(.+-)([^-]*)$" ) + if rest + then + log.trace("chem.compounds.parse", "prefixes: »"..prefixes.."«", "rest: »"..rest.."«") + component = rest + texPrefixes, pdfPrefixes, detailed + = parsePrefixes ( prefixes, detailed, replaceOptionals ) + end + + log.trace("chem.compounds.parse", "component before: »"..component.."«") + if component:sub ( 1, 2 ) == "§" + then + component = component:sub ( 3 ) + if detailed + then + texPrefixes = texPrefixes .. "}" + detailed = false + else + texPrefixes = texPrefixes .. "\\detailed{" + detailed = true + end + end + local texSuffix = "" + if component:sub ( -2 ) == "§" + then + component = component:sub ( 1, -3 ) + if detailed + then + texSuffix = "}" + detailed = false + else + texSuffix = "\\detailed{" + detailed = true + end + end + log.trace("chem.compounds.parse", "component after: »"..component.."«") + + local texComponent = component + local pdfComponent = component + local component = component:lower ( ) + local acronym = chem.compounds.knownAcronyms [ component ] + if acronym + then + if acronyms.list [ acronym ] + then + texComponent = acronyms.getLink ( acronym, pdfComponent ) + else + texComponent = acronyms.getLinkUnchecked ( acronym, pdfComponent ) + acronyms.mind [ acronym ] = true + end + elseif chem.compounds.knownErrors [ component ] + then + log.error + ( + "printCompound", + "Found known error »" .. pdfComponent .. "«, did you mean »" .. compounds.knownErrors [ component ] .. "«?" + ) + elseif true + and replaceOptionals + and chem.compounds.someOptionals [ component ] + then + texComponent + = "\\AcrOptional{" + .. chem.compounds.someOptionals [ component ] + .. "}" + pdfComponent = texComponent + elseif true + then + local element = chem.elements.lookUp.deu [ component ] + if element + then + texComponent = chem.elements.linkToPSE ( element, pdfComponent ) + end + end + log.trace("chem.compounds.parse", "Insert Inner TEX »"..texPrefixes.."«..»"..texComponent.."«..»"..texSuffix.."«") + table.insert + ( + texStringInner, + texPrefixes .. texComponent .. texSuffix + ) + + log.trace("chem.compounds.parse", "Insert Inner PDF »"..pdfPrefixes.."«..»"..pdfComponent.."«") + table.insert + ( + pdfStringInner, + pdfPrefixes .. pdfComponent + ) + end + end + + table.insert + ( + texStringOuter, + table.concat ( texStringInner ) + ) + + table.insert + ( + pdfStringOuter, + table.concat ( pdfStringInner ) + ) + end + + local texString = table.concat ( texStringOuter, "\\-" ) + local pdfString = table.concat ( pdfStringOuter ) + if texString == "" + or pdfString == "" + then + log.error("chem.compounds.print", "Empty String!") + else + log.debug + ( + "chem.compounds.print", + "texOutput: »" .. texString .. "«", + "pdfOutput: »" .. pdfString .. "«" + ) + end + if detailed + then + log.fatal + ( + "chem.compounds.parse", + "Uneven number of §", + texString + ) + end + return texString, pdfString +end + +function chem.compounds.print ( name, replaceOptionals ) + local texString, pdfString = chem.compounds.parse ( name, replaceOptionals ) + log.warn("chem.compounds.print", texString) + tex.print ( "\\relax\\texorpdfstring{" .. texString .. "}{" .. pdfString .. "}" ) +end + +function chem.compounds.texPrint ( name ) + chem.compounds.print ( name ) +end diff --git a/NixTeX/dependencies/source/lua/chemistry/elements.lua b/NixTeX/dependencies/source/lua/chemistry/elements.lua new file mode 100644 index 0000000..200d8fe --- /dev/null +++ b/NixTeX/dependencies/source/lua/chemistry/elements.lua @@ -0,0 +1,294 @@ +chem.elements += { + enableLinks = false, + classes + = { + AlkaliMetal = 1, + AlkaliEarthMetal = 2, + TransitionMetal = 3, + Metal = 4, + Lanthanoids = 5, + Actinoids = 6, + Metalloid = 7, + NonMetal = 8, + NobleGas = 9, + }, + states + = { + Solid = 1, + Liquid = 2, + Gas = 3, + Unknown = 4, + }, + lookUp + = { + deu = { }, + eng = { }, + }, + pse = { }, + } + +local elements += { +-- Symbol = Number, Mass, Name, Electronegativity, State, Radioactivity, Class + [ "H" ] = { 1, 1.0079, { deu = "Wasserstoff", eng = "Hydrogen", }, 2.2, chem.elements.states.Gas, false, chem.elements.classes.NonMetal, }, + [ "He" ] = { 2, 4.0026, { deu = "Helium", eng = "Helium", }, 0, chem.elements.states.Gas, false, chem.elements.classes.NobleGas, }, + + [ "Li" ] = { 3, 6.9675, { deu = "Lithium", eng = "Lithium", }, 0.98, chem.elements.states.Solid, false, chem.elements.classes.AlkaliMetal, }, + [ "Be" ] = { 4, 9.0122, { deu = "Beryllium", eng = "Beryllium", }, 1.57, chem.elements.states.Solid, false, chem.elements.classes.AlkaliEarthMetal, }, + [ "B" ] = { 5, 10.813, { deu = "Bor", eng = "Boron", }, 2.04, chem.elements.states.Solid, false, chem.elements.classes.Metalloid, }, + [ "C" ] = { 6, 12.011, { deu = "Kohlenstoff", eng = "Carbon", }, 2.55, chem.elements.states.Solid, false, chem.elements.classes.NonMetal, }, + [ "N" ] = { 7, 14.007, { deu = "Stickstoff", eng = "Nitrogen", }, 3.04, chem.elements.states.Gas, false, chem.elements.classes.NonMetal, }, + [ "O" ] = { 8, 15.999, { deu = "Sauerstoff", eng = "Oxygen", }, 3.44, chem.elements.states.Gas, false, chem.elements.classes.NonMetal, }, + [ "F" ] = { 9, 18.998, { deu = "Fluor", eng = "Fluorine", }, 3.98, chem.elements.states.Gas, false, chem.elements.classes.NonMetal, }, + [ "Ne" ] = { 10, 20.180, { deu = "Neon", eng = "Neon", }, 0, chem.elements.states.Gas, false, chem.elements.classes.NobleGas, }, + + [ "Na" ] = { 11, 22.990, { deu = "Natrium", eng = "Sodium", }, 0.93, chem.elements.states.Solid, false, chem.elements.classes.AlkaliMetal, }, + [ "Mg" ] = { 12, 24.305, { deu = "Magnesium", eng = "Magnesium", }, 1.31, chem.elements.states.Solid, false, chem.elements.classes.AlkaliEarthMetal, }, + [ "Al" ] = { 13, 26.981, { deu = "Aluminium", eng = "Aluminium", }, 1.61, chem.elements.states.Solid, false, chem.elements.classes.Metal, }, + [ "Si" ] = { 14, 28.085, { deu = "Silicium", eng = "Silicon", }, 1.9, chem.elements.states.Solid, false, chem.elements.classes.Metalloid, }, + [ "P" ] = { 15, 30.974, { deu = "Phosphor", eng = "Phosphorus", }, 2.19, chem.elements.states.Solid, false, chem.elements.classes.NonMetal, }, + [ "S" ] = { 16, 32.067, { deu = "Schwefel", eng = "Sulfur", }, 2.58, chem.elements.states.Solid, false, chem.elements.classes.NonMetal, }, + [ "Cl" ] = { 17, 35.451, { deu = "Chlor", eng = "Chlorine", }, 3.16, chem.elements.states.Gas, false, chem.elements.classes.NonMetal, }, + [ "Ar" ] = { 18, 39.948, { deu = "Argon", eng = "Argon", }, 0.82, chem.elements.states.Gas, false, chem.elements.classes.NobleGas, }, + + [ "K" ] = { 19, 39.098, { deu = "Kalium", eng = "Potassium", }, 0.82, chem.elements.states.Solid, false, chem.elements.classes.AlkaliMetal, }, + [ "Ca" ] = { 20, 40.078, { deu = "Calcium", eng = "Calcium", }, 1.0, chem.elements.states.Solid, false, chem.elements.classes.AlkaliEarthMetal, }, + [ "Sc" ] = { 21, 44.956, { deu = "Scandium", eng = "Scandium", }, 1.36, chem.elements.states.Solid, false, chem.elements.classes.TransitionMetal, }, + [ "Ti" ] = { 22, 47.867, { deu = "Titan", eng = "Titanium", }, 1.54, chem.elements.states.Solid, false, chem.elements.classes.TransitionMetal, }, + [ "V" ] = { 23, 50.941, { deu = "Vanadium", eng = "Vanadium", }, 1.63, chem.elements.states.Solid, false, chem.elements.classes.TransitionMetal, }, + [ "Cr" ] = { 24, 51.996, { deu = "Chrom", eng = "Chromium", }, 1.66, chem.elements.states.Solid, false, chem.elements.classes.TransitionMetal, }, + [ "Mn" ] = { 25, 54.938, { deu = "Mangan", eng = "Manganese", }, 1.55, chem.elements.states.Solid, false, chem.elements.classes.TransitionMetal, }, + [ "Fe" ] = { 26, 55.845, { deu = "Eisen", eng = "Iron", }, 1.83, chem.elements.states.Solid, false, chem.elements.classes.TransitionMetal, }, + [ "Co" ] = { 27, 58.933, { deu = "Cobalt", eng = "Cobalt", }, 1.91, chem.elements.states.Solid, false, chem.elements.classes.TransitionMetal, }, + [ "Ni" ] = { 28, 58.693, { deu = "Nickel", eng = "Nickel", }, 1.88, chem.elements.states.Solid, false, chem.elements.classes.TransitionMetal, }, + [ "Cu" ] = { 29, 63.546, { deu = "Kupfer", eng = "Copper", }, 1.9, chem.elements.states.Solid, false, chem.elements.classes.TransitionMetal, }, + [ "Zn" ] = { 30, 65.380, { deu = "Zink", eng = "Zinc", }, 1.65, chem.elements.states.Solid, false, chem.elements.classes.TransitionMetal, }, + [ "Ga" ] = { 31, 69.723, { deu = "Gallium", eng = "Gallium", }, 1.81, chem.elements.states.Solid, false, chem.elements.classes.Metal, }, + [ "Ge" ] = { 32, 72.631, { deu = "Germanium", eng = "Germanium", }, 2.01, chem.elements.states.Solid, false, chem.elements.classes.Metalloid, }, + [ "As" ] = { 33, 74.922, { deu = "Arsen", eng = "Arsenic", }, 2.18, chem.elements.states.Solid, false, chem.elements.classes.Metalloid, }, + [ "Se" ] = { 34, 78.972, { deu = "Selen", eng = "Selenium", }, 2.55, chem.elements.states.Solid, false, chem.elements.classes.NonMetal, }, + [ "Br" ] = { 35, 79.904, { deu = "Brom", eng = "Bromine", }, 2.96, chem.elements.states.Liquid, false, chem.elements.classes.NonMetal, }, + [ "Kr" ] = { 36, 83.798, { deu = "Krypton", eng = "Krypton", }, 0, chem.elements.states.Gas, false, chem.elements.classes.NobleGas, }, + + [ "Rb" ] = { 37, 85.468, { deu = "Rubidium", eng = "Rubidium", }, 0.82, chem.elements.states.Solid, false, chem.elements.classes.AlkaliMetal, }, + [ "Sr" ] = { 38, 87.620, { deu = "Strontnium", eng = "Strontnium", }, 0.95, chem.elements.states.Solid, false, chem.elements.classes.AlkaliEarthMetal, }, + [ "Y" ] = { 39, 88.906, { deu = "Yttrium", eng = "Yttrium", }, 1.22, chem.elements.states.Solid, false, chem.elements.classes.TransitionMetal, }, + [ "Zr" ] = { 40, 91.224, { deu = "Zirconium", eng = "Zirconium", }, 1.33, chem.elements.states.Solid, false, chem.elements.classes.TransitionMetal, }, + [ "Nb" ] = { 41, 92.906, { deu = "Niob", eng = "Niobium", }, 1.6, chem.elements.states.Solid, false, chem.elements.classes.TransitionMetal, }, + [ "Mo" ] = { 42, 95.95, { deu = "Molybdän", eng = "Molybdenum", }, 2.16, chem.elements.states.Solid, false, chem.elements.classes.TransitionMetal, }, + [ "Tc" ] = { 43, 97, { deu = "Technetium", eng = "Technetium", }, 1.9, chem.elements.states.Solid, true, chem.elements.classes.TransitionMetal, }, + [ "Ru" ] = { 44, 101.07, { deu = "Ruthenium", eng = "Ruthenium", }, 2.2, chem.elements.states.Solid, false, chem.elements.classes.TransitionMetal, }, + [ "Rh" ] = { 45, 102.905, { deu = "Rhodium", eng = "Rhodium", }, 2.28, chem.elements.states.Solid, false, chem.elements.classes.TransitionMetal, }, + [ "Pd" ] = { 46, 106.42, { deu = "Palladium", eng = "Palladium", }, 2.2, chem.elements.states.Solid, false, chem.elements.classes.TransitionMetal, }, + [ "Ag" ] = { 47, 107.686, { deu = "Silber", eng = "Silver", }, 1.93, chem.elements.states.Solid, false, chem.elements.classes.TransitionMetal, }, + [ "Cd" ] = { 48, 112.414, { deu = "Cadmium", eng = "Cadmium", }, 1.69, chem.elements.states.Solid, false, chem.elements.classes.TransitionMetal, }, + [ "In" ] = { 49, 114.818, { deu = "Indium", eng = "Indium", }, 1.78, chem.elements.states.Solid, false, chem.elements.classes.Metal, }, + [ "Sn" ] = { 50, 118.711, { deu = "Zinn", eng = "Tin", }, 1.96, chem.elements.states.Solid, false, chem.elements.classes.Metal, }, + [ "Sb" ] = { 51, 121.760, { deu = "Antimon", eng = "Antimony", }, 2.05, chem.elements.states.Solid, false, chem.elements.classes.Metalloid, }, + [ "Te" ] = { 52, 127.60, { deu = "Tellur", eng = "Tellurium", }, 2.66, chem.elements.states.Solid, false, chem.elements.classes.Metalloid, }, + [ "I" ] = { 53, 126.904, { deu = "Iod", eng = "Iodine", }, 2.1, chem.elements.states.Solid, false, chem.elements.classes.NonMetal, }, + [ "Xe" ] = { 54, 131.294, { deu = "Xenon", eng = "Xenon", }, 2.6, chem.elements.states.Gas, false, chem.elements.classes.NobleGas, }, + + [ "Cs" ] = { 55, 132.906, { deu = "Caesium", eng = "Caesium", }, 0.79, chem.elements.states.Solid, false, chem.elements.classes.AlkaliMetal, }, + [ "Ba" ] = { 56, 137.328, { deu = "Barium", eng = "Barium", }, 0.89, chem.elements.states.Solid, false, chem.elements.classes.AlkaliEarthMetal, }, + [ "La" ] = { 57, 138.906, { deu = "Lanthan", eng = "Lanthanum", }, 1.1, chem.elements.states.Solid, false, chem.elements.classes.Lanthanoids, }, + [ "Ce" ] = { 58, 140.116, { deu = "Cer", eng = "Cerium", }, 1.12, chem.elements.states.Solid, false, chem.elements.classes.Lanthanoids, }, + [ "Pr" ] = { 59, 140.908, { deu = "Praseodym", eng = "Praseodymium", }, 1.13, chem.elements.states.Solid, false, chem.elements.classes.Lanthanoids, }, + [ "Nd" ] = { 60, 144.242, { deu = "Neodym", eng = "Neodymium", }, 1.14, chem.elements.states.Solid, false, chem.elements.classes.Lanthanoids, }, + [ "Pm" ] = { 61, 145, { deu = "Promethium", eng = "Promethium", }, 1.13, chem.elements.states.Solid, true, chem.elements.classes.Lanthanoids, }, + [ "Sm" ] = { 62, 150.360, { deu = "Samarium", eng = "Samarium", }, 1.17, chem.elements.states.Solid, false, chem.elements.classes.Lanthanoids, }, + [ "Eu" ] = { 63, 151.964, { deu = "Europium", eng = "Europium", }, 1.2, chem.elements.states.Solid, false, chem.elements.classes.Lanthanoids, }, + [ "Gd" ] = { 64, 157.25, { deu = "Gadolinium", eng = "Gadolinium", }, 1.2, chem.elements.states.Solid, false, chem.elements.classes.Lanthanoids, }, + [ "Tb" ] = { 65, 158.925, { deu = "Terbium", eng = "Terbium", }, 1.1, chem.elements.states.Solid, false, chem.elements.classes.Lanthanoids, }, + [ "Dy" ] = { 66, 162.500, { deu = "Dysprosium", eng = "Dysprosium", }, 1.22, chem.elements.states.Solid, false, chem.elements.classes.Lanthanoids, }, + [ "Ho" ] = { 67, 164.930, { deu = "Holmium", eng = "Holmium", }, 1.23, chem.elements.states.Solid, false, chem.elements.classes.Lanthanoids, }, + [ "Er" ] = { 68, 167.259, { deu = "Erbium", eng = "Erbium", }, 1.24, chem.elements.states.Solid, false, chem.elements.classes.Lanthanoids, }, + [ "Tm" ] = { 69, 168.934, { deu = "Thulium", eng = "Thulium", }, 1.25, chem.elements.states.Solid, false, chem.elements.classes.Lanthanoids, }, + [ "Yb" ] = { 70, 173.045, { deu = "Ytterbium", eng = "Ytterbium", }, 1.1, chem.elements.states.Solid, false, chem.elements.classes.Lanthanoids, }, + [ "Lu" ] = { 71, 174.967, { deu = "Lutetium", eng = "Lutetium", }, 1.27, chem.elements.states.Solid, false, chem.elements.classes.Lanthanoids, }, + [ "Hf" ] = { 72, 178.49, { deu = "Hafnium", eng = "Hafnium", }, 1.3, chem.elements.states.Solid, false, chem.elements.classes.TransitionMetal, }, + [ "Ta" ] = { 73, 180.948, { deu = "Tantal", eng = "Tantalum", }, 1.5, chem.elements.states.Solid, false, chem.elements.classes.TransitionMetal, }, + [ "W" ] = { 74, 183.84, { deu = "Wolfram", eng = "Tungsten", }, 2.36, chem.elements.states.Solid, false, chem.elements.classes.TransitionMetal, }, + [ "Re" ] = { 75, 186.207, { deu = "Rhenium", eng = "Rhenium", }, 1.9 , chem.elements.states.Solid, false, chem.elements.classes.TransitionMetal, }, + [ "Os" ] = { 76, 190.23, { deu = "Osmium", eng = "Osmium", }, 2.2, chem.elements.states.Solid, false, chem.elements.classes.TransitionMetal, }, + [ "Ir" ] = { 77, 192.217, { deu = "Iridium", eng = "Iridium", }, 2.2, chem.elements.states.Solid, false, chem.elements.classes.TransitionMetal, }, + [ "Pt" ] = { 78, 195.085, { deu = "Platin", eng = "Platinum", }, 2.28, chem.elements.states.Solid, false, chem.elements.classes.TransitionMetal, }, + [ "Au" ] = { 79, 196.967, { deu = "Gold", eng = "Gold", }, 2.54, chem.elements.states.Solid, false, chem.elements.classes.TransitionMetal, }, + [ "Hg" ] = { 80, 200.592, { deu = "Quecksilber", eng = "Mercury", }, 1.9, chem.elements.states.Liquid, false, chem.elements.classes.TransitionMetal, }, + [ "Tl" ] = { 81, 204.384, { deu = "Thallium", eng = "Thallium", }, 1.62, chem.elements.states.Solid, false, chem.elements.classes.Metal, }, + [ "Pb" ] = { 82, 207.2, { deu = "Blei", eng = "Lead", }, 2.33, chem.elements.states.Solid, false, chem.elements.classes.Metal, }, + [ "Bi" ] = { 83, 208.980, { deu = "Bismut", eng = "Bismuth", }, 2.02, chem.elements.states.Solid, true, chem.elements.classes.Metal, }, + [ "Po" ] = { 84, 209.98, { deu = "Polonium", eng = "Polonium", }, 2.0, chem.elements.states.Solid, true, chem.elements.classes.Metal, }, + [ "At" ] = { 85, 210, { deu = "Astat", eng = "Astatine", }, 2.2, chem.elements.states.Solid, true, chem.elements.classes.Metal, }, + [ "Rn" ] = { 86, 222, { deu = "Radon", eng = "Radon", }, 0, chem.elements.states.Gas, true, chem.elements.classes.NobleGas, }, + + [ "Fr" ] = { 87, 223, { deu = "Francium", eng = "Francium", }, 0.7, chem.elements.states.Solid, true, chem.elements.classes.AlkaliMetal, }, + [ "Ra" ] = { 88, 226, { deu = "Radium", eng = "Radium", }, 0.89, chem.elements.states.Solid, true, chem.elements.classes.AlkaliEarthMetal, }, + [ "Ac" ] = { 89, 227, { deu = "Actinium", eng = "Actinium", }, 1.1, chem.elements.states.Solid, true, chem.elements.classes.Actinoids, }, + [ "Th" ] = { 90, 232.038, { deu = "Thorium", eng = "Thorium", }, 1.5, chem.elements.states.Solid, true, chem.elements.classes.Actinoids, }, + [ "Pa" ] = { 91, 231.036, { deu = "Protactinium", eng = "Protactinium", }, 1.3, chem.elements.states.Solid, true, chem.elements.classes.Actinoids, }, + [ "U" ] = { 92, 238.029, { deu = "Uran", eng = "Uranium", }, 1.36, chem.elements.states.Solid, true, chem.elements.classes.Actinoids, }, + [ "Np" ] = { 93, 237, { deu = "Neptunium", eng = "Neptunium", }, 1.38, chem.elements.states.Solid, true, chem.elements.classes.Actinoids, }, + [ "Pu" ] = { 94, 244, { deu = "Plutonium", eng = "Plutonium", }, 1.3, chem.elements.states.Solid, true, chem.elements.classes.Actinoids, }, + [ "Am" ] = { 95, 243, { deu = "Americium", eng = "Americium", }, 1.28, chem.elements.states.Solid, true, chem.elements.classes.Actinoids, }, + [ "Cm" ] = { 96, 247, { deu = "Curium", eng = "Curium", }, 1.3, chem.elements.states.Solid, true, chem.elements.classes.Actinoids, }, + [ "Bk" ] = { 97, 247, { deu = "Berkelium", eng = "Berkelium", }, 1.3, chem.elements.states.Solid, true, chem.elements.classes.Actinoids, }, + [ "Cf" ] = { 98, 251, { deu = "Californium", eng = "Californium", }, 1.3, chem.elements.states.Solid, true, chem.elements.classes.Actinoids, }, + [ "Es" ] = { 99, 252, { deu = "Einsteinium", eng = "Einsteinium", }, 1.3, chem.elements.states.Solid, true, chem.elements.classes.Actinoids, }, + [ "Fm" ] = { 100, 257, { deu = "Fermium", eng = "Fermium", }, 1.3, chem.elements.states.Solid, true, chem.elements.classes.Actinoids, }, + [ "Md" ] = { 101, 258, { deu = "Mendelevium", eng = "Mendelevium", }, 1.3, chem.elements.states.Solid, true, chem.elements.classes.Actinoids, }, + [ "No" ] = { 102, 259, { deu = "Nobelium", eng = "Nobelium", }, 1.3, chem.elements.states.Solid, true, chem.elements.classes.Actinoids, }, + [ "Lr" ] = { 103, 262, { deu = "Lawrencium", eng = "Lawrencium", }, 1.3, chem.elements.states.Solid, true, chem.elements.classes.Actinoids, }, + [ "Rf" ] = { 104, 267, { deu = "Rutherfordium", eng = "Rutherfordium", }, nil, chem.elements.states.Solid, true, chem.elements.classes.TransitionMetal, }, + [ "Db" ] = { 105, 269, { deu = "Dubnium", eng = "Dubnium", }, nil, chem.elements.states.Solid, true, chem.elements.classes.TransitionMetal, }, + [ "Sg" ] = { 106, 270, { deu = "Seaborgium", eng = "Seaborgium", }, nil, chem.elements.states.Solid, true, chem.elements.classes.TransitionMetal, }, + [ "Bh" ] = { 107, 272, { deu = "Bohrium", eng = "Bohrium", }, nil, chem.elements.states.Solid, true, chem.elements.classes.TransitionMetal, }, + [ "Hs" ] = { 108, 273, { deu = "Hassium", eng = "Hassium", }, nil, chem.elements.states.Solid, true, chem.elements.classes.TransitionMetal, }, + [ "Mt" ] = { 109, 277, { deu = "Meitnerium", eng = "Meitnerium", }, nil, chem.elements.states.Solid, true, chem.elements.classes.TransitionMetal, }, + [ "Ds" ] = { 110, 281, { deu = "Darmstadtium", eng = "Darmstadtium", }, nil, chem.elements.states.Solid, true, chem.elements.classes.TransitionMetal, }, + [ "Rg" ] = { 111, 281, { deu = "Roentgenium", eng = "Roentgenium", }, nil, chem.elements.states.Solid, true, chem.elements.classes.TransitionMetal, }, + [ "Cn" ] = { 112, 285, { deu = "Copernicium", eng = "Copernicium", }, nil, chem.elements.states.Unknown, true, chem.elements.classes.TransitionMetal, }, + [ "Nh" ] = { 113, 286, { deu = "Nihonium", eng = "Nihonium", }, nil, chem.elements.states.Unknown, true, chem.elements.classes.Metal, }, + [ "Fl" ] = { 114, 289, { deu = "Flerovium", eng = "Flerovium", }, nil, chem.elements.states.Unknown, true, chem.elements.classes.Metal, }, + [ "Mc" ] = { 115, 288, { deu = "Moscovium", eng = "Moscovium", }, nil, chem.elements.states.Unknown, true, chem.elements.classes.Metal, }, + [ "Lv" ] = { 116, 293, { deu = "Livermorium", eng = "Livermorium", }, nil, chem.elements.states.Unknown, true, chem.elements.classes.Metal, }, + [ "Ts" ] = { 117, 294, { deu = "Tenness", eng = "Tennessine", }, nil, chem.elements.states.Unknown, true, chem.elements.classes.Metal, }, + [ "Og" ] = { 118, 294, { deu = "Oganesson", eng = "Oganesson", }, nil, chem.elements.states.Unknown, true, chem.elements.classes.NobleGas, }, + } + +local classColours += { + "magenta", + "red", + "orange", + "yellow", + "green", + "lime", + "cyan", + "blue", + "purple", + } + +local stateShort += { + "s", + "l", + "g", + "?", + } + +local function initElements ( ) + for symbol, entry in pairs ( elements ) + do + local deu = ( entry [ 3 ].deu ):lower ( ) + local eng = ( entry [ 3 ].eng ):lower ( ) + chem.elements.lookUp.deu [ deu ] = symbol + chem.elements.lookUp.eng [ eng ] = symbol + + chem.elements.pse [ symbol ] + = { + number = entry [ 1 ], + mass = entry [ 2 ], + name = entry [ 3 ], + electronegativity = entry [ 4 ], + state = entry [ 5 ], + radioactive = entry [ 6 ], + class = entry [ 7 ], + } + end +end + +-- ToDo: Language, calculate mass from formula +function chem.elements.printAnalysis ( formula, calculatedMass, gotThisMass ) + tex.print + ( + "Elementaranalyse berechnet für " + .. chem.getSimple ( formula ) + .. ": " + .. tostring ( calculatedMass ) + .. ", gefunden: " + .. tostring ( gotThisMass ) + ) +end + +function chem.elements.printEntry ( symbol ) + local entry = chem.elements.pse [ symbol ] + if entry + then + local radioactivity = "" + local electronegativity = entry.electronegativity + if entry.radioactive + then + radioactivity = "*" + end + if electronegativity + then + if electronegativity > 0 + then + electronegativity = tostring(electronegativity) + else + electronegativity = "—" + end + else + electronegativity = "?" + end + local mass = entry.mass + if ( mass % 1 ) > 0 + then + mass = tostring ( mass ) + else + mass = "(" .. tostring ( mass ) .. ")" + end + tex.print + ( + "\\relax\\cellcolor{" + .. classColours [ entry.class ] + .. "!25}\\relax\\hypertarget{table:PSE_" + .. symbol + .. "}{" + .. tostring ( entry.number ) + .. "}~\\hfill{" + .. mass + .. "}\\newline\\textbf{\\small " + .. symbol + .. radioactivity + .. "}\\newline{\\mbox{\\fontsize{5}{6}\\selectfont " + .. entry.name.deu + .. "}}\\newline{" + .. electronegativity + .. "}~\\hfill{(" + .. stateShort [ entry.state ] + .. ")}" + ) + else + tex.print("??") + end +end + +function chem.elements.printColours ( ) + tex.print + ( + "\\textbf{Farben der Serien}" + .. "\\newline{\\color{" .. classColours [ chem.elements.classes.AlkaliMetal ] .. "}$\\blacksquare$}~Alkalimetalle" + .. "\\newline{\\color{" .. classColours [ chem.elements.classes.AlkaliEarthMetal ] .. "}$\\blacksquare$}~Erdalkalimetalle" + .. "\\newline{\\color{" .. classColours [ chem.elements.classes.TransitionMetal ] .. "}$\\blacksquare$}~Übergangsmetalle" + .. "\\newline{\\color{" .. classColours [ chem.elements.classes.Metal ] .. "}$\\blacksquare$}~Metalle" + .. "\\newline{\\color{" .. classColours [ chem.elements.classes.Lanthanoids ] .. "}$\\blacksquare$}~Lanthanoide" + .. "\\newline{\\color{" .. classColours [ chem.elements.classes.Actinoids ] .. "}$\\blacksquare$}~Actinoide" + .. "\\newline{\\color{" .. classColours [ chem.elements.classes.Metalloid ] .. "}$\\blacksquare$}~Halbmetalle" + .. "\\newline{\\color{" .. classColours [ chem.elements.classes.NonMetal ] .. "}$\\blacksquare$}~Nichtmetalle" + .. "\\newline{\\color{" .. classColours [ chem.elements.classes.NobleGas ] .. "}$\\blacksquare$}~Edelgase" + ) +end + +function chem.elements.linkToPSE ( symbol, text ) + if chem.elements.enableLinks + then + return "\\protect\\hyperlink{table:PSE_" .. symbol .. "}{" .. text .. "}" + else + return text + end +end + +initElements ( ) diff --git a/NixTeX/dependencies/source/lua/chemistry/spectra.lua b/NixTeX/dependencies/source/lua/chemistry/spectra.lua new file mode 100644 index 0000000..b8c876f --- /dev/null +++ b/NixTeX/dependencies/source/lua/chemistry/spectra.lua @@ -0,0 +1,135 @@ +chem.spectra = {} + +function chem.spectra.draw(xlabel, ylabel, unsetX, unsetY, title, fileName, xMin, xMax, yMin, yMax, colour, plot, peaks, above, points) + if type ( fileName ) == "table" + then + theFunction = {} + for index, file in ipairs ( fileName ) + do + if type ( file ) == "table" + then + markFileAsUsed ( file [ 1 ] ) + file [ 1 ] = "'"..file[1].."'" + table.insert ( theFunction, file ) + else + markFileAsUsed ( file ) + table.insert ( theFunction, "'"..file.."'" ) + end + end + else + markFileAsUsed ( fileName ) + theFunction = "'"..tostring(fileName).."'" + end + return gnuplot.plotFunction + ( + xlabel, + ylabel, + unsetX, unsetY, + title or "\\GetTitleStringResult", + theFunction, + xMin, xMax, + yMin, yMax, + colour, plot, + peaks, above, + points + ) +end + +function chem.spectra.ir(title, fileName, xMin, xMax, yMin, yMax, colour, plot, peaks) + return chem.spectra.draw + ( + "${\\acrshort{waveNumber} / \\Newunit{cm-1}{}}$", + "${\\text{Transmission} / \\Newunit{percent}{}}$", + false, false, + title, fileName, + xMin, xMax, + yMin, yMax, + colour, plot, + peaks, false + ) +end + +function chem.spectra.raman(title, fileName, xMin, xMax, yMin, yMax, colour, plot, peaks) + return chem.spectra.draw + ( + "${\\Delta\\acrshort{waveNumber} / \\Newunit{cm-1}{}}$", + "${\\text{Intensität}}$", + false, true, + title, fileName, + xMin, xMax, + yMin, yMax, + colour, plot, + peaks, true + ) +end + +function chem.spectra.pxrd(title, fileName, xMin, xMax, yMin, yMax, colour, plot, peaks) + return chem.spectra.draw + ( + "${2\\,\\Theta / \\Newunit{degree}{}}$", + "${\\text{Intensität}}$", + false, true, + title, fileName, + xMin, xMax, + yMin, yMax, + colour, plot, + peaks, true + ) +end + +function chem.spectra.uvvis(title, fileName, xMin, xMax, yMin, yMax, colour, plot, peaks) + return chem.spectra.draw + ( + "${\\acrshort{waveLength} / \\Newunit{nanometre}{}}$", + "${\\text{Extinktion}}$", + false, true, + title, fileName, + xMin, xMax, + yMin, yMax, + colour, plot, + peaks, true + ) +end + +function chem.spectra.iuvvis(title, fileName, xMin, xMax, yMin, yMax, colour, plot, peaks) + return chem.spectra.draw + ( + "${\\acrshort{waveNumber} / \\Newunit{cm-1}{}}$", + "${\\text{Extinktion}}$", + false, true, + title, fileName, + xMin, xMax, + yMin, yMax, + colour, plot, + peaks, true + ) +end + +function chem.spectra.tauc(title, fileName, xMin, xMax, yMin, yMax, colour, plot, peaks) + return spectra + ( + "${\\acrshort{bandGap} / \\Newunit{electronVolt}{}}$", + "${\\left(\\acrshort{absorptionCoefficient}\\cdot\\acrshort{planckConstant}\\cdot\\acrshort{waveFrequency}\\right)^2}$", + false, false, + title, fileName, + xMin, xMax, + yMin, yMax, + colour, plot, + peaks, true + ) +end + +function chem.spectra.cv(title, reference, fileName, xMin, xMax, yMin, yMax, colour, plot, points) + return chem.spectra.draw + ( + "${\\acrshort{dcVoltage} / \\Newunit{volt}{}}$ \\acrshort{versus} "..reference, + "${\\acrshort{dcCurrent} / \\Newunit{microampere}{}}$", + false, false, + title, fileName, + xMin, xMax, + yMin, yMax, + colour, plot, + false, true, + points + ) +end diff --git a/NixTeX/dependencies/source/lua/chemistry/substances.lua b/NixTeX/dependencies/source/lua/chemistry/substances.lua new file mode 100644 index 0000000..71b5e5d --- /dev/null +++ b/NixTeX/dependencies/source/lua/chemistry/substances.lua @@ -0,0 +1,661 @@ +substances += { + counter = 0, + list = { }, + extension = "subs", + noNumber = false, + } + +local function texOrPDFstring ( label, texString, pdfString ) + local output + = "\\relax" + .. "\\texorpdfstring{" + .. "\\hyperref[substance:" .. label .. "]" + .. "{" .. texString .. "}}" + .. "{" .. pdfString .. "}" + log.debug( "texOrPDFstring", output) + return output +end + +local function getMass ( input, identifier ) + if not input + then + log.warn + ( + "getMass", + "Substance »" .. identifier .. "« does not have a mass." + ) + end + local mass = tostring ( input or "???" ) + if type ( input ) == "table" + then + mass = "" + for index, weight in pairs ( input ) + do + mass = mass .. "+" .. weight .. "·" .. index + end + mass = "(" .. mass:sub(2) .. ")" + end + return "\\Physical[2]{" .. mass .. "}{}{gram}{}\\Unit{mol}{-1}" +end + +local function getNumberCode ( substance ) + if substances.noNumber + then + log.error("getNumberCode", "This will print a number for »"..substance.identifier.."«") + end + if substance.code.texString ~= "" + then + return "\\textbf{" .. tostring ( substance.number ) .. "};~" .. substance.code.texString, + tostring ( substance.number ) .. "; " .. substance.code.pdfString + else + return "\\textbf{" .. tostring ( substance.number ) .. "}", + tostring ( substance.number ) + end +end + +local function sortByDefault ( this, that ) + local this = substances.list [ this ] + local that = substances.list [ that ] + if this.sortedBy ~= that.sortedBy + then + return this.sortedBy < that.sortedBy + else + return this.identifier < that.identifier + end +end + +local function sortByNumber ( this, that ) + local this = substances.list [ this ] + local that = substances.list [ that ] + return ( this.number or this.oldNumber or -1 ) < ( that.number or that.oldNumber or -1 ) +end + +function substances.declare ( identifier, object ) + if type ( identifier ) == "string" + and type ( object ) == "table" + then + local name = { } + local acronym = object.acronym + if acronym + then + local entry = acronyms.getEntry ( acronym ) + if entry + then +-- log.debug +-- ( +-- "substances.declare", +-- "got: »" .. tostring ( entry.long [ 1 ] ) .. "«" +-- ) + name + = { + texString + = acronyms.getLink + ( + acronym, + entry.long [ 1 ] + ), + pdfString = entry.long [ 2 ], + } + else + log.fatal + ( + { "substances", "declare", }, + "cannot find acronym with identifier -»" .. acronym .. "«!" + ) + end + else + local texString, pdfString = chem.compounds.parse ( object.name or "" ) + name + = { + texString = texString, + pdfString = pdfString, + } + end + + local texString, pdfString, sortBy = chem.parseSimple ( object.simple or "" ) + local simple + = { + texString = texString, + pdfString = pdfString, + } + + local code = object.code + if code + then + local texString, pdfString, sorty = chem.parseSimple ( code or "" ) + code + = { + texString = texString, + pdfString = pdfString, + } + sortBy = sorty + else + if object.acronym + then + local entry = acronyms.getEntry ( object.acronym, true ) + if entry + then + code + = { + texString = entry.short [ 1 ], + pdfString = entry.short [ 2 ], + } + sortBy = entry.sortedBy + end + else + code = simple + end + end + + local structure = object.structure or { } + if type ( structure ) == "table" + then + structure + = { + figPart = tostring ( structure.figPart or "" ), + movPart = tostring ( structure.movPart or "" ), + } + else + structure + = { + figPart = tostring ( structure ), + movPart = "", + } + end + +-- log.debug +-- ( +-- "substances.declare", +-- "name: »" .. name.texString .. "« | »" .. name.pdfString .. "«", +-- "code: »" .. code.texString .. "« | »" .. code.pdfString .. "«", +-- "simple: »" .. simple.texString .. "« | »" .. simple.pdfString .. "«", +-- "structure: »" .. structure.figPart .. "« | »" .. structure.movPart .. "«", +-- "mass: »" .. tostring ( object.mass or "???" ) .. "«" +-- ) + + log.debug + ( + "substances.declare", + "Sort by: »" .. sortBy .. "«" + ) + + substances.list [ identifier ] + = { + identifier = identifier, + name = name, + code = code, + simple = simple, + structure = structure, + mass = object.mass, + sortedBy = sortBy, + oldNumber = tonumber ( substances.list [ identifier ] ), + } + else + log.fatal + ( + { "substances", "declare", }, + "Invalid Input Types: string for identifier and table for object expected" + ) + end +end + +function substances.getAs ( identifier, texString, pdfString ) + local substance, identifier = substances.use ( "getAs", identifier, false, false ) + log.info + ( + "substance.getAs", + "identifier: »"..identifier.."«", + "tex: »"..texString.."«", + "pdf: »"..pdfString.."«" + ) + return texOrPDFstring + ( + identifier, + texString, + pdfString + ) +end + +function substances.getCode ( identifier ) + local substance, identifier = substances.use ( "getCode", identifier, false, false ) + --log.info("substance.getCode", "pdf: »"..substance.simple.pdfString.."«") + return texOrPDFstring + ( + identifier, + substance.code.texString, + substance.code.pdfString + ) +end + +function substances.getCodeID ( identifier ) + local substance, identifier = substances.use ( "getCodeID", identifier, false, true ) + return texOrPDFstring + ( + identifier, + substance.code.texString .. " (\\textbf{" .. tostring ( substance.number ) .. "})", + substance.code.pdfString .. " (" .. tostring ( substance.number ) .. ")" + ) +end + +function substances.getFull ( identifier ) + local substance, identifier = substances.use ( "getFull", identifier, true, true ) + local texCode, pdfCode = getNumberCode ( substance ) + return texOrPDFstring + ( + identifier, + substance.name.texString .. " (" .. texCode .. ")", + substance.name.pdfString .. " (" .. pdfCode .. ")" + ) +end + +function substances.getLabel ( identifier ) + local substance, identifier = substances.use ( "getLabel", identifier, false, false ) + return "\\label{substance:" .. identifier .. "}" +end + +function substances.getList ( byNumber ) + local identifiers = { } + for identifier, entry in pairs ( substances.list ) + do + table.insert ( identifiers, identifier ) + end + + local config = "l@{\\quad}X" + if byNumber + then + table.sort ( identifiers, sortByNumber ) + config = "c@{\\quad}" .. config + else + table.sort ( identifiers, sortByDefault ) + end + + local output = "" + for index, identifier in ipairs ( identifiers ) + do + local entry = substances.list [ identifier ] + if entry.number + or entry.oldNumber + then + if byNumber + then + output + = output .. "\\textbf{" .. tostring ( entry.oldNumber ) .. "} & " .. entry.code.texString .. " & " .. entry.name.texString .. "\\\\" + else + output + = output .. entry.code.texString .. " & " .. entry.name.texString .. "\\\\" + end + end + end + + local header = "Kürzel & Name \\\\" + if byNumber + then + header = "\\# & "..header + end + + result = "\\begin{longtabu}{" .. config .. "}" + .. output + .. "\\end{longtabu}" + .. "\\addtocounter{table}{-1}" + + log.warn("substance", "Result: "..result) + + return result +end + +function substances.getMass ( identifier, monomer ) + local substance, identifier = substances.use ( "getMass", identifier, true, false ) + if monomer + and monomer ~= "" + then + if substance.mass + and type ( substance.mass ) == "table" + then + return getMass ( substance.mass [ monomer ], identifier ) + else + log.error + ( + "substances.getMass", + "Substance does not have a monomere with index »" .. monomer .. "«" + ) + return getMass ( "¿¿" .. monomer .. "??", identifier ) + end + else + return getMass ( substance.mass, identifier ) + end +end + +function substances.getMolecule ( identifier ) + local substance, identifier = substances.use ( "getMolecule", identifier, false, false ) + if substance.structure.movPart ~= "" + then + return "\\relax" + .. "\\chemfig{" .. substance.structure.figPart .. "}" + .. "\\chemmove{" .. substance.structure.movPart .. "}" + else + return "\\relax" + .. "\\chemfig{" .. substance.structure.figPart .. "}" + end +end + +function substances.getMoleculeWithCode ( identifier ) + local substance, identifier = substances.use ( "getMoleculeWithCode", identifier, false, false ) + local text + = "\\relax" + .. "\\chemname{\\chemfig{" + .. substance.structure.figPart + .. "}}{\\tiny" + .. ( ( substance.code or { texString = "?????" } ).texString or "???" ) + .. "}" + if substance.structure.movPart ~= "" + then + return text .. "\\chemmove{" .. substance.structure.movPart .. "}" + else + return text + end +end + +function substances.getMoleculeWithMass ( identifier ) + local substance, identifier = substances.use ( "getMoleculeWithMass", identifier, false, false ) + local text + = "\\relax" + .. "\\chemname{\\chemfig{" + .. substance.structure.figPart + .. "}}{\\tiny" + .. getMass ( substance.mass, identifier ) + .. "}" + if substance.structure.movPart ~= "" + then + return text .. "\\chemmove{" .. substance.structure.movPart .. "}" + else + return text + end +end + +function substances.getMoleculeWithNumber ( identifier ) + local substance, identifier = substances.use ( "getMoleculeWithNumber", identifier, false, false ) + local text + = "\\relax" + .. "\\chemname{\\chemfig{" + .. substance.structure.figPart + .. "}}{\\tiny" + .. "\\textbf{"..tostring(substance.number).."}" + .. "}" + log.info("substances.getMoleculeWithNumber", text) + if substance.structure.movPart ~= "" + then + return text .. "\\chemmove{" .. substance.structure.movPart .. "}" + else + return text + end +end + +function substances.getMoleculeWithNumberYield ( identifier, yield ) + local substance, identifier = substances.use ( "getMoleculeWithNumberYield", identifier, false, false ) + local text + = "\\relax" + .. "\\chemname{\\chemfig{" + .. substance.structure.figPart + .. "}}{\\tiny" + .. "\\textbf{"..tostring(substance.number)..", \\Physical{"..yield.."}{}{percent}{}}" + .. "}" + if substance.structure.movPart ~= "" + then + return text .. "\\chemmove{" .. substance.structure.movPart .. "}" + else + return text + end +end + +function substances.getMoleculeWithNumberCode ( identifier ) + local substance, identifier = substances.use ( "getMoleculeWithNumberCode", identifier, false, false ) + local texCode, pdfCode = getNumberCode ( substance ) + local text + = "\\relax" + .. "\\chemname{\\chemfig{" + .. substance.structure.figPart + .. "}}{\\tiny" + .. texCode + .. "}" + if substance.structure.movPart ~= "" + then + return text .. "\\chemmove{" .. substance.structure.movPart .. "}" + else + return text + end +end + +function substances.getName ( identifier ) + local substance, identifier = substances.use ( "getName", identifier, true, false ) + return texOrPDFstring + ( + identifier, + substance.name.texString, + substance.name.pdfString + ) +end + +function substances.getNumber ( identifier ) + local substance, identifier = substances.use ( "getNumber", identifier, false, true ) + if substances.noNumber + then + log.error("substance.getNumber", "This will print a number for »"..substance.identifier.."«") + end + return texOrPDFstring + ( + identifier, + "\\textbf{" .. tostring ( substance.number ) .. "}", + tostring ( substance.number ) + ) +end + +function substances.getSimple ( identifier ) + local substance, identifier = substances.use ( "getSimple", identifier, false, false ) + return texOrPDFstring + ( + identifier, + substance.simple.texString, + substance.simple.pdfString + ) +end + +function substances.getWithID ( identifier ) + local substance, identifier = substances.use ( "getWithCode", identifier, true, true ) + if substances.noNumber + then + log.error("substance.getWithID", "This will print a number for »"..substance.identifier.."«") + end + return texOrPDFstring + ( + identifier, + substance.name.texString .. " (\\textbf{" .. tostring ( substance.number ) .. "})", + substance.name.pdfString .. " (\\textbf{" .. tostring ( substance.number ) .. "})" + ) +end + +function substances.getWithCode ( identifier ) + local substance, identifier = substances.use ( "getWithCode", identifier, false, true ) + --log.info("substance.getCode", "pdf: »"..substance.simple.pdfString.."«") + if substances.noNumber + then + log.error("substance.getWithCode", "This will print a number for »"..substance.identifier.."«") + end + return texOrPDFstring + ( + identifier, + "\\textbf{" .. tostring ( substance.number ) .. "} (" .. substance.simple.texString .. ")", + tostring ( substance.number ) .. " (" .. substance.simple.pdfString .. ")" + ) +end + +function substances.init ( ) + local file = buildFiles.open ( substances.extension ) + if file + then + local counter = 0 + for identifier in file:lines ( ) + do + if identifier ~= "" + then + counter = counter + 1 + substances.list [ identifier ] = substances.list [ identifier ] or counter + end + end + file:close ( ) + end +end + +function substances.load ( path ) + loadLuaFile ( path ) +end + +function substances.printAs ( identifier, texString, pdfString ) + tex.print ( substances.getAs ( identifier, texString, pdfString ) ) +end + +function substances.printCode ( identifier ) + tex.print ( substances.getCode ( identifier ) ) +end + +function substances.printCodeID ( identifier ) + tex.print ( substances.getCodeID ( identifier ) ) +end + +function substances.printFull ( identifier ) + tex.print ( substances.getFull ( identifier ) ) +end + +function substances.printLabel ( identifier ) + tex.print ( substances.getLabel ( identifier ) ) +end + +function substances.printList ( byNumber ) + tex.print ( substances.getList ( byNumber ) ) +end + +function substances.printMass ( identifier, monomer ) + tex.print ( substances.getMass ( identifier, monomer ) ) +end + +function substances.printMolecule ( identifier ) + tex.print ( substances.getMolecule ( identifier ) ) +end + +function substances.printMoleculeWithCode ( identifier ) + tex.print ( substances.getMolecule ( identifier ) ) +end + +function substances.printMoleculeWithMass ( identifier ) + tex.print ( substances.getMoleculeWithMass ( identifier ) ) +end + +function substances.printMoleculeWithNumberCode ( identifier ) + tex.print ( substances.getMoleculeWithNumberCode ( identifier ) ) +end + +function substances.printMoleculeWithNumber ( identifier ) + tex.print ( substances.getMoleculeWithNumber ( identifier ) ) +end + +function substances.printMoleculeWithNumberYield ( identifier, yield ) + tex.print ( substances.getMoleculeWithNumberYield ( identifier, yield ) ) +end + +function substances.printName ( identifier ) + tex.print ( substances.getName ( identifier ) ) +end + +function substances.printNumber ( identifier ) + tex.print ( substances.getNumber ( identifier ) ) +end + +function substances.printSimple ( identifier ) + tex.print ( substances.getSimple ( identifier ) ) +end + +function substances.printWithCode ( identifier ) + tex.print ( substances.getWithCode ( identifier ) ) +end + +function substances.printWithID ( identifier ) + tex.print ( substances.getWithID ( identifier ) ) +end + +function substances.save ( ) + local identifiers = { } + for identifier, entry in pairs ( substances.list ) + do + table.insert ( identifiers, identifier ) + end + table.sort ( identifiers, sortByNumber ) + + local file = buildFiles.create ( substances.extension ) + if file + then + for index, identifier in ipairs ( identifiers ) + do + if substances.list [ identifier ].number + then + file:write ( identifier .. "\n" ) + end + end + file:close ( ) + else + log.error + ( + "substances.save", + "Could not save Substances!", + "Listing substances might result in unexpected output." + ) + end +end + +function substances.useIt ( identifier) + local substance, identifier = substances.use ( "useIt", identifier, true, true ) +end + +function substances.use ( source, identifier, withName, withNumber ) + local entry = substances.list [ identifier ] + if entry + then + --log.info({ source, "useSubstance", }, "Use Subtance with Identifier »" .. identifier .. "«") + if entry.number == nil + then + substances.counter = substances.counter + 1 + entry.number = substances.counter + end + entry.nameUsed = entry.nameUsed or withName + entry.numberUsed = entry.numberUsed or withNumber + if not entry.nameUsed + then + log.warn + ( + { source, "useSubstance", }, + "Substance was used, but not the Name.", + "Consider to use \\substanceFull{"..identifier.."}" + .." to tell the reader the Name of the substance before refering to it" + ) + end + if not entry.numberUsed + and not noNumber + then + log.warn + ( + { source, "useSubstance", }, + "Substance was used, but not the Number.", + "Consider to use \\substanceFull{"..identifier.."}" + .." to tell the reader the Name of the substance before refering to it" + ) + end + else + log.fatal + ( + { source, "useSubstance", }, + "Unknown Substance with Identifier »" .. identifier .. "«" + ) + end + return entry, tostring ( identifier ) +end + +substances.init ( ) diff --git a/NixTeX/dependencies/source/lua/chemistry/xray.lua b/NixTeX/dependencies/source/lua/chemistry/xray.lua new file mode 100644 index 0000000..98d8ade --- /dev/null +++ b/NixTeX/dependencies/source/lua/chemistry/xray.lua @@ -0,0 +1,319 @@ +chem.xray = { } + +function chem.xray.details ( file ) + local counter, length, verbindung + loadLuaFile ( file ) +-- tex.print ( "{\\setlength{\\textheight}{1.1\\textheight}" ) + tex.print ( "\\clearpage{\\newgeometry{bottom=4cm}" ) + + for index1, value1 in ipairs(xtable) + do + length = 0 + for index2, value2 in ipairs(value1) + do + length = length + 1 + end + if length == 1 + then + verbindung = "Verbindung" + else + verbindung = "Verbindungen" + end + tex.print("\\clearpage") + tex.print("\\expandafter\\belowpdfbookmark{\\nolink{"..verbindung.." ") + counter = 0 + for index2, value2 in ipairs(value1) + do + counter = counter + 1 + if counter == 1 + then + if value2 ~= "" + then + tex.print("\\substance{"..value2.."}") + end + elseif counter == length + then + if value2 ~= "" + then + tex.print(" und \\substance{"..value2.."}") + end + else + if value2 ~= "" + then + tex.print(", \\substance{".. value2.."}, ") + end + end + end + tex.print("}}{page:\\thepage}") + tex.print("\\htable{p{.4\\linewidth}*{"..tostring(length).."}{|c}}{") + tex.print("Verbindung") + for index2, value2 in ipairs(value1) + do + if value2 ~= "" + then + tex.print("& \\substance{"..value2.."}") + else + tex.print("& \\hspace{4em}") + end + end + tex.print(tex.newline) + tex.print("\\midrule") + + tex.print("Summenformel") + for index2, value2 in ipairs(value1) + do + tex.print("& \\ch{"..xray[value2][1].."}" ) + end + tex.print(tex.newline) + + tex.print("Molare Masse / \\Newunit{gram}{}\\Unit{mol}{-1}") + for index2, value2 in ipairs(value1) + do + tex.print("& "..xray[value2][2] ) + end + tex.print(tex.newline) + + tex.print("Temperatur / \\Newunit{kelvin}{}") + for index2, value2 in ipairs(value1) + do + tex.print("& "..xray[value2][3] ) + end + tex.print(tex.newline) + + tex.print("Wellenlänge / \\Newunit{angstroem}{}") + for index2, value2 in ipairs(value1) + do + tex.print("& "..xray[value2][4] ) + end + tex.print(tex.newline) + + tex.print("Kristallsystem") + for index2, value2 in ipairs(value1) + do + tex.print("& "..xray[value2][5] ) + end + tex.print(tex.newline) + + tex.print("Raumgruppe") + for index2, value2 in ipairs(value1) + do + tex.print("& $"..xray[value2][6].."$" ) + end + tex.print(tex.newline) + + tex.print("a / \\Newunit{angstroem}{}") + for index2, value2 in ipairs(value1) + do + tex.print("& "..xray[value2][7] ) + end + tex.print(tex.newline) + + tex.print("b / \\Newunit{angstroem}{}") + for index2, value2 in ipairs(value1) + do + tex.print("& "..xray[value2][8] ) + end + tex.print(tex.newline) + + tex.print("c / \\Newunit{angstroem}{}") + for index2, value2 in ipairs(value1) + do + tex.print("& "..xray[value2][9] ) + end + tex.print(tex.newline) + + tex.print("α / \\Newunit{degree}{}") + for index2, value2 in ipairs(value1) + do + tex.print("& "..xray[value2][10] ) + end + tex.print(tex.newline) + + tex.print("β / \\Newunit{degree}{}") + for index2, value2 in ipairs(value1) + do + tex.print("& "..xray[value2][11] ) + end + tex.print(tex.newline) + + tex.print("γ / \\Newunit{degree}{}") + for index2, value2 in ipairs(value1) + do + tex.print("& "..xray[value2][12] ) + end + tex.print(tex.newline) + + tex.print("Volumen / \\Newunit{angstroem}{3}") + for index2, value2 in ipairs(value1) + do + tex.print("& "..xray[value2][13] ) + end + tex.print(tex.newline) + + tex.print("ρ / \\Newunit{kilogram}{}\\Unit{litre}{}") + for index2, value2 in ipairs(value1) + do + tex.print("& "..xray[value2][14] ) + end + tex.print(tex.newline) + + tex.print("$F(000)$") + for index2, value2 in ipairs(value1) + do + tex.print("& "..xray[value2][15] ) + end + tex.print(tex.newline) + + tex.print("Kristallgröße / \\Newunit{millimetre}{}") + for index2, value2 in ipairs(value1) + do + tex.print("& "..xray[value2][16] ) + end + tex.print(tex.newline) + + tex.print("Z") + for index2, value2 in ipairs(value1) + do + tex.print("& "..xray[value2][17] ) + end + tex.print(tex.newline) + + tex.print("Max. Transmission") + for index2, value2 in ipairs(value1) + do + tex.print("& "..xray[value2][18] ) + end + tex.print(tex.newline) + + tex.print("Min. Transmission") + for index2, value2 in ipairs(value1) + do + tex.print("& "..xray[value2][19] ) + end + tex.print(tex.newline) + + tex.print("μ / \\Newunit{millimetre}{-1}") + for index2, value2 in ipairs(value1) + do + tex.print("& "..xray[value2][20] ) + end + tex.print(tex.newline) + + tex.print("Θ-Bereich / \\Newunit{degree}{}") + for index2, value2 in ipairs(value1) + do + tex.print("& "..xray[value2][21] ) + end + tex.print(tex.newline) + + tex.print("Limiting Indices") + for index2, value2 in ipairs(value1) + do + tex.print("& "..xray[value2][22] ) + end + tex.print(tex.newline) + for index2, value2 in ipairs(value1) + do + tex.print("& "..xray[value2][23] ) + end + tex.print(tex.newline) + for index2, value2 in ipairs(value1) + do + tex.print("& "..xray[value2][24] ) + end + tex.print(tex.newline) + + tex.print("Reflektionen \\mbox{gesammelt/einzigartig}") + for index2, value2 in ipairs(value1) + do + tex.print("& "..xray[value2][25] ) + end + tex.print(tex.newline) + + tex.print("Vollständigkeit zu Θ\\textsubscript{max} / \\Newunit{percent}{}") + for index2, value2 in ipairs(value1) + do + tex.print("& "..xray[value2][26] ) + end + tex.print(tex.newline) + + tex.print("Beschränkungen / Parameter") + for index2, value2 in ipairs(value1) + do + tex.print("& "..xray[value2][27] ) + end + tex.print(tex.newline) + + tex.print("$R_{int}$") + for index2, value2 in ipairs(value1) + do + tex.print("& "..xray[value2][28] ) + end + tex.print(tex.newline) + tex.print("$R_1, \\omega R_2\\ [I\\leq 2\\cdot\\sigma(I)]$") + for index2, value2 in ipairs(value1) + do + tex.print("& "..xray[value2][29] ) + end + tex.print(tex.newline) + + tex.print("$R_1, \\omega R_2$ (alle Daten)") + for index2, value2 in ipairs(value1) + do + tex.print("& "..xray[value2][30] ) + end + tex.print(tex.newline) + + tex.print("Anpassungsgüte $S$") + for index2, value2 in ipairs(value1) + do + tex.print("& "..xray[value2][31] ) + end + tex.print(tex.newline) + tex.print("Δρ / e\\textsuperscript{$-$}\\Unit{angstroem}{-3}") + for index2, value2 in ipairs(value1) + do + tex.print("& "..xray[value2][32] ) + end + tex.print(tex.newline) + + tex.print("Absoluter Strukturparameter") + for index2, value2 in ipairs(value1) + do + tex.print("& "..xray[value2][33] ) + end + tex.print(tex.newline) + + tex.print("}{Kristall-, Sammlungs- und Verfeinerungsdetails von Verbindung \\mbox{") + counter = 0 + for index2, value2 in ipairs ( value1 ) + do + counter = counter + 1 + if counter == 1 + then + if value2 ~= "" + then + if counter == length + then + tex.print("\\substance{"..value2.."}.") + else + tex.print("\\substance{"..value2.."}") + end + end + elseif counter == length + then + if value2 ~= "" + then + tex.print(" und \\substance{"..value2.."}.") + end + else + if value2 ~= "" + then + tex.print(", \\substance{"..value2.."}, ") + end + end + end + tex.print("}}{}") + end + tex.print("\\restoregeometry}") +end diff --git a/NixTeX/dependencies/source/lua/classes.lua b/NixTeX/dependencies/source/lua/classes.lua new file mode 100644 index 0000000..1b5d110 --- /dev/null +++ b/NixTeX/dependencies/source/lua/classes.lua @@ -0,0 +1,70 @@ +superclasses = {} +superclasses [ "application" ] = "letter" +superclasses [ "slides" ] = "beamer" +superclasses [ "letter" ] = "letter" +superclasses [ "meeting" ] = "article" +superclasses [ "plain" ] = "plain" +superclasses [ "experiment" ] = "thesis" +superclasses [ "thesis" ] = "thesis" +superclasses [ "book" ] = "book" +superclasses [ "tucletter" ] = "tucbrief" + +achromatopsia = false +if class == nil +then + assert(false, "no class given") +else + superclass = superclasses [ class ] + if superclass == nil + then + assert(false, "unknown class: ›"..class.."‹" ) + end +end +documentTitle = "" +if draftMode == nil +then + draftMode = false +end +dyslexia = false +if fontSize == nil +then + fontSize = "12pt" +end +if fullPage == nil +then + fullPage = 0 +elseif fullPage == true +then + fullPage = 1 +end +hazDualScreen = false +hazHandout = false +hazLink = true +hazNotesOnly = false +if headSepLine == nil +then + headSepLine = false +end +neverRotatePages = "false" +noAppendix = "false" +if noCitations == nil +then + noCitations = false +end +if noChapters == nil +then + noChapters = false +end +noMainMatter = "false" +if openLeft == nil +then + openLeft = false +end +if pageFormat == nil +then + pageFormat = "a4paper" +end +if twoSided == nil +then + twoSided = false +end diff --git a/NixTeX/dependencies/source/lua/colour.lua b/NixTeX/dependencies/source/lua/colour.lua new file mode 100644 index 0000000..223bcd5 --- /dev/null +++ b/NixTeX/dependencies/source/lua/colour.lua @@ -0,0 +1,32 @@ +colour += { + html + = { + [ "white" ] = "FFFFFF", + [ "black" ] = "000000", + [ "darkgray" ] = "333333", + [ "gray" ] = "5D5D5D", + [ "lightgray" ] = "999999", + [ "green" ] = "C2E15F", + [ "orange" ] = "FDA333", + [ "purple" ] = "D3A4F9", + [ "red" ] = "FB4485", + [ "blue" ] = "6CE0F1", + [ "darktext" ] = "414141", + [ "awesome-emerald" ] = "00A388", + [ "awesome-skyblue" ] = "0395DE", + [ "awesome-red" ] = "DC3522", + [ "awesome-pink" ] = "EF4089", + [ "awesome-orange" ] = "FF6138", + [ "awesome-nephritis" ] = "27AE60", + [ "awesome-concrete" ] = "95A5A6", + [ "awesome-darknight" ] = "131A28", + } + } + +function colour.texDefineAll ( ) + for name, value in pairs ( colour.html ) + do + tex.print("\\definecolor{"..name.."}{HTML}{"..value.."}") + end +end diff --git a/NixTeX/dependencies/source/lua/common.lua b/NixTeX/dependencies/source/lua/common.lua new file mode 100644 index 0000000..c5202bb --- /dev/null +++ b/NixTeX/dependencies/source/lua/common.lua @@ -0,0 +1,91 @@ +bs = string.char ( 92 ) +escape = string.char ( 27 ) +newline = string.char ( 10 ) +percent = string.char ( 37 ) +tilde = string.char ( 126 ) + +loadedFiles = {} +function include(name) + local fileName = name .. ".lua" + markFileAsUsed ( fileName ) + assert + ( + not dofile(fileName), + "something is wrong with " .. fileName + ) +end + +function includeCode ( name ) + include(source.."source/lua/"..name) +end + +function includeTUC ( name ) + include(source.."tuc/"..name) +end + +function markFileAsUsed ( name ) + table.insert ( loadedFiles, name ) +end + +function loadTexFile ( name ) + markFileAsUsed ( name .. ".tex" ) +end + +function loadLuaFile ( name ) + include ( name ) +end + + +function commonFinal() + spellChecker.listMacros ( ) + labels.check ( ) + glossary.saveAll ( ) + substances.save ( ) + local loaded = "Loaded Files:\n" + for index, file in ipairs ( loadedFiles ) + do + loaded = loaded .. "→ " .. file .. "\n" + end + log.info + ( + "Common Final", + loaded + ) + for line in io.open(buildFiles.name("lgo")):lines() + do + if line == "" + then + else + local luaotfload, message = line:match("luaotfload | (.*)") + if luaotfload and message + then + log.info + ( + "luaotfload", + message + ) + else + log.info + ( + "output", + "> »"..line.."«" + ) + end + end + end + --log.putStatistics ( ) + --spellCheckerLog:close() +end + +function commonAfterDependencies ( ) + colour.texDefineAll() +end + +includeCode ( "buildFiles" ) +tex.newline = bs..bs + +includeCode ( "logging" ) +includeCode ( "units" ) +includeCode ( "utf8" ) +includeCode ( "colour" ) +includeCode ( "roman" ) diff --git a/NixTeX/dependencies/source/lua/dependencies.lua b/NixTeX/dependencies/source/lua/dependencies.lua new file mode 100644 index 0000000..6f1a268 --- /dev/null +++ b/NixTeX/dependencies/source/lua/dependencies.lua @@ -0,0 +1,32 @@ +if superclass ~= "beamer" +and superclass ~= "tucbrief" +then + local temp = "" + if headSepLine + then + temp = ",headsepline" + end + local scrletter = "" + if superclass == "letter" + then + scrletter = "\\usepackage[singlespacing=true]{scrletter}" + end + tex.print ( "\\usepackage[automark" .. temp .. "]{scrlayer-scrpage}" .. scrletter ) +end +if draftMode +then + tex.print + ( + "\\showboxbreadth=50" .. + "\\showboxdepth=50" .. + "\\overfullrule=1mm" + ) +end +if class ~= "tucletter" +then + tex.print + ( + "\\usepackage{subcaption}" .. + "\\usepackage[figure,table]{totalcount}" + ) +end diff --git a/NixTeX/dependencies/source/lua/document.lua b/NixTeX/dependencies/source/lua/document.lua new file mode 100644 index 0000000..be1a90d --- /dev/null +++ b/NixTeX/dependencies/source/lua/document.lua @@ -0,0 +1,162 @@ +document += { + languages + = { + }, + } + +local function prepareLanguage ( object, text ) + local language = document.languages [ object.language ] or {} + return { + language = object.language or "", + marks = object.marks or language.marks or "", + marksLeft = object.marksLeft or language.marksLeft or "", + marksRight = object.marksRight or language.marksRight or "", + right = language.right or false, + prepare = language.prepare or false, + font = language.font or "", + type = language.type or "\\textit", + text = text, + } +end + +function document.parseQuote ( inputOptionList, inputOriginalText, inputTranscript, inputTranslatedText, inputAuthor ) + -- parse options + local original = {} + local translated = {} + for option in inputOptionList:gmatch ( "([^,]+)" ) + do + opName, opValue = option:match ( "([^=]+)=(.+)" ) + if opName and opValue + then + if opName == "originalMarks" + then + original.marks = opValue + elseif opName == "originalLeft" + then + original.marksLeft = opValue + elseif opName == "originalRight" + then + original.marksRight = opValue + elseif opName == "originalLanguage" + then + original.language = opValue + elseif opName == "translatedMarks" + then + translated.marks = opValue + elseif opName == "translatedLeft" + then + translated.marksLeft = opValue + elseif opName == "translatedRight" + then + translated.marksRight = opValue + elseif opName == "translatedLanguage" + then + translated.language = opValue + end + else + -- flags + end + end + + -- construct quote-object + document.quote + = { + optionList = inputOptionList, + author = inputAuthor, + text = false, + original = prepareLanguage ( original, inputOriginalText ), + transcript = inputTranscript, + translated = prepareLanguage ( translated, inputTranslatedText ), + } + + local original = document.quote.original + local translated = document.quote.translated + + -- Generate Original Quote + if original.text ~= "" + then + if type ( original.prepare ) == "function" + then + original.text = original.prepare ( original.text ) or "" + end + + -- Quotation Marks for Original Quote + if original.marks == "" + then + if original.marksLeft == "" + and original.marksRight == "" + then + original.text = "\\q{" .. original.text .. "}" + else + original.text = original.marksLeft .. original.text .. original.marksRight + end + else + original.text = "\\" .. original.marks .. "{" .. original.text .. "}" + end + original.text = "\\normalsize" .. original.type .. original.font .. "{" .. original.text .. "}" + + -- Transcript + if document.quote.transcript ~= "" + then + original.text = original.text .. "\\linebreak\\tiny{[" .. document.quote.transcript .. "]}" + end + if original.right + then + original.text = "\\begin{flushright}{" .. original.text .. "}\\end{flushright}" + end + + -- Generate Translated Quote + if translated.text ~= "" + then + if type ( translated.prepare ) == "function" + then + translated.text = translated.prepare ( translated.text ) or "" + end + + -- Quotation Marks for Translated Quote + if translated.marks == "" + then + if translated.marksLeft == "" + and translated.marksRight == "" + then + translated.text = "\\q{" .. translated.text .. "}" + else + translated.text = translated.marksLeft .. translated.text .. translated.marksRight + end + else + translated.text = "\\" .. translated.marks .. "{" .. translated.text .. "}" + end + translated.text = "\\footnotesize" .. translated.font .. "(" .. translated.type .. "{" .. translated.text .. "})" + if translated.right + then + translated.text = "\\begin{flushright}{" .. translated.text .. "}\\end{flushright}" + end + translated.text = "\\par" .. translated.text + end + + if document.quote.author ~= "" + then + document.quote.author = "\\par{\\raggedleft\\footnotesize– " .. document.quote.author .. "}" + end + + document.quote.text + = original.text + .. translated.text + .. document.quote.author + + log.debug("document.parseQuote", "Got Text: »"..document.quote.text.."«") + end +end + +function document.printQuote ( ) + if document.quote.text + then + tex.print + ( + "{~\\vfill\\hfill\\parbox[][][t]{0.618\\linewidth}{\\noWordBreaks " + .. document.quote.text + .. "\\newpage}{}}" + ) + end +end diff --git a/NixTeX/dependencies/source/lua/floats/enumerations.lua b/NixTeX/dependencies/source/lua/floats/enumerations.lua new file mode 100644 index 0000000..dae1d39 --- /dev/null +++ b/NixTeX/dependencies/source/lua/floats/enumerations.lua @@ -0,0 +1,81 @@ +enumerations += { + prefix = "", + counter = 0, + } + +local function replace ( value ) + return value + :gsub ( "\\arabic %*", "\\noexpand\\EnumArabic" ) + :gsub ( "\\arabic", "\\noexpand\\EnumArabic" ) + :gsub ( "\\alph %*", "\\noexpand\\EnumAlphaL" ) + :gsub ( "\\alph", "\\noexpand\\EnumAlphaL" ) + :gsub ( "\\Alph %*", "\\noexpand\\EnumAlphaU" ) + :gsub ( "\\Alph", "\\noexpand\\EnumAlphaU" ) + :gsub ( "\\roman %*", "\\noexpand\\EnumRomanL" ) + :gsub ( "\\roman", "\\noexpand\\EnumRomanL" ) + :gsub ( "\\Roman %*", "\\noexpand\\EnumRomanU" ) + :gsub ( "\\Roman", "\\noexpand\\EnumRomanU" ) +end + +function enumerations.init ( options, prefix ) + enumerations.counter = 0 + local result = "" + for option in ( options .. "," ):gmatch ( "(.-)," ) + do + local key, value = option:match ( "(.-)=(.*)" ) + if key == "label" + then + result = replace ( value ) + enumerations.prefix = "" + break + elseif key == "label*" + then + result = replace ( value ) + enumerations.prefix = prefix + break + end + end +-- log.error +-- ( +-- "enumerations.init", +-- "Result: »" .. result .. "«" +-- ) + tex.print ( result ) +end + +function enumerations.item ( ) + enumerations.counter = enumerations.counter + 1 +-- log.error +-- ( +-- "enumerations.item", +-- "Counter After: " .. tostring ( enumerations.counter ) +-- ) +end + +function enumerations.arabic ( ) + tex.print ( enumerations.prefix .. tostring ( enumerations.counter ) ) +end + +function enumerations.romanLower ( ) + tex.print ( enumerations.prefix .. toroman ( enumerations.counter ):lower ( ) ) +end + +function enumerations.romanUpper ( ) + tex.print ( enumerations.prefix .. toroman ( enumerations.counter ) ) +end + +function enumerations.alphaLower ( ) + --log.error + --( + -- "enumerations.alphaLower", + -- "Counter: " .. tostring ( enumerations.counter ), + -- "ASCII: " .. tostring ( 96 + enumerations.counter ), + -- "Char: »" .. string.char ( 96 + enumerations.counter ) .. "«" + --) + tex.print ( enumerations.prefix .. string.char ( 96 + enumerations.counter ) ) +end + +function enumerations.alphaUpper ( ) + tex.print ( enumerations.prefix .. string.char ( 64 + enumerations.counter ) ) +end diff --git a/NixTeX/dependencies/source/lua/floats/equations.lua b/NixTeX/dependencies/source/lua/floats/equations.lua new file mode 100644 index 0000000..85b5fdb --- /dev/null +++ b/NixTeX/dependencies/source/lua/floats/equations.lua @@ -0,0 +1,296 @@ +local unitPrefixes += { + "yotta", "zetta", "exa", "peta", "tera", "giga", "mega", "kilo", "hecto", "deca", + "deci", "centi", "milli", "micro", "nano", "pico", "femto", "atto", "zepto", "yocto", + } +function unit2string ( unit, space ) + local entry = acronyms.getEntry ( unit, true ) + if entry + then + if not space + or entry.data [ 1 ] == acronyms.types.Angle + then + -- x°/′/″ + return "\\acrshort{"..unit .."}" + elseif entry.data [ 1 ] == acronyms.types.Unit + then + -- x kg/m/s + return "\\,\\acrshort{"..unit .."}" + elseif entry.data [ 1 ] == acronyms.types.Currency + then + -- x € or $ x or x CHF + return "\\,\\acrshort{"..unit .."}" + else + -- x Users + return "~\\acrshort{"..unit .."}" + end + else + local output = "" + for index, prefix in ipairs ( unitPrefixes ) + do + local match = unit:match ( prefix .. "(%a+)" ) + if match + then + unit = match + output = "\\acrshort{" .. prefix .. "}" + break + end + end + if unit == "gram" + then + if space + then + return "\\," .. output .. "\\acrtext[kilogram]{g}" + else + return output .. "\\acrtext[kilogram]{g}" + end + elseif unit == "calorie" + then + if space + then + return "\\,"..output.."\\acrtext[kilocalorie]{kcal}" + else + return output.."\\acrtext[kilocalorie]{kcal}" + end + else + local entry = acronyms.getEntry ( unit ) + if entry + then + if not space + or entry.data [ 1 ] == acronyms.types.Angle + then + --°, ′, ″ + return output.."\\acrshort{"..unit.."}" + elseif entry.data [ 1 ] == acronyms.types.Unit + then + --kg, m, s + return "\\,"..output.."\\acrshort{"..unit.."}" + else + --Einwohner + return "~"..output.."\\acrshort{"..unit.."}" + end + elseif not space + then + return output.."<\\acrshort{"..unit.."}>" + else + return "\\,"..output.."<\\acrshort{"..unit.."}>" + end + end + end +end + +function unit ( inUnit, inExponent, cdot ) + if cdot + then + cdot = "\\cdot" + else + cdot = "" + end + local output + = "\\ensuremath{" .. cdot + .. "\\text{" .. unit2string ( inUnit, true ) .. "}" + sign = inExponent:gsub ( " ", "" ):utf8char ( ) + exponent = load("return ("..inExponent..")") + if exponent ~= nil + and exponent ( ) ~= nil + and tonumber ( exponent ( ) ) ~= nil + then + if exponent ( ) < 0 + then + exponent = -exponent ( ) + sign = "-" + elseif sign == "+" + then + exponent = exponent ( ) + else + exponent = exponent ( ) + sign = "" + end + output = output.."^{"..sign.."\\text{"..exponent.."}}}" + else + if sign == "+" + then + sign = "\\plus" + elseif sign == "-" + then + sign = "\\minus" + elseif sign == "±" + then + sign = "\\pm" + elseif sign == "∓" + then + sign = "\\mp" + else + sign = "" + end + output = output.."^{"..sign..inExponent.."}}" + end + --log.debug("unit",output) + tex.print(output) +end + +function physical ( inDecimals, inValue, inExponent, inUnit, unitExponent ) + if inUnit:match ( "[(),.;:)]" ) + or unitExponent:match ( "[(),.;:)%a]" ) + then + log.error + ( + "physical", + "Physical takes one Optional and four Mandatory Arguments:", + " [decimals] value value-exponent unit unit-exponent", + "Perhabs you forgot one or two {} somewhere? Have a look:", + "decimals: »" .. inDecimals .. "«", + "value: »" .. inValue .. "«", + "value-exponent: »" .. inExponent .. "«", + "unit: »" .. inUnit .. "«", + "unit-exponent: »" .. unitExponent .. "«" + ) + end + if inValue == "" + then + log.error + ( + "physical", + "Got no value.", + "Do you forgot it or do you mean \\Newunit or \\Unit?" + ) + end + value = load("return ("..inValue..")") + output = "" + if value and value() and tonumber(value()) + then + sign = inValue:gsub(" ", ""):utf8char ( ) + if value()<0 + then + value = -value() + sign = "-" + else + value = value() + end + if sign == "+" + then + output = output.."\\plus" + elseif sign == "-" + then + output = output.."\\minus" + elseif sign == "±" + then + output = output.."\\pm" + elseif sign == "∓" + then + output = output.."\\mp" + end + decimals = load("return ("..inDecimals..")") + if value == false + then + elseif decimals and decimals() and tonumber(decimals()) + then + if decimals() >= 0 + then + output = output..string.format(percent.."."..decimals().."f", value) + else + uncertainty = -decimals() + if ( uncertainty < 1 ) + then + decimals = 0 + while ( uncertainty < 1 ) + do + decimals = decimals + 1 + uncertainty = uncertainty * 10 + end + uncertainty = math.floor(uncertainty+0.5) + if ( uncertainty == 10 ) + then + decimals = decimals - 1 + uncertainty = "(1)" + else + uncertainty = "("..uncertainty..")" + end + output = output..string.format(percent.."."..decimals.."f", value).."\\,"..uncertainty + else + decimals = 1 + while ( uncertainty > 10 ) + do + decimals = decimals * 10 + uncertainty = uncertainty / 10 + end + output = (math.floor(value / decimals + 0.5) * decimals).."\\,("..(math.floor(uncertainty+0.5) * decimals)..")" + end + end + else + output = output..value + end + elseif inValue == "" + then + value = false + else + output = output.."\\noexpand"..inValue + end + output = "\\ensuremath{\\text{"..output.."}" + exponent = load("return ("..inExponent..")") + if exponent and exponent() and tonumber(exponent()) + then + sign = inExponent:gsub(" ", ""):utf8char ( ) + if exponent()<0 + then + exponent = -exponent() + sign = "-" + else + exponent = exponent() + end + if sign == "+" + then + sign = "\\plus" + elseif sign == "-" + then + sign = "\\minus" + elseif sign == "±" + then + sign = "\\pm" + elseif sign == "∓" + then + sign = "\\mp" + else + sign = "" + end + if value ~= false + then + output = output.."\\text{·}" + end + output = output.."\\text{10}^{"..sign.."\\text{"..exponent.."}}" + end + if not ( inUnit == "" ) + then + output = output.."\\text{"..unit2string ( inUnit, true ).."}" + exponent = load("return ("..unitExponent..")") + if exponent and exponent() and tonumber(exponent()) + then + sign = unitExponent:gsub(" ", ""):utf8char ( ) + if exponent()<0 + then + exponent = -exponent() + sign = "-" + else + exponent = exponent() + end + if sign == "+" + then + sign = "\\plus" + elseif sign == "-" + then + sign = "\\minus" + elseif sign == "±" + then + sign = "\\pm" + elseif sign == "∓" + then + sign = "\\mp" + else + sign = "" + end + output = output.."^{"..sign.."\\text{"..exponent.."}}" + end + end + output = "{" .. output.."}}" + tex.print(output) +end diff --git a/NixTeX/dependencies/source/lua/floats/floats.lua b/NixTeX/dependencies/source/lua/floats/floats.lua new file mode 100644 index 0000000..9af3ff9 --- /dev/null +++ b/NixTeX/dependencies/source/lua/floats/floats.lua @@ -0,0 +1,54 @@ +tblNotes = 0 +tblNamedNotes = {} +tblNoteText = "" +tblSmall = false +unlabeledTab = 0 +unlabeledFig = 0 +bookmarkcounter = 0 + +function tableNote(identifier, text) + tblNotes = tblNotes + 1 + tex.print( "\\textsuperscript{("..string.char(96+tblNotes)..")}" ) + if not ( tblNoteText == "" ) + then + tblNoteText=tblNoteText.."; " + end + tblNoteText = tblNoteText.."()"..string.char(96+tblNotes)..") "..text + if not ( identifier == "" ) + then + tblNamedNotes[ identifier ] = tblNotes + end +end + +function theNote(identifier) + if tblNamedNotes[ identifier ] + then + text = string.char(96+tblNamedNotes[ identifier ]) + else + text = identifier.."?" + end + tex.print( "\\textsuperscript{("..text..")}" ) +end + +colourSchemes = {} +numColourSchemes = 0 +function newColourScheme ( name, colour, mark, fill, line ) + colourSchemes [ numColourSchemes ] = + { + name = name, + colour = colour, + mark = mark, + fill = fill, + line = line + } + numColourSchemes = numColourSchemes + 1 +end + +newColourScheme ( "blue", "0.00,0.45,0.70", "*", "white", "solid" ) +newColourScheme ( "red", "0.80,0.40,0.00", "triangle*", "white", "dashed" ) +newColourScheme ( "orange", "0.90,0.60,0.00", "square*", "white", "dotted" ) +newColourScheme ( "green", "0.00,0.60,0.50", "diamond*", "white", "" ) +newColourScheme ( "cyan", "0.35,0.70,0.90", "pentagon*", "white", "" ) +newColourScheme ( "yellow", "0.95,0.90,0.25", "otimes*", "white", "" ) +newColourScheme ( "purple", "0.80,0.60,0.70", "star*", "white", "" ) +newColourScheme ( "black", "0.00,0.00,0.00", "rtrianble*", "white", "" ) diff --git a/NixTeX/dependencies/source/lua/floats/labels.lua b/NixTeX/dependencies/source/lua/floats/labels.lua new file mode 100644 index 0000000..661f2fe --- /dev/null +++ b/NixTeX/dependencies/source/lua/floats/labels.lua @@ -0,0 +1,247 @@ +labels += { + conjunction = " und ", + appendices + = { + name = "Appendix", + singular = "Anhang", + plural = "Anhänge", + prefix = "appendix", + list = {}, + }, + chapters + = { + name = "Chapter", + singular = "Kapitel", + plural = "Kapitel", + prefix = "chapter", + list = {}, + }, + equations + = { + name = "Equation", + singular = "Gleichung", + plural = "Gleichungen", + prefix = "equation", + list = {}, + }, + figures + = { + name = "Figure", + singular = "Abbildung", + plural = "Abbildungen", + prefix = "figure", + list = {}, + }, + listings + = { + name = "Listing", + singular = "Quelltext", + plural = "Quelltexte", + prefix = "listing", + list = {}, + }, + paragraphs + = { + name = "Paragraph", + singular = "Absatz", + plural = "Absätze", + prefix = "paragraph", + list = {}, + }, + parts + = { + name = "Part", + singular = "Teil", + plural = "Teile", + prefix = "part", + list = {}, + }, + schemes + = { + name = "Scheme", + singular = "Schema", + plural = "Schemata", + prefix = "scheme", + list = {}, + }, + sections + = { + name = "Section", + singular = "Abschnitt", + plural = "Abschnitte", + prefix = "section", + list = {}, + }, + sentences + = { + name = "Sentence", + singular = "Satz", + plural = "Sätze", + prefix = "sentence", + list = {}, + }, + subparagraphs + = { + name = "Subparagraph", + singular = "Unterabsatz", + plural = "Unterabsätze", + prefix = "subparagraph", + list = {}, + }, + subsections + = { + name = "Subsection", + singular = "Unterabschnitt", + plural = "Unterabschnitte", + prefix = "subsection", + list = {}, + }, + subsubsections + = { + name = "Subsubsection", + singular = "Unterunterabschnitt", + plural = "Unterunterabschnitte", + prefix = "subsubsection", + list = {}, + }, + tables + = { + name = "Table", + singular = "Tabelle", + plural = "Tabellen", + prefix = "table", + list = {}, + }, + } + +local function getReferenceName ( object, label ) + log.info("getReferenceName", "Use "..object.name.."-Label »"..label.."«") + if object.list [ label ] + then + object.list [ label ].uses = object.list [ label ].uses + 1 + else + object.list [ label ] + = { + declared = 0, + uses = 1, + } + end + return object.prefix .. ":" .. label +end + +local function getReference ( object, label ) + return "\\ref{" .. getReferenceName ( object, label ) .. "}" +end + +function labels.declare ( object, label, allowDeclarationTwice ) + local tries = 1 + -- Equation does weird stuff and this function is invoked twice + if allowDeclarationTwice + then + tries = 2 + end + if label == "" + then + log.error + ( + "labels.declare", + "Label for " .. object.name .. " empty!", + "Use \\label" .. object.name .. "{}" + ) + else + if object.list [ label ] + and object.list [ label ].declared + and object.list [ label ].declared > tries + then + log.error + ( + "labels.declare", + "Label for " .. object.name .. " »" .. label .. "« already declared!" + ) + else + if object.list [ label ] + then + object.list [ label ].declared = object.list [ label ].declared + 1 + else + object.list [ label ] + = { + declared = 1, + uses = 0, + } + end + tex.print ( "\\label{" .. object.prefix .. ":" .. label .. "}" ) + end + end +end + +function labels.hyperlink ( object, name ) + return "\\hyperlink{" .. getReferenceName ( object, name ) .. "}" +end + +function labels.reference ( object, list ) + -- Parse Labels + local listOfLabels = list:split("|") + + -- Generate Output + local output = object.singular .. "~" + local length = #listOfLabels + if length == 0 + then + output = output .. "\\todo{Insert Label For " .. object.name .. "}" + elseif length == 1 + then + output = output .. getReference ( object, listOfLabels [ 1 ] ) + else + output = object.plural .. "~" + local final = listOfLabels [ length ] + table.remove ( listOfLabels, length ) + for index, entry in ipairs ( listOfLabels ) + do + listOfLabels [ index ] = getReference ( object, entry ) + end + output = output .. table.concat ( listOfLabels, ", " ) .. labels.conjunction .. getReference ( object, final ) + end + tex.print ( output ) +end + +local function check ( object ) + log.info({"labels.check", "check"}, "Check "..object.name.."-Labels") + for label, entry in pairs ( object.list ) + do + if entry.declared + then + if entry.uses == 0 + then + log.warn + ( + { "labels.check", "check(" .. object.name .. ")" }, + "Unused Label »" .. label .. "«!" + ) + else + log.debug + ( + { "labels.check", "check(" .. object.name .. ")" }, + "Label »" .. label .. "« was declared and used." + ) + end + else + log.error + ( + { "labels.check", "check(" .. object.name .. ")" }, + "Label »" .. label .. "« used, but not declared!" + ) + end + end +end + +function labels.check ( ) + log.info("labels.check", "Start checking labels…") + check ( labels.appendices ) + check ( labels.equations ) + check ( labels.figures ) + check ( labels.listings ) + check ( labels.schemes ) + check ( labels.tables ) + log.info("labels.check", "Check Labels done") +end diff --git a/NixTeX/dependencies/source/lua/fluent.lua b/NixTeX/dependencies/source/lua/fluent.lua new file mode 100644 index 0000000..88c6fee --- /dev/null +++ b/NixTeX/dependencies/source/lua/fluent.lua @@ -0,0 +1,130 @@ +fluent += { + languages = { "deu", "eng", }, + snippets = { }, + } + +function fluent.check ( snippet, definition ) + if type ( definition ) == "table" + then + if not definition.eng + then + log.warn + ( + { "fluent.add", "fluent.check", } + "No translation to english defined for snippet " .. tostring ( snippet ) .. "!", + "At least a translation to english should exist." + ) + if not definition [ 1 ] + then + log.warn + ( + { "fluent.add", "fluent.check", } + "No default translation defined for snippet " .. tostring ( snippet ) .. "!", + "Even if there is no translation to english, there must be default translation." + ) + end + else + for index, language in ipairs ( fluent.languages ) + do + if not definition [ language ] + then + log.warn + ( + { "fluent.add", "fluent.check", } + "No translation to language " .. tostring ( language ) + .. " defined for snippet " .. tostring ( snippet ) .. "!" + "There should be a translation available for all languages." + ) + end + end + end + elseif type ( definition ) ~= "string" + and type ( definition ) ~= "function" + then + log.error + ( + { "fluent.add", "fluent.check", } + "Invalid type of definition for snippet " .. tostring ( snippet ) .. "!", + "Must be either of type string, table or function." + ) + end +end + +function fluent.add ( snippet, definition ) + fluent.check ( snippet, definition ) + fluent.snippets [ snippet ] = definition +end + +function fluent.translate ( snippet, language, ... ) + local entry = fluent.snippets [ snippet ] + if entry + then + if type ( entry ) == "string" + then + return entry + elseif type ( entry ) == "table" + then + if entry [ language ] + then + return entry [ language ] + elseif entry.eng + then + log.error + ( + "fluent.translate", + "Cannot find snippet " .. tostring ( snippet ) + .. " for language " .. tostring ( language ) .. "!", + "I will try english instead." + ) + return entry.eng + elseif entry [ 1 ] + then + log.error + ( + "fluent.translate", + "Cannot find snippet " .. tostring ( snippet ) + .. " neither for language " .. tostring ( language ) + .. " nor for the english language!", + "I will try the first definition of unknown language instead." + ) + return entry [ 1 ] + else + log.fatal + ( + "fluent.translate", + "Cannot find a suitable translation for snippet " .. tostring ( snippet ) .. "!" + ) + return nil + end + elseif type ( entry ) == "function" + then + local result = entry ( snippet, language, ... ) + if not result + then + log.fatal + ( + "fluent.translate", + "Cannot translate complex snippet " .. tostring ( snippet ) .. " with given arguments!" + ) + return nil + else + return result + end + else + log.fatal + ( + "fluent.translate", + "Something is wrong with the definition of snippet " .. tostring ( snippet ) .. "!" + ) + return nil + end + else + log.fatal + ( + "fluent.translate", + "Cannot find snippet " .. tostring ( snippet ) .. "!" + ) + return nil + end +end diff --git a/NixTeX/dependencies/source/lua/fonts.lua b/NixTeX/dependencies/source/lua/fonts.lua new file mode 100644 index 0000000..3651105 --- /dev/null +++ b/NixTeX/dependencies/source/lua/fonts.lua @@ -0,0 +1,87 @@ +function fonts.textLS ( strInput, spacing ) + local lenInput = string.len ( strInput ) + local lstOutput = { "" } + local ctrOutput = 1 + local posInput = 1 + while ( posInput <= lenInput ) + do + local char = utf8split ( strInput, posInput ) + while ( + string.byte ( char ) >= 48 + and + string.byte ( char ) <= 57 + ) + or char == "." + or char == "‚" + or char == "‘" + or char == "„" + or char == "“" + or char == "»" + or char == "«" + or char == "›" + or char == "‹" + or char == "°" + do + lstOutput [ ctrOutput ] = lstOutput [ ctrOutput ] .. char + posInput = posInput + string.len ( char ) + char = utf8split ( strInput, posInput ) + end + + if lstOutput [ ctrOutput ] ~= "" + then + ctrOutput = ctrOutput + 1 + end + + if string.sub ( strInput, posInput, posInput + 1 ) == "Ch" + then + lstOutput [ ctrOutput ] = "Ch" + posInput = posInput + 1 + elseif string.sub ( strInput, posInput, posInput + 1 ) == "ch" + then + lstOutput [ ctrOutput ] = "ch" + posInput = posInput + 1 + elseif string.sub ( strInput, posInput, posInput + 1 ) == "Ck" + then + lstOutput [ ctrOutput ] = "Ck" + posInput = posInput + 1 + elseif string.sub ( strInput, posInput, posInput + 1 ) == "ck" + then + lstOutput [ ctrOutput ] = "ck" + posInput = posInput + 1 + elseif string.sub ( strInput, posInput, posInput + 1 ) == "St" + then + lstOutput [ ctrOutput ] = "St" + posInput = posInput + 1 + elseif string.sub ( strInput, posInput, posInput + 1 ) == "st" + then + lstOutput [ ctrOutput ] = "st" + posInput = posInput + 1 + elseif string.sub ( strInput, posInput, posInput + 1 ) == "Tz" + then + lstOutput [ ctrOutput ] = "Tz" + posInput = posInput + 1 + elseif string.sub ( strInput, posInput, posInput + 1 ) == "tz" + then + lstOutput [ ctrOutput ] = "tz" + posInput = posInput + 1 + elseif char == " " + then + lstOutput [ ctrOutput ] = " " + ctrOutput = ctrOutput + 1 + lstOutput [ ctrOutput ] = "" + else + lstOutput [ ctrOutput ] = char + end + posInput = posInput + string.len ( char ) + end + + for _, item in pairs ( lstOutput ) + do + if item == " " + then + tex.print ( "\\kern " .. tostring ( 2*spacing ) .. "em" ) + else + tex.print ( item .. "\\kern " .. tostring ( spacing ) .. "em" ) + end + end +end diff --git a/NixTeX/dependencies/source/lua/glossaries/acronyms.lua b/NixTeX/dependencies/source/lua/glossaries/acronyms.lua new file mode 100644 index 0000000..afd6043 --- /dev/null +++ b/NixTeX/dependencies/source/lua/glossaries/acronyms.lua @@ -0,0 +1,347 @@ +acronyms += { + deprecated + = { + [ "AcOEt" ] = "EtOAc", + [ "bzw" ] = "beziehungsweise", + [ "CHCl3" ] = "trichlormethane", + [ "dcm" ] = "dichlormethane", + [ "zB" ] = "forExample", + [ "zT" ] = "partially", + [ "ua" ] = "unterAnderem", + [ "zumTeil" ] = "partially", + }, + extension = "glsa", + language = "deu", + list = { }, + mind = { }, + sections = { }, + table = { }, + types + = { + Default = 0x00, + Math = 0x01, + Unit = 0x02, + Angle = 0x03, + Currency = 0x04, + Chemical = 0x05, + }, + underline = false, + } + +local function fail ( acronym, source ) + log.error + ( + { source, "acrfail", }, + "cannot find acronym with identifier -»" .. tostring ( acronym ) .. "«!" + ) + return "¿¿" .. acronym .. "??" +end + +local function getTextUnchecked ( entry, acronym, texString, pdfString, noLink ) + entry.uses = entry.uses + 1 + if hazLink == true + and noLink ~= true + then + texString = acronyms.getLinkUnchecked ( acronym, texString ) + end + if acronyms.underline + then + texString = "\\underLine{" .. texString .. "}" + end + return "{\\texorpdfstring{" .. texString .. "}{" .. pdfString .. "}}" +end + +function acronyms.getChemical ( acronym, noLink ) + local entry = acronyms.getEntry ( acronym ) + if entry + then + entry.uses = entry.uses + 1 + return "<" .. identifier .. ">" + else + return fail ( acronym, "acrchem" ) + end +end + +function acronyms.getDescription ( acronym, noLink ) + local entry = acronyms.getEntry ( acronym ) + if entry + then + return getTextUnchecked + ( + entry, + acronym, + entry.description.native, + entry.description.native, + noLink + ) + else + return fail ( acronym, "acrdesc" ) + end +end + +function acronyms.use ( acronym ) + local entry = acronyms.getEntry ( acronym ) + if entry + then + entry.uses = entry.uses + 1 + else + return fail ( acronym, "acruse" ) + end +end + +function acronyms.getEntry ( acronym, mightFail ) + log.info("acronyms.getEntry", "Try »"..acronym.."«") + local entry = acronyms.list [ acronym ] + if entry + then + if not entry.uses + then + local oldDebug = log.stepping + log.stepping = log.stepping or entry.debug or false + local text = entry.text [ acronyms.language ] or entry.text.eng or "" + local longTEX = text + local longPDF = text + if type ( text ) == "table" + then + longTEX = text [ 1 ] + longPDF = text [ 2 ] + end + local shortTEX = "" + local shortPDF = "" + if type ( entry.data ) == "table" + then + local kind = entry.data [ 1 ] + local data = entry.data [ 2 ] + if type ( data ) == "table" + and ( not data [ 1 ] or not data [ 2 ] ) + then + data = data [ acronyms.language ] or data.eng or "" + end + if type ( data ) == "table" + then + shortTEX = data [ 1 ] + shortPDF = data [ 2 ] + else + shortTEX = data + shortPDF = data + end + if kind == acronyms.types.Default + or kind == acronyms.types.Unit + or kind == acronyms.types.Angle + or kind == acronyms.types.Currency + then + -- ok + elseif kind == acronyms.types.Math + then + shortTEX = "\\ensuremath{" .. shortTEX .. "}" + elseif kind == acronyms.types.Chemical + then + shortTEX, shortPDF, sortedBy = chem.parseSimple ( shortTEX ) + entry.sortedBy = entry.sortedBy or sortedBy + else + log.fatal + ( + "acronyms.getEntry", + "Invalid Data-Type: " .. tostring ( kind ) + ) + end + else + log.fatal + ( + "acronyms.getEntry", + "Table expected, got: " .. tostring ( entry.data ) .. " (" .. type ( entry.data ) .. ")" + ) + end + entry.uses = 0 + entry.identifier = acronym + entry.title = longTEX + entry.short = { shortTEX, shortPDF, } + entry.long = { longTEX, longPDF, } + if entry.bookmarkAs + then + if type ( entry.bookmarkAs ) == "table" + then + entry.bookmarkAs = entry.bookmarkAs [ acronyms.language ] or entry.bookmarkAs.eng or "" + else + entry.bookmarkAs = tostring ( entry.bookmarkAs ) + end + else + entry.bookmarkAs = shortTEX + end + if entry.sortedBy + then + if type ( entry.sortedBy ) == "table" + then + entry.sortedBy = entry.sortedBy [ acronyms.language ] or entry.sortedBy.eng or "" + else + --log.warn("sortedBy", tostring ( entry.sortedBy )) + entry.sortedBy = entry.sortedBy + end + else + entry.sortedBy = shortPDF + end + if entry.description + then + entry.description.native = entry.description [ acronyms.language ] or entry.description.eng or "" + else + entry.description = { native = "" } + end +-- log.debug +-- ( +-- "acronyms.getEntry", +-- "Got:", +-- entry.identifier .. ": " .. entry.description.native, +-- entry.short [ 1 ] .. ": " .. entry.short [ 2 ], +-- entry.long [ 1 ] .. ": " .. entry.long [ 2 ], +-- entry.bookmarkAs .. ": " .. entry.sortedBy +-- ) + log.stepping = oldDebug + end + elseif acronyms.deprecated [ acronym ] + then + log.warn + ( + "acronyms.getEntry", + "Acronym »" .. tostring ( acronym ) .. "« is depricated", + "I think, you mean »" .. acronyms.deprecated [ acronym ] .. "«…" + ) + entry = acronyms.getEntry ( acronyms.deprecated [ acronym ] ) + elseif mightFail ~= true + then + log.warn + ( + "acronyms.getEntry", + "Unknown Acronym »" .. tostring(acronym) .. "«" + ) + end + return entry +end + +function acronyms.getExplanation ( acronym ) + local entry = acronyms.getEntry ( acronym ) + if entry + then + entry.uses = entry.uses + 1 + if acronyms.underline + then + return "\\underLine{" .. entry.short [ 1 ] .. ": " + .. entry.long [ 1 ] .. "}" + else + return entry.short [ 1 ] .. ": " + .. entry.long [ 1 ] + end + else + return fail ( acronym, "getExplanation" ) + end +end + +function acronyms.getFullText ( acronym, noLink ) + local entry = acronyms.getEntry ( acronym ) + if entry + then + log.info + ( + "acronyms.getFullText", + "Long: "..entry.long [ 1 ] + ) + return getTextUnchecked + ( + entry, + acronym, + entry.long [ 1 ] .. " (" .. entry.short [ 1 ] .. ")", + entry.long [ 2 ] .. " (" .. entry.short [ 2 ] .. ")", + noLink + ) + else + return fail ( acronym, "acrfull" ) + end +end + +function acronyms.getLink ( acronym, text ) + local entry = acronyms.getEntry ( acronym ) + if entry + then + entry.uses = entry.uses + 1 + return acronyms.getLinkUnchecked(acronym, text) + else + return fail ( acronym, "acrlink" ) + end +end + +function acronyms.getLinkUnchecked ( acronym, text ) + --log.info("acronym.getLink", "reference link: »" .. acronym .. "«") + return "\\protect\\hyperlink{acronym:" .. acronym .. "}{" .. text .. "}" +end + +function acronyms.getLongText ( acronym, noLink ) + local entry = acronyms.getEntry ( acronym ) + if entry + then + return getTextUnchecked + ( + entry, + acronym, + entry.long [ 1 ], + entry.long [ 2 ], + noLink + ) + else + return fail ( acronym, "acrlong" ) + end +end + +function acronyms.getShortText ( acronym, noLink ) + local entry = acronyms.getEntry ( acronym ) + if entry + then + return getTextUnchecked ( entry, acronym, entry.short [ 1 ], entry.short [ 2 ], noLink ) + else + return fail ( acronym, "acrshort" ) + end +end + +function acronyms.getText ( acronym, texString, pdfString, noLink ) + local entry = acronyms.getEntry ( acronym ) + if entry + then + return getTextUnchecked ( entry, acronym, texString, pdfString or "", noLink ) + else + return fail ( acronym, "acrtext" ) + end +end + +function acronyms.sort ( this, that ) + local a = acronyms.sections [ this.section ] + local b = acronyms.sections [ that.section ] + if a.class == b.class + then + if a.title:lower ( ) == b.title:lower ( ) + then + if type ( this.sortedBy ) == "number" + and type ( that.sortedBy ) == "number" + then + --log.info("acronyms.sort", "sortedBy: "..tostring(this.sortedBy).." > "..tostring(that.sortedBy)) + return this.sortedBy > that.sortedBy + else + a = tostring(this.sortedBy) + b = tostring(that.sortedBy) + if a:lower ( ) == b:lower ( ) + then + --log.info("acronyms.sort", "identifier: »"..this.identifier.."« < »"..that.identifier.."«") + return this.identifier < that.identifier + else + --log.info("acronyms.sort", "sortedBy: »"..a.."« < »"..b.."«") + return a:lower() < b:lower() + end + end + else + --log.info("acronyms.sort", "title: »"..a.title:lower().."« < »"..b.title:lower().."«") + return a.title:lower ( ) < b.title:lower ( ) + end + else + --log.info("acronyms.sort", "class: "..tostring(a.class).." < "..tostring(b.class)) + return a.class < b.class + end +end + diff --git a/NixTeX/dependencies/source/lua/glossaries/glossaries.lua b/NixTeX/dependencies/source/lua/glossaries/glossaries.lua new file mode 100644 index 0000000..2c934c7 --- /dev/null +++ b/NixTeX/dependencies/source/lua/glossaries/glossaries.lua @@ -0,0 +1,147 @@ +glossary = { } + +function glossary.load ( this ) + local glossaryFile = buildFiles.open ( this.extension ) + if glossaryFile + then + local identifierList = { } + for identifier in glossaryFile:lines ( ) + do + if identifier ~= "" + then + table.insert ( identifierList, identifier ) + end + end + glossaryFile:close ( ) + + for index, value in ipairs ( identifierList ) + do + --log.info("glossary.load", "value: »"..value.."«") + local entry = this.getEntry ( value ) + if entry + then + table.insert ( this.table, entry ) + --log.trace("glossary.load","entry: »"..value.."«") + else + log.error + ( + "glossary.load", + "Unknown entry »" .. value .. "«." + ) + end + end + + os.setlocale ( os.setlocale ( nil,"ctype" ), "collate" ) + table.sort ( this.table, this.sort ) + else + log.warn + ( + "glossary.load", + "Cannot Open File: »" .. buildFiles.name ( this.extension ) .. "«" + ) + end +end + +function glossary.loadAll ( ) + glossary.load ( acronyms ) + glossary.load ( people ) +end + +function glossary.save ( this, name ) + local hasChanged = false + local output = "" + for index, value in pairs ( this.mind ) + do + local entry = this.getEntry ( index ) + if not entry + then + log.error + ( + "glossary.save", + "I was told " .. name .. " »" .. index .. "« does exist, but was not declared yet, but I could not find it." + ) + else + entry.uses = entry.uses + 1 +-- log.info +-- ( +-- "acronyms.save", +-- "I was told " .. name .. " »" .. index .. "« does exist and I found it." +-- ) + end + end + for index, value in pairs ( this.list ) + do + if value.uses + and value.uses > 0 + then + local thisIsKnown = hasChanged or containsExact ( this.table, index ) + hasChanged = hasChanged or ( not thisIsKnown ) + output = output .. index .. "\n" + end + end + if hasChanged + then + local glossaryFile = buildFiles.create ( this.extension ) + glossaryFile:write ( output ) + glossaryFile:close ( ) + end +end + +function glossary.saveAll ( ) + glossary.save ( acronyms, "acronym" ) + glossary.save ( people, "person" ) +end + +-- Definitions +includeCode ( "glossaries/acronyms" ) +includeCode ( "glossaries/people" ) +includeCode ( "glossaries/sections" ) +includeCode ( "glossaries/styles" ) +includeCode ( "glossaries/taxa" ) + +dofile(source.."/"..acronymFile) + +-- Frontend +function acronyms.printChemical ( acronym, noLink ) + tex.print ( acronyms.getChemical ( acronym, noLink ) ) +end + +function acronyms.printDescription ( acronym, noLink ) + tex.print ( acronyms.getDescription ( acronym, noLink ) ) +end + +function acronyms.printExplanation ( acronym ) + tex.print ( acronyms.getExplanation ( acronym ) ) +end + +function acronyms.printFullText ( acronym, noLink ) + tex.print ( acronyms.getFullText ( acronym, noLink ) ) +end + +function acronyms.printLongText ( acronym, noLink ) + tex.print ( acronyms.getLongText ( acronym, noLink ) ) +end + +function acronyms.printShortText ( acronym, noLink ) + tex.print ( acronyms.getShortText ( acronym, noLink ) ) +end + +function acronyms.printText ( acronym, texString, pdfString, noLink ) + tex.print ( acronyms.getText ( acronym, texString, pdfString, noLink ) ) +end + +function acronyms.printList ( style ) + glossary.printSection ( acronyms, style, "acronym" ) +end + +function people.printList ( style ) + glossary.printSection ( people, style, "person" ) +end + +function glossary.printSection ( this, style, name ) + local result = glossaryStyles.getSection ( style, this, name ) + --log.warn ( "glossary.printSection", result ) + tex.print ( result ) +end + +glossary.loadAll ( ) diff --git a/NixTeX/dependencies/source/lua/glossaries/people.lua b/NixTeX/dependencies/source/lua/glossaries/people.lua new file mode 100644 index 0000000..b9a1d1b --- /dev/null +++ b/NixTeX/dependencies/source/lua/glossaries/people.lua @@ -0,0 +1,157 @@ +people += { + extension = "glsp", + language = "deu", + list = { }, + mind = { }, + table = { }, + } + +local function parseDate ( this ) + if this + and this.date + and type ( this.date ) == "string" + then + local maybe = false + local date = this.date + local unknown = date:match ( "(.+)%?") + if unknown + then + maybe = true + date = unknown + end + + if #date == 10 + then + local year, month, day = date:match("(%d%d%d%d)-(%d%d)-(%d%d)") + return { + year = tonumber ( year ), + month = tonumber ( month ), + day = tonumber ( day ), + maybe = maybe, + } + elseif #date == 7 + then + local year, month = date:match("(%d%d%d%d)-(%d%d)") + return { + year = tonumber ( year ), + month = tonumber ( month ), + maybe = maybe, + } + elseif #date == 4 + then + return { + year = tonumber ( date ), + maybe = maybe, + } + else + return nil + end + else + return nil + end +end + +local month += { + "Januar", + "Februar", + "März", + "April", + "Mai", + "Juni", + "Juli", + "August", + "September", + "Oktober", + "November", + "Dezember", + } + +local function putDate ( date ) + if date + and date.year + then + local life = tostring ( date.year ) + if date.month + then + life = month [ date.month ] .. " " .. life + if date.day + then + life = tostring ( date.day ) .. ".~" .. life + end + end + if date.maybe + then + life = life .. "?" + end + return life + else + return "?" + end +end + +function people.getEntry ( name ) + local entry = people.list [ name ] + if entry + then + if not entry.uses + then + local bornAs = "" + if entry.born + and entry.born.as + then + bornAs = "geboren \\textsc{" .. entry.born.as .. "} " + end + local life = putDate(parseDate(entry.born)) + if entry.died + then + life = life .. "–" .. putDate(parseDate(entry.died)) + end + entry.life = life + entry.long = "\\textsc{" .. entry.full .. "} \\mbox{(" .. life .. ")}" + + entry.identifier = name + if entry.description + then + entry.description.native + = entry.description [ people.language ] + or entry.description.eng + or "" + end + entry.bookmarkAs = "\\textsc{" .. entry.full .. "}" + entry.title = bornAs .. "(" .. life .. ")" + entry.uses = 1 + else + entry.uses = entry.uses + 1 + end + end + return entry +end + +function people.sort ( this, that ) + return this.full < that.full +end + +function people.print ( name, text ) + if not name + or name == "" + then + name = text:lower() + end + local pdfString = text + local texString = "\\textsc{" .. text .. "}" + + local entry = people.getEntry ( name ) + if entry + then + texString = "\\protect\\hyperlink{person:" .. name .. "}{" .. texString .. "}" + else + log.warn + ( + "people.print", + "Who is »"..text.."« (»"..name.."«)?" + ) + end + tex.print ( "{\\texorpdfstring{\\mbox{" .. texString .. "}}{" .. pdfString .. "}}" ) +end diff --git a/NixTeX/dependencies/source/lua/glossaries/sections.lua b/NixTeX/dependencies/source/lua/glossaries/sections.lua new file mode 100644 index 0000000..0b167a3 --- /dev/null +++ b/NixTeX/dependencies/source/lua/glossaries/sections.lua @@ -0,0 +1,34 @@ +local sectionCounter = 0 +local function section ( class, title ) + sectionCounter = sectionCounter + 1 + acronyms.sections [ sectionCounter ] + = { + class = class or 0, + title = title [ acronyms.language ] or title.eng or "", + } + return sectionCounter +end + +sections += { + General + = section ( 1, { deu = "", eng = "", } ), + Analytical + = section ( 2, { deu = "Analytik", eng = "Analytic", } ), + Substances + = section ( 2, { deu = "Chemische Substanzen oder Gruppen", eng = "Chemical Substances and Groups", } ), + Units + = section ( 2, { deu = "Einheiten", eng = "Units", } ), + Variables + = section ( 2, { deu = "Formel\\-zeichen und Konstanten", eng = "Common Symbols and Constants", } ), + Standards + = section ( 2, { deu = "Normen, Standards und Organisationen", eng = "Standards and Organisations", } ), + Prefixes + = section ( 2, { deu = "Vorsätze für Maß\\-einheiten", eng = "Unit Prefixes", } ), + Electronics + = section ( 2, { deu = "Elektronik und elektrische Bau\\-elemente", eng = "Electronics and Electronic Components", } ), + Quantum + = section ( 2, { deu = "Quanten\\-physikalische Begriffe und Phänomene", eng = "Quantum Physical Terms and Phenomenons", } ), + Miscellaneous + = section ( 3, { deu = "Sonstiges", eng = "Miscellaneous", } ), + } diff --git a/NixTeX/dependencies/source/lua/glossaries/styles.lua b/NixTeX/dependencies/source/lua/glossaries/styles.lua new file mode 100644 index 0000000..94e415e --- /dev/null +++ b/NixTeX/dependencies/source/lua/glossaries/styles.lua @@ -0,0 +1,132 @@ +linefeed = ""--string.char(10) +function putHyperTarget ( identifier, text, name ) + log.info("putHyperTarget", "declare link: »" .. name .. ":" .. identifier .. "«") + return "\\vadjust pre{\\hypertarget{" .. name .. ":" + .. identifier + .. "}{}}\\acrWithOptional{" + .. text + .. "}" +end + +function glossaryStyle1 ( value, name ) + return + ( + putHyperTarget ( value.identifier, value.bookmarkAs, name ) + .. "& " .. value.title .. "&" .. + ( value.description.native or "" ) .. tex.newline..linefeed + ) +end + +function glossaryStyle2 ( value, name ) + if not value.description.native + or value.description.native == "" + then + return + ( + putHyperTarget ( value.identifier, value.bookmarkAs, name ) + .. "& \\textit{" .. value.title .. "}" .. tex.newline..linefeed + ) + else + return + ( + putHyperTarget ( value.identifier, value.bookmarkAs, name ) + .. "& \\textit{" .. value.title + .. "}: " .. value.description.native..tex.newline..linefeed + ) + end +end + +function glossaryStyle3 ( value, name ) + if not value.description.native + or value.description.native == "" + then + return + ( + putHyperTarget ( value.identifier, value.bookmarkAs, name ) + .. "& " .. "\\textit{" .. value.title .. "}: \\newline " + .. value.title .. "}" .. tex.newline..linefeed + ) + else + return + ( + putHyperTarget ( value.identifier, value.bookmarkAs, name ) + .. "& " .. "\\textit{" .. value.title .. "}: \\newline " + .. value.description.native .. tex.newline..linefeed + ) + end +end + +function glossaryStyle4 ( value, name ) + return + ( + putHyperTarget ( value.identifier, value.bookmarkAs, name ) + .. " " .. value.title .. tex.newline .. "*" ..linefeed + .. "\\multicolumn{1}{@{\\qquad}p{\\linewidth-2em}}{" + .. ( value.description.native or "" ) + .. "}" .. tex.newline..linefeed + ) +end + +glossaryStyles += { + [ "simple" ] + = { + foo = glossaryStyle1, + bar = "l@{\\quad}p{.3\\linewidth}X", + }, + [ "single-line" ] + = { + foo = glossaryStyle2, + bar = "l@{\\quad}X", + }, + [ "multi-line" ] + = { + foo = glossaryStyle3, + bar = "l@{\\quad}X", + }, + [ "people" ] + = { + foo = glossaryStyle4, + bar = "l", + }, + } + +function glossaryStyles.getSection ( style, this, name ) + local glossaryStyle = glossaryStyles [ style ] + local currentSection = 0 + local output + = "\\begin{longtabu}{" .. + glossaryStyle.bar .. + "}"..linefeed + local firstLine = true + for index, entry in ipairs ( this.table ) + do + if entry.section + and entry.section ~= currentSection + then + currentSection = entry.section + local title = this.sections [ entry.section ].title + if title ~= "" + then + if not firstLine + then + output = output .. tex.newline .. "*" + end + output + = output .. "\\multicolumn{\\numColumns}{l}{\\textbf{" + .. title + .. "}}" .. tex.newline .. "*"..linefeed + end + end + if not firstLine + then + output = output .. tex.newline .. "*[-16pt]"..linefeed + else + firstLine = false + end + output = output .. glossaryStyle.foo ( entry, name ) + end + output = output .. "\\end{longtabu}"..linefeed + --print(output) + return output +end diff --git a/NixTeX/dependencies/source/lua/glossaries/taxa.lua b/NixTeX/dependencies/source/lua/glossaries/taxa.lua new file mode 100644 index 0000000..856eea1 --- /dev/null +++ b/NixTeX/dependencies/source/lua/glossaries/taxa.lua @@ -0,0 +1,51 @@ + +taxa += { + list = { }, + ranks = { }, + } + +local ctrRank = 0 +local function newRank ( eng, deu ) + ctrRank = ctrRank + 1 + return { + level = ctrRank, + name + = { + eng = eng, + deu = deu or eng, + }, + } +end + +taxa.ranks += { + Domain = newRank ( "Domain", "Domäne" ), + SubDomain = newRank ( "Subdomain", "Unterdomäne" ), + Realm = newRank ( "Realm", "Bereich" ), + SubRealm = newRank ( "Subrealm", "Unterbereich" ), + HyperKingdom = newRank ( "Hyperkingdom", "Reich" ), + Kingdom = newRank ( "Kingdom", "Reich" ), + SubKingdom = newRank ( "Subkingdom", "Unterreich" ), + Phylum = newRank ( "Phylum", "Stamm" ), + SubPhylum = newRank ( "Subphylum", "Unterstamm" ), + InfraPhylum = newRank ( "Infraphylum", "Infrastamm" ), + SuperClass = newRank ( "Superclass", "Überklasse" ), + Class = newRank ( "Class", "Klasse" ), + SubClass = newRank ( "Subclass", "Unterklasse" ), + InfraClass = newRank ( "Infraclass", "Infraklasse" ), + SubterClass = newRank ( "Subterclass", "Subterklasse" ), + ParvClass = newRank ( "Parvclass", "Parvklasse" ), + Order = newRank ( "Order", "Ordnung" ), + SubOrder = newRank ( "Suborder", "Unterordnung" ), + SubSubOrder = newRank ( "???", "Teilordnung" ), + SuperFamily = newRank ( "Superfamily", "Überfamilie" ), + Family = newRank ( "Family", "Familie" ), + SubFamily = newRank ( "Subfamily", "Unterfamilie" ), + Tribe = newRank ( "Tribe", "Tribus" ), + SubTribe = newRank ( "Subtribe", "Untertribus" ), + Genus = newRank ( "Genus", "Gattung" ), + Species = newRank ( "Species", "Art" ), + SubSpecies = newRank ( "Subspecies", "Unterart" ), + Strain = newRank ( "Strain", "Strain" ), + } diff --git a/NixTeX/dependencies/source/lua/hazardous/adr.lua b/NixTeX/dependencies/source/lua/hazardous/adr.lua new file mode 100644 index 0000000..b34161f --- /dev/null +++ b/NixTeX/dependencies/source/lua/hazardous/adr.lua @@ -0,0 +1,411 @@ +hazardClassExplosive = 1 +hazardClassGas = 2 +hazardClassFlammableLiquid = 3 +hazardClassFlammableSolid = 4 +hazardClassOxidiser = 5 +hazardClassOxidizer = hazardClassOxidiser +hazardClassPoison = 6 +hazardClassToxic = hazardClassPoison +hazardClassInfectious = hazardClassPoison +hazardClassRadioactive = 7 +hazardClassCorrosive = 8 +hazardClassMiscellaneous = 9 +hazardClassOther = hazardClassMiscellaneous + +function adrData ( hazardousData ) + local result = hazardousData + if result.unNumber ~= nil + then + result.unNumber = tostring ( result.unNumber ) + else + result.unNumber = "" + end + if result.kemler ~= nil + then + if type ( result.kemler ) == "number" + then + if result.kemler < 0 + then + result.kemler = "X" .. tostring ( -result.kemler ) + else + result.kemler = tostring ( result.kemler ) + end + elseif type ( result.kemler ) ~= "string" + then + result.kemler = "???" + end + else + result.kemler = "" + end + return result +end + +function adrPictograms ( hazardousData, pictograms ) + if hazardousData.hazardClass ~= nil + and type ( hazardousData.hazardClass ) == "table" + then + for index, class in pairs ( hazardousData.hazardClass ) + do + if type ( class ) == "number" + then + if class == 3 -- flammable liquids + or class == 8 -- corrosive substancees + or class == 9 -- miscellaneous hazards + then + log.error + ( + "adrPictograms", + "Only Class 3 (Flammable Liquids) and 8 (Corrosive Substances) do not need further specification" + ) + end + elseif type ( class ) == "table" + then + if class.class ~= nil + and type ( class.class ) == "number" + then + if class.class == hazardClassExplosive + and class.subClass ~= nil + and type ( class.subClass ) == "number" + then + -- explosives + if class.compatibility == nil + then + class.compatibility = "" + elseif type ( class.compatibility ) == "number" + then + class.compatibility = "A" + end + if class.subClass > 0 + and class.subClass < 4 + then + -- with pictogram + table.insert + ( + pictograms, + "\\adrExplosive" + .. "[\\@HazardousPictogramSize]" + .. "{" .. class.subClass .. "}" + .. "{" .. class.compatibility .. "}" + ) + elseif class.subClass < 7 + then + -- with subclass + table.insert + ( + pictograms, + "\\adrLessExplosive" + .. "[\\@HazardousPictogramSize]" + .. "{" .. class.subClass .. "}" + .. "{" .. class.compatibility .. "}" + ) + else + log.error + ( + { "adrPictograms", "explosives", }, + "Invalid Subclass: " .. tostring ( class.subClass ) + ) + end + elseif class.class == hazardClassGas + and class.subClass ~= nil + and type ( class.subClass ) == "number" + then + -- gases + if class.subClass == 1 + then + table.insert + ( + pictograms, + "\\adrFlammableGas" + .. "[\\@HazardousPictogramSize]" + ) + elseif class.subClass == 2 + then + table.insert + ( + pictograms, + "\\adrNonFlammableGas" + .. "[\\@HazardousPictogramSize]" + ) + elseif class.subClass == 3 + then + table.insert + ( + pictograms, + "\\adrPoisonGas" + .. "[\\@HazardousPictogramSize]" + ) + else + log.error + ( + { "adrPictograms", "gases", }, + "Invalid Subclass: " .. tostring ( class.subClass ) + ) + end + elseif class.class == hazardClassFlammableLiquid + then + table.insert + ( + pictograms, + "\\adrFlammableLiquid" + .. "[\\@HazardousPictogramSize]" + ) + elseif class.class == hazardClassFlammableSolid + and class.subClass ~= nil + and type ( class.subClass ) == "number" + then + -- flammable solids + if class.subClass == 1 + then + table.insert + ( + pictograms, + "\\adrFlammableSolid" + .. "[\\@HazardousPictogramSize]" + ) + elseif class.subClass == 2 + then + table.insert + ( + pictograms, + "\\adrSpontaneouslyCombustible" + .. "[\\@HazardousPictogramSize]" + ) + elseif class.subClass == 3 + then + table.insert + ( + pictograms, + "\\adrDangerousWhenWet" + .. "[\\@HazardousPictogramSize]" + ) + else + log.error + ( + { "adrPictograms", "flammable solids", }, + "Invalid Subclass: " .. tostring ( class.subClass ) + "error" + ) + end + elseif class.class == hazardClassOxidiser + and class.subClass ~= nil + and type ( class.subClass ) == "number" + then + -- oxidising substances and organic peroxides + if class.subClass == 1 + then + table.insert + ( + pictograms, + "\\adrOxidiser" + .. "[\\@HazardousPictogramSize]" + ) + elseif class.subClass == 2 + then + table.insert + ( + pictograms, + "\\adrPeroxide" + .. "[\\@HazardousPictogramSize]" + ) + else + log.error + ( + { "adrPictograms", "oxidising substances and organic peroxides", }, + "Invalid Subclass: " .. tostring ( class.subClass ) + ) + end + elseif class.class == hazardClassPoison + and class.subClass ~= nil + and type ( class.subClass ) == "number" + then + -- toxic, poisonous and infectious substances + if class.subClass == 1 + then + table.insert + ( + pictograms, + "\\adrToxic" + .. "[\\@HazardousPictogramSize]" + ) + elseif class.subClass == 2 + then + table.insert + ( + pictograms, + "\\adrInfectious" + .. "[\\@HazardousPictogramSize]" + ) + else + log.error + ( + { "adrPictograms", "toxic, poisonous and infectious substances", }, + "Invalid Subclass: " .. tostring ( class.subClass ) + ) + end + elseif class.class == hazardClassRadioactive + and class.subClass ~= nil + and type ( class.subClass ) == "number" + then + -- radioactive and fissile material + if class.subClass == 1 + then + if class.activity ~= nil + and type ( class.activity ) == "number" + then + local exponent = math.floor ( math.log ( class.activity, 10 ) ) + local decimal = tostring ( class.activity * 10 ^ -exponent ) + if exponent == 0 + then + exponent = "" + else + exponent = tostring ( exponent ) + end + table.insert + ( + pictograms, + "\\adrRadioactiveI" + .. "[\\@HazardousPictogramSize]" + .. "{" .. ( class.contents or "" ) .. "}" + .. "{{" .. decimal .. "}{" .. exponent .. "}{becquerel}{}\\Unit{kilogram}{-1}}" + ) + else + log.error + ( + { "adrPictograms", "radioactive and fissile material", "RadioactiveI", }, + "No Valid Activity Given." + ) + end + elseif class.subClass == 2 + or class.subClass == 3 + then + local macro = "" + if class.subClass == 2 + then + macro = "adrRadioactiveII" + else + macro = "adrRadioactiveIII" + end + if class.activity ~= nil + and type ( class.activity ) == "number" + and class.index ~= nil + and tostring ( class.index ) ~= nil + then + local exponent = math.floor ( math.log ( class.activity, 10 ) ) + local decimal = tostring ( class.activity * 10 ^ -exponent ) + if exponent == 0 + then + exponent = "" + else + exponent = tostring ( exponent ) + end + table.insert + ( + pictograms, + bs .. macro + .. "[\\@HazardousPictogramSize]" + .. "{" .. ( class.contents or "" ) .. "}" + .. "{{" .. decimal .. "}{" .. exponent .. "}{becquerel}{}\\Unit{kilogram}{-1}}" + .. "{" .. tostring ( class.index ) .. "}" + ) + else + log.error + ( + { "adrPictograms", "radioactive and fissile material", macro, }, + "No Valid Activity and/or Index Given." + ) + end + elseif class.subClass == 5 + then + if class.index ~= nil + and tostring ( class.index ) ~= nil + then + table.insert + ( + pictograms, + "\\adrFissile" + .. "[\\@HazardousPictogramSize]" + .. "{" .. tostring ( class.index ) .. "}" + ) + else + log.error + ( + { "adrPictograms", "radioactive and fissile material", "Fissile", }, + "No Valid Index Given." + ) + end + else + log.error + ( + { "adrPictograms", "radioactive and fissile material", }, + "Invalid Subclass: " .. tostring ( class.subClass ) + ) + end + elseif class.class == hazardClassCorrosive + then + -- corrosive substances + table.insert + ( + pictograms, + "\\adrCorrosive" + .. "[\\@HazardousPictogramSize]" + ) + elseif class.class == hazardClassMiscellaneous + then + -- lithium ion cells, miscellaneous + if class.subClass == "A" + then + table.insert + ( + pictograms, + "\\adrLithiumCells" + .. "[\\@HazardousPictogramSize]" + ) + else + table.insert + ( + pictograms, + "\\adrOther" + .. "[\\@HazardousPictogramSize]" + ) + end + elseif class.class >= 1 + and class.class <= 9 + then + log.error + ( + "adrPictograms", + "SubClass must be specified as a number" + ) + else + log.error + ( + "adrPictograms", + "Class must be between 1 and 9" + ) + end + else + log.error + ( + "adrPictograms", + "Class must be specified as a number between 1 and 9" + ) + end + else + log.error + ( + "adrPictograms", + "Class must be of of type number or table, not ›" .. type ( class ) .. "‹" + ) + end + end + end + if hazardousData.unNumber ~= "" + or hazardousData.kemler ~= "" + then + return tex.newline + .. "\\adrPlate[0.07]{" .. hazardousData.kemler .. "}{" .. hazardousData.unNumber .. "}" + .. "\\hspace{\\@HazardousPictogramSep}" + else + return "" + end +end diff --git a/NixTeX/dependencies/source/lua/hazardous/ghs/euhazards.lua b/NixTeX/dependencies/source/lua/hazardous/ghs/euhazards.lua new file mode 100644 index 0000000..66fd577 --- /dev/null +++ b/NixTeX/dependencies/source/lua/hazardous/ghs/euhazards.lua @@ -0,0 +1,32 @@ +function ghsEUHazards ( ghs ) + local options = "" + if next ( ghs.euHazards ) + then + for index, value in ipairs ( ghs.euHazards ) + do + if type ( value ) == "number" + then + if value < 100 + then + value = "0" .. tostring ( value ) + else + value = tostring ( value ) + end + elseif type ( value ) == "table" + then + if value.substance ~= nil + then + options = options .. "substance=" .. value.organs + end + value = tostring ( value.id ) + end + if options == "" + then + tex.print("\\ghs{euh}{"..value.."}") + else + tex.print("\\ghs["..options.."]{euh}{"..value.."}") + end + end + tex.print(tex.newline) + end +end diff --git a/NixTeX/dependencies/source/lua/hazardous/ghs/ghs.lua b/NixTeX/dependencies/source/lua/hazardous/ghs/ghs.lua new file mode 100644 index 0000000..21be175 --- /dev/null +++ b/NixTeX/dependencies/source/lua/hazardous/ghs/ghs.lua @@ -0,0 +1,170 @@ +includeCode ( "hazardous/ghs/euhazards" ) +includeCode ( "hazardous/ghs/hazards" ) +includeCode ( "hazardous/ghs/precautions" ) +includeCode ( "hazardous/ghs/signals" ) + +-- pictograms +ghsExplosive = 1 +ghsFlame = 2 +ghsOFlame = 3 -- roundflame +ghsBottle = 4 +ghsAcid = 5 +ghsSkull = 6 +ghsExclam = 7 +ghsHealth = 8 -- silhouette +ghsPollu = 9 -- aqpol + +-- signal words +ghsNone = 1 +ghsWarning = 2 +ghsDanger = 3 +ghsInvalid = 4 + +function ghsData ( hazardousData ) + local result + local name = hazardousData.title + if hazardousData.ghs == nil + then + log.warn + ( + "gethazardousData", + "please update ›" .. name .. "‹ to new format (ghs { hazards, euHazards, precautions, pictograms, signal})!" + ) + result + = { + hazards = hazardousData.hazards, + euHazards = hazardousData.euHazards, + precautions = hazardousData.precautions, + pictograms = hazardousData.dangers, + signal = hazardousData.signal, + } + else + result = hazardousData.ghs + end + + -- hazard statements + if result.hazards == nil + then + result.hazards = {} + elseif type ( result.hazards ) == "number" + or type ( result.hazards ) == "string" + then + result.hazards = { tostring ( result.hazards ) } + end + + -- eu-hazard statements + if result.euHazards == nil + then + result.euHazards = {} + elseif type ( result.euHazards ) == "number" + or type ( result.euHazards ) == "string" + then + result.euHazards = { tostring ( result.euHazards ) } + end + + -- precaution statements + if result.precautions == nil + then + result.precautions = {} + elseif type ( result.precautions ) == "number" + or type ( result.precautions ) == "string" + then + result.precautions = { tostring ( result.precautions ) } + end + + -- pictograms + result.pictograms = result.pictograms or {} + + -- signal word + if result.signal == nil + then + result.signal = ghsInvalid + elseif type ( result.signal ) ~= "number" + or result.signal >= ghsInvalid + or result.signal < ghsNone + then + log.warn + ( + "gethazardousData", + "›" .. name .. "‹ has invalid signal word!" + ) + result.signal = ghsInvalid + end + return result +end + +function ghsPictograms ( ghs, pictograms ) + for index, pictogram in ipairs ( ghs.pictograms ) + do + table.insert ( pictograms, ghsSinglePictogram ( pictogram, "" ) ) + end +end + +function ghsNamedPictogram ( inPictogram, extra ) + pictogram = inPictogram:lower ( ) + if pictogram == "explosive" + or pictogram == "1" + then + return ghsSinglePictogram ( ghsExplosive, extra ) + elseif pictogram == "flame" + or pictogram == "2" + then + return ghsSinglePictogram ( ghsFlame, extra ) + elseif pictogram == "oflame" + or pictogram == "roundflame" + or pictogram == "3" + then + return ghsSinglePictogram ( ghsOFlame, extra ) + elseif pictogram == "bottle" + or pictogram == "gas" + or pictogram == "4" + then + return ghsSinglePictogram ( ghsBottle, extra ) + elseif pictogram == "acid" + or pictogram == "corrosive" + or pictogram == "5" + then + return ghsSinglePictogram ( ghsAcid, extra ) + elseif pictogram == "skull" + or pictogram == "toxic" + or pictogram == "poisonous" + or pictogram == "6" + then + return ghsSinglePictogram ( ghsSkull, extra ) + elseif pictogram == "exclam" + or pictogram == "!" + or pictogram == "7" + then + return ghsSinglePictogram ( ghsExclam, extra ) + elseif pictogram == "health" + or pictogram == "silhouette" + or pictogram == "8" + then + return ghsSinglePictogram ( ghsHealth, extra ) + elseif pictogram == "pollu" + or pictogram == "aqpol" + or pictogram == "9" + then + return ghsSinglePictogram ( ghsPollu, extra ) + else + return "Unknown Pictogram »" .. inPictogram .. "«!" + end +end + +function ghsSinglePictogram ( pictogram, extra ) + return "\\includegraphics[width=\\@HazardousPictogramSize" .. ( "," .. extra or "" ) .. "]" + .. ( "{"..source.."assets/pictograms/ghs/%02d.pdf}" ):format ( pictogram ) +end + +function ghsStatements ( ghs ) + if not next ( ghs.hazards ) + and not next ( ghs.euHazards ) + and not next ( ghs.precautions ) + then + tex.print ( "H: —, P: —" ) + else + ghsHazards ( ghs ) + ghsEUHazards ( ghs ) + ghsPrecautions ( ghs ) + end +end diff --git a/NixTeX/dependencies/source/lua/hazardous/ghs/hazards.lua b/NixTeX/dependencies/source/lua/hazardous/ghs/hazards.lua new file mode 100644 index 0000000..f575b1b --- /dev/null +++ b/NixTeX/dependencies/source/lua/hazardous/ghs/hazards.lua @@ -0,0 +1,82 @@ +function ghsHazards ( ghs ) + local options = "" + if next( ghs.hazards) + then + for index, value in ipairs(ghs.hazards) + do + if type ( value ) == "number" + then + value = tostring ( value ) + elseif type ( value ) == "table" + then + if value.organs ~= nil + then + options = options .. "organs=" .. value.organs + end + if value.effect ~= nil + then + options = options .. "effect=" .. value.effect + end + if value.exposure ~= nil + then + options = options .. "exposure=" .. value.exposure + end + value = tostring ( value.id ) + end + if options == "" + then + tex.print("\\ghs{h}{"..value.."}") + else + tex.print("\\ghs["..options.."]{h}{"..value.."}") + end + end + tex.print(tex.newline) + end +end + +local statements += { + [ "deu" ] + = { + + }, + [ "eng" ] + = { + [ "200" ] = "Unstable explosive.", + [ "201" ] = "Explosive; mass explosion hazard.", + [ "202" ] = "Explosive; severe projection hazard.", + [ "203" ] = "Explosive; fire, blast or projection hazard.", + [ "204" ] = "Fire or projection hazard.", + [ "205" ] = "May mass explode in fire.", + [ "206" ] = "Fire, blast or projection hazard: increased risk of explosion if desensitizing agent is reduced.", + [ "207" ] = "Fire or projection hazard: increased risk of explosion if desensitizing agent is reduced.", + [ "208" ] = "Fire hazard: increased risk of explosion if desensitizing agent is reduced.", + [ "220" ] = "Extremely flammable gas.", + [ "221" ] = "Flammable gas.", + [ "222" ] = "Extremely flammable aerosol.", + [ "223" ] = "Flammable aerosol.", + [ "224" ] = "Extremely flammable liquid and vapour.", + [ "225" ] = "Highly flammable liquid and vapour.", + [ "226" ] = "Flammable liquid and vapour.", + [ "227" ] = "Combustible liquid.", + [ "228" ] = "Flammable solid.", + [ "229" ] = "Pressurized container: may burst if heated.", + [ "230" ] = "May react explosively even in the absence of air.", + [ "231" ] = "May react explosively even in the absence of air at elevated pressure and/or temperature.", + [ "232" ] = "May ignite spontaneously if exposed to air.", + [ "240" ] = "Heating may cause an explosion.", + [ "241" ] = "Heating may cause a fire or explosion.", + [ "242" ] = "Heating may cause a fire.", + [ "250" ] = "Catches fire spontaneously if exposed to air.", + [ "251" ] = "Self-heating; may catch fire.", + [ "252" ] = "Self-heating in large quantities; may catch fire.", + [ "260" ] = "In contact with water releases flammable gases which may ignite spontaneously.", + [ "261" ] = "In contact with water releases flammable gas.", + [ "270" ] = "May cause or intensify fire; oxidizer.", + [ "271" ] = "May cause fire or explosion; strong oxidizer.", + [ "272" ] = "May intensify fire; oxidizer.", + [ "280" ] = "Contains gas under pressure; may explode if heated.", + [ "281" ] = "Contains refrigerated gas; may cause cryogenic burns or injury.", + [ "290" ] = "May be corrosive to metals.", + }, + } diff --git a/NixTeX/dependencies/source/lua/hazardous/ghs/precautions.lua b/NixTeX/dependencies/source/lua/hazardous/ghs/precautions.lua new file mode 100644 index 0000000..7ffd76a --- /dev/null +++ b/NixTeX/dependencies/source/lua/hazardous/ghs/precautions.lua @@ -0,0 +1,44 @@ +function ghsPrecautions ( ghs ) + local options = "" + if next(hazardousData.ghs.precautions) + then + for index, value in ipairs(ghs.precautions) + do + if type ( value ) == "number" + then + value = tostring ( value ) + elseif type ( value ) == "table" + then + if value.text ~= nil + then + options = options .. "text=" .. value.text + end + if value.dots ~= nil + then + options = options .. "dots=" .. value.dots + end + if value.tempC ~= nil + then + options = options .. "C-termperature=" .. value.tempC + elseif value.tempF ~= nil + then + options = options .. "F-termperature=" .. value.tempF + end + if value.massKG ~= nil + then + options = options .. "kg-mass=" .. value.massKG + elseif value.massLBS ~= nil + then + options = options .. "lbs-mass=" .. value.massLBS + end + value = tostring ( value.id ) + end + if options == "" + then + tex.print("\\ghs{p}{"..value.."}") + else + tex.print("\\ghs["..options.."]{p}{"..value.."}") + end + end + end +end diff --git a/NixTeX/dependencies/source/lua/hazardous/ghs/signals.lua b/NixTeX/dependencies/source/lua/hazardous/ghs/signals.lua new file mode 100644 index 0000000..cd4b4db --- /dev/null +++ b/NixTeX/dependencies/source/lua/hazardous/ghs/signals.lua @@ -0,0 +1,6 @@ +ghsWarnings = {} +ghsWarnings["DE"] = { "", "Achtung", "Gefahr", } + +function ghsSignal ( ghs ) + return "\\textbf{" .. ghsWarnings [ "DE" ] [ ghs.signal ] .. "}" +end diff --git a/NixTeX/dependencies/source/lua/hazardous/hazardous.lua b/NixTeX/dependencies/source/lua/hazardous/hazardous.lua new file mode 100644 index 0000000..5993656 --- /dev/null +++ b/NixTeX/dependencies/source/lua/hazardous/hazardous.lua @@ -0,0 +1,702 @@ +includeCode ( "hazardous/iso7010" ) + +hazardousADR = false +hazardousADRplate = false +hazardousGHS = true +hazardousISO7010 = false +hazardousNFPA704 = false + +hazardous = { } +hazardous [ "blueprint" ] += { + name = + { + deu = "", + eng = "", + }, + -- empty values like "" and {} are all optional and should be either removed or filled + label = "", + physical + = { + formula = {}, -- Formula + density = 0, -- g·ml⁻¹ + nD20 = 0, -- + melting = 0, -- °C + boiling = 0, -- °C + decompose = 0, -- °C + }, + ghs + = { + hazards = {}, + euHazards = {}, + precautions = {}, + pictograms = { ghsExplosive, ghsFlame, ghsOFlame, ghsBottle, ghsAcid, ghsSkull, ghsExclam, ghsHealth, ghsPollu, }, + -- not optional: + signal = ghsDanger, + }, + iso7010 + = { + warnings = { 10, }, + }, + nfpa + = { + fire = 0, + health = 0, + reaction = 0, + other = nfpaNone, + }, + ecNumber = "", -- either European Community number + ufIdentifier = "XXXX-XXXX-XXXX-XXXX", -- or Unique Formula Identifier + casNumber = "", -- and Chemical Abstracts Service identifier + -- Accord européen relatif au transport international des marchandises Dangereuses par Route (ADR) + -- Règlement concernant le transport international ferroviaire de marchandises Dangereuses (RID) + unNumber = 1337, + kemler = -123, + hazardClass + = { + { + class = hazardClassExplosive, + subClass = 1, -- only if applicable, e.g. not 3 or 8 + compatibility = hazardCompatibilityX, -- compatibility group, only for explosives + contents = "", -- material, only radioactive material + activity = 0, -- Bq·kg⁻¹, only radioactive material, use \hazardousMassAndIndex + index = 0, -- transport index, only radioactive material, use \hazardousMassAndIndex + }, + }, + source = "gestis", -- replace with actual source or list of sources: { "one", "two", … } + update = "2020-02-17", + } + +function getHazardous ( name ) + local result + = hazardous [ name ] + or { + name = + { + deu = "Unbekannter Gefahrenstoff: »"..name.."«", + eng = "Unknown Hazardous Substance: »"..name.."«", + }, + ghs = {}, + iso7010 = {}, + nfpa = {}, + source = {}, + update = "never", + unknown = true + } + + -- name + if result.name ~= nil + and result.name.deu ~= nil + and result.name.deu ~= "" + then + result.title = result.name.deu + elseif result.name ~= nil + and result.name.eng ~= nil + and result.name.eng ~= "" + then + result.title = result.name.eng + else + result.title = "Unnamed Hazardous Substance" + end + + result.label = result.label or "" + result.physical = result.physical or {} + + if result.ufIdentifier == nil + or result.ufIdentifier == "" + then + -- European Community number + if result.ecNumber == nil + or result.ecNumber == "" + then + result.ecNumber = "—" + end + -- Chemical Abstracts Service identifier + if result.casNumber == nil + or result.casNumber == "" + then + result.casNumber = "—" + end + end + + -- source + if result.source == nil + then + log.warn + ( + "gethazardousData", + "›" .. result.name .. "‹ does not have a source!" + ) + result.source = {} + end + + -- date of last update + if result.update == nil + then + log.warn + ( + "gethazardousData", + "please update ›" .. result.name .. "‹!" + ) + result.update = "never" + end + + result = adrData ( result ) + result.ghs = ghsData ( result ) + result.iso7010 = iso7010data ( result ) + result.nfpa = nfpaData ( result ) + + return result +end + +function hazardousMolar ( list ) + local formula = "" + local mass = 0 + local previous = 0 + for index, value in ipairs ( list ) + do + if type ( value ) == "number" + then + formula = formula .. tostring ( value ) + if previous ~= 0 + then + mass = mass + previous * value + previous = 0 + end + elseif type ( value ) == "string" + then + mass = mass + previous + if chemicalElements [ value ] ~= nil + then + formula = formula .. value + previous = chemicalElements [ value ].mass + elseif value == "." + or value == "-" + then + formula = formula .. value + previous = 0 + else + log.error + ( + "hazardousMolar", + "Unknown Chemical Element ›" .. value .. "‹" + ) + end + elseif type ( value ) == "table" + then + mass = mass + previous + local resultFormula, resultMass = hazardousMolar(value) + formula = formula .. "(" .. resultFormula .. ")" + previous = resultMass + else + log.error + ( + "hazardousMolar", + "Unexpected value ›" .. tostring ( value ) .. "‹ of type ›" .. type ( value ) .. "‹" + ) + end + end + return formula, mass + previous +end + +function hazardousPhysicals(hazPurity, hazardousData) + local result = "" + if hazPurity + then + result = ", " + end + if hazardousData.physical.formula ~= nil + and type ( hazardousData.physical.formula ) == "table" + and #hazardousData.physical.formula > 0 + then + local formula, mass = hazardousMolar(hazardousData.physical.formula) + result = result .. "\\ch{"..formula.."}, " + result = result .. "\\Physical[2]{"..tostring(mass).."}{}{gram}{}" + result = result .. "\\Unit{mol}{-1}" + end + if hazardousData.physical.density ~= nil + then + if result ~= "" + then + result = result .. ", " + end + result = result .. "\\Physical[2]{"..tostring(hazardousData.physical.density).."}{}{gram}{}" + result = result .. "\\Unit{millilitre}{-1}" + end + if hazardousData.physical.nD20 ~= nil + then + if result ~= "" + then + result = result .. ", " + end + result = result .. "\\acrshort{nD20}~" + result = result .. "\\Physical[4]{"..tostring(hazardousData.physical.nD20).."}{}{}{}" + end + if hazardousData.physical.pH ~= nil + and tostring(hazardousData.physical.pH) ~= nil + then + if result ~= "" + then + result = result .. ", " + end + result = result .. "pH~" + result = result .. "\\Physical[2]{"..tostring(hazardousData.physical.pH).."}{}{}{}" + end + if hazardousData.physical.melting ~= nil + then + if result ~= "" + then + result = result .. ", " + end + result = result .. "\\acrshort{meltingTemperature}~" + result = result .. "\\Physical[0]{"..tostring(hazardousData.physical.melting).."}{}{celsius}{}" + end + if hazardousData.physical.boiling ~= nil + then + if result ~= "" + then + result = result .. ", " + end + result = result .. "\\acrshort{boilingTemperature}~" + result = result .. "\\Physical[0]{"..tostring(hazardousData.physical.boiling).."}{}{celsius}{}" + end + if hazardousData.physical.decompose ~= nil + then + if result ~= "" + then + result = result .. ", " + end + result = result .. "\\acrshort{decompositionTemperature}~" + result = result .. "\\Physical[0]{"..tostring(hazardousData.physical.decompose).."}{}{celsius}{}" + end + if result ~= "" + then + log.trace + ( + "hazardousPhysicals", + "Result: " .. result + ) + tex.print(result) + end +end + +function hazardousPictograms ( hazardousData, width ) + local result = "" + local width = tonumber ( width ) or 0 + local pictograms = {} + if hazardousGHS + then + ghsPictograms ( hazardousData.ghs, pictograms ) + end + if hazardousNFPA704 + then + nfpaPictograms ( hazardousData.nfpa, pictograms ) + end + if hazardousADR + then + adrPlate = adrPictograms ( hazardousData, pictograms ) + end + if hazardousISO7010 + then + iso7010Pictrograms ( hazardousData.iso7010, pictograms ) + end + if width == 1.5 + and #pictograms >= 1 + and #pictograms <= 16 + then + result = pictograms [ 1 ] + result = result .. hazardousPictogramsFill ( pictograms, 2 ) + result = result .. hazardousPictogramsSkip ( pictograms, 3 ) + result = result .. hazardousPictogramsFill ( pictograms, 4 ) + result = result .. hazardousPictogramsSkip ( pictograms, 5 ) + result = result .. hazardousPictogramsFill ( pictograms, 6 ) + result = result .. hazardousPictogramsSkip ( pictograms, 7 ) + result = result .. hazardousPictogramsFill ( pictograms, 8 ) + result = result .. hazardousPictogramsSkip ( pictograms, 9 ) + result = result .. hazardousPictogramsFill ( pictograms, 10 ) + result = result .. hazardousPictogramsSkip ( pictograms, 11 ) + result = result .. hazardousPictogramsFill ( pictograms, 12 ) + result = result .. hazardousPictogramsSkip ( pictograms, 13 ) + result = result .. hazardousPictogramsFill ( pictograms, 14 ) + result = result .. hazardousPictogramsSkip ( pictograms, 15 ) + if ( #pictograms % 2 ) == 1 + then + result + = result + .. "\\hspace{.5\\@HazardousPictogramSep}" + .. "\\hspace{.5\\@HazardousPictogramSize}" + .. "\\mbox{}" + end + elseif width == 2.0 + and #pictograms >= 1 + and #pictograms <= 15 + then + result = pictograms [ 1 ] + if ( #pictograms % 3 ) ~= 1 + then + result = result .. hazardousPictogramsStep ( pictograms, 2 ) + result = result .. hazardousPictogramsSkip ( pictograms, 3 ) + result = result .. hazardousPictogramsSkip ( pictograms, 4 ) + result = result .. hazardousPictogramsStep ( pictograms, 5 ) + result = result .. hazardousPictogramsSkip ( pictograms, 6 ) + result = result .. hazardousPictogramsSkip ( pictograms, 7 ) + result = result .. hazardousPictogramsStep ( pictograms, 8 ) + result = result .. hazardousPictogramsSkip ( pictograms, 9 ) + result = result .. hazardousPictogramsSkip ( pictograms, 10 ) + result = result .. hazardousPictogramsStep ( pictograms, 11 ) + result = result .. hazardousPictogramsSkip ( pictograms, 12 ) + result = result .. hazardousPictogramsStep ( pictograms, 13 ) + result = result .. hazardousPictogramsStep ( pictograms, 14 ) + result = result .. hazardousPictogramsStep ( pictograms, 15 ) + else + result = result .. hazardousPictogramsSkip ( pictograms, 2 ) + result = result .. hazardousPictogramsStep ( pictograms, 3 ) + result = result .. hazardousPictogramsSkip ( pictograms, 4 ) + result = result .. hazardousPictogramsSkip ( pictograms, 5 ) + result = result .. hazardousPictogramsStep ( pictograms, 6 ) + result = result .. hazardousPictogramsSkip ( pictograms, 7 ) + result = result .. hazardousPictogramsSkip ( pictograms, 8 ) + result = result .. hazardousPictogramsStep ( pictograms, 9 ) + result = result .. hazardousPictogramsSkip ( pictograms, 10 ) + result = result .. hazardousPictogramsSkip ( pictograms, 11 ) + result = result .. hazardousPictogramsStep ( pictograms, 12 ) + result = result .. hazardousPictogramsSkip ( pictograms, 13 ) + result = result .. hazardousPictogramsSkip ( pictograms, 14 ) + result = result .. hazardousPictogramsStep ( pictograms, 15 ) + end + elseif width == 2.5 + and #pictograms >= 1 + and #pictograms <= 15 + then + result = pictograms [ 1 ] + result = result .. hazardousPictogramsStep ( pictograms, 2 ) + result = result .. hazardousPictogramsFill ( pictograms, 3 ) + result = result .. hazardousPictogramsStep ( pictograms, 4 ) + result = result .. hazardousPictogramsSkip ( pictograms, 5 ) + result = result .. hazardousPictogramsStep ( pictograms, 6 ) + result = result .. hazardousPictogramsFill ( pictograms, 7 ) + result = result .. hazardousPictogramsStep ( pictograms, 8 ) + result = result .. hazardousPictogramsSkip ( pictograms, 9 ) + result = result .. hazardousPictogramsStep ( pictograms, 10 ) + result = result .. hazardousPictogramsFill ( pictograms, 11 ) + result = result .. hazardousPictogramsStep ( pictograms, 12 ) + result = result .. hazardousPictogramsSkip ( pictograms, 13 ) + result = result .. hazardousPictogramsStep ( pictograms, 14 ) + result = result .. hazardousPictogramsFill ( pictograms, 15 ) + result = result .. hazardousPictogramsStep ( pictograms, 16 ) + result + = result + .. "\\hspace{.5\\@HazardousPictogramSep}" + .. "\\hspace{.5\\@HazardousPictogramSize}" + .. "\\mbox{}" + if ( #pictograms % 2 ) == 1 + then + result + = result + .. "\\hspace{.5\\@HazardousPictogramSep}" + .. "\\hspace{.5\\@HazardousPictogramSize}" + .. "\\mbox{}" + end + elseif width == 3.0 + and #pictograms >= 1 + and #pictograms <= 15 + then + result = pictograms [ 1 ] + local rest = ( #pictograms % 5 ) + if rest == 2 + then + result = result .. hazardousPictogramsStep ( pictograms, 2 ) + result = result .. hazardousPictogramsSkip ( pictograms, 3 ) + result = result .. hazardousPictogramsStep ( pictograms, 4 ) + result = result .. hazardousPictogramsStep ( pictograms, 5 ) + result = result .. hazardousPictogramsSkip ( pictograms, 6 ) + result = result .. hazardousPictogramsStep ( pictograms, 7 ) + result = result .. hazardousPictogramsSkip ( pictograms, 8 ) + result = result .. hazardousPictogramsStep ( pictograms, 9 ) + result = result .. hazardousPictogramsStep ( pictograms, 10 ) + result = result .. hazardousPictogramsSkip ( pictograms, 11 ) + result = result .. hazardousPictogramsStep ( pictograms, 12 ) + result = result .. hazardousPictogramsSkip ( pictograms, 13 ) + result = result .. hazardousPictogramsStep ( pictograms, 14 ) + result = result .. hazardousPictogramsStep ( pictograms, 15 ) + result = result .. hazardousPictogramsSkip ( pictograms, 16 ) + elseif rest == 4 + then + result + = result + .. "\\hspace{\\@HazardousPictogramSep}" + .. "\\hspace{\\@HazardousPictogramSize}" + result = result .. hazardousPictogramsStep ( pictograms, 2 ) + result = result .. hazardousPictogramsSkip ( pictograms, 3 ) + result = result .. hazardousPictogramsStep ( pictograms, 4 ) + result = result .. hazardousPictogramsSkip ( pictograms, 5 ) + result = result .. hazardousPictogramsStep ( pictograms, 6 ) + result = result .. hazardousPictogramsStep ( pictograms, 7 ) + result = result .. hazardousPictogramsSkip ( pictograms, 8 ) + result = result .. hazardousPictogramsStep ( pictograms, 9 ) + result = result .. hazardousPictogramsSkip ( pictograms, 10 ) + result = result .. hazardousPictogramsStep ( pictograms, 11 ) + result = result .. hazardousPictogramsStep ( pictograms, 12 ) + result = result .. hazardousPictogramsSkip ( pictograms, 13 ) + result = result .. hazardousPictogramsStep ( pictograms, 14 ) + result = result .. hazardousPictogramsSkip ( pictograms, 15 ) + result = result .. hazardousPictogramsStep ( pictograms, 16 ) + else + result = result .. hazardousPictogramsStep ( pictograms, 2 ) + result = result .. hazardousPictogramsStep ( pictograms, 3 ) + result = result .. hazardousPictogramsSkip ( pictograms, 4 ) + result = result .. hazardousPictogramsStep ( pictograms, 5 ) + result = result .. hazardousPictogramsSkip ( pictograms, 6 ) + result = result .. hazardousPictogramsStep ( pictograms, 7 ) + result = result .. hazardousPictogramsStep ( pictograms, 8 ) + result = result .. hazardousPictogramsSkip ( pictograms, 9 ) + result = result .. hazardousPictogramsStep ( pictograms, 10 ) + result = result .. hazardousPictogramsSkip ( pictograms, 11 ) + result = result .. hazardousPictogramsStep ( pictograms, 12 ) + result = result .. hazardousPictogramsStep ( pictograms, 13 ) + result = result .. hazardousPictogramsSkip ( pictograms, 14 ) + result = result .. hazardousPictogramsStep ( pictograms, 15 ) + result = result .. hazardousPictogramsSkip ( pictograms, 16 ) + end + elseif width == 3.5 + and #pictograms >= 1 + and #pictograms <= 15 + then + result = pictograms [ 1 ] + result = result .. hazardousPictogramsStep ( pictograms, 2 ) + result = result .. hazardousPictogramsStep ( pictograms, 3 ) + result = result .. hazardousPictogramsFill ( pictograms, 4 ) + result = result .. hazardousPictogramsStep ( pictograms, 5 ) + result = result .. hazardousPictogramsStep ( pictograms, 6 ) + result = result .. hazardousPictogramsSkip ( pictograms, 7 ) + result = result .. hazardousPictogramsStep ( pictograms, 8 ) + result = result .. hazardousPictogramsStep ( pictograms, 9 ) + result = result .. hazardousPictogramsFill ( pictograms, 10 ) + result = result .. hazardousPictogramsStep ( pictograms, 11 ) + result = result .. hazardousPictogramsStep ( pictograms, 12 ) + result = result .. hazardousPictogramsSkip ( pictograms, 13 ) + result = result .. hazardousPictogramsStep ( pictograms, 14 ) + result = result .. hazardousPictogramsStep ( pictograms, 15 ) + result = result .. hazardousPictogramsFill ( pictograms, 16 ) + result + = result + .. "\\hspace{.5\\@HazardousPictogramSep}" + .. "\\hspace{.5\\@HazardousPictogramSize}" + .. "\\mbox{}" + if ( #pictograms % 3 ) == 1 + then + result + = result + .. "\\hspace{1.5\\@HazardousPictogramSep}" + .. "\\hspace{1.5\\@HazardousPictogramSize}" + .. "\\mbox{}" + end + elseif width == 4.0 + and #pictograms >= 1 + and #pictograms <= 15 + then + local rest = ( #pictograms % 7 ) + if rest == 1 + then + result = pictograms [ 1 ] + result = result .. hazardousPictogramsStep ( pictograms, 2 ) + result = result .. hazardousPictogramsStep ( pictograms, 3 ) + result = result .. hazardousPictogramsSkip ( pictograms, 4 ) + result + = result + .. "\\hspace{2\\@HazardousPictogramSep}" + .. "\\hspace{2\\@HazardousPictogramSize}" + result = result .. hazardousPictogramsStep ( pictograms, 5 ) + result = result .. hazardousPictogramsSkip ( pictograms, 6 ) + result = result .. hazardousPictogramsStep ( pictograms, 7 ) + result = result .. hazardousPictogramsStep ( pictograms, 8 ) + result = result .. hazardousPictogramsSkip ( pictograms, 9 ) + result = result .. hazardousPictogramsStep ( pictograms, 10 ) + result = result .. hazardousPictogramsStep ( pictograms, 11 ) + result = result .. hazardousPictogramsStep ( pictograms, 12 ) + result = result .. hazardousPictogramsSkip ( pictograms, 13 ) + result = result .. hazardousPictogramsStep ( pictograms, 14 ) + result = result .. hazardousPictogramsStep ( pictograms, 15 ) + result = result .. hazardousPictogramsSkip ( pictograms, 16 ) + result = result .. hazardousPictogramsStep ( pictograms, 17 ) + elseif rest == 3 + then + result = pictograms [ 1 ] + result = result .. hazardousPictogramsStep ( pictograms, 2 ) + result = result .. hazardousPictogramsStep ( pictograms, 3 ) + result = result .. hazardousPictogramsSkip ( pictograms, 4 ) + result = result .. hazardousPictogramsStep ( pictograms, 5 ) + result = result .. hazardousPictogramsStep ( pictograms, 6 ) + result = result .. hazardousPictogramsStep ( pictograms, 7 ) + result = result .. hazardousPictogramsSkip ( pictograms, 8 ) + result = result .. hazardousPictogramsStep ( pictograms, 9 ) + result = result .. hazardousPictogramsStep ( pictograms, 10 ) + result = result .. hazardousPictogramsSkip ( pictograms, 11 ) + result = result .. hazardousPictogramsStep ( pictograms, 12 ) + result = result .. hazardousPictogramsStep ( pictograms, 13 ) + result = result .. hazardousPictogramsStep ( pictograms, 14 ) + result = result .. hazardousPictogramsSkip ( pictograms, 15 ) + result = result .. hazardousPictogramsStep ( pictograms, 16 ) + result = result .. hazardousPictogramsStep ( pictograms, 17 ) + elseif rest == 5 + then + result + = result + .. "\\hspace{\\@HazardousPictogramSep}" + .. "\\hspace{\\@HazardousPictogramSize}" + result = pictograms [ 1 ] + result = result .. hazardousPictogramsStep ( pictograms, 2 ) + result + = result + .. "\\hspace{\\@HazardousPictogramSep}" + .. "\\hspace{\\@HazardousPictogramSize}" + result = result .. hazardousPictogramsSkip ( pictograms, 3 ) + result = result .. hazardousPictogramsStep ( pictograms, 4 ) + result = result .. hazardousPictogramsStep ( pictograms, 5 ) + result = result .. hazardousPictogramsSkip ( pictograms, 6 ) + result = result .. hazardousPictogramsStep ( pictograms, 7 ) + result = result .. hazardousPictogramsStep ( pictograms, 8 ) + result = result .. hazardousPictogramsStep ( pictograms, 9 ) + result = result .. hazardousPictogramsSkip ( pictograms, 10 ) + result = result .. hazardousPictogramsStep ( pictograms, 11 ) + result = result .. hazardousPictogramsStep ( pictograms, 12 ) + result = result .. hazardousPictogramsSkip ( pictograms, 13 ) + result = result .. hazardousPictogramsStep ( pictograms, 14 ) + result = result .. hazardousPictogramsStep ( pictograms, 15 ) + result = result .. hazardousPictogramsStep ( pictograms, 16 ) + result = result .. hazardousPictogramsSkip ( pictograms, 17 ) + else + result = pictograms [ 1 ] + result = result .. hazardousPictogramsStep ( pictograms, 2 ) + result = result .. hazardousPictogramsStep ( pictograms, 3 ) + result = result .. hazardousPictogramsStep ( pictograms, 4 ) + result = result .. hazardousPictogramsSkip ( pictograms, 5 ) + result = result .. hazardousPictogramsStep ( pictograms, 6 ) + result = result .. hazardousPictogramsStep ( pictograms, 7 ) + result = result .. hazardousPictogramsSkip ( pictograms, 8 ) + result = result .. hazardousPictogramsStep ( pictograms, 9 ) + result = result .. hazardousPictogramsStep ( pictograms, 10 ) + result = result .. hazardousPictogramsStep ( pictograms, 11 ) + result = result .. hazardousPictogramsSkip ( pictograms, 12 ) + result = result .. hazardousPictogramsStep ( pictograms, 13 ) + result = result .. hazardousPictogramsStep ( pictograms, 14 ) + result = result .. hazardousPictogramsSkip ( pictograms, 15 ) + result = result .. hazardousPictogramsStep ( pictograms, 16 ) + result = result .. hazardousPictogramsStep ( pictograms, 17 ) + end + else + for index, pictogram in ipairs ( pictograms ) + do + result + = result .. pictogram .. "\\hspace{\\@HazardousPictogramSep}" + end + end + if hazardousADRplate + then + result = result .. adrPlate + end + result = "\\makeatletter" .. result .. "\\makeatother" + log.info + ( + "hazardousPictograms", + "result: »" .. result .. "«" + ) + tex.print ( result ) +end + +function hazardousPictogramsFill ( pictograms, level ) + if #pictograms >= level + then + return "\\hspace{\\@HazardousPictogramSep}" + .. "\\hspace{.5\\@HazardousPictogramSize}" + .. "\\mbox{}" + .. tex.newline .. "[-3\\normalbaselineskip]" + .. "\\hspace{.5\\@HazardousPictogramSize}" + .. "\\mbox{}" + .. pictograms [ level ] + else + return "" + end +end + +function hazardousPictogramsSkip ( pictograms, level ) + if #pictograms >= level + then + return tex.newline .. "[-3\\normalbaselineskip]" .. pictograms [ level ] + else + return "" + end +end + +function hazardousPictogramsStep ( pictograms, level ) + if #pictograms >= level + then + return "\\hspace{\\@HazardousPictogramSep}" .. pictograms [ level ] + else + return "" + end +end + +function hazardousSignal ( hazardousData ) + tex.print ( ghsSignal ( hazardousData.ghs ) ) +end +function hazardousStatements ( hazardousData ) + ghsStatements ( hazardousData.ghs ) +end + +function hazardousTitle ( hazardousData ) + local sources = "" + if citations == true + then + for index, source in ipairs ( hazardousData.sources ) + do + sources = sources .. "\\cite{" .. tostring ( source ) .. "}" + end + end + local result = hazardousData.title .. sources + if hazardousData.label ~= "" + then + result = hypertarget ( hazardousData.label ) .. result + end + tex.print ( result ) +end + +function hazardousUFIorCASident ( hazardousData ) + if hazardousData.ufIdentifier == nil + or hazardousData.ufIdentifier == "" + then + tex.print ( hazardousData.casNumber ) + end +end + +function hazardousUFIorCAStitle ( hazardousData ) + if hazardousData.ufIdentifier == nil + or hazardousData.ufIdentifier == "" + then + -- EG is german, EC is english, … + tex.print ( "CAS:~" ) + else + tex.print ( "" ) + end +end + +function hazardousUFIorECident ( hazardousData ) + if hazardousData.ufIdentifier == nil + or hazardousData.ufIdentifier == "" + then + tex.print ( hazardousData.ecNumber ) + else + tex.print ( hazardousData.ufIdentifier ) + end +end + +function hazardousUFIorECtitle ( hazardousData ) + if hazardousData.ufIdentifier == nil + or hazardousData.ufIdentifier == "" + then + -- EG is german, EC is english, … + tex.print ( "EG-Nr:~" ) + else + tex.print ( "UFI:~" ) + end +end diff --git a/NixTeX/dependencies/source/lua/hazardous/iso7010.lua b/NixTeX/dependencies/source/lua/hazardous/iso7010.lua new file mode 100644 index 0000000..8fd03e7 --- /dev/null +++ b/NixTeX/dependencies/source/lua/hazardous/iso7010.lua @@ -0,0 +1,17 @@ +function iso7010data ( hazardousData ) + local result = hazardousData.iso7010 or {} + result.warnings = result.warnings or {} + return result +end + +function iso7010Pictrograms ( iso7010, pictograms ) + for index, pictogram in ipairs ( iso7010.warnings ) + do + table.insert + ( + pictograms, + "\\includegraphics[width=\\@HazardousPictogramSize]" + .. ( "{"..source.."/assets/pictograms/iso7010/warnings/%03d.pdf}" ):format ( pictogram ) + ) + end +end diff --git a/NixTeX/dependencies/source/lua/hazardous/nfpa.lua b/NixTeX/dependencies/source/lua/hazardous/nfpa.lua new file mode 100644 index 0000000..746489e --- /dev/null +++ b/NixTeX/dependencies/source/lua/hazardous/nfpa.lua @@ -0,0 +1,62 @@ +nfpaOthers += { + "", + "\\nfpaAsphyxiant", + "\\nfpaNoWater", + "\\nfpaOxidiser", + "\\nfpaAcid", + "\\nfpaAlkaline", + "\\nfpaBioHazard", + "\\nfpaCryogenic", + "\\nfpaEcoHazard", + "\\nfpaEtching", + "\\nfpaExplosive", + "\\nfpaHot", + "\\nfpaRadioactive", + "\\nfpaToxic", + } + +nfpaNone = 0x00 +nfpaAsphyxiant = 0x01 +nfpaNoWater = 0x02 +nfpaOxidiser = 0x03 +nfpaAcid = 0x04 +nfpaAlkaline = 0x05 +nfpaBioHazard = 0x06 +nfpaCorrosive = 0x07 +nfpaCryogenic = 0x08 +nfpaEcoHazard = 0x09 +nfpaExplosive = 0x0a +nfpaHot = 0x0b +nfpaRadioactive = 0x0c +nfpaToxic = 0x0d + +function nfpaData ( hazardousData ) + if hazardousData.nfpa ~= nil + and type ( hazardousData.nfpa ) == "table" + then + return { + fire = hazardousData.nfpa.fire or 0, + health = hazardousData.nfpa.health or 0, + reaction = hazardousData.nfpa.reaction or 0, + other = nfpaOthers [ hazardousData.nfpa.other ] or hazardousData.nfpa.other or "", + } + else + return nil + end +end + +function nfpaPictograms ( nfpa, pictograms ) + if nfpa ~= nil + then + table.insert + ( + pictograms, + "\\nfpaDiamond[\\@HazardousPictogramSize]" + .. "{" .. tostring ( nfpa.fire ) .. "}" + .. "{" .. tostring ( nfpa.health ) .. "}" + .. "{" .. tostring ( nfpa.reaction ) .. "}" + .. "{" .. tostring ( nfpa.other ) .. "}" + ) + end +end diff --git a/NixTeX/dependencies/source/lua/hiddentext.lua b/NixTeX/dependencies/source/lua/hiddentext.lua new file mode 100644 index 0000000..a6f32f4 --- /dev/null +++ b/NixTeX/dependencies/source/lua/hiddentext.lua @@ -0,0 +1,98 @@ +ignore += { + "0", + "1", + "2", + "3", + "4", + "5", + "6", + "7", + "8", + "9", + "a", "an", "and", "also", "are", "as", + "b", "be", "being", "bullshit", "but", + "c", "comes", + "d", + "e", + "f", "for", "freak", "fuck", + "g", "go", "goes", "going", + "h", "has", "have", "his", "her", + "i", "in", "into", "is", "it", + "j", + "k", + "l", + "m", + "n", + "o", "odd", "of", "on", "one", "or", "our", + "p", + "q", + "r", + "s", + "t", "take", "than", "that", "the", "then", "there", "this", "to", "too", + "u", + "v", + "w", "want", "was", "went", "we’re", "what", "when", "where", "will", "with", + "x", + "y", "you", "your", "you’re", + "z", + } + +keywords += { + "0", + "1", "1.0", "10 years", "11 years", "12 years", "13 years", "1337", "14 years", "15 years", + "2", "2 years", "2+ years", "23", + "3", "3 years", "3+ years", + "4", "4 years", "4+ years", "42", + "5", "5 years", "5+ years", + "6", "6 years", "6+ years", + "7", "7 years", "7+ years", + "8", "8 years", "8+ years", + "9", "9 years", "9+ years", + "A", "Admin", "Administrator", "agil", "agility", "AI", "amazon", "AMD", "android", "Apple", "artificial intelligence", "awk", + "B", "B.Sc.", "bachelor degree", "BASF", "bash", "big data", "blockchain", "browser", "business", + "C", "C++", "C\\#", "California Institute of Technology", "Chemnitz University of Technology", "Cobol", "code", "Columbia University", "Cornell University", "crypto", + "cryptography", "css", "customer", + "D", "data mining", "developer", "Dr.", + "E", "embedded", "ETH Zürich", "experience", + "F", "F\\#", "flexible", "fortran", "fourier", "future", + "G", "Go", "Google", + "H", "Harvard University", "Haskell", "html", "html5", + "I", "Imperial College London", "Intel", + "J", "java", "js", + "K", "Karlsruhe Institute of Technology", "KIT", + "L", "LaTeX", "luaLaTeX", "Linux", "Lisp", + "M", "M.Sc.", "machine learning", "Massachusetts Institute of Technology", "master degree", "Microsoft", "MIT", "mobile", + "N", "Nanyang Technological University", "National University of Singapore", + "O", "office", "online", + "P", "partner", "PDF", "perl", "PhD", "phone", "php", "Princeton University", "Prof.", "professional", "project manager", "Projektmanager", "python", + "Q", "quality", "quantum", + "R", "Ruby", "Rust", + "S", "Scala", "Senior", "sh", "Silcon Valley", "smart", "software architect", "software developer", "Stanford University", "success", "system", + "T", "team", "TeX", "time-to-market", "Tsinghua-Universität", "TypeScript", + "U", "University College London", "University of California, Berkeley", "University of Cambridge", "University of Chicago", "University of Edinburgh", "University of Michigan", + "University of Oxford", "University of Pennsylvania", "University of Sivicia", + "V", + "W", "Windows", + "X", "XeLaTeX", + "Y", "Yale University", + "Z", "zsh", + } + +seperators = " ?!.:,;()/&{}<>’" + +function hideKeywords(text) + for keyword in text:gmatch ( "[^"..seperators.."]+" ) + do + if ( not contains ( ignore, keyword ) ) + and ( not contains ( keywords, keyword ) ) + then + table.insert ( keywords, keyword ) + end + end + for index, keyword in ipairs ( keywords ) + do + tex.print ( keyword:gsub ( " ", "\\quad " ).."\\quad" ) + end +end diff --git a/NixTeX/dependencies/source/lua/logging.lua b/NixTeX/dependencies/source/lua/logging.lua new file mode 100644 index 0000000..31cd449 --- /dev/null +++ b/NixTeX/dependencies/source/lua/logging.lua @@ -0,0 +1,366 @@ +local logLevel += { + Trace = 6, -- here I am, if you really want to go that deep + Debug = 5, -- helpfull message for debugging, e.g. with values of variables + Info = 4, -- should not result in unexpected output, will not fail to compile + Warn = 3, -- might result in unexpected output, should not fail to compile + Error = 2, -- will result in unexpected output, might fail to compile + Dafuq = 1, -- internal errors + Silent = 0, -- be quite, be silent + } + +-- access by numeric level +logLevel.list += { + [ logLevel.Silent ] + = { + level = logLevel.Silent, + message = "SILENT", + colour = "97", -- white + }, + [ logLevel.Dafuq ] + = { + level = logLevel.Dafuq, + message = "DAFUQ", + colour = "95", -- pink + }, + [ logLevel.Error ] + = { + level = logLevel.Error, + message = "ERROR", + colour = "91", -- red + }, + [ logLevel.Warn ] + = { + level = logLevel.Warn, + message = "WARN", + colour = "93", -- yellow + }, + [ logLevel.Info ] + = { + level = logLevel.Info, + message = "INFO", + colour = "92", -- green + }, + [ logLevel.Debug ] + = { + level = logLevel.Debug, + message = "DEBUG", + colour = "96", -- blue + }, + [ logLevel.Trace ] + = { + level = logLevel.Trace, + message = "TRACE", + colour = "37", -- grey + }, + } + +-- access by stringly level +logLevel.map += { + [ "dafuq" ] = logLevel.list [ logLevel.Dafuq ], + [ "debug" ] = logLevel.list [ logLevel.Debug ], + [ "error" ] = logLevel.list [ logLevel.Error ], + [ "info" ] = logLevel.list [ logLevel.Info ], + [ "silent" ] = logLevel.list [ logLevel.Silent ], + [ "trace" ] = logLevel.list [ logLevel.Trace ], + [ "warn" ] = logLevel.list [ logLevel.Warn ], + } + +log += { + helpText = "", + files + = { + main = buildFiles.create ( "llg" ), + todo = buildFiles.create ( "todo" ), + }, + levels + = { + console = logLevel.Warn, + failure = logLevel.Dafuq, + file = logLevel.Trace, + pause = logLevel.Error, + }, + stepping = false, + statistics = { 0, 0, 0, 0, 0, 0 }, + } + +local function logThis ( source, lines, level, fatal ) + local fatal + = fatal + or ( + level.level > logLevel.Silent + and + level.level <= log.levels.failure + ) + + local pause = ( level.level <= log.levels.pause ) + + -- Always log fatal messages to console. + local logToConsole = fatal or ( level.level <= log.levels.console ) or pause + -- Always log fatal messages to file. + local logToFile = fatal or ( level.level <= log.levels.file ) + + -- only if necessary + if logToConsole + or logToFile + then + log.statistics [ level.level ] = log.statistics [ level.level ] + 1 + if type ( source ) == "table" + then + source = table.concat ( source, " → " ) + end + -- [level] {source} + -- | message line 0 + -- | message line 1 + local head + = "[" .. level.message .. "] " + .. "{" .. source .. "}\n" + + local consoleMessage = "" + local fileMessage = "" + for index, line in pairs ( lines ) + do + for line in line:gmatch ( "[^\n]+" ) + do + line = line:match ( "(.-)[ ]*$" ) + if line ~= "." + then + line + = "| " .. line .. "\n" + consoleMessage + = consoleMessage + .. escape .. "[" .. level.colour .. "m" .. line + fileMessage + = fileMessage .. line + end + end + end + + if logToFile and log.files.main ~= nil + then + log.files.main:write ( head .. fileMessage .. "\n" ) + --log.files.main:flush ( ) + end + + if logToConsole + then + texio.write_nl("") + print + ( + escape .. "[" .. level.colour .. "m" + .. head + .. consoleMessage + .. escape .. "[0m" + ) + if log.stepping + then + pause = true + end + end + + if ( fatal or pause ) + and log.helpText ~= "" + then + print ( escape .. "[94m| " .. log.helpText .. escape .. "[0m" ) + end + + if fatal + then + log.putStatistics ( ) + -- Fail Safe on fatal errors. + error ( "<>" ) + elseif pause + then + print("Press Enter/Return to continue…") + local result = io.read("*line") + if result:byte ( ) == 0x1b + then + log.putStatistics ( ) + error ( "<>" ) + end + return result + end + end + log.helpText = "" +end + +local function parseLogLevel ( level ) + local this = logLevel.map [ level ] + if this ~= nil + then + return this.level + else + log.error + ( + "parseLogLevel", + "Invalid Log Level »" .. level .. "«, valid are: trace, debug, info, warn, fail and silent" + ) + return nil + end +end + +function log.help ( text ) + log.helpText = tostring ( text ) +end + +--tex.define ( "logDafuq", "log.dafuq", 2 ) +function log.dafuq ( source, ... ) + return logThis ( source, { ... }, logLevel.list [ logLevel.Dafuq ], false ) +end + +--tex.define ( "logDebug", "log.debug", 2 ) +function log.debug ( source, ... ) + return logThis ( source, { ... }, logLevel.list [ logLevel.Debug ], false ) +end + +--tex.define ( "logError", "log.error", 2 ) +function log.error ( source, ... ) + return logThis ( source, { ... }, logLevel.list [ logLevel.Error ], false ) +end + +--tex.define ( "logFatal", "log.fatal", 2 ) +function log.fatal ( source, ... ) + -- try to avoid and use log.error instead. + -- use only, if you cannot recover. + logThis ( source, { ... }, logLevel.list [ logLevel.Error ], true ) +end + +--tex.define ( "logInfo", "log.info", 2 ) +function log.info ( source, ... ) + return logThis ( source, { ... }, logLevel.list [ logLevel.Info ], false ) +end + +--tex.define ( "logSilent", "log.silent", 2 ) +function log.silent ( source, ... ) + -- will not log anything, but might be somehow useful? + return logThis ( source, { ... }, logLevel.list [ logLevel.Silent ], false ) +end + +--tex.define ( "logTrace", "log.trace", 2 ) +function log.trace ( source, ... ) + return logThis ( source, { ... }, logLevel.list [ logLevel.Trace ], false ) +end + +--tex.define ( "logWarn", "log.warn", 2 ) +function log.warn ( source, ... ) + return logThis ( source, { ... }, logLevel.list [ logLevel.Warn ], false ) +end + +function log.todo ( ... ) + log.files.todo:write(table.concat({...}, "\n").."\n") + log.warn ( "<>", ... ) +end + +function log.setConsoleLevel ( level ) + if type ( level ) == "string" + then + level = parseLogLevel ( level ) + end + if level >= logLevel.Silent + and level <= logLevel.Trace + then + log.trace + ( + "log.setConsoleLevel", + "Set File Log Level to " .. tostring ( level ) + ) + log.levels.console = level + else + log.warn + ( + "log.setConsoleLevel", + "Log Level must be a Number Between 0 and 6" + ) + end +end + +function log.setFailureLevel ( level ) + if type ( level ) == "string" + then + level = parseLogLevel ( level ) + end + if level >= logLevel.Silent + and level <= logLevel.Trace + then + log.trace + ( + "log.setFailureLevel", + "Set File Log Level to " .. tostring ( level ) + ) + log.levels.failure = level + else + log.warn + ( + "log.setFailureLevel", + "Log Level must be a Number Between 0 and 6" + ) + end +end + +function log.setFileLevel ( level ) + if type ( level ) == "string" + then + level = parseLogLevel ( level ) + end + if level >= logLevel.Silent + and level <= logLevel.Trace + then + log.trace + ( + "log.setFileLevel", + "Set File Log Level to " .. tostring ( level ) + ) + log.levels.file = level + else + log.warn + ( + "log.setFileLevel", + "Log Level must be a Number Between 0 and 6" + ) + end +end + +function log.setPauseLevel ( level ) + if type ( level ) == "string" + then + level = parseLogLevel ( level ) + end + if level >= logLevel.Silent + and level <= logLevel.Trace + then + log.trace + ( + "log.setConsoleLevel", + "Set File Log Level to " .. tostring ( level ) + ) + log.levels.pause = level + else + log.warn + ( + "log.setConsoleLevel", + "Log Level must be a Number Between 0 and 6" + ) + end +end + +function log.putStatistics ( ) + local message + = "There were " + .. tostring ( log.statistics [ logLevel.Error ] ) .. " errors, " + .. tostring ( log.statistics [ logLevel.Warn ] ) .. " warnings, " + .. tostring ( log.statistics [ logLevel.Info ] ) .. " info-messages, " + .. tostring ( log.statistics [ logLevel.Debug ] ) .. " debug-messages, " + .. tostring ( log.statistics [ logLevel.Trace ] ) .. " traces and " + .. tostring ( log.statistics [ logLevel.Dafuq ] ) .. " fuck-ups." +end + +log.trace +( + jobname, + "Start Logging" +) + +io.output(buildFiles.create ( "lgo" )) diff --git a/NixTeX/dependencies/source/lua/math2unicode.lua b/NixTeX/dependencies/source/lua/math2unicode.lua new file mode 100644 index 0000000..ae25db1 --- /dev/null +++ b/NixTeX/dependencies/source/lua/math2unicode.lua @@ -0,0 +1,215 @@ +--- Replace these Commands with Unicode Character. +local CommandReplace += { + [ "m" ] = "µ", + } + +--- States of the Parser. +local States += { + Normal = 1, + SubScript = 2, + SubScriptGroup = 3, + SuperScript = 4, + SuperScriptGroup = 5, + Escape = 6, + Command = 7, + Argument = 8, + } + +local StateStack += { + [ States.Normal ] = { push = States.Normal, }, + [ States.SubScript ] = { push = States.SubScriptGroup, }, + [ States.SubScriptGroup ] = { push = States.SubScriptGroup, }, + [ States.SuperScript ] = { push = States.SuperScriptGroup, }, + [ States.SuperScriptGroup ] = { push = States.SuperScriptGroup, }, + -- States.Escape gets ignored anyway. + [ States.Command ] = { push = States.Argument, }, + } + +--- Ignore Style Commands, but Use its Argument. +local StyleCommands += { + "emph" = true, + "mathbf" = true, + "text" = true, + "textbf" = true, + "textit" = true, + "textrm" = true, + "textsc" = true, + "textsf" = true, + "texttt" = true, + "underline" = true, + } + +--- Replace Subscript Characters with Unicode Character. +local SubScripts += { + [ "0" ] = "₀", + [ "1" ] = "₁", + [ "2" ] = "₂", + [ "3" ] = "₃", + [ "4" ] = "₄", + [ "5" ] = "₅", + [ "6" ] = "₆", + [ "7" ] = "₇", + [ "8" ] = "₈", + [ "9" ] = "₉", + } + +--- Replace Superscript Characters with Unicode Character. +local SuperScripts += { + [ "0" ] = "⁰", + [ "1" ] = "¹", + [ "2" ] = "²", + [ "3" ] = "³", + [ "4" ] = "⁴", + [ "5" ] = "⁵", + [ "6" ] = "⁶", + [ "7" ] = "⁷", + [ "8" ] = "⁸", + [ "9" ] = "⁹", + } + +stack = {} + +function stack.new ( ) + return { + stack = { }, + pointer = 0, + } +end + +function table:peek ( ) + return self.stack [ self.pointer ] +end + +function table:pop ( ) + local result = self.stack [ self.pointer ] + self.pointer = self.pointer - 1 + return self, result +end + +function table:push ( value ) + self.pointer = self.pointer + 1 + self.stack [ self.pointer ] = value + return self +end + +function string:math2unicode ( ) + local output = "" + local state = States.Normal + local restate = stack.new ( ) + local depth = stack.new ( ) + local command = "" + for char in self:utf8split ( ) + do + if char == "{" + and state ~= States.Escape + then + state = StateStack [ state ].push + + elseif char == "}" + and state ~= States.Escape + then + -- … + elseif state == States.Normal + then + if char == "_" + then + state = States.SubScript + elseif char == "^" + then + state = States.SuperScript + elseif char == bs + then + state = States.Escape + restate = restate:push ( States.Normal ) + else + output = output .. char + end + elseif state == States.SubScript + then + state = States.Normal + output = output .. ( SubScripts [ char ] or char ) + elseif state == States.SubScriptGroup + then + output = output .. ( SubScripts [ char ] or char ) + elseif state == States.SuperScript + then + state = states.Normal + output = output .. ( SuperScripts [ char ] or char ) + elseif state == States.SuperScriptGroup + then + output = output .. ( SuperScripts [ char ] or char ) + elseif state == States.Escape + then + if ( ( char >= "A" ) and ( char <= "Z" ) ) + or ( ( char >= "a" ) and ( char <= "z" ) ) + then + command = char + state = States.Command + else + output = output .. char + state = restate + end + elseif state == States.Command + then + if ( ( char >= "A" ) and ( char <= "Z" ) ) + or ( ( char >= "a" ) and ( char <= "z" ) ) + then + command = command .. char + else + if char == " " + then + char = "" + elseif char == bs + then + -- \cmd0\cmd0 + -- ^ + char = "" + state = States.Escape + else + restate, state = restate:pop ( ) + if state == States.Normal + then + if char == "_" + then + char = "" + state = States.SubScript + elseif char == "^" + then + char = "" + state = States.SuperScript + end + end + end + output + = output + .. ( CommandReplace [ command ] or ( bs .. command ) ) + .. char + end + elseif state == States.Argument + then + restate, state = restate:pop ( ) + if StyleCommands [ command ] ~= nil + then + output = output .. char + else + output + = output + .. ( CommandReplace [ command ] or ( bs .. command ) ) + .. char + end + else + log.fatal + ( + "math2unicode", + "Invalid State: " .. tonumber ( state ) + ) + end + end + return output +end diff --git a/NixTeX/dependencies/source/lua/rate.lua b/NixTeX/dependencies/source/lua/rate.lua new file mode 100644 index 0000000..22823de --- /dev/null +++ b/NixTeX/dependencies/source/lua/rate.lua @@ -0,0 +1,26 @@ +function rateFullStars ( stars, maximum ) + stars = eval(stars) + maximum = eval(maximum) + assert + ( + stars ~= nil and maximum ~= nil, + "cannot print full stars: " .. stars .. " – " .. maximum + ) + full = math.floor(stars*maximum) + rest = maximum - full + tex.print (("\\faStar"):rep(full)..("\\faStarO"):rep(rest)) +end + +function rateHalfStars ( stars, maximum ) + stars = eval(stars) + maximum = eval(maximum) + assert + ( + stars ~= nil and maximum ~= nil, + "cannot print half stars: " .. stars .. " – " .. maximum + ) + full = math.floor(stars*maximum) + rest = math.floor((1-stars)*maximum) + half = maximum - full - rest + tex.print (("\\faStar"):rep(full)..("\\faStarHalfFull"):rep(half)..("\\faStarO"):rep(rest)) +end diff --git a/NixTeX/dependencies/source/lua/roman.lua b/NixTeX/dependencies/source/lua/roman.lua new file mode 100644 index 0000000..23def78 --- /dev/null +++ b/NixTeX/dependencies/source/lua/roman.lua @@ -0,0 +1,91 @@ +local numbers = { 1000, 500, 100, 50, 10, 5, 1 } +local chars = { "M", "D", "C", "L", "X", "V", "I" } + +local function convertToRoman ( value ) + local result = "" + for index, number in ipairs ( numbers ) + do + local times = math.floor ( value / number ) +-- print +-- ( +-- "Value: "..tostring(value) +-- ..", index|number: "..tostring(index).."|"..tostring(number) +-- ..", times: "..tostring(times) +-- ) + result = result .. chars [ index ]:rep ( times ) + value = value % number + for inner = #numbers, index + 1, -1 + do + local aux = numbers [ inner ] + local temp = number - aux +-- print +-- ( +-- "inner: "..tostring(inner) +-- ..", value: "..tostring(value) +-- ..", aux: "..tostring(aux) +-- ..", temp: "..tostring(temp) +-- ) + if value - temp >= 0 + and value < number + and value > 0 + and temp ~= aux + then +-- print ( "!" .. chars [ inner ] .. chars [ index ] ) + result = result .. chars [ inner ] .. chars [ index ] + value = value - temp + break + end + end + end + return result +end + +function toroman ( value ) + local value = tonumber ( value ) + if not value + or value ~= value + then + error("Input not a number") + elseif value == math.huge + or -value == math.huge + then + error("Input too large") + else + local value = math.floor ( value ) + if value == 0 + then + return "0" + elseif value < 0 + then + return "-" .. convertToRoman ( -value ) + else + return convertToRoman ( value ) + end + end +end + +if false +then + print("9876", toroman(9876), "MMMMMMMMMDCCCLXXVI") + print("944", toroman(944), "CMXLIV") + print("1", toroman(1), "I") + print("4", toroman(4), "IV") + print("5", toroman(5), "V") + print("6", toroman(6), "VI") + print("9", toroman(9), "IX") + print("501", toroman(501), "DI") + print("1024", toroman(1024), "MXXIV") + print("369", toroman(369), "CCCLXIX") + if false + then + print(3999999, toroman(3999999)) -- these two nuke the horizontal scroll bar... + print(4000000, toroman(4000000)) + print(math.huge, toroman(math.huge)) -- fails, which is good. + end + print(0, toroman(0), "0") + print(2012, toroman(2012), "MMXII") + print(99, toroman(99), "XCIX") + print(999, toroman(999), "CMXCIX") + print(1001, toroman(1001), "MI") + print(-2012, toroman(-2012), "-MMXII") +end diff --git a/NixTeX/dependencies/source/lua/tex.lua b/NixTeX/dependencies/source/lua/tex.lua new file mode 100644 index 0000000..f7e6da9 --- /dev/null +++ b/NixTeX/dependencies/source/lua/tex.lua @@ -0,0 +1,30 @@ +tex.newline = bs..bs + +function tex.define ( name, func, arguments, optional ) + if type ( arguments ) == "number" + and arguments > 0 + then + if arguments < 10 + then + local argumentString = "[[#1]]" + for index = 2, arguments + do + argumentString = argumentString .. ", [[#" .. tostring ( index ) .. "]]" + end + if optional + then + tex.print ( "\\newcommand{\\" .. name .. "}[" .. arguments .. "]{\\directlua{" .. func .. "(" .. argumentString .. ")}}") + else + tex.print ( "\\newcommand{\\" .. name .. "}[" .. arguments .. "][" .. tostring ( optional ) .. "]{\\directlua{" .. func .. "(" .. argumentString .. ")}}") + end + else + log.dafuq + ( + "tex.define", + "Cannot define tex-commands with more than 9 arguments." + ) + end + else + tex.print ( "\\def\\" .. name .. "{\\directlua{" .. func .. "()}}") + end +end diff --git a/NixTeX/dependencies/source/lua/text/spelling.lua b/NixTeX/dependencies/source/lua/text/spelling.lua new file mode 100644 index 0000000..9dbd0ee --- /dev/null +++ b/NixTeX/dependencies/source/lua/text/spelling.lua @@ -0,0 +1,996 @@ +local NewSentence += { + No = 0, + Maybe = 1, + Yes = 2, + Hyphen = 3, + } + +local function sentence ( newSentence ) + if newSentence == NewSentence.No + then + return "No" + elseif newSentence == NewSentence.Maybe + then + return "Maybe" + elseif newSentence == NewSentence.Yes + then + return "Yes" + elseif newSentence == NewSentence.Hyphen + then + return "Hyphen" + else + return "???" + end +end + +local NewSentenceAfterCommand += { + [ "," ] = NewSentence.No, + [ ";" ] = NewSentence.Maybe, + [ "." ] = NewSentence.Yes, + [ "-" ] = NewSentence.Hyphen, + [ "?" ] = false, + [ "!" ] = false, + } + +spellChecker += { + colours + = { + [ "typo" ] = "red", + }, + logFile = buildFiles.create ( "spell" ), + dictionaries = { }, + -- These command should be inside environments I do not touch. + -- Otherwise fail, because these commands have weird argument encodings like \cmd+<…>(…){}[…]+; + -- Parsing these command would bloat the code. + -- However, I will try to parse other commands, + -- that should only occur inside environments I do not touch. + failCommands + = { + [ "arrow" ] = true, + [ "draw" ] = true, + [ "makebraces" ] = true, + [ "Makebraces" ] = true, + }, + knownCommands + = { + -- If the command is not known, + -- optional arguments will be ignored and + -- mandatory arguments will be checked. + -- Otherwise while parsing the arguments, + -- the provided pattern will be used. + -- Note that weird command that take arguments in a form like \foo+(){}[]{}+ + -- cannot be parsed, + -- but they should occure only in special, ignored contexts anyway. + -- Nevertheless such commands should have the pattern "!" to tell the parser + -- to raise an exception. + -- If such commands are in not-ignored contexts, escape them with \correct. + -- String pattern are in the form of "([chi]*[,.][|])?[chi]*[-,;.?!]": + -- * c for caption: + -- this argument starts at the beginning of a sentence, + -- even if the macro is called in the middle of a sentence. + -- * h for here: + -- this argument will be placed here + -- * i for ignore: + -- this argument will be ignored + -- * , means: + -- text after this command is in the middle of a sentence + -- * . means: + -- text after this command is at the beginning of a sentence + -- * - means: + -- text after this command is after an hyphen + -- * ; means: + -- text after this command might be a new sentence + -- * ? means: + -- whether the text after this command is in the middle of a new sentence or not + -- depends on the last character of the last argument or on the context before. + -- * ! means: + -- raise an exception, this cannot be parsed + -- If the pattern is in the form of …|…, + -- the first part is for optionals and the second for mandatory arguments. + -- Otherwise optional arguments will be ignored and the pattern is for mandatory arguments. + [ "acrchem" ] = "!", + [ "acrdesc" ] = "i.", + [ "acrfull" ] = "i,", + [ "acrlong" ] = "i,", + [ "acrshort" ] = "i,", + [ "acrtext" ] = "i|i?", + [ "assign" ] = "i|ii!", + [ "assignVar" ] = "ii!", + [ "cchem" ] = "i|ihi?", + [ "cfigure" ] = "i|iici?", + [ "cFigure" ] = "i|iici?", + [ "cgnuplot" ] = "i|iiici?", + [ "ch" ] = "i,", + [ "chapter" ] = "i|cc?", + [ "charge" ] = "ii,", + [ "chem" ] = "i|ii!", + [ "chemabove" ] = "ii!", + [ "chembelow" ] = "ii!", + [ "cheme" ] = "i|ii!", + [ "ctable" ] = "i|iici?", + [ "chemfig" ] = "i!", + [ "chemmove" ] = "i!", + [ "chemname" ] = "ii!", + [ "cite" ] = "i|i?", + [ "claim" ] = "hi?", + [ "Claim" ] = "hi?", + [ "compound" ] = "i|i,", + [ "Compound" ] = "i|i,", + [ "correct" ] = "i,", + [ "defineVar" ] = "ih!", + [ "equations" ] = "i?", + [ "explainVar" ] = "i!", + [ "frac" ] = "ii!", + [ "footnote" ] = "i|c,", + [ "hchem" ] = "i|ici?", + [ "hfigure" ] = "i|iici?", + [ "hFigure" ] = "i|iici?", + [ "hgnuplot" ] = "i|iiici?", + [ "htable" ] = "i|iici?", + [ "lchem" ] = "i|ici?", + [ "left" ] = "i!", + [ "MayRefchem" ] = "i,", + [ "MayWrapchem" ] = "i|icic?", + [ "Newunit" ] = "ii,", + [ "nmrH" ] = "i|ii.", + [ "nmrC" ] = "i|ii.", + [ "nmrCH" ] = "i|ii.", + [ "nmrP" ] = "i|ii.", + [ "nmrPH" ] = "i|ii.", + [ "parcite" ] = "i?", + [ "person" ] = "i|i,", + [ "phantom" ] = "i!", + [ "Physical" ] = "i|iiii,", + [ "refEquation" ] = "i,", + [ "refFigure" ] = "i,", + [ "refScheme" ] = "i,", + [ "refTable" ] = "i,", + [ "review" ] = "i|ih?", + [ "reviewBlock" ] = "i|i?", + [ "reviewSide" ] = "i|i?", + [ "right" ] = "i!", + [ "section" ] = "i|cc?", + [ "sqrt" ] = "i|i!", + [ "subfig" ] = "i|iic?", + [ "Subfig" ] = "i|iic?", + [ "SubFig" ] = "i|iic?", + [ "subsection" ] = "i|cc?", + [ "subsubsection" ] = "i|cc?", + [ "subsubsubsection" ] = "i|cc?", + [ "substance" ] = "i|i,", + [ "substanceAbout" ] = "i|icc?", + [ "SubstanceAbout" ] = "i|icc?", + [ "substanceAboutUnwrapped" ] = "i|icc?", + [ "substanceAboutUnwrapped" ] = "i|icc?", + [ "substanceAboutWrapped" ] = "i|icc?", + [ "SubstanceAboutWrapped" ] = "i|icc?", + [ "substanceAs" ] = "i|ii,", + [ "substanceCode" ] = "i|i,", + [ "SubstanceCode" ] = "i|i,", + [ "substanceFull" ] = "i|i,", + [ "substanceLabel" ] = "i?", + [ "substanceMass" ] = "i|i,", + [ "substanceName" ] = "i,", + [ "substanceSimple" ] = "i,", + [ "substanceWithCode" ] = "i|i,", + [ "Unit" ] = "ii,", + }, + macros = { }, + } + +local State += { + Beginning = 0x00, + Inner = 0x01, + EndSentence = 0x02, + Space = 0x03, + EndWord = 0x04, + Macro = 0x10, + IgnoreArgument = 0x11, + Number = 0x12, + OpenMath = 0x20, + LineMath = 0x21, + LongMath = 0x22, + StopMath = 0x23, + FailSafe = 0xee, + Escape = 0xff, + } + +local StateAfterCommand += { + [ "," ] = NewSentence.EndWord, + [ ";" ] = NewSentence, + [ "." ] = NewSentence.Beginning, + [ "-" ] = NewSentence.Hyphen, + [ "?" ] = false, + [ "!" ] = false, + } + +local function tostate ( state ) + if state == State.Beginning + then + return "Beginning" + elseif state == State.Inner + then + return "Inner" + elseif state == State.EndSentence + then + return "EndSentence" + elseif state == State.Space + then + return "Space" + elseif state == State.EndWord + then + return "EndWord" + elseif state == State.Macro + then + return "Macro" + elseif state == State.IgnoreArgument + then + return "IgnoreArgument" + elseif state == State.Number + then + return "Number" + elseif state == State.OpenMath + then + return "OpenMath" + elseif state == State.LineMath + then + return "LineMath" + elseif state == State.LongMath + then + return "LongMath" + elseif state == State.StopMath + then + return "StopMath" + elseif state == State.FailSafe + then + return "FailSafe" + elseif state == State.Escape + then + return "Escape" + else + return "???" + end +end + +local function isSpace ( char ) + return char == " " + or char == "~" + or char == "\t" + or char == "\n" + or char == "\r" +end + +local function isQuote ( char ) + return char == "»" + or char == "«" + or char == "›" + or char == "‹" + or char == "„“" + or char == "“" + or char == "”" + or char == "‚‘" + or char == "‘" + or char == "’" +end + +local Error += { + --- Unknown word, presumably a typo. + Unknown = 0, + --- Known typo. + Typo = 1, + --- Word is known, but usually in another case. + Case = 2, + --- Orthography is fine, but grammar is not. + Grammar = 3, + --- Unexpected Character. + Char = 4, + } + +local function mark ( error, comment, text ) + local prefix = "\\PDFmarkupComment{" .. comment .. "}{" .. text .. "}" + if error == Error.Unknown + then + return prefix .. "{Unknown Word}" .. "{red}" + elseif error == Error.Typo + then + return prefix .. "{Typo}" .. "{red}" + elseif error == Error.Case + then + return prefix .. "{Wrong Case}" .. "{orange}" + elseif error == Error.Grammar + then + return prefix .. "{Grammar}" .. "{green}" + elseif error == Error.Char + then + return prefix .. "{Character}" .. "{blue}" + else + log.error + ( + { "spellChecker.check", "mark" }, + "Unknown Error: #" .. tostring ( error ), + "Text: »" .. text .. "«" + ) + return prefix .. "{???}" .. "{red}" + end +end + +function spellChecker.check ( language, text ) + log.debug + ( + "spellChecker.check", + "Check with »" .. language .. "«:", + text + ) + -- function generates this output, where errors are somehow marked + local texOutput = "" + local mdOutput = "" + -- use this dictionary as reference + local dictionary = spellChecker.dictionaries [ language ] + -- argument stack, might be implemented later + local argStack = {} + local ctrStack = 0 -- increases with {[ and decreases with ]} + local theStack = 0 -- base for ignoring arguments + local command = "" + local optionals = "" + local arguments = "" + local onlyCurly = false + -- state and substate + local state = State.Beginning + local escape = State.Escape + local newSentence = NewSentence.Yes + -- word or command of interest + local cWord = "" -- command word + local lWord = "" -- lowercase word + local tWord = "" -- unmodified word (the word) + local uWord = "" -- uppercase word + + local function leaveMandatory ( ) + command = argStack [ ctrStack ].command + optionals = argStack [ ctrStack ].optionals + arguments = argStack [ ctrStack ].arguments + newSentence = argStack [ ctrStack ].newSentence + spellChecker.logFile:write ( ( " " ):rep ( ctrStack ) .. "leave mandatory: »"..arguments.."« ("..tostring(ctrStack)..")\n" ) + ctrStack = ctrStack - 1 + state = State.EndWord + if #arguments == 1 + then + newSentence = NewSentenceAfterCommand [ arguments ] or newSentence + if arguments == "!" + then + log.fatal ( { "spellChecker.check", "leaveMandatory", }, "Cannot parse special command »" .. command .. "«" ) + end + arguments = "" + end + end + + local function enterMandatory ( ) + ctrStack = ctrStack + 1 + spellChecker.logFile:write ( ( " " ):rep ( ctrStack ) .. "enter mandatory: »"..arguments.."« ("..tostring(ctrStack)..")\n" ) + optionals = "" + local this = arguments:sub(1,1) + arguments = arguments:sub(2) argStack [ ctrStack ] + = { + command = command, + optionals = optionals, + arguments = arguments, + newSentence = newSentence, + } + if this == "c" + then + newSentence = NewSentence.Yes + state = State.Beginning + elseif this == "i" + then + theStack = ctrStack + onlyCurly = true + state = State.IgnoreArgument + elseif this == "h" + or this == "" + then + state = State.Beginning + elseif this == "!" + then + log.fatal ( { "spellChecker.check", "enterMandatory", }, "Cannot parse special command »" .. command .. "«" ) + elseif this == "-" + or this == "," + or this == ";" + or this == "." + or this == "?" + then + spellChecker.logFile:write ( ( ">>" ):rep ( ctrStack ) .. "should not be mandatory\n" ) + arguments = this + leaveMandatory ( ) + else + log.fatal + ( + { "spellChecker.check", "enterMandatory", }, + "Unexpected Character »" .. this .. "« in pattern »" .. ( spellChecker.knownCommands [ command ] or "" ) .. "« of command »" .. command .. "«" + ) + end + end + + local function leaveOptional ( ) + command = argStack [ ctrStack ].command + optionals = argStack [ ctrStack ].optionals + arguments = argStack [ ctrStack ].arguments + newSentence = argStack [ ctrStack ].newSentence + spellChecker.logFile:write ( ( " " ):rep ( ctrStack ) .. "leave optional: »"..optionals.."« ("..tostring(ctrStack)..")\n" ) + ctrStack = ctrStack - 1 + state = State.EndWord + end + + local function enterOptional ( ) + ctrStack = ctrStack + 1 + spellChecker.logFile:write ( ( " " ):rep ( ctrStack ) .. "enter optional: »"..optionals.."« ("..tostring(ctrStack)..")\n" ) + local this = optionals:sub(1,1) + optionals = optionals:sub(2) + argStack [ ctrStack ] + = { + command = command, + optionals = optionals, + arguments = arguments, + newSentence = newSentence, + } + if this == "c" + then + newSentence = NewSentence.Yes + state = State.Beginning + elseif this == "i" + or this == "" + then + theStack = ctrStack + state = State.IgnoreArgument + elseif this == "h" + then + state = State.Beginning + elseif this == "-" + or this == "," + or this == ";" + or this == "." + or this == "?" + then + spellChecker.logFile:write ( ( ">>" ):rep ( ctrStack ) .. "should not be optional\n" ) + optionals = this + leaveOptional ( ) + else + log.fatal + ( + { "spellChecker.check", "enterOptional", }, + "Unexpected Character »" .. this .. "« in pattern »" .. ( spellChecker.knownCommands [ command ] or "" ) .. "« of command »" .. command .. "«" + ) + end + end + + spellChecker.logFile:write ( "\n\nInput:\n" .. text .. "\n\n" ) + if dictionary + then + -- for each utf8-character (does not check, if valid) + local chars = { } + for char in text:gmatch("([%z\1-\127\194-\244][\128-\191]*)") + do + table.insert ( chars, char ) + end + local charsLength = #chars + + for index, char in ipairs ( chars ) + do + spellChecker.logFile:write ( ( " " ):rep ( ctrStack ) .. tostate(state)..": »"..char.."«(" .. sentence(newSentence) .. ")\n" ) + if state == State.Beginning + then + if containsExact ( dictionary._upper, char ) + then + arguments = "" + optionals = "" + lWord = dictionary._lower [ containsWhere ( dictionary._upper, char ) ] + tWord = char + uWord = char + state = State.Inner + elseif containsExact ( dictionary._lower, char ) + then + arguments = "" + optionals = "" + lWord = char + tWord = char + uWord = dictionary._upper [ containsWhere ( dictionary._lower, char ) ] + state = State.Inner + else + texOutput = texOutput .. char + if char == "\\" + then + cWord = "" + state = State.Macro + elseif char == "{" + then + enterMandatory ( ) + elseif char == "}" + then + leaveMandatory ( ) + elseif char == "[" + then + enterOptional ( ) + elseif char == "]" + then + leaveOptional ( ) + elseif char == "$" + then + state = State.OpenMath + elseif char == "-" + then + newSentence = NewSentence.No + elseif char >= "0" + and char <= "9" + then + arguments = "" + optionals = "" + state = State.Number + elseif isSpace ( char ) + or isQuote ( char ) + or char == "(" + or char == ")" -- (Koordinations-)Chemie + then + -- just ignore + else + -- should fail? + spellChecker.logFile:write ( ( ">>" ):rep ( ctrStack ) .. "unexpected character »"..char.."« in Beginning\n" ) + state = State.FailSafe + end + end + elseif state == State.Inner + then + if containsExact ( dictionary._lower, char ) + then + lWord = lWord .. char + tWord = tWord .. char + uWord = uWord .. char + else + spellChecker.logFile:write ( ( " " ):rep ( ctrStack ) .. "check »"..tWord.."« ("..sentence(newSentence)..")\n" ) + if dictionary [ tWord ] + then + if newSentence == NewSentence.Yes + and tWord == lWord + then + -- word is usually in lower case, but at beginning of sentences, it has to be uppercase + spellChecker.logFile:write ( "\n" .. ( "!!" ):rep ( ctrStack ) .. tWord .. " (upper case at new sentence expected)\n" ) + texOutput = texOutput .. mark ( Error.Case, "Upper Case at new sentence expected", tWord ) + else + texOutput = texOutput .. tWord + end + elseif dictionary [ lWord ] + then + if newSentence == NewSentence.No + then + -- word is usually lower case, but it is written in upper case here + spellChecker.logFile:write ( "\n" .. ( "!!" ):rep ( ctrStack ) .. tWord .. " (lower case expected)\n" ) + texOutput = texOutput .. mark ( Error.Case, "Lower Case expected", tWord ) + else + -- word is usually lower case, but this might be a new sentence + texOutput = texOutput .. tWord + end + elseif dictionary [ uWord ] + then + -- word is usually upper case, but it is written in lower case here + if newSentence == NewSentence.Hyphen + or ( ( index + 2 ) <= charsLength and chars [ index ] == "\\" and chars [ index + 1 ] == "-" ) + then + -- because it is inside another word, e.g. due to Neu\-jahrs\-anfang. + texOutput = texOutput .. tWord + else + spellChecker.logFile:write ( "\n" .. ( "!!" ):rep ( ctrStack ) .. "chars: " .. chars [ index ] .. chars [ index + 1 ] .. "\n" ) + spellChecker.logFile:write ( "\n" .. ( "!!" ):rep ( ctrStack ) .. tWord .. " (upper case expected)\n" ) + texOutput = texOutput .. mark ( Error.Case, "Upper Case expected", tWord ) + end + elseif newSentence == NewSentence.Hyphen + and containsExact ( dictionary._ending, lWord ) + then + newSentence = NewSentence.No + else + spellChecker.logFile:write ( "\n" .. ( " " ):rep ( ctrStack ) .. tWord .. "\n" ) + texOutput = texOutput .. mark ( Error.Unknown, "Unknown Word", tWord ) + end + if char == "\\" + then + cWord = "" + state = State.Macro + newSentence = NewSentence.No + elseif char == "{" + then + enterMandatory ( ) + elseif char == "}" + then + leaveMandatory ( ) + elseif char == "[" + then + enterOptional ( ) + elseif char == "]" + then + leaveOptional ( ) + elseif char == "$" + then + state = State.OpenMath + elseif char == "-" + then + newSentence = NewSentence.Hyphen + state = State.Beginning + elseif char == "." + or char == "?" + or char == "!" + then + state = State.EndSentence + elseif char == "," + then + state = State.Space + newSentence = NewSentence.No + elseif char == ":" + or char == ";" + then + state = State.Space + newSentence = NewSentence.Maybe + elseif isSpace ( char ) + then + state = State.Beginning + newSentence = NewSentence.No + elseif isQuote ( char ) + or char == ")" + then + state = State.EndWord + newSentence = NewSentence.No + else + spellChecker.logFile:write ( ( ">>" ):rep ( ctrStack ) .. "unexpected character »"..char.."« in Inner\n" ) + texOutput = texOutput .. mark ( Error.Char, "Unexpected Character", char ) + char = "" + state = State.FailSafe + end + texOutput = texOutput .. char + end + else + if state == State.FailSafe + then + -- do nothing special + elseif state == State.EndSentence + then + newSentence = NewSentence.Yes + if isSpace ( char ) + then + state = State.Beginning + elseif isQuote ( char ) + or char == ")" + then + state = State.EndWord + newSentence = NewSentence.No + elseif char == "." + or char == "?" + or char == "!" + then + -- bad style, but ok + elseif char == "\\" + then + cWord = "" + state = State.Macro + elseif char == "}" + then + leaveMandatory ( ) + elseif char == "]" + then + leaveOptional ( ) + else + -- should fail? + spellChecker.logFile:write ( ( ">>" ):rep ( ctrStack ) .. "unexpected character »"..char.."« in EndSentence\n" ) + state = State.FailSafe + end + elseif state == State.Space + then + if isSpace ( char ) + then + state = State.Beginning + elseif char == "\\" + then + cWord = "" + state = State.Macro + elseif char == "}" + then + leaveMandatory ( ) + elseif char == "]" + then + leaveOptional ( ) + else + -- should fail? + spellChecker.logFile:write ( ( ">>" ):rep ( ctrStack ) .. "unexpected character »"..char.."« in Space\n" ) + state = State.FailSafe + end + elseif state == State.EndWord + then + if isSpace ( char ) + then + state = State.Beginning + elseif isQuote ( char ) + or char == ")" + or char == "/" + then + state = State.EndWord + newSentence = NewSentence.No + elseif char == "\\" + then + cWord = "" + state = State.Macro + elseif char == "{" + then + enterMandatory ( ) + elseif char == "}" + then + leaveMandatory ( ) + elseif char == "[" + then + enterOptional ( ) + elseif char == "]" + then + leaveOptional ( ) + elseif char == "-" + then + newSentence = NewSentence.Hyphen + state = State.Beginning + elseif char == "." + or char == "?" + or char == "!" + then + state = State.EndSentence + elseif char == "," + then + state = State.Space + newSentence = NewSentence.No + elseif char == ":" + or char == ";" + then + state = State.Space + newSentence = NewSentence.Maybe + elseif containsExact ( dictionary._lower, char ) + then + lWord = char + tWord = char + uWord = dictionary._upper [ containsWhere ( dictionary._lower, char ) ] + newSentence = NewSentence.Hyphen + state = State.Inner + char = "" + else + -- should fail? + spellChecker.logFile:write ( ( ">>" ):rep ( ctrStack ) .. "unexpected character »"..char.."« in EndWord\n" ) + state = State.FailSafe + end + elseif state == State.Macro + then + if char:match ( "%a" ) + then + cWord = cWord .. char + else + spellChecker.logFile:write ( ( " " ):rep ( ctrStack ) .. "Macro: "..cWord ) + command = cWord + if char ~= "\\" + then + if command == "-" + then + state = State.Beginning + newSentence = NewSentence.Hyphen + else + local entry = spellChecker.knownCommands [ cWord ] + if entry + then + local left, right = entry:match ( "([chi]*)|([chi]*[-,;.?!]?)" ) + if left and right + then + optionals = left + arguments = right + elseif entry == "!" + then + log.fatal ( "spellChecker.check", "Cannot parse special command »" .. cWord .. "«" ) + else + optionals = "" + arguments = entry + end + spellChecker.logFile:write ( "\n" .. ( " " ):rep ( ctrStack ) .. "\\" .. cWord .. "[" .. optionals .. "]{" .. arguments .. "}" ) + elseif spellChecker.failCommands [ cWord ] + then + log.fatal ( "spellChecker.check", "Found the failCommand »\\" .. cWord .. "«" ) + else + spellChecker + .macros [ cWord ] = true + optionals = "" + arguments = "" + end + if isSpace ( char ) + then + state = State.Beginning + elseif isQuote ( char ) + or char == ")" + then + state = State.EndWord + newSentence = NewSentence.No + elseif char == "}" + then + leaveMandatory ( ) + elseif char == "]" + then + leaveOptional ( ) + elseif char == "{" + then + enterMandatory ( ) + elseif char == "[" + then + enterOptional ( ) + elseif char == "-" + then + newSentence = NewSentence.Hyphen + state = State.Beginning + elseif char == "." + or char == "?" + or char == "!" + then + state = State.EndSentence + elseif char == "," + then + state = State.Space + newSentence = NewSentence.No + elseif char == ":" + then + state = State.Space + newSentence = NewSentence.Maybe + else + state = State.Beginning + end + end + else + cWord = "" + end + spellChecker.logFile:write ( "\n" ) + end + elseif state == State.IgnoreArgument + then + if char == "}" + or ( char == "]" and not onlyCurly ) + then + if ctrStack == theStack + then + state = State.Beginning + onlyCurly = false + if char == "}" + then + leaveMandatory ( ) + else + leaveOptional ( ) + end + else + ctrStack = ctrStack - 1 + end + elseif char == "{" + or ( char == "[" and not onlyCurly ) + then + ctrStack = ctrStack + 1 + elseif char == "\\" + then + escape = State.IgnoreArgument + state = State.Escape + else + -- just ignore + end + elseif state == State.Number + then + if isSpace ( char ) + then + state = State.Beginning + elseif char == "}" + then + leaveMandatory ( ) + elseif char == "]" + then + leaveOptional ( ) + elseif char == "{" + then + enterMandatory ( ) + elseif char == "[" + then + enterOptional ( ) + else + -- just ignore + end + elseif state == State.OpenMath + then + if char == "$" + then + state = State.LongMath + elseif char == "\\" + then + escape = State.LineMath + state = State.Escape + else + state = State.LineMath + end + elseif state == State.LineMath + then + if char == "$" + then + state = State.EndWord + newSentence = NewSentence.No + elseif char == "\\" + then + escape = State.LineMath + state = State.Escape + else + -- just ignore + end + elseif state == State.LongMath + then + if char == "$" + then + state = spellStopMath + elseif char == "\\" + then + escape = State.LongMath + state = State.Escape + else + -- just ignore + end + elseif state == State.StopMath + then + if char == "$" + then + state = State.EndWord + newSentence = NewSentence.Yes + elseif char == "\\" + then + escape = State.LongMath + state = State.Escape + else + state = State.LongMath + end + elseif state == State.Escape + then + state = escape + else + spellChecker.logFile:write ( "Invalid State\n" ) + end + texOutput = texOutput .. char + end + end + log.info + ( + "spellChecker.check", + "Checked:", + "»"..texOutput.."«" + ) + spellChecker.logFile:write ( "Output checked:\n" .. texOutput ) + tex.print(texOutput) + else + log.warn + ( + "spellChecker.check", + "Cannot check spelling, because dictionary »" .. language .. "« was not loaded.", + "Use \\loadDictionary{…} to load dictionary file." + ) + spellChecker.logFile:write ( "Output unchecked:\n" .. text ) + tex.print(text) + end +end + +function spellChecker.loadDictionary ( dict ) + local fileName = source .. "assets/dictionaries/" .. dict .. ".lua" + markFileAsUsed ( fileName ) + local file = loadfile ( fileName ) + if file + then + spellChecker.dictionaries [ dict ] = file ( ) + else + log.fatal ( "spellChecker.loadDictionary", "Cannot load dictionary »" .. dict .. "« (" .. fileName .. ")" ) + end +end + +function spellChecker.listMacros ( ) + spellChecker.logFile:write ( "\n\nFound these macros:\n" ) + for index, ignore in pairs ( spellChecker.macros ) + do + spellChecker.logFile:write ( "\\" .. index .. "\n" ) + end +end diff --git a/NixTeX/dependencies/source/lua/text/text.lua b/NixTeX/dependencies/source/lua/text/text.lua new file mode 100644 index 0000000..7e1b8db --- /dev/null +++ b/NixTeX/dependencies/source/lua/text/text.lua @@ -0,0 +1,96 @@ +text += { + annotations = false, + reviewSeen = "", + reviewSuffix = "", + reviewColours + = { + [ "" ] = "orange", + [ "minor" ] = "orange", + [ "disagree" ] = "yellow", + [ "urgent" ] = "red", + [ "solved" ] = "green", + }, + details + = { + threshold = 2, + default = 1, + }, + thinkDash + = { + threshold = 2, + default = 1, + comma = ",", + dash = "~–", + }, + } + +function text.thd ( input ) + local level = tonumber ( input ) or text.thinkDash.default + if level < text.thinkDash.threshold + then + tex.print ( text.thinkDash.comma ) + else + tex.print ( text.thinkDash.dash ) + end +end + +function text.thinkDash.setThreshold ( input ) + text.thinkDash.threshold = tonumber ( input ) or text.thinkDash.default +end + +function text.detailed ( input, message ) + local level = tonumber ( input ) or text.details.default + if level >= text.details.threshold + then + tex.print ( message ) + end +end + +function text.elaborate ( input ) + text.details.threshold = tonumber ( input ) or text.details.default +end + +function text.annotate ( state ) + text.annotations = ( state == "true" or state == "annotate" ) +end + + + +function text.reviewColour ( state, comment ) + if text.annotations + then + if text.reviewColours [ state ] + then + tex.print ( text.reviewColours [ state ] ) + else + -- Unknown? + log.warning + ( + "text.reviewColour", + "Unknown State: »" .. state .. "«", + "Comment: »" .. comment .. "«" + ) + tex.print ( "yellow" ) + end + end + if state ~= "solved" + and text.reviewSeen ~= comment + then + text.reviewSeen = comment + if state == "" + then + log.todo + ( + "Review:", + comment + ) + else + log.todo + ( + "Review [" .. state .. "]:", + comment + ) + end + end +end diff --git a/NixTeX/dependencies/source/lua/thesis.lua b/NixTeX/dependencies/source/lua/thesis.lua new file mode 100644 index 0000000..33bacab --- /dev/null +++ b/NixTeX/dependencies/source/lua/thesis.lua @@ -0,0 +1,34 @@ +thesis += { + logo = "", + defaults + = { + logoColour = "", + logoMonochrome = "", + }, + } + +function thesis.parseInstituteOptions ( options ) + --log.debug + --( + -- "thesisInstitute", + -- "Parse Institute Options: (" .. options .. ")" + --) + thesis.logo = thesis.defaults.logoColour + for option in options:gmatch ( "([^,]+)" ) + do + opName, opValue = option:match ( "([^=]+)=(.+)" ) + --log.debug + --( + -- "thesisInstitute", + -- "Name: »" .. opName:tostring ( ) .. "«, Value: »" .. opValue:tostring ( ) .. "«" + --) + if not ( opName and opValue ) + then + if option == "monochrome" + then + thesis.logo = thesis.defaults.logoMonochrome + end + end + end +end diff --git a/NixTeX/dependencies/source/lua/time.lua b/NixTeX/dependencies/source/lua/time.lua new file mode 100644 index 0000000..8e857c6 --- /dev/null +++ b/NixTeX/dependencies/source/lua/time.lua @@ -0,0 +1,154 @@ +time += { + monthNames + = { + de + = { + "Januar", + "Februar", + "März", + "April", + "Mai", + "Juni", + "Juli", + "August", + "September", + "Oktober", + "November", + "Dezember", + } + } + } + +function time.printToday ( today ) + local date + if today + then + date = os.date ( "*t", tonumber ( today ) ) + else + date = os.date ( "*t" ) + end + local today + = tostring ( date.day ) .. ".~" + .. time.monthNames.de [ date.month ] .. " " + .. tostring ( date.year ) + log.trace + ( + "time.printToday", + "Today is " .. today + ) + tex.print ( today ) +end + +function time.printPDFtoday ( ) + local date + if time ~= "" + then + date = os.date ( "*t", tonumber ( time ) ) + else + date = os.date ( "*t" ) + end + local today + = ( "D:%04d%02d%02d133742+0100" ):format + ( + date.year, + date.month, + date.day + ) + tex.print ( today ) +end + +function time.printMonthAndYear ( today ) + local date + if today + then + date = os.date ( "*t", tonumber ( today ) ) + else + date = os.date ( "*t" ) + end + local today + = time.monthNames.de [ date.month ] .. "~" + .. tostring ( date.year ) + log.trace + ( + "time.printMonthAndYear", + "Today is " .. today + ) + tex.print ( today ) +end + +function time.parse ( date ) + if date + and type ( date ) == "string" + then + if #date == 10 + then + local year, month, day = date:match("(%d%d%d%d)-(%d%d)-(%d%d)") + return { + year = tonumber ( year ), + month = tonumber ( month ), + day = tonumber ( day ), + } + elseif #date == 7 + then + local year, month = date:match("(%d%d%d%d)-(%d%d)") + return { + year = tonumber ( year ), + month = tonumber ( month ), + } + elseif #date == 4 + then + return { + year = tonumber ( date ), + } + else + return nil + end + else + return nil + end +end + +function time.printFrom ( date ) + if date + then + if type ( date ) == "string" + then + if date == "" + then + time.printToday ( ) + else + time.printFrom ( time.parse ( date ) ) + end + elseif type ( date ) == "number" + then + time.printToday ( date ) + elseif type ( date ) == "table" + then + if date.year + then + local today = tostring ( date.year ) + if date.month + then + today = time.monthNames.de [ date.month ] .. " " .. today + if date.day + then + today = tostring ( date.day ) .. ".~" .. today + end + end + log.trace + ( + " time.printFrom", + "Today is " .. today + ) + tex.print ( today ) + else + log.fatal ( "print.printTable", "Year Missing" ) + end + else + log.fatal ( "print.printTable", "Invalid type of date: " .. type ( date ) ) + end + else + time.printToday ( ) + end +end diff --git a/NixTeX/dependencies/source/lua/units.lua b/NixTeX/dependencies/source/lua/units.lua new file mode 100644 index 0000000..dec1364 --- /dev/null +++ b/NixTeX/dependencies/source/lua/units.lua @@ -0,0 +1,61 @@ +units += { + [ "" ] = 1, + [ "bp" ] = 352.77777777778, + [ "cc" ] = 4512, + [ "cm" ] = 10000, + [ "dd" ] = 376, + [ "in" ] = 25400, + [ "mm" ] = 1000, + [ "nc" ] = 4500, + [ "nd" ] = 375, + [ "pc" ] = 4218, + [ "pt" ] = 351.46, + [ "sp" ] = 0.00536, + } + +function convert ( value, toUnit, mul, add ) + local fromUnit + if ( not mul ) + then + mul = 1 + end + if ( not add ) + then + add = 0 + end + value, fromUnit = value:match ( "([0-9e+-.]+)(.*)" ) + value = tonumber ( value ) + if value + and fromUnit + and units [ fromUnit ] + and units [ toUnit ] + then + local mul = tonumber ( mul ) + local add = tonumber ( add ) + local factor = units [ fromUnit ] / units [ toUnit ] + local length = tostring ( ( value * mul + add ) * factor ) .. toUnit + log.debug + ( + "convert", + "Conversion Parameters:", + " factor: " .. tostring ( factor ), + " input: " .. tostring ( value ), + " length: " .. length + ) + return length + else + log.fatal + ( + "convert", + "Cannot Parse Length:", + " value: »" .. tostring ( value ) .. "«", + " fromUnit: " .. tostring ( fromUnit ), + " fromUnit: " .. tostring ( units[fromUnit] ), + " toUnit: " .. tostring ( toUnit ), + " toUnit: " .. tostring ( units[toUnit] ), + " mul: " .. tostring ( mul ), + " add: " .. tostring ( add ) + ) + end +end diff --git a/NixTeX/dependencies/source/lua/utf8.lua b/NixTeX/dependencies/source/lua/utf8.lua new file mode 100644 index 0000000..5463181 --- /dev/null +++ b/NixTeX/dependencies/source/lua/utf8.lua @@ -0,0 +1,23 @@ +utf8 += { + -- Lazy Match! + charMatch = "([%z\1-\127\194-\244][\128-\191]*)", + } + +function utf8.split ( input ) + return input:utf8split ( ) +end + +function utf8.char ( input ) + return input:utf8char ( ) +end + +--- Split String into Table of UTF8 Characters. +function string:utf8split ( ) --> table < string > + return self:gmatch ( utf8.charMatch ) +end + +--- get utf8-character at given `offset`. +function string:utf8char ( offset ) --> string + return self:match ( utf8.charMatch, offset ) +end diff --git a/NixTeX/dependencies/source/lua/utils.lua b/NixTeX/dependencies/source/lua/utils.lua new file mode 100644 index 0000000..ad0328c --- /dev/null +++ b/NixTeX/dependencies/source/lua/utils.lua @@ -0,0 +1,122 @@ +utils = {} +function utils.reverseText(text) + local output = "" + log.trace("reverseText", "text: »"..text.."«") + for char in text:utf8split() + do + log.trace("reverseText", "char: »"..char.."«") + output = char .. output + end + log.trace("reverseText", "output: »"..output.."«") + return output +end + +function utils.printReverseText(text) + tex.print(utils.reverseText(text)) +end + +function utils.prepareRTL(text) + local output = "" + for word in text:gmatch("([^%s]+)") + do + local temp = "" + for char in word:utf8split() + do + temp = char .. temp + end + output = " " .. temp .. output + end + return output +end + +function utils.printRTL(text) + tex.print(utils.prepareRTL(text)) +end + +function contains (tab, val) + for index, value in ipairs(tab) + do + if value:lower() == val:lower() + then + return true + end + end + return false +end + +function containsExact (tab, val) + for index, value in ipairs(tab) + do + if value == val + then + return true + end + end + return false +end + +function containsWhere (tab, val) + for index, value in ipairs(tab) + do + if value == val + then + return index + end + end + return 0 +end + +function table.reduce (list, fn) + local acc + for k, v in ipairs(list) + do + if 1 == k then + acc = v + else + acc = fn(acc, v) + end + end + return acc +end + +function sum ( a, b ) + return a + b +end + +function round(exact, quantum) + local quant,frac = math.modf(exact/quantum) + return quantum * (quant + (frac > 0.5 and 1 or 0)) +end + + +function eval(text) + value = load ( "return (" .. text .. ")" ) + if value + and value() + and tonumber(value()) + then + return tonumber(value()) + else + return nil + end +end + +function hypertarget ( label ) + return "\\vadjust pre{\\hypertarget{" .. label .. "}{}}" --.. percent +end + +function string:split ( sep ) + local sep = sep or "," + local fields = {} + local pattern = string.format ( "([^%s]+)", sep ) + self:gsub ( pattern, function(c) fields[#fields+1] = c end ) + return fields +end + + +function utils.printNames ( names, prefix, suffix ) + for name in string.gmatch(names, "[^;]+") + do + tex.print((prefix or "&" )..name..( suffix or tex.newline)) + end +end diff --git a/NixTeX/dependencies/source/lua/values/mod.lua b/NixTeX/dependencies/source/lua/values/mod.lua new file mode 100644 index 0000000..415af54 --- /dev/null +++ b/NixTeX/dependencies/source/lua/values/mod.lua @@ -0,0 +1,252 @@ +values += { + prefixes + = { + "yotta", "zetta", "exa", "peta", "tera", "giga", "mega", "kilo", "hecto", "deca", + "deci", "centi", "milli", "micro", "nano", "pico", "femto", "atto", "zepto", "yocto", + }, + } + +local function formatEntry ( entry, unit, wantSpace ) + --> ( + -- formatedUnit: string, + -- isCurrency: bool, + -- ) + unit = acronyms.getShortText ( unit ) + if not wantSpace + or entry.attributes == attributes.Angle + then + -- x°/′/″ or any consecutive unit + return "" .. unit, false + elseif entry.attributes == attributes.Unit + then + -- x kg/m/s + return "\\," .. unit, false + elseif entry.attributes == attributes.Currency + then + -- x € + -- you might want to format money yourself, + -- e.g. »€ 13.37«, »23.42 CHF«, »3 €, 5 ct«. + return "\\," .. unit, true + else + -- x Users + return "~" .. unit, false + end +end + +local function formatUnit ( unit, wantSpace ) + --> ( + -- formatedUnit: string, + -- isCurrency: bool, + -- ) + local entry = acronyms.list [ unit ] + if entry + then + return formatEntry ( entry, unit, wantSpace ) + else + local unitPrefix = "" + for index, prefix in ipairs ( values.prefixes ) + do + local match = unit:match ( prefix .. "(%a+)" ) + if match + then + unit = match + unitPrefix = acronyms.getShortText ( prefix ) + break + end + end + if unit == "gram" + then + unit = acronyms.getText ( "kilogram", "g", "g", false ) + elseif unit == "calorie" + then + unit = acronyms.getText ( "kilocalorie", "cal", "cal", false ) + else + local entry = acronyms.list [ unit ] + if entry + then + unit = formatEntry ( entry, unit, false ) + else + unit = "(¿" .. unit .. "?)" + end + end + if wantSpace + then + return "\\," .. output .. unit + else + return output .. unit + end + end +end + +function values.getNumber ( value ) + local output = "{" .. value .. "}" + local States + = { + Sign = 1, + Integer = 2, + Decimal = 3, + ExponentSign = 4, + ExponentValue = 5, + Constant = 6, + Fraction = 7, + } + + local constant = "" + local exponent = 0 + local exponentSign = "" + local multiplier = 0.1 + local sign = "" + local value = 0 + + local state = States.Sign + for char in value:utf8split ( ) + do + if state == States.Sign + then + if char == "+" + then + if sign == "" + then + sign = "+" + elseif sign == "−" + then + sign = "∓" + else + break + end + elseif char == "-" + then + if sign == "" + then + sign = "−" + elseif sign == "+" + then + sign = "±" + else + break + end + elseif char == "±" + or char == "∓" + then + sign = char + elseif char >= "0" and char <= "9" + then + value = char:byte ( ) - 48 + state = States.Integer + elseif char >= "A" and char <= "Z" + or char >= "a" and char <= "z" + then + constant = char + state = States.Constant + elseif char == "." + or char == "," + state = States.Decimal + else + break + end + elseif state == States.Integer + then + if char >= "0" and char <= "9" + then + value = value * 10 + char:byte ( ) - 48 + elseif char == "." + or char == "," + state = States.Decimal + elseif char == "E" + or char == "e" + state = States.ExponentSign + elseif char == "*" + or char == "·" + then + value = sign .. tostring ( value ) + constant = "" + state = States.Constant + else + break + end + elseif state == States.Decimal + then + if char >= "0" and char <= "9" + then + value = value + ( char:byte ( ) - 48 ) * multiplier + multiplier = multiplier / 10 + elseif char == "E" + or char == "e" + state = States.ExponentSign + elseif char == "*" + or char == "·" + then + value = sign .. tostring ( value ) + constant = "" + state = States.Constant + else + break + end + elseif state == States.ExponentSign + then + if char == "+" + then + exponentSign = "+" + elseif char == "-" + then + exponentSign = "−" + elseif char >= "0" and char <= "9" + then + else + break + end + else + log.fatal + ( + "values.getNumber", + "Not Implemented Yet" + ) + break + end + end + return output +end + +function values.getUnit ( unit ) + local output = "" + local wantSpace = true + for unit in unit:gmatch ( "([^*]+)" ) + do + local exponent = "" + unit, exponent = value:match ( "(%a+)([+-]%d+)" ) + + if not wantSpace + then + output = output .. "·" + end + output = output .. formatUnit ( unit, wantSpace ) + wantSpace = false + + exponent = tonumber ( exponent ) + if exponent + then + output = output .. "^{" .. tostring ( exponent ) .. "}" + end + end +end + +function values.getValue ( precision, value, unit ) + local sign, number, exponent = values.getNumber ( value ) + local unit = values.getUnit ( unit ) + local output = sign or "" .. number + if exponent + then + return output .. "·10^{" .. exponent .. "}" + else + return output + end +end + +function values.printUnit ( unit ) + tex.print ( values.getUnit ( unit ) ) +end + +function values.printValue ( precision, value, unit ) + tex.print ( values.getValue ( precision, value, unit ) ) +end diff --git a/NixTeX/dependencies/source/pictograms.tex b/NixTeX/dependencies/source/pictograms.tex new file mode 100644 index 0000000..730a75c --- /dev/null +++ b/NixTeX/dependencies/source/pictograms.tex @@ -0,0 +1,25 @@ +\newcommand{\pictogramOther}[1] +{% + \makeatletter% + \ifthenelse{\equal{\@PictogramInverted}{true}} + {% + \includegraphics + [height=\normalbaselineskip] + {./\source/assets/pictograms/other/#1_inverted.pdf}% + }% + {% + \includegraphics + [height=\normalbaselineskip] + {./\source/assets/pictograms/other/#1.pdf}% + }% + \makeatother% +} +\def\pictogramCorrosive {\pictogramOther{corrosive}} +\def\pictogramEcoHazard {\pictogramOther{ecoHazard}} +\def\pictogramExplosive {\pictogramOther{explosive}} +\def\pictogramFlammable {\pictogramOther{flammable}} +\def\pictogramGasBottle {\pictogramOther{gasBottle}} +\def\pictogramLithiumCells {\pictogramOther{lithiumCells}} +\def\pictogramOxidiser {\pictogramOther{oxidiser}} +\def\pictogramSkull {\pictogramOther{skull}} +\def\@PictogramInverted {false} diff --git a/NixTeX/dependencies/source/slides.tex b/NixTeX/dependencies/source/slides.tex new file mode 100644 index 0000000..4f41f56 --- /dev/null +++ b/NixTeX/dependencies/source/slides.tex @@ -0,0 +1,37 @@ +\renewcommand<>{\cfigure}[1][]{\thecfigure{h}{#2}{#1}} +\renewcommand<>{\hfigure}[1][]{\thecfigure{H}{#2}{#1}} +\renewcommand<>{\cgnuplot}[1][]{\thegnuplot{h}{#2}{#1}} +\renewcommand<>{\hgnuplot}[1][]{\thegnuplot{H}{#2}{#1}} +\renewcommand<>{\cFigure}[1][]{\Thecfigure{h}{#2}{#1}} +\renewcommand<>{\hFigure}[1][]{\Thecfigure{H}{#2}{#1}} +\renewcommand<>{\subchem}[4][b]{\thesubchem{#1}{#2}{#3}{#4}{#5}} +\renewcommand<>{\subfig}[4][b]{\thesubfig{#1}{#2}{#3}{#4}{#5}} +\renewcommand<>{\Subfig}[4][b]{\theSubfig{#1}{#2}{#3}{#4}{#5}} +\renewcommand<>{\subgnuplot}[6][b]{\thesubgnuplot{#1}{#2}{#3}{#4}{#5}{#6}{#7}} +\renewcommand<>{\Subgnuplot}[6][b]{\theSubgnuplot{#1}{#2}{#3}{#4}{#5}{#6}{#7}} +\renewcommand<>{\wrapfig}[6][0.3]{\thewrapfig{#1}{#2}{#3}{#4}{#5}{#6}{#7}} +\renewcommand<>{\footcite}[1]{\footnote#2[frame]{\fullcite{#1}}} +\renewcommand{\thefootnote}{\relax\textsuperscript{[\arabic{footnote}]}} + +\makeatletter + \def\setfixbeamer + { + \def\fix@beamer@close{\ifnum\beamer@trivlistdepth>0\beamer@closeitem\fi} + \def\fix@beamer@open{\ifnum\beamer@trivlistdepth>0\gdef\beamer@closeitem{}\fi} + } + \def\clrfixbeamer + { + \def\fix@beamer@close{} + \def\fix@beamer@open{} + } + + \BeforeBeginEnvironment{enumerate}{\fix@beamer@close} + \AfterEndEnvironment{enumerate}{\fix@beamer@open} + \BeforeBeginEnvironment{itemize}{\fix@beamer@close} + \AfterEndEnvironment{itemize}{\fix@beamer@open} + \BeforeBeginEnvironment{description}{\fix@beamer@close} + \AfterEndEnvironment{description}{\fix@beamer@open} + %\newcommand{\bookmarkthis}[1][2]{\bookmark[page=\the\c@page,level=#1]{\GetTitleStringResult}} + \let\footnoterule\relax +\makeatother +\setfixbeamer diff --git a/NixTeX/dependencies/source/symbols.tex b/NixTeX/dependencies/source/symbols.tex new file mode 100644 index 0000000..7c1e995 --- /dev/null +++ b/NixTeX/dependencies/source/symbols.tex @@ -0,0 +1,69 @@ +\protected\def\zero {0} +\protected\def\one {1} +\protected\def\two {2} +\protected\def\three {3} +\protected\def\four {4} +\protected\def\five {5} +\protected\def\six {6} +\protected\def\seven {7} +\protected\def\eight {8} +\protected\def\nine {9} + +\protected\def\dash {-} + +\def\addressicon {\faHome} +%\def\cdot {·} +\def\birthicon {\faBirthdayCake} +\def\emailicon {\faEnvelope} +\def\facebookicon {\faFacebook} +\def\faxicon {\faFax} +\def\giticon {\faGit} +\def\githubicon {\faGithubSquare} +\def\gitlabicon {\faGitlab} +\def\googlescholaricon {\faGraduationCap} +\def\homepageicon {\faGlobe} +\def\keyicon {{\ForkAwesome^^^^f2f7}} +%\def\keyicon {{\FontAwesomeSolid^^^^f084}} +\def\lightning {{\fontspec{DejaVuSans}↯\relax}} +\def\linkedinicon {\faLinkedinSquare} +\def\matrixicon {{\ForkAwesome^^^^f313}} +\def\mediumicon {\faMedium} +\def\mobileicon {\faMobile} +\def\officeicon {\faBuilding} +\def\orcidicon {{\FontAwesomeBrands^^^^f8d2}} +\def\phoneicon {\faPhone} +\def\plus {+} +\def\redditicon {\faReddit} +\def\skypeicon {\faSkype} +\def\stackoverflowicon {\faStackOverflow} +\def\twittericon {\faTwitter} +\def\wikipediaicon {\faWikipediaW} +\def\xingicon {\faXingSquare} + +\def\radioactivity +{% + \resizebox{1.5em}{1.5em}% + {% + \begin{tikzpicture}% + \node [ white, opacity = 0 ] at ( 0, 0 ) {\Huge\DejaVuSans^^^^2622}; + \fill ( 0, 0 ) circle ( .1 ); + \fill ( 60:.15 ) arc ( 60:120:.15 ) -- ( 120:.5 ) arc ( 120: 60:.5 ) -- cycle; + \fill ( 180:.15 ) arc ( 180:240:.15 ) -- ( 240:.5 ) arc ( 240:180:.5 ) -- cycle; + \fill ( 300:.15 ) arc ( 300:360:.15 ) -- ( 360:.5 ) arc ( 360:300:.5 ) -- cycle; + \end{tikzpicture}% + }% +} + +\def\Radioactivity +{% + \resizebox{1.5em}{1.5em}% + {% + \begin{tikzpicture}% + \node [ white, opacity = 0 ] at ( 0, 0 ) {\Huge\DejaVuSans^^^^2622}; + \fill ( 0, 0 ) circle ( .1 ); + \fill ( 0:.15 ) arc ( 0: 60:.15 ) -- ( 60:.5 ) arc ( 60: 00:.5 ) -- cycle; + \fill ( 120:.15 ) arc ( 120:180:.15 ) -- ( 180:.5 ) arc ( 180:120:.5 ) -- cycle; + \fill ( 240:.15 ) arc ( 240:300:.15 ) -- ( 300:.5 ) arc ( 300:240:.5 ) -- cycle; + \end{tikzpicture}% + }% +} diff --git a/NixTeX/dependencies/source/text/gender.tex b/NixTeX/dependencies/source/text/gender.tex new file mode 100644 index 0000000..d464e2f --- /dev/null +++ b/NixTeX/dependencies/source/text/gender.tex @@ -0,0 +1,7 @@ +\def\gendergap {\_} +\newcommand{\DerDie} {der\gendergap\relax{}die} +\newcommand{\In} {\gendergap\relax{}in} +\newcommand{\Innen} {\gendergap\relax{}in\-nen} + +\def\n{\In} +\def\innen{\Innen} diff --git a/NixTeX/dependencies/source/text/languages.tex b/NixTeX/dependencies/source/text/languages.tex new file mode 100644 index 0000000..f10dd42 --- /dev/null +++ b/NixTeX/dependencies/source/text/languages.tex @@ -0,0 +1,12 @@ +\directlua{tex.enableprimitives("luatex",tex.extraprimitives("luatex"))} + +% Language or Country Related Macros +% Flags +\newcommand{\countryFlag}[1]{\faFlag} + +% Quotes +\newcommand{\q}[2][]{»#2«\ifthenelse{\equal{#1}{}}{}{(»#1«)}} +\newcommand{\Q}[2][]{›#2‹\ifthenelse{\equal{#1}{}}{}{(›#1‹)}} + +\newcommand{\fromHebrew}[3][]{\acrshort{hebrew}~\texthebrew{#2}\ifnotempty{#1}{ \textit{#1}}\ifnotempty{#3}{: \Q{#3}}} +\newcommand{\fromEnglish}[3][]{\acrshort{english}~#2\ifnotempty{#1}{ \textit{#1}}\ifnotempty{#3}{: \Q{#3}}} diff --git a/NixTeX/dependencies/source/text/plain.tex b/NixTeX/dependencies/source/text/plain.tex new file mode 100644 index 0000000..fd848d9 --- /dev/null +++ b/NixTeX/dependencies/source/text/plain.tex @@ -0,0 +1,9 @@ +\newboolean{@plainText} +\setboolean{@plainText}{false} +\def\enablePlainText{\setboolean{@plainText}{true}\directlua{plainText=true}} +\def\disablePlainText{\setboolean{@plainText}{false}\directlua{plainText=false}} +\newcommand{\ifPlainText}[2]{\if@plainText #1\else#2\fi} + +\let\@textbf=\textbf\renewcommand{\textbf}[1]{\ifPlainText{**#1**}{\@textbf{#1}}} +\let\@textit=\textit\renewcommand{\textit}[1]{\ifPlainText{*#1*}{\@textit{#1}}} +\let\@textsc=\textsc\renewcommand{\textsc}[1]{\ifPlainText{+#1+}{\@textsc{#1}}} diff --git a/NixTeX/dependencies/source/text/spelling.tex b/NixTeX/dependencies/source/text/spelling.tex new file mode 100644 index 0000000..8be80b3 --- /dev/null +++ b/NixTeX/dependencies/source/text/spelling.tex @@ -0,0 +1,13 @@ +\directlua{includeCode("text/spelling")} +\newcommand{\loadDictionary}[1]{\directlua{spellChecker.loadDictionary([[#1]])}} +\def\@SpellCheckerFlag{false} +\def\enableSpellChecker{\def\@SpellCheckerFlag{true}} +\def\disableSpellChecker{\def\@SpellCheckerFlag{false}} +\newcommand{\spellCheck}[2][de/common] +{% + \ifthenelse{\equal{\@SpellCheckerFlag}{true}}% + {\expandafter\directlua{spellChecker.check([[#1]], [[\detokenize{#2}]])}}% + {#2}% +} + +\newcommand{\correct}[1]{\ifthenelse{\equal{\@SpellCheckerFlag}{true}}{\PDFmarkupComment{Marked as Correct}{#1}{Correct}{green}}{#1}} diff --git a/NixTeX/dependencies/source/text/text.tex b/NixTeX/dependencies/source/text/text.tex new file mode 100644 index 0000000..e69d4bf --- /dev/null +++ b/NixTeX/dependencies/source/text/text.tex @@ -0,0 +1,60 @@ +\directlua{includeCode("text/text")} +\inputCode{text/gender} +\inputCode{text/languages} +\inputCode{text/plain} +\inputCode{text/spelling} + +\newcommand\thinkDash[1][]{\directlua{text.thinkDash.setThreshold([[#1]])}} +\newcommand{\thd}[1][]{\directlua{text.thd([[#1]])} } +\newcommand{\elaborate}[1][]{\directlua{text.elaborate([[#1]])}} +\newcommand{\detailed }[2][]{} +\newcommand{\takeFirst}[2]{#1} +\newcommand{\PDFmarkupComment}[4] +{ + % 1 – comment + % 2 – text + % 3 – title + % 4 – colour + %\pdfmarkupcomment[markup=Highlight,author={#3},color={#4}]{#2}{#1}% + \pdfmargincomment[icon=Comment,author={#3},color={#4},date={\pdfDay}]{#1}\highLight[#4]{\trim@spaces{#2}}% +} +\newcommand{\PDFblockComment}[4] +{ + % 1 – comment + % 2 – text + % 3 – title + % 4 – colour + %\pdfmarkupcomment[markup=Highlight,author={#3},color={#4}]{#2}{#1}% + \pdfmargincomment[icon=Comment,author={#3},color={#4},date={\pdfDay}]{#1}% + \newline\noindent\textcolor{#4}{\rule{\textwidth}{0.5pt}}\newline\trim@spaces{#2}\newline\noindent\textcolor{#4}{\rule{\textwidth}{0.5pt}}% +} +\newcommand{\@reviewSide}[3]{\pdfmargincomment[icon=Comment,author={#2},color={#3},date={\pdfDay}]{\trim@spaces{#1}}} +\newcommand{\reviewSide }[2][] +{% + \ifthenelse{\equal{\@Annotations}{true}}% + {\ifthenelse{\equal{\@AnnotationsSolved|#1}{false|solved}}{}{\@reviewSide{#2}{#1}{\directlua{text.reviewColour([[#1]],[[#2]])}}}}% + {}% +} + +\newcommand{\reviewBlock }[3][] +{% + \ifthenelse{\equal{\@Annotations}{true}}% + {\ifthenelse{\equal{\@AnnotationsSolved|#1}{false|solved}}{#3}{\PDFblockComment{#2}{#3}{#1}{\directlua{text.reviewColour([[#1]],[[#2]])}}}}% + {#3}% +} + +\newcommand{\review }[3][] +{% + \ifthenelse{\equal{\@Annotations}{true}}% + {\ifthenelse{\equal{\@AnnotationsSolved|#1}{false|solved}}{#3}{\PDFmarkupComment{#2}{#3}{#1}{\directlua{text.reviewColour([[#1]],[[#2]])}}}}% + {#3}% +} + +\def\@Annotations{false} +\def\@AnnotationsSolved{true} +\def\disableAnnotations {\def\@Annotations{false}\directlua{text.annotate ( "false" )}} +\def\enableAnnotations {\def\@Annotations{true}\directlua{text.annotate ( "true" )}} +\def\hideSolved {\def\@AnnotationsSolved{false}} +\def\showSolved {\def\@AnnotationsSolved{true}} + +\newcommand{\organism}[2][]{\ifthenelse{\equal{#1}{}}{\textit{#2}}{(#1 \textit{#2})}} diff --git a/NixTeX/dependencies/source/tucSlides.tex b/NixTeX/dependencies/source/tucSlides.tex new file mode 100644 index 0000000..c2ccdfe --- /dev/null +++ b/NixTeX/dependencies/source/tucSlides.tex @@ -0,0 +1,67 @@ +\directlua +{ + class = "slides" + fontSize = "10pt" +} +\input{\source/code/common} +\input{\source/code/slides} + +\newcommand{\theSlides}[9][tuc] +{ + %1 – Fakultät + %2 – title + %3 – subtitle + %4 – author + %5 – date + %6 – logo + %7 – before document + %8 – content + %9 – appendix + \directlua + { + fakultaet = "#1" + } + \usepackage{\source/tuc/source/beamerthemetuc2014} + \mode
{\usepackage{\source/tuc/source/beamerarticletuc2014}} + \title{#2} + \subtitle{#3} + \author{#4} + \date{#5} + %\makeglossaries + #7 + \setbeameroption{\directlua{if hazDualScreen then tex.print([[show notes on second screen]]) end}} + \setbeamertemplate{note page}[plain] + \beamertemplatenavigationsymbolsempty + \begin{document} + \robfamily + %\let\oldprintslidenumber=\printslidenumber + %\renewcommand{\printslidenumber}[2]{\oldprintslidenumber{1}{1337}} + %\begingroup + %\section*{Titelseite}%\bookmarkthis + \setbeamertemplate{tuc2 headlines}[title] + \frame{\titlepage #6} + \setbeamertemplate{tuc2 headlines}[section] + %\endgroup + %\let\printslidenumber=\oldprintslidenumber + \newcommand{\slide}[4][t] + { + \begin{frame}[##1] + \ifthenelse{\isempty{##2}}{}{\frametitle{##2}} + \ifthenelse{\isempty{##3}}{}{\framesubtitle{##3}} + ##4 + \end{frame} + } + #8 + \renewcommand{\printslidenumber}[2]{Extra} + \renewcommand{\slide}[4][t] + { + \begin{frame}[noframenumbering,##1] + \ifthenelse{\isempty{##2}}{}{\frametitle{##2}} + \ifthenelse{\isempty{##3}}{}{\framesubtitle{##3}} + ##4 + \end{frame} + } + \section*{Extra}%\bookmarkthis + #9 + \end{document} +} diff --git a/NixTeX/dependencies/source/utils.tex b/NixTeX/dependencies/source/utils.tex new file mode 100644 index 0000000..8ebc662 --- /dev/null +++ b/NixTeX/dependencies/source/utils.tex @@ -0,0 +1,80 @@ +\directlua{includeCode("utils")} + +\newcommand{\ifnotempty }[2]{\ifthenelse{\equal{}{#1}}{}{#2}} +\newcommand{\ifempty }[2]{\ifthenelse{\equal{}{#1}}{#2}{}} +\newcommand{\ifnotEmpty }[2]{\ifthenelse{\isempty{#1}}{}{#2}} +\newcommand{\ifnotequal }[3]{\ifthenelse{\equal{#1}{#2}}{}{#3}} +\newcommand{\ifequal }[3]{\ifthenelse{\equal{#1}{#2}}{#3}{}} +\newcommand{\fourCases }[9][]{\ifthenelse{\equal{#1}{#2}}{#3}{}\ifthenelse{\equal{#1}{#4}}{#5}{\ifthenelse{\equal{#1}{#6}}{#7}{\ifthenelse{\equal{#1}{#8}}{#9}{}}}} + +\newcommand{\noWordBreaks}[1][500] +{% + % Maximum Badness tex is allowed to use while setting the paragraph, + % that is it inserts breakpoints allowing white space to stretch and penalties to be taken, + % so long as the badness keeps below this threshold. + % If it can not do that then you get overfull boxes. + % So different values produce different typeset result. + \tolerance #1% + % Used if TeX can not set the paragraph below the \tolerance badness, + % but rather than make overfull boxes it tries an extra pass "pretending" + % that every line has an additional \emergencystretch of stretchable glue, + % this allows the overall badness to be kept below 1000 and stops TeX "giving up" and + % putting all stretch into one line. + % So \emergencystretch does not change the setting of "good" paragraphs, + % it only changes the setting of paragraphs that would have produced overfull boxes. + % Note that you get warnings about the real badness calculation from TeX + % even though it retries with \emergencystretch the extra stretch is used + % to control the typesetting but it is not considered as good for the purposes of logging. + \emergencystretch 3em% + % Only Warn of Overfull \hbox, if Above This Value + \hfuzz=2pt% + % Only Warn of Overfull \vbox, if Above This Value + \vfuzz=2pt% + % Prevent Hyphenation + \hyphenchar\font=-1% +} + +\newcommand{\constPDF}[6] +{ + \pdfvariable suppressoptionalinfo \numexpr32+64+512\relax + \AtBeginDocument + { + \hypersetup + { + pdfauthor={#1}, + pdftitle={% + \directlua + { + if ( documentTitle == "" ) + then + tex.print([[#2]]) + else + tex.print(documentTitle) + end + }% + }, + pdfsubject={#3}, + pdfkeywords={#4}, + pdfproducer={#5}, + pdfcreator={#6}, + } + } +} + +\newcommand{\unchapter}[3][] +{% + \cleardoublepage% + \begingroup% + \let\@makechapterhead\@gobble % make \@makechapterhead do nothing + \chapter{#2}{#3}% + \endgroup% +}% + +\newcommand{\Cleardoublepage}[1][] +{% + \newpage% + %\ifthenelse{\equal{#1}{rotate}}{\rotatePages}{\unrotatePages}% + \thispagestyle{empty}% + %\leavevmode + \phantomsection% +} \ No newline at end of file diff --git a/NixTeX/dependencies/source/values/mod.tex b/NixTeX/dependencies/source/values/mod.tex new file mode 100644 index 0000000..98ecaac --- /dev/null +++ b/NixTeX/dependencies/source/values/mod.tex @@ -0,0 +1,2 @@ +\newcommand{\value}[3][]{\directlua { values.printValue ( [[#1]], [[#2]], [[#3]] )}} +\newcommand{\unit }[1] {\directlua { values.printUnit ( [[#1]] )}} diff --git a/NixTeX/flake.nix b/NixTeX/flake.nix new file mode 100644 index 0000000..b9177a6 --- /dev/null +++ b/NixTeX/flake.nix @@ -0,0 +1,23 @@ +{ + description = "NixTeX is a nix-library to create TeX-files and compile them e.g. to the Portable Document Format"; + inputs + = { + fork-awesome.url = "github:sivizius/nixfiles?dir=packages/fork-awesome"; + libconfig.url = "github:sivizius/nixfiles?dir=libs/config"; + libcore.url = "github:sivizius/nixfiles?dir=libs/core"; + nixpkgs.url = "github:sivizius/nixpkgs/master"; + }; + outputs + = { self, fork-awesome, libconfig, libcore, nixpkgs, ... }: + let + core = libcore.lib { inherit self; debug.logLevel = "info"; }; + in + { + lib + = core.path.import ./. + { + inherit core fork-awesome nixpkgs; + stdenv = libconfig.stdenv; + }; + }; +} diff --git a/NixTeX/source/common/bibliography/biblatex.nix b/NixTeX/source/common/bibliography/biblatex.nix new file mode 100644 index 0000000..28f955e --- /dev/null +++ b/NixTeX/source/common/bibliography/biblatex.nix @@ -0,0 +1,203 @@ +{ core, document, ... } @ libs: +let + inherit(core) debug list number path set string time type; + inherit(document) escapeEncode; + + formatAuthors + = let + formatParticle + = particle: + if particle != null + then + "${particle} " + else + ""; + formatSuffix + = suffix: + if suffix != null + then + ", ${suffix}" + else + ""; + in + string.concatMappedWith + ( + { + dropping-particle ? null, + family ? "", + given ? "", + suffix ? null, + ... + }: + "{${given}} {${formatParticle dropping-particle}${family}${formatSuffix suffix}}" + ) + " and "; + + formatCommon + = { authors, doi, title, url, ... }: + [ + ( toLine "author" ( formatAuthors authors ) ) + ( toLineEscapedAmpersand "title" title ) + ( toLine "doi" doi ) + ( toLine "url" url ) + ]; + + formatDate + = { day, month, year, ... }: + let + year' = "year = {${string year}}"; + month' = "month = {${string month}}"; + day' = "day = {${string day}}"; + in + if day != null + then + [ year' month' day' ] + else if month != null + then + [ year' month' ] + else + [ year' ]; + + formatPages + = pages: + if set.isInstanceOf pages + then + formatPagesFromTill pages + else + "pages = {${string pages}}"; + + formatPagesFromTill + = { from, till }: + if from != till + then + "pages = {${string from}–${string till}}" + else + "pages = {${string from}}"; + + getType + = variant: + { + Book = "book"; + BookChapter = "incollection"; + ConferenceArticle = "inproceeding"; + JournalArticle = "article"; + Patent = "patent"; + ReviewArticle = "article"; + }.${variant} + or (debug.panic "getType" "Invalid variant »${variant}«"); + + getFormatter + = shortJournalNames: + variant: + let + JournalArticle + = { issue, pages, ... }: + let + journalName + = if shortJournalNames + then + issue.journal.short + else + issue.journal.name; + in + ( formatDate issue.date ) + ++ [ + ( toLineEscapedAmpersand "journal" journalName ) + ( toLine "number" issue.number ) + ( formatPages pages ) + ( toLineEscapedAmpersand "publisher" issue.journal.publisher.name ) + ( toLine "volume" issue.volume ) + ]; + in + { + Book + = { date, isbn, publisher, series, ... }: + ( formatDate date ) + ++ [ + ( toLine "isbn" isbn ) + ( toLineEscapedAmpersand "publisher" publisher.name ) + ( toLineEscapedAmpersand "series" series ) + ]; + BookChapter + = { book, ... }: + [] + ++ [ + ( toLineEscapedAmpersand "booktitle" book.title ) + ] + ++ ( formatDate book.date ) + ++ [ + ( toLine "isbn" book.isbn ) + ( toLineEscapedAmpersand "publisher" book.publisher.name ) + ( toLineEscapedAmpersand "series" book.series ) + ]; + ConferenceArticle + = { conference, pages, ... }: + ( formatDate conference.date ) + ++ [ + ( toLineEscapedAmpersand "booktitle" conference.title ) + ( formatPages pages ) + ( toLineEscapedAmpersand "publisher" conference.publisher.name ) + ]; + inherit JournalArticle; + Patent + = { date, number, type, ... }: + ( formatDate date ) + ++ [ + ( toLine "number" number ) + ( toLine "type" type ) + ]; + ReviewArticle = JournalArticle; + }.${variant} + or (debug.panic "getFormatter" "Invalid variant »${variant}«"); + + toBibTeX + = { bibliography ? { }, ... }: + name: + { + __type__ ? (debug.panic "toBibTeX" "Entries must be generated using constructors"), + ... + } @ entry: + let + keys + = list.filter + (key: key != null) + ((formatCommon entry) ++ (getFormatter (bibliography.shortJournalNames or false) __type__ entry)); + in + '' + @${getType __type__}{${name}, + ${string.concatWith ",\n " keys} + } + ''; + + toLine + = name: + value: + if value != null + then + "${name} = {${string value}}" + else + null; + + toLineEscapedAmpersand + = name: + value: + if value != null + then + let + value' = string.replace [ "&" ] [ "\\&" ] value; + in + "${name} = {${string value'}}" + else + null; +in + { configuration, resources, ... }: + { ... } @ references: + let + references' = set.filterKeys (name: name != "__functor") references; + bibFile = path.fromSet "references.bib" (toBibTeX configuration) references'; + in + debug.info "load" "BibTeX-File: ${bibFile}" + { + src = bibFile; + dst = "generated/references.bib"; + } diff --git a/NixTeX/source/common/bibliography/default.nix b/NixTeX/source/common/bibliography/default.nix new file mode 100644 index 0000000..19eed13 --- /dev/null +++ b/NixTeX/source/common/bibliography/default.nix @@ -0,0 +1,18 @@ +{ core, ... } @ libs: + let + inherit(core) library; + libs' + = libs + // { + inherit bibliography; + }; + + bibliography = library.import ./definition.nix libs'; + toBibTeX = library.import ./biblatex.nix libs'; + prepare = library.import ./prepare.nix libs'; + evaluate = library.import ./evaluate.nix libs'; + in + { + inherit bibliography; + inherit prepare evaluate toBibTeX; + } \ No newline at end of file diff --git a/NixTeX/source/common/bibliography/definition.nix b/NixTeX/source/common/bibliography/definition.nix new file mode 100644 index 0000000..8747adc --- /dev/null +++ b/NixTeX/source/common/bibliography/definition.nix @@ -0,0 +1,288 @@ +{ core, document, ... }: +let + inherit(core) debug list number set string time type; + + adjustDate + = source: + date: + let + panic = debug.panic ( source ++ [ "adjustDate" ] ); + date' = time.from date; + in + if date' != null + then + date' + else + panic "Invalid date: »${date}«"; + + adjustPages + = source: + pages: + let + panic = debug.panic ( source ++ [ "adjustPages" ] ); + in + type.matchPrimitiveOrPanic pages + { + "int" + = { + from = pages; + till = pages; + }; + "set" + = { + from = pages.from or ( panic "Pages need a from!" ); + till = pages.till or ( panic "Pages need a till!" ); + }; + "string" + = let + pages' = string.match "([^-]+)--?([^-]+)" pages; + in + if pages' != null + then + { + from = list.get pages' 0; + till = list.get pages' 1; + } + else + let + page = number.toInteger' pages; + in + if page != null + then + { + from = page; + till = page; + } + else + let + page = string.match "!?(.*)" pages; + in + list.head page; + }; + + adjustWhitespace + = text: + string.concatMapped + ( + item: + if string.isInstanceOf item + then + item + else + " " + ) + ( string.trim' text ); + + toChapterBook + = source: + let + source' = source ++ [ "toChapterBook" ]; + in + { + date ? ( debug.panic source' "Need a date!" ), + isbn ? null, + publisher ? ( debug.panic source' "Needs a publisher!" ), + series ? null, + title ? ( debug.panic source' "Needs a title!" ) + }: + { + date = adjustDate source' date; + title = adjustWhitespace title; + series + = if series != null + then + adjustWhitespace series + else + null; + inherit isbn publisher; + }; + + toConference + = source: + let + source' = source ++ [ "toConference" ]; + in + { + date ? ( debug.panic source' "Need a date!" ), + publisher ? ( debug.panic source' "Needs a publisher!" ), + title ? ( debug.panic source' "Needs a title!" ) + }: + { + date = adjustDate source' date; + title = adjustWhitespace title; + inherit publisher; + }; + + toIssue + = source: + let + source' = source ++ [ "toIssue" ]; + in + { + date ? ( debug.panic source' "Need a date!" ), + journal ? ( debug.panic source' "Need a journal!" ), + number ? null, + volume ? null + }: + { + date = adjustDate source' date; + journal = toJournal source' journal; + inherit number volume; + }; + + toJournal + = source: + let + source' = source ++ [ "toJournal" ]; + in + { + name ? ( debug.panic source' "Need a name!" ), + publisher ? ( debug.panic source' "Need a publisher!" ), + short ? "" + }: + { + name = adjustWhitespace name; + short = adjustWhitespace short; + publisher = toPublisher source' publisher; + }; + + toPublisher + = source: + let + source' = source ++ [ "toPublisher" ]; + in + { + name ? ( debug.panic source' "Needs a name!" ), + ... + } @ publisher: + publisher + // { + name = adjustWhitespace name; + }; +in +{ + Article + = { + authors ? ( debug.panic "Article" "Need some authors!" ), + doi ? null, + issue ? ( debug.panic "Article" "Need an issue!" ), + pages ? ( debug.panic "Article" "Need pages!" ), + title ? ( debug.panic "Article" "Need a title!" ), + url ? null, + ... + } @ article: + article + // { + __type__ = "JournalArticle"; + title = adjustWhitespace title; + inherit authors doi url; + + pages = adjustPages [ "Article" ] pages; + issue = toIssue [ "Article" ] issue; + }; + + Book + = { + authors ? ( debug.panic "Book" "Need some authors!" ), + date ? ( debug.panic "Book" "Need a date!" ), + doi ? null, + isbn ? null, + publisher ? ( debug.panic "Book" "Need a publisher!" ), + series ? null, + title ? ( debug.panic "Book" "Need a title!" ), + url ? null, + ... + } @ book: + book + // { + __type__ = "Book"; + title = adjustWhitespace title; + inherit authors doi url; + + date = adjustDate [ "Book" ] date; + inherit isbn publisher series; + }; + + Chapter + = { + authors ? ( debug.panic "Chapter" "Need some authors!" ), + book ? ( debug.panic "Chapter" "Need a book!" ), + doi ? null, + title ? ( debug.panic "Chapter" "Need a title!" ), + url ? null, + ... + } @ chapter: + chapter + // { + __type__ = "BookChapter"; + title = adjustWhitespace title; + inherit authors doi url; + + book = toChapterBook [ "Chapter" ] book; + }; + + ConferenceArticle + = { + authors ? ( debug.panic "ConferenceArticle" "Need some authors!" ), + conference ? ( debug.panic "ConferenceArticle" "Need a conference!" ), + doi ? null, + title ? ( debug.panic "ConferenceArticle" "Need a title!" ), + pages ? ( debug.panic "ConferenceArticle" "Need pages!" ), + url ? null, + ... + } @ paper: + paper + // { + __type__ = "ConferenceArticle"; + title = adjustWhitespace title; + inherit authors doi url; + + pages = adjustPages [ "ConferenceArticle" ] pages; + conference = toConference [ "ConferenceArticle" ] conference; + }; + + Patent + = { + authors ? ( debug.panic "Patent" "Need some authors!" ), + date ? ( debug.panic "Patent" "Need a date!" ), + doi ? null, + number ? ( debug.panic "Patent" "Need a Number!" ), + stage ? null, + title ? ( debug.panic "Patent" "Need a title!" ), + type ? ( debug.panic "Patent" "Need a type!" ), + url ? null, + ... + } @ patent: + patent + // { + __type__ = "Patent"; + title = adjustWhitespace title; + inherit authors doi url; + + date = adjustDate [ "Patent" ] date; + inherit number stage type; + }; + + Review + = { + authors ? ( debug.panic "Review" "Need some authors!" ), + doi ? null, + issue ? ( debug.panic "Review" "Need an issue!" ), + pages ? ( debug.panic "Review" "Need pages!" ), + title ? ( debug.panic "Review" "Need a title!" ), + url ? null, + ... + } @ review: + review + // { + __type__ = "ReviewArticle"; + title = adjustWhitespace title; + inherit authors doi url; + + pages = adjustPages [ "Review" ] pages; + issue = toIssue [ "Review" ] issue; + }; + + Journal = toJournal [ "Journal" ]; + Publisher = toPublisher [ "Publisher" ]; +} diff --git a/NixTeX/source/common/bibliography/evaluate.nix b/NixTeX/source/common/bibliography/evaluate.nix new file mode 100644 index 0000000..3a518f7 --- /dev/null +++ b/NixTeX/source/common/bibliography/evaluate.nix @@ -0,0 +1,27 @@ +{ core, document, ... } @ libs: +let + inherit(core) list; +in +{ + initEvaluationState + = { + __functor + = list.fold + ( + { counter, list, lookUp, ... } @ self: + name: + if lookUp.${name} or null == null + then + { + counter = counter + 1; + list = list ++ [ name ]; + lookUp = lookUp // { ${name} = counter; }; + } + else + self + ); + counter = 0; + list = [ ]; + lookUp = { }; + }; +} \ No newline at end of file diff --git a/NixTeX/source/common/bibliography/prepare.nix b/NixTeX/source/common/bibliography/prepare.nix new file mode 100644 index 0000000..9291e93 --- /dev/null +++ b/NixTeX/source/common/bibliography/prepare.nix @@ -0,0 +1,111 @@ +{ bibliography, core, document, ... } @ libs: +let + inherit(core) debug list path set string type; + inherit(document) escapeEncode; + + citeList + = self: + citations: + let + result + = list.fold + ( + { encode, range, previous, text, ... } @ state: + name: + if self.${name} or null != null + then + if self.${name} ? id + then + state + // { + range = previous != null && self.${name}.id == ( previous + 1 ); + previous = self.${name}.id; + text + = if text == null + then + "${string self.${name}.id}" + else if previous != null + && self.${name}.id == ( previous + 1 ) + then + text + else if range + then + "${text}–${string self.${name}.id}" + else + "${text},${string self.${name}.id}"; + } + else + { + encode = encode ++ [ name ]; + } + else + debug.panic "citeList" "Unknown Reference »${name}«!" + ) + { + range = false; + previous = null; + text = null; + encode = [ ]; + } + citations; + text + = if result.text != null + then + result.text + else + "[???]"; + in + if result.encode == [] + then + "\\textsuperscript{[${text}]}" + else + escapeEncode "bibliography" result.encode; + + citeString + = self: + name: + if self.${name} or null != null + then + if self.${name}.id or null != null + then + "\\textsuperscript{[${string self.${name}.id}]}" + else + escapeEncode "bibliography" [ name ] + else + debug.panic "citeString" "Unknown Reference »${name}«!"; + + prepare + = references: + type.matchPrimitiveOrPanic references + { + lambda = prepare ( references libs ); + path = prepare ( path.import references ); + set + = ( + set.map + ( + name: + value: + value + // { + inherit name; + __toString + = self: + "\\cite{${name}}"; + } + ) + references + ) + // { + __functor + = self: + name: + type.matchPrimitiveOrPanic name + { + #list = citeList self name; + string = citeString self name; + }; + }; + }; +in + prepare \ No newline at end of file diff --git a/NixTeX/source/common/chemistry/compound.nix b/NixTeX/source/common/chemistry/compound.nix new file mode 100644 index 0000000..64b8d8d --- /dev/null +++ b/NixTeX/source/common/chemistry/compound.nix @@ -0,0 +1,22 @@ +{ core, document, ... } @ libs: +let + inherit(core) debug string type; + + format + = compound: + type.matchPrimitiveOrPanic compound + { + string = "\\directlua{chem.compounds.texPrint([[${compound}]])}"; + list = "\\directlua{chem.compounds.texPrint([[${string.concatWith "||" compound}]])}"; + }; + from + = compound: + { + input = compound; + __toString = { input, ... }: format input; + }; +in +{ + inherit format from; + __functor = { ... }: from; +} \ No newline at end of file diff --git a/NixTeX/source/common/chemistry/default.nix b/NixTeX/source/common/chemistry/default.nix new file mode 100644 index 0000000..c0149e1 --- /dev/null +++ b/NixTeX/source/common/chemistry/default.nix @@ -0,0 +1,43 @@ +{ chemistry, core, ... } @ libs: +let + inherit(core) library; + + elements = library.import ./elements.nix libs; + compound = library.import ./compound.nix libs; + groups + = let + inherit (elements.fullTable) C Fe H O P S; + Ac = [ Me C O 2 ]; + CC = [ C 2 ]; + CH2 = [ C H 2 ]; + Et = [ Me CH2 ]; + Fc = [ Fe C 10 H 9 ]; + Fc' = [ Fe C 10 H 8 ]; + Me = [ C H 3 ]; + Ms = [ Me S O 3 ]; + Ph = [ C 6 H 5 ]; + Pyr = [ C 16 H 8 ]; + in + { inherit Ac CC CH2 Et Fc Fc' Me Ms Ph Pyr; }; + ir = library.import ./ir.nix libs; + journal = library.import ./journal.nix libs; + ligands + = let + inherit(elements.fullTable) C O P; + inherit(groups) Fc' Ph; + in + { + CO = [ C O ]; + dppf = [ Fc' [ P Ph 2 ] 2 ]; + }; + ms = library.import ./ms.nix libs; + nmr = library.import ./nmr.nix libs; + substances = library.import ./substances libs; + symbols = elements.fullTable // groups // ligands; + synthesis = library.import ./synthesis.nix libs; + values = library.import ./values.nix libs; +in +{ + inherit compound elements groups ir journal ligands ms nmr substances synthesis symbols values; + inherit(substances) Substance Mixture; +} \ No newline at end of file diff --git a/NixTeX/source/common/chemistry/elements.nix b/NixTeX/source/common/chemistry/elements.nix new file mode 100644 index 0000000..4355f6f --- /dev/null +++ b/NixTeX/source/common/chemistry/elements.nix @@ -0,0 +1,277 @@ +{ core, physical, ... }: +let + inherit(core) debug list number set string type; + inherit(physical) formatValue; + + fullTable + = set.map (symbol: value: value // { inherit symbol; } ) + { + # Period 1 + H = { dalton = 1.0080; }; + He = { dalton = 4.0026; }; + + # Period 2 + Li = { dalton = 6.94; }; + Be = { dalton = 9.0122; }; + B = { dalton = 10.81; }; + C = { dalton = 12.011; }; + N = { dalton = 14.007; }; + O = { dalton = 15.999; }; + F = { dalton = 18.998; }; + Ne = { dalton = 20.180; }; + + # Period 3 + Na = { dalton = 22.990; }; + Mg = { dalton = 24.305; }; + Al = { dalton = 26.982; }; + Si = { dalton = 28.085; }; + P = { dalton = 30.974; }; + S = { dalton = 32.06; }; + Cl = { dalton = 35.45; }; + Ar = { dalton = 39.948; }; + + # Period 4 + K = { dalton = 39.098; }; + Ca = { dalton = 40.078; }; + Sc = { dalton = 44.956; }; + Ti = { dalton = 47.867; }; + V = { dalton = 50.942; }; + Cr = { dalton = 51.996; }; + Mn = { dalton = 54.938; }; + Fe = { dalton = 55.845; }; + Co = { dalton = 58.933; }; + Ni = { dalton = 58.693; }; + Cu = { dalton = 63.546; }; + Zn = { dalton = 65.380; }; + Ga = { dalton = 69.723; }; + Ge = { dalton = 72.630; }; + As = { dalton = 74.922; }; + Se = { dalton = 78.971; }; + Br = { dalton = 79.904; }; + Kr = { dalton = 83.798; }; + + # Period 5 + Rb = { dalton = 85.468; }; + Sr = { dalton = 87.620; }; + Y = { dalton = 88.906; }; + Zr = { dalton = 91.224; }; + Nb = { dalton = 92.906; }; + Mo = { dalton = 95.950; }; + Tc = { dalton = 97.4; }; + Ru = { dalton = 101.07; }; + Rh = { dalton = 102.91; }; + Pd = { dalton = 106.42; }; + Ag = { dalton = 107.87; }; + Cd = { dalton = 112.41; }; + In = { dalton = 114.82; }; + Sn = { dalton = 118.71; }; + Sb = { dalton = 121.76; }; + Te = { dalton = 127.60; }; + I = { dalton = 126.90; }; + Xe = { dalton = 131.29; }; + + # Period 6 + Cs = { dalton = 132.91; }; + Ba = { dalton = 137.33; }; + # = { dalton = ; }; + # = { dalton = ; }; + # = { dalton = ; }; + # = { dalton = ; }; + # = { dalton = ; }; + # = { dalton = ; }; + # = { dalton = ; }; + # = { dalton = ; }; + # = { dalton = ; }; + # = { dalton = ; }; + # = { dalton = ; }; + # = { dalton = ; }; + # = { dalton = ; }; + # = { dalton = ; }; + # = { dalton = ; }; + # = { dalton = ; }; + # = { dalton = ; }; + # = { dalton = ; }; + # = { dalton = ; }; + # = { dalton = ; }; + # = { dalton = ; }; + # = { dalton = ; }; + # = { dalton = ; }; + # = { dalton = ; }; + # = { dalton = ; }; + Pb = { dalton = 207.20; }; + Bi = { dalton = 208.98; }; + Po = { dalton = 209.98; }; + At = { dalton = 210; }; + Rn = { dalton = 222; }; + + # Period 7 + }; + tableOfMasses = set.mapValues ( value: value.dalton ) fullTable; + + normaliseMolecularFormula + = let + addElements + = { ... } @ elements: + previous: + count: + type.matchPrimitiveOrPanic previous + { + set + = set.fold + ( + { ... } @ elements: + name: + previous: + elements + // { + ${name} = previous * count + ( elements.${name} or 0 ); + } + ) + elements + previous; + string + = elements + // { + ${previous} = ( elements.${previous} or 0 ) + count; + }; + null = elements; + }; + getSymbol = foo: foo.symbol or foo; + parse + = { elements, previous } @ this: + token: + type.matchPrimitiveOrPanic token + { + int + = if previous != null + then + { + elements = addElements elements previous token; + previous = null; + } + else + debug.panic [ "normaliseMolecularFormula" "parse" ] "Unexpected Number!"; + list + = { + elements = addElements elements previous 1; + previous = normalise token; + }; + set + = { + elements = addElements elements previous 1; + previous = getSymbol token; + }; + string + = { + elements = addElements elements previous 1; + previous = token; + }; + }; + defaultState + = { + elements = { }; + previous = null; + }; + finalise = { elements, previous }: addElements elements previous 1; + normalise + = this: + finalise ( list.fold parse defaultState this ); + in + this: finalise (parse defaultState this); + + calculateMassOfFormula + = formula: + debug.debug "calculateMassOfFormula" + { + text = "Molecular Formula"; + data = formula; + } + ( + type.matchPrimitiveOrPanic formula + { + null = null; + set + = set.fold + ( + state: + symbol: + count: + ( state + count * ( tableOfMasses.${symbol} or (debug.panic "calculateMassOfFormula" "Unknown symbol: ${symbol}")) ) + ) + 0 + formula; + } + ); + + formatMolecularFormula + = { ... } @ formula: + list.fold + ( + result: + symbol: + let + count = formula.${symbol} or 0; + in + if count == 0 + then + result + else if count == 1 + then + "${result}${symbol}" + else + "${result}${symbol}${string count}" + ) + "" + ( + if formula.C or 0 == 0 + then + set.names fullTable + else + [ + "C" "H" + "Ag" "Al" "Ar" "As" "At" "B" "Ba" "Be" "Bi" "Br" "Ca" "Cd" "Cl" "Co" + "Cr" "Cs" "Cu" "F" "Fe" "Ga" "Ge" "He" "I" "In" "K" "Kr" "Li" "Mg" + "Mn" "Mo" "N" "Na" "Nb" "Ne" "Ni" "O" "P" "Pb" "Pd" "Po" "Rb" "Rh" + "Rn" "Ru" "S" "Sb" "Sc" "Se" "Si" "Sn" "Sr" "Tc" "Te" "Ti" "V" "Xe" + "Y" "Zn" "Zr" + ] + ); + + mapAnalysis + = { formula, ... } @ substance: + { ... } @ gotElements: + if gotElements != { } + then + let + formula' = normaliseMolecularFormula formula; + format + = elements: + string.concatWith ", " + ( + set.mapToList + ( + symbol: + value: + "\\ch{${symbol}}:~${formatValue { inherit value; precision = 2; } "percent"}" + ) + elements + ); + calculated + = let + mapped = set.map (symbol: value: tableOfMasses.${symbol} * value) formula'; + sum = number.sum (set.values mapped); + filtered = set.map (symbol: _: mapped.${symbol} or 0.0 ) gotElements; + calcElements = set.mapValues (value: value / sum * 100.0) filtered; + in + format calcElements; + found = format gotElements; + in + [ "Elementar\\-analyse berechnet für \\ch{${formatMolecularFormula formula'}}: ${calculated}; gefunden: ${found}." ] + else + [ ]; +in +{ + inherit normaliseMolecularFormula formatMolecularFormula calculateMassOfFormula; + inherit mapAnalysis; + inherit fullTable tableOfMasses; +} diff --git a/NixTeX/source/common/chemistry/ir.nix b/NixTeX/source/common/chemistry/ir.nix new file mode 100644 index 0000000..b2b2186 --- /dev/null +++ b/NixTeX/source/common/chemistry/ir.nix @@ -0,0 +1,378 @@ +{ core, document, ... } @ libs: +let + inherit(core) debug indentation lambda list number path set string type; + inherit(document) ClearPage Heading' LaTeX PhantomHeading; + + getDetails + = minimum: + peak: + string.concatWith ", " + ( + list.filter (x: x != null) + [ + ( + let + strength = ( 100.0 - peak.y ) / ( 100.0 - minimum ) * 1.2; + in + if strength >= 0.7 then "s" + else if strength <= 0.3 then "w" + else "m" + ) + ( + let + assignment = "\\ch{${peak.assignment}}"; + type + = { + stretching = "\\nu"; + bending = "\\delta"; + scissoring = "\\delta"; + rocking = "\\gamma"; + twisting = "\\tau"; + wagging = "\\kappa"; + }.${peak.type} or "???"; + symmetric + = if peak.sym == null then "" + else if peak.sym then "\\textsubscript{s}" + else "\\textsubscript{as}"; + in + if peak.assignment == null then null + else if peak.type == null then "${assignment}" + else "${symmetric}${type}(${assignment})" + ) + ] + ); + + getXpos + = peak: + if set.isInstanceOf peak.x then "${string (number.round peak.x.from)}–${string (number.round peak.x.till)}" + else (string (number.round peak.x)); + + reportSpectrum + = { acronyms, ... }: + spectrum: + let + signals + = list.filter + ( + { y, ... }: + let + strength = ( 100.0 - y ) / ( 100.0 - spectrum.min ) * 1.2; + in + strength >= 0.3 + ) + spectrum.signals; + signals' + = list.sort + ( + first: + second: + let + first' + = if list.isInstanceOf first.x + then + list.head first.x + else if set.isInstanceOf first.x + then + first.x.from + else + first.x; + second' + = if list.isInstanceOf second.x + then + list.head second.x + else if set.isInstanceOf second.x + then + second.x.from + else + second.x; + in + debug.info "compare ir-signals" { data = { first = first.x; second = second.x; }; } + first' > second' + ) + signals; + spectrum' + = list.map + ( peak: "${getXpos peak} (${getDetails spectrum.min peak})" ) + signals'; + note + = if spectrum.note or null != null + then + "${spectrum.note}, " + else + ""; + in + if spectrum' != [ ] + then + LaTeX + ( + [ + "\\mbox{}\\textbf{${acronyms.infrared.short}} (${note}${acronyms.waveNumber.short}/${acronyms.cm-1.short}):" + indentation.more + ] + ++ ( list.generate (x: "${list.get spectrum' x},") (( list.length spectrum' ) - 1) ) + ++ [ + "${list.foot spectrum'}." + indentation.less + ] + ) + else + null; + + genPeaks + = list.map + ( + peak: + let + x' + = if set.isInstanceOf peak.x + then + ( peak.x.from + peak.x.till ) / 2 + else + peak.x; + x = string (number.round x'); + y = string peak.y; + z = string (number.round ( x' + peak.z or 0 )); + colour = "0x00aaaaaa"; + in + '' + set arrow from first ${x}, graph 0.2 to first ${x}, first ${y} nohead lc rgb "${colour}" + set arrow from first ${x}, graph 0.2 to first ${z}, graph 0.13 nohead lc rgb "${colour}" + set label "\\tiny ${x}" right rotate by 90 at first ${z}, graph 0.12 + '' + ); + genAppendix + = { acronyms, ... }: + { journal ? "", substance, ... } @ product: + { label ? null, plot, min, max, note ? null, range, signals ? [], ... } @ spectrum: + if plot != null + then + let + fileName + = let + plot' = path.getBaseName plot; + matching = string.match "(.+)[.]plot$" plot'; + in + if matching != null + then + list.head matching + else + plot'; + + body + = '' + ${string.concat ( genPeaks signals )} + set xlabel "{\\small ''${\${acronyms.waveNumber.short} / \${acronyms.cm-1.short}}$}" + set ylabel "{\\small ''${\\text{Transmission} / \${acronyms.percent.short}}$}" + set xrange [${string range.max}:${string range.min}] + set yrange [${string min}:${string max}] + plot "${plot}" notitle with lines lt rgb "0x00777777" + set output + ''; + + hash = string.hash "sha1" body; + dst = "generated/appendix/ir/${hash}-plot"; + epsFile = "${dst}.eps"; + texFile = "${dst}.tex"; + gnuplotSourceFile + = path.toFile "${hash}.gnuplot" + '' + set terminal epslatex + set output "${epsFile}" + ${body} + ''; + gnuplotDestinationFile = "${dst}.gnuplot"; + + src + = output: + string.concatWith " && " + [ + "(mkdir -p \"generated/appendix/ir/${substance.name}/\"" + "gnuplot \"${gnuplotSourceFile}\"" + "mv \"${texFile}\" \"${output}.tex\"" + "epstopdf \"${epsFile}\" \"${output}.pdf\")" + ]; + note' + = if note != null + then + " (${note})" + else + ""; + in + Heading' "${acronyms.infrared.short}-Spektrum~${substance.NameID}${note'}" + [ + ( + LaTeX + ( + ( + if label != null + then + [ "\\labelAppendix{ir:${label}}%" ] + else + [ ] + ) + ++ ( + if true + then + [ + "\\vspace{-1\\normalbaselineskip}" + "\\begin{figure}[H]%" indentation.more + "\\centering%" + "\\begin{adjustbox}%" indentation.more + "{max width=\\textwidth,max height=.4\\textheight,keepaspectratio}%" + "{\\input{\\source/${texFile}}}%" + indentation.less "\\end{adjustbox}%" + indentation.less "\\end{figure}%" null + ] + else + [ + "\\begin{figure}[H]%" indentation.more + "\\centering%" + "\\begin{adjustbox}%" indentation.more + "{angle=90,min width=\\textwidth,min totalheight=\\textheightleft,max width=\\textwidth,max totalheight=\\textheightleft-2em}%" + "{\\input{\\source/${texFile}}}%" + indentation.less "\\end{adjustbox}%" + indentation.less "\\end{figure}%" null + ] + ) + ) + ) + ] + { + clearPage = false; +# rotate = false; + before = "\\refstepcounter{ctrAppendix}%"; + dependencies + = [ + { src = gnuplotSourceFile; dst = gnuplotDestinationFile; } + { inherit dst src; } + ]; + } + else + [ ]; + genAppendix' + = resources: + { failure ? false, ... } @ product: + let + ir + = product.ir + or product.substance.ir + or null; + genAppendix' = genAppendix resources product; + in + if ir != null + && !failure + then + if list.isInstanceOf ir + then + list.map genAppendix' ir + else + [ ( genAppendix' ir ) ] + else + [ ]; + generateAppendix + = syntheses: + { configuration, resources, ... } @ document: + let + syntheses' + = if path.isInstanceOf syntheses + then + import + syntheses + (libs // { chemistry = libs.chemistry // { ir = null; }; }) + document + else + syntheses; + in + LaTeX + [ + ( ClearPage ) + ( + PhantomHeading + ( + PhantomHeading + ( + list.concatMap + ( + synthesis: + if synthesis ? product + then + let + product + = if lambda.isInstanceOf synthesis.product then synthesis.product { } + else synthesis.product; + in + if list.isInstanceOf product then list.map (genAppendix' resources) product + else [ ( genAppendix' resources product ) ] + else + [ ] + ) + ( + if list.isInstanceOf syntheses' + then + syntheses' + else + syntheses'.list + ) + ) + ) + ) + ]; + + report + = { ... } @ resources: + spectra: + let + reportSpectrum' = reportSpectrum resources; + in + if list.isInstanceOf spectra + then + list.filter + (x: x != null) + (list.map reportSpectrum' spectra) + else + [ ( reportSpectrum' spectra ) ]; + + Spectrum + = plot: + config: + signals: + { + inherit plot signals; + min = config.min or (-10); + max = config.max or 101; + range + = { + min = ( config.range or {} ).min or 500; + max = ( config.range or {} ).max or 4000; + }; + note = config.note or null; + }; + Signal + = x: y: z: + type: + sym: + assignment: + { + x + = type.matchPrimitiveOrDefault x + { + set + = { + from = x.from; + till = x.till; + }; + list + = { + from = list.get x 0; + till = list.get x 1; + }; + } + x; + inherit y z type sym assignment; + }; +in + { + inherit generateAppendix report; + inherit Spectrum Signal; + Signal' = x: y: z: Signal x y z null null null; + } \ No newline at end of file diff --git a/NixTeX/source/common/chemistry/journal.nix b/NixTeX/source/common/chemistry/journal.nix new file mode 100644 index 0000000..8cbe818 --- /dev/null +++ b/NixTeX/source/common/chemistry/journal.nix @@ -0,0 +1,178 @@ +{ chemistry, core, document, ... }: +let + inherit(chemistry) compound; + inherit(core) debug indentation integer list set string type; + + formatJournal' + = substance: + if substance ? simple + then + "\\ch{${substance.simple}}" + else + compound.format substance.title; + + formatJournal + = product: + if product.ignore or false + then + null + else if product.substance != null + then + if list.isInstanceOf product.substance + then + string.concatWith " + " ( list.map formatJournal' product.substance ) + else + formatJournal' product.substance + else if product ? title + then + "\\textbf{${product.title}}" + else + "a???"; + + productAsList + = syn: + product: + type.matchPrimitiveOrDefault product + { + list = product; + lambda = productAsList syn ( product syn ); + } + [ product ]; + + idToFloat + = id: + let + matched = string.match "([0-9]+)([A-Z])" id; + letters = string.toCharacters "ABCDEFGHIJKLMNOPQRSTUVWXYZ"; + letters' = list.generate (x: { name = list.get letters x; value = 0.01 * x; } ) ( list.length letters ); + lookUpLetter = list.toSet letters'; + in + if matched != null + then + integer ( list.get matched 0 ) + lookUpLetter.${ list.get matched 1 } + else + 0; + + compareIDs + = a: + b: + let + a' = if string.isInstanceOf a.id then idToFloat a.id else a.id; + b' = if string.isInstanceOf b.id then idToFloat b.id else b.id; + in + a' < b'; + + generateJournal' + = items: + let + items' + = list.fold + ( + items: + item: + if item ? journal + then + items + ++ ( + list.map + ( + id: + { + inherit id; + title = item.title or "—"; + product = formatJournal item; + reaction = item.reaction or null; + chemicals = item.chemicals or {}; + } + ) + item.journal + ) + else + items ++ ( generateJournal' ( productAsList null ( item.product or [ ] ) ) ) + ) + [ ] + items; + in + list.sort compareIDs items'; + + formatJournalEntry + = entry: + if entry.product != null + then let + getSimple + = input: + if input.substance or null != null + then + input.substance.simple or "b???" + else if input.acronym or null != null + then + "<${input.acronym}>" + else if input.simple or null != null + then + input.simple + else + null; + mapInput + = list.map + ( + input: + if list.isInstanceOf input + then let + simple = getSimple ( list.get input 1 ); + in + "\\ch{${string ( list.get input 0 )} ${if simple != null then simple else "??"}}" + else let + simple = getSimple input; + in if simple != null + then + "\\ch{${simple}}" + else + "c???" + ); + inputs + = if entry.reaction != null + then let + reaction = entry.reaction entry; + first = list.head reaction; + other = list.filter ( entry: set.isInstanceOf entry && entry ? input ) reaction; + other' = list.concatMap ( entry: entry.input ) other; + in + string.concatWith " + " ( mapInput ( first ++ other' ) ) + else + "…"; + in + debug.debug "formatJournalEntry" "${string entry.id}: ${entry.product}" "${string entry.id} & ${inputs} & ${entry.product}\\\\" + else + debug.debug "formatJournalEntry" "${string entry.id}: ${entry.title}" "${string entry.id} & \\multicolumn{2}{l}{${entry.title}} \\\\"; + + generateJournal + = syntheses: + { ... } @ arguments: + let + syntheses' + = if path.isInstanceOf syntheses + then + import syntheses ( { core = null; } // arguments ) + else + syntheses; + in + document.LaTeX + ( + [ + "\\ltable{l|l@{$\\rightarrow$}l}" + "{Kürzel & \\multicolumn{2}{l}{Reaktion und Produkt} \\\\}" + "{Kürzel & \\multicolumn{2}{l}{Reaktion und Produkt} \\\\}" + "{" indentation.more + ] + ++ ( list.map formatJournalEntry ( generateJournal' syntheses' ) ) + ++ [ + indentation.less "}" + "{}{}" + "{Zuordnung der Kürzel im Labor\\-journal zu den durchgeführten Reaktionen/Produkten.}" + "{ZuordnungKuerzelReaktion}" + ] + ); +in +{ + inherit generateJournal; +} \ No newline at end of file diff --git a/NixTeX/source/common/chemistry/ms.nix b/NixTeX/source/common/chemistry/ms.nix new file mode 100644 index 0000000..32064f0 --- /dev/null +++ b/NixTeX/source/common/chemistry/ms.nix @@ -0,0 +1,252 @@ +{ chemistry, core, document, physical, ... } @ libs: +let + inherit(core) debug indentation list number string type; + inherit(document) ClearPage Heading' LaTeX PhantomHeading; + inherit(physical) formatUnit; + inherit(number) toStringWithPrecision; + inherit(chemistry.elements) calculateMassOfFormula formatMolecularFormula normaliseMolecularFormula; + + adjustIons#: [ string ] -> [ string ] + = ions: + let + len-1 = ( list.length ions ) - 1; + in + if ions != [ ] + then + ( list.generate (x: "${list.get ions x};") len-1 ) ++ [ "${list.get ions len-1}." ] + else + [ ]; + + genAppendix#: Product -> [ string ] + = resources: + { substance, ... }: + { full, ions, ... }: + let + files + = ( + if full != null + then + [ + { + file = full; + title = "Übersichts\\-spektrum von ${substance.NameID}"; + } + ] + else + [] + ) + ++ ( + list.concatMap + ( + { file, formattedFormula, ... }: + if file != null + then + [ + { + inherit file; + title = "Isotopen\\-muster für ${formattedFormula} von ${substance.NameID}"; + } + ] + else + debug.warn "genAppendix" "File missing for ${formattedFormula}!" [] + ) + ions + ); + in + list.map + ( + { file, title }: + Heading' title + ( + LaTeX + [ + "\\vspace{-1\\normalbaselineskip}" + "\\begin{figure}[H]%" indentation.more + "\\centering%" + "\\begin{adjustbox}%" indentation.more + "{max width=\\textwidth,max height=.4\\textheight,keepaspectratio}%" + "\\includegraphics{${file}}%" + indentation.less "\\end{adjustbox}%" + indentation.less "\\end{figure}%" null + ] + ) + { + before = "\\refstepcounter{ctrAppendix}%"; + } + ) + files; + + genAppendix' + = resources: + { failure ? false, ... } @ product: + let + ms + = product.ms + or product.substance.ms + or null; + in + if ms != null + && !failure + then + genAppendix resources product ms + else + [ ]; + + generateAppendix + = syntheses: + { configuration, resources, ... } @ document: + let + syntheses' + = if type.isPath syntheses + then + import + syntheses + (libs // { chemistry = libs.chemistry // { ms = null; }; }) + document + else + syntheses; + in + LaTeX + [ + ( ClearPage ) + ( + PhantomHeading + ( + PhantomHeading + ( + list.concatMap + ( + synthesis: + if synthesis ? product + then + let + product + = if type.isLambda synthesis.product then synthesis.product { } + else synthesis.product; + in + if type.isList product then list.map (genAppendix' resources) product + else [ ( genAppendix' resources product ) ] + else + [ ] + ) + ( + if type.isList syntheses' + then + syntheses' + else + syntheses'.list + ) + ) + ) + ) + ]; + + mapIons + = list.map + ( + { calculated ? null, charge, formula, found, mrm ? null, ... } @ ion: + let + charge' + = if charge == 0 + then + "" + else if charge == 1 + then + "+" + else if charge == -1 + then + "\\minus" + else if charge > 0 + then + "+${string charge}" + else + "\\minus${string (0 - charge)}"; + found' = toStringWithPrecision found 4; + formula' = normaliseMolecularFormula formula; + formula'' = formatMolecularFormula formula'; + mass + = if calculated != null + then + calculated + else + calculateMassOfFormula formula'; + mass' = toStringWithPrecision mass 4; + delta = ((found - mass) / mass) * 1000 * 1000; + delta' + = if delta < 0 + then + "-\\text{${toStringWithPrecision (-delta) 2}}" + else + "\\text{${toStringWithPrecision delta 2}}"; + + formattedCalc = "berechnet für ${formattedFormula}: ${mass'}, "; + formattedDelta = "\${\\Delta m = ${delta'}}$"; + formattedFound = "gefunden: ${found'}, "; + formattedFormula = "[\\ch{${formula''}}]\\textsuperscript{${charge'}}"; + in + ion + // { + inherit mrm formattedFormula; + formattedLine = "${formattedCalc}${formattedFound}${formattedDelta}"; + } + ); + + report# { ... } -> { method: string; ions: [ Ion ] } + = { acronyms, ... } @ resources: + { highRes, ions, method, ... }: + [ + ( + LaTeX + ( + let + method' + = { + "ESI-TOF" = "${acronyms.electroSprayIonisation.short}-${acronyms.timeOfFlightMS.as "TOF"}"; + }.${method} + or ( + ( + acronyms.${method} + or { + short = debug.panic "report" "Unknown method »${method}«"; + } + ).short + ); + ions' = list.map ({ formattedLine, ... }: formattedLine) ions; + unit = formatUnit [ "dalton" "elementaryCharge-1" ]; + highRes' + = if highRes + then + acronyms.highResolutionMassSpectrometry.short + else + acronyms.massSpectrometry.short; + in + #debug.panic "report" { text = "unit"; data = unit; } + [ + "\\mbox{}\\textbf{${highRes'}}" + " (${method'}, ${acronyms.massToChargeRatio.short}~/~${unit}, $\\Delta$~/~${acronyms.ppm.short}):" + indentation.more + ] + ++ ( adjustIons ions' ) + ++ [ indentation.less ] + ) + ) + ]; +in +{ + inherit generateAppendix; + Spectrum + = { full ? null, highRes ? false, ions, method, files ? {} }: + { + inherit files full highRes method; + ions = mapIons ions; + }; + report + = { ... } @ resources: + data: + if type.isSet data + && data != {} + then + report resources data + else + []; +} \ No newline at end of file diff --git a/NixTeX/source/common/chemistry/nmr.nix b/NixTeX/source/common/chemistry/nmr.nix new file mode 100644 index 0000000..6755bf4 --- /dev/null +++ b/NixTeX/source/common/chemistry/nmr.nix @@ -0,0 +1,743 @@ +{ core, document, physical, ... } @ libs: + let + inherit(core) debug indentation lambda list number path set string type; + inherit(document) ClearPage Heading' LaTeX LaTeX' PhantomHeading; + + # T: ToString -> string + extensionOf + = path: + let + name = string.split "[.]" ( string path ); + in + if name != null + then + list.get name ( ( list.length name ) - 1 ) + else + null; + + adjustSignals#: [ string ] -> [ string ] + = signals: + let + len-1 = ( list.length signals ) - 1; + in + debug.info "adjustSignals" { text = "called with"; data = signals; } + ( + if signals != [ ] + then + ( list.generate (x: "${list.get signals x},") len-1 ) ++ [ "${list.get signals len-1}." ] + else + [ ] + ); + + # LaTeX + formatNMRnucleus#: string -> string + = nucleus: + let + tex + = { + "1H" = "\\textsuperscript{1}H"; + "13C" = "\\textsuperscript{13}C"; + "13C{1H}" = "\\textsuperscript{13}C\\{\\textsuperscript{1}H\\}"; + "15N" = "\\textsuperscript{15}N"; + "15N{1H}" = "\\textsuperscript{15}N\\{\\textsuperscript{1}H\\}"; + "19F" = "\\textsuperscript{19}F"; + "19F{1H}" = "\\textsuperscript{19}F\\{\\textsuperscript{1}H\\}"; + "31P" = "\\textsuperscript{31}P"; + "31P{1H}" = "\\textsuperscript{31}P\\{\\textsuperscript{1}H\\}"; + }; + pdf + = { + "1H" = "¹H"; + "13C" = "¹³C"; + "13C{1H}" = "¹³C\\{¹H\\}"; + "15N" = "¹⁵N"; + "15N{1H}" = "¹⁵N\\{¹H\\}"; + "19F" = "¹⁹F"; + "19F{1H}" = "¹⁹F\\{¹H\\}"; + "31P" = "³¹P"; + "31P{1H}" = "³¹P\\{¹H\\}"; + }; + in + "\\texorpdfstring{${tex.${nucleus} or nucleus}}{${pdf.${nucleus} or nucleus}}"; + + # LaTeX + formatSpectrum#: Spectrum -> Chunk + = { acronyms, ... }: + { file, label, method, sample, solvent, substance, title, name, ... }: + let + solvent' + = if solvent != null + then + solvent + else + "${acronyms.CDCl3.short}"; + title' + = if title != null + then + "${method}-${acronyms.nuclearMagneticResonance.short}~${title} in ${solvent'}" + else + "${method}-${acronyms.nuclearMagneticResonance.short}~${substance.NameID}${sample} in ${solvent'}"; + fileName = "\\source/resources/appendix/nmr/${substance.name or name}/${path.getBaseName file}"; + label' = "nmr:${label}"; + in + if ( extensionOf file == "pdf" ) + then + Heading' "${title'}" + [ + ( + LaTeX + ( + ( + if label != null + then + [ "\\labelAppendix{nmr:${label}}%" ] + else + [ ] + ) + ++ ( + if true + then + [ + "\\vspace{-1\\normalbaselineskip}" + "\\begin{figure}[H]%" indentation.more + "\\centering%" + "\\begin{adjustbox}%" indentation.more + "{max width=\\textwidth,max height=.4\\textheight,keepaspectratio}%" + "\\includegraphics{${fileName}}%" + indentation.less "\\end{adjustbox}%" + indentation.less "\\end{figure}%" null + ] + else + [ + "\\begin{figure}[H]%" indentation.more + "\\centering%" + "\\begin{adjustbox}%" indentation.more + "{angle=90,min width=\\textwidth,min totalheight=\\textheightleft,max width=\\textwidth,max totalheight=\\textheightleft-2em}%" + "\\includegraphics{${fileName}}%" + indentation.less "\\end{adjustbox}%" + indentation.less "\\end{figure}%" null + ] + ) + ) + ) + ] + { + clearPage = false; + # rotate = false; + before = "\\refstepcounter{ctrAppendix}%"; + } + else + debug.panic + [ "formatSpectrum" ] + "File in the Portable Document Format (pdf) expected, got »${string file}«!"; + + # LaTeX + formatSpectrumName# Spectrum -> string + = { acronyms, ... }: + { nucleus, kind, ... }: + let + nucleus' + = if nucleus == "1Hx13C" + then + "${formatNMRnucleus "1H"}-${formatNMRnucleus "13C"}" + else + formatNMRnucleus nucleus; + dept#: integer -> string + = degree: + "${formatNMRnucleus nucleus}-${acronyms.dept.short}-${string degree}"; + in + { + "self" = formatNMRnucleus nucleus; + "dc" = formatNMRnucleus "${nucleus}{1H}"; + "dept" = "${formatNMRnucleus nucleus}-${acronyms.dept.short}"; + "dept45" = dept 45; + "dept90" = dept 90; + "dept135" = dept 135; + }.${kind} or "${nucleus'}-${acronyms.${kind}.short}"; + + genAppendix#: Product -> [ string ] + = resources: + { failure ? false, substance ? {}, name ? null, nmr ? null, title ? null, identifier ? null, ... }: + let + nmr' = substance.nmr or nmr; + spectra + = list.concatMap + ( + { nucleus, data }: + if data != null + then + let + inherit(data) files; + in + list.map + ( + spectrum: + spectrum + // { + inherit substance nucleus title name; + inherit(data) comment solvent; + } + ) + ( + { + "1H" + = [ + { kind = "self"; files = files.self or files."1H" or null; } + { kind = "cosy"; files = files.cosy or null; } + { kind = "tocsy"; files = files.tocsy or null; } + { kind = "noesy"; files = files.noesy or null; } + { kind = "roesy"; files = files.roesy or null; } + ]; + "13C" + = [ + { kind = "dc"; files = files.dc or files."13C{1H}" or null; } + { kind = "self"; files = files.self or files."13C" or null; } + { kind = "apt"; files = files.apt or null; } + { kind = "dept"; files = files.dept or null; } + { kind = "dept90"; files = files.dept90 or null; } + { kind = "dept135"; files = files.dept135 or null; } + ]; + "15N" + = [ + { kind = "dc"; files = files.dc or files."15N{1H}" or null; } + { kind = "self"; files = files.self or files."15N" or null; } + ]; + "19F" + = [ + { kind = "dc"; files = files.dc or files."19F{1H}" or null; } + { kind = "self"; files = files.self or files."19F" or null; } + ]; + "31P" + = [ + { kind = "dc"; files = files.dc or files."31P{1H}" or null; } + { kind = "self"; files = files.self or files."31P" or null; } + ]; + "1Hx13C" + = [ + { kind = "hsqc"; files = files.hsqc or null; } + { kind = "hmbc"; files = files.hmbc or null; } + ]; + }.${nucleus} + ) + else + [] + ) + [ + { nucleus = "1H"; data = nmr'."1H" or null; } + { nucleus = "13C"; data = nmr'."13C" or null; } + { nucleus = "15N"; data = nmr'."15N" or null; } + { nucleus = "19F"; data = nmr'."19F" or null; } + { nucleus = "31P"; data = nmr'."31P" or null; } + { nucleus = "1Hx13C"; data = nmr'."1Hx13C" or null; } + ]; + in + if nmr' != null + && !failure + then + list.concatMap (genAppendixForSpectrum resources) spectra + else + [ ]; + + # LaTeX + genAppendixForSpectrum#: Spectrum -> [ Chunk ] | ! + = resources: + { nucleus, kind, files, comment, solvent, substance, title, name, ... } @ spectrum: + let + # string | null -> path -> string -> [ string ] | ! + formatSpectrum' + = sample: + file: + label: + formatSpectrum resources + { + inherit file label substance solvent title name; + method = formatSpectrumName resources spectrum; + sample + = if sample != null + then + " (${string sample})" + else + ""; + }; + in + type.matchPrimitiveOrPanic files + { + lambda = debug.panic "genAppendixForSpectrum" "???"; + list + = ( + list.fold + ( + state: + file: + state + // { + counter = state.counter + 1; + list + = state.list + ++ [ + ( + type.matchPrimitiveOrPanic file + { + lambda + = debug.panic "genAppendix" "2???"; + path + = formatSpectrum' + null + file + ( spectrum.label or "${substance.name or name}_${nucleus}_${string state.counter}" ); + set + = formatSpectrum' + ( file.identifier or null ) + file.file + ( spectrum.label or "${substance.name or name}_${nucleus}_${string file.identifier}" ); + } + ) + ]; + } + ) + { + counter = 1; + list = [ ]; + } + files + ).list; + null = [ ]; + path + = let + kind' + = if kind == "self" + then + nucleus + else + "${nucleus}${kind}"; + spectrum' + = formatSpectrum' + null + files + ( spectrum.label or "${substance.name or name}_${kind'}" ); + in + [ spectrum' ]; + set + = let + identifier + = if files.identifier or null != null + then + "_${string files.identifier}" + else + ""; + in + [ + ( + formatSpectrum' + ( files.identifier or null ) + files.file + ( spectrum.label or "${substance.name or name}_${nucleus}${identifier}" ) + ) + ]; + }; + + genDependencies#: Product -> Dependencies + = { substance ? {}, identifier ? null, nmr ? null, name ? null, ... }: + let + nmr' = substance.nmr or nmr; + files + = list.concatMap + ( + spectrum: + if spectrum != null + then + set.values spectrum.files + else + [] + ) + [ + ( nmr'."1H" or null ) + ( nmr'."13C" or null ) + ( nmr'."15N" or null ) + ( nmr'."19F" or null ) + ( nmr'."31P" or null ) + ( nmr'."1Hx13C" or null ) + ]; + files' = list.flat files; + getFileName = fileName: "resources/appendix/nmr/${substance.name or name}/${path.getBaseName fileName}"; + in + if nmr' != null + then + list.concatMap + ( + file: + type.matchPrimitiveOrDefault file + { + null = []; + path = [ { src = file; dst = getFileName file; } ]; + set = [ { src = file.file; dst = getFileName file.file; } ]; + } + ) + files' + else + [ ]; + + # LaTeX + mapSignals#: string -> [ Signal ] -> [ string ] + = { acronyms, ... }: + nucleus: + list.map + ( + { assignment, charge, couplings, integral, multiplicity, other, protons, range } @ signal: + let + other' + = if other != null + then + if list.isInstanceOf other + then + string.concat (list.map (range: "×${prepareRange 1 range}") other) + else + "×${prepareRange 1 other}" + else + ""; + precision = if nucleus == "1H" then 2 else 1; + prepareRange + = precision: + range: + if list.isInstanceOf range + then + let + from = list.get range 0; + till = list.get range 1; + in + "${number.toStringWithPrecision from precision}–${number.toStringWithPrecision till precision}" + else if string.isInstanceOf range + then + range + else if range < 0 + then + "\\minus${number.toStringWithPrecision (0 - range) precision}" + else + "${number.toStringWithPrecision range precision}"; + + mapCouplings + = set.mapToList + ( + coupling: + list: + let + result = string.match "([0-9]+)([A-Za-z]+)" coupling; + bonds + = if result != null + then + "\\textsuperscript{${list.get result 0}}" + else + ""; + nuclei + = if result != null + then + list.get result 1 + else + coupling; + values = physical.formatValue { value = list; precision = 1; } "hertz"; + in + "${bonds}${acronyms.couplingConstant.short}\\textsubscript{${nuclei}}~=~${values}" + ); + + element + = let + nucleus' = string.match "[0-9]*([A-Za-z]+).*" nucleus; + in + if nucleus' != null + then + list.head nucleus' + else + nucleus; + + protons' + = let + charge' + = if charge == 0 then "" + else if charge == 1 then "\\textsuperscript{+}" + else if charge == -1 then "\\textsuperscript{\\minus}" + else if charge < 0 then "\\textsuperscript{\\minus${string (0 - charge)}}" + else "\\textsuperscript{+${string charge}}"; + in + if protons == 0 + then + let + saturated + = { + "C" = "quaternary"; + "N" = "tertiary"; + }.${element}; + in + "${acronyms.${saturated}.short} \\textit{${element}}${charge'}" + else if protons == 1 + then + "\\textit{${element}}H${charge'}" + else + "\\textit{${element}}H\\textsubscript{${string protons}}${charge'}"; + + details + = ( if false then [ protons' ] else [ ] ) + ++ ( if multiplicity != null then [ "${string multiplicity}" ] else [ ] ) + ++ ( mapCouplings couplings ) + ++ ( if integral != null then [ "${string integral}${element}" ] else [ ] ) + ++ ( if assignment != null then [ "\\ch{${string assignment}}" ] else [ ] ); + in + if details == [ ] + then + "${prepareRange precision range}" + else + "${prepareRange precision range} (${string.concatWith ", " details})" + ); + + # LaTeX + reportSpectra#: NMRdata -> [ LaTeX ] | ! + = { acronyms, ... } @ resources: + { kind, nmrData }: + let + inherit(nmrData) method files signals; + solvent + = if nmrData.solvent != null + then + nmrData.solvent + else + "${acronyms.CDCl3.short}"; + + hyperlink + = if nmrData.label or null != null + then + "\\hyperlink{appendix:${nmrData.label}}" + else + ""; + suffix + = let + methods + = list.filter + ({ method, from }: from) + [ + { method = "apt"; from = method.apt or false; } + { method = "dept"; from = method.dept or false; } + { method = "dept45"; from = method.dept45 or false; } + { method = "dept90"; from = method.dept90 or false; } + { method = "dept135"; from = method.dept135 or false; } + # { method = "cosy"; from = method.cosy or false; } + # { method = "hmbc"; from = method.hmbc or false; } + { method = "hsqc"; from = method.hsqc or false; } + # { method = "noesy"; from = method.noesy or false; } + # { method = "roesy"; from = method.roesy or false; } + # { method = "tocsy"; from = method.tocsy or false; } + ]; + dept = degree: "${acronyms.dept.short}-${string degree}"; + formatMethod + = method: + { + "dept45" = dept 45; + "dept90" = dept 90; + "dept135" = dept 135; + }.${method} or "${acronyms.${method}.short}"; + in + if methods != [] + then + ", aus ${string.concatMappedWith ({ method, ... }: formatMethod method) "/" methods}" + else + ""; + nucleus + = { + "1H" + = if files ? self then "1H" + else null; + "13C" + = if files ? self then "13C" + else if files ? dc then "13C{1H}" + else null; + "15N" + = if files ? self then "15N" + else if files ? dc then "15N{1H}" + else null; + "19F" + = if files ? self then "19F" + else if files ? dc then "19F{1H}" + else null; + "31P" + = if files ? self then "31P" + else if files ? dc then "31P{1H}" + else null; + "1Hx13C" = null; + }.${kind}; + sortSignals + = list.sort + ( + first: + second: + let + first' + = if list.isInstanceOf first.range + then + list.head first.range + else + first.range; + second' + = if list.isInstanceOf second.range + then + list.head second.range + else + second.range; + in + first' > second' + ); + in + if nucleus != null + && signals != [] + then + [ + ( + LaTeX + ( + [ + "\\mbox{}${hyperlink}{\\textbf{${formatNMRnucleus nucleus}-${acronyms.nuclearMagneticResonance.short}}}" + " (${solvent}, ${acronyms.chemShift.short}~/~${acronyms.ppm.short}${suffix}):" + indentation.more + ] + ++ ( adjustSignals ( mapSignals resources nucleus (sortSignals signals) ) ) + ++ [ indentation.less ] + ) + ) + ] + else + [ ]; + + Signal + = range: + { charge ? 0, couplings ? {}, integral ? null, multiplicity ? null, other ? null, protons ? null }: + assignment: + { + inherit assignment charge couplings integral multiplicity other protons range; + }; + + Spectrum + = { ... } @ files: + { method ? {}, ... } @ config: + signals: + { + comment = null; + files = {}; + solvent = null; + } + // config + // { + inherit files method signals; + }; + in + { + inherit formatNMRnucleus; + + inherit Spectrum; + Spectrum' = files: Spectrum files {}; + + inherit Signal; + Signal' = range: multiplicity: integral: Signal range { inherit integral multiplicity; }; + SignalAP = range: protons: integral: Signal range { inherit protons integral; }; + SignalDC = range: integral: Signal range { inherit integral; }; + SignalJ = range: multiplicity: couplings: integral: Signal range { inherit couplings integral multiplicity; }; + SignalX = range: other: Signal range { inherit other; }; + + # [ Synthsis ] -> arguments -> Document::Chunk.LaTeX + generateAppendix + = syntheses: + { resources, ... } @ document: + let + syntheses' + = if path.isInstanceOf syntheses + then + import + syntheses + (libs // { chemistry = libs.chemistry; }) + document + else + syntheses; + syntheses'' + = if list.isInstanceOf syntheses' + then + syntheses' + else + syntheses'.list; + products + = list.concatMap + ( + # Synthesis -> [ string ] + synthesis: + if synthesis ? product + then + let + product + = if lambda.isInstanceOf synthesis.product + then + synthesis.product { } + else + synthesis.product; + product' + = product + // { + name = product.name or null; + substance = product.substance or synthesis.substance or {}; + }; + in + if list.isInstanceOf product + then + product + else + [ product' ] + else + [ ] + ) + syntheses''; + in + LaTeX' + ( + [ + "\\newgeometry" + "{" indentation.more + "top = (\\paperheight-\\textheight+\\headheight+\\headsep+\\footskip)/2 - 73.04765pt," + "textheight = \\textheight+\\footskip," + "footskip = 0cm," + indentation.less "}%" + ( ClearPage ) + ] + ++ [ + ( + PhantomHeading + ( + PhantomHeading + ( + list.concatMap + (genAppendix resources) + products + ) + ) + ) + "\\restoregeometry%" null + ] + ) + { + dependencies = list.concatMap genDependencies products; + }; + + # { string -> NMRdata } -> [ LaTeX ] + report + = resources: + { ... } @ nmrData: + list.concatMap + ( + { nmrData, ... } @ spectra: + if nmrData != null + then + reportSpectra resources spectra + else + [] + ) + [ + { kind = "1H"; nmrData = nmrData."1H" or null; } + { kind = "13C"; nmrData = nmrData."13C" or null; } + { kind = "15N"; nmrData = nmrData."15N" or null; } + { kind = "19F"; nmrData = nmrData."19F" or null; } + { kind = "31P"; nmrData = nmrData."31P" or null; } + ]; + } \ No newline at end of file diff --git a/NixTeX/source/common/chemistry/substances/check.nix b/NixTeX/source/common/chemistry/substances/check.nix new file mode 100644 index 0000000..70a9a24 --- /dev/null +++ b/NixTeX/source/common/chemistry/substances/check.nix @@ -0,0 +1,144 @@ +{ chemistry, core, Substance, ... } @ libs: +let + inherit(core) context debug list path set string type; + + check + = let + libs' = libs // { chemistry = chemistry // { inherit Substance; }; }; + optional + = condition: + body: + if condition + then + [ body ] + else + [ ]; + check1H + = name: + spectra: + if spectra."1H" or null != null + then + let + spectra' = spectra."1H".files; + in + [] + ++ ( + optional + (spectra'.self or null == null) + "1H-Spectrum for novel ${name} missing" + ) + ++ ( + optional + (spectra'.cosy or null == null) + "1H-COSY-Spectrum for novel ${name} missing" + ) + else + [ "1H-NMR for novel ${name} missing" ]; + check13C + = name: + spectra: + if spectra."13C" or null != null + then + let + spectra' = spectra."13C".files; + in + [] + ++ ( + optional + (spectra'.self or spectra'.dc or null == null) + "13C-Spectrum for novel ${name} missing" + ) + ++ ( + optional + (spectra'.apt or spectra'.dept135 or spectra'.dept45 or null == null) + "13C-APT/DEPT-Spectrum for novel ${name} missing" + ) + else + [ "13C-NMR for novel ${name} missing" ]; + checkNMR + = name: + nmr: + if nmr != null + then + [ ] + ++ ( check1H name nmr ) + ++ ( check13C name nmr ) + else + [ "NMR-Data for novel ${name} missing" ]; + checkSubstance + = source: + { + name, + formula ? null, + ir ? null, + ms ? null, + nmr ? null, + novel ? false, + structure ? null, + synthesised ? true, + title ? null, + ... + } @ self: + let + result + = [] + ++ ( optional (title == null) "Title for ${name} missing" ) + ++ ( optional (formula == null) "Formula for ${name} missing" ) + ++ ( optional (structure == null) "Structure for ${name} missing" ) + ++ ( + if novel && synthesised + then + [] + ++ ( optional (ir == null) "IR-Data for novel ${name} missing" ) + ++ ( optional (ms == null) "MS-Data for novel ${name} missing" ) + ++ ( checkNMR name nmr ) + else + [] + ); + in + debug.warn source + { + text = result; + when = result != []; + } + result; + in + source: + substances: + type.matchPrimitiveOrPanic substances + { + lambda = check source (substances libs'); + path = check (source substances) (path.importScoped { inherit Substance; } substances); + list = list.concatMap (check source) substances; + set = checkSubstance source substances; + }; + + check' + = substances: + string.concatLines (check (context "check") substances); + + checkNovel + = { ... } @ substances: + let + novelSubstances = list.filter ({ novel ? false, ... }: novel) (set.values substances); + formattedSubstances + = list.map + ( + { name, nmr ? null, ir ? null, ... }: + let + nmr' + = if nmr != null + then + nmr + else + "\\multicolumn{4}{c|}{– NMR? –}"; + in + "${name} & " + ) + novelSubstances; + in + []; +in +{ + inherit check check' checkNovel; +} \ No newline at end of file diff --git a/NixTeX/source/common/chemistry/substances/default.nix b/NixTeX/source/common/chemistry/substances/default.nix new file mode 100644 index 0000000..f624907 --- /dev/null +++ b/NixTeX/source/common/chemistry/substances/default.nix @@ -0,0 +1,85 @@ +{ core, document, ... } @ libs: +let + inherit(core) debug library list; + inherit(list) generate get head length toSet; + + libs' + = libs + // { + Mixture + = substances: + { ... } @ object: + object + // { + __type__ = "Mixture"; + inherit substances; + }; + + Substance + = name: + { ... } @ object: + object + // { + __type__ = "Substance"; + inherit name; + }; + }; + + finalise#: { string -> Substance } -> [ Substance ] -> { string -> Substance } + = { ... } @ substances: + { ordered, ... } @ state: + substances + // toSet + ( + generate + ( + id: + let + name = get ordered id; + substance = substances.${name}; + in + { + inherit name; + value + = substance + // { + inherit id; + }; + } + ) + (length ordered) + ); + + call + = state: + argument: + let + name = head argument; + in + if state.substances.lookUp.${name} or null != null + then + state + else + state + // { + substances + = state.substances + // { + counter = state.substances.counter + 1; + list = state.substances.list ++ [ name ]; + lookUp + = state.substances.lookUp + // { + ${name} = state.substances.counter; + }; + }; + }; +in +{ + inherit(library.import ./check.nix libs') check check' checkNovel; + inherit(libs') Mixture Substance; + evaluate = library.import ./evaluate.nix libs'; + prepare = library.import ./prepare.nix libs'; + toLua = library.import ./lua.nix libs'; + inherit finalise; +} \ No newline at end of file diff --git a/NixTeX/source/common/chemistry/substances/evaluate.nix b/NixTeX/source/common/chemistry/substances/evaluate.nix new file mode 100644 index 0000000..7bf1ee8 --- /dev/null +++ b/NixTeX/source/common/chemistry/substances/evaluate.nix @@ -0,0 +1,35 @@ +{ core, ... } @ libs: +let + inherit(core) debug list; + + init + = concise: + { + __functor = evaluate; + counter = if concise then 0 else 1; # ToDo !!! + lookUp = { }; + ordered = [ ]; + }; + + evaluate + = { counter, lookUp, ordered, ... } @ self: + arguments: + let + name = list.head arguments; + in + if lookUp.${name} or null != null + then + self + else + self + // { + counter = counter + 1; + lookUp + = lookUp + // { + ${name} = counter; + }; + ordered = ordered ++ [ name ]; + }; +in + init diff --git a/NixTeX/source/common/chemistry/substances/lua.nix b/NixTeX/source/common/chemistry/substances/lua.nix new file mode 100644 index 0000000..b767e17 --- /dev/null +++ b/NixTeX/source/common/chemistry/substances/lua.nix @@ -0,0 +1,51 @@ +{ chemistry, core, ... } @ libs: +let + inherit(core) debug number path string; + inherit(chemistry.elements) calculateMassOfFormula normaliseMolecularFormula; + inherit(string) concatWith replace; + + toLua + = name: + { formula ? [], structure ? {}, ... } @ substance: + let + escape = replace [ "\\" "\"" ] [ "\\\\" "\\\"" ]; + orNil + = attr: + if substance.${attr} or null != null + then + "\"${escape substance.${attr}}\"" + else + "nil"; + formula' = normaliseMolecularFormula ( formula ); + movPart = escape ( concatWith "" structure.movPart or [] ); + in + '' + substances.declare + ( + "${name}", + { + name = ${orNil "title"}, + code = ${orNil "code"}, + mass = ${number.toStringWithPrecision ( calculateMassOfFormula formula' ) 2}, + simple = ${orNil "simple"}, + structure = { + figPart = "${escape ( concatWith "" structure.figPart or [] )}", + movPart = "${movPart}" + }, + } + ) + ''; +in + { configuration, ... }: + { ... } @ substances: + if ( configuration.substances or {}).enable or false + then + { + dst = "generated/substances.lua"; + src = path.fromSet "substances.lua" toLua substances; + } + else + { + dst = null; + src = null; + } diff --git a/NixTeX/source/common/chemistry/substances/prepare.nix b/NixTeX/source/common/chemistry/substances/prepare.nix new file mode 100644 index 0000000..97bc2d2 --- /dev/null +++ b/NixTeX/source/common/chemistry/substances/prepare.nix @@ -0,0 +1,130 @@ +{ chemistry, core, document, physical, Substance, ... } @ libs: + let + inherit(core) context debug list path type; + inherit(chemistry) compound elements; + inherit(elements) calculateMassOfFormula normaliseMolecularFormula; + + defaultOptions#: { code: bool ? false, ... } -> { code: bool, ... } + = { + code ? false, + id ? false, + mass ? false, + name ? false, + structure ? false, + }: + { inherit code id mass name structure; }; + + parseOptions + = options: + defaultOptions + ( + { + "i" = { id = true; }; + }.${options} + ); + + format#: Substance -> Options -> string + = { name, fake ? false, ... } @ substance: + options: + let + options' + = type.matchPrimitiveOrPanic options + { + set = defaultOptions options; + string = parseOptions options; + }; + in + if options' == { code = false; id = false; mass = false; name = false; structure = false; } + then + "\\directlua{substances.printNumber([[${name}]])}" + else if options' == { code = true; id = false; mass = false; name = false; structure = false; } + then + "\\directlua{substances.printCode([[${name}]])}" + else if options' == { code = false; id = true; mass = false; name = false; structure = false; } + then + "\\directlua{substances.printNumber([[${name}]])}" + else if options' == { code = true; id = true; mass = false; name = false; structure = false; } + then + "\\directlua{substances.printCodeID([[${name}]])}" + else if options' == { code = false; id = false; mass = true; name = false; structure = false; } + then + "\\directlua{substances.printMass([[${name}]])}" + else if options' == { code = false; id = false; mass = false; name = true; structure = false; } + then + "\\directlua{substances.printName([[${name}]])}" + else if options' == { code = true; id = false; mass = false; name = true; structure = false; } + then + "\\directlua{substances.printWithCode([[${name}]])}" + else if options' == { code = false; id = true; mass = false; name = true; structure = false; } + then + "\\directlua{substances.printWithID([[${name}]])}" + else if options' == { code = false; id = false; mass = false; name = false; structure = true; } + then + "\\directlua{substances.printMolecule([[${name}]])}" + else if options' == { code = true; id = false; mass = false; name = false; structure = true; } + then + "\\directlua{substances.printMoleculeWithCode([[${name}]])}" + else if options' == { code = false; id = true; mass = false; name = false; structure = true; } + then + "\\directlua{substances.printMoleculeWithNumber([[${name}]])}" + else if options' == { code = true; id = true; mass = false; name = false; structure = true; } + then + "\\directlua{substances.printMoleculeWithNumberCode([[${name}]])}" + else if options' == { code = false; id = false; mass = true; name = false; structure = true; } + then + "\\directlua{substances.printMoleculeWithMass([[${name}]])}" + else + debug.unimplemented "format"; + + libs' + = libs + // { + chemistry + = chemistry + // { + inherit Substance; + }; + }; + + prepare + = source: + substances: + type.matchPrimitiveOrPanic substances + { + null = []; + lambda = prepare source ( substances libs' ); + path + = prepare + (source substances) + (path.importScoped { inherit Substance; } substances); + list = list.concatMap (prepare source) substances; + set + = let + substance = substances; + formula = normaliseMolecularFormula substance.formula or []; + value + = substance + // { + inherit formula source; + dalton = calculateMassOfFormula formula; + }; + in + [ + { + inherit(value) name; + value + = value + // { + __functor = _: format value; + __toString = _: format value {}; + CodeID = format value { code = true; id = true; }; + ID = format value { id = true; }; + Name = format value { name = true; }; + NameID = format value { id = true; name = true; }; + }; + } + ]; + }; + in + substances: + list.toSet (prepare (context "substances") substances) diff --git a/NixTeX/source/common/chemistry/synthesis.nix b/NixTeX/source/common/chemistry/synthesis.nix new file mode 100644 index 0000000..5306a0b --- /dev/null +++ b/NixTeX/source/common/chemistry/synthesis.nix @@ -0,0 +1,925 @@ +{ chemistry, core, document, physical, ... }: +let + inherit(core) debug error indentation list number set string type; + inherit(chemistry) compound elements ir ms nmr values; + inherit(elements) calculateMassOfFormula normaliseMolecularFormula tableOfMasses; + inherit(document) Heading Heading' LaTeX Paragraph Paragraph'; + inherit(tableOfMasses) Cu I; + + default = a: b: if a != null then a else b; + + # null | [ Any ] | T + # -> [ ] | [ Any ] | [ T ] + toList + = value: + type.matchPrimitiveOrDefault value + { + null = [ ]; + list = value; + } + [ value ]; + + # string | [ ? ] -> [ Document::Chunk.Paragraph ] + toParagraphs + = listOrString: + type.matchPrimitiveOrPanic listOrString + { + string = [ ( Paragraph listOrString ) ]; + list = list.map (paragraph: Paragraph paragraph) listOrString; + }; + + # bool -> Synthesis -> [ Document::Chunk.Paragraph ] + mapProcedure + = _newline: + { ... } @ synthesis: + let + procedure = string.trim' synthesis.procedure; + result + = type.matchPrimitiveOrPanic synthesis.procedure + { + lambda = list.map (paragraph: Paragraph' paragraph { endParagraph = "\\par"; }) ( synthesis.procedure synthesis ); + string = [ ( Paragraph procedure ) ]; + list = list.map (paragraph: Paragraph' paragraph { endParagraph = "\\par"; }) ( synthesis.procedure ); + }; + in + result; + + # Synthesis -> Product -> [ Document::Chunk ] + formatAnalysis + = { ... } @ resources: + { ... } @ synthesis: + { analysisOnly ? false, hack ? false, ... } @ product: + let + substance = product.substance or synthesis.substance or { }; + yield = product.yield or {}; + yield' + = if isLambda yield + then + yield product + else + yield; + mass = yield'.mass; + amount = yield'.amount or ( mass / ( substance.dalton or 1 ) ); + amount' = normaliseValue ( amount ) null; + + equivalent = yield'.equivalent or 1; + relativeEquivalents + = if equivalent != 1 + then + " (${physical.formatValue equivalent "equivalent"})" + else + ""; + # float + relative + = let + relative = ( yield'.relative or ( amount / ( reactant'.amount or amount ) * 100 ) ) * 1.0 * equivalent; + in + if relative > 100 + then + debug.warn "formatAnalysis" + { + text = "Yield is over 100 %: ${string relative}!"; + data = yield'; + } + relative + else + relative; + + # string | { title: string } + reactant = yield'.reactant or "???"; + + # string + title + = type.matchPrimitiveOrPanic reactant + { + set + = if reactant.title != null + then + reactant.title + else + reactant.substance.ID; + string = reactant; + }; + + # set + reactant' + = if set.isInstanceOf reactant + then + reactant + else + { }; + + # string + novel = product.novel or substance.novel or false; + novelText = "Diese Verbindung ist bisher literatur\\-unbekannt."; + + # float + purity = ( yield'.purity or 1 ) * 1.0; + + # string + purity' + = if purity != 1.0 + then + "etwa ${physical.formatValue { value = 100*purity; precision = 1; } "percent"}-iger Reinheit und " + else + ""; + + # string + mass' + = if purity != 1.0 + then + "rein: ${physical.formatValue { value = mass * purity; precision = 2; } "gram"}, " + else + ""; + + warn + = name: + debug.warn "formatAnalysis" + { + when = product.novel or substance.novel or false; + text = "${name}-data missing for novel compound ${substance.name}"; + }; + + otherData#: T = int|float|{ from: int|float, till: int|float }|null @ { + # melting: T, + # boiling: T, + # sublimation: T, + # decomposition: T, + # density: int|float|null, + # }? + = product.physical or ( warn "Physical" null ); + eaData = substance.elements or product.elements or ( warn "EA" { } ); + irData = substance.ir or product.ir or ( warn "IR" [ ] ); + msData = substance.ms or product.ms or ( warn "MS" { } ); + nmrData = substance.nmr or product.nmr or ( warn "NMR" { } ); + reports + = [] # Elementaranalyse + ++ ( values.report resources otherData ) + # ++ ( elements.report resources substance Elements ) + ++ ( nmr.report resources nmrData ) + ++ ( ir.report resources irData ) + ++ ( ms.report resources msData ); + failure = synthesis.failure or false || product.failure or false; + in + [ + ( + Paragraph' + ( + if analysisOnly + then + if novel + then + [ novelText ] + else + [] + else if failure + then + if yield' == {} + then + [ "Es konnte kein Produkt erhalten werden." ] + else + [ + "Es konnte kein Produkt erhalten werden und" + " ${physical.formatValue { value = mass; precision = 2; } "gram"}" + " (${physical.formatValue { value = amount'.value; precision = 2; } "${amount'.prefix}mol"})" + " des eingesetzten ${title} wurden zurückgewonnen." + ] + else if yield' == {} + then + [ "Erhalten wurde eine unbestimmte Menge ${product.description or "Produkt"}." ] + else + [ + "Erhalten wurden ${physical.formatValue { value = mass; precision = 2; } "gram"}" + " (${mass'}${physical.formatValue { value = amount'.value*purity; precision = 2; } "${amount'.prefix}mol"})" + " ${product.description or "Produkt"} mit \\mbox{${purity'}${physical.formatValue { value = relative*purity; precision = 1; } "percent"}-iger} Ausbeute" + " bezogen auf eingesetztes ${title}${relativeEquivalents}.${if novel then " ${novelText}" else ""}" + ] + ) + { + endParagraph + = if !hack + then + "\\par" + else + "\\par"; + /*endParagraph + = if !failure + && any (x: x != [] && x != {} && x != null) [ eaData irData msData nmrData otherData ] + then + "" + else + "\\newline";*/ + } + ) + ] + ++ ( + if failure + then + [] + else + reports + ); + + # Synthesis -> Product -> Document::Chunk.Paragraph | null + formatProductChemicals + = { ... } @ resources: + { ... } @ syn: + { ... } @ product: + if product ? "chemicals" + then + let + chemicals + = type.matchPrimitiveOrPanic product.chemicals + { + null = [ ]; + set = set.values product.chemicals; + list = product.chemicals; + }; + len = list.length chemicals; + endParagraph = "\\par"; + in + if len > 1 + then + Paragraph' + ( + [ "Eingesetzt wurden:" ] + ++ ( generate (x: " ${formatChemical (list.get chemicals x)},") ( len - 2 ) ) + ++ [ + " ${formatChemical (list.get chemicals ( len - 2 ))} und" + " ${formatChemical (list.get chemicals ( len - 1 ))}." + ] + ) + { inherit endParagraph; } + else if len == 1 + then + Paragraph' + [ "Eingesetzt wurden ${formatChemical ( list.head chemicals)}." ] + { inherit endParagraph; } + else + null + else + null; + + # Synthesis -> [ Document::Chunk.Heading ] + mapProducts + = { ... } @ resources: + { ... } @ synthesis: + map + ( + { + chemicals ? {}, + clearPage ? false, + note ? null, + substance ? null, + title ? null, + name ? null, + noHeading ? false, + noMolecule ? false, + postAnalysis ? [], + lines ? null, + ... + } @ product: + let + product' + = product + // { + inherit clearPage name substance title; + chemicals = fixChemicals resources chemicals; + }; + body + = ( toList ( formatProductChemicals resources synthesis product' ) ) + ++ ( + if note != null + then + if lambda.isInstanceOf note + then + [ (note product') ] + else + [ note ] + else + [] + ) + ++ ( formatAnalysis resources synthesis product' ) + ++ postAnalysis; + + lines' + = if lines != null + then + "[${string lines}]" + else + ""; + + body' + = LaTeX + ( + if substance != null + && !noMolecule + then + [ + "\\renewcommand{\\NumAtom}[2]{}%" + #"\\renewcommand{\\NumAtom}[2]{-[#1,,,draw=none]{\\scriptstyle#2}}%" + "\\Wrapchem${lines'}{${substance { mass = true; structure = true; }}}" + "{" indentation.more + ] + ++ body + ++ [ indentation.less "}" ] + else + body + ); + + body'' + = if noHeading + then + body' + else if substance != null + then + Heading' + { + bookmark = "${substance.Name}"; + caption = "${substance.NameID}"; + } + [ body' ] + { + inherit clearPage; + label = "substance:${substance.name or name}"; + clearPageOnLastQuarter = true; + } + else if title != null + then + Heading' + { + bookmark = "${compound title}"; + caption = "${compound title}"; + } + [ body' ] + { + inherit clearPage; + label = "substance:${name}"; + clearPageOnLastQuarter = true; + } + else + body'; + in + body'' + ); + + getFullTitle + = { acronyms, ... }: + { casus, degased, dry, molar, solvent, title }: + if solvent != null + then + let + # ToDo: Export to fluent-module + specialSolvents + = { + "H2O" = { deu = "wässrige"; eng = "aqueous"; }; + "Et2O" = { deu = "${acronyms.Et2O.as "etherische"}"; eng = "${acronyms.Et2O.as "etheral"}"; }; + "EtOH" = { deu = "${acronyms.EtOH.as "ethanolische"}"; eng = "${acronyms.EtOH.as "ethanolic"}"; }; + "MeOH" = { deu = "${acronyms.MeOH.as "methanolische"}"; eng = "${acronyms.MeOH.as "methanolic"}"; }; + "NH3" = { deu = "ammoniakalische"; eng = null; }; + "HCl" = { deu = "salz\\-saure"; eng = null; }; + "HNO3" = { deu = "salpeter\\-saure"; eng = null; }; + "H2SO4" = { deu = "schwefel\\-saure"; eng = null; }; + }; + special = specialSolvents.${solvent}.deu or null; + acronym + = { + THF = acronyms."tetrahydrofuran"; + tetrahydrofuran = acronyms."tetrahydrofuran"; + }.${solvent} or null; + in + if isString solvent + then + if special != null then "${special}${default casus "r"} ${molar}${title}\\-lösung" + else if acronym != null then "${molar}${title}-Lösung in ${acronym.long}" + else "${molar}${title}-Lösung in ${compound solvent}" + else "${molar}${title}-Lösung in ${getTitle solvent}" + else if dry && degased then "trockene${default casus "m"} und entgaste${default casus "m"} ${title}" + else if dry then "trockene${default casus "m"} ${title}" + else if degased then "entgaste${default casus "m"} ${title}" + else "${molar}${title}"; + + fixChemical + = { acronyms, ... } @ resources: + { ... } @ chemicals: + name: + { acronym, casus, concentration, mixture, purity, relative, substance, title, ... } @ chemical: + let + molar + = if purity != 1.0 + then + "${physical.formatValue ( purity * 100 ) "percent"}-ige${default casus "r"}~" + else + type.matchPrimitiveOrPanic concentration + { + null = ""; + int = "${formatConcentration concentration}~"; + float = "${formatConcentration concentration}~"; + list = "${concatWith ":" ( list.map formatConcentration concentration)}~"; + string + = { + "conc" = "${acronyms.concentrated.short} "; + "sat" = "${acronyms.saturated.short} "; + "dil" = "${acronyms.diluted.short} "; + }.${concentration} + or ( + debug.panic "fixChemical" "Invalid Concentration »${concentration}«" + ); + }; + + chemical' + = chemical + // { + title + = getFullTitle resources + { + inherit molar; + title = getTitle { inherit acronym mixture substance title; }; + inherit(chemical) casus dry degased solvent; + }; + }; + + relative' + = chemicals.${relative} + or ( + debug.panic + "fixChemical" + "While calculating equivalent for ${name}: There is no chemical »${relative}«!" + ); + in + if relative != null + then + chemical' + // { + equivalent + = debug.warn "fixChemical" + { + text = "relative"; + data + = { + chemical = { inherit(chemical) amount; }; + relative = { inherit(relative') amount equivalent; }; + ratio = chemical.amount / relative'.amount; + }; + } + ( chemical.amount / relative'.amount * relative'.equivalent); + } + else + chemical'; + + # ( string -> Chemical ) -> ( string -> Chemical ) + fixChemicals + = { ... } @ resources: + { ... } @ chemicals: + set.map + ( + name: + { ... } @ chemical: + type.matchPrimitiveOrPanic chemical + { + list = list.map (fixChemical resources chemicals name) chemical; + set = fixChemical resources chemicals name chemical; + } + ) + chemicals; + + # F -> G -> [ T ] -> [ ( F T ) ] + filterMap = m: f: self: filter f ( list.map m self ); + + # [ Synthesis ] -> [ Document::Chunk.Heading ] | ! + mapSyntheses + = { ... } @ resources: + syntheses: + filterMap + ( + { ... } @ syn: + let + syn' + = syn + // { + chemicals = fixChemicals resources syn.chemicals; + }; + mapSubstances + = string.concatMappedWith + ( + { ... } @ substance: + "${substance { mass = true; structure = true; }}" + ) + "\\arrow{0}[-90,0.3]"; + product + = if syn'.product or null != null + then + type.type.matchPrimitiveOrDefault syn'.product + { + lambda = syn'.product syn'; + list + = list.map + ( + product: + type.callLambda product syn' + ) + syn'.product; + } + syn'.product + else + []; + citeLiterature + = { literature ? null, ... }: + type.matchPrimitiveOrPanic literature + { + null = ""; + list = "\\cite{${string.concatMappedWith ({ name, ... }: name) "," literature}}"; + set = "\\cite{${literature.name}}"; + }; + formattedAnalysis + = type.matchPrimitiveOrPanic product + { + null = [ ]; + list + = if product != [] + then + mapProducts resources syn' product + else + [ + ( + Paragraph' + [ "Es konnte kein Produkt erhalten werden." ] + { endParagraph = ""; } + ) + ]; + set + = formatAnalysis resources syn' + ( + product // { chemicals = fixChemicals resources product.chemicals; } + ); + }; + + lines' + = if syn'.lines or null != null + then + "[${string syn'.lines}]" + else + ""; + in + if syn'.ignore or false + then + null + else + ( + if syn'.title or null != null + then + Heading' + ( + if type.isSet syn'.title + then + syn'.title + else + { + bookmark = syn'.title; + caption = "${syn'.title}${citeLiterature syn'}"; + } + ) + ( + if syn'.substances or null != null + then + LaTeX + ( + [ + "\\renewcommand{\\NumAtom}[2]{-[#1,,,draw=none]{\\scriptstyle#2}}%" + "\\Wrapchem${lines'}{${mapSubstances syn'.substances}}" + "{" indentation.more + ] + ++ ( mapProcedure true syn' ) + ++ formattedAnalysis + ++ [ indentation.less "}" ] + ) + else + ( mapProcedure false syn' ) + ++ formattedAnalysis + ) + { + clearPageOnLastQuarter = true; + } + else if syn'.substance or null != null + then + Heading' + { + bookmark = "${syn'.substance.Name}"; + caption = "${syn'.substance.NameID}${citeLiterature syn'}"; + LaTeX = true; + } + ( + LaTeX + ( + [ + "\\renewcommand{\\NumAtom}[2]{-[#1,,,draw=none]{\\scriptstyle#2}}%" + "\\Wrapchem${lines'}{${syn'.substance { mass = true; structure = true; }}}" + "{" indentation.more + ] + ++ ( mapProcedure true syn' ) + ++ formattedAnalysis + ++ [ indentation.less "}" ] + ) + ) + { + label = "substance:${syn'.substance.name}"; + clearPage = syn'.clearPage or false; + clearPageOnLastQuarter = true; + } + else + debug.panic "mapSyntheses" "Either substance or title must be set!" + ) + ) + (x: x != null) + syntheses; + + # Chemical -> string + formatDetails + = { ... } @ chemical: + if list.isInstanceOf chemical then concatWith "; " ( list.map formatDetails' chemical ) + else formatDetails' chemical; + + # Chemical -> string + formatDetails' + = { ... } @ chemical: + let + details + = ( + if chemical.substance != null + then + [ chemical.substance.ID ] + else + [ ] + ) + ++ ( + if chemical.volume != null + then + let + precision + = if chemical.kind != "solvent" then null + else if chemical.volume < 20 then 1 + else 0; + + volume = normaliseValue ( chemical.volume / 1000.0 ) null; + volume' = physical.formatValue { value = volume.value; inherit precision; } "${volume.prefix}litre"; + + fullVolume = normaliseValue ( chemical.times * chemical.volume / 1000.0 ) null; + fullVolume' = physical.formatValue { value = fullVolume.value; inherit precision; } "${fullVolume.prefix}litre"; + in + if chemical.times != null then [ "${string chemical.times}×${volume'}=${fullVolume'}" ] + else + [ volume' ] + else + [ ] + ) + ++ ( + if chemical.mass != null + then + let + mass = normaliseValue ( chemical.mass ) null; + volume = normaliseValue ( chemical.solvent.volume / 1000.0 ) (-3); + precision + = if chemical.solvent.volume < 20 then 1 + else 0; + solvent + = if chemical.solvent != null + && chemical.solvent ? volume + then + " in ${physical.formatValue { value = volume.value; inherit precision; } "${volume.prefix}litre"}" + else + ""; + in + [ "${( physical.formatValue { value = mass.value; precision = 2; } "${mass.prefix}gram" )}" ] + else + [ ] + ) + ++ ( + if chemical.amount != null + then let + amount = normaliseValue ( chemical.amount ) ( chemical.factor or null ); + in + [ ( physical.formatValue { value = amount.value; precision = 2; } "${amount.prefix}mol" ) ] + else + [ ] + ) + ++ ( + if chemical.equivalent != null + then + debug.info "formatDetails'" { text = "Equivalent"; data = chemical.equivalent; } + ( + if chemical.kind == "catalyst" then [ ( physical.formatValue { value = chemical.equivalent; precision = null; } "equivalent" ) ] + else [ ( physical.formatValue { value = chemical.equivalent; precision = 1; } "equivalent" ) ] + ) + else + [ ] + ) + ++ ( + if chemical.details != null then [ chemical.details ] + else [ ] + ); + in + string.concatWith ", " details; + + getUnitPrefix#: integer -> string | ! + = factor: + if factor == -24 then "yokto" + else if factor == -21 then "zepto" + else if factor == -18 then "atto" + else if factor == -15 then "femto" + else if factor == -12 then "pico" + else if factor == -9 then "nano" + else if factor == -6 then "micro" + else if factor == -3 then "milli" + else if factor == 0 then "" + else if factor == 3 then "kilo" + else if factor == 6 then "mega" + else if factor == 9 then "giga" + else if factor == 12 then "tera" + else if factor == 15 then "peta" + else if factor == 18 then "exa" + else if factor == 21 then "zetta" + else if factor == 24 then "yotta" + else error.throw "getUnitPrefix: Invalid Factor: ${string factor}"; + + # Number -> null | Number -> { value: Number; prefix = string; } + normaliseValue + = input: + factor: + let + absInput = number.abs input; + factor' + = if factor != null then factor + else if absInput >= 1000000000000000.0 then 15 + else if absInput >= 1000000000000.0 then 12 + else if absInput >= 1000000000.0 then 9 + else if absInput >= 1000000.0 then 6 + else if absInput >= 1000.0 then 3 + else if absInput >= 1.0 then 0 + else if absInput >= 0.001 then -3 + else if absInput >= 0.000001 then -6 + else if absInput >= 0.000000001 then -9 + else if absInput >= 0.000000000001 then -12 + else if absInput >= 0.000000000000001 then -15 + else 0; + prefix = getUnitPrefix factor'; + value = input * ( number.pow 10 ( 0 - factor' ) ); + in + { inherit value prefix; }; + + # { acronym, mixture, substance, title, ... } -> string + getTitle + = { acronym ? null, mixture ? null, substance ? null, title ? null, ... }: + if title != null then compound title + else if acronym != null then acronym.long + else if substance != null then substance.Name + else if mixture != null then string.concatMappedWith getTitle "-" mixture + else "???"; + + # Chemical -> string + formatName + = { ... } @ chemical: + if list.isInstanceOf chemical + then + "${string.concatMappedWith ({ title, ... }: title) "-" chemical}-Mischung" + else + if chemical.the or null != null + then + "${chemical.the} ${chemical.title}" + else + chemical.title; + + # Chemical -> string + formatChemical + = { ... } @ chemical: + let + name = formatName chemical; + details = formatDetails chemical; + in + if details != "" + then + "${name} (${details})" + else + name; + + # Number -> string | ! + formatConcentration + = concentration: + let + concentration' = normaliseValue concentration null; + in + if concentration != null + then + "${( physical.formatValue { value = concentration'.value; precision = 1; } "${concentration'.prefix}molar" )}" + else + debug.panic "formatConcentration" "Concentration is null!"; + + Chemical + = kind: + { + acronym ? null, + amount ? null, + concentration ? null, + dalton ? null, + degased ? false, + density ? null, + details ? null, + dry ? false, + equivalent ? null, + factor ? null, + formula ? null, + mass ? null, + mixture ? null, + purity ? 1.0, + relative ? null, + simple ? null, + solvent ? null, + substance ? null, + the ? null, + times ? null, + title ? null, + volume ? null + } @ chemical: + casus: + let + formula' = normaliseMolecularFormula ( default formula ( substance.formula or [ ] ) ); + dalton' = calculateMassOfFormula formula'; + + chemical' + = { + __type__ = "Chemical"; + concentration + = if concentration != null then concentration + else if mixture != null then list.map ({ concentration ? null, ... }: concentration) mixture + else null; + + dalton = default dalton ( substance.dalton or dalton' ); + density = default density ( substance.density or null ); + formula = formula'; + inherit acronym amount casus degased details dry equivalent factor kind mass mixture purity relative simple + solvent substance the times title volume; + }; + + chemical'' + = chemical' + // { + amount + = debug.info "chemical" + { + data = chemical; + } + ( + if chemical'.amount != null then chemical'.amount + else if chemical'.volume != null + then + if chemical'.mass != null then debug.panic "Chemical" "Volume and mass are mutualy exclusive!" + else if chemical'.concentration != null + then + if isFloat chemical'.concentration then chemical'.volume * chemical'.concentration / 1000 + else null + else if chemical'.density != null + && chemical'.dalton != null then chemical'.purity * chemical'.volume * chemical'.density / chemical'.dalton + else null + else if chemical'.mass != null + then + if chemical'.dalton != null then chemical'.mass / chemical'.dalton + else null + else null + ); + }; + in + if kind == "reagent" + || kind == "catalyst" + then + if chemical''.amount == null + then + debug.panic "Chemical" + { + text = "Catalysts and Reagents need to have amount of substance (`amount`) given. Perhaps you want Material."; + data = chemical''; + } + else if chemical''.equivalent == null + && chemical''.relative == null + then + debug.panic "Chemical" "Catalysts and Reagents need to have `equivalent` given. Perhaps you want Material." + else + chemical'' + else + chemical''; + + Catalyst' = { ... } @ attrs: Chemical "catalyst" attrs; + Material' = { ... } @ attrs: Chemical "material" attrs; + Product' = { ... } @ attrs: Chemical "product" attrs; + Reagent' = { ... } @ attrs: Chemical "reagent" attrs; + Solvent' = { ... } @ attrs: Chemical "solvent" attrs; + Catalyst = { ... } @ attrs: Catalyst' attrs null; + Material = { ... } @ attrs: Material' attrs null; + Product = { ... } @ attrs: Product' attrs null; + Reagent = { ... } @ attrs: Reagent' attrs null; + Solvent = { ... } @ attrs: Solvent' attrs null; +in +{ + inherit mapSyntheses; + inherit formatChemical formatDetails formatName; + inherit Catalyst Material Product Reagent Solvent; + inherit Catalyst' Material' Product' Reagent' Solvent'; +} diff --git a/NixTeX/source/common/chemistry/values.nix b/NixTeX/source/common/chemistry/values.nix new file mode 100644 index 0000000..7cf56ec --- /dev/null +++ b/NixTeX/source/common/chemistry/values.nix @@ -0,0 +1,57 @@ +{ core, document, physical, ... }: +let + inherit(core) debug string type; + inherit(physical) formatValue; + + report + = { acronyms, ... }: + { + melting ? null, + boiling ? null, + sublimation ? null, + decomposition ? null, + density ? null, + ... + }: + let + formatValue' + = value: + type.matchPrimitiveOrPanic value + { + int = formatValue { value = 1.0 * value; precision = 1; }; + float = formatValue { inherit value; precision = 1; }; + set = formatValue { inherit value; }; + }; + + formatTemperature + = temperature: + formatValue' temperature "celsius"; + + optional + = value: + text: + if value != null + then + [ text ] + else + []; + + result + = ( optional melting "${acronyms.meltingTemperature.short} ${formatTemperature melting}" ) + ++ ( optional boiling "${acronyms.boilingTemperature.short} ${formatTemperature boiling}" ) + ++ ( optional sublimation "${acronyms.sublimationTemperature.short} ${formatTemperature sublimation}" ) + ++ ( optional decomposition "${acronyms.decompositionTemperature.short} ${formatTemperature decomposition}" ) + ++ ( optional density "$\\rho$ ${formatValue' density [ "gram" "millilitre" (-1) ] }" ); + in + [ "${string.concatWith ", " result}." ]; +in +{ + report + = resources: + value: + if value != null + then + report value + else + [ ]; +} \ No newline at end of file diff --git a/NixTeX/source/common/default.nix b/NixTeX/source/common/default.nix new file mode 100644 index 0000000..b1fe6ae --- /dev/null +++ b/NixTeX/source/common/default.nix @@ -0,0 +1,18 @@ +{ core, ... } @ libs: +let + inherit (core.library) Library; +in + Library "common" + libs + { + bibliography = ./bibliography; + chemistry = ./chemistry; + document = ./document; + fonts = ./fonts; + glossaries = ./glossaries; + letters = ./letters; + phonenumbers = ./phonenumbers; + physical = ./physical; + symbols = ./symbols; + urls = ./urls; + } diff --git a/NixTeX/source/common/document/chunks/claim.nix b/NixTeX/source/common/document/chunks/claim.nix new file mode 100644 index 0000000..55d0318 --- /dev/null +++ b/NixTeX/source/common/document/chunks/claim.nix @@ -0,0 +1,70 @@ +# TODO: Remove LaTeX-Code, replace with renderer-methods +{ chunks, core, evaluator, renderer, ... }: + let + inherit(core) debug error string type; + inherit(evaluator) evaluate; + inherit(renderer) toBody render; + + evaluateClaim + = { ... } @ document: + { bibliography, ... } @ state: + { body, dependencies, reference, ... } @ claim: + let + state' = evaluate document state body; + cite + = type.matchPrimitiveOrPanic reference + { + bool = error.throw "Bool in evaluateClaim?"; + list = reference; + set = [ reference ]; + string = [ reference ]; + }; + in + state' + // { + dependencies = state'.dependencies ++ dependencies; + }; + + renderClaim + = { ... } @ document: + { body, reference, ... }: + output: + let + cite + = type.matchPrimitiveOrPanic reference + { + bool = error.throw "Bool in renderClaim?"; + list = string.concatMappedWith ({ name, ... }: name) "," reference; + set = reference.name; + }; + body' + = if reference != null + then + if output == "LaTeX" + then + chunks.addToLastItem body "\\cite{${cite}}" + else if output == "Markdown" + then + body + else + [] + else + body; + in + render document body'; + in + { + Claim + = claim: + reference: + chunks.Chunk "Claim" + { + render = renderClaim; + evaluate = evaluateClaim; + } + { + body = toBody claim; + dependencies = []; + inherit reference; + }; + } diff --git a/NixTeX/source/common/document/chunks/columns.nix b/NixTeX/source/common/document/chunks/columns.nix new file mode 100644 index 0000000..2830c3a --- /dev/null +++ b/NixTeX/source/common/document/chunks/columns.nix @@ -0,0 +1,53 @@ +# TODO: Remove LaTeX-Code, replace with renderer-methods +{ chunks, core, evaluator, renderer, ... }: + let + inherit(core) debug error string type; + inherit(evaluator) evaluate; + inherit(renderer) toBody render; + + evaluateColumns + = { ... } @ document: + { bibliography, ... } @ state: + { body, dependencies, reference, ... } @ columns: + let + state' = evaluate document state body; + in + state' + // { + dependencies = state'.dependencies ++ dependencies; + }; + + renderColumns + = { ... } @ document: + { body, reference, ... }: + output: + let + body' + = if reference != null + then + if output == "LaTeX" + then + chunks.addToLastItem body "\\cite{${cite}}" + else if output == "Markdown" + then + body + else + [] + else + body; + in + render document body'; + in + { + Columns + = { amount, }: + chunks.Chunk "Columns" + { + render = renderColumns; + evaluate = evaluateColumns; + } + { + body = toBody claim; + dependencies = []; + }; + } diff --git a/NixTeX/source/common/document/chunks/dedication.nix b/NixTeX/source/common/document/chunks/dedication.nix new file mode 100644 index 0000000..284798b --- /dev/null +++ b/NixTeX/source/common/document/chunks/dedication.nix @@ -0,0 +1,207 @@ +# TODO: Remove LaTeX-Code, replace with renderer-methods +{ chunks, core, evaluator, renderer, ... }: + let + inherit(core) debug error indentation list string type; + inherit(evaluator) evaluate; + inherit(renderer) toBody render; + + evaluateDedication + = { ... } @ document: + { ... } @ state: + { body, ... } @ dedication: + let + state' = evaluate document state body; + in + state'; + + replaceNewline + = text: + string.replace + [ "\n" ] + [ "\\noexpand\\linebreak " ] + (string.trim text); + + renderDedication + = { ... } @ document: + { body, epigraph, ... } @ dedication: + output: + let + epigraph' + = if epigraph != null + then + { + author + = let + author = epigraph.author or null; + in + type.matchPrimitiveOrPanic author + { + null = null; + string = { name = author; about = null; }; + set = { name = author.name; about = author.about or null; }; + }; + text + = let + text = epigraph.text or null; + in + type.matchPrimitiveOrPanic text + { + null = error.throw "Must not be null"; + string + = { + language= null; + original= text; + }; + set = { language = null; } // text; + }; + translation = epigraph.translation or null; + } + else + null; + + epigraphTeX + = let + transliteration + = let + lines + = let + lines = list.filter (line: line != "") (list.map string.trim (string.splitLines epigraph'.text.latin)); + first = list.head lines; + last = list.foot lines; + middle = list.map (line: "${line}\\linebreak%") ( list.body ( list.tail lines ) ); + length = list.length lines; + in + if length == 1 + then + [ "[${first}]%" ] + else + [ "[${first}\\linebreak%" ] + ++ middle + ++ [ "${last}]%" ]; + in + if epigraph'.text.language != null + && epigraph'.text ? latin + then + [ + "\\par%" + "{\\tiny%" indentation.more + ] + ++ lines + ++ [ indentation.less "}%" ] + else + []; + + text + = let + lines + = let + lines = list.filter (line: line != "") (list.map string.trim (string.splitLines epigraph'.text.original)); + first = list.head lines; + last = list.foot lines; + middle = list.map (line: "${line}\\linebreak%") ( list.body ( list.tail lines ) ); + in + if list.length lines == 1 + then + if epigraph'.text.language != null + then + "\\foreignquote{${epigraph'.text.language}}{${first}}%" + else + [ "${first}%" ] + else + [ "\\begin{quote}%" indentation.more ] + ++ ( + if epigraph'.text.language != null + then + [ "\\selectlanguage{${epigraph'.text.language}}%" ] + else + [] + ) + ++ [ "${first}\\linebreak%" ] + ++ middle + ++ [ + last + indentation.less "\\end{quote}%" + ]; + + text + = [ "{\\normalsize%" indentation.more ] + ++ lines + ++ [ indentation.less "}%" ]; + in + text ++ transliteration; + + translation + = let + formatTranslation + = text: + let + lines = list.filter (line: line != "") (list.map string.trim (string.splitLines text)); + first = list.head lines; + last = list.foot lines; + middle = list.map (line: "${line}\\newline%") ( list.body ( list.tail lines ) ); + in + if list.length lines == 1 + then + [ "\\par\\footnotesize(»${text}«)%" ] + else + [ "\\par\\footnotesize(»${first}\\newline%" ] + ++ middle + ++ [ "${last}«)%" ]; + in + type.matchPrimitiveOrPanic epigraph'.translation + { + null = []; + string = formatTranslation epigraph'.translation; + set = formatTranslation epigraph'.translation.deu; + }; + + author + = if epigraph'.author != null + then + if epigraph'.author.about != null + then + [ "\\par{\\raggedleft\\footnotesize– \\person{${epigraph'.author.name}}~(${replaceNewline epigraph'.author.about})}" ] + else + [ "\\par{\\raggedleft\\footnotesize– \\person{${epigraph'.author.name}}}" ] + else + []; + in + text + ++ translation + ++ author; + + epigraphTeX' + = if epigraph != null + then + [ + "{~\\vfill\\hfill\\parbox[][][t]{0.666\\linewidth}{{%" indentation.more + "\\tolerance 500%" + "\\emergencystretch 3em%" + "\\hfuzz=2pt%" + "\\vfuzz=2pt%" + "\\hyphenchar\\font=-1%" + ] + ++ epigraphTeX + ++ [ indentation.less "}}\\newpage}" ] + else + []; + in + ( render document body ) ++ epigraphTeX'; + + Dedication + = body: + epigraph: + chunks.Chunk "Dedication" + { + render = renderDedication; + evaluate = evaluateDedication; + } + { + body = toBody body; + inherit epigraph; + }; + in + { + inherit Dedication; + Epigraph = Dedication []; + } \ No newline at end of file diff --git a/NixTeX/source/common/document/chunks/default.nix b/NixTeX/source/common/document/chunks/default.nix new file mode 100644 index 0000000..aa1eb6f --- /dev/null +++ b/NixTeX/source/common/document/chunks/default.nix @@ -0,0 +1,79 @@ +{ core, evaluator, ... } @ libs: + let + inherit(core) debug library list set string type; + + Chunk + = type "Chunk" + { + from + = name: + { render, evaluate }: + fields: + Chunk.instanciateAs name + ( + fields + // { + inherit render evaluate; + } + ); + }; + + # [ T ] -> string -> [ T ] + addToLastItem + = items: + text: + let + len-1 = ( list.length items ) - 1; + last = list.foot items; + in + if list.isInstanceOf items + && items != [] + then + if string.isInstanceOf last + then + ( list.generate (n: list.get items n) len-1 ) ++ [ "${last}${text}" ] + else if set.isInstanceOf last && last ? body + then + ( list.generate (n: list.get items n) len-1 ) ++ [ ( last // { body = addToLastItem last.body text; } ) ] + else + items + else + items; + + # Import Chunk-Constructors + chunks + = let + libs' + = libs + // { + chunks = { inherit Chunk addToLastItem; }; + }; + in + list.fold + ( + { ... } @ chunks: + file: + chunks // ( library.import file libs' ) + ) + {} + [ + ./claim.nix + ./dedication.nix + ./figure.nix + ./heading.nix + ./latex.nix + ./list.nix + ./multilingual.nix + ./page.nix + ./paragraph.nix + ./phantomHeading.nix + ./scheme.nix + ./section.nix + ./slide.nix + ./table.nix + ./todo.nix + ]; + in + { + inherit Chunk chunks addToLastItem; + } \ No newline at end of file diff --git a/NixTeX/source/common/document/chunks/figure.nix b/NixTeX/source/common/document/chunks/figure.nix new file mode 100644 index 0000000..eda9349 --- /dev/null +++ b/NixTeX/source/common/document/chunks/figure.nix @@ -0,0 +1,458 @@ +# TODO: Remove LaTeX-Code, replace with renderer-methods +{ chunks, core, evaluator, renderer, ... }: + let + inherit(core) debug error indentation list number path set string type; + inherit(evaluator) evaluate; + inherit(renderer) putCaption toCaption toDescription render; + + evaluateFigure + = { ... } @ document: + { ... } @ state: + { dependencies, ... } @ figure: + let + state' = state; + in + state' + // { + dependencies = state'.dependencies ++ dependencies; + figures + = state'.figures + // { + counter = state'.figures.counter + 1; + }; + }; + + getOptions + = config: + ( if config ? width then [ "width=${string config.width}" ] else [ ] ) + ++ ( if config ? height then [ "height=${string config.height}" ] else [ ] ) + ++ ( getOptions' config ); + + getOptions' + = config: + ( if config ? totalheight then [ "totalheight=${string config.totalheight}" ] else [ ] ) + ++ ( if config.keepaspectratio or false then [ "keepaspectratio" ] else [ ] ) + ++ ( if config ? scale then [ "scale=${string config.scale}" ] else [ ] ) + ++ ( if config ? angle then [ "angle=${string config.angle}" ] else [ ] ) + ++ ( if config ? origin then [ "origin=${string config.origin}" ] else [ ] ) + ++ ( if config ? viewport then [ "viewport=${string config.viewport}" ] else [ ] ) + ++ ( if config ? trim then [ "trim=${string config.trim}" ] else [ ] ) + ++ ( if config.clip or false then [ "clip" ] else [ ] ) + ++ ( if config ? page then [ "page=${string config.page}" ] else [ ] ) + ++ ( if config ? pagebox then [ "pagebox=${string config.pagebox}" ] else [ ] ) + ++ ( if config.interpolate or false then [ "interpolate" ] else [ ] ) + ++ ( if config.quiet or false then [ "quiet" ] else [ ] ) + ++ ( if config.draft or false then [ "draft" ] else [ ] ) + ++ ( if config ? type then [ "type=${string config.type}" ] else [ ] ) + ++ ( if config ? ext then [ "ext=${string config.ext}" ] else [ ] ) + ++ ( if config ? read then [ "read=${string config.read}" ] else [ ] ) + ++ ( if config ? command then [ "command=${string config.command}" ] else [ ] ) + ++ ( config.extraOptions or [] ); + + orDefault + = first: + second: + if first != null + then + first + else + second; + + mapSubfigure + = { + align ? "b", + body ? null, + caption ? null, + cite ? null, + description ? null, + file ? null, + height ? null, + label ? null, + plot ? null, + uncover ? null, + only ? null, + width ? null, + ... + } @ config: + { + caption = null; + description = toDescription ( orDefault description caption); + inherit align cite label height width uncover only; + } + // ( + if file != null + then + { + body = null; + file + = type.matchPrimitiveOrPanic file + { + path = file; + string = file; + }; + options = getOptions' config; + plot = null; + } + else if plot != null + then + { + body = null; + file = null; + options = null; + inherit plot; + } + else if body != null + then + { + file = null; + options = null; + plot = null; + inherit body; + } + else + error.unimplemented + ); + + mapSubfigures + = list.map + ( + config: + if config != null + then + mapSubfigure config + else + config + ); + + # { ... } -> Document::Chunk::Figure -> [ string | Indentation ] + renderFigure + = _: + { label ? null, subfigures ? null, environment, ... } @ figure: + output: + let + render + = { body, file, options, uncover, only, ... }: + let + uncover' + = text: + if uncover != null + then + [ + "\\uncover<${uncover}>{%" indentation.more + "\\alt<${uncover}>{%" indentation.more + "${text}%" + indentation.less "}{%" indentation.more + "\\begin{tikzpicture}%" indentation.more + "\\node[anchor=south west,inner sep=0] (B) at (4,0) {${text}};%" + "\\fill [draw=none, fill=white, fill opacity=0.9] (B.north west) -- (B.north east) -- (B.south east) -- (B.south west) -- (B.north west) -- cycle;%" + indentation.less "\\end{tikzpicture}%" + indentation.less "}%" + indentation.less "}%" + ] + else if only != null + then + [ + "\\only<${only}>{%" indentation.more + "${text}%" + indentation.less "}%" + ] + else + [ text ]; + in + if file != null + then + if options != [ ] + then + uncover' "\\includegraphics[${string.concatWith "," options}]{\\source/${file}}" + else + uncover' "\\includegraphics[width=\\linewidth]{\\source/${file}}" + else + body; + in + if output == "LaTeX" + then + [ + "\\begin{${environment}}[H]%" indentation.more + "\\centering%" + ] + ++ ( + if subfigures != null + then + let + convert + = { align, label ? null, width, ... } @ figure: + [ + "\\begin{subfigure}[${align}]{${width}}" indentation.more + "\\centering" + ] + ++ ( render figure ) + ++ ( putCaption figure ) + ++ ( if label != null then [ "\\label{${label}}" ] else [] ) + ++ [ indentation.less "\\end{subfigure}" ]; + in + list.concatMap + ( + figure: + ( + if figure != null + then + convert figure + else + [ "\\hfill" ] + ) + ) + subfigures + else + render figure + ) + ++ ( putCaption figure ) + ++ ( + if label != null + then + [ "\\labelFigure{${label}}%" ] + else + [ ] + ) + ++ [ indentation.less "\\end{${environment}}%" ] + else if output == "Markdown" + then + [] + else + debug.panic "render" "Unknown output ${output}"; + + choose + = list.fold + ( + result: + item: + if result == null + then + item + else + result + ) + null; + in + { + # set | string -> list -> list -> Document::Chunk::Figure + Figure + = { + body ? null, + caption ? null, + cite ? null, + dependencies ? [], + description ? null, + file ? null, + height ? null, + label ? null, + plot ? null, + uncover ? null, + subfigures ? null, + width ? null, + only ? null, + environment ? "figure", + } @ config: + chunks.Chunk "Figure" + { + render = renderFigure; + evaluate = evaluateFigure; + } + ( + { + caption = toCaption ( choose [ caption description "" ] ); + description = toDescription ( choose [ description caption "" ] ); + inherit cite label height width uncover only environment; + } + // ( + if file != null + then + let + file' + = type.matchPrimitiveOrPanic file + { + path = "resources/figures/${path.getBaseName file}"; + string = file; + }; + in + { + body = null; + file = file'; + options = getOptions config; + subfigures = null; + dependencies + = dependencies + ++ ( + type.matchPrimitiveOrPanic file + { + path = [ { src = "${file}"; dst = "resources/figures/${path.getBaseName file}"; } ]; + string = []; + } + ); + } + else if plot != null + then + let + toPlot + = data: + type.matchPrimitiveOrPanic data + { + bool = error.throw "Bool in renderFigure?"; + path = "\"${data}\" notitle with lines lt rgb \"0x00777777\""; + string = "${data} notitle with lines lt rgb \"0x00777777\""; + set + = ( + let + plot + = if data.file or null != null + then + "\"${data.file}\"" + else if data.eq or null != null + then + data.eq + else + error.unimplemented; + title + = if data.title or null != null + then + "title \"${data.title}\"" + else + "notitle"; + lines + = if data.lines or true + then + "with lines lt" + else + ""; + colour + = if data.colour or null != null + then + data.colour + else + "0x00777777"; + in + "${plot} ${title} ${lines} rgb \"${colour}\"" + ); + }; + plots + = if list.isInstanceOf plot.data + then + string.concatWith ", " ( list.map toPlot plot.data ) + else + toPlot plot.data; + + genPeaks + = list.map + ( + { + x, y, + z ? 0, + colour ? "0x00aaaaaa", + text ? null, + }: + let + x' + = if set.isInstanceOf x + then + ( x.from + x.till ) / 2 + else + x; + x'' = string (number.round x'); + y' = string y; + z' = string (number.round ( x' + z )); + z'' = string (number.round ( x' + z - 60 )); + in + if plot.peaksTop or true + then + '' + set arrow from first ${x''}, graph 0.8 to first ${x''}, first ${y'} nohead lc rgb "${colour}" + set arrow from first ${x''}, graph 0.8 to first ${z'}, graph 0.87 nohead lc rgb "${colour}" + set label "\\tiny ${x''}" right rotate by 90 at first ${z'}, graph 0.88 + ${if text != null then ''set label "\\tiny (${text})" right rotate by 90 at first ${z''}, graph 0.88'' else ""} + '' + else + '' + set arrow from first ${x''}, graph 0.2 to first ${x''}, first ${y'} nohead lc rgb "${colour}" + set arrow from first ${x''}, graph 0.2 to first ${z'}, graph 0.13 nohead lc rgb "${colour}" + set label "\\tiny ${x''}" right rotate by 90 at first ${z'}, graph 0.12 + ${if text != null then ''set label "\\tiny (${text})" right rotate by 90 at first ${z''}, graph 0.12'' else ""} + '' + ); + + formatRange = { min, max }: "[${string min}:${string max}]"; + body + = string.concatLines + ( + [] + ++ ( if plot.title or null != null then [ "set title \"{\\\\footnotesize{${plot.title}}}\"" ] else [ "unset title" ] ) + ++ ( if plot.xLabel or null != null then [ "set xlabel \"{\\\\small{${plot.xLabel}}}\"" ] else [ "unset xlabel" ] ) + ++ ( if plot.yLabel or null != null then [ "set ylabel \"{\\\\small{${plot.yLabel}}}\"" ] else [ "unset ylabel" ] ) + ++ ( if plot.xRange or null != null then [ "set xrange ${formatRange plot.xRange}" ] else [] ) + ++ ( if plot.yRange or null != null then [ "set yrange ${formatRange plot.yRange}" ] else [] ) + ++ ( if plot.xTics or true then [ "set xtics in" ] else [ "unset xtics" ] ) + ++ ( if plot.yTics or true then [ "set ytics in" ] else [ "unset ytics" ] ) + ++ ( if plot.keyPos or null != null then [ "set key ${plot.keyPos}" ] else [] ) + ++ ( if plot.peaks or null != null then genPeaks plot.peaks else [] ) + ++ [ + "plot ${plots}" + "set output" + ] + ); + hash = string.hash "sha1" body; + dst = "generated/gnuplot/${hash}-plot"; + epsFile = "${dst}.eps"; + texFile = "${dst}.tex"; + gnuplotSrcFile + = path.toFile "${hash}.gnuplot" + '' + set terminal epslatex size ${string width},${string ( if height != null then height else width )} + set output "${epsFile}" + ${body} + ''; + gnuplotDstFile = "${dst}.gnuplot"; + + src + = output: + string.concatWith " && " + [ + "(mkdir -p \"generated/gnuplot/\"" + "gnuplot \"${gnuplotSrcFile}\"" + "mv \"${texFile}\" \"${output}.tex\"" + "epstopdf \"${epsFile}\" \"${output}.pdf\")" + ]; + + in + { + body = [ "{\\input{\\source/${texFile}}}%" ]; + file = null; + options = null; + subfigures = null; + dependencies + = dependencies + ++ [ + { src = gnuplotSrcFile; dst = gnuplotDstFile; } + { inherit dst src; } + ]; + } + else if body != null + then + { + body = list.expect body; + file = null; + options = null; + subfigures = null; + inherit dependencies; + } + else if subfigures != null + then + { + body = null; + file = null; + options = null; + subfigures = mapSubfigures ( list.expect subfigures ); + inherit dependencies; + } + else + error.unimplemented + ) + ); + } \ No newline at end of file diff --git a/NixTeX/source/common/document/chunks/heading.nix b/NixTeX/source/common/document/chunks/heading.nix new file mode 100644 index 0000000..2b92d22 --- /dev/null +++ b/NixTeX/source/common/document/chunks/heading.nix @@ -0,0 +1,129 @@ +# TODO: Remove LaTeX-Code, replace with renderer-methods +{ chunks, core, evaluator, renderer, ... }: + let + inherit(core) debug indentation list string type; + inherit(evaluator) evaluate; + inherit(renderer) putCaption toBody toTitle render; + + evaluateHeading + = { ... } @ document: + { ... } @ state: + { body, dependencies, ... } @ heading: + let + state' = evaluate document state body; + in + state' + // { + dependencies = state'.dependencies ++ dependencies; + }; + + renderHeading + = { level, ... } @ document: + { before, body, clearDoublePage, clearPage, clearPageOnLastQuarter, concise, label, rotate, title, ... } @ heading: + output: + let + body' = render (document // { level = list.tailOr level []; }) body; + level' = list.headOr level "paragraph"; + in + if output == "LaTeX" + then + let + label' + = if label != null + then + [ "\\label{${label}}%" ] + else + [ ]; + header + = [ "\\${level'}[\\nolink{%" indentation.more ] + ++ title.bookmark + ++ [ indentation.less "}]{%" indentation.more ] + ++ title.caption + ++ [ indentation.less "}" ]; + header' + = if title.visible + then + header + else + [ + "\\begingroup" indentation.more + "\\makeatletter\\let\\@makechapterhead\\@gobble\\makeatother" + ] + ++ header + ++ [ indentation.less "\\endgroup" ]; + clearPage' + = if !concise + && ( clearDoublePage || level' == "chapter" ) + then + [ "\\cleardoublepage%" ] + else if clearPage + then + [ "\\clearpage%" ] + else if clearPageOnLastQuarter + then + [ "\\clearPageOnLastQuarter%" ] + else + []; + rotate' + = if rotate + then + [ "\\rotatePages%" ] + else + [ "\\unrotatePages%" ]; + before' + = if before == null + then + [ ] + else if list.isInstanceOf before + then + before + else + [ before ]; + in + before' ++ clearPage' ++ rotate' ++ label' ++ header' ++ body' + else if output == "Markdown" + then + let + level'' + = { + chapter = "# "; + section = "## "; + subsection = "### "; + subsubsection = "#### "; + }.${level'} or ""; + in + [ + "${level''}${string.concatWith " " title.caption}" + ] + ++ body' + else + []; + + Heading = title: body: Heading' title body {}; + Heading' + = title: + body: + { + after ? null, + before ? null, + clearDoublePage ? false, + clearPage ? false, + clearPageOnLastQuarter ? false, + concise ? false, + dependencies ? [], + label ? null, + LaTeX ? false, + rotate ? false, + }: + chunks.Chunk "Heading" + { + render = renderHeading; + evaluate = evaluateHeading; + } + { + inherit after before clearDoublePage clearPage clearPageOnLastQuarter concise dependencies label rotate; + title = toTitle title LaTeX; + body = toBody body; + }; + in + { inherit Heading Heading'; } \ No newline at end of file diff --git a/NixTeX/source/common/document/chunks/journal.nix b/NixTeX/source/common/document/chunks/journal.nix new file mode 100644 index 0000000..77c90b7 --- /dev/null +++ b/NixTeX/source/common/document/chunks/journal.nix @@ -0,0 +1,113 @@ +# TODO: Remove LaTeX-Code, replace with renderer-methods +{ chunks, core, evaluator, renderer, ... }: + let + inherit(core) debug indentation list type; + inherit(evaluator) evaluate; + inherit(renderer) putCaption toBody toTitle render; + + evaluateJournal + = { ... } @ document: + { ... } @ state: + { body, dependencies, ... } @ journal: + let + state' = evaluate document state body; + in + state' + // { + dependencies = state'.dependencies ++ dependencies; + }; + + renderJournal + = { level, ... } @ document: + { before, body, clearDoublePage, clearPage, concise, label, rotate, title, ... } @ journal: + output: + let + label' + = if label != null + then + [ "\\label{${label}}%" ] + else + [ ]; + level' = list.headOr level "paragraph"; + header + = [ "\\${level'}[\\nolink{%" indentation.more ] + ++ title.bookmark + ++ [ indentation.less "}]{%" indentation.more ] + ++ title.caption + ++ [ indentation.less "}" ]; + header' + = if title.visible + then + header + else + [ + "\\begingroup" indentation.more + "\\makeatletter\\let\\@makechapterhead\\@gobble\\makeatother" + ] + ++ header + ++ [ indentation.less "\\endgroup" ]; + clearPage' + = if !concise + && ( clearDoublePage || level' == "chapter" ) + then + [ "\\cleardoublepage%" ] + else if clearPage + then + [ "\\clearpage%" ] + else + [ ]; + rotate' + = if rotate + then + [ "\\rotatePages%" ] + else + [ "\\unrotatePages%" ]; + body' = render (document // { level = list.tailOr level []; }) body; + before' + = if before == null + then + [ ] + else if list.isInstanceOf before + then + before + else + [ before ]; + in + before' ++ clearPage' ++ rotate' ++ label' ++ header' ++ [ "{" indentation.more ] ++ body' ++ [ indentation.less "}" null ]; + in + { + Journal + = { + __functor + = self: + { ... }: + { + + }; + Entry + = self: + title: + body: + { + after ? null, + before ? null, + clearDoublePage ? false, + clearPage ? false, + concise ? false, + dependencies ? [], + label ? null, + LaTeX ? false, + rotate ? false, + }: + chunks.Chunk "Journal" + { + render = renderJournal; + evaluate = evaluateJournal; + } + { + inherit after before clearDoublePage clearPage concise dependencies label rotate; + title = toTitle title LaTeX; + body = toBody body; + }; + }; + } \ No newline at end of file diff --git a/NixTeX/source/common/document/chunks/latex.nix b/NixTeX/source/common/document/chunks/latex.nix new file mode 100644 index 0000000..5f3fbe1 --- /dev/null +++ b/NixTeX/source/common/document/chunks/latex.nix @@ -0,0 +1,88 @@ +{ chunks, core, evaluator, renderer, ... }: +let + inherit(core) debug error indentation list string type; + inherit(evaluator) evaluate; + inherit(renderer) toBody render; + + evaluateLaTeX + = { ... } @ document: + { ... } @ state: + { dependencies, lines, ... }: + let + state' + = list.fold + ( + state: + chunk: + type.matchPrimitiveOrPanic chunk + { + lambda = error.throw "Lambda in evaluateLaTeX?"; + bool = error.throw "Bool in evaluateLaTeX?"; + null = state; + set + = if indentation.isInstanceOf chunk + then + state + else + evaluate document state chunk; + string = state; + } + ) + state + lines; + in + state' + // { + dependencies = state'.dependencies ++ dependencies; + }; + + renderLaTeX + = document: + { lines, ... }: + output: + if output == "LaTeX" + then + list.concatMap + ( + chunk: + type.matchPrimitiveOrPanic chunk + { + bool = error.throw "Bool in renderLaTeX?"; + null = [ chunk ]; + set = if indentation.isInstanceOf chunk then [ chunk ] else render document chunk; + string = [ chunk ]; + } + ) + lines + else if output == "Markdown" + then + [] + else + debug.panic "render" "Unknown output ${output}"; + LaTeX' + = lines: + { + dependencies ? [], + ... + }: + chunks.Chunk "LaTeX" + { + render = renderLaTeX; + evaluate = evaluateLaTeX; + } + ( + { + inherit dependencies; + lines + = type.matchPrimitiveOrPanic lines + { + string = string.splitLines lines; + list = lines; + }; + } + ); +in +{ + inherit LaTeX'; + LaTeX = lines: LaTeX' lines {}; +} \ No newline at end of file diff --git a/NixTeX/source/common/document/chunks/list.nix b/NixTeX/source/common/document/chunks/list.nix new file mode 100644 index 0000000..12b3179 --- /dev/null +++ b/NixTeX/source/common/document/chunks/list.nix @@ -0,0 +1,63 @@ +# TODO: Remove LaTeX-Code, replace with renderer-methods +{ chunks, core, evaluator, renderer, ... }: +let + inherit(core) debug indentation list type; + inherit(evaluator) evaluate; + inherit(renderer) toBody render; + + evaluateList + = { ... } @ document: + { bibliography, ... } @ state: + { items, ... }: + state; + + renderList + = document: + { items, ... }: + output: + [ "\\begin{itemize}" indentation.more ] + ++ ( + list.map + ( + item: + type.matchPrimitiveOrPanic item + { + string = "\\item ${item}"; + set + = let + label + = if item.label or null != null + then + "[${item.label}]" + else + ""; + slides + = if item.slides or null != null + then + "<${item.slides}>" + else + ""; + in + "\\item${slides}${label} ${item.text}"; + } + ) + items + ) + ++ [ indentation.less "\\end{itemize}" ]; +in +{ + List + = config: + items: + chunks.Chunk "List" + { + render = renderList; + evaluate = evaluateList; + } + ( + config + // { + inherit items; + } + ); +} \ No newline at end of file diff --git a/NixTeX/source/common/document/chunks/multilingual.nix b/NixTeX/source/common/document/chunks/multilingual.nix new file mode 100644 index 0000000..ef184d5 --- /dev/null +++ b/NixTeX/source/common/document/chunks/multilingual.nix @@ -0,0 +1,28 @@ +{ chunks, core, evaluator, renderer, ... }: + let + inherit(core) debug list type; + inherit(evaluator) evaluate; + inherit(renderer) render; + + evaluateMultilingual + = { language, ... } @ document: + { ... } @ state: + { ... } @ body: + evaluate document state body.${language}; + + renderMultilingual + = { language, ... } @ document: + { ... } @ body: + output: + render document body.${language}; + in + { + Multilingual + = { ... } @ body: + chunks.Chunk "Multilingual" + { + render = renderMultilingual; + evaluate = evaluateMultilingual; + } + body; + } \ No newline at end of file diff --git a/NixTeX/source/common/document/chunks/page.nix b/NixTeX/source/common/document/chunks/page.nix new file mode 100644 index 0000000..932d441 --- /dev/null +++ b/NixTeX/source/common/document/chunks/page.nix @@ -0,0 +1,35 @@ +# TODO: Remove LaTeX-Code, replace with renderer-methods +{ chunks, core, evaluator, renderer, ... }: + let + inherit(core) debug; + + evaluatePage + = { ... } @ document: + { ... } @ state: + { body, ... }: + state; + + renderClearPage + = { ... } @ document: + { body, ... }: + output: + if output == "LaTeX" + then + [ body ] + else if output == "Markdown" + then + [] + else + debug.panic "render" "Unknown output ${output}"; + in + { + ClearPage + = chunks.Chunk "ClearPage" + { + render = renderClearPage; + evaluate = evaluatePage; + } + { + body = "\\clearpage"; + }; + } \ No newline at end of file diff --git a/NixTeX/source/common/document/chunks/paragraph.nix b/NixTeX/source/common/document/chunks/paragraph.nix new file mode 100644 index 0000000..2409ffb --- /dev/null +++ b/NixTeX/source/common/document/chunks/paragraph.nix @@ -0,0 +1,54 @@ +# TODO: Remove LaTeX-Code, replace with renderer-methods +{ chunks, core, evaluator, renderer, ... }: + let + inherit(core) debug list; + inherit(evaluator) evaluateLine; + inherit(renderer) toLines; + + evaluateParagraph + = { ... }: + { ... } @ state: + { body, dependencies, ... }: + let + state' = list.fold evaluateLine state body; + in + state' + // { + dependencies = state'.dependencies ++ dependencies; + }; + + # { ... } -> Paragraph -> [ string ] + renderParagraph + = { ... }: + { body, endParagraph, ...}: + output: + if output == "LaTeX" + then + chunks.addToLastItem body endParagraph + else if output == "Markdown" + then + body + else + debug.panic "render" "Unknown output ${output}"; + + # string | [ string ] -> Document::Chunk::Paragraph + Paragraph = body: Paragraph' body {}; + + # string | [ string ] -> { ... } -> Document::Chunk::Paragraph + Paragraph' + = body: + { + endParagraph ? "\\par", + }: + chunks.Chunk "Paragraph" + { + render = renderParagraph; + evaluate = evaluateParagraph; + } + { + inherit endParagraph; + body = toLines body; + dependencies = []; + }; + in + { inherit Paragraph Paragraph'; } \ No newline at end of file diff --git a/NixTeX/source/common/document/chunks/phantomHeading.nix b/NixTeX/source/common/document/chunks/phantomHeading.nix new file mode 100644 index 0000000..e009670 --- /dev/null +++ b/NixTeX/source/common/document/chunks/phantomHeading.nix @@ -0,0 +1,45 @@ +# TODO: Remove LaTeX-Code, replace with renderer-methods +{ chunks, core, evaluator, renderer, ... }: + let + inherit(core) debug list; + inherit(evaluator) evaluate; + inherit(renderer) toBody render; + + evaluatePhantomHeading + = { ... } @ document: + { ... } @ state: + { body, dependencies, ... } @ heading: + let + state' = evaluate document state body; + in + state' + // { + dependencies = state'.dependencies ++ dependencies; + }; + + renderPhantomHeading + = { level, ... } @ document: + { body, ... } @ heading: + output: + render + ( + document + // { + level = list.tailOr level []; + } + ) + body; + + PhantomHeading + = body: + chunks.Chunk "PhantomHeading" + { + render = renderPhantomHeading; + evaluate = evaluatePhantomHeading; + } + { + body = toBody body; + dependencies = []; + }; + in + { inherit PhantomHeading; } \ No newline at end of file diff --git a/NixTeX/source/common/document/chunks/scheme.nix b/NixTeX/source/common/document/chunks/scheme.nix new file mode 100644 index 0000000..bff1c23 --- /dev/null +++ b/NixTeX/source/common/document/chunks/scheme.nix @@ -0,0 +1,273 @@ +# TODO: Remove LaTeX-Code, replace with renderer-methods +{ chunks, core, evaluator, renderer, ... }: +let + inherit(core) debug error indentation list string type; + inherit(evaluator) evaluate; + inherit(renderer) toBody toCaption toDescription putCaption render; + + # { ... } -> [ string ]: + mapChemeToken + = token: + let + phantom + = text: + if token.phantom or false + then + "\\phantom{${text}}" + else + text; + in + if token ? plus + then + [ "\\+" ] + else if token ? arrow + then + let + optionals + = list.map + ( + argument: + type.matchPrimitiveOrPanic argument + { + bool = error.throw "Bool in mapChemeToken?"; + null = "[]"; + int = "[${string argument}]"; + float = "[${string argument}]"; + string = "[\\tiny{${argument}}]"; + set + = if argument ? text + then let + pos + = if argument ? pos + then + ".${argument.pos}" + else + ""; + in + "[*{0${pos}}\\tiny{${argument.text}}]" + else + debug.panic "mapChemeToken" "Argument does not has a text."; + } + ) + token.arguments; + from = token.config.from or ""; + till = token.config.till or ""; + fromTo + = if from != "" + || till != "" + then + "(${string from}--${string till})" + else + ""; + angle = token.config.angle or ""; + length = token.config.length or ""; + config + = if angle != "" || length != "" + then + "[${string angle},${string length}]" + else + ""; + in + [ (phantom "\\arrow${fromTo}{${token.arrow}${string.concat optionals}}${config}") ] + else let + yield = token.config.yield or null; + withYield = if yield != null then "Yield{${string yield}}" else ""; + in if token ? substance + then + if token.number or false + && token.code or false + then + [ (phantom "\\directlua{substances.printMoleculeWithNumberCode([[${token.substance}]])}") ] + else if token.number or false + then + [ (phantom "\\directlua{substances.printMoleculeWithNumber([[${token.substance}]])}") ] + else if token.code or false + then + [ (phantom "\\directlua{substances.printMoleculeWithCode([[${token.substance}]])}") ] + else if token.text or null != null + then + [ (phantom "\\chemname{\\directlua{substances.printMolecule([[${token.substance}]])}}{\\tiny ${token.text}}") ] + else + [ (phantom "\\directlua{substances.printMolecule([[${token.substance}]])}") ] + else let + movPart + = type.matchPrimitiveOrPanic token.movPart + { + list = string.concat token.movPart; + string = token.movPart; + }; + movPart' + = if token ? movPart + then + [ "\\chemmove{${movPart}}" ] + else + []; + figPart + = type.matchPrimitiveOrPanic token.figPart + { + list = string.concat token.figPart; + string = token.figPart; + }; + in if token ? name + then + [ + (phantom "\\chemname{\\chemfig{${figPart}}}{\\tiny{${token.name}}}") + ] ++ movPart' + else + [ (phantom "\\chemfig{${figPart}}") ] ++ movPart'; + + + # [ { ... } ] -> [ string ]: + mapChemeLine + = line: + list.concatMap + ( + { scale ? 1.5, scheme, skip ? null, only ? null, uncover ? null, ... } @ line: + ( + if only != null + then + [ "\\only<${only}>{%" ] + else if uncover != null + then + [ "\\uncover<${uncover}>{%" ] + else + [] + ) + ++ [ + "\\scalebox{${string scale}}%" + "{%" indentation.more + ] + ++ [ "\\schemestart%" ] + ++ ( list.concatMap mapChemeToken scheme ) + ++ [ "\\schemestop%" ] + ++ ( + if line ? movPart + then + [ "\\chemmove{%" indentation.more ] + ++ line.movPart + ++ [ indentation.less "}%" ] + else + [] + ) + ++ [ indentation.less "}%" ] + ++ ( + let + skip' + = if skip != null + then + "[${string skip}\\normalbaselineskip]" + else + ""; + + in + [ "\\chemnameinit{}\\\\${skip'}%" ] + ) + ++ ( + if only != null || uncover != null + then + [ "}%" ] + else + [] + ) + ) + line; + + evaluateCheme + = { ... } @ document: + { ... } @ state: + { dependencies, ... } @ scheme: + let + state' = state; + in + state + // { + dependencies = state'.dependencies ++ dependencies; + schemes + = state'.schemes + // { + counter = state'.schemes.counter + 1; + }; + }; + + # { ... } -> Document::Chunk::Cheme -> [ indentation | string ]: + renderCheme + = _: + { numbers, body, label ? null, ... } @ scheme: + output: + if output == "LaTeX" + then + [ + "\\begin{scheme}[H]" indentation.more + ] + ++ ( + if numbers + then + [ "\\numAtoms" ] + else + [] + ) + ++ [ + "\\centering{%" indentation.more + ] + ++ ( mapChemeLine body ) + ++ [ indentation.less "}%" ] + ++ ( putCaption scheme ) + ++ ( + if label != null + then + [ "\\labelScheme{${label}}%" ] + else + [ ] + ) + ++ [ indentation.less "\\end{scheme}" ] + else if output == "Markdown" + then + [] + else + debug.panic "render" "Unknown output ${output}"; +in +{ + # string | set -> [ T ] -> Document::Chunk::Cheme: + Cheme + = { + Arrow + = arrow: + config: + arguments: + { inherit arrow config arguments; }; + Plus = { plus = null; }; + __functor + = self: + config: + body: + chunks.Chunk "Cheme" + { + render = renderCheme; + evaluate = evaluateCheme; + } + ( + type.matchPrimitiveOrPanic config + { + string + = { + caption = toCaption config; + description = toDescription config; + label = null; + numbers = false; + dependencies = []; + }; + set + = { + caption = toCaption ( config.caption or config.description or "" ); + description = toDescription ( config.description or config.caption or "" ); + label = config.label or null; + numbers = config.numbers or false; + dependencies = config.dependencies or []; + }; + } + // { + body = list.expect body; + } + ); + }; +} \ No newline at end of file diff --git a/NixTeX/source/common/document/chunks/section.nix b/NixTeX/source/common/document/chunks/section.nix new file mode 100644 index 0000000..0faf98c --- /dev/null +++ b/NixTeX/source/common/document/chunks/section.nix @@ -0,0 +1,57 @@ +# TODO: Remove LaTeX-Code, replace with renderer-methods +{ chunks, core, evaluator, renderer, ... }: + let + inherit(core) debug indentation list string type; + inherit(chunks) declare; + inherit(evaluator) evaluate; + inherit(renderer) putCaption toBody toTitle render; + + evaluateSection + = { ... } @ document: + { level ? 0, notes, ... } @ state: + { body, title, ... } @ section: + let + state' + = state + // { + level = level + 1; + notes + = notes + // { + pages + = notes.pages + ++ [ + { + inherit level; + title = title.caption; + } + ]; + }; + }; + state'' = evaluate document state' body; + in + state'' // { inherit level; }; + + renderSection + = { nested ? false, ... } @ document: + { body, title, ... } @ section: + output: + [ "\\${if nested then "sub" else ""}section{" indentation.more ] + ++ title.caption + ++ [ indentation.less "}" ] + ++ ( render ( document // { nested = true; } ) body ); + + Section + = title: + body: + chunks.Chunk "Section" + { + render = renderSection; + evaluate = evaluateSection; + } + { + body = toBody body; + title = toTitle title false; + }; + in + { inherit Section; } \ No newline at end of file diff --git a/NixTeX/source/common/document/chunks/slide.nix b/NixTeX/source/common/document/chunks/slide.nix new file mode 100644 index 0000000..cdcffa7 --- /dev/null +++ b/NixTeX/source/common/document/chunks/slide.nix @@ -0,0 +1,65 @@ +# TODO: Remove LaTeX-Code, replace with renderer-methods +{ chunks, core, evaluator, renderer, ... }: + let + inherit(core) debug indentation list string type; + inherit(evaluator) evaluate; + inherit(renderer) putCaption toBody toTitle render; + + evaluateSlide + = { ... } @ document: + { ... } @ state: + { body, dependencies, notes, ... } @ slide: + let + state' = evaluate document state body; + label = state'.notes.label + 1; + label' = string label; + pages + = list.imap + ( + overlay: + note: + { + inherit note overlay; + label = label'; + } + ) + notes; + in + state' + // { + dependencies = state'.dependencies ++ dependencies; + notes + = state'.notes + // { + inherit label; + pages = state'.notes.pages ++ pages; + }; + }; + + renderSlide + = { ... } @ document: + { align, body, notes, ... } @ slide: + output: + [ "\\begin{frame}[${align}]" indentation.more ] + ++ ( render document body ) + ++ (list.ifOrEmpty (notes != [] && notes != null) "\\only<1-${string (list.length notes)}>{}%") + ++ [ indentation.less "\\end{frame}" ]; + + Slide + = { + align ? "c", + dependencies ? [], + notes ? [], + }: + body: + chunks.Chunk "Slide" + { + render = renderSlide; + evaluate = evaluateSlide; + } + { + inherit align dependencies notes; + body = toBody body; + }; + in + { inherit Slide; } \ No newline at end of file diff --git a/NixTeX/source/common/document/chunks/table.nix b/NixTeX/source/common/document/chunks/table.nix new file mode 100644 index 0000000..b31efe5 --- /dev/null +++ b/NixTeX/source/common/document/chunks/table.nix @@ -0,0 +1,162 @@ +# TODO: Remove LaTeX-Code, replace with renderer-methods +{ chunks, core, evaluator, renderer, ... }: + let + inherit(core) debug indentation list string type; + inherit(evaluator) evaluate; + inherit(renderer) toCaption toDescription putCaption; + + evaluateTable + = { ... } @ document: + { ... } @ state: + { dependencies, ... } @ table: + let + state' = state; + in + state' + // { + dependencies = state'.dependencies ++ dependencies; + tables + = state'.tables + // { + counter = state'.tables.counter + 1; + }; + }; + + # { ... } -> Document::Chunk::Table -> [ string | Indentation ] + renderTable + = _: + { header, body, label, fontsize, ... } @ table: + output: + if output == "LaTeX" + then + let + header' + = list.fold + ( + state: + entry: + type.matchPrimitiveOrPanic entry + { + string + = { + line = state.line ++ [ entry ]; + config = "${state.config}l"; + bar = false; + }; + set + = let + bar = entry.bar or false; + bar' = if bar then "|" else ""; + in + if entry.config == "." + then + { + line = state.line ++ [ "\\${if bar then "T" else "t"}head{${entry.title}}" ]; + config = "${state.config}.${bar'}"; + inherit bar; + } + else + { + line = state.line ++ [ entry.title ]; + config = "${state.config}${entry.config}${bar'}"; + inherit bar; + }; + } + ) + { + line = [ ]; + config = ""; + bar = false; + } + header; + in + [ + "\\begin{table}[H]%" indentation.more + "\\centering{%" indentation.more + ] + ++ ( putCaption table ) + ++ ( + if label != null + then + [ "\\labelTable{${label}}%" ] + else + [ ] + ) + ++ ( + if fontsize != null + then + [ fontsize ] + else + [ ] + ) + ++ [ + "\\begin{tabular}{${header'.config}}" indentation.more + "\\toprule%" + "${string.concatWith " & " header'.line} \\\\" + "\\midrule%" + ] + ++ ( + list.map + ( + # list | string -> string + line: + type.matchPrimitiveOrPanic line + { + null = "\\midrule"; + list = "${string.concatWith " & " line} \\\\"; + string = line; + } + ) + body + ) + ++ [ + "\\bottomrule%" + indentation.less "\\end{tabular}" + indentation.less "}%" + indentation.less "\\end{table}" + ] + else if output == "Markdown" + then + [] + else + debug.panic "render" "Unknown output ${output}"; + in + { + # set | string -> list -> list -> Document::Chunk::Table + Table + = config: + header: + body: + chunks.Chunk "Table" + { + render = renderTable; + evaluate = evaluateTable; + } + ( + type.matchPrimitiveOrPanic config + { + string + = { + caption = toCaption config; + description = toDescription config; + cite = null; + label = null; + fontsize = null; + dependencies = []; + }; + set + = { + caption = toCaption ( config.caption or config.description or "" ); + description = toDescription ( config.description or config.caption or "" ); + cite = config.cite or null; + label = config.label or null; + fontsize = config.fontsize or null; + dependencies = config.dependencies or []; + }; + } + // { + header = list.expect header; + body = list.expect body; + } + ); + } diff --git a/NixTeX/source/common/document/chunks/todo.nix b/NixTeX/source/common/document/chunks/todo.nix new file mode 100644 index 0000000..dc0f502 --- /dev/null +++ b/NixTeX/source/common/document/chunks/todo.nix @@ -0,0 +1,52 @@ +{ chunks, core, evaluator, renderer, ... }: + let + inherit(core) debug list type; + inherit(evaluator) evaluate; + inherit(renderer) render; + + evaluateToDo + = { ... } @ document: + { context, todos, ... } @ state: + { body, tasks, ... }: + let + state' + = (evaluate document state body) + // { + todos + = todos + ++ ( + list.map + (task: { inherit context task; }) + tasks + ); + }; + in + if tasks != [] + then + debug.warn + context + { text = "Todo"; data = tasks; } + state' + else + state'; + + renderToDo + = { ... } @ document: + { body, ... }: + output: + render document body; + in + { + ToDo + = tasks: + body: + chunks.Chunk "ToDo" + { + render = renderToDo; + evaluate = evaluateToDo; + } + { + inherit body; + tasks = list.expect tasks; + }; + } \ No newline at end of file diff --git a/NixTeX/source/common/document/default.nix b/NixTeX/source/common/document/default.nix new file mode 100644 index 0000000..feaa121 --- /dev/null +++ b/NixTeX/source/common/document/default.nix @@ -0,0 +1,42 @@ +{ core, ... } @ libs: + let + inherit(core) library; + chunks = library.import ./chunks (libs // { inherit evaluator renderer; } ); + evaluator = library.import ./evaluate.nix (libs // { inherit chunks; } ); + renderers = library.import ./renderer (libs // { inherit chunks; } ); + renderer = renderers.LaTeX; + in + { + inherit(evaluator) escapeEncode evaluate; + toMarkdown + = { ... } @ document: + body: + if body != null + then + renderers.Markdown.render + ( + document + // { + level = [ "chapter" "section" "subsection" "subsubsection" ]; + } + ) + body + else + [ ]; + toTex + = { ... } @ document: + body: + if body != null + then + renderers.LaTeX.render + ( + document + // { + level = [ "chapter" "section" "subsection" "subsubsection" ]; + } + ) + body + else + [ ]; + } + // chunks.chunks diff --git a/NixTeX/source/common/document/evaluate.nix b/NixTeX/source/common/document/evaluate.nix new file mode 100644 index 0000000..fc002cf --- /dev/null +++ b/NixTeX/source/common/document/evaluate.nix @@ -0,0 +1,90 @@ +{ chunks, core, ... } @ libs: + let + inherit(core) debug error lambda list path set string type; + inherit(chunks) Chunk; + + # Helpers + escape = string.char.escape; + + # string -> arguments -> string + escapeEncode + = identifier: + arguments: + let + tabSepList = string.concatWith "\t" ( [ identifier ] ++ arguments ); + in + "${escape}${tabSepList}${escape}"; + + # State -> [ string ] -> State + evaluateLine + = let + # State -> string -> State + evaluateToken + = { ... } @ state: + token: + let + # (\t)* + token' = string.splitTabs token; + name = list.head token'; + arguments = list.tail token'; + in + if lambda.isInstanceOf state.${list.head token'} + then + state + // { + "${token'}" = _: state.${list.head token'} state arguments; + } + else + state + // { + "${token'}" = state.${list.head token'} arguments; + }; + in + state: + body: + list.fold # Lists will be evaulated from left to right! + ( + state: + token: + if list.isInstanceOf token + then + evaluateToken state token + else + state + ) + state + ( string.splitAt "${escape}(.*)${escape}" body ); + + + # State -> { ... } -> lambda | list | path | set | string -> State + evaluate + = { ... } @ document: + { context, ... } @ state: + body: + type.matchPrimitiveOrPanic body + { + bool = error.throw "Bool in evaluate?"; + list = list.fold (evaluate document) state body; + lambda + = let + libs' = libs // { inherit(state) context; }; + in + evaluate document state (body libs document); + path + = let + state' = state // { context = [ body ]; }; + in + evaluate document state' (path.import body); + set + = if body ? __type__ + then + ( Chunk.expect body ).evaluate document state body + else + #throw "Not a Chunk" + debug.panic "evaluate" { text = "This is not a Chunk!"; data = set.names body; }; + string = state; + }; + in + { + inherit evaluate evaluateLine escapeEncode; + } \ No newline at end of file diff --git a/NixTeX/source/common/document/renderer/LaTeX.nix b/NixTeX/source/common/document/renderer/LaTeX.nix new file mode 100644 index 0000000..a726bdf --- /dev/null +++ b/NixTeX/source/common/document/renderer/LaTeX.nix @@ -0,0 +1,315 @@ +{ chunks, core, ... } @ libs: + let + inherit(core) debug error indentation list path set string type; + inherit(chunks) Chunk addToLastItem; + inherit(chunks.chunks) Paragraph; + + escape = string.char.escape; + + # { ... } -> lambda | list | path | set | string -> [ string ] + render = render' false; + + render' + = paragraphs: + { ... } @ document: + body: + type.matchPrimitiveOrPanic body + { + bool = error.throw "Bool in render?"; + lambda = render' paragraphs document ( body libs document ); + list = list.concatMap (render' true document) body; + path = render' paragraphs document ( path.import body ); + set = ( Chunk.expect body ).render document body "LaTeX"; + string + = let + body' = list.map ( toLine true ) ( splitTexLines body ); + in + if paragraphs + then + addToLastItem body' "\\par" + else + body'; + }; + + # string -> [ string ] + splitTexLines = text: string.splitLines ( string.trim ( verifyString text ) ); + + # { caption, description, ... } -> [ Chunk ] + putCaption + = { caption, description, cite ? null, ... }: + if description != null + && description != [] + then + ( + if caption != null + then + [ "\\caption[\\nolink{%" indentation.more ] + ++ caption + ++ [ indentation.less "}]{%" indentation.more ] + else + [ "\\caption{%" indentation.more ] + ) + ++ [ + "\\tolerance 500%" + "\\emergencystretch 3em%" + "\\hfuzz=2pt%" + "\\vfuzz=2pt%" + "\\hyphenchar\\font=-1%" + ] + ++ ( + type.matchPrimitiveOrPanic cite + { + null = description; + list = addToLastItem description "\\cite{${string.concatMappedWith ({ name, ... }: name) "," cite}}"; + set = addToLastItem description "\\cite{${cite.name}}"; + } + ) + ++ [ indentation.less "}%" ] + else + []; + + # [ T ] | null | set | string -> [ T ] | [ ] + toBody + = body: + type.matchPrimitiveOrPanic body + { + bool = error.throw "Bool in toBody?"; + list = body; + null = [ ]; + set = [ body ]; + string = [ ( Paragraph body ) ]; + }; + + # string -> [ string ] + toCaption + = text: + if text != null + then + list.map ( toLine true ) ( splitTexLines text ) + else + null; + + # string -> [ string ] + toDescription + = text: + if text != null + then + list.map ( toLine true ) ( splitTexLines text ) + else + null; + + toLine + = checkCommands: + line: + let + knownCommands + = let + greekLetters + = [ + "alpha" "Alpha" + "beta" "Beta" + "gamma" "Gamma" + "delta" "Delta" + "epsilon" "Epsilon" + "zeta" "Zeta" + "eta" "Eta" + "theta" "Theta" "vartheta" + "iota" "Iota" + "kappa" "Kappa" + "lambda" "Lambda" + "mu" "Mu" + "nu" "Nu" + "xi" "Xi" + "omicron" "Omicron" + "pi" "Pi" + "rho" "Rho" + "sigma" "Sigma" + "tau" "Tau" + "upsilon" "Upsilon" + "phi" "Phi" + "chi" "Chi" + "psi" "Psi" + "omega" "Omega" + ]; + knownCommands + = [ + # Deprecate them soon + # Acronyms/Glossary + "acrfull" "acrlong" "acrshort" "acrtext" + "person" + # Chemistry + "ch" "compound" + "substance" "substanceFull" "substanceName" "substanceWithID" + # Labels and References + "refAppendix" "refEquation" "refFigure" "refScheme" "refTable" + "refPart" "refChapter" "refSection" "refSubsection" "refSubsubsection" "refParagraph" "refSubparagraph" "refSentence" + # Primitive + "ensuremath" + "mbox" + "minus" + "texorpdfstring" + "text" + "textsubscript" "textsuperscript" + + "rightarrow" + "directlua" + ] + ++ greekLetters; + in + list.mapNamesToSet (name: null) knownCommands; + filter + = item: + let + item' = list.head item; + in + if list.isInstanceOf item + then + if set.hasAttribute item' knownCommands + then + [ ] # Replace? + else + item + else + [ ]; + commands = list.concatMap filter ( string.split "[\\]([A-Za-z]+)" line ); + formatCommands + = { + "~~" = "\\strikeThrough{"; + "__" = "\\underLine{"; + "**" = "\\textbf{"; + "//" = "\\textit{"; + "++" = "\\highLight{"; + "--" = "{\\scriptsize "; + "`" = "\\texttt{"; + "##" = "\\textsc{"; + "\"" = "\\q{"; + }; + line' + = ( + list.fold + ( + { stack, text }: + token: + if string.isInstanceOf token + then + { + inherit stack; + text = "${text}${token}"; + } + else if list.head token != null + then + { + inherit stack; + text = "${text}${list.foot token}"; + } + else if stack != [] + -> list.head stack != list.foot token + then + { + stack = list.tail token ++ stack; + text = "${text}${formatCommands.${list.foot token}}"; + } + else + { + text = "${text}}"; + stack = list.tail stack; + } + ) + { + stack = []; + text = ""; + } + ( string.split "(\\\\)?(~~|__|\\*\\*|//|\\+\\+|--|`|##|\")" line ) + ).text; + in + debug.warn "toLine" + { + text = [ "Unknown LaTeX-Commands in line:" line ]; + data = commands; + when = checkCommands && commands != []; + } + ( string.concat ( string.splitAt "${escape}(.*)${escape}" line' ) ); + + # string | [ string ] -> [ string ] | ! + toLines + = toLines' true; + + toLines' + = checkCommands: + let + checkLines + = list.map + ( + line: + if string.isInstanceOf line + && string.match ".*\n.*" line == null + then + verifyString line + else + debug.panic [ "toLines'" "checkLines" ] "Lines must be a list of strings without newline \\n, got »${string line}«!" + ); + in + body: + type.matchPrimitiveOrPanic body + { + bool = error.throw "Bool in toLines'?"; + list = list.map ( toLine checkCommands ) ( checkLines body ); + string = list.map ( toLine checkCommands ) ( splitTexLines body ); + }; + + # string | { caption: string, bookmark: string?, visible: bool? } + # -> { caption: string, bookmark: string, visible: bool } + toTitle + = title: + latex: + type.matchPrimitiveOrPanic title + { + bool = error.throw "Bool in toTitle?"; + string + = { + caption = toLines' latex title; + bookmark = toLines' latex title; + visible = true; + }; + set + = { + caption = toLines' latex ( title.caption or (debug.panic "toTitle" "Title needs caption!" ) ); + bookmark = toLines' latex ( title.bookmark or title.caption or (debug.panic "toTitle" "Title needs bookmark!") ); + visible = title.visible or true; + }; + }; + + verifyString#: string -> string + = text: + let + count + = char: + list.fold + (counter: char': counter + (if char == char' then 1 else 0)) + 0 + (string.toCharacters text); + openA = count "{"; + closeA = count "}"; + openB = count "["; + closeB = count "]"; + openC = count "("; + closeC = count ")"; + warnIfUnequal + = a: b: + msg: + if a != b + then + debug.warn [ "document" "verifyString" ] "Counting ${msg} in\n${text}" + else + (x: x); + in + ( warnIfUnequal openA closeA "${string openA} »{« but ${string closeA} »}«" ) + ( warnIfUnequal openB closeB "${string openB} »[« but ${string closeB} »]«" ) + ( warnIfUnequal openC closeC "${string openC} »(« but ${string closeC} »)«" ) + text; + in + { + inherit toBody toCaption toDescription toLine toLines toTitle; + inherit putCaption render; + splitLines = splitTexLines; + } diff --git a/NixTeX/source/common/document/renderer/Markdown.nix b/NixTeX/source/common/document/renderer/Markdown.nix new file mode 100644 index 0000000..049ad6a --- /dev/null +++ b/NixTeX/source/common/document/renderer/Markdown.nix @@ -0,0 +1,180 @@ +{ chunks, core, ... } @ libs: + let + inherit(core) debug error indentation list set string type; + inherit(chunks) Chunk addToLastItem; + inherit(chunks.chunks) Paragraph; + + escape = string.char.escape; + + splitLines = text: string.splitLines ( string.trim text ); + + libs' + = libs + // { + chemistry + = libs.chemistry + // { + compound + = name: + let + parts = string.split "[|]" name; + parts' = list.filter (foo: string.isInstanceOf foo) parts; + in + string.concatWith "" parts'; + formatNMRnucleus + = nucleus: + nucleus; + }; + physical + = libs.physical + // { + formatValue + = value: + unit: + let + value' + = if set.isInstanceOf value + then + if value ? value + then + string value.value + else + "" + else + string value; + unit' + = if string.isInstanceOf unit + then + unit + else + ""; + in + "${value'} ${unit'}"; + }; + }; + + # { ... } -> lambda | list | path | set | string -> [ string ] + render + = { ... } @ document: + body: + type.matchPrimitiveOrPanic body + { + bool = error.throw "Bool in render?"; + lambda = render document ( body libs' document ); + list = list.concatMap (render document) body; + path = render document ( import body ); + set = ( Chunk.expect body ).render document body "Markdown"; + string = list.map ( toLine true ) ( splitLines body ); + }; + + putCaption + = { caption, description, cite ? null, ... }: + []; + + toBody + = body: + type.matchPrimitiveOrPanic body + { + bool = error.throw "Bool in toBody?"; + list = body; + null = [ ]; + set = [ body ]; + string = [ ( Paragraph body ) ]; + }; + + # string -> [ string ] + toCaption = text: list.map ( toLine true ) ( splitLines text ); + + # string -> [ string ] + toDescription = text: list.map ( toLine true ) ( splitLines text ); + + toLine + = checkCommands: + line: + let + formatCommands + = { + "~~" = "\\strikeThrough{"; + "__" = "\\underLine{"; + "**" = "\\textbf{"; + "//" = "\\textit{"; + "++" = "\\highLight{"; + "--" = "{\\scriptsize "; + "`" = "\\texttt{"; + "##" = "\\textsc{"; + "\"" = "\\q{"; + }; + line' + = ( + list.fold + ( + { stack, text }: + token: + if string.isInstanceOf token + then + { + inherit stack; + text = "${text}${token}"; + } + else if stack == [] + || ( list.head stack ) != ( list.head token ) + then + { + stack = token ++ stack; + text = "${text}"; # \textit{ + } + else + { + text = "${text}"; # } + stack = list.tail stack; + } + ) + { + stack = []; + text = ""; + } + ( string.split "(~~|__|\\*\\*|//|\\+\\+|--|`|##|\")" line ) + ).text; + in + string.concat ( string.splitAt "${escape}(.*)${escape}" line' ); + + # string | [ string ] -> [ string ] | ! + toLines + = toLines' true; + + toLines' + = checkCommands: + body: + type.matchPrimitiveOrPanic body + { + bool = error.throw "Bool in toLines'?"; + list = list.map ( toLine checkCommands ) body; + string = list.map ( toLine checkCommands ) ( splitLines body ); + }; + + # string | { caption: string, bookmark: string?, visible: bool? } + # -> { caption: string, bookmark: string, visible: bool } + toTitle + = title: + latex: + type.matchPrimitiveOrPanic title + { + bool = error.throw "Bool in toTitle?"; + string + = { + caption = toLines' latex title; + bookmark = toLines' latex title; + visible = true; + }; + set + = { + caption = toLines' latex ( title.caption or (debug.panic "toTitle" "Title needs caption!" ) ); + bookmark = toLines' latex ( title.bookmark or title.caption or (debug.panic "toTitle" "Title needs bookmark!") ); + visible = title.visible or true; + }; + }; + in + { + inherit splitLines toBody toCaption toDescription toLine toLines toTitle; + inherit putCaption render; + } \ No newline at end of file diff --git a/NixTeX/source/common/document/renderer/default.nix b/NixTeX/source/common/document/renderer/default.nix new file mode 100644 index 0000000..96ee625 --- /dev/null +++ b/NixTeX/source/common/document/renderer/default.nix @@ -0,0 +1,8 @@ +{ core, ... } @ libs: + let + inherit(core) library; + in + { + LaTeX = library.import ./LaTeX.nix libs; + Markdown = library.import ./Markdown.nix libs; + } \ No newline at end of file diff --git a/NixTeX/source/common/fonts/default.nix b/NixTeX/source/common/fonts/default.nix new file mode 100644 index 0000000..ccca728 --- /dev/null +++ b/NixTeX/source/common/fonts/default.nix @@ -0,0 +1,122 @@ +{ core, ... }: + let + inherit(core) indentation set; + + boldFont + = { + BoldFont = "*-Bold"; + UprightFont = "*-Regular"; + }; + + regularFont + = { + UprightFont = "*-Regular"; + }; + + lightFont + = { + BoldFont = "*-Bold"; + ItalicFont = "*-Light"; + UprightFont = "*-Regular"; + }; + + usualFont + = { + BoldFont = "*-Bold"; + BoldItalicFont = "*-BoldItalic"; + ItalicFont = "*-Italic"; + UprightFont = "*-Regular"; + }; + + defaultFontFeatures + = fontName: + { ... } @ features: + [ + "\\defaultfontfeatures[${fontName}]{" indentation.more + ] + ++ ( + set.mapToList + (key: value: "${key} = ${value},") + ( + { + Path = "\\source/fonts/"; + Extension = ".ttf"; + } + // features + ) + ) + ++ [ indentation.less "}" ]; + in [] + ++ ( defaultFontFeatures "Arimo" usualFont ) + ++ ( defaultFontFeatures "Cousine" usualFont ) + ++ ( defaultFontFeatures "DejaVu Sans" regularFont ) + ++ ( defaultFontFeatures "Liberation Mono" usualFont ) + ++ ( defaultFontFeatures "Liberation Sans" usualFont ) + ++ ( defaultFontFeatures "Liberation Serif" usualFont ) + ++ ( defaultFontFeatures "Noto Sans" usualFont ) + ++ ( defaultFontFeatures "Noto Serif" usualFont ) + ++ ( defaultFontFeatures "Noto Color Emoji" regularFont ) + ++ ( defaultFontFeatures "Noto Kufi Arabic" lightFont ) + ++ ( defaultFontFeatures "Noto Music Regular" regularFont ) + ++ ( defaultFontFeatures "Noto Naskh Arabic" boldFont ) + ++ ( defaultFontFeatures "Noto Naskh Arabic UI" boldFont ) + ++ ( defaultFontFeatures "Noto Nastaliq Urdu" boldFont ) + ++ ( defaultFontFeatures "Noto Rashi Hebrew" lightFont ) + ++ ( defaultFontFeatures "Noto Sans Adlam" boldFont ) + ++ ( defaultFontFeatures "Noto Sans Adlam Unjoined" boldFont ) + ++ ( defaultFontFeatures "Noto Sans Hebrew" lightFont ) + ++ ( defaultFontFeatures "Noto Serif Hebrew" lightFont ) + ++ ( defaultFontFeatures "Roboto" usualFont ) + ++ ( defaultFontFeatures "Roboto Condensed" usualFont ) + ++ ( defaultFontFeatures "Roboto Mono" usualFont ) + ++ ( defaultFontFeatures "Roboto Slab" lightFont ) + ++ ( defaultFontFeatures "Tinos" usualFont ) + ++ ( defaultFontFeatures "unifont" regularFont ) + ++ ( + defaultFontFeatures "forkawesome" + { + UprightFont = "*-webfont"; + } + ) + ++ ( + defaultFontFeatures "Font-Awesome" + { + Extension = ".otf"; + UprightFont = "*-6-Free-Regular-400"; + ItalicFont = "*-6-Free-Solid-900"; + SmallCapsFont = "*-6-Brands-Regular-400"; + } + ) + ++ [ + "\\newfontfamily{\\fontAwesome}{Font-Awesome}" + "\\DeclareTextFontCommand{\\textFontAwesome}{\\fontAwesome}" + "\\newfontfamily{\\forkAwesome}{forkawesome}" + "\\DeclareTextFontCommand{\\textForkAwesome}{\\forkAwesome}" + "\\def\\fullStop{\\foreignlanguage{british}{.}}" + "\\def\\comma{\\foreignlanguage{british}{,}}" + "\\setmainfont{Tinos}[]" + "\\setsansfont{Roboto}[]" + "\\setmonofont{Roboto Mono}[]" + "\\setmathfont{latinmodern-math.otf}[]" + "\\babelprovide[import]{british}" + "\\babelprovide[import,main]{ngerman}" + "\\babelfont{rm}{Tinos}" + "\\babelfont{sf}{Roboto}" + "\\babelfont{tt}{Roboto Mono}" + "\\babelprovide[import]{arabic}" + "\\babelfont[*arabic]{rm}[RawFeature=]{Noto Naskh Arabic}" + "\\babelfont[*arabic]{sf}[RawFeature={fallback=NotoSansFallback}]{Noto Kufi Arabic}" + "\\babelprovide[import]{greek}" + "\\babelfont[greek]{rm}{Noto Serif}" + "\\babelfont[greek]{sf}{Roboto}" + "\\babelfont[greek]{tt}{Roboto}" + "\\babelprovide[import]{hebrew}" + "\\babelfont[*hebrew]{rm}{Noto Serif Hebrew}" + "\\babelfont[*hebrew]{sf}{Noto Sans Hebrew}" + "\\babelfont[*hebrew]{tt}{Noto Sans Hebrew}" + #"\\babelprovide[import]{japanese}" + #"\\babelfont[japanese]{rm}{Noto Serif Japanese}" + #"\\babelfont[japanese]{sf}{Noto Sans Japanese}" + #"\\babelfont[japanese]{tt}{Noto Sans Japanese}" + "\\renewcommand{\\familydefault}{\\sfdefault}" + ] diff --git a/NixTeX/source/common/glossaries/acronyms/default.nix b/NixTeX/source/common/glossaries/acronyms/default.nix new file mode 100644 index 0000000..b5fb5bb --- /dev/null +++ b/NixTeX/source/common/glossaries/acronyms/default.nix @@ -0,0 +1,9 @@ +{ core, ... } @ libs: +let + inherit(core) library; +in + (library.import ./definition.nix libs) + // { + prepare = library.import ./prepare.nix libs; + toLua = library.import ./lua.nix libs; + } \ No newline at end of file diff --git a/NixTeX/source/common/glossaries/acronyms/definition.nix b/NixTeX/source/common/glossaries/acronyms/definition.nix new file mode 100644 index 0000000..6929553 --- /dev/null +++ b/NixTeX/source/common/glossaries/acronyms/definition.nix @@ -0,0 +1,128 @@ +{ core, physical, ... } @ libs: +let + inherit(core) debug list set string type; + inherit(physical) formatValueInMath; + + formatUnitDescription + = unit: + { + about ? null, + alternatives ? [], + archaic ? false, + description ? null, + foreign ? null, + person ? null, + pseudoUnit ? false, + siBasic ? false, + siDerived ? false, + value ? null, + }: + let + optional + = condition: + text: + if condition + then + [ text ] + else + [ ]; + origin + = if foreign != null + then + let + text = if foreign.text or null != null then " \\Q{${foreign.text}}" else ""; + latin = if foreign.latin or null != null then " (${foreign.latin})" else ""; + meaning = if foreign.meaning or null != null then ": \\textit{${foreign.meaning}}" else ""; + in + [ "von \\acrshort{${foreign.language}}${text}${latin}${meaning}" ] + else if person != null + then + [ "benannt nach ${person.about} \\person{${person.name}}" ] + else + []; + alternatives' + = let + last = list.foot alternatives; + first = list.body alternatives; + first' = list.map (item: "\\textit{${item}}") first; + in + if first != [] + then + "auch ${string.concatWith ", " first'} oder \\textit{${last}}" + else + "auch \\textit{${last}}"; + value' + = let + unit' = { value = 1; inherit unit; }; + mapValues + = ValueList: + "\\mbox{\\ensuremath{${string.concatMappedWith ({ value, unit }: formatValueInMath value unit) " = " ValueList}}}"; + in + type.matchPrimitiveOrPanic value + { + list = mapValues ( [ unit' ] ++ value ); + set = mapValues [ unit' value ]; + }; + parts + = ( + if siBasic + then + [ "\\acrshort{siStandard}-Basis\\-einheit ${about}" ] + else if siDerived + then + [ "\\acrshort{siStandard}-Einheit ${about}" ] + else if pseudoUnit + then + [ "Pseudo\\-einheit" ] + else if archaic + then + [ "Veraltete Einheit ${about}" ] + else + [ "Einheit ${about}" ] + ) + ++ (optional (alternatives != []) alternatives') + ++ origin + ++ (optional (value != null) value') + ++ (optional (description != null) description); + in + string.concatWith ", " parts; + + Miscellaneous + = { description, long, short, sortedBy ? "" }: + { + __type__ = "Acronym"; + __variant__ = "Miscellaneous"; + section = "Miscellaneous"; + inherit long short description sortedBy; + text = long; + data + = { + kind = "Default"; + inherit short; + }; + }; + + RawUnit + = kind: + short: + { title, description, sortedBy ? "" }: + { + __type__ = "Acronym"; + __variant__ = "Unit"; + section = "Units"; + text = title; + inherit title sortedBy; + description + = { name, ... }: + { + deu = formatUnitDescription name description.deu; + }; + data = { inherit kind short; }; + }; + +in +{ + Angle = RawUnit "Angle"; + Unit = RawUnit "Unit"; + inherit Miscellaneous; +} \ No newline at end of file diff --git a/NixTeX/source/common/glossaries/acronyms/lua.nix b/NixTeX/source/common/glossaries/acronyms/lua.nix new file mode 100644 index 0000000..aa07e58 --- /dev/null +++ b/NixTeX/source/common/glossaries/acronyms/lua.nix @@ -0,0 +1,83 @@ +{ core, ... }: + let + inherit(core) debug integer list path set string type; + in + { configuration, resources, ... }: + { + dst = "generated/acronyms.lua"; + src + = path.fromSet "acronyms.lua" + ( + name: + value: + let + escape = text: string.trim ( string.replace [ "\\" "\n" ] [ "\\\\" " " ] text ); + textDeu + = if set.isInstanceOf value.text.deu + then + "{\n \"${escape value.text.deu.tex or ""}\",\n \"${escape value.text.deu.pdf or ""}\"\n }" + else + "\"${escape value.text.deu}\""; + textEng + = if value.text ? eng + && set.isInstanceOf value.text.eng + then + "{\n \"${escape value.text.eng.tex or ""}\",\n \"${escape value.text.eng.pdf or ""}\"\n }" + else + "\"${escape value.text.eng or ""}\""; + sortedBy + = if value ? "sortedBy" + then + if set.isInstanceOf value.sortedBy + then + "\n sortedBy\n = {\n deu = \"${escape value.sortedBy.deu or ""}\",\n eng = \"${escape value.sortedBy.eng or ""},\"\n }," + else if integer.isInstanceOf value.sortedBy + then + "\n sortedBy = ${string value.sortedBy}," + else + "\n sortedBy = \"${escape value.sortedBy}\"," + else + ""; + bookmarkAs + = if value ? "bookmarkAs" + then + "\n bookmarkAs = \"${escape value.bookmarkAs}\"," + else + ""; + chemical + = if value.data ? "struct" + then + "\n \"${escape value.data.struct}\"," + else + ""; + short + = if set.isInstanceOf value.data.short + then + "{\n deu = \"${escape value.data.short.deu or ""}\",\n eng = \"${escape value.data.sorshortt.eng or ""},\"\n }" + else + "\"${escape value.data.short}\""; + in + '' + acronyms.list [ "${name}" ] + = { + section = sections.${value.section}, + text + = { + deu = ${textDeu}, + eng = ${textEng}, + }, + description + = { + deu = "${escape value.description.deu or ""}", + eng = "${escape value.description.eng or ""}", + }, + data + = { + acronyms.types.${value.data.kind}, + ${short},${chemical} + },${sortedBy}${bookmarkAs} + } + '' + ) + resources.acronyms or { }; + } diff --git a/NixTeX/source/common/glossaries/acronyms/prepare.nix b/NixTeX/source/common/glossaries/acronyms/prepare.nix new file mode 100644 index 0000000..a794b1b --- /dev/null +++ b/NixTeX/source/common/glossaries/acronyms/prepare.nix @@ -0,0 +1,30 @@ +{ core, ... }: + let + inherit(core) debug set string type; + in + { ... } @ acronyms: + ( + set.map + ( + name: + { description ? null, ... } @ acronym: + let + acronym' + = acronym + // { + inherit name; + full = { __toString = self: "\\acrfull{${name}}"; }; + long = { __toString = self: "\\acrlong{${name}}"; }; + short = { __toString = self: "\\acrshort{${name}}"; }; + as = text: { __toString = self: "\\acrtext[${name}]{${text}}"; }; + }; + in + type.matchPrimitiveOrPanic description + { + null = acronym'; + lambda = acronym' // { description = description acronym'; }; + set = acronym'; + } + ) + acronyms + ) diff --git a/NixTeX/source/common/glossaries/default.nix b/NixTeX/source/common/glossaries/default.nix new file mode 100644 index 0000000..94469a1 --- /dev/null +++ b/NixTeX/source/common/glossaries/default.nix @@ -0,0 +1,8 @@ +{ core, ... } @ libs: + let + inherit(core) library; + in + { + acronyms = library.import ./acronyms libs; + people = library.import ./people.nix libs; + } \ No newline at end of file diff --git a/NixTeX/source/common/glossaries/people.nix b/NixTeX/source/common/glossaries/people.nix new file mode 100644 index 0000000..eea125f --- /dev/null +++ b/NixTeX/source/common/glossaries/people.nix @@ -0,0 +1,90 @@ +{ core, ... } @ libs: +let + inherit(core) debug library list set type; + + uid + = { + __functor + = self: + counter: + { + inherit counter; + keys = { }; + values = [ ]; + inserted = null; + }; + + insert + = { ... } @ self: + value: + let + self' = tryInsert self value; + in + if !self'.inserted + then + debug.panic [ "uid" "insert" ] "Cannot insert value to unique, because it is already there!" + else + self'; + + length#: + = { values, ... }: + list.length values; + + tryInsert + = { counter, keys, values, ... } @ self: + value: + let + key = string value; + in + if keys.${key} or null == null + then + { + counter = counter + 1; + keys = keys // { ${key} = value; }; + values = values ++ [ value ]; + inserted = true; + } + else + self + // { + inserted = false; + }; + }; + + preparePerson + = identifier: + value: + value + // { + __functor + = self: + { surname, ... }: + "##${surname}##"; + }; + + preparePeople + = people: + type.matchPrimitiveOrPanic people + { + lambda + = preparePeople + ( + people + ( + libs + // { + Person + = name: + { + inherit name; + }; + } + ) + ); + path = preparePeople ( library.import people ); + set = set.map preparePerson people; + }; +in +{ + initEvaluationState = uid 0; +} \ No newline at end of file diff --git a/NixTeX/source/common/letters/default.nix b/NixTeX/source/common/letters/default.nix new file mode 100644 index 0000000..62f4265 --- /dev/null +++ b/NixTeX/source/common/letters/default.nix @@ -0,0 +1,40 @@ +{ ... }: + let + openingFromName + = { given ? null, honorific ? null, family, title ? null, ... }: + language: + let + honorific' + = if honorific != null + then + "${honorific} " + else + ""; + geehrter + = { + "Frau " = "geehrte"; + "Herr " = "geehrter"; + }.${honorific'} or "geehrte*r"; + name + = if given != null + then + "${given} ${family}" + else + family; + title' + = if title != null + then + "${title}~" + else + ""; + in + { + "deu" = "Sehr ${geehrter} ${honorific'}${title'}${name}"; + "eng" = "Dear ${honorific'}${title'}${name}"; + }.${language}; + + in + { + inherit openingFromName; + openingFromRecipient = { name, ... }: openingFromName name; + } \ No newline at end of file diff --git a/NixTeX/source/common/phonenumbers/default.nix b/NixTeX/source/common/phonenumbers/default.nix new file mode 100644 index 0000000..c7d6142 --- /dev/null +++ b/NixTeX/source/common/phonenumbers/default.nix @@ -0,0 +1,104 @@ +{ core, urls, ... }: + let + inherit(core) debug list string type; + + fromSet = { area, country, suffix } @ number: number; + splitRest = string.splitAt "[ ]+"; + + p2 = "2[07]|2[0-9]{2}"; + p3 = "3[0-469]|3[0-9]{2}"; + p4 = "42[0-9]|4[0-9]"; + p5 = "5[09][0-9]|5[1-8]"; + p6 = "6[0-6]|6[7-9][0-9]"; + p8 = "8[1246]|8[035789][0-9]"; + p9 = "9[0-58]|9[679][0-9]"; + restRegEx = "([0-9 /-]+)"; + internationalRegEx = "[+](1|${p2}|${p3}|${p4}|${p5}|${p6}|7|${p8}|${p9})[ -]?${restRegEx}"; + nationalRegEx = "0${restRegEx}"; + + formatTeX + = number: + let + number' = parse number; + rest = string.concatWith "\\," number'.suffix; + in + urls.formatTeXboxed "tel:${number}" + ( + if number'.country != null + then + if number'.area != null + then + "${number'.country}\\,${number'.area}\\,${rest}" + else + "${number'.country}\\,${rest}" + else + rest + ); + + parse + = number: + let + international = string.match internationalRegEx number; + national = string.match nationalRegEx number; + + country + = if international != null then "+${list.head international}" + else if national != null then "0" + else null; + + rest + = if international != null then list.get international 1 + else if national != null then list.head national + else number; + + defaultAreaAndSuffix + = { + area = null; + suffix = splitRest rest; + }; + + areaAndSuffix + = if country != null + && country != "0" + then + { + "+49" + = let + foo = string.match "(1?[0-9]{2})([0-9 -]+)" rest; + in + if foo != null + then + debug.info "areaAndSuffix" + { + text = "foo != null"; + show = true; + } + { + area = list.get foo 0; + suffix = splitRest (list.get foo 1); + } + else + debug.info "areaAndSuffix" + { + text = "foo == null"; + data = rest; + } + defaultAreaAndSuffix; + }.${country} or defaultAreaAndSuffix + else + defaultAreaAndSuffix; + in + type.matchPrimitiveOrPanic number + { + set = fromSet number; + string + = { + inherit country; + area = areaAndSuffix.area; + suffix = areaAndSuffix.suffix; + }; + }; + in + { + inherit formatTeX parse; + } diff --git a/NixTeX/source/common/physical/default.nix b/NixTeX/source/common/physical/default.nix new file mode 100644 index 0000000..75c0334 --- /dev/null +++ b/NixTeX/source/common/physical/default.nix @@ -0,0 +1,329 @@ +{ core, ... }: + let + inherit(core) debug integer number list string type; + + formatSign# string? -> string + = sign: + if sign != null + then + { + "+" = "+"; + "-" = "-"; + "+-" = "{\\pm}"; + "-+" = "{\\mp}"; + }.${sign} or "{${sign}}" + else + ""; + + Unit#: U: ToUnit @ U -> Unit | ! + = unit: + type.matchPrimitiveOrPanic unit + { + null = { inherit unit; }; + set + = { + prefix = unit.prefix or null; + inherit unit; + sign = unit.sign or null; + exp = unit.exp or null; + }; + string = parseUnit unit; + }; + + parseUnit#: string -> Unit + = let + prefixes = "yotta|zetta|exa|peta|tera|giga|mega|kilo|hecto|deca"; + prefixes' = "deci|centi|milli|micro|nano|pico|femto|atto|zepto|yocto"; + regex = "(${prefixes}|${prefixes'})?([A-Za-z]+)([-+])?([0-9]+|[0-9]*[.][0-9]*)?"; + in + unit: + let + parsed = string.match regex unit; + in + if unit == "cm-1" + then + { + prefix = null; + inherit unit; + sign = null; + exp = null; + } + else if unit == "" + then + null + else if parsed != null + then + { + prefix = list.get parsed 0; + unit = list.get parsed 1; + sign = list.get parsed 2; + exp = list.get parsed 3; + } + else + debug.panic "parseUnit" { data = unit; text = "Cannot parse unit:"; }; + + formatUnit#: U: ToUnit @ [ U ] | U -> string + = unit: + let + text = formatUnit' unit; + in + if text != null + then + "\\ensuremath{${text}}" + else + ""; + + formatUnit'#: U: ToUnit @ [ U ] | U -> string + = maybeUnit: + if list.isInstanceOf maybeUnit + then + string.concatMappedWith formatUnit' "\\cdot" maybeUnit + else + let + unit = Unit maybeUnit; + prefix + = if unit.prefix != null + && unit.prefix != "" + then + "\\acrshort{${unit.prefix}}" + else + ""; + link + = { + "gram" = "\\acrtext[kilogram]{g}"; + "calorie" = "\\acrtext[kilocalorie]{cal}"; + }.${unit.unit} or "\\acrshort{${unit.unit}}"; + formated = "\\text{${prefix}${link}}"; + withNumericExponent + = if unit.exp < 0 + then + "${formated}^{-\\text{${number.toSignificantString (0 - unit.exp)}}}" + else + "${formated}^{\\text{${number.toSignificantString unit.exp}}}"; + sign = formatSign unit.sign; + in + if unit != null + then + type.matchPrimitiveOrPanic unit.exp + { + null = formated; + int = withNumericExponent; + float = withNumericExponent; + string = "${formated}^{${sign}${adjustNumbers unit.exp}}"; + } + else + null; + + parseValue'#: V: ToValue @ [ V ] | V -> Value + = nested: + value: + type.matchPrimitiveOrPanic value + { + string + = let + parsed = string.match "([-+]|[+][-]|[-][+])?([0-9])[.]?([0-9]*)e?([+-]?)([0-9.]*)" value; + precision = string.length (list.get parsed 2); + in + if parsed != null + then + { + value + = ( integer "0${list.get parsed 1}" ) + + ( ( integer "0${list.get parsed 2}" ) + / ( number.pow 10 precision ) + ); + exp + = let + exponent = list.get parsed 4; + sign = list.get parsed 3; + in + if exponent != "" then "${if sign == "-" then "-" else ""}${exponent}" + else ""; + inherit precision; + sign = list.get parsed 0; + } + else + { + inherit value; + exp = null; + precision = null; + sign = null; + }; + float + = { + inherit value; + exp = null; + precision = null; + sign = null; + }; + int + = { + inherit value; + exp = null; + precision = 0; + sign = null; + }; + set + = if value ? from + && value ? till + then + { + value = { inherit(value) from till; }; + exp = value.exp or null; + precision = value.precision or null; + sign = value.sign or null; + } + else + { + value + = type.matchPrimitiveOrPanic value.value + { + string = value.value; + float = value.value; + int = value.value; + set + = if value.value ? from + && value.value ? till + then + value.value + else + debug.panic "parseValue'" "from and till expected!"; + list + = if nested + then + list.map (parseValue' false) value.value + else + debug.panic "parseValue'" "Set-Value cannot be nested!"; + }; + exp + = let + exp = value.exp or null; + in + type.matchPrimitiveOrPanic exp + { + null = null; + int = exp; + float = exp; + string = exp; + }; + precision = value.precision or (if integer.isInstanceOf value then 0 else null); + sign = value.sign or null; + }; + list + = if nested + then + { + value = list.map (parseValue' false) value; + exp = null; + precision = null; + sign = null; + } + else + debug.panic "parseValue'" "Lists cannot be nested!"; + }; + + parseValue#: V: ToValue @ [ V ] | V -> Value + = parseValue' true; + + formatValue#: V: ToValue, U: ToUnit @ V -> U -> string + = value: + unit: + "\\mbox{\\ensuremath{${formatValueInMath value unit}}}"; + + formatValueInMath#: V: ToValue, U: ToUnit @ V -> U -> string + = value: + unit: + let + valueText = formatValue' value; + unitText = formatUnit' unit; + in + if unitText != null + then + "${valueText}\\,${unitText}" + else + valueText; + + formatValue'#: V: ToValue @ [ V ] | V -> string + = value: + let + value' = parseValue value; + numeric = number.toStringWithPrecision value'.value value'.precision; + valueText + = type.matchPrimitiveOrPanic value'.value + { + set + = let + text = number.toStringWithPrecision value'.value value'.precision; + in + if value'.exp != null + || value'.sign != null + then + "(${text})" + else + text; + string = "${value'.value}"; + float = numeric; + int = numeric; + list + = let + text + = string.concatMappedWith + ( + { precision, ... } @ value: + formatValue' + ( + if precision != null + then + value // { inherit precision; } + else + value + ) + ) + ", " value'.value; + in + if value'.exp != null + || value'.sign != null + then + "(${text})" + else + text; + }; + exponentText + = let + withNumericExponent + = if value'.exp < 0 + then + "-\\text{${number.toSignificantString (0 - value'.exp)}}" + else + "\\text{${number.toSignificantString value'.exp}}"; + exponent + = type.matchPrimitiveOrPanic value'.exp + { + null = null; + int = withNumericExponent; + float = withNumericExponent; + string = adjustNumbers value'.exp; + }; + in + if exponent != null + then + "\\cdot\\text{10}^{${exponent}}" + else + ""; + in + "${formatSign value'.sign}${adjustNumbers valueText}${exponentText}"; + + adjustNumbers + = this: + string.concatMapped + ( + part: + if list.isInstanceOf part + then + "\\text{${list.head part}}" + else + part + ) + (string.split "([0-9]+|[0-9]*[.][0-9]*)" this); + in + { inherit formatValue formatValueInMath formatUnit; } \ No newline at end of file diff --git a/NixTeX/source/common/rate/default.nix b/NixTeX/source/common/rate/default.nix new file mode 100644 index 0000000..c3e847b --- /dev/null +++ b/NixTeX/source/common/rate/default.nix @@ -0,0 +1,12 @@ +{ core, ... }: + let + rate + = full: half: empty: + ""; + in + { + rateFullStars + = value: + maximum: + ""; + } diff --git a/NixTeX/source/common/symbols/default.nix b/NixTeX/source/common/symbols/default.nix new file mode 100644 index 0000000..43f925b --- /dev/null +++ b/NixTeX/source/common/symbols/default.nix @@ -0,0 +1,18 @@ +{ core, fork-awesome, ... }: + let + inherit(core) set; + + fromFontAwesome + = { + Regular = codePoint: "\\textFontAwesome{\\upshape^^^^${codePoint}}"; + Solid = codePoint: "\\textFontAwesome{\\itshape^^^^${codePoint}}"; + Brands = codePoint: "\\textFontAwesome{\\scshape^^^^${codePoint}}"; + }; + fromForkAwesome = codePoint: "\\textForkAwesome{^^^^${codePoint}}"; + + forkAwesome = fork-awesome.packages.x86_64-linux.default.icons; + in + { + inherit fromFontAwesome fromForkAwesome; + forkAwesome = set.mapValues fromForkAwesome forkAwesome; + } diff --git a/NixTeX/source/common/urls/default.nix b/NixTeX/source/common/urls/default.nix new file mode 100644 index 0000000..7ed3f66 --- /dev/null +++ b/NixTeX/source/common/urls/default.nix @@ -0,0 +1,16 @@ +{ core, ... }: + let + inherit(core) string; + escape = string.replace [ "_" "%" ] [ "\\_" "\\%" ]; + formatEmailTeX = href: formatTeX "mailto:${href}"; + formatHttpsTeX = href: formatTeX "https://${href}"; + formatHttpsTeX' = href: formatTeX "https:\\//${href}"; + formatTeX = href: text: "\\href{${href}}{${escape text}}"; + in + { + inherit formatEmailTeX formatHttpsTeX formatHttpsTeX' formatTeX; + formatEmailTeXboxed = href: text: "\\mbox{${formatEmailTeX href text}}"; + formatHttpsTeXboxed = href: text: "\\mbox{${formatHttpsTeX href text}}"; + formatHttpsTeXboxed' = href: text: "\\mbox{${formatHttpsTeX' href text}}"; + formatTeXboxed = href: text: "\\mbox{${formatTeX href text}}"; + } diff --git a/NixTeX/source/default.nix b/NixTeX/source/default.nix new file mode 100644 index 0000000..d46ac3d --- /dev/null +++ b/NixTeX/source/default.nix @@ -0,0 +1,60 @@ +{ core, ... } @ libs: + let + inherit(core) library path string; + + common = library.import ./common libs; + libs' = libs // common; + evaluate = library.import ./evaluate.nix libs'; + prepare = library.import ./prepare.nix libs'; + render = library.import ./render libs'; + + /*Document + = type "Document" + { + from + = documentType: + { evaluationOrder, render, ... }: + name: + { ... } @ document: + Document.instanciate documentType + { + __functor + = self: + outputFormat: + render outputFormat (evaluate evaluationOrder (prepare document)); + }; + };*/ + + constructDocument + = __type__: + { evaluationOrder, render, ... }: + name: + { ... } @ document: + { + __functor + = self: + outputFormat: + render outputFormat + ( + evaluate evaluationOrder + ( + prepare + ( + document + // { + inherit name __type__; + } + ) + ) + ); + }; + in + { + Application = constructDocument "Application" render.application; + Dependencies = [ { src = path; dst = string; } ]; + Disputation = constructDocument "Disputation" render.disputation; + # Journal = constructDocument "Journal" render.journal; + # Letter = constructDocument "Letter" render.letter; + # Thesis = constructDocument "Thesis" render.thesis; + } + // common diff --git a/NixTeX/source/evaluate.nix b/NixTeX/source/evaluate.nix new file mode 100644 index 0000000..65b89db --- /dev/null +++ b/NixTeX/source/evaluate.nix @@ -0,0 +1,164 @@ +{ bibliography, chemistry, core, document, ... }: + let + inherit(core) context expression list path set string; + inherit(chemistry) substances; + inherit(document) evaluate; + in + evaluationOrder: + { configuration, content, dependencies, name, resources, state ? {}, titleNotes ? null, ... } @ document: + let + initialState + = { + bibliography = bibliography.initEvaluationState; + dependencies = []; + figures + = { + counter = 1; + }; + notes + = let + notes + = { + enableMarkdown= true; + fontSize = 20; + version = 1; + } + // (configuration.notes or {}); + in + { + inherit(notes) enableMarkdown fontSize version; + label = if titleNotes != null then 1 else 0; + pages + = list.ifOrEmpty' + (titleNotes != null) + [ + { + title = "Title Page"; + level = 0; + } + { + label = "1"; + overlay = 0; + note = titleNotes; + } + ]; + }; + schemes + = { + counter = 1; + }; + source = context name; + substances = substances.evaluate configuration.concise; + tables + = { + counter = if configuration.concise then 0 else 1; # ToDo !!! + }; + todos = []; + } + // state; + + evaluatedState + = list.fold + ( + state: + part: + if set.hasAttribute part content + then + evaluate + { inherit configuration resources; } + (state // { context = [ ]; }) + content.${part} + else + state + ) + initialState + evaluationOrder; + + notes + = let + inherit(evaluatedState) notes; + in + { + dst = "${name}.md"; + src + = path.toFile "${name}.md" + ( + string.concatMappedLines + ( + { level ? 0, note ? [], title ? null, ... }: + if title != null + then + let + title' + = if list.isInstanceOf title + then + string.concatWith " " title + else + string title; + in + if level == 0 + then + "# ${title'}" + else + "## ${title'}" + else + note + ) + notes.pages + ); + }; + + pdfpc + = let + inherit(evaluatedState) notes; + in + { + dst = "${name}.pdfpc"; + src + = path.toFile "${name}.pdfpc" + ( + expression.toJSON + { + pdfpcFormat = notes.version; + disableMarkdown = !notes.enableMarkdown; + noteFontSize = notes.fontSize; + pages + = list.imap + (idx: page: page // { inherit idx; }) + ( + list.filter + ({ title ? null, ... }: title == null) + notes.pages + ); + } + ); + }; + in + document + // { + dependencies + = dependencies + ++ evaluatedState.dependencies + ++ (list.ifOrEmpty' (evaluatedState.notes.label != 0) [ pdfpc notes ]) + ++ [ + { + dst = "todos"; + src + = path.toFile "todos" + ( + string.concatMappedLines + ({ context, task }: "${string.concatWith " → " context}: ${task}") + evaluatedState.todos + ); + } + ]; + resources + = resources + // { + substances + = substances.finalise + resources.substances + evaluatedState.substances; + }; + state = evaluatedState; + } diff --git a/NixTeX/source/prepare.nix b/NixTeX/source/prepare.nix new file mode 100644 index 0000000..0d912c9 --- /dev/null +++ b/NixTeX/source/prepare.nix @@ -0,0 +1,59 @@ +{ bibliography, chemistry, core, glossaries, ... } @ libs: + let + inherit(core) library list path set string type; + inherit(chemistry) substances; + in#: D -> PreparedDocument where D: Document + { configuration, resources, title, ... } @ document: + let + concise = configuration.concise or false; + figures = path.import resources.figures; + figures' + = set.map + ( + name: + figure: + type.matchPrimitiveOrPanic figure + { + "path" = { src = figure; dst = "resources/figures/${name}-${path.getBaseName figure}"; }; + "string" = { src = figure; dst = "resources/figures/${name}-${path.getBaseName figure}"; }; + "set" = ({ src, dst }: { inherit src; dst = "resources/figures/${dst}"; }) figure; + } + ) + figures; + in + document + // { + configuration + = configuration + // { + inherit concise; + graduationThesis = configuration.graduationThesis or false; + }; + dependencies + = [ + { src = ../dependencies/assets; dst = "assets"; } + #{ src = ../dependencies/make.sh; dst = "make.sh"; } + { src = ../dependencies/source; dst = "source"; } + #{ src = ../dependencies/tuc; dst = "tuc"; } + ] + ++ (set.values figures'); + resources + = let + assets = library.import ../assets libs; + in + resources + // { + acronyms = glossaries.acronyms.prepare ( assets.acronyms // ( resources.acronyms or {} ) ); + figures = set.mapValues ({ src, dst }: dst) figures'; + hazardous = ( assets.hazardous // ( resources.acronyms or {} ) ); + references = bibliography.prepare ( ( resources.references or {} ) ); + substances = substances.prepare ( ( resources.substances or null ) ); + }; + title + = string.concatWith " " + ( + list.filter + (x: string.isInstanceOf x && !( string.isEmpty x ) ) + ( string.split "[[:space:]]+" title ) + ); + } diff --git a/NixTeX/source/render/application/default.nix b/NixTeX/source/render/application/default.nix new file mode 100644 index 0000000..2332543 --- /dev/null +++ b/NixTeX/source/render/application/default.nix @@ -0,0 +1,22 @@ +{ core, ... } @ libs: + let + inherit(core) library; + + getFormat + = outputFormat: + if outputFormat != null + then + outputFormat + else + "tex"; + renderTex = library.import ./tex libs; + renderMarkdown = library.import ./markdown libs; + in + { + evaluationOrder = []; + render + = outputFormat: + { + "tex" = renderTex; + }.${getFormat outputFormat}; + } diff --git a/NixTeX/source/render/application/tex/beginDocument.nix b/NixTeX/source/render/application/tex/beginDocument.nix new file mode 100644 index 0000000..edc58ff --- /dev/null +++ b/NixTeX/source/render/application/tex/beginDocument.nix @@ -0,0 +1,107 @@ +{ core, ... }: +let + inherit(core) indentation list string; + + setTolerances + = { + pretolerance ? 100, # + tolerance ? 200, # + hfuzz ? "0.1pt", # + vfuzz ? "0.1pt", # + hbadness ? 1000, # + vbadness ? 1000, # + emergencystretch ? "3em", # + }: + [ + "\\pretolerance=${string pretolerance}%" + "\\tolerance=${string tolerance}%" + "\\hfuzz=${string hfuzz}%" + "\\vfuzz=${string vfuzz}%" + "\\hbadness=${string hbadness}%" + "\\vbadness=${string vbadness}%" + "\\emergencystretch=${string emergencystretch}%" + ]; + + setPenalties + = { + binaryOperator ? 700, # for a line break in math mode after a binary operator. + brokenHyphen ? 100, # for a page break, where the last line of the previous page contains a hyphenation. + club ? 150, # for a broken page, with a single line of a paragraph remaining on the bottom of the preceding page. + displayWidow ? 50, # for a break before last line of a paragraph. + doubleHyphen ? 10000, # for two consecutive hyphenated lines. + explicitHyphen ? 50, # for hyphenating a word which already contains a hyphen. + finalHyphen ? 5000, # for a hyphen in the last full line of a paragraph. + floating ? 20000, # for splitting an insertion. + hyphen ? 50, # for line breaking at an automatically inserted hyphen. + incompatibleLines ? 10000, # for two consecutive lines are visually incompatible. + interDisplay ? 100, # for breaking a display on two pages. + interFootnote ? 100, # for breaking a footnote on two pages. + interLine ? 0, # for the penalty added after each line of a paragraph + line ? 10, # for each line within a paragraph. + postDisplay ? 0, # for a break after a display. + preDisplay ? 10000, # for a break before a display. + relationOperator ? 500, # for a line break in math mode after a a relation operator. + widow ? 150, # for a broken page, with a single line of a paragraph remaining on the top of the succeeding page. + }: + [ + "\\adjdemerits=${string incompatibleLines}%" + "\\binoppenalty=${string binaryOperator}%" + "\\brokenpenalty=${string brokenHyphen}%" + "\\clubpenalty=${string club}%" + "\\doublehyphendemerits=${string doubleHyphen}%" + "\\displaywidowpenalty=${string displayWidow}%" + "\\exhyphenpenalty=${string explicitHyphen}%" + "\\finalhyphendemerits=${string finalHyphen}%" + "\\floatingpenalty=${string floating}%" + "\\hyphenpenalty=${string hyphen}%" + "\\interdisplaylinepenalty=${string interDisplay}%" + "\\interfootnotelinepenalty=${string interFootnote}%" + "\\interlinepenalty=${string interLine}%" + "\\linepenalty=${string line}%" + "\\postdisplaypenalty=${string postDisplay}%" + "\\predisplaypenalty=${string preDisplay}%" + "\\relpenalty=${string relationOperator}%" + "\\widowpenalty=${string widow}%" + ]; +in + { + author ? "", + creator ? "", + keywords ? "", + producer ? "", + subject ? "", + title ? "", + ... + }: + [ + "\\hypersetup{" indentation.more + "pdfauthor={${author}}," + "pdftitle={${title}}," + "pdfsubject={${subject}}," + "pdfkeywords={${keywords}}," + "pdfproducer={${producer}}," + "pdfcreator={${creator}}," + indentation.less "}" + "\\hyphenchar\\font=-1%" + ] + ++ ( + setTolerances + { + tolerance = 500; + emergencystretch = "3em"; + hfuzz = "2pt"; + vfuzz = "2pt"; + } + ) + ++ ( + setPenalties + { + brokenHyphen = 100; + club = 350; + hyphen = 10000; + widow = 350; + } + ) + ++ [ + "\\markboth{}{}%" + ] diff --git a/NixTeX/source/render/application/tex/default.nix b/NixTeX/source/render/application/tex/default.nix new file mode 100644 index 0000000..f6dcf72 --- /dev/null +++ b/NixTeX/source/render/application/tex/default.nix @@ -0,0 +1,193 @@ +{ bibliography, chemistry, core, document, glossaries, ... } @ libs: +{ configuration, content, date, dependencies, language ? "eng", name, place, resources, ... } @ document: + let + inherit(core) debug indentation library list path string time; + + renderBeginDocument = library.import ./beginDocument.nix libs'; + renderEnclosures = library.import ./enclosures.nix libs'; + renderLetter = library.import ./letter.nix libs'; + renderPrelude = library.import ./prelude.nix libs'; + renderResume = library.import ./resume libs'; + + libs' + = libs + // { + toTex = libs.document.toTex { inherit configuration language resources; }; + }; + + packages + = [ + "logging" + "dependencies" + "chemistry/chem" + "chemistry/elements" + "bibliography/citation" + "floats/floats" + "geometry" + "glossaries/glossaries" + "links" + "symbols" + "text/text" + "utils" + ]; + + acronyms = glossaries.acronyms.toLua { inherit configuration resources; }; + references = bibliography.toBibTeX { inherit configuration resources; } resources.references; + substances = chemistry.substances.toLua { inherit configuration resources; } resources.substances; + + prelude + = { + acronyms = acronyms.dst; + assets = "assets/"; + packages = list.map (name: "\\input{\\source/source/${name}.tex}") packages; + references = references.dst; + source + = { + lua = "source/lua/"; + tex = "source/"; + }; + substances = substances.dst; + inherit(resume) publications; + }; + + letter + = { + inherit(document) configuration date language place; + sender + = { + inherit(resume) name social; + }; + subject = document.title; + } + // (path.import content.letter libs' document); + resume + = { + inherit(document) date language place; + } + // (path.import content.resume libs' document); + + pdfMeta + = { + author = "${resume.name.given} ${resume.name.family}"; + title + = "${document.title} ${{ deu = "am"; eng = "on"; }.${language}} ${time.formatDate document.date language}"; + subject + = { + deu = "Bewerbung"; + eng = "Application"; + }.${language}; + }; + + enclosures + = { + inherit(document) language; + inherit(letter) enclosures; + }; + + content' + = indentation { initial = ""; tab = " "; } + ( + [] + ++ ( renderPrelude prelude ) + ++ [ "\\begin{document}" indentation.more ] + ++ ( renderBeginDocument pdfMeta ) + ++ list.ifOrEmpty' + ((configuration.application or {}).letter or true) + ( renderLetter letter ) + ++ list.ifOrEmpty' + ((configuration.application or {}).resume or true) + ( renderResume resume ) + ++ list.ifOrEmpty' + ((configuration.application or {}).enclosures or true) + ( renderEnclosures enclosures ) + ++ [ "\\directlua{commonFinal()}" ] # ToDo: Remove! + ++ [ indentation.less "\\end{document}" ] + ); + + optimiser + = if configuration.optimise or false + then + '' + # Optimise and linearise + # This removes tooltips, sorry + mv "${name}.pdf" "${name}-raw.pdf" + gs \ + -dBATCH \ + -dColorImageResolution=288 \ + -dCompatibilityLevel=1.7 \ + -dDEBUG \ + -dDetectDuplicateImages \ + -dDownsampleColorImages=true \ + -dDownsampleGrayImages=true \ + -dDownsampleMonoImages=true \ + -dFastWebView \ + -dGrayImageResolution=288 \ + -dMonoImageResolution=288 \ + -dNOPAUSE \ + -dPDFSETTINGS=/ebook \ + -dPrinted=false \ + -sDEVICE=pdfwrite \ + -sOutputFile="${name}.pdf" \ + "${name}-raw.pdf" \ + > "${name}.gslog" 2>&1 + '' + else + ""; + + compile + = path.toFile "compile-${name}.sh" + '' + #!/usr/bin/env bash + echo "$out/${name}.tex" + #exit 0 + + newHash="false" + oldHash="true" + out="$1" + + counter="" + while [[ "$newHash" != "$oldHash" && "$counter" != "${configuration.foo or "+++++"}" ]] + do + if lualatex \ + --interaction=nonstopmode \ + --halt-on-error \ + --output-format=pdf \ + "\def\source{$out}\def\build{.}\input{$out/${name}.tex}" #2> /dev/null > /dev/null + then + oldHash="$newHash" + newHash="$(md5sum "${name}.pdf")" + echo "$newHash" + mv "${name}.log" "$out/${name}.log" + mv "${name}.llg" "$out/${name}.llg" + biber "${name}" + counter="+$counter" + else + exit 1 + fi + done + + ${optimiser} + # move the generated and processed document to the final-directory + mv "${name}.pdf" "$out/${name}.pdf" + ''; + texFile = path.toFile "${name}.tex" content'; + in + document + // { + content = content'; + dependencies + = dependencies + ++ [ + acronyms + references + substances + { + src = texFile; + dst = "${name}.tex"; + } + { + src = { store = compile; executable = true; }; + dst = "compile-${name}.sh"; + } + ]; + } diff --git a/NixTeX/source/render/application/tex/enclosures.nix b/NixTeX/source/render/application/tex/enclosures.nix new file mode 100644 index 0000000..11286d3 --- /dev/null +++ b/NixTeX/source/render/application/tex/enclosures.nix @@ -0,0 +1,57 @@ +{ core, ... }: +let + inherit(core) indentation list string; +in + { enclosures, language, ... }: + let + title + = { + deu = "Anlagen"; + eng = "Enclosures"; + }.${language}; + in + list.ifOrEmpty' (enclosures != null) + ( + [ + "\\cleardoublepage%" + "\\markboth{}{}%" + "\\markleft{${title}}%" + "\\thispagestyle{empty}%" + "\\phantomsection%" + "\\addsectiontocentry{}{${title}}%" + "\\begin{center}" indentation.more + "\\mbox{}%" + "\\vfill" + "{\\Huge \\textbf{${title}}}" + "\\vfill" + "\\begin{itemize}" indentation.more + ] + ++ ( + list.map + ( + { title, ... }: + "\\item ${title}" + ) + enclosures + ) + ++ [ + indentation.less "\\end{itemize}" + indentation.less "\\end{center}" + ] + ++ ( + list.concatMap + ( + { content, title, ... }: + [ "\\clearpage\\markleft{${title}}%" ] + ++ ( + list.map + ( + file: + "\\includegraphics[width=\\textwidth]{\\source/${string file}}\\clearpage%" + ) + content + ) + ) + enclosures + ) + ) diff --git a/NixTeX/source/render/application/tex/letter.nix b/NixTeX/source/render/application/tex/letter.nix new file mode 100644 index 0000000..ed07201 --- /dev/null +++ b/NixTeX/source/render/application/tex/letter.nix @@ -0,0 +1,319 @@ +{ core, letters, phonenumbers, symbols, toTex, urls, ... }: +{ + body, + closing, + configuration, + copies ? null, + customer ? null, + date, + enclosures ? null, + invoice ? null, + language ? "eng", + logo ? null, + my ? {}, + opening, + place, + recipient, + sender, + signature ? null, + subject, + your ? {}, + ... +}: + let + inherit(core) indentation list string time; + inherit(sender) name social; + inherit(social) address; + inherit(symbols.forkAwesome) email-bulk fax globe gnupg mobile phone; + + country' + = if address.country or null != null + then + "${address.country}\\," + else + ""; + + fluent + = { + deu + = { + cellPhone = "Mobil"; + copies = "Verteiler"; + email = "E-Mail"; + enclosures = "Anlagen"; + homePage = "Homepage"; + pgpKey = "PGP-Schlüssel"; + teleFax = "Fax"; + telePhone = "Telefon"; + }; + eng + = { + cellPhone = "Cellphone"; + copies = "Copies"; + email = "Email"; + enclosures = "Enclosures"; + homePage = "Homepage"; + pgpKey = "PGP-Key"; + teleFax = "Telefax"; + telePhone = "Telephone"; + }; + }; + + signatureHeight = "1.2cm"; + + formatEmail + = label: + address: + list.ifOrEmpty + (address != null) + "${label}: & ${urls.formatEmailTeXboxed address "\\texttt{${address}}"} \\\\"; + + formatPhoneNumber + = label: + number: + list.ifOrEmpty + (number != null) + "${label}: & ${phonenumbers.formatTeX number} \\\\"; + + formatURL + = label: + url: + list.ifOrEmpty + (url != null) + "${label}: & ${urls.formatHttpsTeXboxed url "\\texttt{${url}}"} \\\\"; + + + cellPhone = social.phone.cell or null; + email = social.email or null; + homePage = social.homepage or null; + pgpURL = social.pgpURL or null; + teleFax = social.phone.fax or null; + telePhone = social.phone.home or null; + + opening' + = if recipient.name or null != null + then + letters.openingFromName recipient.name language + else + opening; + + recipientToList + = { institute ? null, municipality ? null, name ? null, street ? null, ... }: + let + institute' + = institute; + + name' + = let + honorific + = if name.honorific or null != null + then + "${name.honorific}~" + else + ""; + title + = if name.title or null != null + then + "${name.title}~" + else + ""; + actualName + = if name.given or null != null + && name.family or null != null + then + "${name.given}~${name.family}" + else + name.given or name.family or name; + in + "${honorific}${title}${actualName}"; + + street' + = if street.name or null != null + && street.number or null != null + then + "${street.name}~${string street.number}" + else + street.name or street; + + municipality' + = let + country + = if municipality.country or null != null + then + if postalCode != "" + then + "${municipality.country}\\," + else + "${municipality.country}~" + else + ""; + postalCode + = if municipality.code or null != null + then + "${string municipality.code}~" + else + ""; + in + "${country}${postalCode}${municipality.name or municipality}"; + in [] + ++ (list.ifOrEmpty (institute != null) institute' ) + ++ (list.ifOrEmpty (name != null) name' ) + ++ (list.ifOrEmpty (street != null) street' ) + ++ (list.ifOrEmpty (municipality != null) municipality'); + + recipient' + = if list.isInstanceOf recipient + then + recipient + else + recipientToList recipient; + in + [ + #"\\addsectiontocentry{}{Anschreiben}" + "\\setkomavar{backaddress}{" indentation.more + "${name.given}\\ ${name.family} \\\\" + "${address.street.name}~${address.street.number} \\\\" + ] + ++ ( + list.ifOrEmpty + (address.street.extra or null != null) + "${address.street.extra} \\\\" + ) + ++ [ + "${country'}${address.postalCode}~${address.municipality}" + indentation.less "}%" + "\\setkomavar{backaddressseparator}{\\,·\\,}" + "\\KOMAoptions{" indentation.more + "foldmarks = H," + "subject = titled," + "pagenumber = off," + indentation.less "}%" + ] + ++ ( + list.ifOrEmpty + (customer != null) + "\\setkomavar{customer}[${customer.name or "Kunden\\-nummer"}]{${customer.value or customer}}%" + ) + ++ [ + "\\setkomavar{date}{${time.formatDate date language}}%" + ] + ++ ( + list.ifOrEmpty' (logo != null) + [ + "\\KOMAoptions{fromlogo=true}" + "\\setkomavar{fromlogo}{\\includegraphics[width=${logo.width}]{\\source/${logo.file}}}" + ] + ) + ++ ( + list.ifOrEmpty + (invoice != null) + "\\setkomavar{custominvoiceer}[${invoice.name or "Rechnungs\\-nummer"}]{${invoice.value or invoice}}%" + ) + ++ [ + "\\setkomavar{location}{{" indentation.more + "\\scriptsize" + "\\begin{tabular}{r@{\\,}ll}" indentation.more + "\\multicolumn{3}{l}{${name.given}\\ ${name.family}} \\\\" + "\\multicolumn{3}{l}{${address.street.name}~${address.street.number}} \\\\" + ] + ++ ( + list.ifOrEmpty + (address.street.extra or null != null) + "\\multicolumn{3}{l}{${address.street.extra}} \\\\" + ) + ++ [ "\\multicolumn{3}{l}{${country'}${address.postalCode}~${address.municipality}} \\\\" ] + ++ ( formatPhoneNumber "${phone} & ${fluent.${language}.telePhone}" telePhone ) + ++ ( formatPhoneNumber "${fax} & ${fluent.${language}.teleFax}" teleFax ) + ++ ( formatPhoneNumber "${mobile} & ${fluent.${language}.cellPhone}" cellPhone ) + ++ ( formatEmail "${email-bulk} & ${fluent.${language}.email}" email ) + ++ ( formatURL "${gnupg} & ${fluent.${language}.pgpKey}" pgpURL ) + ++ ( formatURL "${globe} & ${fluent.${language}.homePage}" homePage ) + ++ [ + indentation.less "\\end{tabular}" + indentation.less "}}%" + ] + ++ ( + list.ifOrEmpty + (my.ref or null != null) + "\\setkomavar{myref}[${my.ref.name or "Mein Zeichen"}]{${my.ref.value or my.ref}}%" + ) + ++ [ + "\\setkomavar{place}{${place}}%" + "\\makeatletter%" + "\\@setplength{lochpos}{1.0cm}%" + "\\@setplength{locwidth}{7.5cm}%" + "\\makeatother%" + "\\setkomavar{signature}{" indentation.more + ] + ++ ( + list.ifOrEmpty' (signature != null) + [ + "\\vspace{-${signatureHeight}}%" + "\\includegraphics[height=${signatureHeight}]{\\source/${signature}}\\\\[-.3\\normalbaselineskip]%" + ] + ) + ++ [ + "${name.given}~${name.family}" + indentation.less "}%" + "\\setkomavar{subject}{${subject}}%" + ] + ++ ( + list.ifOrEmpty + (your.mail or null != null) + "\\setkomavar{yourref}[${your.mail.name or "Ihr Zeichen"}]{${your.ref.value or your.ref}}%" + ) + ++ ( + list.ifOrEmpty + (your.ref or null != null) + "\\setkomavar{yourmail}[${your.ref.name or "Ihr Schreiben vom"}]{${your.ref.value or your.ref}}%" + ) + ++ [ + "\\begin{letter}{" indentation.more + ] + ++ (list.map (line: "${line}\\\\") recipient') + ++ [ + indentation.less "}" indentation.more + "\\opening{${opening'}}" + ] + ++ (toTex body) + ++ [ + "\\closing{${closing}}" + "\\vfill" + ] + ++ ( + list.ifOrEmpty' + ( + enclosures != null + && enclosures != [] + && (configuration.application or {}).enclosures or true + ) + ( + [ + "\\setkomavar*{enclseparator}{${fluent.${language}.enclosures}}%" + "\\encl{%" indentation.more + ] + ++ ( + list.map + ({ title, ... }: "${title},") + (list.body enclosures) + ) + ++ [ + "${(list.foot enclosures).title}" + indentation.less "}%" + ] + ) + ) + ++ ( + list.ifOrEmpty' + ( + copies != null + && copies != [] + && (configuration.application or {}).copies or true + ) + [ + "\\setkomavar*{ccseparator}{${fluent.${language}.copies}}%" + "\\cc{%" indentation.more + indentation.less "}%" + ] + ) + ++ [ indentation.less "\\end{letter}" ] diff --git a/NixTeX/source/render/application/tex/prelude.nix b/NixTeX/source/render/application/tex/prelude.nix new file mode 100644 index 0000000..3ad5a08 --- /dev/null +++ b/NixTeX/source/render/application/tex/prelude.nix @@ -0,0 +1,139 @@ +{ core, fonts, ... }: + let + inherit(core) indentation list set string; + in + { acronyms, assets, packages, publications, references, source, substances, ... }: + ( + [ + '' + \documentclass[ + 11pt, + a4paper, + twoside, + bookmarks = true, + pdfborder = {0 0 0}, + pdfencoding = auto, + unicode = true, + sections, + BCOR = 10mm, + listof = flat, + numbers = noenddot, + toc = listof, + toc = index, + table, + ] + {scrartcl} + '' + '' + \directlua{ + acronymFile = "${acronyms}" + jobname = [[\jobname]] + source = [[\source]].."/" + buildDirectory = [[\build]].."/" + dofile(source.."${source.lua}common.lua") + } + '' + "\\newcommand{\\inputCode }[1]{\\input{\\source/${source.tex}#1}}" + "\\newcommand{\\inputAssets}[1]{\\input{\\source/${assets}#1}}" + "\\def\\biblatexStyle{\\source/${assets}biblatex/chem-angew}" + "\\makeatletter" + ] + ++ packages + ++ [ + "\\makeatother" + "\\usepackage{scrlayer-scrpage}" + "\\usepackage{scrletter}" + ] + ++ fonts + ++ [ + "\\pdfvariable suppressoptionalinfo ${string ( 32 + 64 + 512 )}" # Makes the PDF constant + "\\setstretch{1.433}" # 1/2-spacing + + "\\DeclareFloatingEnvironment[" indentation.more + "fileext = los," + "listname = {Schema\\-verzeichnis}," + "name = Schema," + indentation.less "]{scheme}" + + # Header and Footer + '' + \def\pagemark{\thepage~/~\thelastpage} + \pagestyle{scrheadings} + \clearscrheadfoot + \ohead{\leftmark} + \ihead{\rightmark} + %\cfoot[\pagemark]{\pagemark} + \ofoot{\pagemark} + \newgeometry{ + margin=2.5cm + } + '' + + /* + '' + \newcommand{\enclosureSection }[2]% + {% + \phantomsection% + \mbox{}\\[-\normalbaselineskip]\nopagebreak% + \addsubsectiontocentry{} {#1}% + \markleft {#1}% + \ignorespaces#2\clearpage% + }% + + \constPDF + {\@LetterSenderFirstName\ \@LetterSenderLastName} + {\@LetterSubject vom \@LetterDate} + {\@LetterType} + + % Positons, Lengths, Alingments, etc. + \newgeometry + { + textwidth = 16.5cm, + left = 2.5cm, + } + '' + */ + ] + ++ ( + set.mapToList + ( + name: + colour: + "\\definecolor{${name}}{HTML}{${colour}}" + ) + { + white = "FFFFFF"; + black = "000000"; + darkgray = "333333"; + gray = "5D5D5D"; + lightgray = "999999"; + green = "C2E15F"; + orange = "FDA333"; + purple = "D3A4F9"; + red = "FB4485"; + blue = "6CE0F1"; + darktext = "414141"; + awesome-emerald = "00A388"; + awesome-skyblue = "0395DE"; + awesome-red = "DC3522"; + awesome-pink = "EF4089"; + awesome-orange = "FF6138"; + awesome-nephritis = "27AE60"; + awesome-concrete = "95A5A6"; + awesome-darknight = "131A28"; + } + ) + ++ ( + if substances != null + then + [ "\\directlua{substances.load(source..\"${string.slice 0 ((string.length substances) - 4) substances}\")}%" ] + else + [] + ) + + ++ [ + "\\addbibresource{\\source/${references}}" + "\\DeclareBibliographyCategory{ResumePublications}%" + ] + ++ (list.map ({ name, ... }: "\\addtocategory{ResumePublications}{${name}}%") publications) + ) diff --git a/NixTeX/source/render/application/tex/resume/default.nix b/NixTeX/source/render/application/tex/resume/default.nix new file mode 100644 index 0000000..d958c9a --- /dev/null +++ b/NixTeX/source/render/application/tex/resume/default.nix @@ -0,0 +1,13 @@ +{ core, ... } @ libs: +{ language, style, title, ... } @ resume: + let + inherit(core) indentation library; + config = { inherit language; } // (style.config or {}); + style' = (library.import ./styles libs).${style.name or style} config; + in + [ + "\\cleardoublepage" + "\\phantomsection" + "\\addsectiontocentry{}{${title}}" + ] + ++ style' resume diff --git a/NixTeX/source/render/application/tex/resume/styles/awesome/committees.nix b/NixTeX/source/render/application/tex/resume/styles/awesome/committees.nix new file mode 100644 index 0000000..0764d5a --- /dev/null +++ b/NixTeX/source/render/application/tex/resume/styles/awesome/committees.nix @@ -0,0 +1,45 @@ +{ core, document, helpers, styles, toTex, ... }: +{ language, ... }: + let + inherit(core) indentation list string; + inherit(document) Multilingual; + inherit(helpers) formatDate formatSection; + + toTex' = body: string.concatWith " " (toTex body); + + formatCommitteeEntries + = list.concatMap + ( + { date, institution, position, show ? true, title }: + let + date' = styles.committeeDate (formatDate date language); + institution' = styles.committeeInstitute (toTex' institution); + position' = styles.committeePosition (toTex' position); + title' = styles.committeeTitle (toTex' title); + in + list.ifOrEmpty show "${date'} & ${title'}, ${position'} & ${institution'} \\\\%" + ); + in + committees: + formatSection + ( + Multilingual + { + deu = "Gremientätigkeit"; + eng = "Committees"; + } + ) + ( + [ + "\\vspace{-1em}%" + "\\begin{center}%" indentation.more + "\\setlength{\\tabcolsep}{1ex}%" + "\\setlength{\\extrarowheight}{0pt}%" + "\\begin{tabularx}{\\textwidth}{cXr}%" indentation.more + ] + ++ (formatCommitteeEntries committees) + ++ [ + indentation.less "\\end{tabularx}%" + indentation.less "\\end{center}%" + ] + ) diff --git a/NixTeX/source/render/application/tex/resume/styles/awesome/default.nix b/NixTeX/source/render/application/tex/resume/styles/awesome/default.nix new file mode 100644 index 0000000..2e32f9a --- /dev/null +++ b/NixTeX/source/render/application/tex/resume/styles/awesome/default.nix @@ -0,0 +1,190 @@ +{ core, helpers, toTex, ... } @ libs: +{ + highlight ? 3, + language, + order ? [ + "summary" + "education" + "committees" + "honors" + "skills" + "languages" + "publications" + "motivation" + ], + ... +} @ config: + let + inherit(core) indentation list path string time; + inherit(helpers) formatDate; + + toTex' = body: string.concatWith " " (toTex body); + + libs' + = libs + // { + inherit styles; + helpers + = helpers + // { + inherit formatSection; + + formatEntry + = { date, description ? null, place ? null, position, title ? null }: + let + description' + = "\\multicolumn{2}{L{\\textwidth}}{${styles.description (toTex' description)}} \\\\%"; + title' + = if title != null + then + "${styles.entryTitle (toTex' title)} " + else + ""; + place' + = if place != null + then + "${styles.entryLocation (toTex' place)}" + else + ""; + in [] + ++ (list.ifOrEmpty (title != null || place != null) "${title'}& ${place'} \\\\%") + ++ [ "${styles.entryPosition (toTex' position)} & ${styles.entryDate (formatDate date language)} \\\\%" ] + ++ (list.ifOrEmpty (description != null) description'); + + formatItems + = title: + items: + formatSection title + ( + [ + "\\vspace{-1em}%" + "\\begin{justify}%" indentation.more + "\\begin{itemize}[label=\\bullet, #1, leftmargin=2ex, nosep, noitemsep]%" indentation.more + "\\setlength{\\parskip}{0pt}%" + ] + ++ items + ++ [ + indentation.less "\\end{itemize}%" + indentation.less "\\end{justify}%" + "\\vspace{-1em}%" + ] + ); + + formatParagraph + = title: + body: + formatSection title + ( + [ "\\\\[0pt]${styles.paragraphOpen}%" indentation.more ] + ++ (toTex body) + ++ [ indentation.less "\\vspace{1em}${styles.paragraphClose}%" ] + ); + }; + }; + + + formatCommittees = path.import ./committees.nix libs' config; + formatEducation = path.import ./education.nix libs' config; + formatHeader = path.import ./header.nix libs' config; + formatHonors = path.import ./honors.nix libs' config; + formatLanguages = path.import ./languages.nix libs' config; + formatMotivation = path.import ./motivation.nix libs' config; + formatPublications = path.import ./publications.nix libs' config; + formatSkills = path.import ./skills.nix libs' config; + formatSummary = path.import ./summary.nix libs' config; + + formatSection + = title: + body: + [ + "\\pagebreak[3]\\phantomsection%" + "\\addsubsectiontocentry{}{%" indentation.more + ] + ++ (toTex title) + ++ [ + indentation.less "}{%" indentation.more + styles.sectionTitleOpen indentation.more + ] + ++ (toTex title) + ++ [ + indentation.less styles.sectionTitleClose + indentation.less "}%" + styles.sectionBodyOpen indentation.more + ] + ++ body + ++ [ indentation.less styles.sectionBodyClose ]; + + styles = path.import ./styles.nix libs'; + in + { + about ? null, + birth ? null, + committees ? null, + date, + education ? null, + honors ? null, + languages ? null, + motivation ? null, + name, + nationality ? null, + photo ? null, + place ? null, + publications ? null, + quote ? null, + skills ? null, + social ? null, + summary ? null, + title, + ... + } @ resume: + [ + "\\pagestyle{scrheadings}%" + "\\clearscrheadfoot%" + "\\ifoot{${styles.footer (time.formatDate date language)}}%" + "\\cfoot{${styles.footer "${name.given} ${name.family}\\quad \\leftmark"}}%" + "\\ofoot{${styles.footer "\\pagemark"}}%" + "\\markboth{}{}%" + "\\markleft{${title}}%" + "\\newgeometry{%" indentation.more + "bottom = 2.0cm,%" + "footskip = 0.5cm,%" + "left = 2.0cm,%" + "right = 2.0cm,%" + "top = 1.5cm,%" + indentation.less "}%" + + "\\newsavebox\\acvHeaderSocialSepBox%" + "\\sbox\\acvHeaderSocialSepBox{\\textbar}%" + ( + let + args + = string.concat + ( + list.generate + (index: "#${string (index + 1)}") + highlight + ); + in + "\\def\\sectioncolor${args}{${styles.sectionColor args}}%" + ) + ] + ++ (formatHeader resume) + #++ [ "\\vspace{2.5\\normalbaselineskip}%" ] + ++ ( + list.concatMap + ( + sectionName: + { + committees = list.ifOrEmpty' (committees != null) (formatCommittees committees ); + education = list.ifOrEmpty' (education != null) (formatEducation education ); + honors = list.ifOrEmpty' (honors != null) (formatHonors honors ); + languages = list.ifOrEmpty' (languages != null) (formatLanguages languages ); + motivation = list.ifOrEmpty' (motivation != null) (formatMotivation motivation ); + publications = list.ifOrEmpty' (publications != null) (formatPublications publications); + skills = list.ifOrEmpty' (skills != null) (formatSkills skills ); + summary = list.ifOrEmpty' (summary != null) (formatSummary summary ); + }.${sectionName} + ) + order + ) + ++ [ "\\vfill%" ] diff --git a/NixTeX/source/render/application/tex/resume/styles/awesome/default.tex b/NixTeX/source/render/application/tex/resume/styles/awesome/default.tex new file mode 100644 index 0000000..937fdbf --- /dev/null +++ b/NixTeX/source/render/application/tex/resume/styles/awesome/default.tex @@ -0,0 +1,23 @@ +\renewcommand{\@ResumeSubEntry }[6] +{ + % 1 – date + % 2 – optional: position + % 3 – title + % 4 – location + % 5 – optional: grades + % 6 – optional: comment/description + \setlength\tabcolsep{0pt} + \setlength{\extrarowheight}{0pt} + \begin{tabular*}{\textwidth}{@{\extracolsep{\fill}} L{\textwidth - 4.5cm} R{4.5cm}} + \setlength\leftskip{0.2cm} + \subentrytitlestyle{#3} & \ifempty{#2}{\subentrydatestyle{#1}} \\ + \ifnotempty{#2} + { + \subentrypositionstyle{#2\ifnotempty{#5}{, #5}} & \subentrydatestyle{#1} \\ + } + \ifnotempty{#6} + { + \multicolumn{2}{L{17.0cm}}{\subdescriptionstyle{#6}} \\ + } + \end{tabular*} +} diff --git a/NixTeX/source/render/application/tex/resume/styles/awesome/education.nix b/NixTeX/source/render/application/tex/resume/styles/awesome/education.nix new file mode 100644 index 0000000..513a5d4 --- /dev/null +++ b/NixTeX/source/render/application/tex/resume/styles/awesome/education.nix @@ -0,0 +1,54 @@ +{ core, helpers, toTex, ... }: +{ ... }: + let + inherit(core) indentation list string; + inherit(helpers) formatEntry formatSection; + + toTex' = body: string.concatWith " " (toTex body); + + formatEducationEntries + = list.concatMap + ( + { date, degree, description ? null, grade ? null, institution, place ? null, show ? true }: + list.ifOrEmpty' show + ( + formatEntry + { + inherit date description place; + position + = if grade != null + then + "${toTex' degree}, ${toTex' grade}" + else + degree; + title = institution; + } + ) + ); + in + { body, show ? true, title }: + list.ifOrEmpty' show + ( + formatSection title + ( + [ + "\\begin{center}%" indentation.more + "\\vspace{-1em}%" + "\\setlength{\\tabcolsep}{0pt}%" + "\\setlength{\\extrarowheight}{0pt}%" + "\\begin{tabularx}{\\textwidth}{Xr}%" indentation.more + ] + ++ ( + list.concatMap + ( + { body, title }: + formatEducationEntries body + ) + body + ) + ++ [ + indentation.less "\\end{tabularx}%" + indentation.less "\\end{center}%" + ] + ) + ) diff --git a/NixTeX/source/render/application/tex/resume/styles/awesome/header.nix b/NixTeX/source/render/application/tex/resume/styles/awesome/header.nix new file mode 100644 index 0000000..3adff90 --- /dev/null +++ b/NixTeX/source/render/application/tex/resume/styles/awesome/header.nix @@ -0,0 +1,83 @@ +{ core, symbols, styles, toTex, ... } @ libs: +{ ... } @ config: + let + inherit(core) indentation list path string; + inherit(symbols.forkAwesome) home; + + toTex' = body: string.concatWith " " (toTex body); + + formatAddress + = { country, municipality, postalCode, street, ... }: + "${street.name}~${street.number}, ${country}${postalCode}~${municipality}"; + + formatHeaderAbout + = about: + styles.headerPosition "${toTex' about}\\\\[.4em]"; + + formatHeaderName + = { family, given, ... }: + [ + (styles.headerFirstName given) + (styles.headerLastName family) + ]; + + formatPicture + = position: + { + align ? "left", + edge ? true, + fileName, + shape ? "circle", + }: + if position == align + then + [ + "\\begin{minipage}[c]{.25\\linewidth}" indentation.more + { "left" = "\\raggedright{%"; "right" = "\\raggedleft{%"; }.${align} indentation.more + "\\begin{tikzpicture}%" indentation.more + "\\node[%" indentation.more + "${shape},%" + "draw = ${if edge then "none" else "darkgray"},%" + "line width = 0.1em,%" + "inner sep = ${{ "circle" = "3.2em"; "rectangle" = "4.5em"; }.${shape}},%" + "fill overzoom image = \\source/${fileName},%" + indentation.less "] () {};%" + indentation.less "\\end{tikzpicture}" + indentation.less "}%" + indentation.less "\\end{minipage}" + ] + else + []; + + formatQuote + = quote: + [ + ]; + + formatSocial = path.import ./social.nix libs config; + in + { + about ? null, + name, + photo ? null, + quote ? null, + show ? true, + social ? null, + ... + }: + list.ifOrEmpty' show + ( + [ "\\begin{minipage}[c]{\\textwidth}%" indentation.more ] + ++ (list.ifOrEmpty' (photo != null) (formatPicture "left" photo)) + ++ [ "\\begin{minipage}[c]{${if photo != null then ".75" else ""}\\linewidth}%" indentation.more ] + ++ (formatHeaderName name) + ++ [ "\\vspace{.4em}%" ] + ++ (list.ifOrEmpty (about != null) (formatHeaderAbout about)) + ++ [ (styles.headerAddress "${home}\\,${formatAddress social.address}\\\\[-.5em]") ] + ++ [ "\\\\[-2.5\\normalbaselineskip]%" ] + ++ (list.ifOrEmpty' (social != null) (formatSocial social)) + ++ (list.ifOrEmpty' (quote != null) (formatQuote quote)) + ++ [ indentation.less "\\end{minipage}%" ] + ++ (list.ifOrEmpty' (photo != null) (formatPicture "right" photo)) + ++ [ indentation.less "\\end{minipage}\\\\[0.5\\normalbaselineskip]%" ] + ) diff --git a/NixTeX/source/render/application/tex/resume/styles/awesome/honors.nix b/NixTeX/source/render/application/tex/resume/styles/awesome/honors.nix new file mode 100644 index 0000000..494e612 --- /dev/null +++ b/NixTeX/source/render/application/tex/resume/styles/awesome/honors.nix @@ -0,0 +1,40 @@ +{ core, helpers, styles, toTex, ... }: +{ language, ... }: + let + inherit(core) indentation list string; + inherit(helpers) formatDate formatSection; + + toTex' = body: string.concatWith " " (toTex body); + + formatHonor + = { date, description, place, show ? true, title }: + let + date' = styles.honorDate (formatDate date language); + place' = styles.honorLocation (toTex' place); + position' = styles.honorPosition (toTex' title); + title' = styles.honorTitle (toTex' description); + in + list.ifOrEmpty show "${date'} & ${position'}, ${title'} & ${place'} \\\\%"; + in + list.concatMap + ( + { body, show ? true, title }: + list.ifOrEmpty' show + ( + formatSection title + ( + [ + "\\vspace{-1em}%" + "\\begin{center}%" indentation.more + "\\setlength{\\tabcolsep}{1ex}%" + "\\setlength{\\extrarowheight}{0pt}%" + "\\begin{tabularx}{\\textwidth}{lXr}%" indentation.more + ] + ++ (list.concatMap formatHonor body) + ++ [ + indentation.less "\\end{tabularx}%" + indentation.less "\\end{center}%" + ] + ) + ) + ) diff --git a/NixTeX/source/render/application/tex/resume/styles/awesome/languages.nix b/NixTeX/source/render/application/tex/resume/styles/awesome/languages.nix new file mode 100644 index 0000000..8db0f1a --- /dev/null +++ b/NixTeX/source/render/application/tex/resume/styles/awesome/languages.nix @@ -0,0 +1,201 @@ +{ core, document, helpers, symbols, styles, toTex, ... }: +{ maxStars ? 5, ... }: + let + inherit(core) debug indentation list number set string type; + inherit(document) Multilingual; + inherit(helpers) formatSection; + inherit(symbols.forkAwesome) star star-half-o star-o; + + toTex' = body: string.concatWith " " (toTex body); + + languageLevels + = { + "native" + = { + description + = { + deu = "Muttersprache"; + eng = "Native Language"; + }; + level = Multilingual { deu = "nativ"; eng = "native"; }; + stars = 1.0; + }; + "C2" + = { + description + = { + deu = "Kompetente Sprachverwendung"; + eng = "Proficient User"; + }; + level = "C2"; + stars = 7 / 8.; + }; + "C1" + = { + description + = { + deu = "Kompetente Sprachverwendung"; + eng = "Proficient User"; + }; + level = "C1"; + stars = 6 / 8.; + }; + "B2" + = { + description + = { + deu = "Selbstständige Sprachverwendung"; + eng = "Independent User"; + }; + level = "B2"; + stars = 5 / 8.; + }; + "B1" + = { + description + = { + deu = "Selbstständige Sprachverwendung"; + eng = "Independent User"; + }; + level = "B1"; + stars = 4 / 8.; + }; + "A2" + = { + description + = { + deu = "Elementare Sprachverwendung"; + eng = "Basic User"; + }; + level = "A2"; + stars = 3 / 8.; + }; + "A1" + = { + description + = { + deu = "Elementare Sprachverwendung"; + eng = "Basic User"; + }; + level = "A1"; + stars = 2 / 8.; + }; + "latinum" + = { + description + = { + deu = "Latinum"; + eng = "Latinum"; + }; + level = null; + stars = 1 / 8.; + }; + }; + + languageNames + = { + ces = { deu = "Tschechisch"; eng = "Czech"; }; + deu = { deu = "Deutsch"; eng = "German"; }; + eng = { deu = "Englisch"; eng = "English"; }; + epo = { deu = "Esperanto"; eng = "Esperanto"; }; + heb = { deu = "Ivrit"; eng = "Ivrit"; }; + lat = { deu = "Latein"; eng = "Latin"; }; + }; + + rateHalfStars + = value: + maximum: + let + full = number.floor (value * maximum); + empty = number.floor ((1 - value) * maximum); + half = maximum - full - empty; + in + (list.generate (_: star) full) + ++ (list.ifOrEmpty (half != 0) star-half-o) + ++ (list.generate (_: star-o) empty); + + formatLanguage + = name: + { description, level, stars, ... }: + let + name' = styles.skillType (toTex' (Multilingual name)); + level' = if level != null then styles.skillSet (toTex' level) else ""; + description' = styles.description (toTex' (Multilingual description)); + stars' + = if stars != null + then + string.concat (rateHalfStars stars maxStars) + else + ""; + in + "${name'} & ${description'} & ${level'} & ${styles.entryLocation stars'} \\\\%"; + in + languages: + let + emptyLevel + = { + description = ""; + level = ""; + stars = 0; + }; + languages' + = set.mapToList + ( + language: + level: + { + name = languageNames.${language} or language; + level + = type.matchPrimitiveOrPanic level + { + null = emptyLevel; + int + = debug.panic "languages'" + { + text = "Level of type integer must be between 0 and `maxStars` (${string maxStars}) inclusive, got:"; + data = level; + when = level < 0 || level > maxStars; + } + ( emptyLevel // { stars = 1.0 * level / maxStars; }); + float + = debug.panic "languages'" + { + text = "Level of type float must be between 0.0 and 1.0 inclusive, got:"; + data = level; + when = level < 0.0 || level > 1.0; + } + ( emptyLevel // { stars = level; }); + set = emptyLevel // level; + string = languageLevels.${level}; + }; + } + ) + languages; + compare = foo: bar: foo.level.stars > bar.level.stars; + in + formatSection + ( + Multilingual + { + deu = "Sprachen"; + eng = "Languages"; + } + ) + ( + [ + "\\vspace{-1em}%" + "\\begin{center}%" indentation.more + "\\setlength{\\tabcolsep}{1ex}%" + "\\setlength{\\extrarowheight}{0pt}%" + "\\begin{tabularx}{\\textwidth}{rXrl}%" indentation.more + ] + ++ ( + list.map + ({ name, level }: formatLanguage name level) + (list.sort compare languages') + ) + ++ [ + indentation.less "\\end{tabularx}%" + indentation.less "\\end{center}%" + ] + ) diff --git a/NixTeX/source/render/application/tex/resume/styles/awesome/motivation.nix b/NixTeX/source/render/application/tex/resume/styles/awesome/motivation.nix new file mode 100644 index 0000000..31efab1 --- /dev/null +++ b/NixTeX/source/render/application/tex/resume/styles/awesome/motivation.nix @@ -0,0 +1,15 @@ +{ core, toTex, ... }: +{ ... }: + let + inherit(core) indentation; + in + body: + [ + "{%" indentation.more + "\\def\\section#1{(((#1)))}%" + "\\def\\subsection#1{((#1))}%" + ] + #++ (toTex body) + ++ [ + indentation.less "}%" + ] diff --git a/NixTeX/source/render/application/tex/resume/styles/awesome/publications.nix b/NixTeX/source/render/application/tex/resume/styles/awesome/publications.nix new file mode 100644 index 0000000..050d233 --- /dev/null +++ b/NixTeX/source/render/application/tex/resume/styles/awesome/publications.nix @@ -0,0 +1,25 @@ +{ core, document, helpers, ... }: +{ ... }: + let + inherit(core) indentation list; + inherit(document) Multilingual; + inherit(helpers) formatSection; + in + publications: + formatSection + ( + Multilingual + { + deu = "Publikationen"; + eng = "Publicationen"; + } + ) + ( + [ "\\vspace{-1em}%" ] + ++ (list.map ({ name, ... }: "\\nocite{${name}}%") publications) + ++ [ + "\\begin{refcontext}[sorting=ydnt]%" indentation.more + "\\printbibliography[heading=none,category=ResumePublications]%" + indentation.less "\\end{refcontext}%" + ] + ) diff --git a/NixTeX/source/render/application/tex/resume/styles/awesome/save.nix b/NixTeX/source/render/application/tex/resume/styles/awesome/save.nix new file mode 100644 index 0000000..4428dc8 --- /dev/null +++ b/NixTeX/source/render/application/tex/resume/styles/awesome/save.nix @@ -0,0 +1,80 @@ +{ + formatChapter + = { body, title }: + [ + "\\markleft{#1}%" + "{\\fontsize{32pt}{1em}${selectFont.headerLight}\\color{graytext} ${title}}\\newline%" + "{\\ignorespaces\\unskip{${body}}}%" + ]; + + formatItem + = { body, title }: + [ "\\item{${if title != null then "\\textbf{${title}}\\newline" else ""}%" indentation.more ] + ++ body + ++ [ indentation.less "}" ]; + + formatItemList + = { config, body }: + [ + "\\relax%" + "\\begin{cvitems}[${config}]%" indentation.more + "${body}%" + indentation.less "\\end{cvitems}%" + ]; + + formatNote + = { body, ... }: + [ + '' + \def\@note{} + \ifnotempty{\@ResumeColumns} + {\def\@note{\@multispan{\@ResumeColumns}}} + \@note{{\tiny ${body}\hfill}} + '' + ]; + + formatSubEntry + = { date, description, grade, place, position, title, ... }: + let + date' = "\\subentrydatestyle{${formatDate date language}}"; + description' + = if description != null + then + [ "\\multicolumn{2}{L{17.0cm}}{\\subdescriptionstyle{${description}}}\\\\" ] + else + []; + grade' + = if grade != null then ", ${grade}" + else ""; + position' + = if position != null + then + [ + "\\subentrypositionstyle{${position}${grade}} & ${date'}\\\\" + "${title'}\\\\" + ] + else + [ + "${title'} & ${date'}\\\\" + ]; + title' = "\\subentrytitlestyle{${title}}"; + in + [ + "\\setlength\\tabcolsep{0pt}" + "\\setlength{\\extrarowheight}{0pt}" + "\\begin{tabular*}{\\textwidth}{@{\\extracolsep{\\fill}} L{\\textwidth - 4.5cm} R{4.5cm}}" indentation.more + "\\setlength\\leftskip{0.2cm}" + ] + ++ position' + ++ description' + ++ [ indentation.less "\\end{tabular*}" ]; + + formatSubSection' + = { body, environment ? null, title, ... }: + [ + "\\vspace{-3mm}%" + "\\phantomsection%" + "\\addsubsectiontocentry{}{}%" + "{\\fontsize{12pt}{1em}\\sourcesanspro\\scshape\\textcolor{text}{${title}}{${body}}}%" + ]; +} \ No newline at end of file diff --git a/NixTeX/source/render/application/tex/resume/styles/awesome/skills.nix b/NixTeX/source/render/application/tex/resume/styles/awesome/skills.nix new file mode 100644 index 0000000..7fec108 --- /dev/null +++ b/NixTeX/source/render/application/tex/resume/styles/awesome/skills.nix @@ -0,0 +1,43 @@ +{ core, helpers, styles, toTex, urls, ... }: +{ ... }: + let + inherit(core) indentation list string; + inherit(helpers) formatSection; + + toTex' = body: string.concatWith " " (toTex body); + + formatSkill + = { description, extra ? null, show ? true, title, url ? null, ... }: + let + description' = styles.skillSet (toTex' description); + extra' + = if extra != null then toTex' extra + else if url != null then urls.formatHttpsTeXboxed url url + else null; + extra'' = if extra' != null then "& ${styles.description extra'} " else ""; + title' = styles.skillType (toTex' title); + in + list.ifOrEmpty show "${title'} & ${description'} ${extra''}\\\\%"; + in + list.concatMap + ( + { body, show ? true, title }: + list.ifOrEmpty' show + ( + formatSection title + ( + [ + "\\vspace{-1em}%" + "\\begin{center}%" indentation.more + "\\setlength{\\tabcolsep}{1ex}%" + "\\setlength{\\extrarowheight}{0pt}%" + "\\begin{tabularx}{\\textwidth}{rXl}%" indentation.more + ] + ++ (list.concatMap formatSkill body) + ++ [ + indentation.less "\\end{tabularx}%" + indentation.less "\\end{center}%" + ] + ) + ) + ) diff --git a/NixTeX/source/render/application/tex/resume/styles/awesome/social.nix b/NixTeX/source/render/application/tex/resume/styles/awesome/social.nix new file mode 100644 index 0000000..eea86b2 --- /dev/null +++ b/NixTeX/source/render/application/tex/resume/styles/awesome/social.nix @@ -0,0 +1,171 @@ +{ core, phonenumbers, symbols, styles, urls, ... }: +{ ... }: + let + inherit(core) indentation list; + icons + = { + inherit(symbols.forkAwesome) + email-bulk fax + git github gitlab gitea globe gnupg graduation-cap + linkedin matrix-org medium mobile orcid phone reddit skype stackoverflow twitter wikipedia xing; + }; + + acvHeaderSocialSep + = "\\unskip\\enspace\\cleaders\\copy\\acvHeaderSocialSepBox\\hskip\\wd\\acvHeaderSocialSepBox\\enspace\\ignorespaces"; + + formatEmail + = address: + urls.formatEmailTeXboxed address "${icons.email-bulk}\\,${address}"; + + formatGit + = { name, domain, isGitea ? false, ... }: + let + icon + = { + "github" = icons.github; + "github.com" = icons.github; + "gitlab" = icons.gitlab; + "gitlab.com" = icons.gitlab; + }.${domain} or null; + icon' + = if isGitea + then + icons.gitea + else + icons.git; + in + if icon != null + then + urls.formatHttpsTeXboxed "${domain}/${name}" "${icon}\\,${name}" + else + urls.formatHttpsTeXboxed "${domain}/${name}" "${icon'}\\,\\texttt{${domain}/${name}}"; + + formatGoogleScholar + = { id, name }: + urls.formatHttpsTeXboxed "scholar.google.com/citations?user=${id}" "${icons.graduation-cap}\\,${id}"; + + formatHomePage + = homepage: + urls.formatHttpsTeXboxed homepage "${icons.globe}\\,\\texttt{${homepage}}"; + + formatLinkedIn + = { id, name }: + urls.formatHttpsTeXboxed "www.linkedin.com/in/${id}" "${icons.linkedin}\\,${id}"; + + formatMatrix + = { name, domain }: + urls.formatHttpsTeXboxed "${domain}/${name}" "${icons.matrix-org}\\,@${name}:${domain}"; + + formatMedium + = { id, name }: + urls.formatHttpsTeXboxed "medium.com/@${id}" "${icons.medium}\\,${name}"; + + formatOrcid + = { id, name }: + urls.formatHttpsTeXboxed "orcid.org/${id}" "${icons.orcid}\\,${id}"; + + formatPGP + = { fingerprint, url }: + urls.formatHttpsTeXboxed url "${icons.gnupg}\\,\\texttt{${url} (\\texttt{${fingerprint}})}"; + + formatPhoneNumber + = icon: + number: + "${icon}\\,${phonenumbers.formatTeX number}"; + + formatReddit + = name: + urls.formatHttpsTeXboxed "www.reddit.com/user/${name}" "${icons.reddit}\\,u/${name}"; + + formatSkype = name: "${icons.skype}\\,${name}"; + + formatStackOverflow + = { id, name }: + urls.formatHttpsTeXboxed "stackoverflow.com/users/${id}" "${icons.stackoverflow}\\,${name}"; + + formatTwitter + = name: + urls.formatHttpsTeXboxed "www.twitter.com/${name}" "${icons.twitter}\\,${name}"; + + + formatWikipedia + = { language ? "en", name }: + urls.formatHttpsTeXboxed "${language}.wikipedia.org/wiki/User:${name}" "${icons.wikipedia}\\,${name}"; + + formatXing + = { id, name }: + urls.formatHttpsTeXboxed "www.xing.com/profile/${id}" "${icons.xing}\\,${name}"; + + mapGit = list.map formatGit; + + mapPhone + = { cell ? null, fax ? null, home ? null }: + [] + ++ (list.ifOrEmpty (cell != null) (formatPhoneNumber icons.mobile cell)) + ++ (list.ifOrEmpty (home != null) (formatPhoneNumber icons.phone home)) + ++ (list.ifOrEmpty (fax != null) (formatPhoneNumber icons.fax fax)); + in + { + email ? null, + git ? null, + googleScholar ? null, + homepage ? null, + linkedIn ? null, + matrix ? null, + medium ? null, + orcid ? null, + pgp ? null, + phone ? null, + reddit ? null, + show ? true, + skype ? null, + stackOverflow ? null, + twitter ? null, + wikipedia ? null, + xing ? null, + ... + }: + let + items + = (list.ifOrEmpty (matrix != null) (formatMatrix matrix)) + ++ (list.ifOrEmpty (skype != null) (formatSkype skype)) + ++ (list.ifOrEmpty' (git != null) (mapGit git)) + ++ (list.ifOrEmpty (stackOverflow != null) (formatStackOverflow stackOverflow)) + ++ (list.ifOrEmpty (linkedIn != null) (formatLinkedIn linkedIn)) + ++ (list.ifOrEmpty (xing != null) (formatXing xing)) + ++ (list.ifOrEmpty (twitter != null) (formatTwitter twitter)) + ++ (list.ifOrEmpty (reddit != null) (formatReddit reddit)) + ++ (list.ifOrEmpty (googleScholar != null) (formatGoogleScholar googleScholar)) + ++ (list.ifOrEmpty (orcid != null) (formatOrcid orcid)) + ++ (list.ifOrEmpty (medium != null) (formatMedium medium)) + ++ (list.ifOrEmpty (wikipedia != null) (formatWikipedia wikipedia)) + ++ (list.ifOrEmpty (homepage != null) (formatHomePage homepage)) + ++ (list.ifOrEmpty' (phone != null) (mapPhone phone)) + ++ (list.ifOrEmpty (email != null) (formatEmail email)) + ++ (list.ifOrEmpty (pgp != null) (formatPGP pgp)); + in + list.ifOrEmpty' show + ( + [ + "\\begin{center}%" indentation.more + styles.headerSocialOpen indentation.more + ] + ++ ( + list.fold + ( + result: + item: + if result != [] + then + result ++ [ "${acvHeaderSocialSep}{${item}}%" ] + else + result ++ [ "{${item}}%" ] + ) + [] + items + ) + ++ [ + indentation.less styles.headerSocialClose + indentation.less "\\end{center}%" + ] + ) diff --git a/NixTeX/source/render/application/tex/resume/styles/awesome/styles.nix b/NixTeX/source/render/application/tex/resume/styles/awesome/styles.nix new file mode 100644 index 0000000..1a590cf --- /dev/null +++ b/NixTeX/source/render/application/tex/resume/styles/awesome/styles.nix @@ -0,0 +1,67 @@ +{ ... }: + let + colours + = { + grayText = "gray"; + main = "awesome-red"; + mainLight = "awesome-orange"; + text = "darkgray"; + lightText = "lightgray"; + darkText = "black"; + }; + fonts + = { + header = "\\setmainfont{Roboto}"; + headerLight = "\\setmainfont{Roboto}"; + footer = "\\setmainfont{Roboto}"; + body = "\\setmainfont{Roboto}"; + bodyLight = "\\setmainfont{Roboto}"; + }; + in + { + committeeDate = text: ''{\fontsize{8pt}{1em}${fonts.body}\color{${colours.grayText}} ${text}}''; + committeeInstitute = text: ''{\fontsize{9pt}{1em}${fonts.bodyLight}\slshape\color{${colours.main}} ${text}}''; + committeePosition = text: ''{\fontsize{9pt}{1em}${fonts.body}\color{${colours.grayText}} ${text}}''; + committeeTitle = text: ''{\fontsize{9pt}{1em}${fonts.body}\bfseries\color{${colours.darkText}} ${text}}''; + description = text: ''{\fontsize{9pt}{1em}${fonts.bodyLight}\upshape\color{${colours.text}} ${text}}''; + entryDate = text: ''{\fontsize{10pt}{1em}${fonts.bodyLight}\slshape\color{${colours.mainLight}} ${text}}''; + entryLocation = text: ''{\fontsize{9pt}{1em}${fonts.bodyLight}\slshape\color{${colours.main}} ${text}}''; + entryPosition = text: ''{\fontsize{8pt}{1em}${fonts.body}\scshape\color{${colours.grayText}} ${text}}''; + entryTitle = text: ''{\fontsize{10pt}{1em}${fonts.body}\bfseries\color{${colours.darkText}} ${text}}''; + footer = text: ''{\fontsize{8pt}{1em}${fonts.footer}\scshape\color{${colours.lightText}} ${text}}''; + headerAddress = text: ''{\fontsize{8pt}{1em}${fonts.header}\itshape\color{${colours.lightText}} ${text}}''; + headerFirstName = text: ''{\fontsize{32pt}{1em}${fonts.headerLight}\color{${colours.grayText}} ${text}}''; + headerLastName = text: ''{\fontsize{32pt}{1em}${fonts.header}\bfseries\color{${colours.text}} ${text}}''; + headerPosition = text: ''{\fontsize{7.6pt}{1em}${fonts.body}\scshape\color{${colours.main}} ${text}}''; + headerQuote = text: ''{\fontsize{9pt}{1em}${fonts.body}\itshape\color{${colours.darkText}} ${text}}''; + headerSocialClose = "}"; + headerSocialOpen = ''{\fontsize{6.8pt}{1em}${fonts.header}\color{${colours.text}}''; + honorDate = text: ''{\fontsize{9pt}{1em}${fonts.body}\color{${colours.grayText}} ${text}}''; + honorLocation = text: ''{\fontsize{9pt}{1em}${fonts.bodyLight}\slshape\color{${colours.main}} ${text}}''; + honorPosition = text: ''{\fontsize{9pt}{1em}${fonts.body}\bfseries\color{${colours.darkText}} ${text}}''; + honorTitle = text: ''{\fontsize{9pt}{1em}${fonts.body}\color{${colours.grayText}} ${text}}''; + letterDate = text: ''{\fontsize{9pt}{1em}${fonts.bodyLight}\slshape\color{${colours.grayText}} ${text}}''; + letterEnclosure = text: ''{\fontsize{10pt}{1em}${fonts.bodyLight}\slshape\color{${colours.lightText}} ${text}}''; + letterName = text: ''{\fontsize{10pt}{1em}${fonts.body}\bfseries\color{${colours.darkText}} ${text}}''; + letterSection = text: ''{\fontsize{14pt}{1em}${fonts.body}\bfseries\color{${colours.text}}\sectioncolor ${text}}''; + letterText = ''{\fontsize{10pt}{1.4em}${fonts.bodyLight}\upshape\color{${colours.grayText}}}''; + letterTitle = text: ''{\fontsize{10pt}{1em}${fonts.bodyLight}\bfseries\color{${colours.darkText}} \underline{${text}}}''; + paragraphClose = "}"; + paragraphOpen = ''{\fontsize{9pt}{1em}${fonts.bodyLight}\upshape\color{${colours.text}}''; + recipientAddress = text: ''{\fontsize{9pt}{1em}${fonts.body}\scshape\color{${colours.grayText}} ${text}}''; + recipientTitle = text: ''{\fontsize{11pt}{1em}${fonts.body}\bfseries\color{${colours.darkText}} ${text}}''; + sectionBodyClose = ''}\vfill%''; + sectionBodyOpen = ''\makeatletter\color{${colours.grayText}}\leavevmode\leaders\hrule\@height0.9pt\hfill\kern\z@\makeatother{%''; + sectionTitle = text: ''{\fontsize{16pt}{1em}${fonts.body}\bfseries\color{${colours.text}}\sectioncolor ${text}}''; + sectionTitleOpen = ''{\fontsize{16pt}{1em}${fonts.body}\bfseries\color{${colours.text}}\sectioncolor%''; + sectionTitleClose = ''}%''; + sectionColor = text: ''{\color{${colours.main}} ${text}}''; + skillSet = text: ''{\fontsize{9pt}{1em}${fonts.bodyLight}\color{${colours.text}} ${text}}''; + skillType = text: ''{\fontsize{10pt}{1em}${fonts.body}\bfseries\color{${colours.darkText}} ${text}}''; + subDescription = text: ''{\fontsize{8pt}{1em}${fonts.bodyLight}\upshape\color{${colours.text}} ${text}}''; + subEntryDate = text: ''{\fontsize{7pt}{1em}${fonts.bodyLight}\slshape\color{${colours.grayText}} ${text}}''; + subEntryLocation = text: ''{\fontsize{7pt}{1em}${fonts.bodyLight}\slshape\color{${colours.main}} ${text}}''; + subEntryPosition = text: ''{\fontsize{7pt}{1em}${fonts.body}\scshape\color{${colours.grayText}} ${text}}''; + subEntryTitle = text: ''{\fontsize{8pt}{1em}${fonts.body}\mdseries\color{${colours.grayText}} ${text}}''; + subSection = text: ''{\fontsize{12pt}{1em}${fonts.body}\scshape\textcolor{${colours.text}}{${text}}}''; + } diff --git a/NixTeX/source/render/application/tex/resume/styles/awesome/summary.nix b/NixTeX/source/render/application/tex/resume/styles/awesome/summary.nix new file mode 100644 index 0000000..3515d04 --- /dev/null +++ b/NixTeX/source/render/application/tex/resume/styles/awesome/summary.nix @@ -0,0 +1,8 @@ +{ core, helpers, ... }: +{ ... }: + let + inherit(core) list; + inherit(helpers) formatParagraph; + in + { body, show ? true, title }: + list.ifOrEmpty' show (formatParagraph title body) diff --git a/NixTeX/source/render/application/tex/resume/styles/classic/default.tex b/NixTeX/source/render/application/tex/resume/styles/classic/default.tex new file mode 100644 index 0000000..73bdd17 --- /dev/null +++ b/NixTeX/source/render/application/tex/resume/styles/classic/default.tex @@ -0,0 +1,201 @@ +\renewcommand{\@ResumeAfter } +{ +} + +\renewcommand{\@ResumeBefore } +{ + \def\@ResumeIconSeperator {\space} + \ifthenelse{\equal {\@ResumePictureEdge} {edge}} + {\def\@ResumePictureBorder {darkgray}} + {\def\@ResumePictureBorder {none}} + \ifthenelse{\equal {\@ResumePictureShape} {circle}} + {\def\@ResumePictureDimension {1.3cm}} + {\def\@ResumePictureDimension {1.8cm}} + \markboth + {} + {} +} + +\renewcommand{\@ResumeContent }[1] +{ + \begin{tabularx}{\linewidth}{XR{5cm}L{3.1cm}} + { + {\Huge \@ResumeFirstName~\@ResumeLastName}\newline + {\large\textit{Lebenslauf}} + } & + { + \footnotesize + \ifnotempty{\@ResumeMobile} {\@@ResumeMobile\newline} + \ifnotempty{\@ResumeEMail} {\@@ResumeEMail\newline} + \ifnotempty{\@ResumeKey} {\@@ResumeKey\newline} + \ifnotempty{\@ResumeHomepage} {\@@ResumeHomepage\newline} + \ifnotempty{\@ResumeGit} {\@@ResumeGit\newline} + \ifnotempty{\@ResumeGithub} {\@@ResumeGithub\newline} + \ifnotempty{\@ResumeGitlab} {\@@ResumeGitlab\newline} + \ifnotempty{\@ResumeStackOverflowID} {\@@ResumeStackOverflow\newline} + \ifnotempty{\@ResumeLinkedin} {\@@ResumeLinkedin\newline} + \ifnotempty{\@ResumeTwitter} {\@@ResumeTwitter\newline} + \ifnotempty{\@ResumeSkype} {\@@ResumeSkype\newline} + \ifnotempty{\@ResumeReddit} {\@@ResumeReddit\newline} + \ifnotempty{\@ResumeXing} {\@@ResumeXing\newline} + \ifnotempty{\@ResumeMedium} {\@@ResumeMedium\newline} + \ifnotempty{\@ResumeWikipediaName} {\@@ResumeWikipedia\newline} + \ifnotempty{\@ResumeGoogleScholarID} {\@@ResumeGoogleSchoolar\newline} + \ifnotempty{\@ResumeExtra} {\@ResumeExtra\newline} + } & + { + \ifnotempty{\@ResumePicture}{\@@ResumePicture} + } \\ + \end{tabularx} + \ifnotempty{\@ResumeQuote} + { + \begin{center} + \color{main}\@ResumeQuote + \end{center} + } + \begin{longtabu}[l]{R{3.5cm}p{\linewidth-9cm}p{4cm}} + #1\\ + \end{longtabu} +} + +\renewcommand{\@ResumeEntry }[6] +{ + % 1 – when + % 2 – what + % 3 – institution + % 4 – where + % 5 – optional: grades + % 6 – optional: comment/description + \\* + #1 & + \multicolumn{2}{p{\linewidth-4cm}} + { + \noWordBreaks + \textbf{#2}, \textit{#3}, #4\ifnotempty{#5}{, \textit{#5}} + \ifnotempty{#6}{\newline#6} + } +} + +\renewcommand{\@ResumeHonor }[4] +{ + % 1 – date + % 2 – position + % 3 – title + % 4 – location + \\* + #1 & + \noWordBreaks + { + \textbf{#2}, \textit{#3} + } & + #4 +} + +\renewcommand{\@ResumeItem }[2] +{ + % 1 – title (optional) + % 2 – body + \\* + #1 & + \multicolumn{2}{p{\linewidth-3.5cm}} + { + \noWordBreaks + #2 + } +} + +\renewcommand{\@ResumeItemisation }[2] +{ + % 1 – optional: config + % 2 – body + \itemisation[#1] + { + #2 + } +} + +\renewcommand{\@ResumeLanguage }[4] +{ + % 1 – optional: numeric level 0–1 + % 2 – name + % 3 – level + % 4 – optional: comment/description + \\* + #2 & + \rateHalfStars{#1}{6} #3 & + #4 +} + +\renewcommand{\@ResumeNote }[1] +{ + % 1 – note + \\*& + \multicolumn{2}{p{\linewidth-4cm}} + { + \noWordBreaks + #1 + } +} + +\renewcommand{\@ResumeSection }[3] +{ + % 1 – optional: environment + % 2 – title + % 3 – body + \def\@PreviousCategory{} + \def\@PreviousProgram{} + \def\@ResumeSectionName{#2}% + {\color{main}\rule[-0.5em]{\linewidth}{0.4em}} & + {\large\color{main}#2} + \ifnum\pdf@strcmp{#1}{cvparagraph}=\z@ + \\*\expandafter\multicolumn{3}{p{\linewidth}}{#3} + \else + \expandafter#3 + \fi\\ +} + +\renewcommand{\@ResumeSkill }[3] +{ + % 1 – optional: comment, link to repository, … + % 2 – category + % 3 – software/language/skill + \\* + #2 & + #3 & + #1 +} + +\renewcommand{\@ResumeSubEntry }[6] +{ + % 1 – date + % 2 – optional: position + % 3 – title + % 4 – location + % 5 – optional: grades + % 6 – optional: comment/description + \\* + #1 & + { + \noWordBreaks + \ifnotempty{#2}{#2, }#3\ifnotempty{#5}{, #5}\newline + #6 + } & + #4 +} + +\renewcommand{\@ResumeSubSection }[3] +{ + % 1 – ignored: environment + % 2 – title + % 3 – body + \def\@PreviousCategory{} + \def\@PreviousProgram{} + \def\@ResumeSectionName{#2}% + \\& + {\large\color{main}#2} + \ifnum\pdf@strcmp{#1}{cvparagraph}=\z@ + \\*\expandafter\multicolumn{3}{p{\linewidth}}{#3} + \else + \expandafter#3 + \fi\\ +} diff --git a/NixTeX/source/render/application/tex/resume/styles/default.nix b/NixTeX/source/render/application/tex/resume/styles/default.nix new file mode 100644 index 0000000..2e4c713 --- /dev/null +++ b/NixTeX/source/render/application/tex/resume/styles/default.nix @@ -0,0 +1,13 @@ +{ core, ... } @ libs: + let + inherit(core) path; + + libs' + = libs + // { + helpers = path.import ./helpers.nix libs'; + }; + in + { + awesome = path.import ./awesome libs'; + } diff --git a/NixTeX/source/render/application/tex/resume/styles/green/default.tex b/NixTeX/source/render/application/tex/resume/styles/green/default.tex new file mode 100644 index 0000000..0f93c36 --- /dev/null +++ b/NixTeX/source/render/application/tex/resume/styles/green/default.tex @@ -0,0 +1,2 @@ +\colorlet {main} {awesome-nephritis} +\colorlet {main-light} {green} diff --git a/NixTeX/source/render/application/tex/resume/styles/helpers.nix b/NixTeX/source/render/application/tex/resume/styles/helpers.nix new file mode 100644 index 0000000..0b3303c --- /dev/null +++ b/NixTeX/source/render/application/tex/resume/styles/helpers.nix @@ -0,0 +1,33 @@ +{ core, ... }: + let + inherit(core) debug list string time type; + + formatDate + = date: + language: + type.matchPrimitiveOrPanic date + { + int = string date; + string = date; + set + = let + from = time.tryParseISO8601 date.from; + till = time.tryParseISO8601 date.till; + in + (debug.info "formatDate" { text = "from"; data = from; }) + (debug.info "formatDate" { text = "till"; data = till; }) + ( + if from != null + && till != null + && from.month != null + && till.month != null + then + "${time.formatYearShortMonth from language}–${time.formatYearShortMonth till language}" + else + "${string date.from}–${string date.till}" + ); + }; + in + { + inherit formatDate; + } diff --git a/NixTeX/source/render/application/tex/resume/styles/simple/default.tex b/NixTeX/source/render/application/tex/resume/styles/simple/default.tex new file mode 100644 index 0000000..8c4f13d --- /dev/null +++ b/NixTeX/source/render/application/tex/resume/styles/simple/default.tex @@ -0,0 +1,153 @@ +\renewcommand{\@ResumeAfter } +{ + \restoregeometry +} + +\renewcommand{\@ResumeBefore } +{ + \ifthenelse{\equal {\@ResumePictureEdge} {edge}} + {\def\@ResumePictureBorder {gray}} + {\def\@ResumePictureBorder {none}} + \ifthenelse{\equal {\@ResumePictureShape} {circle}} + {\def\@ResumePictureDimension {1.5cm}} + {\def\@ResumePictureDimension {2.0cm}} + \newgeometry + { + footskip = 30pt, + includefoot, + margin = 2.0cm, + } + \small +} + +% TODO: Internationalising +\renewcommand{\@ResumeContent }[1] +{ + \begin{longtabu}[l]{r|X} + \toprule + \endfirsthead + \toprule + \endhead + \bottomrule + \endfoot + \bottomrule + \endlastfoot + \multicolumn{2}{l}{{\huge\textbf{\@ResumeFirstName\ \@ResumeLastName}}}\raisedrule[0.2em]{2pt} + \ungroup\ifnotempty{\@ResumePicture}{\\*&\raggedleft\@@ResumePicture\\*[-4.2cm]} + \ungroup\ifnotempty{\@ResumeBirthDay} {\@ResumeEntry {} {} {\@@ResumeBirth} {}{}{}} + \ungroup\ifnotempty{\@ResumeNationality} {\@ResumeEntry {} {} {\@@ResumeNationality} {}{}{}} + \ungroup\ifnotempty{\@ResumeTelephone} {\@ResumeEntry {} {} {\@@ResumeTelephone} {}{}{}} + \ungroup\ifnotempty{\@ResumeFax} {\@ResumeEntry {} {} {\@@ResumeFax} {}{}{}} + \ungroup\ifnotempty{\@ResumeMobile} {\@ResumeEntry {} {} {\@@ResumeMobile} {}{}{}} + \ungroup\ifnotempty{\@ResumeEMail} {\@ResumeEntry {} {} {\@@ResumeEMail} {}{}{}} + \ungroup\ifnotempty{\@ResumeKey} {\@ResumeEntry {} {} {\@@ResumeKey} {}{}{}} + \ungroup\ifnotempty{\@ResumeHomepage} {\@ResumeEntry {} {} {\@@ResumeHomepage} {}{}{}} + \ungroup\ifnotempty{\@ResumeGit} {\@ResumeEntry {} {} {\@@ResumeGit} {}{}{}} + \ungroup\ifnotempty{\@ResumeGithub} {\@ResumeEntry {} {} {\@@ResumeGithub} {}{}{}} + \ungroup\ifnotempty{\@ResumeGitlab} {\@ResumeEntry {} {} {\@@ResumeGitlab} {}{}{}} + \ungroup\ifnotempty{\@ResumeStackOverflowID} {\@ResumeEntry {} {} {\@@ResumeStackOverflow} {}{}{}} + \ungroup\ifnotempty{\@ResumeLinkedin} {\@ResumeEntry {} {} {\@@ResumeLinkedin} {}{}{}} + \ungroup\ifnotempty{\@ResumeTwitter} {\@ResumeEntry {} {} {\@@ResumeTwitter} {}{}{}} + \ungroup\ifnotempty{\@ResumeSkype} {\@ResumeEntry {} {} {\@@ResumeSkype} {}{}{}} + \ungroup\ifnotempty{\@ResumeReddit} {\@ResumeEntry {} {} {\@@ResumeReddit} {}{}{}} + \ungroup\ifnotempty{\@ResumeXing} {\@ResumeEntry {} {} {\@@ResumeXing} {}{}{}} + \ungroup\ifnotempty{\@ResumeMedium} {\@ResumeEntry {} {} {\@@ResumeMedium} {}{}{}} + \ungroup\ifnotempty{\@ResumeWikipediaName} {\@ResumeEntry {} {} {\@@ResumeWikipedia} {}{}{}} + \ungroup\ifnotempty{\@ResumeGoogleScholarID} {\@ResumeEntry {} {} {\@@ResumeGoogleSchoolar} {}{}{}} + \ungroup\ifnotempty{\@ResumeExtra} {\@ResumeEntry {} {} {\@ResumeExtra} {}{}{}} + \ungroup\ifnotempty{\@ResumeAddressBusinessRoad\@ResumeAddressPrivateCity} {\@ResumeEntry {} {} {\@@ResumeAddressPrivate} {}{}{}} + \ungroup\ifnotempty{\@ResumeAddressBusinessRoad\@ResumeAddressBusinessCity} {\@ResumeEntry {} {} {\@@ResumeAddressBusiness} {}{}{}} + \ungroup\ifnotempty{\@ResumeAddressBusinessRoad\@ResumeAddressBusinessCity} {\@ResumeEntry {} {} {\@@ResumeAddressBusiness} {}{}{}} + #1\\ + \end{longtabu} +} + +\renewcommand{\@ResumeEntry }[6] +{ + % 1 – date + % 2 – optional: position + % 3 – institution + % 4 – optional: location + % 5 – optional: grades + % 6 – optional: comment/description + \\*{#1} & {\ifnotempty{#2}{\textbf{#2:\newline}}#3\ifnotempty{#4}{ (#4)}\ifnotempty{#5}{\newline #5}\ifnotempty{#6}{\newline #6}} +} + +\renewcommand{\@ResumeHonor }[4] +{ + % 1 – date + % 2 – optional: position + % 3 – title + % 4 – location + \\*{#1} & {\ifthenelse{\equal{}{#2}}{\textbf{#3}}{\textbf{#2}, #3}, #4} +} + +\renewcommand{\@ResumeItem }[2] +{ + % 1 – optional: title + % 2 – body + \\*{} & {\bullet\parbox[t][][]{\linewidth}{\ifnotempty{#1}{\textbf{#1}\newline}#2}} +} + +\renewcommand{\@ResumeItemisation }[2] +{ + % 1 – optional: config + % 2 – body + \itemisation[#1]{#2} +} + +\renewcommand{\@ResumeLanguage }[4] +{ + % 1 – optional: numeric level 0–1 + % 2 – name + % 3 – short level ([ABC][12]+?|–)? + % 4 – optional: comment/description + \\*{#2} & {\textbf{#3}\newline\rateHalfStars{#1-0}{5}\ifnotempty{#4}{~#4}} +} + +\renewcommand{\@ResumeNote }[1] +{ + % 1 – note + \\*\multicolumn{\LT@cols}{l}{{\footnotesize #1}} +} + +\renewcommand{\@ResumeSection }[3] +{ + % 1 – ignored: environment + % 2 – title + % 3 – body + \\\multicolumn{2}{l}{{\large\textbf{#2}}\raisedrule[0.2em]{1pt}} + \ifnum\pdf@strcmp{#1}{cvparagraph}=\z@ + \\\multicolumn{2}{p{\linewidth}}{#3\par} + \else + #3 + \fi +} + +\renewcommand{\@ResumeSkill }[3] +{ + % 1 – optional: comment, link to repository, … + % 2 – category + % 3 – software/language/skill + \\*{#2} & {#3\ifnotempty{#1}{(#1)}} +} + +\renewcommand{\@ResumeSubEntry }[6] +{ + % 1 – date + % 2 – position + % 3 – institution + % 4 – optional: location + % 5 – optional: grades + % 6 – optional: comment/description + \\*{#1} & {\quad\textbf{#2:}\newline #3\ifnotempty{#4}{ (#4)}\ifnotempty{#5}{\newline #5}\ifnotempty{#6}{\newline #6}} +} + +\renewcommand{\@ResumeSubSection }[3] +{ + % 1 – ignored: environment + % 2 – title + % 3 – body + \\*\multicolumn{2}{l}{{\quad\textbf{#2}}}\raisedrule[0.1em]{0.25pt} + #3 +} diff --git a/NixTeX/source/render/default.nix b/NixTeX/source/render/default.nix new file mode 100644 index 0000000..08c63d6 --- /dev/null +++ b/NixTeX/source/render/default.nix @@ -0,0 +1,11 @@ +{ core, ... } @ libs: + let + inherit(core) library; + in + { + application = library.import ./application libs; + disputation = library.import ./disputation libs; + #letter = library.import ./letter libs; + #journal = library.import ./journal libs; + #thesis = library.import ./thesis libs; + } diff --git a/NixTeX/source/render/disputation/default.nix b/NixTeX/source/render/disputation/default.nix new file mode 100644 index 0000000..82878f4 --- /dev/null +++ b/NixTeX/source/render/disputation/default.nix @@ -0,0 +1,25 @@ +{ core, ... } @ libs: + let + inherit(core) library; + getFormat + = outputFormat: + if outputFormat != null + then + outputFormat + else + "tex"; + renderTex = library.import ./tex libs; + in + { + evaluationOrder + = [ + "slides" + "extra" + ]; + render + = outputFormat: + { + "tex" = renderTex; + "markdown" = foo: []; + }.${getFormat outputFormat}; + } diff --git a/NixTeX/source/render/disputation/tex/default.nix b/NixTeX/source/render/disputation/tex/default.nix new file mode 100644 index 0000000..7119479 --- /dev/null +++ b/NixTeX/source/render/disputation/tex/default.nix @@ -0,0 +1,154 @@ +{ bibliography, chemistry, core, document, glossaries,... } @ libs: + let + inherit(core) debug indentation library list path string; + + libs' + = libs + // { + formatAuthor + = author: + "${author.forename} ${author.surname}"; + }; + + renderExtra = library.import ./extra.nix libs'; + renderPrelude = library.import ./prelude.nix libs'; + renderSlides = library.import ./slides.nix libs'; + renderTitle = library.import ./title.nix libs'; + in + { authors, configuration, content, date, dependencies, name, place, resources, disputation, ... } @ document: + let + style = (library.import ./styles libs').${disputation.style}; + document' = document // { inherit style; }; + toTex = libs.document.toTex { inherit configuration resources; }; + + packages + = [ + "logging" + "dependencies" + "chemistry/chem" + "chemistry/elements" + "bibliography/citation" + "floats/floats" + "geometry" + "glossaries/glossaries" + "links" + "text/text" + "utils" + ]; + + acronyms = glossaries.acronyms.toLua { inherit configuration resources; }; + references = bibliography.toBibTeX { inherit configuration resources; } resources.references; + substances = chemistry.substances.toLua { inherit configuration resources; } resources.substances; + + prelude + = { + acronyms = acronyms.dst; + assets = "assets/"; + packages = list.map (name: "\\input{\\source/source/${name}.tex}") packages; + references = references.dst; + source + = { + lua = "source/lua/"; + tex = "source/"; + }; + substances = substances.dst; + }; + + content' + = indentation { initial = ""; tab = " "; } + ( + [] + ++ ( renderPrelude document' prelude ) + ++ [ "\\begin{document}" indentation.more ] + ++ ( renderTitle document' ) + ++ ( renderSlides document' ( toTex content.slides or null ) ) + ++ ( renderExtra document' ( toTex content.extra or null ) ) + ++ [ "\\directlua{commonFinal()}" ] # ToDo: Remove! + ++ [ indentation.less "\\end{document}" ] + ); + + optimiser + = if configuration.optimise or false + then + '' + # Optimise and linearise + # This removes tooltips, sorry + mv "${name}.pdf" "${name}-raw.pdf" + gs \ + -dBATCH \ + -dColorImageResolution=288 \ + -dCompatibilityLevel=1.7 \ + -dDEBUG \ + -dDetectDuplicateImages \ + -dDownsampleColorImages=true \ + -dDownsampleGrayImages=true \ + -dDownsampleMonoImages=true \ + -dFastWebView \ + -dGrayImageResolution=288 \ + -dMonoImageResolution=288 \ + -dNOPAUSE \ + -dPDFSETTINGS=/ebook \ + -dPrinted=false \ + -sDEVICE=pdfwrite \ + -sOutputFile="${name}.pdf" \ + "${name}-raw.pdf" \ + > "${name}.gslog" 2>&1 + '' + else + ""; + + compile + = path.toFile "compile-${name}.sh" + '' + #!/usr/bin/env bash + newHash="false" + oldHash="true" + out="$1" + + counter="" + while [[ "$newHash" != "$oldHash" && "$counter" != "${configuration.foo or "+++++"}" ]] + do + if lualatex \ + --interaction=nonstopmode \ + --halt-on-error \ + --output-format=pdf \ + "\def\source{$out}\def\build{.}\input{$out/${name}.tex}" #2> /dev/null > /dev/null + then + oldHash="$newHash" + newHash="$(md5sum "${name}.pdf")" + echo "$newHash" + mv "${name}.log" "$out/${name}.log" + mv "${name}.llg" "$out/${name}.llg" + biber "${name}" + counter="+$counter" + else + exit 1 + fi + done + + ${optimiser} + # move the generated and processed document to the final-directory + mv "${name}.pdf" "$out/${name}.pdf" + exit 0 + ''; + texFile = path.toFile "${name}.tex" content'; + in + document' + // { + content = content'; + dependencies + = dependencies + ++ [ + acronyms + references + substances + { + src = texFile; + dst = "${name}.tex"; + } + { + src = { store = compile; executable = true; }; + dst = "compile-${name}.sh"; + } + ]; + } diff --git a/NixTeX/source/render/disputation/tex/extra.nix b/NixTeX/source/render/disputation/tex/extra.nix new file mode 100644 index 0000000..0409f47 --- /dev/null +++ b/NixTeX/source/render/disputation/tex/extra.nix @@ -0,0 +1,20 @@ +{ core, ... }: + let + inherit(core) debug; + in + { ... }: + extra: + [ + "\\newcounter{finalframe}%" + "\\setcounter{finalframe}{\\value{framenumber}}%" + "\\setcounter{framenumber}{0}%" + "\\ifx\\finalExtraSlide\\undefined\\xdef\\finalExtraSlide{???}\\fi%" + "\\renewcommand{\\printslidenumber}[2]{Extra \\arabic{framenumber}/\\finalExtraSlide}%" + ] + ++ extra + ++ [ + "\\makeatletter%" + "\\immediate\\write\\@auxout{\\string\\xdef\\string\\finalExtraSlide{\\arabic{framenumber}}}%" + "\\makeatother%" + "\\setcounter{framenumber}{\\value{finalframe}}%" + ] diff --git a/NixTeX/source/render/disputation/tex/prelude.nix b/NixTeX/source/render/disputation/tex/prelude.nix new file mode 100644 index 0000000..dc851c1 --- /dev/null +++ b/NixTeX/source/render/disputation/tex/prelude.nix @@ -0,0 +1,123 @@ +{ core, fonts, formatAuthor, ... }: + let + inherit(core) debug indentation list set string time; + + facultyColours = "natwi"; + in + { title, authors, date, disputation, ... }: + { assets, acronyms, packages, references, source, substances, ... } @ args: + ( + [ + '' + \documentclass[ + 8pt, + bookmarks = true, + pdfborder = {0 0 0}, + pdfencoding = auto, + unicode = true, + aspectratio = 169, + sections, + listof = flat, + numbers = noenddot, + table, + ] + {beamer} + '' + '' + \directlua{ + acronymFile = "${acronyms}" + jobname = [[\jobname]] + source = [[\source]].."/" + buildDirectory = [[\build]].."/" + dofile(source.."${source.lua}common.lua") + } + '' + "\\newcommand{\\inputCode }[1]{\\input{\\source/${source.tex}#1}}" + "\\newcommand{\\inputAssets}[1]{\\input{\\source/${assets}#1}}" + "\\def\\biblatexStyle{\\source/${assets}biblatex/chem-angew}" + "\\makeatletter" + ] + ++ packages + ++ [ + "\\makeatother" + "\\usetikzlibrary{shapes.misc}" + ] + ++ fonts + ++ [ + "\\renewcommand{\\familydefault}{\\sfdefault}" + "\\pdfvariable suppressoptionalinfo ${string ( 32 + 64 + 512 )}" # Makes the PDF constant + "\\setstretch{1.433}" # 1/2-spacing + + "\\DeclareFloatingEnvironment[" indentation.more + "fileext = los," + "listname = {Schema\\-verzeichnis}," + "name = Schema," + indentation.less "]{scheme}" + "\\resetcounteronoverlays{scheme}" + + # Slides + "\\renewcommand<>{\\cfigure}[1][]{\\thecfigure{h}{#2}{#1}}" + "\\renewcommand<>{\\hfigure}[1][]{\\thecfigure{H}{#2}{#1}}" + "\\renewcommand<>{\\cgnuplot}[1][]{\\thegnuplot{h}{#2}{#1}}" + "\\renewcommand<>{\\hgnuplot}[1][]{\\thegnuplot{H}{#2}{#1}}" + "\\renewcommand<>{\\cFigure}[1][]{\\Thecfigure{h}{#2}{#1}}" + "\\renewcommand<>{\\hFigure}[1][]{\\Thecfigure{H}{#2}{#1}}" + "\\renewcommand<>{\\subchem}[4][b]{\\thesubchem{#1}{#2}{#3}{#4}{#5}}" + "\\renewcommand<>{\\subfig}[4][b]{\\thesubfig{#1}{#2}{#3}{#4}{#5}}" + "\\renewcommand<>{\\Subfig}[4][b]{\\theSubfig{#1}{#2}{#3}{#4}{#5}}" + "\\renewcommand<>{\\subgnuplot}[6][b]{\\thesubgnuplot{#1}{#2}{#3}{#4}{#5}{#6}{#7}}" + "\\renewcommand<>{\\Subgnuplot}[6][b]{\\theSubgnuplot{#1}{#2}{#3}{#4}{#5}{#6}{#7}}" + "\\renewcommand<>{\\wrapfig}[6][0.3]{\\thewrapfig{#1}{#2}{#3}{#4}{#5}{#6}{#7}}" + "\\renewcommand<>{\\footcite}[1]{\\footnote#2[frame]{\\fullcite{#1}}}" + "\\renewcommand{\\thefootnote}{\\relax\\textsuperscript{[\\arabic{footnote}]}}" + "\\def\\labelitemi{{\\NotoSansMono▶}}" + "\\makeatletter" + '' + \def\setfixbeamer{ + \def\fix@beamer@close{\ifnum\beamer@trivlistdepth>0\beamer@closeitem\fi} + \def\fix@beamer@open{\ifnum\beamer@trivlistdepth>0\gdef\beamer@closeitem{}\fi} + } + \def\clrfixbeamer{ + \def\fix@beamer@close{} + \def\fix@beamer@open{} + } + + \BeforeBeginEnvironment{enumerate}{\fix@beamer@close} + \AfterEndEnvironment{enumerate}{\fix@beamer@open} + \BeforeBeginEnvironment{itemize}{\fix@beamer@close} + \AfterEndEnvironment{itemize}{\fix@beamer@open} + \BeforeBeginEnvironment{description}{\fix@beamer@close} + \AfterEndEnvironment{description}{\fix@beamer@open} + %\newcommand{\bookmarkthis}[1][2]{\bookmark[page=\the\c@page,level=#1]{\GetTitleStringResult}} + \let\footnoterule\relax + \setfixbeamer + '' + '' + \makeatother + \directlua{ + fakultaet = "${facultyColours}" + } + \usepackage{\source/tuc/source/beamerthemetuc2014} + \mode
{\usepackage{\source/tuc/source/beamerarticletuc2014}} + %\makeglossaries + \setbeameroption{} + \setbeamertemplate{note page}[plain] + \setbeamertemplate{caption}[numbered] + \beamertemplatenavigationsymbolsempty + + \title{${title}} + \subtitle{${disputation.title}} + \author{${string.concatWith ", " (list.map formatAuthor authors)}} + \date{${time.formatDate date "deu"}} + \tucurl{} + '' + ] + ++ ( + if substances != null + then + [ "\\directlua{substances.load(source..\"${string.slice 0 ((string.length substances) - 4) substances}\")}%" ] + else + [] + ) + ++ [ "\\addbibresource{\\source/${references}}" ] + ) diff --git a/NixTeX/source/render/disputation/tex/slides.nix b/NixTeX/source/render/disputation/tex/slides.nix new file mode 100644 index 0000000..046871d --- /dev/null +++ b/NixTeX/source/render/disputation/tex/slides.nix @@ -0,0 +1,7 @@ +{ core, ... }: + let + inherit(core) debug indentation; + in + { ... }: + body: + body \ No newline at end of file diff --git a/NixTeX/source/render/disputation/tex/title.nix b/NixTeX/source/render/disputation/tex/title.nix new file mode 100644 index 0000000..b251e23 --- /dev/null +++ b/NixTeX/source/render/disputation/tex/title.nix @@ -0,0 +1,102 @@ +{ core, formatAuthor, ... }: + let + inherit(core) debug indentation list string time; + + setTolerances + = { + pretolerance ? 100, # + tolerance ? 200, # + hfuzz ? "0.1pt", # + vfuzz ? "0.1pt", # + hbadness ? 1000, # + vbadness ? 1000, # + emergencystretch ? "3em", # + }: + [ + "\\pretolerance=${string pretolerance}%" + "\\tolerance=${string tolerance}%" + "\\hfuzz=${string hfuzz}%" + "\\vfuzz=${string vfuzz}%" + "\\hbadness=${string hbadness}%" + "\\vbadness=${string vbadness}%" + "\\emergencystretch=${string emergencystretch}%" + ]; + + setPenalties + = { + binaryOperator ? 700, # for a line break in math mode after a binary operator. + brokenHyphen ? 100, # for a page break, where the last line of the previous page contains a hyphenation. + club ? 150, # for a broken page, with a single line of a paragraph remaining on the bottom of the preceding page. + displayWidow ? 50, # for a break before last line of a paragraph. + doubleHyphen ? 10000, # for two consecutive hyphenated lines. + explicitHyphen ? 50, # for hyphenating a word which already contains a hyphen. + finalHyphen ? 5000, # for a hyphen in the last full line of a paragraph. + floating ? 20000, # for splitting an insertion. + hyphen ? 50, # for line breaking at an automatically inserted hyphen. + incompatibleLines ? 10000, # for two consecutive lines are visually incompatible. + interDisplay ? 100, # for breaking a display on two pages. + interFootnote ? 100, # for breaking a footnote on two pages. + interLine ? 0, # for the penalty added after each line of a paragraph + line ? 10, # for each line within a paragraph. + postDisplay ? 0, # for a break after a display. + preDisplay ? 10000, # for a break before a display. + relationOperator ? 500, # for a line break in math mode after a a relation operator. + widow ? 150, # for a broken page, with a single line of a paragraph remaining on the top of the succeeding page. + }: + [ + "\\adjdemerits=${string incompatibleLines}%" + "\\binoppenalty=${string binaryOperator}%" + "\\brokenpenalty=${string brokenHyphen}%" + "\\clubpenalty=${string club}%" + "\\doublehyphendemerits=${string doubleHyphen}%" + "\\displaywidowpenalty=${string displayWidow}%" + "\\exhyphenpenalty=${string explicitHyphen}%" + "\\finalhyphendemerits=${string finalHyphen}%" + "\\floatingpenalty=${string floating}%" + "\\hyphenpenalty=${string hyphen}%" + "\\interdisplaylinepenalty=${string interDisplay}%" + "\\interfootnotelinepenalty=${string interFootnote}%" + "\\interlinepenalty=${string interLine}%" + "\\linepenalty=${string line}%" + "\\postdisplaypenalty=${string postDisplay}%" + "\\predisplaypenalty=${string preDisplay}%" + "\\relpenalty=${string relationOperator}%" + "\\widowpenalty=${string widow}%" + ]; + + logo = ""; + in + { authors, disputation, title, ... }: + [ + "\\hypersetup{" indentation.more + "pdfauthor={${string.concatWith ", " (list.map formatAuthor authors)}}," + "pdftitle={${title}}," + "pdfsubject={${disputation.title}}," + "pdfkeywords={}," + "pdfproducer={}," + "pdfcreator={}," + indentation.less "}" + ] + ++ ( + setTolerances + { + tolerance = 500; + emergencystretch = "3em"; + hfuzz = "2pt"; + vfuzz = "2pt"; + } + ) + ++ ( + setPenalties + { + brokenHyphen = 100; + club = 350; + hyphen = 10000; + widow = 350; + } + ) + ++ [ + "\\setbeamertemplate{tuc2 headlines}[title]" + "\\frame{\\titlepage ${logo}}" + "\\setbeamertemplate{tuc2 headlines}[section]" + ] diff --git a/NixTeX/source/render/journal/default.nix b/NixTeX/source/render/journal/default.nix new file mode 100644 index 0000000..2245f7a --- /dev/null +++ b/NixTeX/source/render/journal/default.nix @@ -0,0 +1,17 @@ +{ core, ... } @ libs: + let + inherit(core) library; + + getFormat + = outputFormat: + if outputFormat != null + then + outputFormat + else + "tex"; + renderTex = library.import ./tex libs; + in + outputFormat: + { + "tex" = renderTex; + }.${getFormat outputFormat} diff --git a/NixTeX/source/render/journal/tex/appendix.nix b/NixTeX/source/render/journal/tex/appendix.nix new file mode 100644 index 0000000..9f39e91 --- /dev/null +++ b/NixTeX/source/render/journal/tex/appendix.nix @@ -0,0 +1,31 @@ +{ core, chemistry, ... }: +let + inherit(core) indentation; +in + { resources, ... }: + appendix: + ( + [ + "\\addtocontents{toc}{\\protect\\setcounter{tocdepth}{\\sectiontocdepth}}" + "\\appendix{" indentation.more + "\\setcounter{secnumdepth}{5}" + "\\renewcommand*\\thesubsection{\\thechapter.\\arabic{ctrAppendix}}" + "\\renewcommand*\\thesubsubsection{\\thechapter.\\arabic{ctrAppendix}}" + "\\phantomsection" + "\\addxcontentsline{toc}{chapter}{Anhang}" + "\\renewcommand*\\addchaptertocentry[2]{\\addtocentrydefault{section}{#1}{#2}}" + "\\renewcommand*\\addsectiontocentry[2]{\\addtocentrydefault{subsection}{#1}{#2}}" + "\\renewcommand*\\addsubsectiontocentry[2]{\\addtocentrydefault{subsection}{#1}{#2}}" + "\\renewcommand*\\addsubsubsectiontocentry[2]{\\addtocentrydefault{subsection}{#1}{#2}}" + "\\chapter{Charakterisierungen}" + "{" indentation.more + ] + ++ ( chemistry.substances.checkNovel resources.substances ) + ++ [ + indentation.less "}" + "\\chapter{Literaturverzeichnis}" + "\\printbibliography[heading=none]" + ] + ++ appendix + ++ [ "\\clearpage" indentation.less "}" ] + ) diff --git a/NixTeX/source/render/journal/tex/beginDocument.nix b/NixTeX/source/render/journal/tex/beginDocument.nix new file mode 100644 index 0000000..536f2bb --- /dev/null +++ b/NixTeX/source/render/journal/tex/beginDocument.nix @@ -0,0 +1,22 @@ +{ core, journal, ... }: +let + inherit(core) indentation list string; + inherit(journal) formatAuthor; +in + { authors, title, journal, ... }: + beginDocument: + [ + "\\hypersetup{" indentation.more + "pdfauthor={${string.concatWith ", " (list.map formatAuthor authors)}}," + "pdftitle={${title}}," + "pdfsubject={${journal.title}}," + "pdfkeywords={}," + "pdfproducer={}," + "pdfcreator={}," + indentation.less "}" + "\\tolerance 500%" + "\\emergencystretch 3em%" + "\\hfuzz=2pt%" + "\\vfuzz=2pt%" + "\\hyphenchar\\font=-1%" + ] ++ beginDocument diff --git a/NixTeX/source/render/journal/tex/default.nix b/NixTeX/source/render/journal/tex/default.nix new file mode 100644 index 0000000..3814c76 --- /dev/null +++ b/NixTeX/source/render/journal/tex/default.nix @@ -0,0 +1,102 @@ +{ bibliography, chemistry, core, glossaries,... } @ libs: + let + inherit(core) indentation path list string; + libs' + = libs + // { + journal + = { + formatAuthor + = author: + let + author' = "${author.forename} ${author.surname}"; + matched = string.match "[BM][.]?[A-Za-z.]+" author.title; + in + if author.title or null != null + then + if matched != null + then + "${author'} (${author.title})" + else + "${author.title} ${author'}" + else + author'; + }; + }; + + appendix = path.import ./appendix.nix libs'; + beginDocument = path.import ./beginDocument.nix libs'; + frontMatter = path.import ./frontMatter.nix libs'; + mainMatter = path.import ./mainMatter.nix libs'; + prelude = path.import ./prelude.nix libs'; + titleMatter = path.import ./titleMatter.nix libs'; + in + { configuration, content, dependencies, resources, style, ... } @ document: + let + document' + = document + // { + style = (path.import ./styles libs').${style}; + }; + toTex = libs.document.toTex { inherit configuration resources; }; + + #list.map (name: "\\input{${../tex/${name}.tex}}") + + packages + = [ + "logging" + "dependencies" + "chemistry/chem" + "chemistry/elements" + "bibliography/citation" + "floats/floats" + "fonts" + "geometry" + "glossaries/glossaries" + "links" + "numbers" + "text/text" + "utils" + ]; + acronyms = glossaries.acronyms.loadAcronyms { inherit configuration resources; }; + references = bibliography.loadReferences { inherit configuration resources; }; + substances = chemistry.substances.loadSubstances { inherit configuration resources; }; + + preludeArguments + = { + acronyms = acronyms.dst; + assets = "assets/"; + packages = list.map (name: "\\input{\\source/source/${name}.tex}") packages; + references = references.dst; + source + = { + lua = "source/lua/"; + tex = "source/"; + }; + substances = substances.dst; + }; + in + document' + // { + content + = indentation { initial = ""; tab = " "; } + ( + [] + ++ ( prelude document' preludeArguments) + ++ [ "\\begin{document}" indentation.more ] + ++ ( beginDocument document' []) + ++ ( titleMatter document' null) + ++ ( frontMatter document' null) + ++ ( mainMatter document' (toTex ( content.journal or null ))) + ++ ( appendix document' (toTex ( content.appendix or null ))) + ++ [ "\\directlua{commonFinal()}" ] # ToDo: Remove! + ++ [ indentation.less "\\end{document}" ] + ); + dependencies + = dependencies + ++ [ + acronyms + references + substances + ]; + } diff --git a/NixTeX/source/render/journal/tex/frontMatter.nix b/NixTeX/source/render/journal/tex/frontMatter.nix new file mode 100644 index 0000000..0148487 --- /dev/null +++ b/NixTeX/source/render/journal/tex/frontMatter.nix @@ -0,0 +1,43 @@ +{ core, ... }: +let + inherit(core) indentation; +in + { state, ... }: + _frontmatter: + ( + [ + "{" indentation.more + "\\cleardoublepage" + "\\renewcommand*\\chapterpagestyle{scrheadings}" + "\\pagestyle{scrheadings}" + "\\addxcontentsline{toc}{chapter}{Inhaltsverzeichnis}" + "\\tableofcontents{" indentation.more + "\\elaborate[0]" + "\\clearpage\\addchap{Abkürzungs- und Symbol\\-verzeichnis}{\\printAcronyms}\\afteracronyms" + "\\clearpage\\listSubstancesByNumber{Substanzverzeichnis}" + "\\elaborate[2]" + indentation.less "}" + ] + ++ ( + if state.schemes.counter > 0 + then + [ "\\clearpage\\listofschemes" ] + else + [ ] + ) + ++ ( + if state.figures.counter > 0 + then + [ "\\clearpage\\listoffigures" ] + else + [ ] + ) + ++ ( + if state.tables.counter > 0 + then + [ "\\clearpage\\listoftables" ] + else + [ ] + ) + ++ [ indentation.less "}" ] + ) diff --git a/NixTeX/source/render/journal/tex/mainMatter.nix b/NixTeX/source/render/journal/tex/mainMatter.nix new file mode 100644 index 0000000..1785092 --- /dev/null +++ b/NixTeX/source/render/journal/tex/mainMatter.nix @@ -0,0 +1,17 @@ +{ core, ... }: + let + inherit(core) indentation; + in + { ... }: + mainmatter: + ( + [ + "{" indentation.more + "\\cleardoublepage" + "\\renewcommand*\\chapterpagestyle{scrheadings}" + "\\pagestyle{scrheadings}" + "\\pagenumbering{arabic}" + ] + ++ mainmatter + ++ [ indentation.less "}" ] + ) diff --git a/NixTeX/source/render/journal/tex/prelude.nix b/NixTeX/source/render/journal/tex/prelude.nix new file mode 100644 index 0000000..13adca4 --- /dev/null +++ b/NixTeX/source/render/journal/tex/prelude.nix @@ -0,0 +1,106 @@ +{ core, ... }: + let + inherit(core) string; + in + { ... }: + { assets, acronyms, packages, references, source, substances, ... }: + ( + [ + '' + \documentclass[ + 12pt, + a4paper, + twoside, + bookmarks = true, + pdfborder = {0 0 0}, + pdfencoding = auto, + unicode = true, + sections, + BCOR = 10mm, + listof = flat, + numbers = noenddot, + toc = listof, + toc = index, + table, + ] + {scrreprt} + '' + '' + \directlua{ + acronymFile = "${acronyms}" + jobname = [[\jobname]] + source = [[\source]].."/" + buildDirectory = [[\build]].."/" + dofile("${source.lua}common.lua") + } + '' + "\\newcommand{\\inputCode }[1]{\\input{\\source/${source.tex}#1}}" + "\\newcommand{\\inputAssets}[1]{\\input{\\source/${assets}#1}}" + "\\def\\biblatexStyle{${assets}biblatex/chem-angew}" + "\\makeatletter" + ] + ++ packages + ++ [ + "\\makeatother" + "\\usepackage{scrlayer-scrpage}" + "\\pdfvariable suppressoptionalinfo ${string ( 32 + 64 + 512 )}" # Makes the PDF constant + "\\setstretch{1.433}" # 1/2-spacing + + # Positons, Lengths, Alingments, etc. for TOC + "\\setlength{\\parindent}{0cm}" + "\\newlength{\\chapterindent}" + "\\setlength{\\chapterindent}{0em}" + "\\newlength{\\chapterspace}" + "\\settowidth{\\chapterspace}{6. }" + "\\renewcommand{\\chapterheadstartvskip}{\\vspace{0pt}}" + "\\newlength{\\sectionindent}" + "\\setlength{\\sectionindent}{\\chapterindent}" + "\\addtolength{\\sectionindent}{\\chapterspace}" + "\\newlength{\\sectionspace}" + "\\settowidth{\\sectionspace}{6.6. }" + "\\newlength{\\subsectionindent}" + "\\setlength{\\subsectionindent}{\\sectionindent}" + "\\addtolength{\\subsectionindent}{\\sectionspace}" + "\\newlength{\\subsectionspace}" + "\\settowidth{\\subsectionspace}{6.6.66. }" + "\\newlength{\\subsubsectionindent}" + "\\setlength{\\subsubsectionindent}{\\subsectionindent}" + "\\addtolength{\\subsubsectionindent}{\\subsectionspace}" + "\\newlength{\\subsubsectionspace}" + "\\settowidth{\\subsubsectionspace}{6.6.66.66. }" + # Redefine Sections and Paragraphs + "\\RedeclareSectionCommands[tocpagenumberwidth=6ex]%" + " {part,chapter,section,subsection,subsubsection,paragraph,subparagraph}" + '' + \RedeclareSectionCommands[ + tocentryformat=\tocentryformat, + tocpagenumberformat=\tocentryformat + ] + {section,subsection,subsubsection,paragraph,subparagraph} + '' + '' + \makeatletter + \patchcmd {\l@chapter} {\chapterindent }{\chapterspace}{}{} + \renewcommand {\l@section} {\@dottedtocline{1} {\sectionindent }{\sectionspace}} + \renewcommand {\l@subsection} {\@dottedtocline{2} {\subsectionindent }{\subsectionspace}} + \renewcommand {\l@subsubsection}{\@dottedtocline{3} {\subsubsectionindent }{\subsubsectionspace}} + \makeatother + '' + + # Header and Footer + "\\def\\pagemark{\\thepage}" + "\\pagestyle{scrheadings}" + "\\clearpairofpagestyles" + "\\ohead{\\leftmark}" + "\\ofoot[\\pagemark]{\\pagemark}" + "\\robkoma" + ] + ++ ( + if substances != null + then + [ "\\loadSubstances{${string.slice 0 ((string.length substances) - 4) substances}}" ] + else + [] + ) + ++ [ "\\addbibresource{${references}}" ] + ) diff --git a/NixTeX/source/render/journal/tex/styles/default.nix b/NixTeX/source/render/journal/tex/styles/default.nix new file mode 100644 index 0000000..3c4c130 --- /dev/null +++ b/NixTeX/source/render/journal/tex/styles/default.nix @@ -0,0 +1,7 @@ +{ context, ... } @ libs: +let + libs' = libs // { context = context ++ [ "style" ]; }; + tuc = import ./tuc.nix ( libs' // { inherit vanilla; } ); + vanilla = import ./vanilla.nix libs'; +in + { inherit tuc vanilla; } \ No newline at end of file diff --git a/NixTeX/source/render/journal/tex/styles/tuc.nix b/NixTeX/source/render/journal/tex/styles/tuc.nix new file mode 100644 index 0000000..ebefef0 --- /dev/null +++ b/NixTeX/source/render/journal/tex/styles/tuc.nix @@ -0,0 +1,30 @@ +{ core, journal, vanilla, ... }: +let + inherit(core) indentation list string time; + inherit(journal) formatAuthor; +in +{ + name = "Chemnitz University of Technology"; + titlePage + = { authors, date, journal, place, title, ... }: + [ + "\\vspace*{-1.2cm}" + "{" indentation.more + "\\centering" + "\\raisebox" + " {-1ex}" + " {\\includegraphics[scale=1.4]{tuc/assets/green.pdf}}%\\\\[2.22em]%" + "\\\\[-2.15\\normalbaselineskip]{\\tikz\\node [opacity=0.0,text width=10cm,align=center]%" + " {\\Large TECHNISCHE UNIVERSITÄT\\\\[.07\\normalbaselineskip]CHEMNITZ};}%" + "\\\\[-0.43\\normalbaselineskip+2.22em]%" + "\\hrulefill\\hspace{0pt}\\\\[2.84em]" + "{\\Large ${journal.organisation.department}}\\hspace{0pt}\\\\[0.50em]" + "{${journal.organisation.group}}\\hspace{0pt}\\\\[3.00em]" + "{\\Huge ${title}}\\hspace{0pt}\\\\[2.00em]" + "{\\large ${journal.title}}\\hspace{0pt}\\\\[1.00em]" + "{${string.concatWith ", " ( list.map formatAuthor authors )}}\\hspace{0pt}\\\\[1.00em]" + "{\\scriptsize ${place}, ${time.formatDate date.from "deu"} bis ${time.formatDate date.till "deu"}}" + indentation.less "}" + "\\clearpage" + ]; +} diff --git a/NixTeX/source/render/journal/tex/styles/vanilla.nix b/NixTeX/source/render/journal/tex/styles/vanilla.nix new file mode 100644 index 0000000..898195d --- /dev/null +++ b/NixTeX/source/render/journal/tex/styles/vanilla.nix @@ -0,0 +1,20 @@ +{ core, thesis, ... }: +let + inherit(core) indentation list string time; + inherit(thesis) formatAuthor formatAuthorTableLine thesisVersion; +in +{ + name = "Vanilla"; + titlePage + = { authors, date, place, title, ... }: + [ + "\\centering" + "{\\Large ${journal.organisation.department}} \\\\" + "{${journal.organisation.group}} \\\\" + "{\\Huge ${title}} \\\\" + "{\\large ${journal.title}} \\\\" + "{${string.concatWith ", " ( list.map formatAuthor authors )}} \\\\" + "{\\scriptsize ${place}, ${time.formatDate date.from "deu"} bis ${time.formatDate date.till "deu"}}" + "\\clearpage" + ]; +} diff --git a/NixTeX/source/render/journal/tex/titleMatter.nix b/NixTeX/source/render/journal/tex/titleMatter.nix new file mode 100644 index 0000000..13c19d1 --- /dev/null +++ b/NixTeX/source/render/journal/tex/titleMatter.nix @@ -0,0 +1,32 @@ +{ core, journal, ... }: + let + inherit(core) indentation list string time; + inherit(journal) formatAuthor; + in + { authors, date, journal, place, title, style, ... } @ document: + _: + let + authorList = string.concatWith ", " ( list.map formatAuthor authors ); + in + ( + [ + "{" indentation.more + "\\cleardoublepage" + "\\pagenumbering{roman}" + "\\renewcommand*\\chapterpagestyle{empty}" + "\\pagestyle{empty}" + "\\currentpdfbookmark{Titelseite}{titlepage}" + "\\begin{titlepage}" indentation.more + ] + ++ ( style.titlePage document ) + ++ [ + "~\\vfill" + "\\textbf{${authorList}}\\\\" + "{\\def\\Linebreak{\\newline}\\textit{${title}}}\\\\" + "${journal.title}, ${journal.organisation.department}\\\\" + "${journal.organisation.name}, ${time.formatYearMonth date.from "deu"} bis ${time.formatYearMonth date.till "deu"}" + "\\cleardoublepage" + indentation.less "\\end{titlepage}" + indentation.less "}" + ] + ) diff --git a/NixTeX/source/render/letter/default.nix b/NixTeX/source/render/letter/default.nix new file mode 100644 index 0000000..ee95454 --- /dev/null +++ b/NixTeX/source/render/letter/default.nix @@ -0,0 +1,131 @@ +{ core, document, ... }: +{ configuration, style, ... }: + let + inherit(core) indentation list string type; + + toTex + = document.toTex + { + inherit configuration mod; + resources = {}; + }; + + parseAddress + = address: + type.matchPrimitiveOrPanic address + { + list + = { + name = list.head address; + body = list.tail address; + }; + set + = { + name + = address.name + or "${address.forname} ${address.surname}"; + body + = address.body + or []; + }; + }; + + compileAddress + = kind: + address: + [ + "\\setkomavar{${kind}name}{${string.trim address.name}}" + "\\setkomavar{${kind}address}{${string.concatMappedWith string.trim "\\\\" address.body}}" + ]; + + compileLocation + = fields: + if fields != null + then + [ "\\begin{tabular}{ll}" indentation.more ] + ++ ( + list.map + ( + line: + let + line' + = type.matchPrimitiveOrPanic line + { + null = ""; + set = "${line.name}: & ${line.value}"; + string = "\\multicolumn{2}{l}{${line}}"; + }; + in + "${line'}\\\\" + ) + fields + ) + ++ [ indentation.less "\\end{tabular}" ] + else + [ ]; + + options + = let + getOptions + = let + option + = option: + line: + if option != null + then + [ line ] + else + []; + in + { + appendix ? null, + copies ? null, + subject ? null, + ... + }: + { + appendix = option appendix "\\encl{${appendix}}"; + copies = option copies "\\cc{${trim copies}}"; + subject = option subject "\\setkomavar{subject}{${trim subject}}"; + }; + in + getOptions document; + in + { + paths + = [ + { src = ../tex; dst = "tex"; } + ]; + text + = indentation { initial = ""; tab = " "; } + ( + [ + "\\documentclass[" indentation.more + indentation.less "]{scrlttr2}" + "\\setkomavar{location}{%" indentation.more + ] + ++ ( compileLocation document.location or null ) + ++ [ indentation.less "}" ] + ++ ( compileAddress "back" ( parseAddress document.return or document.sender )) + ++ ( compileAddress "from" ( parseAddress document.sender )) + ++ ( compileAddress "to" ( parseAddress document.recipient )) + ++ options.subject + ++ [ + "\\begin{document}" indentation.more + "\\begin{letter}{}" indentation.more + ] + ++ options.appendix + ++ options.copies + ++ [ + "\\opening{${document.opening}}" + "{" indentation.more + ] + ++ ( toTex document.body ) + ++ [ + indentation.less "}" + "\\closing{${document.closing}}" + indentation.less "\\end{letter}" + indentation.less "\\end{document}" + ] + ); + } diff --git a/NixTeX/source/render/thesis/default.nix b/NixTeX/source/render/thesis/default.nix new file mode 100644 index 0000000..251d6ba --- /dev/null +++ b/NixTeX/source/render/thesis/default.nix @@ -0,0 +1,30 @@ +{ core, ... } @ libs: + let + inherit(core) library; + + getFormat + = outputFormat: + if outputFormat != null + then + outputFormat + else + "tex"; + renderTex = library.import ./tex libs; + renderMarkdown = library.import ./markdown libs; + in + { + evaluationOrder + = [ + "titleMatter" + "frontMatter" + "mainMatter" + "appendix" + "backMatter" + ]; + render + = outputFormat: + { + "tex" = renderTex; + "markdown" = renderMarkdown; + }.${getFormat outputFormat}; + } diff --git a/NixTeX/source/render/thesis/markdown/default.nix b/NixTeX/source/render/thesis/markdown/default.nix new file mode 100644 index 0000000..7fe1f12 --- /dev/null +++ b/NixTeX/source/render/thesis/markdown/default.nix @@ -0,0 +1,27 @@ +{ core, ... } @ libs: +{ authors, configuration, content, date, dependencies, name, place, resources, thesis, ... } @ document: + let + inherit(core) indentation path; + toMarkdown = libs.document.toMarkdown { inherit configuration resources; }; + + mainMatter = toMarkdown ( content.mainMatter or content.body or null ); + + content' + = indentation { initial = ""; tab = " "; } + ( + mainMatter + ); + mdFile = path.toFile "${name}.md" content'; + in + document + // { + content = content'; + dependencies + = dependencies + ++ [ + { + src = mdFile; + dst = "${name}.tex"; + } + ]; + } diff --git a/NixTeX/source/render/thesis/tex/appendix.nix b/NixTeX/source/render/thesis/tex/appendix.nix new file mode 100644 index 0000000..82493b8 --- /dev/null +++ b/NixTeX/source/render/thesis/tex/appendix.nix @@ -0,0 +1,47 @@ +{ context, core, ... }: + let + inherit(core) indentation; + in + { configuration, ... }: + appendix: + ( + [ + "\\addtocontents{toc}{\\protect\\setcounter{tocdepth}{\\sectiontocdepth}}" + "\\appendix{" indentation.more + "\\setcounter{secnumdepth}{5}" + "\\renewcommand*\\thesubsection{\\thechapter.\\arabic{ctrAppendix}}" + "\\renewcommand*\\thesubsubsection{\\thechapter.\\arabic{ctrAppendix}}" + ] + ++ ( + if configuration.concise or false + then + [] + else + [ + "\\newpage" + "\\thispagestyle{empty}" + "~" + "\\cleardoublepage" + ] + ) + ++ [ + "\\phantomsection" + "\\addxcontentsline{toc}{chapter}{Anhang}" + "\\renewcommand*\\addchaptertocentry[2]{\\addtocentrydefault{section}{#1}{#2}}" + "\\renewcommand*\\addsectiontocentry[2]{\\addtocentrydefault{subsection}{#1}{#2}}" + "\\renewcommand*\\addsubsectiontocentry[2]{\\addtocentrydefault{subsection}{#1}{#2}}" + "\\renewcommand*\\addsubsubsectiontocentry[2]{\\addtocentrydefault{subsection}{#1}{#2}}" + "\\chapter{Literaturverzeichnis}" + "\\printbibliography[heading=none]" + ] + ++ appendix + ++ [ "\\clearpage" ] + ++ ( + if configuration.concise or false + then + [] + else + [ "\\thispagestyle{empty}" ] + ) + ++ [ indentation.less "}" ] + ) diff --git a/NixTeX/source/render/thesis/tex/backMatter.nix b/NixTeX/source/render/thesis/tex/backMatter.nix new file mode 100644 index 0000000..1364dc7 --- /dev/null +++ b/NixTeX/source/render/thesis/tex/backMatter.nix @@ -0,0 +1,28 @@ +{ context, core, thesis, ... }: + let + inherit(core) indentation; + in + { configuration, ... }: + backmatter: + ( + [ + "{" indentation.more + ] + ++ [ + "\\renewcommand*\\chapterpagestyle{empty}" + "\\pagestyle{empty}" + "\\renewcommand*\\thechapter{}" + "\\renewcommand*\\thesection{}" + "\\renewcommand*\\thesubsection{}" + "\\renewcommand*\\thesubsubsection{}" + ] + ++ ( + if configuration.concise or false + then + [ ] + else + [ "\\newpage\\unrotatePages\\thispagestyle{empty}\\mbox{}" ] + ) + ++ backmatter + ++ [ indentation.less "}" ] + ) diff --git a/NixTeX/source/render/thesis/tex/beginDocument.nix b/NixTeX/source/render/thesis/tex/beginDocument.nix new file mode 100644 index 0000000..d676470 --- /dev/null +++ b/NixTeX/source/render/thesis/tex/beginDocument.nix @@ -0,0 +1,99 @@ +{ context, core, thesis, ... }: + let + inherit(core) indentation list string; + inherit(thesis) formatAuthor; + + setTolerances + = { + pretolerance ? 100, # + tolerance ? 200, # + hfuzz ? "0.1pt", # + vfuzz ? "0.1pt", # + hbadness ? 1000, # + vbadness ? 1000, # + emergencystretch ? "3em", # + }: + [ + "\\pretolerance=${string pretolerance}%" + "\\tolerance=${string tolerance}%" + "\\hfuzz=${string hfuzz}%" + "\\vfuzz=${string vfuzz}%" + "\\hbadness=${string hbadness}%" + "\\vbadness=${string vbadness}%" + "\\emergencystretch=${string emergencystretch}%" + ]; + + setPenalties + = { + binaryOperator ? 700, # for a line break in math mode after a binary operator. + brokenHyphen ? 100, # for a page break, where the last line of the previous page contains a hyphenation. + club ? 150, # for a broken page, with a single line of a paragraph remaining on the bottom of the preceding page. + displayWidow ? 50, # for a break before last line of a paragraph. + doubleHyphen ? 10000, # for two consecutive hyphenated lines. + explicitHyphen ? 50, # for hyphenating a word which already contains a hyphen. + finalHyphen ? 5000, # for a hyphen in the last full line of a paragraph. + floating ? 20000, # for splitting an insertion. + hyphen ? 50, # for line breaking at an automatically inserted hyphen. + incompatibleLines ? 10000, # for two consecutive lines are visually incompatible. + interDisplay ? 100, # for breaking a display on two pages. + interFootnote ? 100, # for breaking a footnote on two pages. + interLine ? 0, # for the penalty added after each line of a paragraph + line ? 10, # for each line within a paragraph. + postDisplay ? 0, # for a break after a display. + preDisplay ? 10000, # for a break before a display. + relationOperator ? 500, # for a line break in math mode after a a relation operator. + widow ? 150, # for a broken page, with a single line of a paragraph remaining on the top of the succeeding page. + }: + [ + "\\adjdemerits=${string incompatibleLines}%" + "\\binoppenalty=${string binaryOperator}%" + "\\brokenpenalty=${string brokenHyphen}%" + "\\clubpenalty=${string club}%" + "\\doublehyphendemerits=${string doubleHyphen}%" + "\\displaywidowpenalty=${string displayWidow}%" + "\\exhyphenpenalty=${string explicitHyphen}%" + "\\finalhyphendemerits=${string finalHyphen}%" + "\\floatingpenalty=${string floating}%" + "\\hyphenpenalty=${string hyphen}%" + "\\interdisplaylinepenalty=${string interDisplay}%" + "\\interfootnotelinepenalty=${string interFootnote}%" + "\\interlinepenalty=${string interLine}%" + "\\linepenalty=${string line}%" + "\\postdisplaypenalty=${string postDisplay}%" + "\\predisplaypenalty=${string preDisplay}%" + "\\relpenalty=${string relationOperator}%" + "\\widowpenalty=${string widow}%" + ]; + in + { authors, thesis, title, ... }: + beginDocument: + [ + "\\hypersetup{" indentation.more + "pdfauthor={${string.concatWith ", " (list.map formatAuthor authors)}}," + "pdftitle={${title}}," + "pdfsubject={${thesis.title}}," + "pdfkeywords={}," + "pdfproducer={}," + "pdfcreator={}," + indentation.less "}" + #"\\hyphenchar\\font=-1%" + ] + ++ ( + setTolerances + { + tolerance = 500; + emergencystretch = "3em"; + hfuzz = "2pt"; + vfuzz = "2pt"; + } + ) + ++ ( + setPenalties + { + brokenHyphen = 100; + club = 350; + hyphen = 10000; + widow = 350; + } + ) + ++ beginDocument diff --git a/NixTeX/source/render/thesis/tex/default.nix b/NixTeX/source/render/thesis/tex/default.nix new file mode 100644 index 0000000..3df8149 --- /dev/null +++ b/NixTeX/source/render/thesis/tex/default.nix @@ -0,0 +1,256 @@ +{ bibliography, chemistry, core, document, glossaries,... } @ libs: + let + inherit(core) indentation library list path string time; + + formatAuthor + = author: + let + author' = "${author.forename} ${author.surname}"; + matched = string.match "[BM][.]?[A-Za-z.]+" author.title; + in + if author.title or null != null + then + if matched != null + then + "${author'} (${author.title})" + else + "${author.title} ${author'}" + else + author'; + + libs' + = libs + // { + thesis + = let + cleardoublepage + = configuration: + if configuration.concise or false + then + "\\clearpage" + else + "\\cleardoublepage"; + + formatAuthorTableLine = author: "& ${formatAuthor author}\\\\"; + + thesisVersion + = version: + { + final = "Abgabe am"; + draft = "Vorläufige Abgabe am"; + revised = "Überarbeitet, Abgegeben am"; + }.${version} or version; + in + { + inherit cleardoublepage formatAuthor formatAuthorTableLine thesisVersion; + }; + }; + + renderAppendix = library.import ./appendix.nix libs'; + renderBackMatter = library.import ./backMatter.nix libs'; + renderBeginDocument = library.import ./beginDocument.nix libs'; + renderFrontMatter = library.import ./frontMatter.nix libs'; + renderMainMatter = library.import ./mainMatter.nix libs'; + renderPrelude = library.import ./prelude.nix libs'; + renderTitleMatter = library.import ./titleMatter.nix libs'; + in + { authors, configuration, content, date, dependencies, name, place, resources, thesis, ... } @ document: + let + style = (import ./styles libs').${thesis.style}; + document' = document // { inherit style; }; + toTex = libs.document.toTex { inherit configuration resources; }; + + #list.map (name: "\\input{${../tex/${name}.tex}}") + + packages + = [ + "logging" + "dependencies" + "chemistry/chem" + "chemistry/elements" + "bibliography/citation" + "floats/floats" + "geometry" + "glossaries/glossaries" + "links" + "text/text" + "utils" + ]; + acronyms = glossaries.acronyms.toLua { inherit configuration resources; }; + references = bibliography.toBibTeX { inherit configuration resources; } resources.references; + substances = chemistry.substances.toLua { inherit configuration resources; } resources.substances; + prelude + = { + acronyms = acronyms.dst; + assets = "assets/"; + packages = list.map (name: "\\input{\\source/source/${name}.tex}") packages; + references = references.dst; + source + = { + lua = "source/lua/"; + tex = "source/"; + }; + substances = substances.dst; + }; + + titleMatter = toTex ( content.titleMatter or content.titlematter or null ); + frontMatter = toTex ( content.frontMatter or content.frontmatter or null ); + mainMatter = toTex ( content.mainMatter or content.body or null ); + appendix = toTex ( content.appendix or null ); + + originalityDeclaration + = if thesis.originalityDeclaration or null != null + then + "resources/${path.getBaseName thesis.originalityDeclaration}" + else + null; + backMatter + = ( toTex ( content.backMatter or content.backmatter or null ) ) + ++ ( + if configuration.concise or false + then + [ ] + else + [ "\\cleardoublepage" ] + ) + ++ ( + if originalityDeclaration == null + then + [ + "\\chapter*{Selbstständigkeitserklärung}{" indentation.more + "\\addcontentsline{toc}{chapter}{Selbstständigkeitserklärung}" + "\\markboth{Selbstständigkeitserklärung}{}" + ] + ++ ( style.originalityDeclaration document ) + ++ [ "\\par\\mbox{}\\\\${place}, den ${time.formatDate date "deu"}\\\\\\\\\\\\" ] + ++ ( + list.concatMap + ( + { forename, surname, ... } @ author: + [ + "\\parbox[][][t]{0.5\\hsize}" + "{" + " \\begin{tabularx}{\\hsize}{@{}p{0.8\\hsize}@{}}" + " ~~\\,\\dotfill\\\\" + " ~~~${formatAuthor author} \\\\" + " \\end{tabularx}" + "}" + ] + ) + authors + ) + ++ [ indentation.less "}" ] + else + [ + "\\addcontentsline{toc}{chapter}{Selbstständigkeitserklärung}" + "\\includepdf[pages={1}]{\\source/${originalityDeclaration}}" + ] + ); + + content' + = indentation { initial = ""; tab = " "; } + ( + [] + ++ ( renderPrelude document' prelude ) + ++ [ "\\begin{document}" indentation.more ] + ++ ( renderBeginDocument document' [] ) + ++ ( renderTitleMatter document' titleMatter ) + ++ ( renderFrontMatter document' frontMatter ) + ++ ( renderMainMatter document' mainMatter ) + ++ ( renderAppendix document' appendix ) + ++ ( renderBackMatter document' backMatter ) + ++ [ "\\directlua{commonFinal()}" ] # ToDo: Remove! + ++ [ indentation.less "\\end{document}" ] + ); + + optimiser + = if configuration.optimise or false + then + '' + # Optimise and linearise + # This removes tooltips, sorry + mv "${name}.pdf" "${name}-raw.pdf" + gs \ + -dBATCH \ + -dColorImageResolution=288 \ + -dCompatibilityLevel=1.7 \ + -dDEBUG \ + -dDetectDuplicateImages \ + -dDownsampleColorImages=true \ + -dDownsampleGrayImages=true \ + -dDownsampleMonoImages=true \ + -dFastWebView \ + -dGrayImageResolution=288 \ + -dMonoImageResolution=288 \ + -dNOPAUSE \ + -dPDFSETTINGS=/ebook \ + -dPrinted=false \ + -sDEVICE=pdfwrite \ + -sOutputFile="${name}.pdf" \ + "${name}-raw.pdf" \ + > "${name}.gslog" 2>&1 + '' + else + ""; + + compile + = path.toFile "compile-${name}.sh" + '' + #!/usr/bin/env bash + newHash="false" + oldHash="true" + out="$1" + + counter="" + while [[ "$newHash" != "$oldHash" && "$counter" != "${configuration.foo or "+++++"}" ]] + do + if lualatex \ + --interaction=nonstopmode \ + --halt-on-error \ + --output-format=pdf \ + "\def\source{$out}\def\build{.}\input{$out/${name}.tex}" #2> /dev/null > /dev/null + then + oldHash="$newHash" + newHash="$(md5sum "${name}.pdf")" + echo "$newHash" + mv "${name}.log" "$out/${name}.log" + mv "${name}.llg" "$out/${name}.llg" + biber "${name}" + counter="+$counter" + else + exit 1 + fi + done + + ${optimiser} + # move the generated and processed document to the final-directory + mv "${name}.pdf" "$out/${name}.pdf" + ''; + texFile = path.toFile "${name}.tex" content'; + in + document' + // { + content = content'; + dependencies + = dependencies + ++ [ + acronyms + references + substances + { + src = texFile; + dst = "${name}.tex"; + } + { + src = { store = compile; executable = true; }; + dst = "compile-${name}.sh"; + } + ] + ++ ( + if originalityDeclaration != null + then + [ { src = thesis.originalityDeclaration; dst = originalityDeclaration; } ] + else + [] + ); + } diff --git a/NixTeX/source/render/thesis/tex/frontMatter.nix b/NixTeX/source/render/thesis/tex/frontMatter.nix new file mode 100644 index 0000000..2496d14 --- /dev/null +++ b/NixTeX/source/render/thesis/tex/frontMatter.nix @@ -0,0 +1,61 @@ +{ context, core, thesis, ... }: + let + inherit(core) indentation; + inherit(thesis) cleardoublepage; + in + { configuration, state, ... }: + frontMatter: + let + cleardoublepage' = cleardoublepage configuration; + in + ( + [ + "{%" indentation.more + "\\cleardoublepage%" + "\\renewcommand*\\chapterpagestyle{scrheadings}%" + "\\pagestyle{scrheadings}%" + ] + ++ [ + "\\addxcontentsline{toc}{chapter}{Inhaltsverzeichnis}%" + "\\tableofcontents{%" indentation.more + "\\directlua{text.elaborate(\"0\")}%" + "${cleardoublepage'}%" + "\\addchap{Abkürzungs- und Symbol\\-verzeichnis}{\\directlua{acronyms.printList([[single-line]])}}%" + "\\afteracronyms%" + ] + ++ ( + if configuration.substances.enable + && configuration.substances.list + then + [ "${cleardoublepage'}\\addchap{Substanzverzeichnis}{\\directlua{substances.printList(true)}}" ] + else + [ ] + ) + ++ [ + "\\directlua{text.elaborate(\"2\")}%" + indentation.less "}" + ] + ++ ( + if state.schemes.counter > 0 + then + [ "${cleardoublepage'}\\listofschemes" ] + else + [ ] + ) + ++ ( + if state.figures.counter > 0 + then + [ "${cleardoublepage'}\\listoffigures" ] + else + [ ] + ) + ++ ( + if state.tables.counter > 0 + then + [ "${cleardoublepage'}\\listoftables" ] + else + [ ] + ) + ++ frontMatter + ++ [ indentation.less "}" ] + ) diff --git a/NixTeX/source/render/thesis/tex/mainMatter.nix b/NixTeX/source/render/thesis/tex/mainMatter.nix new file mode 100644 index 0000000..4dc8f09 --- /dev/null +++ b/NixTeX/source/render/thesis/tex/mainMatter.nix @@ -0,0 +1,17 @@ +{ context, core, ... }: + let + inherit(core) indentation; + in + { ... }: + mainmatter: + ( + [ + "{" indentation.more + "\\cleardoublepage" + "\\renewcommand*\\chapterpagestyle{scrheadings}" + "\\pagestyle{scrheadings}" + "\\pagenumbering{arabic}" + ] + ++ mainmatter + ++ [ indentation.less "}" ] + ) diff --git a/NixTeX/source/render/thesis/tex/old.nix b/NixTeX/source/render/thesis/tex/old.nix new file mode 100644 index 0000000..ea2ceb8 --- /dev/null +++ b/NixTeX/source/render/thesis/tex/old.nix @@ -0,0 +1,22 @@ +[ + "\\cleardoublepage" + "\\chapter*{Bibliografische Beschreibung}{" indentation.more + "${authorList} \\\\ \\\\" + "\\textbf{${title}}\\\\\\\\" + "${thesis.organisation.name}," + "${thesis.organisation.department} \\\\" + "${thesis.title}~" + "${time.formatDate' date "deu"}," + "\\thelastpage~Seiten%" + "%\\relax\\ifthenelse{\\equal{\\totalfigures}{0}}{}{, \\ifthenelse{\\equal{\\totalfigures}{1}}{eine~Abbildung}{\\totalfigures~Abbildungen}}%" + "%\\relax\\ifthenelse{\\equal{\\totaltables} {0}}{}{, \\ifthenelse{\\equal{\\totaltables} {1}}{eine~Tabelle} {\\totaltables~Tabellen}}%" + "%\\ifthenelse{\\equal{\\totalfigures\\totaltables}{00}}{\\\\}{\\linebreak}\\\\" + "${abstract}" + "\\vfill" + "\\begin{tabularx}{\\linewidth}{@{}lX@{}}" + indentation.more + "Schlagworte & \\textit{${string.concatWith ", " keywords}}" + indentation.less + "\\end{tabularx}" + indentation.less "{" +] diff --git a/NixTeX/source/render/thesis/tex/prelude.nix b/NixTeX/source/render/thesis/tex/prelude.nix new file mode 100644 index 0000000..e9caadc --- /dev/null +++ b/NixTeX/source/render/thesis/tex/prelude.nix @@ -0,0 +1,202 @@ +{ context, core, ... }: + let + inherit(core) indentation set string; + + boldFont + = { + BoldFont = "*-Bold"; + UprightFont = "*-Regular"; + }; + + regularFont + = { + UprightFont = "*-Regular"; + }; + + lightFont + = { + BoldFont = "*-Bold"; + ItalicFont = "*-Light"; + UprightFont = "*-Regular"; + }; + + usualFont + = { + BoldFont = "*-Bold"; + BoldItalicFont = "*-BoldItalic"; + ItalicFont = "*-Italic"; + UprightFont = "*-Regular"; + }; + + defaultFontFeatures + = fontName: + { ... } @ features: + [ + "\\defaultfontfeatures[${fontName}]{" indentation.more + "Path = \\source/fonts/," + "Extension = .ttf," + ] + ++ (set.mapToList (key: value: "${key} = ${value},") features) + ++ [ indentation.less "}" ]; + in + { ... }: + { assets, acronyms, packages, references, source, substances, ... }: + ( + [ + '' + \documentclass[ + 12pt, + a4paper, + twoside, + bookmarks = true, + pdfborder = {0 0 0}, + pdfencoding = auto, + unicode = true, + sections, + BCOR = 10mm, + listof = flat, + numbers = noenddot, + toc = listof, + toc = index, + table, + ] + {scrreprt} + '' + '' + \directlua{ + acronymFile = "${acronyms}" + jobname = [[\jobname]] + source = [[\source]].."/" + buildDirectory = [[\build]].."/" + dofile(source.."${source.lua}common.lua") + } + '' + "\\newcommand{\\inputCode }[1]{\\input{\\source/${source.tex}#1}}" + "\\newcommand{\\inputAssets}[1]{\\input{\\source/${assets}#1}}" + "\\def\\biblatexStyle{\\source/${assets}biblatex/chem-angew}" + "\\makeatletter" + ] + ++ packages + ++ [ + "\\makeatother" + "\\usepackage{scrlayer-scrpage}" + ] + ++ ( defaultFontFeatures "Arimo" usualFont ) + ++ ( defaultFontFeatures "Cousine" usualFont ) + ++ ( defaultFontFeatures "DejaVu Sans" regularFont ) + ++ ( defaultFontFeatures "Liberation Mono" usualFont ) + ++ ( defaultFontFeatures "Liberation Sans" usualFont ) + ++ ( defaultFontFeatures "Liberation Serif" usualFont ) + ++ ( defaultFontFeatures "Noto Sans" usualFont ) + ++ ( defaultFontFeatures "Noto Serif" usualFont ) + ++ ( defaultFontFeatures "Noto Color Emoji" regularFont ) + ++ ( defaultFontFeatures "Noto Kufi Arabic" lightFont ) + ++ ( defaultFontFeatures "Noto Music Regular" regularFont ) + ++ ( defaultFontFeatures "Noto Naskh Arabic" boldFont ) + ++ ( defaultFontFeatures "Noto Naskh Arabic UI" boldFont ) + ++ ( defaultFontFeatures "Noto Nastaliq Urdu" boldFont ) + ++ ( defaultFontFeatures "Noto Rashi Hebrew" lightFont ) + ++ ( defaultFontFeatures "Noto Sans Adlam" boldFont ) + ++ ( defaultFontFeatures "Noto Sans Adlam Unjoined" boldFont ) + ++ ( defaultFontFeatures "Noto Sans Hebrew" lightFont ) + ++ ( defaultFontFeatures "Noto Serif Hebrew" lightFont ) + ++ ( defaultFontFeatures "Roboto" usualFont ) + ++ ( defaultFontFeatures "Roboto Condensed" usualFont ) + ++ ( defaultFontFeatures "Roboto Mono" usualFont ) + ++ ( defaultFontFeatures "Roboto Slab" lightFont ) + ++ ( defaultFontFeatures "Tinos" usualFont ) + ++ ( defaultFontFeatures "unifont" regularFont ) + ++ [ + "\\def\\fullStop{\\foreignlanguage{british}{.}}" + "\\def\\comma{\\foreignlanguage{british}{,}}" + "\\setmainfont{Tinos}[]" + "\\setsansfont{Roboto}[]" + "\\setmonofont{Roboto Mono}[]" + "\\setmathfont{latinmodern-math.otf}[]" + "\\babelprovide[import]{british}" + "\\babelprovide[import,main]{ngerman}" + "\\babelfont{rm}{Tinos}" + "\\babelfont{sf}{Roboto}" + "\\babelfont{tt}{Roboto Mono}" + "\\babelprovide[import]{arabic}" + "\\babelfont[*arabic]{rm}[RawFeature=]{Noto Naskh Arabic}" + "\\babelfont[*arabic]{sf}[RawFeature={fallback=NotoSansFallback}]{Noto Kufi Arabic}" + "\\babelprovide[import]{greek}" + "\\babelfont[greek]{rm}{Noto Serif}" + "\\babelfont[greek]{sf}{Roboto}" + "\\babelfont[greek]{tt}{Roboto}" + "\\babelprovide[import]{hebrew}" + "\\babelfont[*hebrew]{rm}{Noto Serif Hebrew}" + "\\babelfont[*hebrew]{sf}{Noto Sans Hebrew}" + "\\babelfont[*hebrew]{tt}{Noto Sans Hebrew}" + #"\\babelprovide[import]{japanese}" + #"\\babelfont[japanese]{rm}{Noto Serif Japanese}" + #"\\babelfont[japanese]{sf}{Noto Sans Japanese}" + #"\\babelfont[japanese]{tt}{Noto Sans Japanese}" + "\\renewcommand{\\familydefault}{\\sfdefault}" + "\\pdfvariable suppressoptionalinfo ${string ( 32 + 64 + 512 )}" # Makes the PDF constant + "\\setstretch{1.433}" # 1/2-spacing + + "\\DeclareFloatingEnvironment[" indentation.more + "fileext = los," + "listname = {Schema\\-verzeichnis}," + "name = Schema," + indentation.less "]{scheme}" + + # Positons, Lengths, Alingments, etc. for TOC + "\\setlength{\\parindent}{0cm}" + "\\newlength{\\chapterindent}" + "\\setlength{\\chapterindent}{0em}" + "\\newlength{\\chapterspace}" + "\\settowidth{\\chapterspace}{6. }" + "\\renewcommand{\\chapterheadstartvskip}{\\vspace{0pt}}" + "\\newlength{\\sectionindent}" + "\\setlength{\\sectionindent}{\\chapterindent}" + "\\addtolength{\\sectionindent}{\\chapterspace}" + "\\newlength{\\sectionspace}" + "\\settowidth{\\sectionspace}{6.6. }" + "\\newlength{\\subsectionindent}" + "\\setlength{\\subsectionindent}{\\sectionindent}" + "\\addtolength{\\subsectionindent}{\\sectionspace}" + "\\newlength{\\subsectionspace}" + "\\settowidth{\\subsectionspace}{6.6.66. }" + "\\newlength{\\subsubsectionindent}" + "\\setlength{\\subsubsectionindent}{\\subsectionindent}" + "\\addtolength{\\subsubsectionindent}{\\subsectionspace}" + "\\newlength{\\subsubsectionspace}" + "\\settowidth{\\subsubsectionspace}{6.6.66.66. }" + # Redefine Sections and Paragraphs + "\\RedeclareSectionCommands[tocpagenumberwidth=6ex]%" + " {part,chapter,section,subsection,subsubsection,paragraph,subparagraph}" + '' + \RedeclareSectionCommands[ + tocentryformat=\tocentryformat, + tocpagenumberformat=\tocentryformat + ] + {section,subsection,subsubsection,paragraph,subparagraph} + '' + '' + \makeatletter + \patchcmd {\l@chapter} {\chapterindent }{\chapterspace}{}{} + \renewcommand {\l@section} {\@dottedtocline{1} {\sectionindent }{\sectionspace}} + \renewcommand {\l@subsection} {\@dottedtocline{2} {\subsectionindent }{\subsectionspace}} + \renewcommand {\l@subsubsection}{\@dottedtocline{3} {\subsubsectionindent }{\subsubsectionspace}} + \makeatother + '' + + # Header and Footer + "\\def\\pagemark{\\thepage}" + "\\pagestyle{scrheadings}" + "\\clearpairofpagestyles" + "\\ohead{\\leftmark}" + "\\ofoot[\\pagemark]{\\pagemark}" + ] + ++ ( + if substances != null + then + [ "\\directlua{substances.load(source..\"${string.slice 0 ((string.length substances) - 4) substances}\")}%" ] + else + [] + ) + ++ [ "\\addbibresource{\\source/${references}}" ] + ) diff --git a/NixTeX/source/render/thesis/tex/styles/default.nix b/NixTeX/source/render/thesis/tex/styles/default.nix new file mode 100644 index 0000000..95d6e55 --- /dev/null +++ b/NixTeX/source/render/thesis/tex/styles/default.nix @@ -0,0 +1,7 @@ +{ context, ... } @ libs: + let + libs' = libs // { context = context ++ [ "style" ]; }; + tuc = import ./tuc.nix ( libs' // { inherit vanilla; } ); + vanilla = import ./vanilla.nix libs'; + in + { inherit tuc vanilla; } diff --git a/NixTeX/source/render/thesis/tex/styles/tuc.nix b/NixTeX/source/render/thesis/tex/styles/tuc.nix new file mode 100644 index 0000000..d76837a --- /dev/null +++ b/NixTeX/source/render/thesis/tex/styles/tuc.nix @@ -0,0 +1,149 @@ +{ core, thesis, vanilla, ... }: + let + inherit(core) indentation list string time; + inherit(thesis) formatAuthor formatAuthorTableLine thesisVersion; + in + { + name = "Chemnitz University of Technology"; + inherit(vanilla) originalityDeclaration; + titlePage + = { authors, date, place, thesis, title, version, ... }: + [ + "\\vspace*{-1.2cm}" + "{" indentation.more + "\\centering" + "\\raisebox" + " {-1ex}" + " {\\includegraphics[scale=1.4]{\\source/tuc/assets/green.pdf}}%\\\\[2.22em]%" + "\\\\[-2.15\\normalbaselineskip]{\\tikz\\node [opacity=0.0,text width=10cm,align=center]%" + " {\\Large TECHNISCHE UNIVERSITÄT\\\\[.07\\normalbaselineskip]CHEMNITZ};}%" + "\\\\[-0.43\\normalbaselineskip+2.22em]%" + "\\hrulefill\\hspace{0pt}\\\\[2.84em]" + "{\\Large ${thesis.organisation.department}}\\hspace{0pt}\\\\[0.50em]" + "{${thesis.organisation.group}}\\hspace{0pt}\\\\[3.00em]" + "{\\Huge ${title}}\\hspace{0pt}\\\\[2.00em]" + "{\\large ${thesis.title}}\\hspace{0pt}\\\\[1.00em]" + ] + ++ ( + if thesis.degree != null + then + let + author = list.head authors; + in + [ + "{zur Erlangung des akademischen Grades}\\\\[1.00em]" + "{${thesis.degree.long}}\\\\" + "{(${thesis.degree.short})}" + "\\vfill" + "\\begin{tabularx}{\\linewidth}{@{}lX@{}}" indentation.more + "Vorgelegt von & ${formatAuthor author}\\\\" + "Fachsemester & ${string author.studies.semester}\\\\" + "Studiengang & ${author.studies.course}\\\\" + ] + else + [ + "{${string.concatWith ", " ( list.map formatAuthor authors )}}" + "\\vfill" + "\\begin{tabularx}{\\linewidth}{@{}lX@{}}" indentation.more + ] + ) + ++ [ ( thesis.auditors or { title = ""; } ).title or "Prüfer" ] + ++ ( list.map formatAuthorTableLine ( thesis.auditors or { people = []; } ).people ) + ++ [ ( thesis.advisors or { title = ""; } ).title or "Betreuer" ] + ++ ( list.map formatAuthorTableLine ( thesis.advisors or { people = []; } ).people ) + ++ [ + "${thesisVersion version} & ${time.formatDate date "deu"} in ${place} \\\\" + indentation.less "\\end{tabularx}" + indentation.less "}" + "\\clearpage" + ]; + } + + /* + { + \normalsize + zur Erlangung des akademischen Grades\\[1em] + \@ThesisTypeTitleLong\\ + (\@ThesisTypeTitleShort)\\[1em] + \ifthenelse{\equal{\@ThesisTypeShort}{Dissertation}} + { + vorgelegt\\[1em] + der \@ThesisDepartment\\der Technischen Universität Chemnitz\\[1em] + von \@ThesisAuthorATitle\@ThesisAuthorAFirstName\ \@ThesisAuthorALastName\ifnotempty{\@ThesisAuthorANumber}{\ (\@ThesisAuthorANumber)}\\ + geboren am \@ThesisAuthorABirthDate\ in \@ThesisAuthorABirthPlace + \vfill + \begin{tabular}{@{}ll@{}} + \ifnotempty{\@ThesisAuditorsNames} + { + \textbf{\@ThesisAuditorsTitle} + \directlua + { + for name in string.gmatch([[\@ThesisAuditorsNames]], "[^,]+") + do + tex.print("&"..name..tex.newline) + end + } + } + \ifnotempty{\@ThesisAdvisorsNames} + { + \textbf{\@ThesisAdvisorsTitle} + \directlua + { + for name in string.gmatch([[\@ThesisAdvisorsNames]], "[^,]+") + do + tex.print("&"..name..tex.newline) + end + } + } + \end{tabular} + \begin{flushleft} + \@ThesisPlace, den \@ThesisDate + \end{flushleft} + } + { + \vfill + \begin{tabularx}{\linewidth}{@{}lX@{}} + Vorgelegt von & \@ThesisAuthorATitle\@ThesisAuthorAFirstName\ \@ThesisAuthorALastName\ifnotempty{\@ThesisAuthorAThanks}{\footnotemark} + \ifnotempty{\@ThesisAuthorBFirstName} + {\@ThesisAuthorBTitle\@ThesisAuthorBFirstName\ \@ThesisAuthorBLastName\ifnotempty{\@ThesisAuthorBThanks}{\footnotemark}} + \\ + \ifnotempty{\@ThesisAuthorASemester} {Fachsemester & \@ThesisAuthorASemester\\} + \ifnotempty{\@ThesisAuthorACourse} {Studiengang & \@ThesisAuthorACourse\\} + \ifnotempty{\@ThesisAuditorsNames} + {% + \@ThesisAuditorsTitle + \directlua + { + for name in string.gmatch([[\@ThesisAuditorsNames]], "[^,]+") + do + tex.print("&"..name..tex.newline) + end + } + } + \ifnotempty{\@ThesisAdvisorsNames} + {% + \@ThesisAdvisorsTitle + \directlua + { + for name in string.gmatch([[\@ThesisAdvisorsNames]], "[^,]+") + do + tex.print("&"..name..tex.newline) + end + } + } + \ifthenelse {\equal{\@ThesisVersion}{final}} + {Eingereicht am} + {% + \ifthenelse {\equal{\@ThesisVersion}{prelimary}} + {Vorläufige Abgabe am} + {% + \ifthenelse {\equal{\@ThesisVersion}{revised}} + {Überarbeitet, Abgegeben am} + {\q{\@ThesisVersion}, Abgegeben am} + } + } + & \@ThesisDate\ in \@ThesisPlace \\ + \end{tabularx} + } + } + */ \ No newline at end of file diff --git a/NixTeX/source/render/thesis/tex/styles/vanilla.nix b/NixTeX/source/render/thesis/tex/styles/vanilla.nix new file mode 100644 index 0000000..d1faaf9 --- /dev/null +++ b/NixTeX/source/render/thesis/tex/styles/vanilla.nix @@ -0,0 +1,50 @@ +{ core, thesis, ... }: + let + inherit(core) indentation list string time; + inherit(thesis) formatAuthor thesisVersion; + in + { + name = "Vanilla"; + originalityDeclaration + = { thesis, title, ... }: + let + withTitle = "mit dem Titel \\textit{${title}}"; + followingWork + = if thesis.article == "den" + || thesis.article == "diesen" + then + "vorliegenden" + else + "vorliegende"; + in + [ + "Ich erkläre," + " dass ich ${thesis.article} ${followingWork} ${thesis.title}" + " ${withTitle}" + " selbstständig und ohne Benutzung anderer als der angegebenen Quellen und Hilfsmittel angefertigt habe.\\par" + "Die vorliegende Arbeit ist frei von Plagiaten. Alle Ausführungen, die wörtlich oder inhaltlich aus anderen Schriften entnommen sind," + " habe ich als solche kenntlich gemacht." + "Diese Arbeit wurde in gleicher oder ähnlicher Form noch nicht als Prüfungsleistung eingereicht und ist auch noch nicht veröffentlicht." + ]; + titlePage + = { authors, date, place, thesis, title, version, ... }: + [ + "\\centering" + "{\\Large ${thesis.organisation.department}} \\\\" + "{${thesis.organisation.group}} \\\\" + "{\\Huge ${title}} \\\\" + "{\\large ${thesis.title}} \\\\" + "{${string.concatWith ", " ( list.map formatAuthor authors )}}" + "\\vfill" + "\\begin{tabularx}{\\linewidth}{@{}lX@{}}" indentation.more + ] + ++ [ ( thesis.auditors or { title = ""; } ).title or "Prüfer" ] + ++ ( list.map thesis.formatAuthorTableLine ( thesis.auditors or { people = []; } ).people ) + ++ [ ( thesis.advisors or { title = ""; } ).title or "Betreuer" ] + ++ ( list.map thesis.formatAuthorTableLine ( thesis.advisors or { people = []; } ).people ) + ++ [ + "${thesisVersion version} & ${time.formatDate date "deu"} in ${place} \\\\" + indentation.less "\\end{tabularx}" + "\\clearpage" + ]; + } diff --git a/NixTeX/source/render/thesis/tex/titleMatter.nix b/NixTeX/source/render/thesis/tex/titleMatter.nix new file mode 100644 index 0000000..2ad4e22 --- /dev/null +++ b/NixTeX/source/render/thesis/tex/titleMatter.nix @@ -0,0 +1,35 @@ +{ context, core, thesis, ... }: + let + inherit(core) indentation list string time; + inherit(thesis) formatAuthor; + in + { authors, date, place, style, thesis, title, ... } @ document: + titleMatter: + let + authorList = string.concatWith ", " ( list.map formatAuthor authors ); + in + ( + [ + "{" indentation.more + "\\cleardoublepage" + "\\pagenumbering{roman}" + "\\renewcommand*\\chapterpagestyle{empty}" + "\\pagestyle{empty}" + "\\currentpdfbookmark{Titelseite}{titlepage}" + "\\begin{titlepage}" indentation.more + ] + ++ ( style.titlePage document ) + ++ [ + "~\\vfill" + "\\textbf{${authorList}}\\\\" + "{\\textit{${title}}}\\\\" + "${thesis.title}, ${thesis.organisation.department}\\\\" + "${thesis.organisation.name}, ${time.formatYearMonth date "deu"}" + "\\cleardoublepage" + ] + ++ titleMatter + ++ [ + indentation.less "\\end{titlepage}" + indentation.less "}" + ] + ) diff --git a/README.md b/README.md new file mode 100644 index 0000000..e69de29 diff --git a/home-manager/flake.nix b/home-manager/flake.nix new file mode 100644 index 0000000..b0963ac --- /dev/null +++ b/home-manager/flake.nix @@ -0,0 +1,20 @@ +{ + description = "Home-Manager"; + inputs + = { + home-manager.url = "github:nix-community/home-manager/master"; + libcore.url = "github:sivizius/nixfiles/development?dir=libs/core"; + }; + outputs + = { self, home-manager, libcore, ... }: + let + core = libcore.lib { inherit self; debug.logLevel = "info"; }; + inherit(core) path; + in + { + lib + = home-manager.lib + // ( path.import ./lib { inherit core; } ); + nixosModules = home-manager.nixosModules.default; + }; +} diff --git a/home-manager/lib/default.nix b/home-manager/lib/default.nix new file mode 100644 index 0000000..fcbf46c --- /dev/null +++ b/home-manager/lib/default.nix @@ -0,0 +1,9 @@ +{ core, ... } @ libs: + let + inherit(core) library; + in + library "homemanager" + libs + { + htop = ./htop.nix; + } diff --git a/home-manager/lib/htop.nix b/home-manager/lib/htop.nix new file mode 100644 index 0000000..4306410 --- /dev/null +++ b/home-manager/lib/htop.nix @@ -0,0 +1,135 @@ +{ core, ... }: + let + inherit(core) list string; + formatMeters + = side: + meters: + { + "${side}_meters" = list.map ({ name, ... }: name) meters; + "${side}_meter_modes" = list.map ({ mode, ... }: mode) meters; + }; + + leftMeters = formatMeters "left"; + rightMeters = formatMeters "right"; + + getNames = column: string.concatWith " " (list.map ({name, ... }: name) column); + getModes = column: string.concatWith " " (list.map ({mode, ... }: string mode) column); + toMeters + = header_layout: + columns: + ( + list.fold + ( + { index, result }: + column: + { + index = index + 1; + result + = result + // { + "column_meters_${string index}" + = getNames column; + "column_meter_modes_${string index}" + = getModes column; + }; + } + ) + { + index = 0; + result = { inherit header_layout; }; + } + columns + ).result; + + fields + = { + PID = 0; + COMM = 1; + STATE = 2; + PPID = 3; + PGRP = 4; + SESSION = 5; + TTY_NR = 6; + TPGID = 7; + MINFLT = 9; + MAJFLT = 11; + PRIORITY = 17; + NICE = 18; + STARTTIME = 20; + PROCESSOR = 37; + M_SIZE = 38; + M_RESIDENT = 39; + ST_UID = 45; + PERCENT_CPU = 46; + PERCENT_MEM = 47; + USER = 48; + TIME = 49; + NLWP = 50; + TGID = 51; + PERCENT_NORM_CPU = 52; + ELAPSED = 53; + CMINFLT = 10; + CMAJFLT = 12; + UTIME = 13; + STIME = 14; + CUTIME = 15; + CSTIME = 16; + M_SHARE = 40; + M_TRS = 41; + M_DRS = 42; + M_LRS = 43; + M_DT = 44; + CTID = 99; + VPID = 100; + VXID = 102; + RCHAR = 102; + WCHAR = 103; + SYSCR = 104; + SYSCW = 105; + RBYTES = 106; + WBYTES = 107; + CNCLWB = 108; + IO_READ_RATE = 109; + IO_WRITE_RATE = 110; + IO_RATE = 111; + CGROUP = 112; + OOM = 113; + IO_PRIORITY = 114; + M_PSS = 118; + M_SWAP = 119; + M_PSSWP = 120; + }; + + modes + = { + Bar = 1; + Text = 2; + Graph = 3; + LED = 4; + }; + + # Utilities for constructing meters + meter = mode: name: { inherit mode name; }; + bar = meter modes.Bar; + text = meter modes.Text; + graph = meter modes.Graph; + led = meter modes.LED; + blank = text "Blank"; + + layouts + = list.mapNamesToSet + ( + name: + { + __functor = { ... }: toMeters name; + } + ) + [ + "two_50_50" "two_33_67" "two_67_33" + "three_33_34_33" "three_25_25_50" "three_25_50_25" "three_50_25_25" "three_40_20_40" + "four_25_25_25_25" + ]; + in + { + inherit fields layouts modes leftMeters rightMeters meter bar text graph led blank; + } diff --git a/home-manager/nixos/default.nix b/home-manager/nixos/default.nix new file mode 100644 index 0000000..0e0dcd2 --- /dev/null +++ b/home-manager/nixos/default.nix @@ -0,0 +1,3 @@ +{ + +} \ No newline at end of file diff --git a/home-manager/options.nix b/home-manager/options.nix new file mode 100644 index 0000000..dc8f48d --- /dev/null +++ b/home-manager/options.nix @@ -0,0 +1,27 @@ +{ modules, ... }: + let + inherit(modules) options types; + literalExpression + = text: + { + _type = "literalExpression"; + inherit text; + }; + in + { + home-manager."sivizius" + = { + shell + = options.mkOption + { + type = types.nullOr types.shellPackage; + default = null; + defaultText = literalExpression "pkgs.zsh"; + description + = '' + The user’s shell derivations, like pkgs.zsh, + or null for system default. + ''; + }; + }; + } diff --git a/hosts/aleph/default.nix b/hosts/aleph/default.nix new file mode 100644 index 0000000..99dc9c6 --- /dev/null +++ b/hosts/aleph/default.nix @@ -0,0 +1,80 @@ +#![in_scope(Host, XFS, VFAT)] +{ peers, profiles, users, ... }: + Host "aleph (a silent letter in hebrew) is usually installed as sivizius on sivizius.eu" + { + config + = [ + ./homepage + ./mail.nix + ]; + devices + = { + "/" = XFS "system" { uuid = "2c26bb06-d932-486d-b48b-365d6cfc076e"; }; + "/boot" = VFAT "boot" { uuid = "F276-B461"; }; + }; + network + = let + IP = "2a01:4f9:c010:6bf5::23"; + legacyIP = "95.217.131.201"; + in + { + domain = "sivizius.eu"; + allowLegacyTLS = true; + interfaces.ens3 + = { + ipv6.addresses + = [ + { + address = IP; + prefixLength = 64; + } + ]; + useDHCP = true; + }; + ips + = [ + legacyIP + "${IP}/64" + ]; + peers + = with peers; + [ + fluepke.wireguard + google + hetzner + petabytedev + ]; + tcp.ports + = { + dns = 53; + exporters + = { + bind = 9119; + nginx = 9113; + node = 9100; + }; + gitea + = { + http = 3000; + ssh = 2222; + }; + grafana = 3001; + http = 80; + https = 443; + initrd.ssh = 2222; + prometheus = 9090; + }; + udp.ports + = { + dns = 53; + }; + }; + profile = profiles.hetznerCloudServer; + system = "x86_64-linux"; + users + = { + sivizius = users.sivizius // { trusted = true; }; + }; + version = "23.05"; + } + diff --git a/hosts/aleph/homepage/default.nix b/hosts/aleph/homepage/default.nix new file mode 100644 index 0000000..7599999 --- /dev/null +++ b/hosts/aleph/homepage/default.nix @@ -0,0 +1,39 @@ +{ core, web, ... } @ libs: + let + inherit(core) debug set; + inherit(web) html; + www."/" + = { + root + = { + "index.html" + = html { language = "eng"; } + { + head + = { + title = "Sivi’s Homepage"; + }; + body + = with html; + [ + ( + main + [ + (h1 "Hello World") + (p "How are you doing?") + ] + ) + ]; + }; + }; + }; + in + debug.warn "homepage" + { + text = "homepage"; + data = www; + nice = true; + } + { + websites = { inherit www; "" = www; }; + } diff --git a/hosts/aleph/mail.nix b/hosts/aleph/mail.nix new file mode 100644 index 0000000..7a5edef --- /dev/null +++ b/hosts/aleph/mail.nix @@ -0,0 +1,31 @@ +{ host, secret, ... }: +{ + mailserver.loginAccounts + = let + inherit(host.network) domain; + in + { + "root@${domain}" + = { + aliases + = [ + "cert${domain}" # Certificates related issues + "dmarc${domain}" # Domain-based Message Authentication, Reporting and Conformance + "dns${domain}" # Domain Name System related issues + ]; + catchAll + = [ + "${domain}" + ]; + hashedPasswordFile = secret.decrypt { encryptedFile = ./root-at-sivizius.eu.asc; owner = "dovecot2"; }; + sieveScript = ''''; + }; + + "sivizius@${domain}" + = { + hashedPasswordFile = secret.decrypt { encryptedFile = ./sivizius-at-sivizius.eu.asc; owner = "dovecot2"; }; + quota = "10G"; + sieveScript = ''''; + }; + }; +} \ No newline at end of file diff --git a/hosts/aleph/root-at-sivizius.eu.asc b/hosts/aleph/root-at-sivizius.eu.asc new file mode 100644 index 0000000..058dbea --- /dev/null +++ b/hosts/aleph/root-at-sivizius.eu.asc @@ -0,0 +1,10 @@ +-----BEGIN PGP MESSAGE----- + +hF4DQpmXgCyyA4oSAQdAhIYtFLQFFU//h1ZwHbnbbTHmZ91D2d9TdwBAeY00VyIw +uItoR9OQ183Fwwe3lfq4j6NddrYIxSU/as1RI4Zua+MJYyJpcFAsRLbtaMRolgUP +0q8BDo+gCLfD7+ozN0k8m5pzVLrV8hUs0+YNh+hTgAv7px8HPP0JOStLw9IGuwvh +phgkcCeUwf8Xj4RTuQ3QbSOK8Qki3KdfAt2E8W7lEhHQrDSj2DSKDCQvbw0ICWd4 +Xc6p9Fblz5QQVXs/3QcyN6z7XK//bPtdRq31IiEixWnQ1ok+nuJ1bWQP6RIK9piz +Kljdm/Ih1xgklwJptYSDxUJS+18aoOE8odaKhuk8P14v +=IJLh +-----END PGP MESSAGE----- diff --git a/hosts/aleph/sivizius-at-sivizius.eu.asc b/hosts/aleph/sivizius-at-sivizius.eu.asc new file mode 100644 index 0000000..671df7c --- /dev/null +++ b/hosts/aleph/sivizius-at-sivizius.eu.asc @@ -0,0 +1,10 @@ +-----BEGIN PGP MESSAGE----- + +hF4DQpmXgCyyA4oSAQdAExpyMAtuypBRkOWEOC7LDBtx6UPfhKjnwW8Tk9Lc228w +Vrsji4DWUEqIiBOiMOccy+WnaUBISGQWx7rx5gzj4KG1EH+Xj+CSWptLa452n8Z3 +0rMBs51AQukzVO+Lqz5gmFgRKfLuPeZVebSeJoqlg/GiZvIzmkPQ6KAoPfdiVuxA +/+fs8J6t3GqSJ3WXIkCxVVF8ZnfslWvzJd1Q0Cietb/APoW96Ax10O7CjPIuO01D +4qNlMAWpxSWvGkr5nh/hRAtIl9F2Mqan0PFQ4buuodkIqDpqRzBfotq68uQfMg7O +eiUyJn+mwyNomf5jzaDzRttbf+vKP0DYzqMpj+jBHcvzFXb9kw== +=7/Vh +-----END PGP MESSAGE----- diff --git a/hosts/aleph/vault.asc b/hosts/aleph/vault.asc new file mode 100644 index 0000000..3af54b3 --- /dev/null +++ b/hosts/aleph/vault.asc @@ -0,0 +1,13 @@ +-----BEGIN PGP PUBLIC KEY BLOCK----- + +mDMEZCHyvBYJKwYBBAHaRw8BAQdA9+9HRDkHTzzvMHdfkjcgItZqV8wdS4WoxQ7j +3j5hp8u0GWFsZXBoIChkZWZhdWx0IHZhdWx0LWtleSmIhwQTFggALxYhBL76V+uH +ZekrwAR2GRVvekntn0ULBQJkIfK8AhsjAgsJAhUKAhYAAh4BAheAAAoJEBVveknt +n0ULTWYA/24vU1uLjD29O9MyxWCtx23vj5YvUqqV+HBYzP3kH9Q1AP0V/qw3H4Tg +tTRvbiJbNa8OrG/xPkizM1Goo4/OAcAAB7g4BGQh8rwSCisGAQQBl1UBBQEBB0BS +YQvZkhoaBR1xAobMqotZMjwtPlQWyicuoVAqYOvyTQMBCAeIeAQYFggAIBYhBL76 +V+uHZekrwAR2GRVvekntn0ULBQJkIfK8AhsMAAoJEBVvekntn0ULk5IBAKYiHm0E +VB1RtN4hUVPI2hmrxjHuLUp3tWZiwhaOKnhNAQCl+5lwkH6Zzdg5H7LP2u4qudDH +wgI00BQvLDGMS4XrBg== +=Jext +-----END PGP PUBLIC KEY BLOCK----- \ No newline at end of file diff --git a/hosts/bet/blog.nix b/hosts/bet/blog.nix new file mode 100644 index 0000000..bee7311 --- /dev/null +++ b/hosts/bet/blog.nix @@ -0,0 +1,94 @@ +{ + sivis-blog + = { + enable = true; + title = "Sivis Blog"; + articles + = [ + { + title = "Über dieses Blog hinaus!"; + author = "sivizius"; + abstract + = '' + Das ist ein Artikel! + ''; + text + = '' + Hallo Welt! + =========== + + Wie geht es ~~dir~~ __euch__? + Ich habe `schon` **so viel** von //dir// gehört! + Eigentlich ##nicht## so viel. + + Das ist eine Liste: + >(URL) Block + : quote + >{Quellenangabe} Nested + : Block + : Quote + : Back + * 0 ABC + : abc + : : Indent! + : : More! + * 1 KLM + : klm + : *(2 NOP) 2 NOPE + : : nope + : : *{Summary} Details + : : : More Details + : k-l-m + *(3 QRS) 3 TUV + : tüv + * 4 123 + : eins zwei drei + *(5 456) 5 789 + : sieben acht neun + : * 6 XYZ + : : xyz + : 7-8-9 a + * hä + + Das ist ein Bild: + + Das ist die Bildbeschreibung + ![Alternativtext](https://external-preview.redd.it/Di9l4ORXUByiHfllJcxQkNqywSTAuhtmQWEbF2iwFKw.jpg?width=640&crop=smart&auto=webp&s=4fbed222b8ec30df5ad29448ebb42b7e02ed145e Titeltext) + + Das ist Code: + ```rust + fn foo(bar: usize) -> ! { + let mut counter = 0; + while true { + println!("Counter: {}", counter); + counter += 1; + } + } + ``` + + $$$ + 1 + 2 + f(x)..."Hello World" + f(x) = a*x^2 + b*x + c + f(x) = 0 <=> x = (-b+-sqrt(b^2-4ac))/(2a) + exp(ix) = cos(x) + i sin(x) + int(1/(1+ax) dx) = 1/a ln(1+ax) + C + e^z = lim_(n->inf)(1+z/n)^(n+0) + $$$ + ''; + } + ]; + authors + = { + "sivizius".name = "Sebastian Walz"; + }; + }; +} +/* +f(x)..."Hello World" + f(x) = a*x^2 + b*x + c + f(x) = 0 <=> x = (-b+-$sqrt(b^2-4ac))/(2a) + $exp(i x) = $cos(x) + i$sin(x) + $int((dx)/(1+ax)) = 1/a $ln(1+ax) + C + e^z = $lim_(n->$inf)(1+z/n)^n + */ \ No newline at end of file diff --git a/hosts/bet/default.nix b/hosts/bet/default.nix new file mode 100644 index 0000000..e58e705 --- /dev/null +++ b/hosts/bet/default.nix @@ -0,0 +1,47 @@ +{ peers, profiles, users, ... }: + Host "bet (from hebrew בית: house) is usually installed on localhost." + { + devices + = { + "/" = XFS "system" { uuid = "6ec7d726-6ef6-4e86-b382-2b4b6933f3e9"; }; + "/boot" = VFAT "boot" { uuid = "C7DE-E0D7"; }; + "swap" = Swap { uuid = "d7553993-772b-4979-abae-9127c65bdb05"; }; + }; + network + = { + interfaces + = { + enp0s25.useDHCP = true; + wlp3s0.useDHCP = true; + # wwp0s20u4i6.useDHCP = true; + }; + peers + = with peers; + [ + chaos + deutsche-bahn + eduroam + fluepke + mum + sivizius + tuc + ]; + tcp.ports + = { + http = 8080; + }; + wireless + = { + enable = true; + interfaces = [ "wlp3s0" ]; + userControlled.enable = true; + }; + }; + profile = profiles.desktop; + system = "x86_64-linux"; + users + = { + sivizius = users.sivizius // { trusted = true; }; + }; + version = "23.05"; + } diff --git a/hosts/bet/vault.asc b/hosts/bet/vault.asc new file mode 100644 index 0000000..8608990 --- /dev/null +++ b/hosts/bet/vault.asc @@ -0,0 +1,13 @@ +-----BEGIN PGP PUBLIC KEY BLOCK----- + +mDMEZCG1uxYJKwYBBAHaRw8BAQdA2b23xnipjdHPB2XIGGUHGTX02S9d21Vok/N8 +rTF8JQO0F2JldCAoZGVmYXVsdCB2YXVsdC1rZXkpiIcEExYKAC8WIQQ+1lDh4QlV +lhXhfo4gh5VXpoGRFwUCZCG1uwIbIwILCQIVCgIWAAIeBQIXgAAKCRAgh5VXpoGR +FzA9APwOXniezzpTkJNWDMm2FcbKuWmBogGWj0fh70o4X8mTdwD9Ezddk4Qi9pQH +0hgOpO0YpVEJf0Gn/0enIZt5uP7d7w24OARkIbW7EgorBgEEAZdVAQUBAQdAYs8R ++TVa7mo5y2a8fSQeYBYsEcuHYJ4qcEVMH5U9miMDAQgHiHgEGBYKACAWIQQ+1lDh +4QlVlhXhfo4gh5VXpoGRFwUCZCG1uwIbDAAKCRAgh5VXpoGRFw2DAQDyaMWbd3Vw +pYh5WpEjhnyKDoqdRFgSvMMN4LBxgsS1uwEA+Ib4kCDkmMkUJoWv7uWMa4737261 +HQuG4dpqvhguDw0= +=Dk3y +-----END PGP PUBLIC KEY BLOCK----- diff --git a/hosts/default.nix b/hosts/default.nix new file mode 100644 index 0000000..e9734b3 --- /dev/null +++ b/hosts/default.nix @@ -0,0 +1,4 @@ +{ + aleph = ./aleph; + bet = ./bet; +} diff --git a/hosts/flake.lock b/hosts/flake.lock new file mode 100644 index 0000000..1a30385 --- /dev/null +++ b/hosts/flake.lock @@ -0,0 +1,3806 @@ +{ + "nodes": { + "blobs": { + "flake": false, + "locked": { + "lastModified": 1604995301, + "narHash": "sha256-wcLzgLec6SGJA8fx1OEN1yV/Py5b+U5iyYpksUY/yLw=", + "owner": "simple-nixos-mailserver", + "repo": "blobs", + "rev": "2cccdf1ca48316f2cfd1c9a0017e8de5a7156265", + "type": "gitlab" + }, + "original": { + "owner": "simple-nixos-mailserver", + "repo": "blobs", + "type": "gitlab" + } + }, + "flake-compat": { + "flake": false, + "locked": { + "lastModified": 1668681692, + "narHash": "sha256-Ht91NGdewz8IQLtWZ9LCeNXMSXHUss+9COoqu6JLmXU=", + "owner": "edolstra", + "repo": "flake-compat", + "rev": "009399224d5e398d03b22badca40a37ac85412a1", + "type": "github" + }, + "original": { + "owner": "edolstra", + "repo": "flake-compat", + "type": "github" + } + }, + "flake-compat_2": { + "flake": false, + "locked": { + "lastModified": 1673956053, + "narHash": "sha256-4gtG9iQuiKITOjNQQeQIpoIB6b16fm+504Ch3sNKLd8=", + "owner": "edolstra", + "repo": "flake-compat", + "rev": "35bb57c0c8d8b62bbfd284272c928ceb64ddbde9", + "type": "github" + }, + "original": { + "owner": "edolstra", + "repo": "flake-compat", + "type": "github" + } + }, + "fork-awesome": { + "inputs": { + "libcore": "libcore_38", + "nixpkgs": "nixpkgs_31" + }, + "locked": { + "dir": "packages/fork-awesome", + "lastModified": 1681394603, + "narHash": "sha256-dVqGLk+tARfFNrSvOXBkAvvPtOqcbTyr9sLFVJieZUw=", + "type": "git", + "url": "file:///home/sivizius/Projects/Active/nixfiles?dir=packages%2ffork-awesome" + }, + "original": { + "dir": "packages/fork-awesome", + "owner": "sivizius", + "ref": "development", + "repo": "nixfiles", + "type": "github" + } + }, + "home-manager": { + "inputs": { + "home-manager": "home-manager_2", + "libcore": "libcore" + }, + "locked": { + "dir": "home-manager", + "lastModified": 1681394603, + "narHash": "sha256-dVqGLk+tARfFNrSvOXBkAvvPtOqcbTyr9sLFVJieZUw=", + "type": "git", + "url": "file:///home/sivizius/Projects/Active/nixfiles?dir=home-manager" + }, + "original": { + "dir": "home-manager", + "owner": "sivizius", + "ref": "development", + "repo": "nixfiles", + "type": "github" + } + }, + "home-manager_2": { + "inputs": { + "nixpkgs": "nixpkgs", + "utils": "utils" + }, + "locked": { + "lastModified": 1680597706, + "narHash": "sha256-ZqJ3T+BxzjPH9TnmeUwS4Uu9ZQPeBXAFC9sUWlharT4=", + "owner": "nix-community", + "repo": "home-manager", + "rev": "ec06f419af79207b33d797064dfb3fc9dbe1df4a", + "type": "github" + }, + "original": { + "owner": "nix-community", + "ref": "master", + "repo": "home-manager", + "type": "github" + } + }, + "home-manager_3": { + "inputs": { + "nixpkgs": "nixpkgs_9", + "utils": "utils_2" + }, + "locked": { + "lastModified": 1680597706, + "narHash": "sha256-ZqJ3T+BxzjPH9TnmeUwS4Uu9ZQPeBXAFC9sUWlharT4=", + "owner": "nix-community", + "repo": "home-manager", + "rev": "ec06f419af79207b33d797064dfb3fc9dbe1df4a", + "type": "github" + }, + "original": { + "owner": "nix-community", + "ref": "master", + "repo": "home-manager", + "type": "github" + } + }, + "libconfig": { + "inputs": { + "libcore": "libcore_2", + "libsecrets": "libsecrets", + "libstore": "libstore_2", + "libweb": "libweb", + "nixpkgs": "nixpkgs_5" + }, + "locked": { + "dir": "libs/config", + "lastModified": 1681394603, + "narHash": "sha256-dVqGLk+tARfFNrSvOXBkAvvPtOqcbTyr9sLFVJieZUw=", + "type": "git", + "url": "file:///home/sivizius/Projects/Active/nixfiles?dir=libs%2fconfig" + }, + "original": { + "dir": "libs/config", + "owner": "sivizius", + "ref": "development", + "repo": "nixfiles", + "type": "github" + } + }, + "libconfig_2": { + "inputs": { + "libcore": "libcore_12", + "libsecrets": "libsecrets_3", + "libstore": "libstore_6", + "libweb": "libweb_3", + "nixpkgs": "nixpkgs_13" + }, + "locked": { + "dir": "libs/config", + "lastModified": 1681394603, + "narHash": "sha256-dVqGLk+tARfFNrSvOXBkAvvPtOqcbTyr9sLFVJieZUw=", + "type": "git", + "url": "file:///home/sivizius/Projects/Active/nixfiles?dir=libs%2fconfig" + }, + "original": { + "dir": "libs/config", + "owner": "sivizius", + "ref": "development", + "repo": "nixfiles", + "type": "github" + } + }, + "libconfig_3": { + "inputs": { + "libcore": "libcore_18", + "libsecrets": "libsecrets_4", + "libstore": "libstore_8", + "libweb": "libweb_4", + "nixpkgs": "nixpkgs_19" + }, + "locked": { + "dir": "libs/config", + "lastModified": 1681394603, + "narHash": "sha256-dVqGLk+tARfFNrSvOXBkAvvPtOqcbTyr9sLFVJieZUw=", + "type": "git", + "url": "file:///home/sivizius/Projects/Active/nixfiles?dir=libs%2fconfig" + }, + "original": { + "dir": "libs/config", + "owner": "sivizius", + "ref": "development", + "repo": "nixfiles", + "type": "github" + } + }, + "libconfig_4": { + "inputs": { + "libcore": "libcore_26", + "libsecrets": "libsecrets_6", + "libstore": "libstore_11", + "libweb": "libweb_5", + "nixpkgs": "nixpkgs_24" + }, + "locked": { + "dir": "libs/config", + "lastModified": 1681394603, + "narHash": "sha256-dVqGLk+tARfFNrSvOXBkAvvPtOqcbTyr9sLFVJieZUw=", + "type": "git", + "url": "file:///home/sivizius/Projects/Active/nixfiles?dir=libs%2fconfig" + }, + "original": { + "dir": "libs/config", + "owner": "sivizius", + "ref": "development", + "repo": "nixfiles", + "type": "github" + } + }, + "libconfig_5": { + "inputs": { + "libcore": "libcore_32", + "libsecrets": "libsecrets_7", + "libstore": "libstore_13", + "libweb": "libweb_6", + "nixpkgs": "nixpkgs_29" + }, + "locked": { + "dir": "libs/config", + "lastModified": 1681394603, + "narHash": "sha256-dVqGLk+tARfFNrSvOXBkAvvPtOqcbTyr9sLFVJieZUw=", + "type": "git", + "url": "file:///home/sivizius/Projects/Active/nixfiles?dir=libs%2fconfig" + }, + "original": { + "dir": "libs/config", + "owner": "sivizius", + "ref": "development", + "repo": "nixfiles", + "type": "github" + } + }, + "libconfig_6": { + "inputs": { + "libcore": "libcore_39", + "libsecrets": "libsecrets_8", + "libstore": "libstore_15", + "libweb": "libweb_8", + "nixpkgs": "nixpkgs_35" + }, + "locked": { + "dir": "libs/config", + "lastModified": 1681394603, + "narHash": "sha256-dVqGLk+tARfFNrSvOXBkAvvPtOqcbTyr9sLFVJieZUw=", + "type": "git", + "url": "file:///home/sivizius/Projects/Active/nixfiles?dir=libs%2fconfig" + }, + "original": { + "dir": "libs/config", + "owner": "sivizius", + "ref": "development", + "repo": "nixfiles", + "type": "github" + } + }, + "libconfig_7": { + "inputs": { + "libcore": "libcore_47", + "libsecrets": "libsecrets_9", + "libstore": "libstore_17", + "libweb": "libweb_9", + "nixpkgs": "nixpkgs_43" + }, + "locked": { + "dir": "libs/config", + "lastModified": 1681394603, + "narHash": "sha256-dVqGLk+tARfFNrSvOXBkAvvPtOqcbTyr9sLFVJieZUw=", + "type": "git", + "url": "file:///home/sivizius/Projects/Active/nixfiles?dir=libs%2fconfig" + }, + "original": { + "dir": "libs/config", + "owner": "sivizius", + "ref": "development", + "repo": "nixfiles", + "type": "github" + } + }, + "libcore": { + "inputs": { + "libintrinsics": "libintrinsics" + }, + "locked": { + "dir": "libs/core", + "lastModified": 1681394603, + "narHash": "sha256-dVqGLk+tARfFNrSvOXBkAvvPtOqcbTyr9sLFVJieZUw=", + "type": "git", + "url": "file:///home/sivizius/Projects/Active/nixfiles?dir=libs%2fcore" + }, + "original": { + "dir": "libs/core", + "owner": "sivizius", + "ref": "development", + "repo": "nixfiles", + "type": "github" + } + }, + "libcore_10": { + "inputs": { + "libintrinsics": "libintrinsics_10" + }, + "locked": { + "dir": "libs/core", + "lastModified": 1681394603, + "narHash": "sha256-dVqGLk+tARfFNrSvOXBkAvvPtOqcbTyr9sLFVJieZUw=", + "type": "git", + "url": "file:///home/sivizius/Projects/Active/nixfiles?dir=libs%2fcore" + }, + "original": { + "dir": "libs/core", + "owner": "sivizius", + "ref": "development", + "repo": "nixfiles", + "type": "github" + } + }, + "libcore_11": { + "inputs": { + "libintrinsics": "libintrinsics_11" + }, + "locked": { + "dir": "libs/core", + "lastModified": 1681394603, + "narHash": "sha256-dVqGLk+tARfFNrSvOXBkAvvPtOqcbTyr9sLFVJieZUw=", + "type": "git", + "url": "file:///home/sivizius/Projects/Active/nixfiles?dir=libs%2fcore" + }, + "original": { + "dir": "libs/core", + "owner": "sivizius", + "ref": "development", + "repo": "nixfiles", + "type": "github" + } + }, + "libcore_12": { + "inputs": { + "libintrinsics": "libintrinsics_12" + }, + "locked": { + "dir": "libs/core", + "lastModified": 1681394603, + "narHash": "sha256-dVqGLk+tARfFNrSvOXBkAvvPtOqcbTyr9sLFVJieZUw=", + "type": "git", + "url": "file:///home/sivizius/Projects/Active/nixfiles?dir=libs%2fcore" + }, + "original": { + "dir": "libs/core", + "owner": "sivizius", + "ref": "development", + "repo": "nixfiles", + "type": "github" + } + }, + "libcore_13": { + "inputs": { + "libintrinsics": "libintrinsics_13" + }, + "locked": { + "dir": "libs/core", + "lastModified": 1681394603, + "narHash": "sha256-dVqGLk+tARfFNrSvOXBkAvvPtOqcbTyr9sLFVJieZUw=", + "type": "git", + "url": "file:///home/sivizius/Projects/Active/nixfiles?dir=libs%2fcore" + }, + "original": { + "dir": "libs/core", + "owner": "sivizius", + "ref": "development", + "repo": "nixfiles", + "type": "github" + } + }, + "libcore_14": { + "inputs": { + "libintrinsics": "libintrinsics_14" + }, + "locked": { + "dir": "libs/core", + "lastModified": 1681394603, + "narHash": "sha256-dVqGLk+tARfFNrSvOXBkAvvPtOqcbTyr9sLFVJieZUw=", + "type": "git", + "url": "file:///home/sivizius/Projects/Active/nixfiles?dir=libs%2fcore" + }, + "original": { + "dir": "libs/core", + "owner": "sivizius", + "ref": "development", + "repo": "nixfiles", + "type": "github" + } + }, + "libcore_15": { + "inputs": { + "libintrinsics": "libintrinsics_15" + }, + "locked": { + "dir": "libs/core", + "lastModified": 1681394603, + "narHash": "sha256-dVqGLk+tARfFNrSvOXBkAvvPtOqcbTyr9sLFVJieZUw=", + "type": "git", + "url": "file:///home/sivizius/Projects/Active/nixfiles?dir=libs%2fcore" + }, + "original": { + "dir": "libs/core", + "owner": "sivizius", + "ref": "development", + "repo": "nixfiles", + "type": "github" + } + }, + "libcore_16": { + "inputs": { + "libintrinsics": "libintrinsics_16" + }, + "locked": { + "dir": "libs/core", + "lastModified": 1681394603, + "narHash": "sha256-dVqGLk+tARfFNrSvOXBkAvvPtOqcbTyr9sLFVJieZUw=", + "type": "git", + "url": "file:///home/sivizius/Projects/Active/nixfiles?dir=libs%2fcore" + }, + "original": { + "dir": "libs/core", + "owner": "sivizius", + "ref": "development", + "repo": "nixfiles", + "type": "github" + } + }, + "libcore_17": { + "inputs": { + "libintrinsics": "libintrinsics_17" + }, + "locked": { + "dir": "libs/core", + "lastModified": 1681394603, + "narHash": "sha256-dVqGLk+tARfFNrSvOXBkAvvPtOqcbTyr9sLFVJieZUw=", + "type": "git", + "url": "file:///home/sivizius/Projects/Active/nixfiles?dir=libs%2fcore" + }, + "original": { + "dir": "libs/core", + "owner": "sivizius", + "ref": "development", + "repo": "nixfiles", + "type": "github" + } + }, + "libcore_18": { + "inputs": { + "libintrinsics": "libintrinsics_18" + }, + "locked": { + "dir": "libs/core", + "lastModified": 1681394603, + "narHash": "sha256-dVqGLk+tARfFNrSvOXBkAvvPtOqcbTyr9sLFVJieZUw=", + "type": "git", + "url": "file:///home/sivizius/Projects/Active/nixfiles?dir=libs%2fcore" + }, + "original": { + "dir": "libs/core", + "owner": "sivizius", + "ref": "development", + "repo": "nixfiles", + "type": "github" + } + }, + "libcore_19": { + "inputs": { + "libintrinsics": "libintrinsics_19" + }, + "locked": { + "dir": "libs/core", + "lastModified": 1681394603, + "narHash": "sha256-dVqGLk+tARfFNrSvOXBkAvvPtOqcbTyr9sLFVJieZUw=", + "type": "git", + "url": "file:///home/sivizius/Projects/Active/nixfiles?dir=libs%2fcore" + }, + "original": { + "dir": "libs/core", + "owner": "sivizius", + "ref": "development", + "repo": "nixfiles", + "type": "github" + } + }, + "libcore_2": { + "inputs": { + "libintrinsics": "libintrinsics_2" + }, + "locked": { + "dir": "libs/core", + "lastModified": 1681394603, + "narHash": "sha256-dVqGLk+tARfFNrSvOXBkAvvPtOqcbTyr9sLFVJieZUw=", + "type": "git", + "url": "file:///home/sivizius/Projects/Active/nixfiles?dir=libs%2fcore" + }, + "original": { + "dir": "libs/core", + "owner": "sivizius", + "ref": "development", + "repo": "nixfiles", + "type": "github" + } + }, + "libcore_20": { + "inputs": { + "libintrinsics": "libintrinsics_20" + }, + "locked": { + "dir": "libs/core", + "lastModified": 1681394603, + "narHash": "sha256-dVqGLk+tARfFNrSvOXBkAvvPtOqcbTyr9sLFVJieZUw=", + "type": "git", + "url": "file:///home/sivizius/Projects/Active/nixfiles?dir=libs%2fcore" + }, + "original": { + "dir": "libs/core", + "owner": "sivizius", + "ref": "development", + "repo": "nixfiles", + "type": "github" + } + }, + "libcore_21": { + "inputs": { + "libintrinsics": "libintrinsics_21" + }, + "locked": { + "dir": "libs/core", + "lastModified": 1681394603, + "narHash": "sha256-dVqGLk+tARfFNrSvOXBkAvvPtOqcbTyr9sLFVJieZUw=", + "type": "git", + "url": "file:///home/sivizius/Projects/Active/nixfiles?dir=libs%2fcore" + }, + "original": { + "dir": "libs/core", + "owner": "sivizius", + "ref": "development", + "repo": "nixfiles", + "type": "github" + } + }, + "libcore_22": { + "inputs": { + "libintrinsics": "libintrinsics_22" + }, + "locked": { + "dir": "libs/core", + "lastModified": 1681394603, + "narHash": "sha256-dVqGLk+tARfFNrSvOXBkAvvPtOqcbTyr9sLFVJieZUw=", + "type": "git", + "url": "file:///home/sivizius/Projects/Active/nixfiles?dir=libs%2fcore" + }, + "original": { + "dir": "libs/core", + "owner": "sivizius", + "ref": "development", + "repo": "nixfiles", + "type": "github" + } + }, + "libcore_23": { + "inputs": { + "libintrinsics": "libintrinsics_23" + }, + "locked": { + "dir": "libs/core", + "lastModified": 1681394603, + "narHash": "sha256-dVqGLk+tARfFNrSvOXBkAvvPtOqcbTyr9sLFVJieZUw=", + "type": "git", + "url": "file:///home/sivizius/Projects/Active/nixfiles?dir=libs%2fcore" + }, + "original": { + "dir": "libs/core", + "owner": "sivizius", + "ref": "development", + "repo": "nixfiles", + "type": "github" + } + }, + "libcore_24": { + "inputs": { + "libintrinsics": "libintrinsics_24" + }, + "locked": { + "dir": "libs/core", + "lastModified": 1681394603, + "narHash": "sha256-dVqGLk+tARfFNrSvOXBkAvvPtOqcbTyr9sLFVJieZUw=", + "type": "git", + "url": "file:///home/sivizius/Projects/Active/nixfiles?dir=libs%2fcore" + }, + "original": { + "dir": "libs/core", + "owner": "sivizius", + "ref": "development", + "repo": "nixfiles", + "type": "github" + } + }, + "libcore_25": { + "inputs": { + "libintrinsics": "libintrinsics_25" + }, + "locked": { + "dir": "libs/core", + "lastModified": 1681394603, + "narHash": "sha256-dVqGLk+tARfFNrSvOXBkAvvPtOqcbTyr9sLFVJieZUw=", + "type": "git", + "url": "file:///home/sivizius/Projects/Active/nixfiles?dir=libs%2fcore" + }, + "original": { + "dir": "libs/core", + "owner": "sivizius", + "ref": "development", + "repo": "nixfiles", + "type": "github" + } + }, + "libcore_26": { + "inputs": { + "libintrinsics": "libintrinsics_26" + }, + "locked": { + "dir": "libs/core", + "lastModified": 1681394603, + "narHash": "sha256-dVqGLk+tARfFNrSvOXBkAvvPtOqcbTyr9sLFVJieZUw=", + "type": "git", + "url": "file:///home/sivizius/Projects/Active/nixfiles?dir=libs%2fcore" + }, + "original": { + "dir": "libs/core", + "owner": "sivizius", + "ref": "development", + "repo": "nixfiles", + "type": "github" + } + }, + "libcore_27": { + "inputs": { + "libintrinsics": "libintrinsics_27" + }, + "locked": { + "dir": "libs/core", + "lastModified": 1681394603, + "narHash": "sha256-dVqGLk+tARfFNrSvOXBkAvvPtOqcbTyr9sLFVJieZUw=", + "type": "git", + "url": "file:///home/sivizius/Projects/Active/nixfiles?dir=libs%2fcore" + }, + "original": { + "dir": "libs/core", + "owner": "sivizius", + "ref": "development", + "repo": "nixfiles", + "type": "github" + } + }, + "libcore_28": { + "inputs": { + "libintrinsics": "libintrinsics_28" + }, + "locked": { + "dir": "libs/core", + "lastModified": 1681394603, + "narHash": "sha256-dVqGLk+tARfFNrSvOXBkAvvPtOqcbTyr9sLFVJieZUw=", + "type": "git", + "url": "file:///home/sivizius/Projects/Active/nixfiles?dir=libs%2fcore" + }, + "original": { + "dir": "libs/core", + "owner": "sivizius", + "ref": "development", + "repo": "nixfiles", + "type": "github" + } + }, + "libcore_29": { + "inputs": { + "libintrinsics": "libintrinsics_29" + }, + "locked": { + "dir": "libs/core", + "lastModified": 1681394603, + "narHash": "sha256-dVqGLk+tARfFNrSvOXBkAvvPtOqcbTyr9sLFVJieZUw=", + "type": "git", + "url": "file:///home/sivizius/Projects/Active/nixfiles?dir=libs%2fcore" + }, + "original": { + "dir": "libs/core", + "owner": "sivizius", + "ref": "development", + "repo": "nixfiles", + "type": "github" + } + }, + "libcore_3": { + "inputs": { + "libintrinsics": "libintrinsics_3" + }, + "locked": { + "dir": "libs/core", + "lastModified": 1681394603, + "narHash": "sha256-dVqGLk+tARfFNrSvOXBkAvvPtOqcbTyr9sLFVJieZUw=", + "type": "git", + "url": "file:///home/sivizius/Projects/Active/nixfiles?dir=libs%2fcore" + }, + "original": { + "dir": "libs/core", + "owner": "sivizius", + "ref": "development", + "repo": "nixfiles", + "type": "github" + } + }, + "libcore_30": { + "inputs": { + "libintrinsics": "libintrinsics_30" + }, + "locked": { + "dir": "libs/core", + "lastModified": 1681394603, + "narHash": "sha256-dVqGLk+tARfFNrSvOXBkAvvPtOqcbTyr9sLFVJieZUw=", + "type": "git", + "url": "file:///home/sivizius/Projects/Active/nixfiles?dir=libs%2fcore" + }, + "original": { + "dir": "libs/core", + "owner": "sivizius", + "ref": "development", + "repo": "nixfiles", + "type": "github" + } + }, + "libcore_31": { + "inputs": { + "libintrinsics": "libintrinsics_31" + }, + "locked": { + "dir": "libs/core", + "lastModified": 1681394603, + "narHash": "sha256-dVqGLk+tARfFNrSvOXBkAvvPtOqcbTyr9sLFVJieZUw=", + "type": "git", + "url": "file:///home/sivizius/Projects/Active/nixfiles?dir=libs%2fcore" + }, + "original": { + "dir": "libs/core", + "owner": "sivizius", + "ref": "development", + "repo": "nixfiles", + "type": "github" + } + }, + "libcore_32": { + "inputs": { + "libintrinsics": "libintrinsics_32" + }, + "locked": { + "dir": "libs/core", + "lastModified": 1681394603, + "narHash": "sha256-dVqGLk+tARfFNrSvOXBkAvvPtOqcbTyr9sLFVJieZUw=", + "type": "git", + "url": "file:///home/sivizius/Projects/Active/nixfiles?dir=libs%2fcore" + }, + "original": { + "dir": "libs/core", + "owner": "sivizius", + "ref": "development", + "repo": "nixfiles", + "type": "github" + } + }, + "libcore_33": { + "inputs": { + "libintrinsics": "libintrinsics_33" + }, + "locked": { + "dir": "libs/core", + "lastModified": 1681394603, + "narHash": "sha256-dVqGLk+tARfFNrSvOXBkAvvPtOqcbTyr9sLFVJieZUw=", + "type": "git", + "url": "file:///home/sivizius/Projects/Active/nixfiles?dir=libs%2fcore" + }, + "original": { + "dir": "libs/core", + "owner": "sivizius", + "ref": "development", + "repo": "nixfiles", + "type": "github" + } + }, + "libcore_34": { + "inputs": { + "libintrinsics": "libintrinsics_34" + }, + "locked": { + "dir": "libs/core", + "lastModified": 1681394603, + "narHash": "sha256-dVqGLk+tARfFNrSvOXBkAvvPtOqcbTyr9sLFVJieZUw=", + "type": "git", + "url": "file:///home/sivizius/Projects/Active/nixfiles?dir=libs%2fcore" + }, + "original": { + "dir": "libs/core", + "owner": "sivizius", + "ref": "development", + "repo": "nixfiles", + "type": "github" + } + }, + "libcore_35": { + "inputs": { + "libintrinsics": "libintrinsics_35" + }, + "locked": { + "dir": "libs/core", + "lastModified": 1681394603, + "narHash": "sha256-dVqGLk+tARfFNrSvOXBkAvvPtOqcbTyr9sLFVJieZUw=", + "type": "git", + "url": "file:///home/sivizius/Projects/Active/nixfiles?dir=libs%2fcore" + }, + "original": { + "dir": "libs/core", + "owner": "sivizius", + "ref": "development", + "repo": "nixfiles", + "type": "github" + } + }, + "libcore_36": { + "inputs": { + "libintrinsics": "libintrinsics_36" + }, + "locked": { + "dir": "libs/core", + "lastModified": 1681394603, + "narHash": "sha256-dVqGLk+tARfFNrSvOXBkAvvPtOqcbTyr9sLFVJieZUw=", + "type": "git", + "url": "file:///home/sivizius/Projects/Active/nixfiles?dir=libs%2fcore" + }, + "original": { + "dir": "libs/core", + "owner": "sivizius", + "ref": "development", + "repo": "nixfiles", + "type": "github" + } + }, + "libcore_37": { + "inputs": { + "libintrinsics": "libintrinsics_37" + }, + "locked": { + "dir": "libs/core", + "lastModified": 1681394603, + "narHash": "sha256-dVqGLk+tARfFNrSvOXBkAvvPtOqcbTyr9sLFVJieZUw=", + "type": "git", + "url": "file:///home/sivizius/Projects/Active/nixfiles?dir=libs%2fcore" + }, + "original": { + "dir": "libs/core", + "owner": "sivizius", + "ref": "development", + "repo": "nixfiles", + "type": "github" + } + }, + "libcore_38": { + "inputs": { + "libintrinsics": "libintrinsics_38" + }, + "locked": { + "dir": "libs/core", + "lastModified": 1681394603, + "narHash": "sha256-dVqGLk+tARfFNrSvOXBkAvvPtOqcbTyr9sLFVJieZUw=", + "type": "git", + "url": "file:///home/sivizius/Projects/Active/nixfiles?dir=libs%2fcore" + }, + "original": { + "dir": "libs/core", + "owner": "sivizius", + "ref": "development", + "repo": "nixfiles", + "type": "github" + } + }, + "libcore_39": { + "inputs": { + "libintrinsics": "libintrinsics_39" + }, + "locked": { + "dir": "libs/core", + "lastModified": 1681394603, + "narHash": "sha256-dVqGLk+tARfFNrSvOXBkAvvPtOqcbTyr9sLFVJieZUw=", + "type": "git", + "url": "file:///home/sivizius/Projects/Active/nixfiles?dir=libs%2fcore" + }, + "original": { + "dir": "libs/core", + "owner": "sivizius", + "ref": "development", + "repo": "nixfiles", + "type": "github" + } + }, + "libcore_4": { + "inputs": { + "libintrinsics": "libintrinsics_4" + }, + "locked": { + "dir": "libs/core", + "lastModified": 1681394603, + "narHash": "sha256-dVqGLk+tARfFNrSvOXBkAvvPtOqcbTyr9sLFVJieZUw=", + "type": "git", + "url": "file:///home/sivizius/Projects/Active/nixfiles?dir=libs%2fcore" + }, + "original": { + "dir": "libs/core", + "owner": "sivizius", + "ref": "development", + "repo": "nixfiles", + "type": "github" + } + }, + "libcore_40": { + "inputs": { + "libintrinsics": "libintrinsics_40" + }, + "locked": { + "dir": "libs/core", + "lastModified": 1681394603, + "narHash": "sha256-dVqGLk+tARfFNrSvOXBkAvvPtOqcbTyr9sLFVJieZUw=", + "type": "git", + "url": "file:///home/sivizius/Projects/Active/nixfiles?dir=libs%2fcore" + }, + "original": { + "dir": "libs/core", + "owner": "sivizius", + "ref": "development", + "repo": "nixfiles", + "type": "github" + } + }, + "libcore_41": { + "inputs": { + "libintrinsics": "libintrinsics_41" + }, + "locked": { + "dir": "libs/core", + "lastModified": 1681394603, + "narHash": "sha256-dVqGLk+tARfFNrSvOXBkAvvPtOqcbTyr9sLFVJieZUw=", + "type": "git", + "url": "file:///home/sivizius/Projects/Active/nixfiles?dir=libs%2fcore" + }, + "original": { + "dir": "libs/core", + "owner": "sivizius", + "ref": "development", + "repo": "nixfiles", + "type": "github" + } + }, + "libcore_42": { + "inputs": { + "libintrinsics": "libintrinsics_42" + }, + "locked": { + "dir": "libs/core", + "lastModified": 1681394603, + "narHash": "sha256-dVqGLk+tARfFNrSvOXBkAvvPtOqcbTyr9sLFVJieZUw=", + "type": "git", + "url": "file:///home/sivizius/Projects/Active/nixfiles?dir=libs%2fcore" + }, + "original": { + "dir": "libs/core", + "owner": "sivizius", + "ref": "development", + "repo": "nixfiles", + "type": "github" + } + }, + "libcore_43": { + "inputs": { + "libintrinsics": "libintrinsics_43" + }, + "locked": { + "dir": "libs/core", + "lastModified": 1681394603, + "narHash": "sha256-dVqGLk+tARfFNrSvOXBkAvvPtOqcbTyr9sLFVJieZUw=", + "type": "git", + "url": "file:///home/sivizius/Projects/Active/nixfiles?dir=libs%2fcore" + }, + "original": { + "dir": "libs/core", + "owner": "sivizius", + "ref": "development", + "repo": "nixfiles", + "type": "github" + } + }, + "libcore_44": { + "inputs": { + "libintrinsics": "libintrinsics_44" + }, + "locked": { + "dir": "libs/core", + "lastModified": 1681394603, + "narHash": "sha256-dVqGLk+tARfFNrSvOXBkAvvPtOqcbTyr9sLFVJieZUw=", + "type": "git", + "url": "file:///home/sivizius/Projects/Active/nixfiles?dir=libs%2fcore" + }, + "original": { + "dir": "libs/core", + "owner": "sivizius", + "ref": "development", + "repo": "nixfiles", + "type": "github" + } + }, + "libcore_45": { + "inputs": { + "libintrinsics": "libintrinsics_45" + }, + "locked": { + "dir": "libs/core", + "lastModified": 1681394603, + "narHash": "sha256-dVqGLk+tARfFNrSvOXBkAvvPtOqcbTyr9sLFVJieZUw=", + "type": "git", + "url": "file:///home/sivizius/Projects/Active/nixfiles?dir=libs%2fcore" + }, + "original": { + "dir": "libs/core", + "owner": "sivizius", + "ref": "development", + "repo": "nixfiles", + "type": "github" + } + }, + "libcore_46": { + "inputs": { + "libintrinsics": "libintrinsics_46" + }, + "locked": { + "dir": "libs/core", + "lastModified": 1681394603, + "narHash": "sha256-dVqGLk+tARfFNrSvOXBkAvvPtOqcbTyr9sLFVJieZUw=", + "type": "git", + "url": "file:///home/sivizius/Projects/Active/nixfiles?dir=libs%2fcore" + }, + "original": { + "dir": "libs/core", + "owner": "sivizius", + "ref": "development", + "repo": "nixfiles", + "type": "github" + } + }, + "libcore_47": { + "inputs": { + "libintrinsics": "libintrinsics_47" + }, + "locked": { + "dir": "libs/core", + "lastModified": 1681394603, + "narHash": "sha256-dVqGLk+tARfFNrSvOXBkAvvPtOqcbTyr9sLFVJieZUw=", + "type": "git", + "url": "file:///home/sivizius/Projects/Active/nixfiles?dir=libs%2fcore" + }, + "original": { + "dir": "libs/core", + "owner": "sivizius", + "ref": "development", + "repo": "nixfiles", + "type": "github" + } + }, + "libcore_48": { + "inputs": { + "libintrinsics": "libintrinsics_48" + }, + "locked": { + "dir": "libs/core", + "lastModified": 1681394603, + "narHash": "sha256-dVqGLk+tARfFNrSvOXBkAvvPtOqcbTyr9sLFVJieZUw=", + "type": "git", + "url": "file:///home/sivizius/Projects/Active/nixfiles?dir=libs%2fcore" + }, + "original": { + "dir": "libs/core", + "owner": "sivizius", + "ref": "development", + "repo": "nixfiles", + "type": "github" + } + }, + "libcore_49": { + "inputs": { + "libintrinsics": "libintrinsics_49" + }, + "locked": { + "dir": "libs/core", + "lastModified": 1681394603, + "narHash": "sha256-dVqGLk+tARfFNrSvOXBkAvvPtOqcbTyr9sLFVJieZUw=", + "type": "git", + "url": "file:///home/sivizius/Projects/Active/nixfiles?dir=libs%2fcore" + }, + "original": { + "dir": "libs/core", + "owner": "sivizius", + "ref": "development", + "repo": "nixfiles", + "type": "github" + } + }, + "libcore_5": { + "inputs": { + "libintrinsics": "libintrinsics_5" + }, + "locked": { + "dir": "libs/core", + "lastModified": 1681394603, + "narHash": "sha256-dVqGLk+tARfFNrSvOXBkAvvPtOqcbTyr9sLFVJieZUw=", + "type": "git", + "url": "file:///home/sivizius/Projects/Active/nixfiles?dir=libs%2fcore" + }, + "original": { + "dir": "libs/core", + "owner": "sivizius", + "ref": "development", + "repo": "nixfiles", + "type": "github" + } + }, + "libcore_50": { + "inputs": { + "libintrinsics": "libintrinsics_50" + }, + "locked": { + "dir": "libs/core", + "lastModified": 1681394603, + "narHash": "sha256-dVqGLk+tARfFNrSvOXBkAvvPtOqcbTyr9sLFVJieZUw=", + "type": "git", + "url": "file:///home/sivizius/Projects/Active/nixfiles?dir=libs%2fcore" + }, + "original": { + "dir": "libs/core", + "owner": "sivizius", + "ref": "development", + "repo": "nixfiles", + "type": "github" + } + }, + "libcore_51": { + "inputs": { + "libintrinsics": "libintrinsics_51" + }, + "locked": { + "dir": "libs/core", + "lastModified": 1681394603, + "narHash": "sha256-dVqGLk+tARfFNrSvOXBkAvvPtOqcbTyr9sLFVJieZUw=", + "type": "git", + "url": "file:///home/sivizius/Projects/Active/nixfiles?dir=libs%2fcore" + }, + "original": { + "dir": "libs/core", + "owner": "sivizius", + "ref": "development", + "repo": "nixfiles", + "type": "github" + } + }, + "libcore_52": { + "inputs": { + "libintrinsics": "libintrinsics_52" + }, + "locked": { + "dir": "libs/core", + "lastModified": 1681394603, + "narHash": "sha256-dVqGLk+tARfFNrSvOXBkAvvPtOqcbTyr9sLFVJieZUw=", + "type": "git", + "url": "file:///home/sivizius/Projects/Active/nixfiles?dir=libs%2fcore" + }, + "original": { + "dir": "libs/core", + "owner": "sivizius", + "ref": "development", + "repo": "nixfiles", + "type": "github" + } + }, + "libcore_6": { + "inputs": { + "libintrinsics": "libintrinsics_6" + }, + "locked": { + "dir": "libs/core", + "lastModified": 1681394603, + "narHash": "sha256-dVqGLk+tARfFNrSvOXBkAvvPtOqcbTyr9sLFVJieZUw=", + "type": "git", + "url": "file:///home/sivizius/Projects/Active/nixfiles?dir=libs%2fcore" + }, + "original": { + "dir": "libs/core", + "owner": "sivizius", + "ref": "development", + "repo": "nixfiles", + "type": "github" + } + }, + "libcore_7": { + "inputs": { + "libintrinsics": "libintrinsics_7" + }, + "locked": { + "dir": "libs/core", + "lastModified": 1681394603, + "narHash": "sha256-dVqGLk+tARfFNrSvOXBkAvvPtOqcbTyr9sLFVJieZUw=", + "type": "git", + "url": "file:///home/sivizius/Projects/Active/nixfiles?dir=libs%2fcore" + }, + "original": { + "dir": "libs/core", + "owner": "sivizius", + "ref": "development", + "repo": "nixfiles", + "type": "github" + } + }, + "libcore_8": { + "inputs": { + "libintrinsics": "libintrinsics_8" + }, + "locked": { + "dir": "libs/core", + "lastModified": 1681394603, + "narHash": "sha256-dVqGLk+tARfFNrSvOXBkAvvPtOqcbTyr9sLFVJieZUw=", + "type": "git", + "url": "file:///home/sivizius/Projects/Active/nixfiles?dir=libs%2fcore" + }, + "original": { + "dir": "libs/core", + "owner": "sivizius", + "ref": "development", + "repo": "nixfiles", + "type": "github" + } + }, + "libcore_9": { + "inputs": { + "libintrinsics": "libintrinsics_9" + }, + "locked": { + "dir": "libs/core", + "lastModified": 1681394603, + "narHash": "sha256-dVqGLk+tARfFNrSvOXBkAvvPtOqcbTyr9sLFVJieZUw=", + "type": "git", + "url": "file:///home/sivizius/Projects/Active/nixfiles?dir=libs%2fcore" + }, + "original": { + "dir": "libs/core", + "owner": "sivizius", + "ref": "development", + "repo": "nixfiles", + "type": "github" + } + }, + "libintrinsics": { + "locked": { + "dir": "libs/intrinsics", + "lastModified": 1681394603, + "narHash": "sha256-dVqGLk+tARfFNrSvOXBkAvvPtOqcbTyr9sLFVJieZUw=", + "type": "git", + "url": "file:///home/sivizius/Projects/Active/nixfiles?dir=libs%2fintrinsics" + }, + "original": { + "dir": "libs/intrinsics", + "owner": "sivizius", + "ref": "development", + "repo": "nixfiles", + "type": "github" + } + }, + "libintrinsics_10": { + "locked": { + "dir": "libs/intrinsics", + "lastModified": 1681394603, + "narHash": "sha256-dVqGLk+tARfFNrSvOXBkAvvPtOqcbTyr9sLFVJieZUw=", + "type": "git", + "url": "file:///home/sivizius/Projects/Active/nixfiles?dir=libs%2fintrinsics" + }, + "original": { + "dir": "libs/intrinsics", + "owner": "sivizius", + "ref": "development", + "repo": "nixfiles", + "type": "github" + } + }, + "libintrinsics_11": { + "locked": { + "dir": "libs/intrinsics", + "lastModified": 1681394603, + "narHash": "sha256-dVqGLk+tARfFNrSvOXBkAvvPtOqcbTyr9sLFVJieZUw=", + "type": "git", + "url": "file:///home/sivizius/Projects/Active/nixfiles?dir=libs%2fintrinsics" + }, + "original": { + "dir": "libs/intrinsics", + "owner": "sivizius", + "ref": "development", + "repo": "nixfiles", + "type": "github" + } + }, + "libintrinsics_12": { + "locked": { + "dir": "libs/intrinsics", + "lastModified": 1681394603, + "narHash": "sha256-dVqGLk+tARfFNrSvOXBkAvvPtOqcbTyr9sLFVJieZUw=", + "type": "git", + "url": "file:///home/sivizius/Projects/Active/nixfiles?dir=libs%2fintrinsics" + }, + "original": { + "dir": "libs/intrinsics", + "owner": "sivizius", + "ref": "development", + "repo": "nixfiles", + "type": "github" + } + }, + "libintrinsics_13": { + "locked": { + "dir": "libs/intrinsics", + "lastModified": 1681394603, + "narHash": "sha256-dVqGLk+tARfFNrSvOXBkAvvPtOqcbTyr9sLFVJieZUw=", + "type": "git", + "url": "file:///home/sivizius/Projects/Active/nixfiles?dir=libs%2fintrinsics" + }, + "original": { + "dir": "libs/intrinsics", + "owner": "sivizius", + "ref": "development", + "repo": "nixfiles", + "type": "github" + } + }, + "libintrinsics_14": { + "locked": { + "dir": "libs/intrinsics", + "lastModified": 1681394603, + "narHash": "sha256-dVqGLk+tARfFNrSvOXBkAvvPtOqcbTyr9sLFVJieZUw=", + "type": "git", + "url": "file:///home/sivizius/Projects/Active/nixfiles?dir=libs%2fintrinsics" + }, + "original": { + "dir": "libs/intrinsics", + "owner": "sivizius", + "ref": "development", + "repo": "nixfiles", + "type": "github" + } + }, + "libintrinsics_15": { + "locked": { + "dir": "libs/intrinsics", + "lastModified": 1681394603, + "narHash": "sha256-dVqGLk+tARfFNrSvOXBkAvvPtOqcbTyr9sLFVJieZUw=", + "type": "git", + "url": "file:///home/sivizius/Projects/Active/nixfiles?dir=libs%2fintrinsics" + }, + "original": { + "dir": "libs/intrinsics", + "owner": "sivizius", + "ref": "development", + "repo": "nixfiles", + "type": "github" + } + }, + "libintrinsics_16": { + "locked": { + "dir": "libs/intrinsics", + "lastModified": 1681394603, + "narHash": "sha256-dVqGLk+tARfFNrSvOXBkAvvPtOqcbTyr9sLFVJieZUw=", + "type": "git", + "url": "file:///home/sivizius/Projects/Active/nixfiles?dir=libs%2fintrinsics" + }, + "original": { + "dir": "libs/intrinsics", + "owner": "sivizius", + "ref": "development", + "repo": "nixfiles", + "type": "github" + } + }, + "libintrinsics_17": { + "locked": { + "dir": "libs/intrinsics", + "lastModified": 1681394603, + "narHash": "sha256-dVqGLk+tARfFNrSvOXBkAvvPtOqcbTyr9sLFVJieZUw=", + "type": "git", + "url": "file:///home/sivizius/Projects/Active/nixfiles?dir=libs%2fintrinsics" + }, + "original": { + "dir": "libs/intrinsics", + "owner": "sivizius", + "ref": "development", + "repo": "nixfiles", + "type": "github" + } + }, + "libintrinsics_18": { + "locked": { + "dir": "libs/intrinsics", + "lastModified": 1681394603, + "narHash": "sha256-dVqGLk+tARfFNrSvOXBkAvvPtOqcbTyr9sLFVJieZUw=", + "type": "git", + "url": "file:///home/sivizius/Projects/Active/nixfiles?dir=libs%2fintrinsics" + }, + "original": { + "dir": "libs/intrinsics", + "owner": "sivizius", + "ref": "development", + "repo": "nixfiles", + "type": "github" + } + }, + "libintrinsics_19": { + "locked": { + "dir": "libs/intrinsics", + "lastModified": 1681394603, + "narHash": "sha256-dVqGLk+tARfFNrSvOXBkAvvPtOqcbTyr9sLFVJieZUw=", + "type": "git", + "url": "file:///home/sivizius/Projects/Active/nixfiles?dir=libs%2fintrinsics" + }, + "original": { + "dir": "libs/intrinsics", + "owner": "sivizius", + "ref": "development", + "repo": "nixfiles", + "type": "github" + } + }, + "libintrinsics_2": { + "locked": { + "dir": "libs/intrinsics", + "lastModified": 1681394603, + "narHash": "sha256-dVqGLk+tARfFNrSvOXBkAvvPtOqcbTyr9sLFVJieZUw=", + "type": "git", + "url": "file:///home/sivizius/Projects/Active/nixfiles?dir=libs%2fintrinsics" + }, + "original": { + "dir": "libs/intrinsics", + "owner": "sivizius", + "ref": "development", + "repo": "nixfiles", + "type": "github" + } + }, + "libintrinsics_20": { + "locked": { + "dir": "libs/intrinsics", + "lastModified": 1681394603, + "narHash": "sha256-dVqGLk+tARfFNrSvOXBkAvvPtOqcbTyr9sLFVJieZUw=", + "type": "git", + "url": "file:///home/sivizius/Projects/Active/nixfiles?dir=libs%2fintrinsics" + }, + "original": { + "dir": "libs/intrinsics", + "owner": "sivizius", + "ref": "development", + "repo": "nixfiles", + "type": "github" + } + }, + "libintrinsics_21": { + "locked": { + "dir": "libs/intrinsics", + "lastModified": 1681394603, + "narHash": "sha256-dVqGLk+tARfFNrSvOXBkAvvPtOqcbTyr9sLFVJieZUw=", + "type": "git", + "url": "file:///home/sivizius/Projects/Active/nixfiles?dir=libs%2fintrinsics" + }, + "original": { + "dir": "libs/intrinsics", + "owner": "sivizius", + "ref": "development", + "repo": "nixfiles", + "type": "github" + } + }, + "libintrinsics_22": { + "locked": { + "dir": "libs/intrinsics", + "lastModified": 1681394603, + "narHash": "sha256-dVqGLk+tARfFNrSvOXBkAvvPtOqcbTyr9sLFVJieZUw=", + "type": "git", + "url": "file:///home/sivizius/Projects/Active/nixfiles?dir=libs%2fintrinsics" + }, + "original": { + "dir": "libs/intrinsics", + "owner": "sivizius", + "ref": "development", + "repo": "nixfiles", + "type": "github" + } + }, + "libintrinsics_23": { + "locked": { + "dir": "libs/intrinsics", + "lastModified": 1681394603, + "narHash": "sha256-dVqGLk+tARfFNrSvOXBkAvvPtOqcbTyr9sLFVJieZUw=", + "type": "git", + "url": "file:///home/sivizius/Projects/Active/nixfiles?dir=libs%2fintrinsics" + }, + "original": { + "dir": "libs/intrinsics", + "owner": "sivizius", + "ref": "development", + "repo": "nixfiles", + "type": "github" + } + }, + "libintrinsics_24": { + "locked": { + "dir": "libs/intrinsics", + "lastModified": 1681394603, + "narHash": "sha256-dVqGLk+tARfFNrSvOXBkAvvPtOqcbTyr9sLFVJieZUw=", + "type": "git", + "url": "file:///home/sivizius/Projects/Active/nixfiles?dir=libs%2fintrinsics" + }, + "original": { + "dir": "libs/intrinsics", + "owner": "sivizius", + "ref": "development", + "repo": "nixfiles", + "type": "github" + } + }, + "libintrinsics_25": { + "locked": { + "dir": "libs/intrinsics", + "lastModified": 1681394603, + "narHash": "sha256-dVqGLk+tARfFNrSvOXBkAvvPtOqcbTyr9sLFVJieZUw=", + "type": "git", + "url": "file:///home/sivizius/Projects/Active/nixfiles?dir=libs%2fintrinsics" + }, + "original": { + "dir": "libs/intrinsics", + "owner": "sivizius", + "ref": "development", + "repo": "nixfiles", + "type": "github" + } + }, + "libintrinsics_26": { + "locked": { + "dir": "libs/intrinsics", + "lastModified": 1681394603, + "narHash": "sha256-dVqGLk+tARfFNrSvOXBkAvvPtOqcbTyr9sLFVJieZUw=", + "type": "git", + "url": "file:///home/sivizius/Projects/Active/nixfiles?dir=libs%2fintrinsics" + }, + "original": { + "dir": "libs/intrinsics", + "owner": "sivizius", + "ref": "development", + "repo": "nixfiles", + "type": "github" + } + }, + "libintrinsics_27": { + "locked": { + "dir": "libs/intrinsics", + "lastModified": 1681394603, + "narHash": "sha256-dVqGLk+tARfFNrSvOXBkAvvPtOqcbTyr9sLFVJieZUw=", + "type": "git", + "url": "file:///home/sivizius/Projects/Active/nixfiles?dir=libs%2fintrinsics" + }, + "original": { + "dir": "libs/intrinsics", + "owner": "sivizius", + "ref": "development", + "repo": "nixfiles", + "type": "github" + } + }, + "libintrinsics_28": { + "locked": { + "dir": "libs/intrinsics", + "lastModified": 1681394603, + "narHash": "sha256-dVqGLk+tARfFNrSvOXBkAvvPtOqcbTyr9sLFVJieZUw=", + "type": "git", + "url": "file:///home/sivizius/Projects/Active/nixfiles?dir=libs%2fintrinsics" + }, + "original": { + "dir": "libs/intrinsics", + "owner": "sivizius", + "ref": "development", + "repo": "nixfiles", + "type": "github" + } + }, + "libintrinsics_29": { + "locked": { + "dir": "libs/intrinsics", + "lastModified": 1681394603, + "narHash": "sha256-dVqGLk+tARfFNrSvOXBkAvvPtOqcbTyr9sLFVJieZUw=", + "type": "git", + "url": "file:///home/sivizius/Projects/Active/nixfiles?dir=libs%2fintrinsics" + }, + "original": { + "dir": "libs/intrinsics", + "owner": "sivizius", + "ref": "development", + "repo": "nixfiles", + "type": "github" + } + }, + "libintrinsics_3": { + "locked": { + "dir": "libs/intrinsics", + "lastModified": 1681394603, + "narHash": "sha256-dVqGLk+tARfFNrSvOXBkAvvPtOqcbTyr9sLFVJieZUw=", + "type": "git", + "url": "file:///home/sivizius/Projects/Active/nixfiles?dir=libs%2fintrinsics" + }, + "original": { + "dir": "libs/intrinsics", + "owner": "sivizius", + "ref": "development", + "repo": "nixfiles", + "type": "github" + } + }, + "libintrinsics_30": { + "locked": { + "dir": "libs/intrinsics", + "lastModified": 1681394603, + "narHash": "sha256-dVqGLk+tARfFNrSvOXBkAvvPtOqcbTyr9sLFVJieZUw=", + "type": "git", + "url": "file:///home/sivizius/Projects/Active/nixfiles?dir=libs%2fintrinsics" + }, + "original": { + "dir": "libs/intrinsics", + "owner": "sivizius", + "ref": "development", + "repo": "nixfiles", + "type": "github" + } + }, + "libintrinsics_31": { + "locked": { + "dir": "libs/intrinsics", + "lastModified": 1681394603, + "narHash": "sha256-dVqGLk+tARfFNrSvOXBkAvvPtOqcbTyr9sLFVJieZUw=", + "type": "git", + "url": "file:///home/sivizius/Projects/Active/nixfiles?dir=libs%2fintrinsics" + }, + "original": { + "dir": "libs/intrinsics", + "owner": "sivizius", + "ref": "development", + "repo": "nixfiles", + "type": "github" + } + }, + "libintrinsics_32": { + "locked": { + "dir": "libs/intrinsics", + "lastModified": 1681394603, + "narHash": "sha256-dVqGLk+tARfFNrSvOXBkAvvPtOqcbTyr9sLFVJieZUw=", + "type": "git", + "url": "file:///home/sivizius/Projects/Active/nixfiles?dir=libs%2fintrinsics" + }, + "original": { + "dir": "libs/intrinsics", + "owner": "sivizius", + "ref": "development", + "repo": "nixfiles", + "type": "github" + } + }, + "libintrinsics_33": { + "locked": { + "dir": "libs/intrinsics", + "lastModified": 1681394603, + "narHash": "sha256-dVqGLk+tARfFNrSvOXBkAvvPtOqcbTyr9sLFVJieZUw=", + "type": "git", + "url": "file:///home/sivizius/Projects/Active/nixfiles?dir=libs%2fintrinsics" + }, + "original": { + "dir": "libs/intrinsics", + "owner": "sivizius", + "ref": "development", + "repo": "nixfiles", + "type": "github" + } + }, + "libintrinsics_34": { + "locked": { + "dir": "libs/intrinsics", + "lastModified": 1681394603, + "narHash": "sha256-dVqGLk+tARfFNrSvOXBkAvvPtOqcbTyr9sLFVJieZUw=", + "type": "git", + "url": "file:///home/sivizius/Projects/Active/nixfiles?dir=libs%2fintrinsics" + }, + "original": { + "dir": "libs/intrinsics", + "owner": "sivizius", + "ref": "development", + "repo": "nixfiles", + "type": "github" + } + }, + "libintrinsics_35": { + "locked": { + "dir": "libs/intrinsics", + "lastModified": 1681394603, + "narHash": "sha256-dVqGLk+tARfFNrSvOXBkAvvPtOqcbTyr9sLFVJieZUw=", + "type": "git", + "url": "file:///home/sivizius/Projects/Active/nixfiles?dir=libs%2fintrinsics" + }, + "original": { + "dir": "libs/intrinsics", + "owner": "sivizius", + "ref": "development", + "repo": "nixfiles", + "type": "github" + } + }, + "libintrinsics_36": { + "locked": { + "dir": "libs/intrinsics", + "lastModified": 1681394603, + "narHash": "sha256-dVqGLk+tARfFNrSvOXBkAvvPtOqcbTyr9sLFVJieZUw=", + "type": "git", + "url": "file:///home/sivizius/Projects/Active/nixfiles?dir=libs%2fintrinsics" + }, + "original": { + "dir": "libs/intrinsics", + "owner": "sivizius", + "ref": "development", + "repo": "nixfiles", + "type": "github" + } + }, + "libintrinsics_37": { + "locked": { + "dir": "libs/intrinsics", + "lastModified": 1681394603, + "narHash": "sha256-dVqGLk+tARfFNrSvOXBkAvvPtOqcbTyr9sLFVJieZUw=", + "type": "git", + "url": "file:///home/sivizius/Projects/Active/nixfiles?dir=libs%2fintrinsics" + }, + "original": { + "dir": "libs/intrinsics", + "owner": "sivizius", + "ref": "development", + "repo": "nixfiles", + "type": "github" + } + }, + "libintrinsics_38": { + "locked": { + "dir": "libs/intrinsics", + "lastModified": 1681394603, + "narHash": "sha256-dVqGLk+tARfFNrSvOXBkAvvPtOqcbTyr9sLFVJieZUw=", + "type": "git", + "url": "file:///home/sivizius/Projects/Active/nixfiles?dir=libs%2fintrinsics" + }, + "original": { + "dir": "libs/intrinsics", + "owner": "sivizius", + "ref": "development", + "repo": "nixfiles", + "type": "github" + } + }, + "libintrinsics_39": { + "locked": { + "dir": "libs/intrinsics", + "lastModified": 1681394603, + "narHash": "sha256-dVqGLk+tARfFNrSvOXBkAvvPtOqcbTyr9sLFVJieZUw=", + "type": "git", + "url": "file:///home/sivizius/Projects/Active/nixfiles?dir=libs%2fintrinsics" + }, + "original": { + "dir": "libs/intrinsics", + "owner": "sivizius", + "ref": "development", + "repo": "nixfiles", + "type": "github" + } + }, + "libintrinsics_4": { + "locked": { + "dir": "libs/intrinsics", + "lastModified": 1681394603, + "narHash": "sha256-dVqGLk+tARfFNrSvOXBkAvvPtOqcbTyr9sLFVJieZUw=", + "type": "git", + "url": "file:///home/sivizius/Projects/Active/nixfiles?dir=libs%2fintrinsics" + }, + "original": { + "dir": "libs/intrinsics", + "owner": "sivizius", + "ref": "development", + "repo": "nixfiles", + "type": "github" + } + }, + "libintrinsics_40": { + "locked": { + "dir": "libs/intrinsics", + "lastModified": 1681394603, + "narHash": "sha256-dVqGLk+tARfFNrSvOXBkAvvPtOqcbTyr9sLFVJieZUw=", + "type": "git", + "url": "file:///home/sivizius/Projects/Active/nixfiles?dir=libs%2fintrinsics" + }, + "original": { + "dir": "libs/intrinsics", + "owner": "sivizius", + "ref": "development", + "repo": "nixfiles", + "type": "github" + } + }, + "libintrinsics_41": { + "locked": { + "dir": "libs/intrinsics", + "lastModified": 1681394603, + "narHash": "sha256-dVqGLk+tARfFNrSvOXBkAvvPtOqcbTyr9sLFVJieZUw=", + "type": "git", + "url": "file:///home/sivizius/Projects/Active/nixfiles?dir=libs%2fintrinsics" + }, + "original": { + "dir": "libs/intrinsics", + "owner": "sivizius", + "ref": "development", + "repo": "nixfiles", + "type": "github" + } + }, + "libintrinsics_42": { + "locked": { + "dir": "libs/intrinsics", + "lastModified": 1681394603, + "narHash": "sha256-dVqGLk+tARfFNrSvOXBkAvvPtOqcbTyr9sLFVJieZUw=", + "type": "git", + "url": "file:///home/sivizius/Projects/Active/nixfiles?dir=libs%2fintrinsics" + }, + "original": { + "dir": "libs/intrinsics", + "owner": "sivizius", + "ref": "development", + "repo": "nixfiles", + "type": "github" + } + }, + "libintrinsics_43": { + "locked": { + "dir": "libs/intrinsics", + "lastModified": 1681394603, + "narHash": "sha256-dVqGLk+tARfFNrSvOXBkAvvPtOqcbTyr9sLFVJieZUw=", + "type": "git", + "url": "file:///home/sivizius/Projects/Active/nixfiles?dir=libs%2fintrinsics" + }, + "original": { + "dir": "libs/intrinsics", + "owner": "sivizius", + "ref": "development", + "repo": "nixfiles", + "type": "github" + } + }, + "libintrinsics_44": { + "locked": { + "dir": "libs/intrinsics", + "lastModified": 1681394603, + "narHash": "sha256-dVqGLk+tARfFNrSvOXBkAvvPtOqcbTyr9sLFVJieZUw=", + "type": "git", + "url": "file:///home/sivizius/Projects/Active/nixfiles?dir=libs%2fintrinsics" + }, + "original": { + "dir": "libs/intrinsics", + "owner": "sivizius", + "ref": "development", + "repo": "nixfiles", + "type": "github" + } + }, + "libintrinsics_45": { + "locked": { + "dir": "libs/intrinsics", + "lastModified": 1681394603, + "narHash": "sha256-dVqGLk+tARfFNrSvOXBkAvvPtOqcbTyr9sLFVJieZUw=", + "type": "git", + "url": "file:///home/sivizius/Projects/Active/nixfiles?dir=libs%2fintrinsics" + }, + "original": { + "dir": "libs/intrinsics", + "owner": "sivizius", + "ref": "development", + "repo": "nixfiles", + "type": "github" + } + }, + "libintrinsics_46": { + "locked": { + "dir": "libs/intrinsics", + "lastModified": 1681394603, + "narHash": "sha256-dVqGLk+tARfFNrSvOXBkAvvPtOqcbTyr9sLFVJieZUw=", + "type": "git", + "url": "file:///home/sivizius/Projects/Active/nixfiles?dir=libs%2fintrinsics" + }, + "original": { + "dir": "libs/intrinsics", + "owner": "sivizius", + "ref": "development", + "repo": "nixfiles", + "type": "github" + } + }, + "libintrinsics_47": { + "locked": { + "dir": "libs/intrinsics", + "lastModified": 1681394603, + "narHash": "sha256-dVqGLk+tARfFNrSvOXBkAvvPtOqcbTyr9sLFVJieZUw=", + "type": "git", + "url": "file:///home/sivizius/Projects/Active/nixfiles?dir=libs%2fintrinsics" + }, + "original": { + "dir": "libs/intrinsics", + "owner": "sivizius", + "ref": "development", + "repo": "nixfiles", + "type": "github" + } + }, + "libintrinsics_48": { + "locked": { + "dir": "libs/intrinsics", + "lastModified": 1681394603, + "narHash": "sha256-dVqGLk+tARfFNrSvOXBkAvvPtOqcbTyr9sLFVJieZUw=", + "type": "git", + "url": "file:///home/sivizius/Projects/Active/nixfiles?dir=libs%2fintrinsics" + }, + "original": { + "dir": "libs/intrinsics", + "owner": "sivizius", + "ref": "development", + "repo": "nixfiles", + "type": "github" + } + }, + "libintrinsics_49": { + "locked": { + "dir": "libs/intrinsics", + "lastModified": 1681394603, + "narHash": "sha256-dVqGLk+tARfFNrSvOXBkAvvPtOqcbTyr9sLFVJieZUw=", + "type": "git", + "url": "file:///home/sivizius/Projects/Active/nixfiles?dir=libs%2fintrinsics" + }, + "original": { + "dir": "libs/intrinsics", + "owner": "sivizius", + "ref": "development", + "repo": "nixfiles", + "type": "github" + } + }, + "libintrinsics_5": { + "locked": { + "dir": "libs/intrinsics", + "lastModified": 1681394603, + "narHash": "sha256-dVqGLk+tARfFNrSvOXBkAvvPtOqcbTyr9sLFVJieZUw=", + "type": "git", + "url": "file:///home/sivizius/Projects/Active/nixfiles?dir=libs%2fintrinsics" + }, + "original": { + "dir": "libs/intrinsics", + "owner": "sivizius", + "ref": "development", + "repo": "nixfiles", + "type": "github" + } + }, + "libintrinsics_50": { + "locked": { + "dir": "libs/intrinsics", + "lastModified": 1681394603, + "narHash": "sha256-dVqGLk+tARfFNrSvOXBkAvvPtOqcbTyr9sLFVJieZUw=", + "type": "git", + "url": "file:///home/sivizius/Projects/Active/nixfiles?dir=libs%2fintrinsics" + }, + "original": { + "dir": "libs/intrinsics", + "owner": "sivizius", + "ref": "development", + "repo": "nixfiles", + "type": "github" + } + }, + "libintrinsics_51": { + "locked": { + "dir": "libs/intrinsics", + "lastModified": 1681394603, + "narHash": "sha256-dVqGLk+tARfFNrSvOXBkAvvPtOqcbTyr9sLFVJieZUw=", + "type": "git", + "url": "file:///home/sivizius/Projects/Active/nixfiles?dir=libs%2fintrinsics" + }, + "original": { + "dir": "libs/intrinsics", + "owner": "sivizius", + "ref": "development", + "repo": "nixfiles", + "type": "github" + } + }, + "libintrinsics_52": { + "locked": { + "dir": "libs/intrinsics", + "lastModified": 1681394603, + "narHash": "sha256-dVqGLk+tARfFNrSvOXBkAvvPtOqcbTyr9sLFVJieZUw=", + "type": "git", + "url": "file:///home/sivizius/Projects/Active/nixfiles?dir=libs%2fintrinsics" + }, + "original": { + "dir": "libs/intrinsics", + "owner": "sivizius", + "ref": "development", + "repo": "nixfiles", + "type": "github" + } + }, + "libintrinsics_6": { + "locked": { + "dir": "libs/intrinsics", + "lastModified": 1681394603, + "narHash": "sha256-dVqGLk+tARfFNrSvOXBkAvvPtOqcbTyr9sLFVJieZUw=", + "type": "git", + "url": "file:///home/sivizius/Projects/Active/nixfiles?dir=libs%2fintrinsics" + }, + "original": { + "dir": "libs/intrinsics", + "owner": "sivizius", + "ref": "development", + "repo": "nixfiles", + "type": "github" + } + }, + "libintrinsics_7": { + "locked": { + "dir": "libs/intrinsics", + "lastModified": 1681394603, + "narHash": "sha256-dVqGLk+tARfFNrSvOXBkAvvPtOqcbTyr9sLFVJieZUw=", + "type": "git", + "url": "file:///home/sivizius/Projects/Active/nixfiles?dir=libs%2fintrinsics" + }, + "original": { + "dir": "libs/intrinsics", + "owner": "sivizius", + "ref": "development", + "repo": "nixfiles", + "type": "github" + } + }, + "libintrinsics_8": { + "locked": { + "dir": "libs/intrinsics", + "lastModified": 1681394603, + "narHash": "sha256-dVqGLk+tARfFNrSvOXBkAvvPtOqcbTyr9sLFVJieZUw=", + "type": "git", + "url": "file:///home/sivizius/Projects/Active/nixfiles?dir=libs%2fintrinsics" + }, + "original": { + "dir": "libs/intrinsics", + "owner": "sivizius", + "ref": "development", + "repo": "nixfiles", + "type": "github" + } + }, + "libintrinsics_9": { + "locked": { + "dir": "libs/intrinsics", + "lastModified": 1681394603, + "narHash": "sha256-dVqGLk+tARfFNrSvOXBkAvvPtOqcbTyr9sLFVJieZUw=", + "type": "git", + "url": "file:///home/sivizius/Projects/Active/nixfiles?dir=libs%2fintrinsics" + }, + "original": { + "dir": "libs/intrinsics", + "owner": "sivizius", + "ref": "development", + "repo": "nixfiles", + "type": "github" + } + }, + "libsecrets": { + "inputs": { + "libcore": "libcore_3", + "libstore": "libstore" + }, + "locked": { + "dir": "libs/secrets", + "lastModified": 1681394603, + "narHash": "sha256-dVqGLk+tARfFNrSvOXBkAvvPtOqcbTyr9sLFVJieZUw=", + "type": "git", + "url": "file:///home/sivizius/Projects/Active/nixfiles?dir=libs%2fsecrets" + }, + "original": { + "dir": "libs/secrets", + "owner": "sivizius", + "ref": "development", + "repo": "nixfiles", + "type": "github" + } + }, + "libsecrets_2": { + "inputs": { + "libcore": "libcore_8", + "libstore": "libstore_3" + }, + "locked": { + "dir": "libs/secrets", + "lastModified": 1681394603, + "narHash": "sha256-dVqGLk+tARfFNrSvOXBkAvvPtOqcbTyr9sLFVJieZUw=", + "type": "git", + "url": "file:///home/sivizius/Projects/Active/nixfiles?dir=libs%2fsecrets" + }, + "original": { + "dir": "libs/secrets", + "owner": "sivizius", + "ref": "development", + "repo": "nixfiles", + "type": "github" + } + }, + "libsecrets_3": { + "inputs": { + "libcore": "libcore_13", + "libstore": "libstore_5" + }, + "locked": { + "dir": "libs/secrets", + "lastModified": 1681394603, + "narHash": "sha256-dVqGLk+tARfFNrSvOXBkAvvPtOqcbTyr9sLFVJieZUw=", + "type": "git", + "url": "file:///home/sivizius/Projects/Active/nixfiles?dir=libs%2fsecrets" + }, + "original": { + "dir": "libs/secrets", + "owner": "sivizius", + "ref": "development", + "repo": "nixfiles", + "type": "github" + } + }, + "libsecrets_4": { + "inputs": { + "libcore": "libcore_19", + "libstore": "libstore_7" + }, + "locked": { + "dir": "libs/secrets", + "lastModified": 1681394603, + "narHash": "sha256-dVqGLk+tARfFNrSvOXBkAvvPtOqcbTyr9sLFVJieZUw=", + "type": "git", + "url": "file:///home/sivizius/Projects/Active/nixfiles?dir=libs%2fsecrets" + }, + "original": { + "dir": "libs/secrets", + "owner": "sivizius", + "ref": "development", + "repo": "nixfiles", + "type": "github" + } + }, + "libsecrets_5": { + "inputs": { + "libcore": "libcore_24", + "libstore": "libstore_9" + }, + "locked": { + "dir": "libs/secrets", + "lastModified": 1681394603, + "narHash": "sha256-dVqGLk+tARfFNrSvOXBkAvvPtOqcbTyr9sLFVJieZUw=", + "type": "git", + "url": "file:///home/sivizius/Projects/Active/nixfiles?dir=libs%2fsecrets" + }, + "original": { + "dir": "libs/secrets", + "owner": "sivizius", + "ref": "development", + "repo": "nixfiles", + "type": "github" + } + }, + "libsecrets_6": { + "inputs": { + "libcore": "libcore_27", + "libstore": "libstore_10" + }, + "locked": { + "dir": "libs/secrets", + "lastModified": 1681394603, + "narHash": "sha256-dVqGLk+tARfFNrSvOXBkAvvPtOqcbTyr9sLFVJieZUw=", + "type": "git", + "url": "file:///home/sivizius/Projects/Active/nixfiles?dir=libs%2fsecrets" + }, + "original": { + "dir": "libs/secrets", + "owner": "sivizius", + "ref": "development", + "repo": "nixfiles", + "type": "github" + } + }, + "libsecrets_7": { + "inputs": { + "libcore": "libcore_33", + "libstore": "libstore_12" + }, + "locked": { + "dir": "libs/secrets", + "lastModified": 1681394603, + "narHash": "sha256-dVqGLk+tARfFNrSvOXBkAvvPtOqcbTyr9sLFVJieZUw=", + "type": "git", + "url": "file:///home/sivizius/Projects/Active/nixfiles?dir=libs%2fsecrets" + }, + "original": { + "dir": "libs/secrets", + "owner": "sivizius", + "ref": "development", + "repo": "nixfiles", + "type": "github" + } + }, + "libsecrets_8": { + "inputs": { + "libcore": "libcore_40", + "libstore": "libstore_14" + }, + "locked": { + "dir": "libs/secrets", + "lastModified": 1681394603, + "narHash": "sha256-dVqGLk+tARfFNrSvOXBkAvvPtOqcbTyr9sLFVJieZUw=", + "type": "git", + "url": "file:///home/sivizius/Projects/Active/nixfiles?dir=libs%2fsecrets" + }, + "original": { + "dir": "libs/secrets", + "owner": "sivizius", + "ref": "development", + "repo": "nixfiles", + "type": "github" + } + }, + "libsecrets_9": { + "inputs": { + "libcore": "libcore_48", + "libstore": "libstore_16" + }, + "locked": { + "dir": "libs/secrets", + "lastModified": 1681394603, + "narHash": "sha256-dVqGLk+tARfFNrSvOXBkAvvPtOqcbTyr9sLFVJieZUw=", + "type": "git", + "url": "file:///home/sivizius/Projects/Active/nixfiles?dir=libs%2fsecrets" + }, + "original": { + "dir": "libs/secrets", + "owner": "sivizius", + "ref": "development", + "repo": "nixfiles", + "type": "github" + } + }, + "libstore": { + "inputs": { + "libcore": "libcore_4", + "nixpkgs": "nixpkgs_2" + }, + "locked": { + "dir": "libs/store", + "lastModified": 1681394603, + "narHash": "sha256-dVqGLk+tARfFNrSvOXBkAvvPtOqcbTyr9sLFVJieZUw=", + "type": "git", + "url": "file:///home/sivizius/Projects/Active/nixfiles?dir=libs%2fstore" + }, + "original": { + "dir": "libs/store", + "owner": "sivizius", + "ref": "development", + "repo": "nixfiles", + "type": "github" + } + }, + "libstore_10": { + "inputs": { + "libcore": "libcore_28", + "nixpkgs": "nixpkgs_21" + }, + "locked": { + "dir": "libs/store", + "lastModified": 1681394603, + "narHash": "sha256-dVqGLk+tARfFNrSvOXBkAvvPtOqcbTyr9sLFVJieZUw=", + "type": "git", + "url": "file:///home/sivizius/Projects/Active/nixfiles?dir=libs%2fstore" + }, + "original": { + "dir": "libs/store", + "owner": "sivizius", + "ref": "development", + "repo": "nixfiles", + "type": "github" + } + }, + "libstore_11": { + "inputs": { + "libcore": "libcore_29", + "nixpkgs": "nixpkgs_22" + }, + "locked": { + "dir": "libs/store", + "lastModified": 1681394603, + "narHash": "sha256-dVqGLk+tARfFNrSvOXBkAvvPtOqcbTyr9sLFVJieZUw=", + "type": "git", + "url": "file:///home/sivizius/Projects/Active/nixfiles?dir=libs%2fstore" + }, + "original": { + "dir": "libs/store", + "owner": "sivizius", + "ref": "development", + "repo": "nixfiles", + "type": "github" + } + }, + "libstore_12": { + "inputs": { + "libcore": "libcore_34", + "nixpkgs": "nixpkgs_26" + }, + "locked": { + "dir": "libs/store", + "lastModified": 1681394603, + "narHash": "sha256-dVqGLk+tARfFNrSvOXBkAvvPtOqcbTyr9sLFVJieZUw=", + "type": "git", + "url": "file:///home/sivizius/Projects/Active/nixfiles?dir=libs%2fstore" + }, + "original": { + "dir": "libs/store", + "owner": "sivizius", + "ref": "development", + "repo": "nixfiles", + "type": "github" + } + }, + "libstore_13": { + "inputs": { + "libcore": "libcore_35", + "nixpkgs": "nixpkgs_27" + }, + "locked": { + "dir": "libs/store", + "lastModified": 1681394603, + "narHash": "sha256-dVqGLk+tARfFNrSvOXBkAvvPtOqcbTyr9sLFVJieZUw=", + "type": "git", + "url": "file:///home/sivizius/Projects/Active/nixfiles?dir=libs%2fstore" + }, + "original": { + "dir": "libs/store", + "owner": "sivizius", + "ref": "development", + "repo": "nixfiles", + "type": "github" + } + }, + "libstore_14": { + "inputs": { + "libcore": "libcore_41", + "nixpkgs": "nixpkgs_32" + }, + "locked": { + "dir": "libs/store", + "lastModified": 1681394603, + "narHash": "sha256-dVqGLk+tARfFNrSvOXBkAvvPtOqcbTyr9sLFVJieZUw=", + "type": "git", + "url": "file:///home/sivizius/Projects/Active/nixfiles?dir=libs%2fstore" + }, + "original": { + "dir": "libs/store", + "owner": "sivizius", + "ref": "development", + "repo": "nixfiles", + "type": "github" + } + }, + "libstore_15": { + "inputs": { + "libcore": "libcore_42", + "nixpkgs": "nixpkgs_33" + }, + "locked": { + "dir": "libs/store", + "lastModified": 1681394603, + "narHash": "sha256-dVqGLk+tARfFNrSvOXBkAvvPtOqcbTyr9sLFVJieZUw=", + "type": "git", + "url": "file:///home/sivizius/Projects/Active/nixfiles?dir=libs%2fstore" + }, + "original": { + "dir": "libs/store", + "owner": "sivizius", + "ref": "development", + "repo": "nixfiles", + "type": "github" + } + }, + "libstore_16": { + "inputs": { + "libcore": "libcore_49", + "nixpkgs": "nixpkgs_40" + }, + "locked": { + "dir": "libs/store", + "lastModified": 1681394603, + "narHash": "sha256-dVqGLk+tARfFNrSvOXBkAvvPtOqcbTyr9sLFVJieZUw=", + "type": "git", + "url": "file:///home/sivizius/Projects/Active/nixfiles?dir=libs%2fstore" + }, + "original": { + "dir": "libs/store", + "owner": "sivizius", + "ref": "development", + "repo": "nixfiles", + "type": "github" + } + }, + "libstore_17": { + "inputs": { + "libcore": "libcore_50", + "nixpkgs": "nixpkgs_41" + }, + "locked": { + "dir": "libs/store", + "lastModified": 1681394603, + "narHash": "sha256-dVqGLk+tARfFNrSvOXBkAvvPtOqcbTyr9sLFVJieZUw=", + "type": "git", + "url": "file:///home/sivizius/Projects/Active/nixfiles?dir=libs%2fstore" + }, + "original": { + "dir": "libs/store", + "owner": "sivizius", + "ref": "development", + "repo": "nixfiles", + "type": "github" + } + }, + "libstore_2": { + "inputs": { + "libcore": "libcore_5", + "nixpkgs": "nixpkgs_3" + }, + "locked": { + "dir": "libs/store", + "lastModified": 1681394603, + "narHash": "sha256-dVqGLk+tARfFNrSvOXBkAvvPtOqcbTyr9sLFVJieZUw=", + "type": "git", + "url": "file:///home/sivizius/Projects/Active/nixfiles?dir=libs%2fstore" + }, + "original": { + "dir": "libs/store", + "owner": "sivizius", + "ref": "development", + "repo": "nixfiles", + "type": "github" + } + }, + "libstore_3": { + "inputs": { + "libcore": "libcore_9", + "nixpkgs": "nixpkgs_6" + }, + "locked": { + "dir": "libs/store", + "lastModified": 1681394603, + "narHash": "sha256-dVqGLk+tARfFNrSvOXBkAvvPtOqcbTyr9sLFVJieZUw=", + "type": "git", + "url": "file:///home/sivizius/Projects/Active/nixfiles?dir=libs%2fstore" + }, + "original": { + "dir": "libs/store", + "owner": "sivizius", + "ref": "development", + "repo": "nixfiles", + "type": "github" + } + }, + "libstore_4": { + "inputs": { + "libcore": "libcore_10", + "nixpkgs": "nixpkgs_7" + }, + "locked": { + "dir": "libs/store", + "lastModified": 1681394603, + "narHash": "sha256-dVqGLk+tARfFNrSvOXBkAvvPtOqcbTyr9sLFVJieZUw=", + "type": "git", + "url": "file:///home/sivizius/Projects/Active/nixfiles?dir=libs%2fstore" + }, + "original": { + "dir": "libs/store", + "owner": "sivizius", + "ref": "development", + "repo": "nixfiles", + "type": "github" + } + }, + "libstore_5": { + "inputs": { + "libcore": "libcore_14", + "nixpkgs": "nixpkgs_10" + }, + "locked": { + "dir": "libs/store", + "lastModified": 1681394603, + "narHash": "sha256-dVqGLk+tARfFNrSvOXBkAvvPtOqcbTyr9sLFVJieZUw=", + "type": "git", + "url": "file:///home/sivizius/Projects/Active/nixfiles?dir=libs%2fstore" + }, + "original": { + "dir": "libs/store", + "owner": "sivizius", + "ref": "development", + "repo": "nixfiles", + "type": "github" + } + }, + "libstore_6": { + "inputs": { + "libcore": "libcore_15", + "nixpkgs": "nixpkgs_11" + }, + "locked": { + "dir": "libs/store", + "lastModified": 1681394603, + "narHash": "sha256-dVqGLk+tARfFNrSvOXBkAvvPtOqcbTyr9sLFVJieZUw=", + "type": "git", + "url": "file:///home/sivizius/Projects/Active/nixfiles?dir=libs%2fstore" + }, + "original": { + "dir": "libs/store", + "owner": "sivizius", + "ref": "development", + "repo": "nixfiles", + "type": "github" + } + }, + "libstore_7": { + "inputs": { + "libcore": "libcore_20", + "nixpkgs": "nixpkgs_16" + }, + "locked": { + "dir": "libs/store", + "lastModified": 1681394603, + "narHash": "sha256-dVqGLk+tARfFNrSvOXBkAvvPtOqcbTyr9sLFVJieZUw=", + "type": "git", + "url": "file:///home/sivizius/Projects/Active/nixfiles?dir=libs%2fstore" + }, + "original": { + "dir": "libs/store", + "owner": "sivizius", + "ref": "development", + "repo": "nixfiles", + "type": "github" + } + }, + "libstore_8": { + "inputs": { + "libcore": "libcore_21", + "nixpkgs": "nixpkgs_17" + }, + "locked": { + "dir": "libs/store", + "lastModified": 1681394603, + "narHash": "sha256-dVqGLk+tARfFNrSvOXBkAvvPtOqcbTyr9sLFVJieZUw=", + "type": "git", + "url": "file:///home/sivizius/Projects/Active/nixfiles?dir=libs%2fstore" + }, + "original": { + "dir": "libs/store", + "owner": "sivizius", + "ref": "development", + "repo": "nixfiles", + "type": "github" + } + }, + "libstore_9": { + "inputs": { + "libcore": "libcore_25", + "nixpkgs": "nixpkgs_20" + }, + "locked": { + "dir": "libs/store", + "lastModified": 1681394603, + "narHash": "sha256-dVqGLk+tARfFNrSvOXBkAvvPtOqcbTyr9sLFVJieZUw=", + "type": "git", + "url": "file:///home/sivizius/Projects/Active/nixfiles?dir=libs%2fstore" + }, + "original": { + "dir": "libs/store", + "owner": "sivizius", + "ref": "development", + "repo": "nixfiles", + "type": "github" + } + }, + "libweb": { + "inputs": { + "libcore": "libcore_6", + "nixpkgs": "nixpkgs_4" + }, + "locked": { + "dir": "libs/web", + "lastModified": 1681394603, + "narHash": "sha256-dVqGLk+tARfFNrSvOXBkAvvPtOqcbTyr9sLFVJieZUw=", + "type": "git", + "url": "file:///home/sivizius/Projects/Active/nixfiles?dir=libs%2fweb" + }, + "original": { + "dir": "libs/web", + "owner": "sivizius", + "ref": "development", + "repo": "nixfiles", + "type": "github" + } + }, + "libweb_2": { + "inputs": { + "libcore": "libcore_11", + "nixpkgs": "nixpkgs_8" + }, + "locked": { + "dir": "libs/web", + "lastModified": 1681394603, + "narHash": "sha256-dVqGLk+tARfFNrSvOXBkAvvPtOqcbTyr9sLFVJieZUw=", + "type": "git", + "url": "file:///home/sivizius/Projects/Active/nixfiles?dir=libs%2fweb" + }, + "original": { + "dir": "libs/web", + "owner": "sivizius", + "ref": "development", + "repo": "nixfiles", + "type": "github" + } + }, + "libweb_3": { + "inputs": { + "libcore": "libcore_16", + "nixpkgs": "nixpkgs_12" + }, + "locked": { + "dir": "libs/web", + "lastModified": 1681394603, + "narHash": "sha256-dVqGLk+tARfFNrSvOXBkAvvPtOqcbTyr9sLFVJieZUw=", + "type": "git", + "url": "file:///home/sivizius/Projects/Active/nixfiles?dir=libs%2fweb" + }, + "original": { + "dir": "libs/web", + "owner": "sivizius", + "ref": "development", + "repo": "nixfiles", + "type": "github" + } + }, + "libweb_4": { + "inputs": { + "libcore": "libcore_22", + "nixpkgs": "nixpkgs_18" + }, + "locked": { + "dir": "libs/web", + "lastModified": 1681394603, + "narHash": "sha256-dVqGLk+tARfFNrSvOXBkAvvPtOqcbTyr9sLFVJieZUw=", + "type": "git", + "url": "file:///home/sivizius/Projects/Active/nixfiles?dir=libs%2fweb" + }, + "original": { + "dir": "libs/web", + "owner": "sivizius", + "ref": "development", + "repo": "nixfiles", + "type": "github" + } + }, + "libweb_5": { + "inputs": { + "libcore": "libcore_30", + "nixpkgs": "nixpkgs_23" + }, + "locked": { + "dir": "libs/web", + "lastModified": 1681394603, + "narHash": "sha256-dVqGLk+tARfFNrSvOXBkAvvPtOqcbTyr9sLFVJieZUw=", + "type": "git", + "url": "file:///home/sivizius/Projects/Active/nixfiles?dir=libs%2fweb" + }, + "original": { + "dir": "libs/web", + "owner": "sivizius", + "ref": "development", + "repo": "nixfiles", + "type": "github" + } + }, + "libweb_6": { + "inputs": { + "libcore": "libcore_36", + "nixpkgs": "nixpkgs_28" + }, + "locked": { + "dir": "libs/web", + "lastModified": 1681394603, + "narHash": "sha256-dVqGLk+tARfFNrSvOXBkAvvPtOqcbTyr9sLFVJieZUw=", + "type": "git", + "url": "file:///home/sivizius/Projects/Active/nixfiles?dir=libs%2fweb" + }, + "original": { + "dir": "libs/web", + "owner": "sivizius", + "ref": "development", + "repo": "nixfiles", + "type": "github" + } + }, + "libweb_7": { + "inputs": { + "libcore": "libcore_37", + "nixpkgs": "nixpkgs_30" + }, + "locked": { + "dir": "libs/web", + "lastModified": 1681394603, + "narHash": "sha256-dVqGLk+tARfFNrSvOXBkAvvPtOqcbTyr9sLFVJieZUw=", + "type": "git", + "url": "file:///home/sivizius/Projects/Active/nixfiles?dir=libs%2fweb" + }, + "original": { + "dir": "libs/web", + "owner": "sivizius", + "ref": "development", + "repo": "nixfiles", + "type": "github" + } + }, + "libweb_8": { + "inputs": { + "libcore": "libcore_43", + "nixpkgs": "nixpkgs_34" + }, + "locked": { + "dir": "libs/web", + "lastModified": 1681394603, + "narHash": "sha256-dVqGLk+tARfFNrSvOXBkAvvPtOqcbTyr9sLFVJieZUw=", + "type": "git", + "url": "file:///home/sivizius/Projects/Active/nixfiles?dir=libs%2fweb" + }, + "original": { + "dir": "libs/web", + "owner": "sivizius", + "ref": "development", + "repo": "nixfiles", + "type": "github" + } + }, + "libweb_9": { + "inputs": { + "libcore": "libcore_51", + "nixpkgs": "nixpkgs_42" + }, + "locked": { + "dir": "libs/web", + "lastModified": 1681394603, + "narHash": "sha256-dVqGLk+tARfFNrSvOXBkAvvPtOqcbTyr9sLFVJieZUw=", + "type": "git", + "url": "file:///home/sivizius/Projects/Active/nixfiles?dir=libs%2fweb" + }, + "original": { + "dir": "libs/web", + "owner": "sivizius", + "ref": "development", + "repo": "nixfiles", + "type": "github" + } + }, + "lowdown-src": { + "flake": false, + "locked": { + "lastModified": 1633514407, + "narHash": "sha256-Dw32tiMjdK9t3ETl5fzGrutQTzh2rufgZV4A/BbxuD4=", + "owner": "kristapsdz", + "repo": "lowdown", + "rev": "d2c2b44ff6c27b936ec27358a2653caaef8f73b8", + "type": "github" + }, + "original": { + "owner": "kristapsdz", + "repo": "lowdown", + "type": "github" + } + }, + "modules": { + "inputs": { + "home-manager": "home-manager_3", + "libconfig": "libconfig_2", + "libcore": "libcore_17", + "nixpkgs": "nixpkgs_14", + "simple-nix-mailserver": "simple-nix-mailserver" + }, + "locked": { + "dir": "modules", + "lastModified": 1681394603, + "narHash": "sha256-dVqGLk+tARfFNrSvOXBkAvvPtOqcbTyr9sLFVJieZUw=", + "type": "git", + "url": "file:///home/sivizius/Projects/Active/nixfiles?dir=modules" + }, + "original": { + "dir": "modules", + "owner": "sivizius", + "ref": "development", + "repo": "nixfiles", + "type": "github" + } + }, + "nix": { + "inputs": { + "flake-compat": "flake-compat_2", + "lowdown-src": "lowdown-src", + "nixpkgs": "nixpkgs_36", + "nixpkgs-regression": "nixpkgs-regression" + }, + "locked": { + "lastModified": 1680692819, + "narHash": "sha256-0mPy3jzHAAeptB+7ZxJUwo3OO3c3MONMbZ5JzoeAmac=", + "owner": "NixOS", + "repo": "nix", + "rev": "bbdb5a58c7204893119ed8c13c55d0dea0f82e35", + "type": "github" + }, + "original": { + "id": "nix", + "type": "indirect" + } + }, + "nixpkgs": { + "locked": { + "lastModified": 1680213900, + "narHash": "sha256-cIDr5WZIj3EkKyCgj/6j3HBH4Jj1W296z7HTcWj1aMA=", + "owner": "nixos", + "repo": "nixpkgs", + "rev": "e3652e0735fbec227f342712f180f4f21f0594f2", + "type": "github" + }, + "original": { + "owner": "nixos", + "ref": "nixos-unstable", + "repo": "nixpkgs", + "type": "github" + } + }, + "nixpkgs-22_11": { + "locked": { + "lastModified": 1669558522, + "narHash": "sha256-yqxn+wOiPqe6cxzOo4leeJOp1bXE/fjPEi/3F/bBHv8=", + "owner": "NixOS", + "repo": "nixpkgs", + "rev": "ce5fe99df1f15a09a91a86be9738d68fadfbad82", + "type": "github" + }, + "original": { + "id": "nixpkgs", + "ref": "nixos-22.11", + "type": "indirect" + } + }, + "nixpkgs-regression": { + "locked": { + "lastModified": 1643052045, + "narHash": "sha256-uGJ0VXIhWKGXxkeNnq4TvV3CIOkUJ3PAoLZ3HMzNVMw=", + "owner": "NixOS", + "repo": "nixpkgs", + "rev": "215d4d0fd80ca5163643b03a33fde804a29cc1e2", + "type": "github" + }, + "original": { + "owner": "NixOS", + "repo": "nixpkgs", + "rev": "215d4d0fd80ca5163643b03a33fde804a29cc1e2", + "type": "github" + } + }, + "nixpkgs_10": { + "locked": { + "lastModified": 1680668850, + "narHash": "sha256-mQMg13yRsS0LXVzaeoSPwqgPO6yhkGzGewPgMSqXSv8=", + "owner": "NixOS", + "repo": "nixpkgs", + "rev": "4a65e9f64e53fdca6eed31adba836717a11247d2", + "type": "github" + }, + "original": { + "id": "nixpkgs", + "type": "indirect" + } + }, + "nixpkgs_11": { + "locked": { + "lastModified": 1680668850, + "narHash": "sha256-mQMg13yRsS0LXVzaeoSPwqgPO6yhkGzGewPgMSqXSv8=", + "owner": "NixOS", + "repo": "nixpkgs", + "rev": "4a65e9f64e53fdca6eed31adba836717a11247d2", + "type": "github" + }, + "original": { + "id": "nixpkgs", + "type": "indirect" + } + }, + "nixpkgs_12": { + "locked": { + "lastModified": 1680729571, + "narHash": "sha256-10Tki8UBF9MNQn2B6mFxDdX1T0QYQ5UHDYMvgCeRNXg=", + "owner": "sivizius", + "repo": "nixpkgs", + "rev": "38901127a4d0accdb89e3426f7d8dc32419dbc6d", + "type": "github" + }, + "original": { + "owner": "sivizius", + "ref": "master", + "repo": "nixpkgs", + "type": "github" + } + }, + "nixpkgs_13": { + "locked": { + "lastModified": 1680729571, + "narHash": "sha256-10Tki8UBF9MNQn2B6mFxDdX1T0QYQ5UHDYMvgCeRNXg=", + "owner": "sivizius", + "repo": "nixpkgs", + "rev": "38901127a4d0accdb89e3426f7d8dc32419dbc6d", + "type": "github" + }, + "original": { + "owner": "sivizius", + "ref": "master", + "repo": "nixpkgs", + "type": "github" + } + }, + "nixpkgs_14": { + "locked": { + "lastModified": 1680729571, + "narHash": "sha256-10Tki8UBF9MNQn2B6mFxDdX1T0QYQ5UHDYMvgCeRNXg=", + "owner": "sivizius", + "repo": "nixpkgs", + "rev": "38901127a4d0accdb89e3426f7d8dc32419dbc6d", + "type": "github" + }, + "original": { + "owner": "sivizius", + "ref": "master", + "repo": "nixpkgs", + "type": "github" + } + }, + "nixpkgs_15": { + "locked": { + "lastModified": 1670751203, + "narHash": "sha256-XdoH1v3shKDGlrwjgrNX/EN8s3c+kQV7xY6cLCE8vcI=", + "owner": "NixOS", + "repo": "nixpkgs", + "rev": "64e0bf055f9d25928c31fb12924e59ff8ce71e60", + "type": "github" + }, + "original": { + "id": "nixpkgs", + "ref": "nixos-unstable", + "type": "indirect" + } + }, + "nixpkgs_16": { + "locked": { + "lastModified": 1680668850, + "narHash": "sha256-mQMg13yRsS0LXVzaeoSPwqgPO6yhkGzGewPgMSqXSv8=", + "owner": "NixOS", + "repo": "nixpkgs", + "rev": "4a65e9f64e53fdca6eed31adba836717a11247d2", + "type": "github" + }, + "original": { + "id": "nixpkgs", + "type": "indirect" + } + }, + "nixpkgs_17": { + "locked": { + "lastModified": 1680668850, + "narHash": "sha256-mQMg13yRsS0LXVzaeoSPwqgPO6yhkGzGewPgMSqXSv8=", + "owner": "NixOS", + "repo": "nixpkgs", + "rev": "4a65e9f64e53fdca6eed31adba836717a11247d2", + "type": "github" + }, + "original": { + "id": "nixpkgs", + "type": "indirect" + } + }, + "nixpkgs_18": { + "locked": { + "lastModified": 1680729571, + "narHash": "sha256-10Tki8UBF9MNQn2B6mFxDdX1T0QYQ5UHDYMvgCeRNXg=", + "owner": "sivizius", + "repo": "nixpkgs", + "rev": "38901127a4d0accdb89e3426f7d8dc32419dbc6d", + "type": "github" + }, + "original": { + "owner": "sivizius", + "ref": "master", + "repo": "nixpkgs", + "type": "github" + } + }, + "nixpkgs_19": { + "locked": { + "lastModified": 1680729571, + "narHash": "sha256-10Tki8UBF9MNQn2B6mFxDdX1T0QYQ5UHDYMvgCeRNXg=", + "owner": "sivizius", + "repo": "nixpkgs", + "rev": "38901127a4d0accdb89e3426f7d8dc32419dbc6d", + "type": "github" + }, + "original": { + "owner": "sivizius", + "ref": "master", + "repo": "nixpkgs", + "type": "github" + } + }, + "nixpkgs_2": { + "locked": { + "lastModified": 1680668850, + "narHash": "sha256-mQMg13yRsS0LXVzaeoSPwqgPO6yhkGzGewPgMSqXSv8=", + "owner": "NixOS", + "repo": "nixpkgs", + "rev": "4a65e9f64e53fdca6eed31adba836717a11247d2", + "type": "github" + }, + "original": { + "id": "nixpkgs", + "type": "indirect" + } + }, + "nixpkgs_20": { + "locked": { + "lastModified": 1680668850, + "narHash": "sha256-mQMg13yRsS0LXVzaeoSPwqgPO6yhkGzGewPgMSqXSv8=", + "owner": "NixOS", + "repo": "nixpkgs", + "rev": "4a65e9f64e53fdca6eed31adba836717a11247d2", + "type": "github" + }, + "original": { + "id": "nixpkgs", + "type": "indirect" + } + }, + "nixpkgs_21": { + "locked": { + "lastModified": 1680668850, + "narHash": "sha256-mQMg13yRsS0LXVzaeoSPwqgPO6yhkGzGewPgMSqXSv8=", + "owner": "NixOS", + "repo": "nixpkgs", + "rev": "4a65e9f64e53fdca6eed31adba836717a11247d2", + "type": "github" + }, + "original": { + "id": "nixpkgs", + "type": "indirect" + } + }, + "nixpkgs_22": { + "locked": { + "lastModified": 1680668850, + "narHash": "sha256-mQMg13yRsS0LXVzaeoSPwqgPO6yhkGzGewPgMSqXSv8=", + "owner": "NixOS", + "repo": "nixpkgs", + "rev": "4a65e9f64e53fdca6eed31adba836717a11247d2", + "type": "github" + }, + "original": { + "id": "nixpkgs", + "type": "indirect" + } + }, + "nixpkgs_23": { + "locked": { + "lastModified": 1680729571, + "narHash": "sha256-10Tki8UBF9MNQn2B6mFxDdX1T0QYQ5UHDYMvgCeRNXg=", + "owner": "sivizius", + "repo": "nixpkgs", + "rev": "38901127a4d0accdb89e3426f7d8dc32419dbc6d", + "type": "github" + }, + "original": { + "owner": "sivizius", + "ref": "master", + "repo": "nixpkgs", + "type": "github" + } + }, + "nixpkgs_24": { + "locked": { + "lastModified": 1680729571, + "narHash": "sha256-10Tki8UBF9MNQn2B6mFxDdX1T0QYQ5UHDYMvgCeRNXg=", + "owner": "sivizius", + "repo": "nixpkgs", + "rev": "38901127a4d0accdb89e3426f7d8dc32419dbc6d", + "type": "github" + }, + "original": { + "owner": "sivizius", + "ref": "master", + "repo": "nixpkgs", + "type": "github" + } + }, + "nixpkgs_25": { + "locked": { + "lastModified": 1680729571, + "narHash": "sha256-10Tki8UBF9MNQn2B6mFxDdX1T0QYQ5UHDYMvgCeRNXg=", + "owner": "sivizius", + "repo": "nixpkgs", + "rev": "38901127a4d0accdb89e3426f7d8dc32419dbc6d", + "type": "github" + }, + "original": { + "owner": "sivizius", + "ref": "master", + "repo": "nixpkgs", + "type": "github" + } + }, + "nixpkgs_26": { + "locked": { + "lastModified": 1680668850, + "narHash": "sha256-mQMg13yRsS0LXVzaeoSPwqgPO6yhkGzGewPgMSqXSv8=", + "owner": "NixOS", + "repo": "nixpkgs", + "rev": "4a65e9f64e53fdca6eed31adba836717a11247d2", + "type": "github" + }, + "original": { + "id": "nixpkgs", + "type": "indirect" + } + }, + "nixpkgs_27": { + "locked": { + "lastModified": 1680668850, + "narHash": "sha256-mQMg13yRsS0LXVzaeoSPwqgPO6yhkGzGewPgMSqXSv8=", + "owner": "NixOS", + "repo": "nixpkgs", + "rev": "4a65e9f64e53fdca6eed31adba836717a11247d2", + "type": "github" + }, + "original": { + "id": "nixpkgs", + "type": "indirect" + } + }, + "nixpkgs_28": { + "locked": { + "lastModified": 1680729571, + "narHash": "sha256-10Tki8UBF9MNQn2B6mFxDdX1T0QYQ5UHDYMvgCeRNXg=", + "owner": "sivizius", + "repo": "nixpkgs", + "rev": "38901127a4d0accdb89e3426f7d8dc32419dbc6d", + "type": "github" + }, + "original": { + "owner": "sivizius", + "ref": "master", + "repo": "nixpkgs", + "type": "github" + } + }, + "nixpkgs_29": { + "locked": { + "lastModified": 1680729571, + "narHash": "sha256-10Tki8UBF9MNQn2B6mFxDdX1T0QYQ5UHDYMvgCeRNXg=", + "owner": "sivizius", + "repo": "nixpkgs", + "rev": "38901127a4d0accdb89e3426f7d8dc32419dbc6d", + "type": "github" + }, + "original": { + "owner": "sivizius", + "ref": "master", + "repo": "nixpkgs", + "type": "github" + } + }, + "nixpkgs_3": { + "locked": { + "lastModified": 1680668850, + "narHash": "sha256-mQMg13yRsS0LXVzaeoSPwqgPO6yhkGzGewPgMSqXSv8=", + "owner": "NixOS", + "repo": "nixpkgs", + "rev": "4a65e9f64e53fdca6eed31adba836717a11247d2", + "type": "github" + }, + "original": { + "id": "nixpkgs", + "type": "indirect" + } + }, + "nixpkgs_30": { + "locked": { + "lastModified": 1680729571, + "narHash": "sha256-10Tki8UBF9MNQn2B6mFxDdX1T0QYQ5UHDYMvgCeRNXg=", + "owner": "sivizius", + "repo": "nixpkgs", + "rev": "38901127a4d0accdb89e3426f7d8dc32419dbc6d", + "type": "github" + }, + "original": { + "owner": "sivizius", + "ref": "master", + "repo": "nixpkgs", + "type": "github" + } + }, + "nixpkgs_31": { + "locked": { + "lastModified": 1680729571, + "narHash": "sha256-10Tki8UBF9MNQn2B6mFxDdX1T0QYQ5UHDYMvgCeRNXg=", + "owner": "sivizius", + "repo": "nixpkgs", + "rev": "38901127a4d0accdb89e3426f7d8dc32419dbc6d", + "type": "github" + }, + "original": { + "owner": "sivizius", + "ref": "master", + "repo": "nixpkgs", + "type": "github" + } + }, + "nixpkgs_32": { + "locked": { + "lastModified": 1680668850, + "narHash": "sha256-mQMg13yRsS0LXVzaeoSPwqgPO6yhkGzGewPgMSqXSv8=", + "owner": "NixOS", + "repo": "nixpkgs", + "rev": "4a65e9f64e53fdca6eed31adba836717a11247d2", + "type": "github" + }, + "original": { + "id": "nixpkgs", + "type": "indirect" + } + }, + "nixpkgs_33": { + "locked": { + "lastModified": 1680668850, + "narHash": "sha256-mQMg13yRsS0LXVzaeoSPwqgPO6yhkGzGewPgMSqXSv8=", + "owner": "NixOS", + "repo": "nixpkgs", + "rev": "4a65e9f64e53fdca6eed31adba836717a11247d2", + "type": "github" + }, + "original": { + "id": "nixpkgs", + "type": "indirect" + } + }, + "nixpkgs_34": { + "locked": { + "lastModified": 1680729571, + "narHash": "sha256-10Tki8UBF9MNQn2B6mFxDdX1T0QYQ5UHDYMvgCeRNXg=", + "owner": "sivizius", + "repo": "nixpkgs", + "rev": "38901127a4d0accdb89e3426f7d8dc32419dbc6d", + "type": "github" + }, + "original": { + "owner": "sivizius", + "ref": "master", + "repo": "nixpkgs", + "type": "github" + } + }, + "nixpkgs_35": { + "locked": { + "lastModified": 1680729571, + "narHash": "sha256-10Tki8UBF9MNQn2B6mFxDdX1T0QYQ5UHDYMvgCeRNXg=", + "owner": "sivizius", + "repo": "nixpkgs", + "rev": "38901127a4d0accdb89e3426f7d8dc32419dbc6d", + "type": "github" + }, + "original": { + "owner": "sivizius", + "ref": "master", + "repo": "nixpkgs", + "type": "github" + } + }, + "nixpkgs_36": { + "locked": { + "lastModified": 1670461440, + "narHash": "sha256-jy1LB8HOMKGJEGXgzFRLDU1CBGL0/LlkolgnqIsF0D8=", + "owner": "NixOS", + "repo": "nixpkgs", + "rev": "04a75b2eecc0acf6239acf9dd04485ff8d14f425", + "type": "github" + }, + "original": { + "owner": "NixOS", + "ref": "nixos-22.11-small", + "repo": "nixpkgs", + "type": "github" + } + }, + "nixpkgs_37": { + "locked": { + "lastModified": 1680729571, + "narHash": "sha256-10Tki8UBF9MNQn2B6mFxDdX1T0QYQ5UHDYMvgCeRNXg=", + "owner": "sivizius", + "repo": "nixpkgs", + "rev": "38901127a4d0accdb89e3426f7d8dc32419dbc6d", + "type": "github" + }, + "original": { + "owner": "sivizius", + "ref": "master", + "repo": "nixpkgs", + "type": "github" + } + }, + "nixpkgs_38": { + "locked": { + "lastModified": 1680729571, + "narHash": "sha256-10Tki8UBF9MNQn2B6mFxDdX1T0QYQ5UHDYMvgCeRNXg=", + "owner": "sivizius", + "repo": "nixpkgs", + "rev": "38901127a4d0accdb89e3426f7d8dc32419dbc6d", + "type": "github" + }, + "original": { + "owner": "sivizius", + "ref": "master", + "repo": "nixpkgs", + "type": "github" + } + }, + "nixpkgs_39": { + "locked": { + "lastModified": 1680729571, + "narHash": "sha256-10Tki8UBF9MNQn2B6mFxDdX1T0QYQ5UHDYMvgCeRNXg=", + "owner": "sivizius", + "repo": "nixpkgs", + "rev": "38901127a4d0accdb89e3426f7d8dc32419dbc6d", + "type": "github" + }, + "original": { + "owner": "sivizius", + "ref": "master", + "repo": "nixpkgs", + "type": "github" + } + }, + "nixpkgs_4": { + "locked": { + "lastModified": 1680729571, + "narHash": "sha256-10Tki8UBF9MNQn2B6mFxDdX1T0QYQ5UHDYMvgCeRNXg=", + "owner": "sivizius", + "repo": "nixpkgs", + "rev": "38901127a4d0accdb89e3426f7d8dc32419dbc6d", + "type": "github" + }, + "original": { + "owner": "sivizius", + "ref": "master", + "repo": "nixpkgs", + "type": "github" + } + }, + "nixpkgs_40": { + "locked": { + "lastModified": 1680668850, + "narHash": "sha256-mQMg13yRsS0LXVzaeoSPwqgPO6yhkGzGewPgMSqXSv8=", + "owner": "NixOS", + "repo": "nixpkgs", + "rev": "4a65e9f64e53fdca6eed31adba836717a11247d2", + "type": "github" + }, + "original": { + "id": "nixpkgs", + "type": "indirect" + } + }, + "nixpkgs_41": { + "locked": { + "lastModified": 1680668850, + "narHash": "sha256-mQMg13yRsS0LXVzaeoSPwqgPO6yhkGzGewPgMSqXSv8=", + "owner": "NixOS", + "repo": "nixpkgs", + "rev": "4a65e9f64e53fdca6eed31adba836717a11247d2", + "type": "github" + }, + "original": { + "id": "nixpkgs", + "type": "indirect" + } + }, + "nixpkgs_42": { + "locked": { + "lastModified": 1680729571, + "narHash": "sha256-10Tki8UBF9MNQn2B6mFxDdX1T0QYQ5UHDYMvgCeRNXg=", + "owner": "sivizius", + "repo": "nixpkgs", + "rev": "38901127a4d0accdb89e3426f7d8dc32419dbc6d", + "type": "github" + }, + "original": { + "owner": "sivizius", + "ref": "master", + "repo": "nixpkgs", + "type": "github" + } + }, + "nixpkgs_43": { + "locked": { + "lastModified": 1680729571, + "narHash": "sha256-10Tki8UBF9MNQn2B6mFxDdX1T0QYQ5UHDYMvgCeRNXg=", + "owner": "sivizius", + "repo": "nixpkgs", + "rev": "38901127a4d0accdb89e3426f7d8dc32419dbc6d", + "type": "github" + }, + "original": { + "owner": "sivizius", + "ref": "master", + "repo": "nixpkgs", + "type": "github" + } + }, + "nixpkgs_5": { + "locked": { + "lastModified": 1680729571, + "narHash": "sha256-10Tki8UBF9MNQn2B6mFxDdX1T0QYQ5UHDYMvgCeRNXg=", + "owner": "sivizius", + "repo": "nixpkgs", + "rev": "38901127a4d0accdb89e3426f7d8dc32419dbc6d", + "type": "github" + }, + "original": { + "owner": "sivizius", + "ref": "master", + "repo": "nixpkgs", + "type": "github" + } + }, + "nixpkgs_6": { + "locked": { + "lastModified": 1680668850, + "narHash": "sha256-mQMg13yRsS0LXVzaeoSPwqgPO6yhkGzGewPgMSqXSv8=", + "owner": "NixOS", + "repo": "nixpkgs", + "rev": "4a65e9f64e53fdca6eed31adba836717a11247d2", + "type": "github" + }, + "original": { + "id": "nixpkgs", + "type": "indirect" + } + }, + "nixpkgs_7": { + "locked": { + "lastModified": 1680668850, + "narHash": "sha256-mQMg13yRsS0LXVzaeoSPwqgPO6yhkGzGewPgMSqXSv8=", + "owner": "NixOS", + "repo": "nixpkgs", + "rev": "4a65e9f64e53fdca6eed31adba836717a11247d2", + "type": "github" + }, + "original": { + "id": "nixpkgs", + "type": "indirect" + } + }, + "nixpkgs_8": { + "locked": { + "lastModified": 1680729571, + "narHash": "sha256-10Tki8UBF9MNQn2B6mFxDdX1T0QYQ5UHDYMvgCeRNXg=", + "owner": "sivizius", + "repo": "nixpkgs", + "rev": "38901127a4d0accdb89e3426f7d8dc32419dbc6d", + "type": "github" + }, + "original": { + "owner": "sivizius", + "ref": "master", + "repo": "nixpkgs", + "type": "github" + } + }, + "nixpkgs_9": { + "locked": { + "lastModified": 1680213900, + "narHash": "sha256-cIDr5WZIj3EkKyCgj/6j3HBH4Jj1W296z7HTcWj1aMA=", + "owner": "nixos", + "repo": "nixpkgs", + "rev": "e3652e0735fbec227f342712f180f4f21f0594f2", + "type": "github" + }, + "original": { + "owner": "nixos", + "ref": "nixos-unstable", + "repo": "nixpkgs", + "type": "github" + } + }, + "peers": { + "inputs": { + "libconfig": "libconfig_3", + "libcore": "libcore_23", + "libsecrets": "libsecrets_5" + }, + "locked": { + "dir": "peers", + "lastModified": 1681394603, + "narHash": "sha256-dVqGLk+tARfFNrSvOXBkAvvPtOqcbTyr9sLFVJieZUw=", + "type": "git", + "url": "file:///home/sivizius/Projects/Active/nixfiles?dir=peers" + }, + "original": { + "dir": "peers", + "owner": "sivizius", + "ref": "development", + "repo": "nixfiles", + "type": "github" + } + }, + "profiles": { + "inputs": { + "libconfig": "libconfig_4", + "libcore": "libcore_31", + "nixpkgs": "nixpkgs_25", + "services": "services" + }, + "locked": { + "dir": "profiles", + "lastModified": 1681394603, + "narHash": "sha256-dVqGLk+tARfFNrSvOXBkAvvPtOqcbTyr9sLFVJieZUw=", + "type": "git", + "url": "file:///home/sivizius/Projects/Active/nixfiles?dir=profiles" + }, + "original": { + "dir": "profiles", + "owner": "sivizius", + "ref": "development", + "repo": "nixfiles", + "type": "github" + } + }, + "redshift-wayland": { + "inputs": { + "libcore": "libcore_45", + "nixpkgs": "nixpkgs_38", + "redshift-wayland": "redshift-wayland_2" + }, + "locked": { + "dir": "packages/redshift-wayland", + "lastModified": 1681394603, + "narHash": "sha256-dVqGLk+tARfFNrSvOXBkAvvPtOqcbTyr9sLFVJieZUw=", + "type": "git", + "url": "file:///home/sivizius/Projects/Active/nixfiles?dir=packages%2fredshift-wayland" + }, + "original": { + "dir": "packages/redshift-wayland", + "owner": "sivizius", + "ref": "development", + "repo": "nixfiles", + "type": "github" + } + }, + "redshift-wayland_2": { + "flake": false, + "locked": { + "lastModified": 1566660017, + "narHash": "sha256-pyR7xNdi/83NSoC2WIrX8U+A6nU+vZBlePLXrQZnc1k=", + "owner": "minus7", + "repo": "redshift", + "rev": "7da875d34854a6a34612d5ce4bd8718c32bec804", + "type": "github" + }, + "original": { + "owner": "minus7", + "repo": "redshift", + "rev": "7da875d34854a6a34612d5ce4bd8718c32bec804", + "type": "github" + } + }, + "registries": { + "inputs": { + "fork-awesome": "fork-awesome", + "libconfig": "libconfig_6", + "libcore": "libcore_44", + "nix": "nix", + "nixpkgs": "nixpkgs_37", + "redshift-wayland": "redshift-wayland", + "wofi-unpatched": "wofi-unpatched" + }, + "locked": { + "dir": "registries", + "lastModified": 1681394603, + "narHash": "sha256-dVqGLk+tARfFNrSvOXBkAvvPtOqcbTyr9sLFVJieZUw=", + "type": "git", + "url": "file:///home/sivizius/Projects/Active/nixfiles?dir=registries" + }, + "original": { + "dir": "registries", + "owner": "sivizius", + "ref": "development", + "repo": "nixfiles", + "type": "github" + } + }, + "root": { + "inputs": { + "home-manager": "home-manager", + "libconfig": "libconfig", + "libcore": "libcore_7", + "libsecrets": "libsecrets_2", + "libstore": "libstore_4", + "libweb": "libweb_2", + "modules": "modules", + "peers": "peers", + "profiles": "profiles", + "registries": "registries", + "sivizius": "sivizius" + } + }, + "services": { + "inputs": { + "libconfig": "libconfig_5", + "libweb": "libweb_7" + }, + "locked": { + "dir": "services", + "lastModified": 1681394603, + "narHash": "sha256-dVqGLk+tARfFNrSvOXBkAvvPtOqcbTyr9sLFVJieZUw=", + "type": "git", + "url": "file:///home/sivizius/Projects/Active/nixfiles?dir=services" + }, + "original": { + "dir": "services", + "owner": "sivizius", + "ref": "development", + "repo": "nixfiles", + "type": "github" + } + }, + "simple-nix-mailserver": { + "inputs": { + "blobs": "blobs", + "flake-compat": "flake-compat", + "nixpkgs": "nixpkgs_15", + "nixpkgs-22_11": "nixpkgs-22_11", + "utils": "utils_3" + }, + "locked": { + "lastModified": 1671738303, + "narHash": "sha256-PRgqtaWf2kMSYqVmcnmhTh+UsC0RmvXRTr+EOw5VZUA=", + "ref": "refs/heads/master", + "rev": "6d0d9fb966cc565a3df74d3b686f924c7615118c", + "revCount": 544, + "type": "git", + "url": "https://gitlab.com/simple-nixos-mailserver/nixos-mailserver.git" + }, + "original": { + "type": "git", + "url": "https://gitlab.com/simple-nixos-mailserver/nixos-mailserver.git" + } + }, + "sivizius": { + "inputs": { + "libconfig": "libconfig_7", + "libcore": "libcore_52" + }, + "locked": { + "dir": "users/sivizius", + "lastModified": 1681394603, + "narHash": "sha256-dVqGLk+tARfFNrSvOXBkAvvPtOqcbTyr9sLFVJieZUw=", + "type": "git", + "url": "file:///home/sivizius/Projects/Active/nixfiles?dir=users%2fsivizius" + }, + "original": { + "dir": "users/sivizius", + "owner": "sivizius", + "ref": "development", + "repo": "nixfiles", + "type": "github" + } + }, + "utils": { + "locked": { + "lastModified": 1678901627, + "narHash": "sha256-U02riOqrKKzwjsxc/400XnElV+UtPUQWpANPlyazjH0=", + "owner": "numtide", + "repo": "flake-utils", + "rev": "93a2b84fc4b70d9e089d029deacc3583435c2ed6", + "type": "github" + }, + "original": { + "owner": "numtide", + "repo": "flake-utils", + "type": "github" + } + }, + "utils_2": { + "locked": { + "lastModified": 1678901627, + "narHash": "sha256-U02riOqrKKzwjsxc/400XnElV+UtPUQWpANPlyazjH0=", + "owner": "numtide", + "repo": "flake-utils", + "rev": "93a2b84fc4b70d9e089d029deacc3583435c2ed6", + "type": "github" + }, + "original": { + "owner": "numtide", + "repo": "flake-utils", + "type": "github" + } + }, + "utils_3": { + "locked": { + "lastModified": 1605370193, + "narHash": "sha256-YyMTf3URDL/otKdKgtoMChu4vfVL3vCMkRqpGifhUn0=", + "owner": "numtide", + "repo": "flake-utils", + "rev": "5021eac20303a61fafe17224c087f5519baed54d", + "type": "github" + }, + "original": { + "owner": "numtide", + "repo": "flake-utils", + "type": "github" + } + }, + "wofi-unpatched": { + "inputs": { + "libcore": "libcore_46", + "nixpkgs": "nixpkgs_39" + }, + "locked": { + "dir": "packages/wofi-unpatched", + "lastModified": 1681394603, + "narHash": "sha256-dVqGLk+tARfFNrSvOXBkAvvPtOqcbTyr9sLFVJieZUw=", + "type": "git", + "url": "file:///home/sivizius/Projects/Active/nixfiles?dir=packages%2fwofi-unpatched" + }, + "original": { + "dir": "packages/wofi-unpatched", + "owner": "sivizius", + "ref": "development", + "repo": "nixfiles", + "type": "github" + } + } + }, + "root": "root", + "version": 7 +} diff --git a/hosts/flake.nix b/hosts/flake.nix new file mode 100644 index 0000000..62ebf52 --- /dev/null +++ b/hosts/flake.nix @@ -0,0 +1,83 @@ +{ + description = "Sivizius’ hosts."; + inputs + = { + home-manager.url = "github:sivizius/nixfiles/development?dir=home-manager"; + libconfig.url = "github:sivizius/nixfiles/development?dir=libs/config"; + libcore.url = "github:sivizius/nixfiles/development?dir=libs/core"; + libsecrets.url = "github:sivizius/nixfiles/development?dir=libs/secrets"; + libstore.url = "github:sivizius/nixfiles/development?dir=libs/store"; + libweb.url = "github:sivizius/nixfiles/development?dir=libs/web"; + modules.url = "github:sivizius/nixfiles/development?dir=modules"; + peers.url = "github:sivizius/nixfiles/development?dir=peers"; + profiles.url = "github:sivizius/nixfiles/development?dir=profiles"; + registries.url = "github:sivizius/nixfiles/development?dir=registries"; + sivizius.url = "github:sivizius/nixfiles/development?dir=users/sivizius"; + }; + outputs + = { self, home-manager, libconfig, libcore, libsecrets, libstore, libweb, modules, peers, profiles, registries, sivizius, ... }: + let + config = libconfig.lib { inherit self; }; + core = libcore.lib { inherit self; debug.logLevel = "info"; }; + secrets = libsecrets.lib { inherit self; }; + + inherit(core) set target time; + inherit(config.hosts) Host PrepareArgument load; + + hosts + = load ./. + { + modules = modules.legacyModules.nixos; + } + { + inherit core self; + inherit(peers) peers; + inherit(profiles) profiles; + inherit(secrets) secret; + web = libweb.lib { inherit self; }; + + dateTime = time.parseDateTime self.lastModifiedDate; + home-manager = home-manager.lib; + registries = PrepareArgument registries.registries; + store = libstore.lib; + users + = { + sivizius = sivizius.user; + }; + }; + + filteredHosts = set.filterValue (Host.isInstanceOf) hosts; + + packages + = target.System.mapStdenv + ( + buildSystem: + set.mapValues + ({ nixosConfiguration, ... }: nixosConfiguration."${buildSystem}".config.system.build.toplevel) + filteredHosts + ); + in + { + inherit hosts packages; + + apps + = target.System.mapStdenv + ( + buildSystem: + set.mapValues + ( + program: + { + type = "app"; + inherit program; + } + ) + packages + ); + + nixosConfigurations + = set.mapValues + ({ nixosConfiguration, system, ... }: nixosConfiguration."${system}") + filteredHosts; + }; +} diff --git a/hosts/gimel/config.nix b/hosts/gimel/config.nix new file mode 100644 index 0000000..21a2e2d --- /dev/null +++ b/hosts/gimel/config.nix @@ -0,0 +1,42 @@ +# TODO: Refactor things + +# gimel (third hebrew character) is usually installed on sivizius@gimel.sivizius.eu +{ config, ... }: +{ + imports = + [ + ./hardware + + # Services + #../../services/blog.nix + ../../services/gitea.nix + ../../services/home-manager.nix + ../../services/monitoring.nix + ../../services/nginx.nix + ]; + + documentation.enable = false; + + self = + { + domain = "sivizius.eu"; + hostName = "gimel"; + ipv4addr = "45.158.41.100"; + ipv6addr = "2a0f:5381::4"; + ipv6range = "2a0f:5381::/64"; + legacyTLS = true; + ports = + { + exporters = + { + bind = 9119; + nginx = 9113; + node = 9100; + }; + gitea = 3000; + grafana = 3001; + prometheus = 9090; + }; + secrets = ./secrets; + }; +} diff --git a/hosts/gimel/default.nix b/hosts/gimel/default.nix new file mode 100644 index 0000000..a789e6b --- /dev/null +++ b/hosts/gimel/default.nix @@ -0,0 +1,9 @@ +{ lib, networks, profiles, users, ... }: +let + inherit(lib.deploy) hosts mount; + inherit(hosts) Host Network Peer; + inherit(mount) XFS VFAT; +in + Host "gimel (third hebrew character) is usually installed on sivizius@gimel.sivizius.eu." + { + } \ No newline at end of file diff --git a/hosts/gimel/hardware/default.nix b/hosts/gimel/hardware/default.nix new file mode 100644 index 0000000..161495d --- /dev/null +++ b/hosts/gimel/hardware/default.nix @@ -0,0 +1,64 @@ +{ config, modulesPath, registries, ... }: +{ + imports = + [ + ( modulesPath + "/profiles/qemu-guest.nix" ) + ./network + ]; + + boot = + { + extraModulePackages = [ ]; + initrd = + { + availableKernelModules = + [ + "ahci" + "sr_mod" + "virtio_blk" + "virtio_pci" + "xhci_pci" + ]; + kernelModules = [ ]; + luks.devices = + { + "encrypted".device = "/dev/disk/by-label/gimel"; + #"encrypted".device = "/dev/disk/by-uuid/50ef0747-99fb-49c1-ae72-ccb8522aa494"; + "encryptedData".device = "/dev/disk/by-label/data"; + #"encryptedData".device = "/dev/disk/by-uuid/e027df47-8c13-4900-a73d-a7f8847e9bd8"; + }; + }; + kernelModules = [ ]; + loader = + { + grub = + { + devices = [ "/dev/vda2" ]; + enable = true; + version = 2; + }; + }; + }; + + nix.maxJobs = 1; + swapDevices = [ ]; + + fileSystems = + { + "/" = + { + device = "/dev/disk/by-uuid/fc7db70b-bf85-4a57-9f60-49cfbbfd569c"; + fsType = "xfs"; + }; + "/boot" = + { + device = "/dev/disk/by-uuid/D93A-CC07"; + fsType = "vfat"; + }; + "/data" = + { + device = "/dev/disk/by-uuid/3c2e33c0-3dc0-46e7-bb90-c2b1f974144b"; + fsType = "xfs"; + }; + }; +} diff --git a/hosts/gimel/hardware/network.nix b/hosts/gimel/hardware/network.nix new file mode 100644 index 0000000..e69de29 diff --git a/hosts/nix.sh b/hosts/nix.sh new file mode 100755 index 0000000..5a784ec --- /dev/null +++ b/hosts/nix.sh @@ -0,0 +1,159 @@ +#!/usr/bin/env bash + +nix "$@" \ + --override-input home-manager ../home-manager \ + --override-input home-manager/libcore ../libs/core \ + --override-input home-manager/libcore/libintrinsics ../libs/intrinsics \ + --override-input libconfig ../libs/config \ + --override-input libconfig/libcore ../libs/core \ + --override-input libconfig/libcore/libintrinsics ../libs/intrinsics \ + --override-input libconfig/libsecrets ../libs/secrets \ + --override-input libconfig/libsecrets/libcore ../libs/core \ + --override-input libconfig/libsecrets/libcore/libintrinsics ../libs/intrinsics \ + --override-input libconfig/libsecrets/libstore ../libs/store \ + --override-input libconfig/libsecrets/libstore/libcore ../libs/core \ + --override-input libconfig/libsecrets/libstore/libcore/libintrinsics ../libs/intrinsics \ + --override-input libconfig/libstore ../libs/store \ + --override-input libconfig/libstore/libcore ../libs/core \ + --override-input libconfig/libstore/libcore/libintrinsics ../libs/intrinsics \ + --override-input libconfig/libweb ../libs/web \ + --override-input libconfig/libweb/libcore ../libs/core \ + --override-input libconfig/libweb/libcore/libintrinsics ../libs/intrinsics \ + --override-input libcore ../libs/core \ + --override-input libcore/libintrinsics ../libs/intrinsics \ + --override-input libsecrets ../libs/secrets \ + --override-input libsecrets/libcore ../libs/core \ + --override-input libsecrets/libcore/libintrinsics ../libs/intrinsics \ + --override-input libsecrets/libstore ../libs/store \ + --override-input libsecrets/libstore/libcore ../libs/core \ + --override-input libsecrets/libstore/libcore/libintrinsics ../libs/intrinsics \ + --override-input libstore ../libs/store \ + --override-input libstore/libcore ../libs/core \ + --override-input libstore/libcore/libintrinsics ../libs/intrinsics \ + --override-input libweb ../libs/web \ + --override-input libweb/libcore ../libs/core \ + --override-input libweb/libcore/libintrinsics ../libs/intrinsics \ + --override-input modules ../modules \ + --override-input modules/libconfig ../libs/config \ + --override-input modules/libconfig/libcore ../libs/core \ + --override-input modules/libconfig/libcore/libintrinsics ../libs/intrinsics \ + --override-input modules/libconfig/libsecrets ../libs/secrets \ + --override-input modules/libconfig/libsecrets/libcore ../libs/core \ + --override-input modules/libconfig/libsecrets/libcore/libintrinsics ../libs/intrinsics \ + --override-input modules/libconfig/libsecrets/libstore ../libs/store \ + --override-input modules/libconfig/libsecrets/libstore/libcore ../libs/core \ + --override-input modules/libconfig/libsecrets/libstore/libcore/libintrinsics ../libs/intrinsics \ + --override-input modules/libconfig/libstore ../libs/store \ + --override-input modules/libconfig/libstore/libcore ../libs/core \ + --override-input modules/libconfig/libstore/libcore/libintrinsics ../libs/intrinsics \ + --override-input modules/libconfig/libweb ../libs/web \ + --override-input modules/libconfig/libweb/libcore ../libs/core \ + --override-input modules/libconfig/libweb/libcore/libintrinsics ../libs/intrinsics \ + --override-input modules/libcore ../libs/core \ + --override-input modules/libcore/libintrinsics ../libs/intrinsics \ + --override-input registries ../registries \ + --override-input registries/fork-awesome ../packages/fork-awesome \ + --override-input registries/fork-awesome/libcore ../libs/core \ + --override-input registries/fork-awesome/libcore/libintrinsics ../libs/intrinsics \ + --override-input registries/libconfig ../libs/config \ + --override-input registries/libconfig/libcore ../libs/core \ + --override-input registries/libconfig/libcore/libintrinsics ../libs/intrinsics \ + --override-input registries/libconfig/libsecrets ../libs/secrets \ + --override-input registries/libconfig/libsecrets/libcore ../libs/core \ + --override-input registries/libconfig/libsecrets/libcore/libintrinsics ../libs/intrinsics \ + --override-input registries/libconfig/libsecrets/libstore ../libs/store \ + --override-input registries/libconfig/libsecrets/libstore/libcore ../libs/core \ + --override-input registries/libconfig/libsecrets/libstore/libcore/libintrinsics ../libs/intrinsics \ + --override-input registries/libconfig/libstore ../libs/store \ + --override-input registries/libconfig/libstore/libcore ../libs/core \ + --override-input registries/libconfig/libstore/libcore/libintrinsics ../libs/intrinsics \ + --override-input registries/libconfig/libweb ../libs/web \ + --override-input registries/libconfig/libweb/libcore ../libs/core \ + --override-input registries/libconfig/libweb/libcore/libintrinsics ../libs/intrinsics \ + --override-input registries/libcore ../libs/core \ + --override-input registries/libcore/libintrinsics ../libs/intrinsics \ + --override-input registries/redshift-wayland ../packages/redshift-wayland \ + --override-input registries/redshift-wayland/libcore ../libs/core \ + --override-input registries/redshift-wayland/libcore/libintrinsics ../libs/intrinsics \ + --override-input registries/wofi-unpatched ../packages/wofi-unpatched \ + --override-input registries/wofi-unpatched/libcore ../libs/core \ + --override-input registries/wofi-unpatched/libcore/libintrinsics ../libs/intrinsics \ + --override-input peers ../peers \ + --override-input peers/libconfig ../libs/config \ + --override-input peers/libconfig/libcore ../libs/core \ + --override-input peers/libconfig/libcore/libintrinsics ../libs/intrinsics \ + --override-input peers/libconfig/libsecrets ../libs/secrets \ + --override-input peers/libconfig/libsecrets/libcore ../libs/core \ + --override-input peers/libconfig/libsecrets/libcore/libintrinsics ../libs/intrinsics \ + --override-input peers/libconfig/libsecrets/libstore ../libs/store \ + --override-input peers/libconfig/libsecrets/libstore/libcore ../libs/core \ + --override-input peers/libconfig/libsecrets/libstore/libcore/libintrinsics ../libs/intrinsics \ + --override-input peers/libconfig/libstore ../libs/store \ + --override-input peers/libconfig/libstore/libcore ../libs/core \ + --override-input peers/libconfig/libstore/libcore/libintrinsics ../libs/intrinsics \ + --override-input peers/libconfig/libweb ../libs/web \ + --override-input peers/libconfig/libweb/libcore ../libs/core \ + --override-input peers/libconfig/libweb/libcore/libintrinsics ../libs/intrinsics \ + --override-input peers/libcore ../libs/core \ + --override-input peers/libcore/libintrinsics ../libs/intrinsics \ + --override-input peers/libsecrets ../libs/secrets \ + --override-input peers/libsecrets/libcore ../libs/core \ + --override-input peers/libsecrets/libcore/libintrinsics ../libs/intrinsics \ + --override-input peers/libsecrets/libstore ../libs/store \ + --override-input peers/libsecrets/libstore/libcore ../libs/core \ + --override-input peers/libsecrets/libstore/libcore/libintrinsics ../libs/intrinsics \ + --override-input profiles ../profiles \ + --override-input profiles/libconfig ../libs/config \ + --override-input profiles/libconfig/libcore ../libs/core \ + --override-input profiles/libconfig/libcore/libintrinsics ../libs/intrinsics \ + --override-input profiles/libconfig/libsecrets ../libs/secrets \ + --override-input profiles/libconfig/libsecrets/libcore ../libs/core \ + --override-input profiles/libconfig/libsecrets/libcore/libintrinsics ../libs/intrinsics \ + --override-input profiles/libconfig/libsecrets/libstore ../libs/store \ + --override-input profiles/libconfig/libsecrets/libstore/libcore ../libs/core \ + --override-input profiles/libconfig/libsecrets/libstore/libcore/libintrinsics ../libs/intrinsics \ + --override-input profiles/libconfig/libstore ../libs/store \ + --override-input profiles/libconfig/libstore/libcore ../libs/core \ + --override-input profiles/libconfig/libstore/libcore/libintrinsics ../libs/intrinsics \ + --override-input profiles/libconfig/libweb ../libs/web \ + --override-input profiles/libconfig/libweb/libcore ../libs/core \ + --override-input profiles/libconfig/libweb/libcore/libintrinsics ../libs/intrinsics \ + --override-input profiles/libcore ../libs/core \ + --override-input profiles/libcore/libintrinsics ../libs/intrinsics \ + --override-input profiles/services ../services \ + --override-input profiles/services/libconfig ../libs/config \ + --override-input profiles/services/libconfig/libcore ../libs/core \ + --override-input profiles/services/libconfig/libcore/libintrinsics ../libs/intrinsics \ + --override-input profiles/services/libconfig/libsecrets ../libs/secrets \ + --override-input profiles/services/libconfig/libsecrets/libcore ../libs/core \ + --override-input profiles/services/libconfig/libsecrets/libcore/libintrinsics ../libs/intrinsics \ + --override-input profiles/services/libconfig/libsecrets/libstore ../libs/store \ + --override-input profiles/services/libconfig/libsecrets/libstore/libcore ../libs/core \ + --override-input profiles/services/libconfig/libsecrets/libstore/libcore/libintrinsics ../libs/intrinsics \ + --override-input profiles/services/libconfig/libstore ../libs/store \ + --override-input profiles/services/libconfig/libstore/libcore ../libs/core \ + --override-input profiles/services/libconfig/libstore/libcore/libintrinsics ../libs/intrinsics \ + --override-input profiles/services/libconfig/libweb ../libs/web \ + --override-input profiles/services/libconfig/libweb/libcore ../libs/core \ + --override-input profiles/services/libconfig/libweb/libcore/libintrinsics ../libs/intrinsics \ + --override-input profiles/services/libweb ../libs/web \ + --override-input profiles/services/libweb/libcore ../libs/core \ + --override-input profiles/services/libweb/libcore/libintrinsics ../libs/intrinsics \ + --override-input sivizius ../users/sivizius \ + --override-input sivizius/libconfig ../libs/config \ + --override-input sivizius/libconfig/libcore ../libs/core \ + --override-input sivizius/libconfig/libcore/libintrinsics ../libs/intrinsics \ + --override-input sivizius/libconfig/libsecrets ../libs/secrets \ + --override-input sivizius/libconfig/libsecrets/libcore ../libs/core \ + --override-input sivizius/libconfig/libsecrets/libcore/libintrinsics ../libs/intrinsics \ + --override-input sivizius/libconfig/libsecrets/libstore ../libs/store \ + --override-input sivizius/libconfig/libsecrets/libstore/libcore ../libs/core \ + --override-input sivizius/libconfig/libsecrets/libstore/libcore/libintrinsics ../libs/intrinsics \ + --override-input sivizius/libconfig/libstore ../libs/store \ + --override-input sivizius/libconfig/libstore/libcore ../libs/core \ + --override-input sivizius/libconfig/libstore/libcore/libintrinsics ../libs/intrinsics \ + --override-input sivizius/libconfig/libweb ../libs/web \ + --override-input sivizius/libconfig/libweb/libcore ../libs/core \ + --override-input sivizius/libconfig/libweb/libcore/libintrinsics ../libs/intrinsics \ + --override-input sivizius/libcore ../libs/core \ + --override-input sivizius/libcore/libintrinsics ../libs/intrinsics diff --git a/libs/accounting/default.nix b/libs/accounting/default.nix new file mode 100644 index 0000000..290ee81 --- /dev/null +++ b/libs/accounting/default.nix @@ -0,0 +1,15 @@ +{ core, ... } @ libs: + let + inherit(core) check library target; + lib = library.load ./lib libs; + tests = check.load ./tests libs lib; + in + { + inherit lib tests; + + checks + = check tests + { + targetSystem = target.System.all.x86_64-linux; + }; + } \ No newline at end of file diff --git a/libs/accounting/flake.nix b/libs/accounting/flake.nix new file mode 100644 index 0000000..7805581 --- /dev/null +++ b/libs/accounting/flake.nix @@ -0,0 +1,13 @@ +{ + description = "…"; + inputs + = { + libcore.url = "github:sivizius/nixfiles/development?dir=libs/core"; + }; + outputs + = { self, libcore, ... }: + let + core = libcore.lib { inherit self; debug.logLevel = "info"; }; + in + core.path.import ./. { inherit core; }; +} \ No newline at end of file diff --git a/libs/accounting/lib/common/account.nix b/libs/accounting/lib/common/account.nix new file mode 100644 index 0000000..bd2b960 --- /dev/null +++ b/libs/accounting/lib/common/account.nix @@ -0,0 +1,35 @@ +{ common, core, ... }: + let + inherit(common) Total; + inherit(core) debug list number path set string time type; + + Account#: { ... } -> Account + = let + __functor + = { credit, debit, ... } @ self: + { ... } @ transaction: + self + // { + }; + + __toString + = { uid, ... }: + "<${uid}>"; + in + type "Account" + { + from + = uid: + { ... } @ meta: + Account.instanciate + ( + meta + // { + inherit uid __functor __toString; + credit = Total false; + debit = Total true; + } + ); + }; + in + { inherit Account; } diff --git a/libs/accounting/lib/common/amount.nix b/libs/accounting/lib/common/amount.nix new file mode 100644 index 0000000..6b3ffaa --- /dev/null +++ b/libs/accounting/lib/common/amount.nix @@ -0,0 +1,52 @@ +{ core, ... }: + let + inherit(core) debug list number path set string time type; + + __toString + = { currency, value, ... }: + let + negative = value < 0; + value' = if negative then -value else value; + text = string value'; + len = string.length text; + decimal = len - 2; + intPart = string.slice 0 decimal text; + decPart = string.slice decimal len text; + mod3 = x: ((x + 2)/ 3 * 3) - x; + mod3' = mod3 decimal; + padding = list.get [ "" " " " " ] mod3'; + tripletts + = list.filter + list.isInstanceOf + ( + string.split + "(.{3})" + "${padding}${intPart}" + ); + tripletts' = list.concat tripletts; + intPart' = string.concatWith "," tripletts'; + text' + = if value' < 10 + then + "0.0${text}" + else if value' < 100 + then + "0.${text}" + else + "${string.slice mod3' (string.length intPart') intPart'}.${decPart}"; + in + "${if negative then "-" else ""}${text'} ${currency}"; + + Amount#: int | float -> Amount + = type "Amount" + { + from + = value: + currency: + Amount.instanciate + { + inherit currency value __toString; + }; + }; + in + { inherit Amount; } diff --git a/libs/accounting/lib/common/book.nix b/libs/accounting/lib/common/book.nix new file mode 100644 index 0000000..d84d42e --- /dev/null +++ b/libs/accounting/lib/common/book.nix @@ -0,0 +1,600 @@ +{ common, core, ... }: + let + inherit(common) Amount; + inherit(core) debug indentation list number path set string time type; + + checkTransactionAccounts#: { Account } -> { Account } -> Transaction -> [ string ] + = { ... } @ allAccounts: + { ... } @ transactionAccounts: + { ... } @ transaction: + let + unknownAccounts = getUnknownAccounts allAccounts transactionAccounts; + in + if unknownAccounts == [] + then + transactionAccounts + else + debug.panic "checkTransactionAccounts" + { + text = "Unknown Accounts: <${string.concatWithFinal ">, <" "> and <" unknownAccounts}>!"; + data = { inherit transaction; }; + }; + + collectAccounts + = list.fold + ( + { ... } @ accounts: + { uid, ... } @ account: + if accounts.${uid} or null == null + then + accounts + // { + ${uid} = account; + } + else + debug.panic + "Book" + "Duplicate of account UID: ${uid}" + ) + {}; + + creditAccounts#: { Account } -> { Amount } -> { reference: R } -> { Account } | ! + # where R: Any + = { ... } @ allAccounts: + { ... } @ creditAccounts: + { ... } @ transaction: + set.fold + ( + { ... } @ allAccounts: + accountUID: + amount: + let + this = allAccounts.${accountUID}; + in + allAccounts + // { + ${accountUID} + = this + // { + credit = this.credit amount transaction; + }; + } + ) + allAccounts + ( checkTransactionAccounts allAccounts creditAccounts transaction ); + + debitAccounts#: { Account } -> { Amount } -> { reference: R } -> { Account } | ! + # where R: Any + = { ... } @ allAccounts: + { ... } @ debitAccounts: + { ... } @ transaction: + set.fold + ( + { ... } @ allAccounts: + accountUID: + amount: + let + this = allAccounts.${accountUID}; + in + allAccounts + // { + ${accountUID} + = this + // { + debit = this.debit amount transaction; + }; + } + ) + allAccounts + ( checkTransactionAccounts allAccounts debitAccounts transaction ); + + flat + = source: + let + source' + = if source != null + then + "${source}-" + else + ""; + in + list.concatMap + ( + { __type__, body ? [], uid ? null, ... } @ entry: + { + Account = [ (entry // { uid = "${source'}${uid}"; }) ]; + Section = flat "${source'}${uid}" body; + }.${__type__} + or ( + debug.panic [ "Book" "flat" ] + { + text = "Either Account or Section expected, got:"; + data = entry; + } + ) + ); + + getSectionUIDs + = source: + let + source' + = if source != null + then + "${source}-" + else + ""; + in + list.concatMap + ( + { __type__, body ? [], uid ? null, ... } @ entry: + { + Account = []; + Section + = [ "${source'}${uid}" ] + ++ getSectionUIDs "${source'}${uid}" body; + }.${__type__} + or ( + debug.panic [ "Book" "getSectionUIDs" ] + { + text = "Either Account or Section expected, got:"; + data = entry; + } + ) + ); + + getUnknownAccounts#: { Accounts } -> [ string ] -> [ string ] + = { ... } @ allAccounts: + { ... } @ checkAccounts: + list.filter + (accountUID: allAccounts.${accountUID} or null == null) + (set.names checkAccounts); + + lookUp + = let + find + = dictionary: + key: + prefixes: + if key != null + then + list.fold + ( + result: + prefix: + let + key' = "${prefix}-${key}"; + value = dictionary.${key'} or null; + in + if value != null + then + debug.panic [ "Book" "lookUp" "find" ] + { + text = "Multiple matches:"; + data = { first = result; second = value; inherit key key'; }; + nice = true; + when = result != null; + } + value + else + result + ) + null + prefixes + else + null; + haz + = dictionary: + key: + if key != null + then + dictionary.${key} or null + else + null; + + match + = { email ? null, uid ? null, ... } @ client: + debug.info [ "Book" "lookUp" "match" ] + { + text = "Try to find match for:"; + data = client; + nice = true; + } + set.filterValue + ( + { matches ? {}, regex ? {}, ... } @ account: + let + regexMatch + = (uid != null && regex.uid or null != null && ((string.match regex.uid uid) != null)) + || (email != null && regex.email or null != null && ((string.match regex.email email) != null)); + + checkParam + = field: + value: + (client.${field} or null != null) + && ( + if list.isInstanceOf value + then + list.find client.${field} value + else + client.${field} == value + ); + + paramMatch + = matches != {} + && (set.any checkParam matches); + in + debug.info [ "Book" "lookUp" "match" ] + { + text = "Check ${account}"; + data = { inherit matches regex; }; + when = (matches != {} || regex != {}); + } + regexMatch || paramMatch + ); + in + { accounts, aliases, emails, ibans, sectionUIDs, ... } @ environment: + { email ? null, iban ? null, uid ? null, ... } @ client: + let + alias = haz aliases uid; + email' = haz emails email; + iban' = haz ibans iban; + client' = find accounts uid sectionUIDs; + + match' + = let + matches = match client accounts; + in + debug.info [ "Book" "lookUp" ] + { + text = "Matches"; + data = matches; + when = matches != {}; + } + set.foldValues + ( + result: + { uid, ... } @ account: + debug.panic "lookUpAccount" + { + text = "Multiple matches: <${result}> and <${uid}>"; + data = { first = result; second = account; }; + when = result != null; + } + account + ) + null + matches; + in + if client' != null then client' + else if alias != null then alias + else if email' != null then email' + else if iban' != null then iban' + else if match' != null then match' + else + debug.panic "lookUpAccount" + { + text = "Cannot determine uid of client:"; + data = { inherit environment client; }; + nice = true; + } + null; + + makeLookUp + = field: + let + insert + = { uid, ... } @ account: + dictionary: + key: + if dictionary.${key} or null == null + then + dictionary // { ${key} = account; } + else + debug.panic + [ "Book" "makeLookUp" ] + "Duplicate ${field} »${key}« for <${uid}> and >${dictionary.${key}}>"; + in + set.foldValues + ( + { ... } @ dictionary: + { ... } @ account: + let + insert' = insert account; + value = account.${field} or null; + in + type.matchPrimitiveOrPanic value + { + list = list.fold insert' dictionary value; + null = dictionary; + string = insert' dictionary value; + } + ) + {}; + + sortJournal + = journal: + list.imap + ( + uid: + transaction: + transaction // { inherit uid; } + ) + ( + list.sort + ( + { dateTime, ... }: + other: + time.before dateTime other.dateTime + ) + journal + ); + + HTML + = let + flat + = body: + if list.isInstanceOf body + then + list.concatMap flat body + else + [ body ]; + + mapAttributes + = { ... } @ attributes: + string.concatMapped + (key: " ${key}=\"${string attributes.${key}}\"") + (set.names attributes); + + Block + = name: + { ... } @ attributes: + body: + [ "<${name}${mapAttributes attributes}>" indentation.more ] + ++ (flat body) + ++ [ indentation.less "" ]; + + Line + = name: + { ... } @ attributes: + text: + "<${name}${mapAttributes attributes}>${text}"; + in + { + inherit Block Line; + Block' = name: Block name {}; + Line' = name: Line name {}; + + __functor + = { ... }: + body: + indentation {} + ( + [ + "" + "" + "" indentation.more + ] + ++ (flat body) + ++ [ indentation.less "" ] + ); + }; + + harmonise + = { inner, ... } @ self: + { inner, ... }: + list.fold + ( + { ... } @ dictionary: + key: + dictionary + // { + ${key} = dictionary.${key} or 0; + } + ) + self.inner + (set.names inner); + + toAmounts + = set.mapToList + ( + currency: + value: + Amount value currency + ); + + toHTML + = let + renderSections + = accounts: + source: + let + source' + = if source != null + then + "${source}-" + else + ""; + in + list.concatMap + ( + { __type__, title ? null, body ? [], uid ? null, ... } @ entry: + let + uid' = "${source'}${uid}"; + inherit(accounts.${uid'}) credit debit; + + credit' = toAmounts (harmonise credit debit); + debit' = toAmounts (harmonise debit credit); + total + = list.imap + ( + index: + credit: + HTML.Block' "tr" + [ + (HTML.Line "th" { style = "text-align: right;"; } "${list.get debit' index}") + (HTML.Line "th" { style = "text-align: right;"; } "${credit}") + ] + ) + credit'; + in + { + Account + = [ + ( + HTML.Block' "details" + [ + (HTML.Line' "summary" (if title != null then "<${uid'}> ${title}" else "<${uid'}>")) + ( + HTML.Block "table" { style = "width: 100%;"; } + ( + [ + ( + HTML.Block' "tr" + [ + (HTML.Line "th" { style = "width:50%;"; } "Soll") + (HTML.Line "th" { style = "width:50%;"; } "Haben") + ] + ) + ] + ++ total + ) + ) + ] + ) + ]; + Section + = [ + ( + HTML.Block' "details" + ( + [ ( HTML.Line' "summary" "[${uid'}] ${title}" ) ] + ++ (renderSections accounts uid' body) + ) + ) + ]; + }.${__type__} + or ( + debug.panic [ "Book" "toHTML" ] + { + text = "Either Account or Section expected, got:"; + data = entry; + } + ) + ); + + render + = { body, accounts, journal, ... } @ subbook: + HTML + [ + ( + HTML.Block' "head" + [ + (HTML.Line' "title" "Übersicht") + ( + HTML.Block' "style" + [ + "table, th, td {" indentation.more + "border: 1px solid black;" + "border-collapse: collapse;" + indentation.less "}" + ] + ) + ] + ) + ( + HTML.Block' "body" + ( + (renderSections accounts null body) + ++ [ + (HTML.Line' "h1" "Laufende Kosten") + ( + HTML.Block' "ul" + ( + list.map + ( + { dateTime, description, credit, debit, type ? "", ... }: + HTML.Line' "li" + ( + let + render + = clients: + string.concatWith ", " + ( + set.mapToList + ( + uid: + amount: + "(${uid}: ${amount})" + ) + clients + ); + in + "[${dateTime}] {${type}} ${render credit} -> ${render debit} »${description}«" + ) + ) + ( + list.filter + ({ ongoing ? false, ... }: ongoing) + journal + ) + ) + ) + ] + ) + ) + ]; + in + book: + render (Book.expect book); + + Book + = type "Book" + { + from + = { body, currency ? "EUR", title, ... }: + let + accounts = collectAccounts (flat null body); + aliases = makeLookUp "alias" accounts; + emails = makeLookUp "email" accounts; + ibans = makeLookUp "iban" accounts; + + journal + = sortJournal + ( + list.concatMap + ( + { journal ? null, uid, ... } @ self: + type.matchPrimitiveOrPanic journal + { + lambda = journal { inherit currency lookUpAccount self; }; + list = journal; + null = []; + } + ) + (set.values accounts) + ); + + lookUpAccount = lookUp { inherit accounts aliases emails ibans sectionUIDs; }; + + sectionUIDs = (getSectionUIDs null body) ++ [ "" ]; + in + Book.instanciate + { + inherit aliases body emails ibans journal title; + accounts + = list.fold + ( + { ... } @ accounts: + { credit, debit, ... } @ transaction: + debitAccounts + (creditAccounts accounts credit transaction) + debit + transaction + ) + accounts + journal; + }; + inherit toHTML; + }; + in + { inherit Book; } diff --git a/libs/accounting/lib/common/default.nix b/libs/accounting/lib/common/default.nix new file mode 100644 index 0000000..494e22e --- /dev/null +++ b/libs/accounting/lib/common/default.nix @@ -0,0 +1,9 @@ +{ core, ... } @ libs: + let + inherit(core) path; + in path.import ./account.nix libs + // path.import ./amount.nix libs + // path.import ./book.nix libs + // path.import ./section.nix libs + // path.import ./total.nix libs + // path.import ./transaction.nix libs diff --git a/libs/accounting/lib/common/section.nix b/libs/accounting/lib/common/section.nix new file mode 100644 index 0000000..f15c2a2 --- /dev/null +++ b/libs/accounting/lib/common/section.nix @@ -0,0 +1,35 @@ +{ common, core, ... }: + let + inherit(common) Account; + inherit(core) debug list number path set string time type; + + Section#: { title: string, ... } | string -> [ { uid, name, ... } | Seection ] -> Section + = type "Section" + { + from + = uid: + title: + body: + Section.instanciate + { + inherit title uid; + body + = list.map + ( + this: + if (Account.isInstanceOf this) + || (Section.isInstanceOf this) + then + this + else + debug.panic [ "Section" title ] + { + text = "Either Section or Account expected, got"; + data = this; + } + ) + body; + }; + }; + in + { inherit Section; } diff --git a/libs/accounting/lib/common/total.nix b/libs/accounting/lib/common/total.nix new file mode 100644 index 0000000..33213be --- /dev/null +++ b/libs/accounting/lib/common/total.nix @@ -0,0 +1,100 @@ +{ common, core, ... }: + let + inherit(common) Amount Transaction; + inherit(core) debug list number path set string time type; + + Total + = type "Total" + { + from + = direction: + Total.instanciate + { + inherit direction; + __functor + = { inner, journal, ... } @ self: + amount: + transaction: + let + amount' = Amount.expect amount; + transaction' + = { + amount = amount'; + inherit(Transaction.expect transaction) uid; + }; + in + self + // { + inner + = inner + // { + ${amount'.currency} + = (inner.${amount'.currency} or 0) + + amount'.value; + }; + journal + = if transaction != null + then + journal ++ [ transaction' ] + else + journal; + }; + __toString + = { direction, inner, journal, ... }: + string.concatLines + ( + [ "
" ] + ++ ( + set.mapToList + ( + currency: + value: + "

${Amount value currency}

" + ) + inner + ) + ++ [ "
" ] + ++ ( + list.map + ( + { amount, uid }: + "

${amount}(${string uid})

" + ) + journal + ) + ++ [ "
" ] + ); + inner = {}; + journal = []; + }; + + isZero + = difference: + set.all + (name: value: value == 0) + (Total.expect difference).inner; + + subtract + = left: + right: + set.fold + ( + { inner, ... } @ total: + currency: + value: + total + // { + inner + = inner + // { + ${currency} + = inner.${currency} or 0 + - value; + }; + } + ) + (Total.expect left) + (Total.expect right).inner; + }; + in + { inherit Total; } diff --git a/libs/accounting/lib/common/transaction.nix b/libs/accounting/lib/common/transaction.nix new file mode 100644 index 0000000..2fcd3c5 --- /dev/null +++ b/libs/accounting/lib/common/transaction.nix @@ -0,0 +1,82 @@ +{ common, core, ... }: + let + inherit(common) Total; + inherit(core) debug list number path set string time type; + + Transaction#: { dateTime: ~DateTime, debit: { Amount }, credit: { Amount }, ... } -> Transaction + = let + sumTransfers + = direction: + set.foldValues + ( + total: + amount: + total amount null + ) + (Total direction); + in + type "Transaction" + { + from + = { dateTime, credit, debit, ... } @ transaction: + let + clients + = set.fold + ( + { ...} @ clients: + uid: + amount: + if clients.${uid} or null == null + then + clients + // { + ${uid} + = amount + // { + value + = -amount.value; + }; + } + else + throw "…" + ) + credit + debit; + + total = sumTransfers false clients; + clients' = set.partitionByValue ({ value, ... }: value >= 0) clients; + in + if Total.isZero total + then + Transaction.instanciate + ( + transaction + // { + dateTime = time.from dateTime; + credit = clients'.right; + debit + = set.mapValues + ( + { value, ... } @ self: + self + // { + value = -value; + } + ) + clients'.wrong; + } + ) + else + debug.panic "Transaction" + { + text = "Sum of Credits and Debits is not equal!"; + data + = { + credit = clients'.right; + debit = clients'.wrong; + inherit transaction total; + }; + }; + }; + in + { inherit Transaction; } diff --git a/libs/accounting/lib/default.nix b/libs/accounting/lib/default.nix new file mode 100644 index 0000000..5aca45a --- /dev/null +++ b/libs/accounting/lib/default.nix @@ -0,0 +1,10 @@ +{ core, ... }: + Library "libaccounting" + { inherit core; } + { + common = ./common; + double = ./double; + parse = ./parse; + schemes = ./schemes; + single = ./single; + } diff --git a/libs/accounting/lib/double/default.nix b/libs/accounting/lib/double/default.nix new file mode 100644 index 0000000..0fc612b --- /dev/null +++ b/libs/accounting/lib/double/default.nix @@ -0,0 +1,212 @@ +{ common, core, ... } @ libs: + let + inherit(core) debug library list number set string time type; + inherit(common) Account Amount Transaction creditAccounts debitAccounts; + + addReferences#: [ { ... } ] -> [ { reference: int, ... } ] + = list.imap + (reference: { ... } @ this: this // { inherit reference; }); + + balance#: Self -> ~DateTime-> Balance | ! + = balanceTime: + { ... } @ self: + let + self' = from self; + balanceTime' = time.from balanceTime; + journal + = addReferences + ( + list.filter + ( { dateTime, ... }: !( time.after dateTime balanceTime' ) ) + self'.journal + ); + in + balance' (self' // { balanceTime = balanceTime'; dateTime = balanceTime'; inherit journal; } ); + + + setAccounts#: { Account } -> A -> A' + # where + # A: { title: string, level: int, accounts: T, ... }, + # T: [ { id: string, name: string, ... } ], + # A': T' | { title: string, level: int, accounts: T', total: Amount, ... }, + # T': [ { id: string, name: string, journal: [ Transaction ], total: Amount, ... } ] + = { ... } @ accounts: + this: + type.matchPrimitiveOrPanic this + { + set + = if this ? accounts + then + let + accounts' = setAccounts' accounts this.accounts; + in + this + // { + accounts = accounts'; + total = 1.0 * number.sum (list.map ({ total, ... }: total) accounts'); + } + else + this + // { + inherit (accounts.${this.id}) total credit debit; + }; + }; + + setAccounts'#: { Account } -> A -> A' + # where + # A: [ { id: string, name: string, ... } ], + # A': T' | { title: string, level: int, accounts: T', total: Amount, ... }, + # T': [ { id: string, name: string, journal: [ Transaction ], total: Amount, ... } ] + = { ... } @ accounts: + this: + type.matchPrimitiveOrPanic this + { + list = list.map (setAccounts accounts) this; + }; + + balance'#: Self -> Balance | ! + = { accounts, assets, liabilities, outcome, journal, ... } @ self: + let + + accounts'#: { Account } + = list.fold + ( + { ... } @ accounts: + { credit, debit, ... } @ transaction: + debitAccounts (creditAccounts accounts credit transaction) debit transaction + ) + accounts + journal; + in + self + // { + assets = setAccounts accounts' assets; + liabilities = setAccounts accounts' liabilities; + outcome = setAccounts accounts' outcome; + }; + + balanceToTransaction#: Balance -> Transaction + = { accounts, dateTime, events ? {}, ... } @ self: + let + initialTransaction = events.initialTransaction or ({ ... }: {}); + transaction = initialTransaction { inherit dateTime; }; + in + transaction + // { + inherit dateTime; + debit + = set.filterValue + ({ total, ... }: total > 0) + accounts; + credit + = set.mapValues + (total: -total) + ( + set.filterValue + ({ total, ... }: total < 0) + accounts + ); + }; + + format + = library.import ./format.nix libs + { + inherit balance balance' balanceToTransaction from outcome; + }; + + from#: { name, assets: T, liabilities: T, outcome: T, journal: [ ~Transaction ] } -> Self + # where T: [ { id: string, name: string, ... } | { title: string, accounts: T, ... } ] + = { name, assets, liabilities, outcome, journal, ... } @ self: + let + flatSections#: { title: string, accounts: T, ... } -> [ { id: string, name: string, ... } ] + # where T: [ { id: string, name: string, ... } | { title: string, accounts: T, ... } ] + = this: + type.matchPrimitiveOrPanic this + { + set + = if this ? accounts + then + flatSections' this.accounts + else + [ this ]; + }; + + flatSections'#: T -> [ { id: string, name: string, ... } ] + # where T: [ { id: string, name: string, ... } | { title: string, accounts: T, ... } ] + = this: + list.concatMap flatSections (list.expect this); + + flatAccounts#: [ { id, name, ... } | { title, level, ... } ] -> { Account } + = accounts: + list.mapValuesToSet + ( { id, name, ... } @ account: { name = id; value = Account account; } ) + ( flatSections' accounts ); + in + self + // { + accounts = flatAccounts [ assets liabilities outcome ]; + journal = list.map Transaction journal; + }; + + fromSelf = from; + + outcome#: Self -> { from: Date, till: ~DateTime } -> { } | ! + = { from, till }: + { ... } @ self: + let + splitTransaction#: [ Transaction ] -> ~DateTime -> ~DateTime -> { current: [ Transaction ], before: [ Transaction ] } + = journal: + let + parts + = list.partition + ({ dateTime, ... }: time.before ( time.from dateTime ) from' ) + journal; + parts' + = list.filter + ({ dateTime, ... }: !( time.after ( time.from dateTime ) till')) + parts.wrong; + in + { + before = parts.right; + current = parts'; + }; + + from' = time.from from; + till' = time.from till; + self' = fromSelf self; + journal = splitTransaction self'.journal; + initialTransaction + = balanceToTransaction + ( + balance' + ( + self' + // { + journal = addReferences journal.before; + dateTime = from'; + } + ) + ); + + balance + = balance' + ( + self' + // { + journal = addReferences ([ initialTransaction ] ++ journal.current); + dateTime = till'; + } + ); + in + balance + // { + from = from'; + till = till'; + dateTime = till'; + }; + in + { + __functor = self: from; + inherit balance balanceToTransaction from outcome; + } + // format \ No newline at end of file diff --git a/libs/accounting/lib/double/format.nix b/libs/accounting/lib/double/format.nix new file mode 100644 index 0000000..f390bb6 --- /dev/null +++ b/libs/accounting/lib/double/format.nix @@ -0,0 +1,226 @@ +{ core, ... }: +{ balance, balance', balanceToTransaction, from, outcome, ... }: + let + inherit(core) list set string time; + inherit(time) formatDate; + + concatLines' + = function: lines: string.concatLines (list.filter (value: value != null) (list.map function lines)); + + lineLength = 111; + + padNameValue#: string -> string + = name: + value: + currency: + extra: + let + value' = string.from value; + nameLength = string.lengthUTF8 name; + valueLength = ( string.length value' ) - 4; + currencyLength = string.lengthUTF8 currency; + length = lineLength - nameLength - valueLength - currencyLength - extra - 2; + padding = string.repeat " " length; + theValue = string.slice 0 valueLength value'; + theValue' = if theValue == "-0.00" then " 0.00" else theValue; + in + "${name}:${padding}${theValue'} ${currency}"; + + listSectionTotal'#: int -> T -> string + # where T: { title: string, accounts: [ T | { name: string, ... } ], ... } + = { ... } @ self: + negative: + depth: + { title, accounts, ... } @ this: + let + entries = listSectionTotal self negative ( depth + 1 ) accounts; + in + if entries != "" + then + " ${string.repeat " " depth}${title}:\n${entries}" + else + null; + + listSectionTotal#: int -> T -> string + # where T: { title: string, accounts: [ T | { name: string, ... } ], ... } + = { currency, events ? {}, ... } @ self: + negative: + depth: + concatLines' + ( + { ... } @ entry: + let + filterSection = events.filterSection or ({ ... }: true); + total + = if negative + then + -entry.total + else + entry.total; + in + if entry ? name + then + " ${padNameValue "${string.repeat " " depth}${entry.name}" total currency 2}" + else if filterSection entry + then + listSectionTotal' self negative depth entry + else + " ${padNameValue "${string.repeat " " depth}${entry.title}" total currency 2}" + ); + + formatBalance#: Self -> Date -> string + = dateTime: + self: + formatBalance' ( balance dateTime self ); + + formatBalance'#: Self -> string + = { name, currency, dateTime, assets, liabilities, outcome, journal, events ? {}, ... } @ self: + let + formatBalanceTitle + = events.formatBalanceTitle + or ( + { name, dateTime, ...}: + "Consolidated Statement Finance Positions of ${name} as of ${formatDate dateTime "eng"}" + ); + title = formatBalanceTitle { inherit name dateTime; }; + formatAccountNames + = events.formatAccountNames + or ( + { ... }: + { + balance = "Assets, Liabilities and Equity"; + outcome = "Expenses and Revenues"; + revenues = "Revenues"; + expenses = "Expenses"; + } + ); + formatBalanceNames + = events.formatBalanceNames + or ( + { ... }: + { + credit = "Credit"; + debit = "Debit"; + total = "Total"; + } + ); + filterSection = events.filterSection or ( { ... }: true ); + accountNames = formatAccountNames {}; + balanceNames = formatBalanceNames {}; + + listSections'#: [ Transaction ] -> bool -> int -> T -> string + # where T: { title: string, accounts: [ T | { name: string, ... } ], ... } + = allTransactions: + depth: + { title, accounts, ... }: + let + entries = listSections allTransactions depth accounts; + in + if entries != "" + then + "${string.repeat " " depth} ${title}:\n${entries}" + else + null; + + listSections#: [ Transaction ] -> bool -> int -> T -> string + # where T: { title: string, accounts: [ T | { name: string, ... } ], ... } + = allTransactions: + depth: + let + padding = string.repeat " " depth; + formatAccount#: int -> { name, credit, debit, total, ... } -> string + = { name, credit, debit, total, ... }: + let + listTransactions#: [ Transaction ] -> [ { amount: Amount, reference: int, ... } ] -> string + = journal: + list.concatMap + ( + { amount, reference, ... }: + let + transaction + = list.get allTransactions reference; + in + "\n${padding} ${padNameValue transaction.description amount currency ( 8 + 2 * depth )}" + ) + journal; + in + if debit.journal != [] + || credit.journal != [] + then + '' + ${padding} ${name} + ${padding} ${balanceNames.debit}:${listTransactions debit.journal} + ${padding} ${string.repeat "–" (lineLength - 8 - 2 * depth)} + ${padding} ${padNameValue balanceNames.total debit.total currency ( 8 + 2 * depth)} + ${padding} ${balanceNames.credit}:${listTransactions credit.journal} + ${padding} ${string.repeat "–" (lineLength - 8 - 2 * depth)} + ${padding} ${padNameValue balanceNames.total credit.total currency ( 8 + 2 * depth)} + '' + else + null; + in + concatLines' + ( + { ... } @ entry: + if entry ? name + then + formatAccount entry + else + listSections' allTransactions ( depth + 1 ) entry + ); + + expensesAndRevenues = list.partition ({ total, ... }: total >= 0) outcome.accounts; + expenses = { title = accountNames.expenses; accounts = expensesAndRevenues.wrong; }; + revenues = { title = accountNames.revenues; accounts = expensesAndRevenues.right; }; + in + '' + == ${accountNames.balance} == + === ${assets.title} === + ${listSections journal 0 assets.accounts} + === ${liabilities.title} === + ${listSections journal 0 liabilities.accounts} + == ${accountNames.outcome} == + === ${expenses.title} === + ${listSections journal 0 expenses.accounts} + === ${revenues.title} === + ${listSections journal 0 revenues.accounts} + == ${title} == + === ${assets.title} === + ${listSectionTotal self false 0 assets.accounts} + ${string.repeat "=" ( lineLength - 2)} + ${padNameValue balanceNames.total assets.total currency 2} + + === ${liabilities.title} === + ${listSectionTotal self true 0 liabilities.accounts} + ${string.repeat "=" ( lineLength - 2)} + ${padNameValue balanceNames.total (- liabilities.total) currency 2} + ''; + + formatOutcome#: Self -> { from: D, till: D } -> string + # where D -> DateTime + = { from, till } @ period: + self: + formatOutcome' (outcome period self); + + formatOutcome'#: Self -> { from: D, till: D } -> string + # where D -> DateTime + = { name, currency, from, till, events, outcome, ... } @ self: + let + formatOutcomeTitle + = events.formatOutcomeTitle + or ( + { name, from, till, ...}: + "Income statement of ${name} between ${time.formatDate from "eng"} and ${time.formatDate till "eng"}" + ); + title = formatOutcomeTitle { inherit name from till; }; + total = -1.0 * outcome.total; + in + '' + ${formatBalance' self} + == ${title} == + ${listSectionTotal self true 0 outcome.accounts} + ${string.repeat "=" ( lineLength - 2)} + ${padNameValue outcome.title total currency 2} + ''; + in + { inherit formatBalance formatOutcome; } \ No newline at end of file diff --git a/libs/accounting/lib/parse/amex.nix b/libs/accounting/lib/parse/amex.nix new file mode 100644 index 0000000..3edbd3b --- /dev/null +++ b/libs/accounting/lib/parse/amex.nix @@ -0,0 +1,203 @@ +{ common, core, helpers, ... }: + let + inherit(common) Transaction; + inherit(core) debug expression list path string; + inherit(helpers) parseAmountComma parseBritishDateTime trim; + + convertTransaction + = { currency, lookUpAccount, self, ... }: + { Adresse, Beschreibung, Betrag, Betreff, Datum, Kategorie, Land, PLZ, Stadt, ... } @ transaction: + let + address + = { + country = trim Land; + municipality = trim Stadt; + postalCode = trim PLZ; + text = trim Adresse; + }; + amount = parseAmountComma Betrag currency; + category = trim Kategorie; + client + = lookUpAccount + { + inherit address category description details message subject uid; + }; + dateTime = parseBritishDateTime Datum "00:00:00"; + description = trim Beschreibung; + details = trim transaction."Weitere Details"; + uid + = if description == "ZAHLUNG/ÜBERWEISUNG ERHALTEN BESTEN DANK" + then + "American Express" + else + trim (list.head (string.splitLines description)); + message = trim transaction."Erscheint auf Ihrer Abrechnung als"; + subject = trim Betreff; + in + Transaction + { + inherit dateTime description; + credit = { ${client.uid} = amount; }; + debit = { ${self.uid} = amount; }; + }; + + next + = { case, columns, index, quote, transaction, text, journal } @ state: + cell: + let + field = list.get columns index; + index' = index + 1; + + isCell = string.isInstanceOf cell; + isColumnSep = sep == ","; + isFinalCell = index' == list.length columns; + isLineBreak = sep == "\n"; + + quoted = string.match "\"(.+)\"|'(.+)'" cell; + quoted0 = list.head quoted; + quoted1 = list.get quoted 1; + quoted' = if quoted0 != null then quoted0 else quoted1; + quotedStart = string.match "([\"'])(.+)" cell; + quotedStop = string.match "(.+)([\"'])" cell; + + sep = list.get cell 1; + in + { + FinaliseCell + = if isFinalCell + then + if isLineBreak + then + { + case = "ParseCell"; + index = 0; + journal = journal ++ [ transaction ]; + transaction = {}; + } + else + debug.panic [ "next" "FinaliseCell" ] "Line Break expected!" + else if isColumnSep + then + { + case = "ParseCell"; + index = index'; + quote = null; + } + else if isLineBreak && quote != null + then + { + case = "Quoted"; + text = "${text}${quote}${string.concat cell}"; + } + else + debug.panic [ "next" "FinaliseCell" ] "Column Seperator expected!"; + + ParseCell + = if !isCell + then + debug.panic [ "next" "ParseCell" ] "Cell expected!" + else if quoted != null + then + { + case = "FinaliseCell"; + transaction + = transaction + // { + ${field} = quoted'; + }; + } + else if quotedStart != null + then + { + case = "Quoted"; + quote = list.head quotedStart; + text = list.get quotedStart 1; + } + else + { + case = "FinaliseCell"; + transaction + = transaction + // { + ${field} = cell; + }; + }; + + ParseHeader + = if isCell + then + { + columns = columns ++ [ cell ]; + } + else if isColumnSep + then + {} + else + { + case = "ParseCell"; + }; + + Quoted + = if !isCell + then + { + text = "${text}${string.concat cell}"; + } + else if quotedStop != null + && quote == (list.get quotedStop 1) + then + { + case = "FinaliseCell"; + transaction + = transaction + // { + ${field} = "${text}${list.head quotedStop}"; + }; + text = "${text}${list.head quotedStop}"; + } + else + { + text = "${text}${cell}"; + }; + }.${case}; + + next' + = { ... } @ state: + cell: + state // (next state cell); + + parseCells + = list.fold next' + { + case = "ParseHeader"; + columns = []; + index = 0; + journal = []; + quote = null; + text = ""; + transaction = {}; + }; + + parseFile + = fileName: + ( + parseCells + ( + string.split + "( *)([\n,])( *)" + (path.readFile fileName) + ) + ).journal; + in + { + journal + = files: + { ... } @ env: + list.map + (convertTransaction env) + ( + list.concatMap + parseFile + files + ); + } diff --git a/libs/accounting/lib/parse/default.nix b/libs/accounting/lib/parse/default.nix new file mode 100644 index 0000000..40302af --- /dev/null +++ b/libs/accounting/lib/parse/default.nix @@ -0,0 +1,82 @@ +{ common, core, ... } @ libs: + let + inherit(common) Amount; + inherit(core) expression library list string; + + parseAmount + = regex: + text: + let + sign = if list.head valid == "-" then -1 else 1; + text' + = list.fold + ( + result: + digit: + if result == "" + -> digit != "0" + then + "${result}${digit}" + else + "" + ) + "" + ( + string.splitAt' + "[^0-9]*" + text + ); + valid = string.match regex text; + value + = if valid != null + && text' != "" + then + #__trace "> »${text}«" + #__trace "< »${text'}«" + sign * (expression.fromJSON text') + else + 0; + in + Amount value; + + parseDMYdateTime + = regex: + date: + time: + let + dateParts = string.match regex date; + day = list.get dateParts 0; + month = list.get dateParts 1; + year = list.get dateParts 2; + in + "${year}-${month}-${day}T${time}"; + + trim + = text: + string.concatWords + ( + list.filter + (part: part != "") + (string.splitSpaces text) + ); + + libs' + = libs + // { + helpers + = { + inherit parseAmount parseDMYdateTime trim; + + parseAmountComma = parseAmount "([+-]?)[0-9.]+,[0-9]{2}"; + parseAmountPeriod = parseAmount "([+-]?)[0-9,]+.[0-9]{2}"; + + parseGermanDateTime = parseDMYdateTime "([0-9]{2})[.]([0-9]{2})[.]([0-9]{4})"; + parseBritishDateTime = parseDMYdateTime "([0-9]{2})/([0-9]{2})/([0-9]{4})"; + }; + }; + in + { + amex = library.import ./amex.nix libs'; + dkb = library.import ./dkb.nix libs'; + paypal = library.import ./paypal.nix libs'; + } diff --git a/libs/accounting/lib/parse/dkb.nix b/libs/accounting/lib/parse/dkb.nix new file mode 100644 index 0000000..64ef41e --- /dev/null +++ b/libs/accounting/lib/parse/dkb.nix @@ -0,0 +1,84 @@ +{ common, core, helpers, ... }: + let + inherit(common) Transaction; + inherit(core) list path string; + inherit(helpers) parseAmountComma parseGermanDateTime trim; + + convertTransaction + = { currency, lookUpAccount, self, ... }: + { amount, bic, clientID, creditorID, customerID, dateTime, dateTime', description, iban, mandateID, type }: + let + amount' = amount currency; + client + = lookUpAccount + { + inherit bic creditorID customerID description iban mandateID; + uid + = if clientID != "" + then + clientID + else + "Deutsche Kreditbank Berlin"; + }; + in + #__trace "${client}" + Transaction + { + inherit dateTime description type; + credit = { ${client.uid} = amount'; }; + debit = { ${self.uid} = amount'; }; + ongoing = type == "Lastschrift" || type == "Dauerauftrag"; + }; + + parseLine + = line: + let + cells = string.splitAt "(\";\"|\")" line; + in + { + # "Buchungstag";"Wertstellung";"Buchungstext";"Auftraggeber / Begünstigter";"Verwendungszweck";"Kontonummer";"BLZ";"Betrag (EUR)";"Gläubiger-ID";"Mandatsreferenz";"Kundenreferenz"; + amount = parseAmountComma (list.get cells 8); + bic = trim (list.get cells 7); + clientID = trim (list.get cells 4); + creditorID = trim (list.get cells 9); + customerID = trim (list.get cells 11); + dateTime = parseGermanDateTime (list.get cells 2) "00:00:00"; + dateTime' = parseGermanDateTime (list.get cells 1) "00:00:00"; + description = trim (list.get cells 5); + iban = trim (list.get cells 6); + mandateID = trim (list.get cells 10); + type + = let + type = trim (list.get cells 3); + in + if type != "" + then + type + else + "Kreditkartenabrechnung"; + }; + + parseFile + = fileName: + let + lines + = list.filter + (line: line != "") + (string.splitLines (path.readFile fileName)); + in + list.map + parseLine + (list.tail lines); + in + { + journal + = files: + { ... } @ env: + list.map + (convertTransaction env) + ( + list.concatMap + parseFile + files + ); + } diff --git a/libs/accounting/lib/parse/paypal.nix b/libs/accounting/lib/parse/paypal.nix new file mode 100644 index 0000000..57cfe5d --- /dev/null +++ b/libs/accounting/lib/parse/paypal.nix @@ -0,0 +1,81 @@ +{ common, core, helpers, ... }: + let + inherit(common) Transaction; + inherit(core) list path string; + inherit(helpers) parseAmountComma parseGermanDateTime; + + convertTransaction + = { lookUpAccount, self, ... }: + { amount, client, currency, dateTime, description, ... } @ inner: + let + client' + = lookUpAccount client; + in + Transaction + { + inherit currency dateTime description inner; + credit = { ${client'.uid} = amount; }; + debit = { ${self.uid} = amount; }; + }; + + parseLine + = line: + let + columns = string.splitAt "(\",\"|^\"|\"$)" line; + currency = list.get columns 5; + in + { + inherit currency; + amount = parseAmountComma (list.get columns 8) currency; + amount' = parseAmountComma (list.get columns 6) currency; + fee = parseAmountComma (list.get columns 7) currency; + balance = parseAmountComma (list.get columns 9) currency; + charge = parseAmountComma (list.get columns 15) currency; + client + = { + account = list.get columns 14; + bank = list.get columns 13; + email = list.get columns 11; + uid + = let + uid = list.get columns 12; + in + if uid != "" + then + uid + else + "PayPal"; + }; + code = list.get columns 10; + code' = list.get columns 18; + dateTime = parseGermanDateTime (list.get columns 1) (list.get columns 2); + description = list.get columns 4; + invoiceID = list.get columns 17; + timeZone = list.get columns 3; + vat = parseAmountComma (list.get columns 16) currency; + }; + + parseFile + = fileName: + let + lines + = list.filter + (line: line != "") + (string.splitLines (path.readFile fileName)); + in + list.map + parseLine + (list.tail lines); + in + { + journal + = files: + { ... } @ env: + list.map + (convertTransaction env) + ( + list.concatMap + parseFile + files + ); + } diff --git a/libs/accounting/lib/schemes/default.nix b/libs/accounting/lib/schemes/default.nix new file mode 100644 index 0000000..416b4d9 --- /dev/null +++ b/libs/accounting/lib/schemes/default.nix @@ -0,0 +1,7 @@ +{ core, ... } @ libs: + let + inherit(core) library; + in + { + hgb = library.import ./hgb.nix libs; + } diff --git a/libs/accounting/lib/schemes/hgb.nix b/libs/accounting/lib/schemes/hgb.nix new file mode 100644 index 0000000..658ac6a --- /dev/null +++ b/libs/accounting/lib/schemes/hgb.nix @@ -0,0 +1,302 @@ +{ common, core, double, ... }: + let + inherit(common) Account Section; + inherit(core) debug time; + + Level + = { + Kleinst = 0; + Klein = 1; + Mittel = 2; + Gross = 3; + }; + in + { + level ? Level.Kleinst, + method ? "Umsatz", + ... + }: + [ + # Aktiva nach § 266 Abs. 2 HGB + ( + Section "Aktiva" "Aktiva" + [ + ( + if level >= Level.Klein + then + Section "A" "Anlagevermögen" + [ + ( + if level >= Level.Mittel + then + Section "I" "Immaterielle Vermögensgegenstände" + [ + (Account "1" { title = "Selbst geschaffene gewerbliche Schutzrechte und ähnliche Rechte und Werte"; }) + (Account "2" { title = "Entgeltlich erworbene Konzessionen, gewerbliche Schutzrechte und ähnliche Rechte und Werte sowie Lizenzen an solchen Rechten und Werten"; }) + (Account "3" { title = "Geschäfts- oder Firmenwert"; }) + (Account "4" { title = "Geleistete Anzahlungen"; }) + ] + else + Account "I" { title = "Immaterielle Vermögensgegenstände"; } + ) + ( + if level >= Level.Mittel + then + Section "II" "Sachanlagen" + [ + (Account "1" { title = "Grundstücke, grundstücksgleiche Rechte und Bauten einschließlich der Bauten auf fremden Grundstücken"; }) + (Account "2" { title = "Technische Anlagen und Maschinen"; }) + (Account "3" { title = "Andere Anlagen, Betriebs- und Geschäftsausstattung"; }) + (Account "4" { title = "Geleistete Anzahlungen und Anlagen im Bau"; }) + ] + else + Account "II" { title = "Sachanlagen"; } + ) + ( + if level >= Level.Mittel + then + Section "III" "Finanzanlagen" + [ + (Account "1" { title = "Anteile an verbundenen Unternehmen"; }) + (Account "2" { title = "Ausleihungen an verbundene Unternehmen"; }) + (Account "3" { title = "Beteiligungen"; }) + (Account "4" { title = "Ausleihungen an Unternehmen, mit denen ein Beteiligungsverhältnis besteht"; }) + (Account "5" { title = "Wertpapiere des Anlagevermögens"; }) + (Account "6" { title = "Sonstige Ausleihungen"; }) + ] + else + Account "III" { title = "Finanzanlagen"; } + ) + ] + else + Account "A" { title = "Anlagevermögen"; } + ) + ( + if level >= Level.Klein + then + Section "B" "Umlaufvermögen" + [ + ( + if level >= Level.Mittel + then + Section "I" "Vorräte" + [ + (Account "1" { title = "Roh-, Hilfs- und Betriebsstoffe"; }) + (Account "2" { title = "Unfertige Erzeugnisse, unfertige Leistungen"; }) + (Account "3" { title = "Fertige Erzeugnisse und Waren"; }) + (Account "4" { title = "Geleistete Anzahlungen"; }) + ] + else + Account "I" { title = "Vorräte"; } + ) + ( + if level >= Level.Mittel + then + Section "II" "Forderungen" + [ + (Account "1" { title = "Forderungen aus Lieferungen und Leistungen"; }) + (Account "2" { title = "Forderungen gegen verbundene Unternehmen"; }) + (Account "3" { title = "Forderungen gegen Unternehmen, mit denen ein Beteiligungsverhältnis besteht"; }) + ( + if level >= Level.Gross + then + Section "4" "Sonstige Vermögensgegenstände" + [ + (Account "1" { title = "Abziehbare Vorsteuer"; }) + ] + else + Account "4" { title = "Sonstige Vermögensgegenstände"; } + ) + ] + else + Account "II" { title = "Forderungen"; } + ) + ( + if level >= Level.Mittel + then + Section "III" "Wertpapiere" + [ + (Account "1" { title = "Anteile an verbundenen Unternehmen"; }) + (Account "2" { title = "Sonstige Wertpapiere"; }) + ] + else + Account "III" { title = "Wertpapiere"; } + ) + ( + if level >= Level.Gross + then + Section "IV" "Sonstiges Umlaufvermögen" + [ + (Account "1" { title = "Kassenbestand"; }) + (Account "2" { title = "Bundesbankguthaben"; }) + (Account "3" { title = "Bank"; }) + (Account "4" { title = "Schecks"; }) + ] + else + Account "IV" { title = "Sonstiges Umlaufvermögen"; } + ) + ] + else + Account "B" { title = "Umlaufvermögen"; } + ) + (Account "C" { title = "Rechnungsabgrenzungsposten"; }) + (Account "D" { title = "Aktive latente Steuern"; }) + (Account "E" { title = "Aktiver Unterschiedsbetrag aus der Vermögensverrechnung"; }) + ] + ) + + # Passiva nach § 266 Abs. 3 HGB + ( + Section "Passiva" "Passiva" + [ + ( + if level >= Level.Klein + then + Section "A" "Eigenkapital" + [ + (Account "I" { title = "Gezeichnetes Kapital"; }) + (Account "II" { title = "Kapitalrücklage"; }) + ( + if level >= Level.Mittel + then + Section "III" "Gewinnrücklagen" + [ + (Account "1" { title = "Gesetzliche Rücklage"; }) + (Account "2" { title = "Rücklage für Anteile an einem herrschenden oder mehrheitlich beteiligten Unternehmen"; }) + (Account "3" { title = "Satzungsmäßige Rücklagen"; }) + (Account "4" { title = "Andere Gewinnrücklagen"; }) + ] + else + Account "III" { title = "Gewinnrücklagen"; } + ) + (Account "IV" { title = "Gewinn-/Verlustvortrag"; }) + (Account "V" { title = "Jahresüberschuß/-fehlbetrag"; }) + ] + else + Account "A" { title = "Eigenkapital"; } + ) + ( + if level >= Level.Mittel + then + Section "B" "Rückstellungen" + [ + (Account "1" { title = "Rückstellungen für Pensionen und ähnliche Verpflichtungen"; }) + (Account "2" { title = "Steuerrückstellungen"; }) + (Account "3" { title = "Sonstige Rückstellungen"; }) + ] + else + Account "B" { title = "Rückstellungen"; } + ) + ( + if level >= Level.Mittel + then + Section "C" "Verbindlichkeiten" + [ + (Account "1" { title = "Anleihen davon konvertibel"; }) + (Account "2" { title = "Verbindlichkeiten gegenüber Kreditinstituten"; }) + (Account "3" { title = "Erhaltene Anzahlungen auf Bestellungen"; }) + (Account "4" { title = "Verbindlichkeiten aus Lieferungen und Leistungen"; }) + (Account "5" { title = "Verbindlichkeiten aus der Annahme gezogener Wechsel und der Ausstellung eigener Wechsel"; }) + (Account "6" { title = "Verbindlichkeiten gegenüber verbundenen Unternehmen"; }) + (Account "7" { title = "Verbindlichkeiten gegenüber Unternehmen, mit denen ein Beteiligungsverhältnis besteht"; }) + ( + if level >= Level.Gross + then + Section "8" "Sonstige Verbindlichkeiten, davon aus Steuern, davon im Rahmen der sozialen Sicherheit" + [ + (Account "1" { title = "Umsatzsteuer"; }) + ] + else + Account "8" { title = "Sonstige Verbindlichkeiten, davon aus Steuern, davon im Rahmen der sozialen Sicherheit"; } + ) + ] + else + Account "C" { title = "Verbindlichkeiten"; } + ) + (Account "D" { title = "Rechnungsabgrenzungsposten"; }) + (Account "E" { title = "Passive latente Steuern"; }) + ] + ) + + # Gewinn- und Verlustrechnung nach § 275 Abs. 5 HGB + ( + Section "GuV" "Gewinn- und Verlustrechnung" + ( + if level == Level.Kleinst + then + [ + (Account "1" { title = "Umsatzerlöse"; }) + (Account "2" { title = "Sonstige Erträge"; }) + (Account "3" { title = "Materialaufwand"; }) + (Account "4" { title = "Personalaufwand"; }) + (Account "5" { title = "Abschreibungen"; }) + (Account "6" { title = "Sonstige Aufwendungen"; }) + (Account "7" { title = "Steuern"; }) + ] + else if method == "Umsatz" + then + [ + + ] + else if method == "Gesamt" + then + [ + ] + else + debug.panic "GuV" + '' + GuV kann entweder für eine Kleinstkapitalgesellschaften (§ 267a HGB) nach § 275 Abs. 5, + nach § 275 Abs. 2 im Gesamtkostenverfahren (method=Gesamt) oder + nach § 275 Abs. 2 Umsatzkostenverfahren (method=Umsatz) erstellt werden! + '' + ) + ) + ] + + +/* + events + = { + balance#: { ... } -> ~Transaction + = { ... } @ accounts: + { + dateTime = 0; + credit = { "Passiva-A.I" = betrag; }; + debit = { "Aktiva-B.IV.3" = betrag; }; + description = "Jemand zahlt seinen*ihren Anteil ein"; + }; + formatAccountNames#: { ... } -> ... + = { ... }: + { + balance = "Bestandskonten"; + assets = "Aktive Konten"; + liabilities = "Passive Konten"; + outcome = "Erfolgskonten"; + revenues = "Ertragskonten"; + expenses = "Aufwandskonten"; + }; + formatBalanceTitle + = { name, dateTime, ... }: + "Bilanz von ${name} am ${time.formatDate dateTime "deu"}"; + formatBalanceNames + = { ... }: + { + credit = "Haben"; + debit = "Soll"; + total = "Gesamt"; + difference = "Saldo"; + }; + formatOutcomeTitle + = { name, from, till, ... }: + "Gewinn- und Verlustrechnung von ${name} zwischen ${time.formatDate from "deu"} und ${time.formatDate till "deu"}"; + formatOutcomeTotal + = { ... }: + "Jahresüberschuss/-fehlbetrag"; + filterSection + = { level, ... }: + level <= 0; + initialTransaction + = { dateTime, ... }: + { description = "Vorjahresbilanz ${time.formatDate dateTime "deu"}"; }; + }; +*/ \ No newline at end of file diff --git a/libs/accounting/lib/single/default.nix b/libs/accounting/lib/single/default.nix new file mode 100644 index 0000000..b9a0d81 --- /dev/null +++ b/libs/accounting/lib/single/default.nix @@ -0,0 +1,2 @@ +{ ... }: + null diff --git a/libs/accounting/tests/common/default.nix b/libs/accounting/tests/common/default.nix new file mode 100644 index 0000000..1147ce4 --- /dev/null +++ b/libs/accounting/tests/common/default.nix @@ -0,0 +1,4 @@ +{ ... }: +{ + +} \ No newline at end of file diff --git a/libs/accounting/tests/default.nix b/libs/accounting/tests/default.nix new file mode 100644 index 0000000..58acc59 --- /dev/null +++ b/libs/accounting/tests/default.nix @@ -0,0 +1,7 @@ +{ core, ... }: +{ ... } @ lib: + let + inherit(core) debug; + in + { + } \ No newline at end of file diff --git a/libs/accounting/tests/double/default.nix b/libs/accounting/tests/double/default.nix new file mode 100644 index 0000000..3016350 --- /dev/null +++ b/libs/accounting/tests/double/default.nix @@ -0,0 +1,298 @@ +{ time, panic, ... }: +{ formatOutcome, Section, Transaction, ... }: +let + inherit (time) formatDate; + Level + = { + Kleinst = 0; + Klein = 1; + Mittel = 2; + Gross = 3; + }; + method = "Umsatz"; + maxLevel = Level.Kleinst; +in + "\n${ + formatOutcome { from = "2021-01-01"; till = "2021-12-31"; } + { + name = "EDV Solutions UG"; + currency = "€"; + events + = { + balance#: { ... } -> ~Transaction + = { ... } @ accounts: + { + inherit time; + credit = { "Passiva-A.I" = betrag; }; + debit = { "Aktiva-B.IV.3" = betrag; }; + description = "Jemand zahlt seinen*ihren Anteil ein"; + }; + formatAccountNames#: { ... } -> ... + = { ... }: + { + balance = "Bestandskonten"; + assets = "Aktive Konten"; + liabilities = "Passive Konten"; + outcome = "Erfolgskonten"; + revenues = "Ertragskonten"; + expenses = "Aufwandskonten"; + }; + formatBalanceTitle = { name, time, ... }: "Bilanz von ${name} am ${formatDate time "deu"}"; + formatBalanceNames + = { ... }: + { + credit = "Haben"; + debit = "Soll"; + total = "Gesamt"; + difference = "Saldo"; + }; + formatOutcomeTitle + = { name, from, till, ... }: + "Gewinn- und Verlustrechnung von ${name} zwischen ${formatDate from "deu"} und ${formatDate till "deu"}"; + formatOutcomeTotal = { ... }: "Jahresüberschuss/-fehlbetrag"; + filterSection = { level, ... }: level <= maxLevel; + initialTransaction = { time, ... }: { description = "Vorjahresbilanz ${formatDate time "deu"}"; }; + }; + assets # Aktiva nach § 266 Abs. 2 HGB + = Section { title = "Aktiva"; level = Level.Kleinst; } + [ + ( + Section { title = "Anlagevermögen"; level = Level.Klein; } + [ + ( + Section { title = "Immaterielle Vermögensgegenstände"; level = Level.Mittel; } + [ + { id = "Aktiva-A.I.1"; name = "Selbst geschaffene gewerbliche Schutzrechte und ähnliche Rechte und Werte"; } + { id = "Aktiva-A.I.2"; name = "Entgeltlich erworbene Konzessionen, gewerbliche Schutzrechte und ähnliche Rechte und Werte sowie Lizenzen an solchen Rechten und Werten"; } + { id = "Aktiva-A.I.3"; name = "Geschäfts- oder Firmenwert"; } + { id = "Aktiva-A.I.4"; name = "Geleistete Anzahlungen"; } + ] + ) + ( + Section { title = "Sachanlagen"; level = Level.Mittel; } + [ + { id = "Aktiva-A.II.1"; name = "Grundstücke, grundstücksgleiche Rechte und Bauten einschließlich der Bauten auf fremden Grundstücken"; } + { id = "Aktiva-A.II.2"; name = "Technische Anlagen und Maschinen"; } + { id = "Aktiva-A.II.3"; name = "Andere Anlagen, Betriebs- und Geschäftsausstattung"; } + { id = "Aktiva-A.II.4"; name = "Geleistete Anzahlungen und Anlagen im Bau"; } + ] + ) + ( + Section { title = "Finanzanlagen"; level = Level.Mittel; } + [ + { id = "Aktiva-A.III.1"; name = "Anteile an verbundenen Unternehmen"; } + { id = "Aktiva-A.III.2"; name = "Ausleihungen an verbundene Unternehmen"; } + { id = "Aktiva-A.III.3"; name = "Beteiligungen"; } + { id = "Aktiva-A.III.4"; name = "Ausleihungen an Unternehmen, mit denen ein Beteiligungsverhältnis besteht"; } + { id = "Aktiva-A.III.5"; name = "Wertpapiere des Anlagevermögens"; } + { id = "Aktiva-A.III.6"; name = "Sonstige Ausleihungen"; } + ] + ) + ] + ) + ( + Section { title = "Umlaufvermögen"; level = Level.Klein; } + [ + ( + Section { title = "Vorräte"; level = Level.Mittel; } + [ + { id = "Aktiva-B.I.1"; name = "Roh-, Hilfs- und Betriebsstoffe"; } + { id = "Aktiva-B.I.2"; name = "Unfertige Erzeugnisse, unfertige Leistungen"; } + { id = "Aktiva-B.I.3"; name = "Fertige Erzeugnisse und Waren"; } + { id = "Aktiva-B.I.4"; name = "Geleistete Anzahlungen"; } + ] + ) + ( + Section { title = "Forderungen"; level = Level.Mittel; } + [ + { id = "Aktiva-B.II.1"; name = "Forderungen aus Lieferungen und Leistungen"; } + { id = "Aktiva-B.II.2"; name = "Forderungen gegen verbundene Unternehmen"; } + { id = "Aktiva-B.II.3"; name = "Forderungen gegen Unternehmen, mit denen ein Beteiligungsverhältnis besteht"; } + ( + Section { title = "Sonstige Vermögensgegenstände"; level = Level.Gross; } + [ + { id = "Aktiva-B.II.4.1"; name = "Abziehbare Vorsteuer"; } + ] + ) + ] + ) + ( + Section { title = "Wertpapiere"; level = Level.Mittel; } + [ + { id = "Aktiva-B.III.1"; name = "Anteile an verbundenen Unternehmen"; } + { id = "Aktiva-B.III.2"; name = "Sonstige Wertpapiere"; } + ] + ) + ( + Section { title = "Sonstiges Umlaufvermögen"; level = Level.Gross; } + [ + { id = "Aktiva-B.IV.1"; name = "Kassenbestand"; } + { id = "Aktiva-B.IV.2"; name = "Bundesbankguthaben"; } + { id = "Aktiva-B.IV.3"; name = "Bank"; } + { id = "Aktiva-B.IV.4"; name = "Schecks"; } + ] + ) + ] + ) + { id = "Aktiva-C"; name = "Rechnungsabgrenzungsposten"; } + { id = "Aktiva-D"; name = "Aktive latente Steuern"; } + { id = "Aktiva-E"; name = "Aktiver Unterschiedsbetrag aus der Vermögensverrechnung"; } + ]; + liabilities # Passiva nach § 266 Abs. 3 HGB + = Section { title = "Passiva"; level = Level.Kleinst; } + [ + ( + Section { title = "Eigenkapital"; level = Level.Klein; } + [ + { id = "Passiva-A.I"; name = "Gezeichnetes Kapital"; } + { id = "Passiva-A.II"; name = "Kapitalrücklage"; } + ( + Section { title = "Gewinnrücklagen"; level = Level.Mittel; } + [ + { id = "Passiva-A.III.1"; name = "Gesetzliche Rücklage"; } + { id = "Passiva-A.III.2"; name = "Rücklage für Anteile an einem herrschenden oder mehrheitlich beteiligten Unternehmen"; } + { id = "Passiva-A.III.3"; name = "Satzungsmäßige Rücklagen"; } + { id = "Passiva-A.III.4"; name = "Andere Gewinnrücklagen"; } + ] + ) + { id = "Passiva-A.IV"; name = "Gewinn-/Verlustvortrag"; } + { id = "Passiva-A.V"; name = "Jahresüberschuß/-fehlbetrag"; } + ] + ) + ( + Section { title = "Rückstellungen"; level = Level.Mittel; } + [ + { id = "Passiva-B.1"; name = "Rückstellungen für Pensionen und ähnliche Verpflichtungen"; } + { id = "Passiva-B.2"; name = "Steuerrückstellungen"; } + { id = "Passiva-B.3"; name = "Sonstige Rückstellungen"; } + ] + ) + ( + Section { title = "Verbindlichkeiten"; level = Level.Mittel; } + [ + { id = "Passiva-C.1"; name = "Anleihen davon konvertibel"; } + { id = "Passiva-C.2"; name = "Verbindlichkeiten gegenüber Kreditinstituten"; } + { id = "Passiva-C.3"; name = "Erhaltene Anzahlungen auf Bestellungen"; } + { id = "Passiva-C.4"; name = "Verbindlichkeiten aus Lieferungen und Leistungen"; } + { id = "Passiva-C.5"; name = "Verbindlichkeiten aus der Annahme gezogener Wechsel und der Ausstellung eigener Wechsel"; } + { id = "Passiva-C.6"; name = "Verbindlichkeiten gegenüber verbundenen Unternehmen"; } + { id = "Passiva-C.7"; name = "Verbindlichkeiten gegenüber Unternehmen, mit denen ein Beteiligungsverhältnis besteht"; } + ( + Section { title = "Sonstige Verbindlichkeiten, davon aus Steuern, davon im Rahmen der sozialen Sicherheit"; level = Level.Gross; } + [ + { id = "Passiva-C.8.1"; name = "Umsatzsteuer"; } + ] + ) + ] + ) + { id = "Passiva-D"; name = "Rechnungsabgrenzungsposten"; } + { id = "Passiva-E"; name = "Passive latente Steuern"; } + ]; + outcome # Gewinn- und Verlustrechnung nach § 275 Abs. 5 HGB + = Section { title = "Jahresüberschuss/-fehlbetrag"; level = Level.Kleinst; } + ( + if maxLevel == Level.Kleinst + then + [ + { id = "GuV-1"; name = "Umsatzerlöse"; } + { id = "GuV-2"; name = "Sonstige Erträge"; } + { id = "GuV-3"; name = "Materialaufwand"; } + { id = "GuV-4"; name = "Personalaufwand"; } + { id = "GuV-5"; name = "Abschreibungen"; } + { id = "GuV-6"; name = "Sonstige Aufwendungen"; } + { id = "GuV-7"; name = "Steuern"; } + ] + else if method == "Umsatz" + then + [ + ] + else if method == "Gesamt" + then + [ + ] + else + debug.panic "GuV" + '' + GuV kann entweder für eine Kleinstkapitalgesellschaften (§ 267a HGB) nach § 275 Abs. 5, + nach § 275 Abs. 2 im Gesamtkostenverfahren (method=Gesamt) oder + nach § 275 Abs. 2 Umsatzkostenverfahren (method=Umsatz) erstellt werden! + '' + ); + inventory # Materialien, Maschinen, Grundstücken, … + = Section "Inventar" + [ + { id = "Inventar-1"; name = "Materialien"; } + ]; + journal # Chronologische Liste aller Geschäftsvorfälle + = import ./journal.nix + { + Gesellschaftereinzahlung + = time: + betrag: + name: + { + inherit time; + credit = { "Passiva-A.I" = betrag; }; + debit = { "Aktiva-B.IV.3" = betrag; }; + description = "${name} zahlt seinen*ihren Anteil ein"; + }; + Kontofuehrungsgebuehr + = time: + betrag: + { + inherit time; + credit = { "Aktiva-B.IV.3" = betrag; }; + debit = { "GuV-6" = betrag; }; + description = "Kontoführungsgebühren"; + }; + Forderung + = time: + betrag: + kunde: + rechnungsnummer: + let + betrag' = betrag / 1.19; + steuer = betrag - betrag'; + in + { + inherit time; + credit = { "GuV-1" = betrag'; "Passiva-C.8.1" = steuer; }; + debit = { "Aktiva-B.II.1" = betrag; }; + description = "Rechnung an ${kunde} (${rechnungsnummer})"; + }; + Rechnungsbegleichung + = time: + betrag: + rechnungsnummer: + { + inherit time; + credit = { "Aktiva-B.II.1" = betrag; }; + debit = { "Aktiva-B.IV.3" = betrag; }; + description = "Rechnung ${rechnungsnummer} beglichen"; + }; + Sachanlagen + = time: + betrag: + sache: + let + betrag' = betrag / 1.19; + steuer = betrag - betrag'; + in + { + inherit time; + credit = { "Aktiva-B.IV.3" = betrag; }; + debit = { "Aktiva-A.II.2" = betrag'; "Aktiva-B.II.4.1" = steuer; }; + description = "Ankauf von ${sache}"; + }; + Gewinnruecklage + = time: + betrag: + { + inherit time; + credit = { "Passiva-A.III.4" = betrag; }; + debit = { "Passiva-A.IV" = betrag; }; + description = "Gewinnrücklage"; + }; + }; + } + }" \ No newline at end of file diff --git a/libs/accounting/tests/double/journal.nix b/libs/accounting/tests/double/journal.nix new file mode 100644 index 0000000..efd5715 --- /dev/null +++ b/libs/accounting/tests/double/journal.nix @@ -0,0 +1,19 @@ +{ + Forderung, + Gesellschaftereinzahlung, + Gewinnruecklage, + Kontofuehrungsgebuehr, + Rechnungsbegleichung, + Sachanlagen, + ... +}: +[ + ( Gesellschaftereinzahlung "2021-03-01" 15000 "Sivizius" ) + ( Gesellschaftereinzahlung "2021-03-02" 20000 "Fluepke" ) + ( Kontofuehrungsgebuehr "2021-03-31" 100 ) + ( Forderung "2021-04-04" 1190 "Kunze GmbH" "2021-0001" ) + ( Rechnungsbegleichung "2021-04-20" 600 "2021-0001" ) + ( Rechnungsbegleichung "2021-05-02" 590 "2021-0001" ) + ( Sachanlagen "2021-06-02" 476 "Computer" ) + ( Gewinnruecklage "2022-01-01" 450 ) +] \ No newline at end of file diff --git a/libs/accounting/tests/single/default.nix b/libs/accounting/tests/single/default.nix new file mode 100644 index 0000000..1147ce4 --- /dev/null +++ b/libs/accounting/tests/single/default.nix @@ -0,0 +1,4 @@ +{ ... }: +{ + +} \ No newline at end of file diff --git a/libs/aes/default.nix b/libs/aes/default.nix new file mode 100644 index 0000000..43584fd --- /dev/null +++ b/libs/aes/default.nix @@ -0,0 +1,15 @@ +{ core, ... } @ libs: + let + inherit(core) check library target; + lib = library.load ./lib libs; + tests = check.load ./tests libs lib; + in + { + inherit lib tests; + + checks + = check tests + { + targetSystem = target.System.all.x86_64-linux; + }; + } \ No newline at end of file diff --git a/libs/aes/flake.lock b/libs/aes/flake.lock new file mode 100644 index 0000000..a2df9cd --- /dev/null +++ b/libs/aes/flake.lock @@ -0,0 +1,46 @@ +{ + "nodes": { + "libcore": { + "inputs": { + "libintrinsics": "libintrinsics" + }, + "locked": { + "dir": "libs/core", + "lastModified": 1681394603, + "narHash": "sha256-vkzKAemGzs2kNWk2yDiLFW2zF4g7ck45QpnB5ACEfms=", + "type": "git", + "url": "file:///home/sivizius/Projects/Active/nixfiles?dir=libs%2fcore" + }, + "original": { + "dir": "libs/core", + "owner": "sivizius", + "ref": "development", + "repo": "nixfiles", + "type": "github" + } + }, + "libintrinsics": { + "locked": { + "dir": "libs/intrinsics", + "lastModified": 1681394603, + "narHash": "sha256-vkzKAemGzs2kNWk2yDiLFW2zF4g7ck45QpnB5ACEfms=", + "type": "git", + "url": "file:///home/sivizius/Projects/Active/nixfiles?dir=libs%2fintrinsics" + }, + "original": { + "dir": "libs/intrinsics", + "owner": "sivizius", + "ref": "development", + "repo": "nixfiles", + "type": "github" + } + }, + "root": { + "inputs": { + "libcore": "libcore" + } + } + }, + "root": "root", + "version": 7 +} diff --git a/libs/aes/flake.nix b/libs/aes/flake.nix new file mode 100644 index 0000000..8ab2d1e --- /dev/null +++ b/libs/aes/flake.nix @@ -0,0 +1,13 @@ +{ + description = "AES implemented as nix-expressions."; + inputs + = { + libcore.url = "github:sivizius/nixfiles/development?dir=libs/core"; + }; + outputs + = { self, libcore, ... }: + let + core = libcore.lib { inherit self; debug.logLevel = "debug"; }; + in + core.path.import ./. { inherit core self; }; +} \ No newline at end of file diff --git a/libs/aes/lib/decrypt/default.nix b/libs/aes/lib/decrypt/default.nix new file mode 100644 index 0000000..f7958d2 --- /dev/null +++ b/libs/aes/lib/decrypt/default.nix @@ -0,0 +1,173 @@ +{ core, helpers, key, serde, ... }: + let + inherit(core) bool debug integer list path; + inherit(helpers) addRoundKey formatColumns unshiftRows4andUnsubstitute toBuffer; + inherit(key) AESkey; + inherit(serde) packDWordBuffer unpackDWord; + + unmixColumns + = list.map + ( + { byte0, byte1, byte2, byte3, ... }: + let + getH = x: bool.select (x > 127) 27 0; + + byte0' = integer.xor (integer.and (byte0 * 2) 255) (getH byte0); + byte1' = integer.xor (integer.and (byte1 * 2) 255) (getH byte1); + byte2' = integer.xor (integer.and (byte2 * 2) 255) (getH byte2); + byte3' = integer.xor (integer.and (byte3 * 2) 255) (getH byte3); + + byte0'' = integer.xor (integer.and (byte0' * 2) 255) (getH byte0'); + byte1'' = integer.xor (integer.and (byte1' * 2) 255) (getH byte1'); + byte2'' = integer.xor (integer.and (byte2' * 2) 255) (getH byte2'); + byte3'' = integer.xor (integer.and (byte3' * 2) 255) (getH byte3'); + + byte0''' = integer.xor (integer.and (byte0'' * 2) 255) (getH byte0''); + byte1''' = integer.xor (integer.and (byte1'' * 2) 255) (getH byte1''); + byte2''' = integer.xor (integer.and (byte2'' * 2) 255) (getH byte2''); + byte3''' = integer.xor (integer.and (byte3'' * 2) 255) (getH byte3''); + + common = integer.xor (integer.xor byte0''' byte1''') (integer.xor byte2''' byte3'''); + fold = list.fold integer.xor common; + in + { + byte0 = fold [ byte0'' byte0' byte1' byte1 byte2'' byte2 byte3 ]; + byte1 = fold [ byte0 byte1'' byte1' byte2' byte2 byte3'' byte3 ]; + byte2 = fold [ byte0'' byte0 byte1 byte2'' byte2' byte3' byte3 ]; + byte3 = fold [ byte0' byte0 byte1'' byte1 byte2 byte3'' byte3' ]; + } + ); + + slowRoundDecryption + = state: + let + state' = unmixColumns state; + state'' = unshiftRows4andUnsubstitute state'; + in + debug.debug "slowRoundDecryption" + { + data + = { + state = formatColumns state; + state' = formatColumns state'; + state'' = formatColumns state''; + }; + nice = true; + } + state''; + + # does not work, because it needs the key-inverse. + fastRoundDecryption + = let + td0 = path.import ./td0.nix; + td1 = path.import ./td1.nix; + td2 = path.import ./td2.nix; + td3 = path.import ./td3.nix; + + subTD0 = list.get td0; + subTD1 = list.get td1; + subTD2 = list.get td2; + subTD3 = list.get td3; + in + state: + let + column0 = list.get state 0; + column1 = list.get state 1; + column2 = list.get state 2; + column3 = list.get state 3; + + column0' + = unpackDWord + ( + integer.xor + (integer.xor (subTD0 column0.byte0) (subTD1 column3.byte1)) + (integer.xor (subTD2 column2.byte2) (subTD3 column1.byte3)) + ); + column1' + = unpackDWord + ( + integer.xor + (integer.xor (subTD0 column1.byte0) (subTD1 column0.byte1)) + (integer.xor (subTD2 column3.byte2) (subTD3 column2.byte3)) + ); + column2' + = unpackDWord + ( + integer.xor + (integer.xor (subTD0 column2.byte0) (subTD1 column1.byte2)) + (integer.xor (subTD2 column0.byte2) (subTD3 column3.byte3)) + ); + column3' + = unpackDWord + ( + integer.xor + (integer.xor (subTD0 column3.byte0) (subTD1 column2.byte1)) + (integer.xor (subTD2 column1.byte2) (subTD3 column0.byte3)) + ); + state' = [ column0' column1' column2' column3' ]; + in + debug.debug "fastRoundDecryption" + { + data + = { + state = formatColumns state; + state' = formatColumns state'; + }; + hex = true; + nice = true; + } + state'; + + decrypt#: AESkey -> [ u8 ] + = applyRoundDecryption: + { roundKeys, ... }: + message: + let + message' = toBuffer 4 message; + applyRoundDecryption' + = state: + roundKey: + let + state' = addRoundKey state roundKey; + in + debug.info "applyRoundDecryption'" + { + data + = { + state = formatColumns state; + state' = formatColumns state'; + roundKey = formatColumns roundKey; + }; + nice = true; + } + (applyRoundDecryption state'); + + firstRoundKey = list.head roundKeys; + lastRoundKey = list.foot roundKeys; + roundKeys' = list.body (list.tail roundKeys); + + state = unshiftRows4andUnsubstitute (addRoundKey message' lastRoundKey); + state' + = list.foldReversed + applyRoundDecryption' + state + roundKeys'; + in + debug.debug "decrypt" + { + data + = { + state = formatColumns state; + state' = formatColumns state'; + }; + hex = true; + nice = true; + } + addRoundKey state' firstRoundKey; + in + { + __functor = _: decrypt; + #fast = key: decrypt fastRoundDecryption (AESkey.expect key); + slow = key: decrypt slowRoundDecryption (AESkey.expect key); + inherit unmixColumns; + } diff --git a/libs/aes/lib/decrypt/td0.nix b/libs/aes/lib/decrypt/td0.nix new file mode 100644 index 0000000..adeaa8e --- /dev/null +++ b/libs/aes/lib/decrypt/td0.nix @@ -0,0 +1,34 @@ +[ + 1353184337 1399144830 3282310938 2522752826 3412831035 4047871263 2874735276 2466505547 + 1442459680 4134368941 2440481928 625738485 4242007375 3620416197 2151953702 2409849525 + 1230680542 1729870373 2551114309 3787521629 41234371 317738113 2744600205 3338261355 + 3881799427 2510066197 3950669247 3663286933 763608788 3542185048 694804553 1154009486 + 1787413109 2021232372 1799248025 3715217703 3058688446 397248752 1722556617 3023752829 + 407560035 2184256229 1613975959 1165972322 3765920945 2226023355 480281086 2485848313 + 1483229296 436028815 2272059028 3086515026 601060267 3791801202 1468997603 715871590 + 120122290 63092015 2591802758 2768779219 4068943920 2997206819 3127509762 1552029421 + 723308426 2461301159 4042393587 2715969870 3455375973 3586000134 526529745 2331944644 + 2639474228 2689987490 853641733 1978398372 971801355 2867814464 111112542 1360031421 + 4186579262 1023860118 2919579357 1186850381 3045938321 90031217 1876166148 4279586912 + 620468249 2548678102 3426959497 2006899047 3175278768 2290845959 945494503 3689859193 + 1191869601 3910091388 3374220536 0 2206629897 1223502642 2893025566 1316117100 + 4227796733 1446544655 517320253 658058550 1691946762 564550760 3511966619 976107044 + 2976320012 266819475 3533106868 2660342555 1338359936 2720062561 1766553434 370807324 + 179999714 3844776128 1138762300 488053522 185403662 2915535858 3114841645 3366526484 + 2233069911 1275557295 3151862254 4250959779 2670068215 3170202204 3309004356 880737115 + 1982415755 3703972811 1761406390 1676797112 3403428311 277177154 1076008723 538035844 + 2099530373 4164795346 288553390 1839278535 1261411869 4080055004 3964831245 3504587127 + 1813426987 2579067049 4199060497 577038663 3297574056 440397984 3626794326 4019204898 + 3343796615 3251714265 4272081548 906744984 3481400742 685669029 646887386 2764025151 + 3835509292 227702864 2613862250 1648787028 3256061430 3904428176 1593260334 4121936770 + 3196083615 2090061929 2838353263 3004310991 999926984 2809993232 1852021992 2075868123 + 158869197 4095236462 28809964 2828685187 1701746150 2129067946 147831841 3873969647 + 3650873274 3459673930 3557400554 3598495785 2947720241 824393514 815048134 3227951669 + 935087732 2798289660 2966458592 366520115 1251476721 4158319681 240176511 804688151 + 2379631990 1303441219 1414376140 3741619940 3820343710 461924940 3089050817 2136040774 + 82468509 1563790337 1937016826 776014843 1511876531 1389550482 861278441 323475053 + 2355222426 2047648055 2383738969 2302415851 3995576782 902390199 3991215329 1018251130 + 1507840668 1064563285 2043548696 3208103795 3939366739 1537932639 342834655 2262516856 + 2180231114 1053059257 741614648 1598071746 1925389590 203809468 2336832552 1100287487 + 1895934009 3736275976 2632234200 2428589668 1636092795 1890988757 1952214088 1113045200 +] \ No newline at end of file diff --git a/libs/aes/lib/decrypt/td1.nix b/libs/aes/lib/decrypt/td1.nix new file mode 100644 index 0000000..df432a3 --- /dev/null +++ b/libs/aes/lib/decrypt/td1.nix @@ -0,0 +1,34 @@ +[ + 2817806672 1698790995 2752977603 1579629206 1806384075 1167925233 1492823211 65227667 + 4197458005 1836494326 1993115793 1275262245 3622129660 3408578007 1144333952 2741155215 + 1521606217 465184103 250234264 3237895649 1966064386 4031545618 2537983395 4191382470 + 1603208167 2626819477 2054012907 1498584538 2210321453 561273043 1776306473 3368652356 + 2311222634 2039411832 1045993835 1907959773 1340194486 2911432727 2887829862 986611124 + 1256153880 823846274 860985184 2136171077 2003087840 2926295940 2692873756 722008468 + 1749577816 4249194265 1826526343 4168831671 3547573027 38499042 2401231703 2874500650 + 686535175 3266653955 2076542618 137876389 2267558130 2780767154 1778582202 2182540636 + 483363371 3027871634 4060607472 3798552225 4107953613 3188000469 1647628575 4272342154 + 1395537053 1442030240 3783918898 3958809717 3968011065 4016062634 2675006982 275692881 + 2317434617 115185213 88006062 3185986886 2371129781 1573155077 3557164143 357589247 + 4221049124 3921532567 1128303052 2665047927 1122545853 2341013384 1528424248 4006115803 + 175939911 256015593 512030921 0 2256537987 3979031112 1880170156 1918528590 + 4279172603 948244310 3584965918 959264295 3641641572 2791073825 1415289809 775300154 + 1728711857 3881276175 2532226258 2442861470 3317727311 551313826 1266113129 437394454 + 3130253834 715178213 3760340035 387650077 218697227 3347837613 2830511545 2837320904 + 435246981 125153100 3717852859 1618977789 637663135 4117912764 996558021 2130402100 + 692292470 3324234716 4243437160 4058298467 3694254026 2237874704 580326208 298222624 + 608863613 1035719416 855223825 2703869805 798891339 817028339 1384517100 3821107152 + 380840812 3111168409 1217663482 1693009698 2365368516 1072734234 746411736 2419270383 + 1313441735 3510163905 2731183358 198481974 2180359887 3732579624 2394413606 3215802276 + 2637835492 2457358349 3428805275 1182684258 328070850 3101200616 4147719774 2948825845 + 2153619390 2479909244 768962473 304467891 2578237499 2098729127 1671227502 3141262203 + 2015808777 408514292 3080383489 2588902312 1855317605 3875515006 3485212936 3893751782 + 2615655129 913263310 161475284 2091919830 2997105071 591342129 2493892144 1721906624 + 3159258167 3397581990 3499155632 3634836245 2550460746 3672916471 1355644686 4136703791 + 3595400845 2968470349 1303039060 76997855 3050413795 2288667675 523026872 1365591679 + 3932069124 898367837 1955068531 1091304238 493335386 3537605202 1443948851 1205234963 + 1641519756 211892090 351820174 1007938441 665439982 3378624309 3843875309 2974251580 + 3755121753 1945261375 3457423481 935818175 3455538154 2868731739 1866325780 3678697606 + 4088384129 3295197502 874788908 1084473951 3273463410 635616268 1228679307 2500722497 + 27801969 3003910366 3837057180 3243664528 2227927905 3056784752 1550600308 1471729730 +] \ No newline at end of file diff --git a/libs/aes/lib/decrypt/td2.nix b/libs/aes/lib/decrypt/td2.nix new file mode 100644 index 0000000..160b3ac --- /dev/null +++ b/libs/aes/lib/decrypt/td2.nix @@ -0,0 +1,34 @@ +[ + 4098969767 1098797925 387629988 658151006 2872822635 2636116293 4205620056 3813380867 + 807425530 1991112301 3431502198 49620300 3847224535 717608907 891715652 1656065955 + 2984135002 3123013403 3930429454 4267565504 801309301 1283527408 1183687575 3547055865 + 2399397727 2450888092 1841294202 1385552473 3201576323 1951978273 3762891113 3381544136 + 3262474889 2398386297 1486449470 3106397553 3787372111 2297436077 550069932 3464344634 + 3747813450 451248689 1368875059 1398949247 1689378935 1807451310 2180914336 150574123 + 1215322216 1167006205 3734275948 2069018616 1940595667 1265820162 534992783 1432758955 + 3954313000 3039757250 3313932923 936617224 674296455 3206787749 50510442 384654466 + 3481938716 2041025204 133427442 1766760930 3664104948 84334014 886120290 2797898494 + 775200083 4087521365 2315596513 4137973227 2198551020 1614850799 1901987487 1857900816 + 557775242 3717610758 1054715397 3863824061 1418835341 3295741277 100954068 1348534037 + 2551784699 3184957417 1082772547 3647436702 3903896898 2298972299 434583643 3363429358 + 2090944266 1115482383 2230896926 0 2148107142 724715757 287222896 1517047410 + 251526143 2232374840 2923241173 758523705 252339417 1550328230 1536938324 908343854 + 168604007 1469255655 4004827798 2602278545 3229634501 3697386016 2002413899 303830554 + 2481064634 2696996138 574374880 454171927 151915277 2347937223 3056449960 504678569 + 4049044761 1974422535 2582559709 2141453664 33005350 1918680309 1715782971 4217058430 + 1133213225 600562886 3988154620 3837289457 836225756 1665273989 2534621218 3330547729 + 1250262308 3151165501 4188934450 700935585 2652719919 3000824624 2249059410 3245854947 + 3005967382 1890163129 2484206152 3913753188 4238918796 4037024319 2102843436 857927568 + 1233635150 953795025 3398237858 3566745099 4121350017 2057644254 3084527246 2906629311 + 976020637 2018512274 1600822220 2119459398 2381758995 3633375416 959340279 3280139695 + 1570750080 3496574099 3580864813 634368786 2898803609 403744637 2632478307 1004239803 + 650971512 1500443672 2599158199 1334028442 2514904430 4289363686 3156281551 368043752 + 3887782299 1867173430 2682967049 2955531900 2754719666 1059729699 2781229204 2721431654 + 1316239292 2197595850 2430644432 2805143000 82922136 3963746266 3447656016 2434215926 + 1299615190 4014165424 2865517645 2531581700 3516851125 1783372680 750893087 1699118929 + 1587348714 2348899637 2281337716 201010753 1739807261 3683799762 283718486 3597472583 + 3617229921 2704767500 4166618644 334203196 2848910887 1639396809 484568549 1199193265 + 3533461983 4065673075 337148366 3346251575 4149471949 4250885034 1038029935 1148749531 + 2949284339 1756970692 607661108 2747424576 488010435 3803974693 1009290057 234832277 + 2822336769 201907891 3034094820 1449431233 3413860740 852848822 1816687708 3100656215 +] \ No newline at end of file diff --git a/libs/aes/lib/decrypt/td3.nix b/libs/aes/lib/decrypt/td3.nix new file mode 100644 index 0000000..14824e8 --- /dev/null +++ b/libs/aes/lib/decrypt/td3.nix @@ -0,0 +1,34 @@ +[ + 1364240372 2119394625 449029143 982933031 1003187115 535905693 2896910586 1267925987 + 542505520 2918608246 2291234508 4112862210 1341970405 3319253802 645940277 3046089570 + 3729349297 627514298 1167593194 1575076094 3271718191 2165502028 2376308550 1808202195 + 65494927 362126482 3219880557 2514114898 3559752638 1490231668 1227450848 2386872521 + 1969916354 4101536142 2573942360 668823993 3199619041 4028083592 3378949152 2108963534 + 1662536415 3850514714 2539664209 1648721747 2984277860 3146034795 4263288961 4187237128 + 1884842056 2400845125 2491903198 1387788411 2871251827 1927414347 3814166303 1714072405 + 2986813675 788775605 2258271173 3550808119 821200680 598910399 45771267 3982262806 + 2318081231 2811409529 4092654087 1319232105 1707996378 114671109 3508494900 3297443494 + 882725678 2728416755 87220618 2759191542 188345475 1084944224 1577492337 3176206446 + 1056541217 2520581853 3719169342 1296481766 2444594516 1896177092 74437638 1627329872 + 421854104 3600279997 2311865152 1735892697 2965193448 126389129 3879230233 2044456648 + 2705787516 2095648578 4173930116 0 159614592 843640107 514617361 1817080410 + 4261150478 257308805 1025430958 908540205 174381327 1747035740 2614187099 607792694 + 212952842 2467293015 3033700078 463376795 2152711616 1638015196 1516850039 471210514 + 3792353939 3236244128 1011081250 303896347 235605257 4071475083 767142070 348694814 + 1468340721 2940995445 4005289369 2751291519 4154402305 1555887474 1153776486 1530167035 + 2339776835 3420243491 3060333805 3093557732 3620396081 1108378979 322970263 2216694214 + 2239571018 3539484091 2920362745 3345850665 491466654 3706925234 233591430 2010178497 + 728503987 2845423984 301615252 1193436393 2831453436 2686074864 1457007741 586125363 + 2277985865 3653357880 2365498058 2553678804 2798617077 2770919034 3659959991 1067761581 + 753179962 1343066744 1788595295 1415726718 4139914125 2431170776 777975609 2197139395 + 2680062045 1769771984 1873358293 3484619301 3359349164 279411992 3899548572 3682319163 + 3439949862 1861490777 3959535514 2208864847 3865407125 2860443391 554225596 4024887317 + 3134823399 1255028335 3939764639 701922480 833598116 707863359 3325072549 901801634 + 1949809742 4238789250 3769684112 857069735 4048197636 1106762476 2131644621 389019281 + 1989006925 1129165039 3428076970 3839820950 2665723345 1276872810 3250069292 1182749029 + 2634345054 22885772 4201870471 4214112523 3009027431 2454901467 3912455696 1829980118 + 2592891351 930745505 1502483704 3951639571 3471714217 3073755489 3790464284 2050797895 + 2623135698 1430221810 410635796 1941911495 1407897079 1599843069 3742658365 2022103876 + 3397514159 3107898472 942421028 3261022371 376619805 3154912738 680216892 4282488077 + 963707304 148812556 3634160820 1687208278 2069988555 3580933682 1215585388 3494008760 +] \ No newline at end of file diff --git a/libs/aes/lib/default.nix b/libs/aes/lib/default.nix new file mode 100644 index 0000000..c71f0e0 --- /dev/null +++ b/libs/aes/lib/default.nix @@ -0,0 +1,10 @@ +{ core, ... }: + Library "libaes" + { inherit core; } + { + decrypt = ./decrypt; + encrypt = ./encrypt; + key = ./key; + helpers = ./helpers; + serde = ./serde; + } diff --git a/libs/aes/lib/encrypt/default.nix b/libs/aes/lib/encrypt/default.nix new file mode 100644 index 0000000..871a28c --- /dev/null +++ b/libs/aes/lib/encrypt/default.nix @@ -0,0 +1,109 @@ +{ core, helpers, key, serde, ... }: + let + inherit(core) bool integer list path; + inherit(helpers) addRoundKey substituteAndShiftRows4 toBuffer; + inherit(key) AESkey; + inherit(serde) unpackDWord; + + slowRoundEncryption + = let + mixColumns + = list.map + ( + { byte0, byte1, byte2, byte3, ... }: + let + getH = x: bool.select (x > 127) 27 0; + byte0' = integer.xor (integer.and (byte0 * 2) 255) (getH byte0); + byte1' = integer.xor (integer.and (byte1 * 2) 255) (getH byte1); + byte2' = integer.xor (integer.and (byte2 * 2) 255) (getH byte2); + byte3' = integer.xor (integer.and (byte3 * 2) 255) (getH byte3); + in + { + byte0 = list.fold integer.xor byte0' [ byte3 byte2 byte1' byte1 ]; + byte1 = list.fold integer.xor byte1' [ byte0 byte3 byte2' byte2 ]; + byte2 = list.fold integer.xor byte2' [ byte1 byte0 byte3' byte3 ]; + byte3 = list.fold integer.xor byte3' [ byte2 byte1 byte0' byte0 ]; + } + ); + in + state: + mixColumns (substituteAndShiftRows4 state); + + fastRoundEncryption + = let + te0 = path.import ./te0.nix; + te1 = path.import ./te1.nix; + te2 = path.import ./te2.nix; + te3 = path.import ./te3.nix; + + subTE0 = list.get te0; + subTE1 = list.get te1; + subTE2 = list.get te2; + subTE3 = list.get te3; + in + state: + let + column0 = list.get state 0; + column1 = list.get state 1; + column2 = list.get state 2; + column3 = list.get state 3; + + column0' + = unpackDWord + ( + integer.xor + (integer.xor (subTE0 column0.byte0) (subTE1 column1.byte1)) + (integer.xor (subTE2 column2.byte2) (subTE3 column3.byte3)) + ); + column1' + = unpackDWord + ( + integer.xor + (integer.xor (subTE0 column1.byte0) (subTE1 column2.byte1)) + (integer.xor (subTE2 column3.byte2) (subTE3 column0.byte3)) + ); + column2' + = unpackDWord + ( + integer.xor + (integer.xor (subTE0 column2.byte0) (subTE1 column3.byte1)) + (integer.xor (subTE2 column0.byte2) (subTE3 column1.byte3)) + ); + column3' + = unpackDWord + ( + integer.xor + (integer.xor (subTE0 column3.byte0) (subTE1 column0.byte1)) + (integer.xor (subTE2 column1.byte2) (subTE3 column2.byte3)) + ); + in + [ column0' column1' column2' column3' ]; + + encrypt#: AESkey -> [ u8 ] + = applyRoundEncryption: + { roundKeys, ... }: + message: + let + message' = toBuffer 4 message; + applyRoundEncryption' = state: addRoundKey (applyRoundEncryption state); + + firstRoundKey = list.head roundKeys; + lastRoundKey = list.foot roundKeys; + roundKeys' = list.body (list.tail roundKeys); + + state = addRoundKey message' firstRoundKey; + state' + = list.fold + applyRoundEncryption' + state + roundKeys'; + in + addRoundKey + (substituteAndShiftRows4 state') + lastRoundKey; + in + { + __functor = _: encrypt; + fast = key: encrypt fastRoundEncryption (AESkey.expect key); + slow = key: encrypt slowRoundEncryption (AESkey.expect key); + } diff --git a/libs/aes/lib/encrypt/te0.nix b/libs/aes/lib/encrypt/te0.nix new file mode 100644 index 0000000..c891257 --- /dev/null +++ b/libs/aes/lib/encrypt/te0.nix @@ -0,0 +1,34 @@ +[ + 2774754246 2222750968 2574743534 2373680118 234025727 3177933782 2976870366 1422247313 + 1345335392 50397442 2842126286 2099981142 436141799 1658312629 3870010189 2591454956 + 1170918031 2642575903 1086966153 2273148410 368769775 3948501426 3376891790 200339707 + 3970805057 1742001331 4255294047 3937382213 3214711843 4154762323 2524082916 1539358875 + 3266819957 486407649 2928907069 1780885068 1513502316 1094664062 49805301 1338821763 + 1546925160 4104496465 887481809 150073849 2473685474 1943591083 1395732834 1058346282 + 201589768 1388824469 1696801606 1589887901 672667696 2711000631 251987210 3046808111 + 151455502 907153956 2608889883 1038279391 652995533 1764173646 3451040383 2675275242 + 453576978 2659418909 1949051992 773462580 756751158 2993581788 3998898868 4221608027 + 4132590244 1295727478 1641469623 3467883389 2066295122 1055122397 1898917726 2542044179 + 4115878822 1758581177 0 753790401 1612718144 536673507 3367088505 3982187446 + 3194645204 1187761037 3653156455 1262041458 3729410708 3561770136 3898103984 1255133061 + 1808847035 720367557 3853167183 385612781 3309519750 3612167578 1429418854 2491778321 + 3477423498 284817897 100794884 2172616702 4031795360 1144798328 3131023141 3819481163 + 4082192802 4272137053 3225436288 2324664069 2912064063 3164445985 1211644016 83228145 + 3753688163 3249976951 1977277103 1663115586 806359072 452984805 250868733 1842533055 + 1288555905 336333848 890442534 804056259 3781124030 2727843637 3427026056 957814574 + 1472513171 4071073621 2189328124 1195195770 2892260552 3881655738 723065138 2507371494 + 2690670784 2558624025 3511635870 2145180835 1713513028 2116692564 2878378043 2206763019 + 3393603212 703524551 3552098411 1007948840 2044649127 3797835452 487262998 1994120109 + 1004593371 1446130276 1312438900 503974420 3679013266 168166924 1814307912 3831258296 + 1573044895 1859376061 4021070915 2791465668 2828112185 2761266481 937747667 2339994098 + 854058965 1137232011 1496790894 3077402074 2358086913 1691735473 3528347292 3769215305 + 3027004632 4199962284 133494003 636152527 2942657994 2390391540 3920539207 403179536 + 3585784431 2289596656 1864705354 1915629148 605822008 4054230615 3350508659 1371981463 + 602466507 2094914977 2624877800 555687742 3712699286 3703422305 2257292045 2240449039 + 2423288032 1111375484 3300242801 2858837708 3628615824 84083462 32962295 302911004 + 2741068226 1597322602 4183250862 3501832553 2441512471 1489093017 656219450 3114180135 + 954327513 335083755 3013122091 856756514 3144247762 1893325225 2307821063 2811532339 + 3063651117 572399164 2458355477 552200649 1238290055 4283782570 2015897680 2061492133 + 2408352771 4171342169 2156497161 386731290 3669999461 837215959 3326231172 3093850320 + 3275833730 2962856233 1999449434 286199582 3417354363 4233385128 3602627437 974525996 +] diff --git a/libs/aes/lib/encrypt/te1.nix b/libs/aes/lib/encrypt/te1.nix new file mode 100644 index 0000000..64b28d1 --- /dev/null +++ b/libs/aes/lib/encrypt/te1.nix @@ -0,0 +1,34 @@ +[ + 1667483301 2088564868 2004348569 2071721613 4076011277 1802229437 1869602481 3318059348 + 808476752 16843267 1734856361 724260477 4278118169 3621238114 2880130534 1987505306 + 3402272581 2189565853 3385428288 2105408135 4210749205 1499050731 1195871945 4042324747 + 2913812972 3570709351 2728550397 2947499498 2627478463 2762232823 1920132246 3233848155 + 3082253762 4261273884 2475900334 640044138 909536346 1061125697 4160222466 3435955023 + 875849820 2779075060 3857043764 4059166984 1903288979 3638078323 825320019 353708607 + 67373068 3351745874 589514341 3284376926 404238376 2526427041 84216335 2593796021 + 117902857 303178806 2155879323 3806519101 3958099238 656887401 2998042573 1970662047 + 151589403 2206408094 741103732 437924910 454768173 1852759218 1515893998 2694863867 + 1381147894 993752653 3604395873 3014884814 690573947 3823361342 791633521 2223248279 + 1397991157 3520182632 0 3991781676 538984544 4244431647 2981198280 1532737261 + 1785386174 3419114822 3200149465 960066123 1246401758 1280088276 1482207464 3486483786 + 3503340395 4025468202 2863288293 4227591446 1128498885 1296931543 859006549 2240090516 + 1162185423 4193904912 33686534 2139094657 1347461360 1010595908 2678007226 2829601763 + 1364304627 2745392638 1077969088 2408514954 2459058093 2644320700 943222856 4126535940 + 3166462943 3065411521 3671764853 555827811 269492272 4294960410 4092853518 3537026925 + 3452797260 202119188 320022069 3974939439 1600110305 2543269282 1145342156 387395129 + 3301217111 2812761586 2122251394 1027439175 1684326572 1566423783 421081643 1936975509 + 1616953504 2172721560 1330618065 3705447295 572671078 707417214 2425371563 2290617219 + 1179028682 4008625961 3099093971 336865340 3739133817 1583267042 185275933 3688607094 + 3772832571 842163286 976909390 168432670 1229558491 101059594 606357612 1549580516 + 3267534685 3553869166 2896970735 1650640038 2442213800 2509582756 3840201527 2038035083 + 3890730290 3368586051 926379609 1835915959 2374828428 3587551588 1313774802 2846444000 + 1819072692 1448520954 4109693703 3941256997 1701169839 2054878350 2930657257 134746136 + 3132780501 2021191816 623200879 774790258 471611428 2795919345 3031724999 3334903633 + 3907570467 3722289532 1953818780 522141217 1263245021 3183305180 2341145990 2324303749 + 1886445712 1044282434 3048567236 1718013098 1212715224 50529797 4143380225 235805714 + 1633796771 892693087 1465364217 3115936208 2256934801 3250690392 488454695 2661164985 + 3789674808 4177062675 2560109491 286335539 1768542907 3654920560 2391672713 2492740519 + 2610638262 505297954 2273777042 3924412704 3469641545 1431677695 673730680 3755976058 + 2357986191 2711706104 2307459456 218962455 3216991706 3873888049 1111655622 1751699640 + 1094812355 2576951728 757946999 252648977 2964356043 1414834428 3149622742 370551866 +] diff --git a/libs/aes/lib/encrypt/te2.nix b/libs/aes/lib/encrypt/te2.nix new file mode 100644 index 0000000..fd8ca59 --- /dev/null +++ b/libs/aes/lib/encrypt/te2.nix @@ -0,0 +1,34 @@ +[ + 1673962851 2096661628 2012125559 2079755643 4076801522 1809235307 1876865391 3314635973 + 811618352 16909057 1741597031 727088427 4276558334 3618988759 2874009259 1995217526 + 3398387146 2183110018 3381215433 2113570685 4209972730 1504897881 1200539975 4042984432 + 2906778797 3568527316 2724199842 2940594863 2619588508 2756966308 1927583346 3231407040 + 3077948087 4259388669 2470293139 642542118 913070646 1065238847 4160029431 3431157708 + 879254580 2773611685 3855693029 4059629809 1910674289 3635114968 828527409 355090197 + 67636228 3348452039 591815971 3281870531 405809176 2520228246 84545285 2586817946 + 118360327 304363026 2149292928 3806281186 3956090603 659450151 2994720178 1978310517 + 152181513 2199756419 743994412 439627290 456535323 1859957358 1521806938 2690382752 + 1386542674 997608763 3602342358 3011366579 693271337 3822927587 794718511 2215876484 + 1403450707 3518589137 0 3988860141 541089824 4242743292 2977548465 1538714971 + 1792327274 3415033547 3194476990 963791673 1251270218 1285084236 1487988824 3481619151 + 3501943760 4022676207 2857362858 4226619131 1132905795 1301993293 862344499 2232521861 + 1166724933 4192801017 33818114 2147385727 1352724560 1014514748 2670049951 2823545768 + 1369633617 2740846243 1082179648 2399505039 2453646738 2636233885 946882616 4126213365 + 3160661948 3061301686 3668932058 557998881 270544912 4293204735 4093447923 3535760850 + 3447803085 202904588 321271059 3972214764 1606345055 2536874647 1149815876 388905239 + 3297990596 2807427751 2130477694 1031423805 1690872932 1572530013 422718233 1944491379 + 1623236704 2165938305 1335808335 3701702620 574907938 710180394 2419829648 2282455944 + 1183631942 4006029806 3094074296 338181140 3735517662 1589437022 185998603 3685578459 + 3772464096 845436466 980700730 169090570 1234361161 101452294 608726052 1555620956 + 3265224130 3552407251 2890133420 1657054818 2436475025 2503058581 3839047652 2045938553 + 3889509095 3364570056 929978679 1843050349 2365688973 3585172693 1318900302 2840191145 + 1826141292 1454176854 4109567988 3939444202 1707781989 2062847610 2923948462 135272456 + 3127891386 2029029496 625635109 777810478 473441308 2790781350 3027486644 3331805638 + 3905627112 3718347997 1961401460 524165407 1268178251 3177307325 2332919435 2316273034 + 1893765232 1048330814 3044132021 1724688998 1217452104 50726147 4143383030 236720654 + 1640145761 896163637 1471084887 3110719673 2249691526 3248052417 490350365 2653403550 + 3789109473 4176155640 2553000856 287453969 1775418217 3651760345 2382858638 2486413204 + 2603464347 507257374 2266337927 3922272489 3464972750 1437269845 676362280 3752164063 + 2349043596 2707028129 2299101321 219813645 3211123391 3872862694 1115997762 1758509160 + 1099088705 2569646233 760903469 253628687 2960903088 1420360788 3144537787 371997206 +] diff --git a/libs/aes/lib/encrypt/te3.nix b/libs/aes/lib/encrypt/te3.nix new file mode 100644 index 0000000..9e9e6f5 --- /dev/null +++ b/libs/aes/lib/encrypt/te3.nix @@ -0,0 +1,34 @@ +[ + 3332727651 4169432188 4003034999 4136467323 4279104242 3602738027 3736170351 2438251973 + 1615867952 33751297 3467208551 1451043627 3877240574 3043153879 1306962859 3969545846 + 2403715786 530416258 2302724553 4203183485 4011195130 3001768281 2395555655 4211863792 + 1106029997 3009926356 1610457762 1173008303 599760028 1408738468 3835064946 2606481600 + 1975695287 3776773629 1034851219 1282024998 1817851446 2118205247 4110612471 2203045068 + 1750873140 1374987685 3509904869 4178113009 3801313649 2876496088 1649619249 708777237 + 135005188 2505230279 1181033251 2640233411 807933976 933336726 168756485 800430746 + 235472647 607523346 463175808 3745374946 3441880043 1315514151 2144187058 3936318837 + 303761673 496927619 1484008492 875436570 908925723 3702681198 3035519578 1543217312 + 2767606354 1984772923 3076642518 2110698419 1383803177 3711886307 1584475951 328696964 + 2801095507 3110654417 0 3240947181 1080041504 3810524412 2043195825 3069008731 + 3569248874 2370227147 1742323390 1917532473 2497595978 2564049996 2968016984 2236272591 + 3144405200 3307925487 1340451498 3977706491 2261074755 2597801293 1716859699 294946181 + 2328839493 3910203897 67502594 4269899647 2700103760 2017737788 632987551 1273211048 + 2733855057 1576969123 2160083008 92966799 1068339858 566009245 1883781176 4043634165 + 1675607228 2009183926 2943736538 1113792801 540020752 3843751935 4245615603 3211645650 + 2169294285 403966988 641012499 3274697964 3202441055 899848087 2295088196 775493399 + 2472002756 1441965991 4236410494 2051489085 3366741092 3135724893 841685273 3868554099 + 3231735904 429425025 2664517455 2743065820 1147544098 1417554474 1001099408 193169544 + 2362066502 3341414126 1809037496 675025940 2809781982 3168951902 371002123 2910247899 + 3678134496 1683370546 1951283770 337512970 2463844681 201983494 1215046692 3101973596 + 2673722050 3178157011 1139780780 3299238498 967348625 832869781 3543655652 4069226873 + 3576883175 2336475336 1851340599 3669454189 25988493 2976175573 2631028302 1239460265 + 3635702892 2902087254 4077384948 3475368682 3400492389 4102978170 1206496942 270010376 + 1876277946 4035475576 1248797989 1550986798 941890588 1475454630 1942467764 2538718918 + 3408128232 2709315037 3902567540 1042358047 2531085131 1641856445 226921355 260409994 + 3767562352 2084716094 1908716981 3433719398 2430093384 100991747 4144101110 470945294 + 3265487201 1784624437 2935576407 1775286713 395413126 2572730817 975641885 666476190 + 3644383713 3943954680 733190296 573772049 3535497577 2842745305 126455438 866620564 + 766942107 1008868894 361924487 3374377449 2269761230 2868860245 1350051880 2776293343 + 59739276 1509466529 159418761 437718285 1708834751 3610371814 2227585602 3501746280 + 2193834305 699439513 1517759789 504434447 2076946608 2835108948 1842789307 742004246 +] diff --git a/libs/aes/lib/helpers/default.nix b/libs/aes/lib/helpers/default.nix new file mode 100644 index 0000000..09f6e7d --- /dev/null +++ b/libs/aes/lib/helpers/default.nix @@ -0,0 +1,185 @@ +{ core, serde, ... }: + let + inherit(core) integer list path string type; + inherit(serde) packDWordBuffer; + + addColumns + = { byte0, byte1, byte2, byte3, ... } @ self: + { byte0, byte1, byte2, byte3, ... }: + { + byte0 = integer.xor self.byte0 byte0; + byte1 = integer.xor self.byte1 byte1; + byte2 = integer.xor self.byte2 byte2; + byte3 = integer.xor self.byte3 byte3; + }; + + addRoundKey = list.zipWith addColumns; + + formatColumns + = list.map + ( + { byte0, byte1, byte2, byte3, ... }: + "${integer.formatHexByte byte0} ${integer.formatHexByte byte1} ${integer.formatHexByte byte2} ${integer.formatHexByte byte3}" + ); + + getRoundConstant = list.get [1 2 4 8 16 32 64 128 27 54]; + + repeat + = rounds: + initial: + convert: + list.fold + convert + initial + (list.generate (x: x) rounds); + + rotateColumn + = { byte0, byte1, byte2, byte3, ... }: + { + byte0 = byte1; + byte1 = byte2; + byte2 = byte3; + byte3 = byte0; + }; + + substituteAndShiftRows4 + = state: + let + column0 = substituteColumn (list.get state 0); + column1 = substituteColumn (list.get state 1); + column2 = substituteColumn (list.get state 2); + column3 = substituteColumn (list.get state 3); + + column0' + = { + inherit(column0) byte0; + inherit(column1) byte1; + inherit(column2) byte2; + inherit(column3) byte3; + }; + + column1' + = { + inherit(column1) byte0; + inherit(column2) byte1; + inherit(column3) byte2; + inherit(column0) byte3; + }; + + column2' + = { + inherit(column2) byte0; + inherit(column3) byte1; + inherit(column0) byte2; + inherit(column1) byte3; + }; + + column3' + = { + inherit(column3) byte0; + inherit(column0) byte1; + inherit(column1) byte2; + inherit(column2) byte3; + }; + in + [ column0' column1' column2' column3' ]; + + substituteByte = list.get (path.import ./sbox.nix); + + substituteColumn + = { byte0, byte1, byte2, byte3, ... }: + { + byte0 = substituteByte byte0; + byte1 = substituteByte byte1; + byte2 = substituteByte byte2; + byte3 = substituteByte byte3; + }; + + toBuffer + = length: + buffer: + type.matchPrimitiveOrPanic buffer + { + list + = if list.length buffer == length + then + list.map + ( + { byte0, byte1, byte2, byte3, ... }: + { inherit byte0 byte1 byte2 byte3; } + ) + buffer + else + packDWordBuffer buffer; + string + = packDWordBuffer (list.map string.getByte (string.toCharacters buffer)); + }; + + unsubstituteByte = list.get (path.import ./isbox.nix); + + unsubstituteColumn + = { byte0, byte1, byte2, byte3, ... }: + { + byte0 = unsubstituteByte byte0; + byte1 = unsubstituteByte byte1; + byte2 = unsubstituteByte byte2; + byte3 = unsubstituteByte byte3; + }; + + unshiftRows4andUnsubstitute + = state: + let + column0 = list.get state 0; + column1 = list.get state 1; + column2 = list.get state 2; + column3 = list.get state 3; + + column0' + = unsubstituteColumn + { + inherit(column0) byte0; + inherit(column3) byte1; + inherit(column2) byte2; + inherit(column1) byte3; + }; + + column1' + = unsubstituteColumn + { + inherit(column1) byte0; + inherit(column0) byte1; + inherit(column3) byte2; + inherit(column2) byte3; + }; + + column2' + = unsubstituteColumn + { + inherit(column2) byte0; + inherit(column1) byte1; + inherit(column0) byte2; + inherit(column3) byte3; + }; + + column3' + = unsubstituteColumn + { + inherit(column3) byte0; + inherit(column2) byte1; + inherit(column1) byte2; + inherit(column0) byte3; + }; + in + [ column0' column1' column2' column3' ]; + + in + { + inherit addColumns addRoundKey + formatColumns + getRoundConstant + repeat rotateColumn + substituteAndShiftRows4 substituteByte substituteColumn + toBuffer + unshiftRows4andUnsubstitute unsubstituteByte unsubstituteColumn; + + } diff --git a/libs/aes/lib/helpers/isbox.nix b/libs/aes/lib/helpers/isbox.nix new file mode 100644 index 0000000..d44bb64 --- /dev/null +++ b/libs/aes/lib/helpers/isbox.nix @@ -0,0 +1,18 @@ +[ + 82 9 106 213 48 54 165 56 191 64 163 158 129 243 215 251 + 124 227 57 130 155 47 255 135 52 142 67 68 196 222 233 203 + 84 123 148 50 166 194 35 61 238 76 149 11 66 250 195 78 + 8 46 161 102 40 217 36 178 118 91 162 73 109 139 209 37 + 114 248 246 100 134 104 152 22 212 164 92 204 93 101 182 146 + 108 112 72 80 253 237 185 218 94 21 70 87 167 141 157 132 + 144 216 171 0 140 188 211 10 247 228 88 5 184 179 69 6 + 208 44 30 143 202 63 15 2 193 175 189 3 1 19 138 107 + 58 145 17 65 79 103 220 234 151 242 207 206 240 180 230 115 + 150 172 116 34 231 173 53 133 226 249 55 232 28 117 223 110 + 71 241 26 113 29 41 197 137 111 183 98 14 170 24 190 27 + 252 86 62 75 198 210 121 32 154 219 192 254 120 205 90 244 + 31 221 168 51 136 7 199 49 177 18 16 89 39 128 236 95 + 96 81 127 169 25 181 74 13 45 229 122 159 147 201 156 239 + 160 224 59 77 174 42 245 176 200 235 187 60 131 83 153 97 + 23 43 4 126 186 119 214 38 225 105 20 99 85 33 12 125 +] \ No newline at end of file diff --git a/libs/aes/lib/helpers/sbox.nix b/libs/aes/lib/helpers/sbox.nix new file mode 100644 index 0000000..ead995b --- /dev/null +++ b/libs/aes/lib/helpers/sbox.nix @@ -0,0 +1,19 @@ +[ + #_0 _1 _2 _3 _4 _5 _6 _7 _8 _9 _a _b _c _d _e _f + 99 124 119 123 242 107 111 197 48 1 103 43 254 215 171 118 # 0_ + 202 130 201 125 250 89 71 240 173 212 162 175 156 164 114 192 # 1_ + 183 253 147 38 54 63 247 204 52 165 229 241 113 216 49 21 # 2_ + 4 199 35 195 24 150 5 154 7 18 128 226 235 39 178 117 # 3_ + 9 131 44 26 27 110 90 160 82 59 214 179 41 227 47 132 # 4_ + 83 209 0 237 32 252 177 91 106 203 190 57 74 76 88 207 # 5_ + 208 239 170 251 67 77 51 133 69 249 2 127 80 60 159 168 # 6_ + 81 163 64 143 146 157 56 245 188 182 218 33 16 255 243 210 # 7_ + 205 12 19 236 95 151 68 23 196 167 126 61 100 93 25 115 # 8_ + 96 129 79 220 34 42 144 136 70 238 184 20 222 94 11 219 # 9_ + 224 50 58 10 73 6 36 92 194 211 172 98 145 149 228 121 # a_ + 231 200 55 109 141 213 78 169 108 86 244 234 101 122 174 8 # b_ + 186 120 37 46 28 166 180 198 232 221 116 31 75 189 139 138 # c_ + 112 62 181 102 72 3 246 14 97 53 87 185 134 193 29 158 # d_ + 225 248 152 17 105 217 142 148 155 30 135 233 206 85 40 223 # e_ + 140 161 137 13 191 230 66 104 65 153 45 15 176 84 187 22 # f_ +] diff --git a/libs/aes/lib/key/default.nix b/libs/aes/lib/key/default.nix new file mode 100644 index 0000000..bf1bd50 --- /dev/null +++ b/libs/aes/lib/key/default.nix @@ -0,0 +1,159 @@ +{ core, helpers, serde, ... }: + let + inherit(core) bool debug integer list set string type; + inherit(helpers) formatColumns getRoundConstant repeat rotateColumn substituteColumn toBuffer; + inherit(serde) packDWord unpackDWord; + + expandRoundKey + = length: + key: + round: + let + prevKey = list.foot key; + finalLine + = let + afterRotWord = rotateColumn (unpackDWord prevKey.final); + afterSubWord = packDWord (substituteColumn afterRotWord); + afterXor = integer.xor roundConstant afterSubWord; + roundConstant = getRoundConstant round; + in + debug.debug "expandRoundKey" + { + text = "Final Coulumn"; + data + = { + inherit afterSubWord afterXor roundConstant; + afterRotWord = packDWord afterRotWord; + before = prevKey.final; + }; + hex = true; + } + afterXor; + + dword0 = integer.xor prevKey.dword0 finalLine; + dword1 = integer.xor prevKey.dword1 dword0; + dword2 = integer.xor prevKey.dword2 dword1; + dword3 = integer.xor prevKey.dword3 dword2; + dword3' + = bool.select (length > 6) + (packDWord (substituteColumn (unpackDWord dword3))) + dword3; + dword4 = integer.xor prevKey.dword4 dword3'; + dword5 = integer.xor prevKey.dword5 dword4; + dword6 = integer.xor prevKey.dword6 dword5; + dword7 = integer.xor prevKey.dword7 dword6; + + final + = list.get + [ dword0 dword1 dword2 dword3 dword4 dword5 dword6 dword7 ] + (length - 1); + in + key + ++ ( + debug.debug "expandRoundKey" + { + text = "Round ${string round}"; + data + = { inherit dword0 dword1 dword2 dword3 final; } + // (set.ifOrEmpty (length > 4) { inherit dword4; }) + // (set.ifOrEmpty (length > 5) { inherit dword5; }) + // (set.ifOrEmpty (length > 6) { inherit dword6; }) + // (set.ifOrEmpty (length > 7) { inherit dword7; }); + hex = true; + } + [ { inherit dword0 dword1 dword2 dword3 dword4 dword5 dword6 dword7 final; } ] + ); + + from + = { length, rounds }: + key: + let + key' = toBuffer length' key; + get = index: (list.get key' index).dword; + length' = length / 32; + roundKeys + = repeat ((rounds * 4 + length' - 1) / length' - 1) + [ + { + dword0 = get 0; + dword1 = get 1; + dword2 = get 2; + dword3 = get 3; + dword4 = get 4; + dword5 = get 5; + dword6 = get 6; + dword7 = get 7; + final = get (length' - 1); + } + ] + ( + debug.debug "expandKey" + { + text = "Key (${string length'})"; + data = list.generate get length'; + hex = true; + } + expandRoundKey length' + ); + roundKeys' + = list.concatMap + ( + { dword0, dword1, dword2, dword3, dword4, dword5, dword6, dword7, final }: + [ (unpackDWord dword0) ] + ++ (list.ifOrEmpty (length' > 1) (unpackDWord dword1)) + ++ (list.ifOrEmpty (length' > 2) (unpackDWord dword2)) + ++ (list.ifOrEmpty (length' > 3) (unpackDWord dword3)) + ++ (list.ifOrEmpty (length' > 4) (unpackDWord dword4)) + ++ (list.ifOrEmpty (length' > 5) (unpackDWord dword5)) + ++ (list.ifOrEmpty (length' > 6) (unpackDWord dword6)) + ++ (list.ifOrEmpty (length' > 7) (unpackDWord dword7)) + ) + roundKeys; + columns = list.generate (list.get roundKeys') (rounds*4); + in + AESkey.instanciate + { + inherit columns length rounds; + inherit + ( + list.fold + ( + { count, roundKeys, state }: + column: + let + state' = state ++ [ column ]; + in + if count != 0 + then + { + inherit roundKeys; + count = count - 1; + state = state'; + } + else + { + count = 3; + roundKeys = roundKeys ++ [ state' ]; + state = []; + } + ) + { + count = 3; + roundKeys = []; + state = []; + } + columns + ) + roundKeys; + }; + + AESkey + = type "AESkey" + { + inherit from; + from128bit = from { length = 128; rounds = 11; }; + from192bit = from { length = 192; rounds = 13; }; + from256bit = from { length = 256; rounds = 15; }; + }; + in + AESkey // { inherit AESkey; } diff --git a/libs/aes/lib/serde/default.nix b/libs/aes/lib/serde/default.nix new file mode 100644 index 0000000..6fba426 --- /dev/null +++ b/libs/aes/lib/serde/default.nix @@ -0,0 +1,235 @@ +{ core, ... }: + let + inherit(core) bool integer list; + + expectU8 + = value: + assert integer.isInstanceOf value + && value >= 0 + && value <= 255; + value; + + splitInteger + = value: + let + value0 = integer.abs value; + value1 = value0 / 256; + value2 = value1 / 256; + value3 = value2 / 256; + value4 = value3 / 256; + value5 = value4 / 256; + value6 = value5 / 256; + value7 = value6 / 256; + in + { + sign = value < 0; + + byte0 = integer.and value0 255; + byte1 = integer.and value1 255; + byte2 = integer.and value2 255; + byte3 = integer.and value3 255; + byte4 = integer.and value4 255; + byte5 = integer.and value5 255; + byte6 = integer.and value6 255; + byte7 = integer.and value7 255; + + word0 = integer.and value0 65535; + word1 = integer.and value2 65535; + word2 = integer.and value4 65535; + word3 = integer.and value6 65535; + + dword0 = integer.and value0 4294967295; + dword1 = integer.and value4 4294967295; + }; + + unpackWord + = word: + { + inherit word; + inherit(splitInteger word) byte0 byte1 + sign; + }; + + unpackDWord + = dword: + { + inherit dword; + inherit(splitInteger dword) byte0 byte1 byte2 byte3 + word0 word1 + sign; + }; + + unpackQWord + = qword: + { + inherit qword; + inherit(splitInteger qword) byte0 byte1 byte2 byte3 byte4 byte5 byte6 byte7 + word0 word1 word2 word3 + dword0 dword1 + sign; + }; + + foldBuffer + = { length, pack }: + let + length-1 = length - 1; + in + list.fold + ( + { buffer, byte0, byte1, byte2, byte3, byte4, byte5, byte6, byte7, count }: + value: + let + buffer' = buffer ++ [ (pack bytes) ]; + bytes + = { + byte0 = bool.select (count == 0) value' byte0; + byte1 = bool.select (count == 1) value' byte1; + byte2 = bool.select (count == 2) value' byte2; + byte3 = bool.select (count == 3) value' byte3; + byte4 = bool.select (count == 4) value' byte4; + byte5 = bool.select (count == 5) value' byte5; + byte6 = bool.select (count == 6) value' byte6; + byte7 = bool.select (count == 7) value' byte7; + }; + value' = expectU8 value; + in + bytes + // { + buffer = bool.select (count != length-1) buffer buffer'; + count = bool.select (count != length-1) (count + 1) 0; + } + ) + { + buffer = []; + byte0 = 0; + byte1 = 0; + byte2 = 0; + byte3 = 0; + byte4 = 0; + byte5 = 0; + byte6 = 0; + byte7 = 0; + count = 0; + }; + + packBuffer + = { length, pack } @ packer: + buffer: + let + state' = foldBuffer packer buffer; + in + assert state'.count == 0; + state'.buffer; + + packWord + = { + byte0 ? 0, + byte1 ? 0, + }: + (expectU8 byte0) + (expectU8 byte1) * 256; + + packWordBuffer + = packBuffer + { + length = 2; + pack + = { byte0, byte1, ... }: + { + inherit byte0 byte1; + word = packWord { inherit byte0 byte1; }; + }; + }; + + packDWord + = { + byte0 ? 0, + byte1 ? 0, + byte2 ? 0, + byte3 ? 0, + }: + list.fold + (result: byte: result * 256 + (expectU8 byte)) + (expectU8 byte3) + [ byte2 byte1 byte0 ]; + + packDWordBuffer + = packBuffer + { + length = 4; + pack + = { byte0, byte1, byte2, byte3, ... }: + { + inherit byte0 byte1 byte2 byte3; + dword = packDWord { inherit byte0 byte1 byte2 byte3; }; + word0 = packWord { inherit byte0 byte1; }; + word1 + = packWord + { + byte0 = byte2; + byte1 = byte3; + }; + }; + }; + + packQWord + = { + byte0 ? 0, + byte1 ? 0, + byte2 ? 0, + byte3 ? 0, + byte4 ? 0, + byte5 ? 0, + byte6 ? 0, + byte7 ? 0, + }: + list.fold + (result: byte: result * 256 + (expectU8 byte)) + (expectU8 byte7) + [ byte6 byte5 byte4 byte3 byte2 byte1 byte0 ]; + + packQWordBuffer + = packBuffer + { + length = 8; + pack + = { byte0, byte1, byte2, byte3, byte4, byte5, byte6, byte7, ... }: + { + inherit byte0 byte1 byte2 byte3 byte4 byte5 byte6 byte7; + dword0 = packDWord { inherit byte0 byte1 byte2 byte3; }; + dword1 + = packDWord + { + byte0 = byte4; + byte1 = byte5; + byte2 = byte6; + byte3 = byte7; + }; + word0 = packWord { inherit byte0 byte1; }; + word1 + = packWord + { + byte0 = byte2; + byte1 = byte3; + }; + word2 + = packWord + { + byte0 = byte4; + byte1 = byte5; + }; + word3 + = packWord + { + byte0 = byte6; + byte1 = byte7; + }; + }; + }; + in + { + inherit packDWord packDWordBuffer + packQWord packQWordBuffer + packWord packWordBuffer + splitInteger + unpackDWord unpackQWord unpackWord; + } diff --git a/libs/aes/nix.sh b/libs/aes/nix.sh new file mode 100755 index 0000000..a899c35 --- /dev/null +++ b/libs/aes/nix.sh @@ -0,0 +1,5 @@ +#!/usr/bin/env bash + +nix "$@" \ + --override-input libcore ../core \ + --override-input libcore/libintrinsics ../intrinsics \ No newline at end of file diff --git a/libs/aes/tests/default.nix b/libs/aes/tests/default.nix new file mode 100644 index 0000000..7ef3d79 --- /dev/null +++ b/libs/aes/tests/default.nix @@ -0,0 +1,204 @@ +{ core, ... }: +{ decrypt, encrypt, helpers, key, serde, ... }: + let + inherit(core) debug; + inherit(helpers) formatColumns; + inherit(key) AESkey; + inherit(serde) packDWordBuffer; + + key128 + = AESkey.from128bit + [ + 43 126 21 22 40 174 210 166 + 171 247 21 136 9 207 79 60 + ]; + key192 + = AESkey.from192bit + [ + 142 115 176 247 218 14 100 82 + 200 16 243 43 128 144 121 229 + 98 248 234 210 82 44 107 123 + ]; + key256 + = AESkey.from256bit + [ + 96 61 235 16 21 202 113 190 + 43 115 174 240 133 125 119 129 + 31 53 44 7 59 97 8 215 + 45 152 16 163 9 20 223 244 + ]; + + msg128 + = [ + 50 67 246 168 136 90 48 141 + 49 49 152 162 224 55 7 52 + ]; + + fastEncrypt = encrypt.fast key128 msg128; + slowEncrypt = encrypt.slow key128 msg128; + + slowDecrypt = decrypt.slow key128 slowEncrypt; + in + { + inherit key128 key192 key256; + msg128 + = debug.warn "msg128" + { + data = formatColumns (packDWordBuffer msg128); + hex = true; + nice = true; + } + msg128; + fastEncrypt + = debug.warn "fastEncrypt" + { + data = formatColumns fastEncrypt; + hex = true; + nice = true; + } + fastEncrypt; + slowEncrypt + = debug.warn "slowEncrypt" + { + data = formatColumns slowEncrypt; + hex = true; + nice = true; + } + slowEncrypt; + slowDecrypt + = debug.warn "slowDecrypt" + { + data = formatColumns slowDecrypt; + hex = true; + nice = true; + } + slowDecrypt; + /*unmixColumns + = debug.debug "unmixColumns" + { + nice = true; + data + = { + before + = formatColumns + ( + packDWordBuffer + [ + 142 77 161 188 + 1 1 1 1 + 159 220 88 157 + 213 213 215 214 + ] + ); + after + = formatColumns + ( + decrypt.unmixColumns + ( + packDWordBuffer + [ + 142 77 161 188 + 1 1 1 1 + 159 220 88 157 + 213 213 215 214 + ] + ) + ); + }; + } + null;*/ + } + + + + + /* + key + = "AES Counter Mode"; + + cipherText + = import ./. + { + inherit key; + text + = '' + Ooh ooh + + We're no strangers to love + You know the rules and so do I + A full commitment's what I'm thinking of + You wouldn't get this from any other guy + I just wanna tell you how I'm feeling + Gotta make you understand + + Never gonna give you up + Never gonna let you down + Never gonna run around and desert you + Never gonna make you cry + Never gonna say goodbye + Never gonna tell a lie and hurt you + + + We've known each other for so long + Your heart's been aching but + You're too shy to say it + Inside we both know what's been going on + We know the game and we're gonna play it + And if you ask me how I'm feeling + Don't tell me you're too blind to see + + Never gonna give you up + Never gonna let you down + Never gonna run around and desert you + Never gonna make you cry + Never gonna say goodbye + Never gonna tell a lie and hurt you + + Never gonna give you up + Never gonna let you down + Never gonna run around and desert you + Never gonna make you cry + Never gonna say goodbye + Never gonna tell a lie and hurt you + + + (Ooh, give you up) + (Ooh, give you up) + (Ooh) + Never gonna give, never gonna give + (Give you up) + (Ooh) + Never gonna give, never gonna give + (Give you up) + + We've know each other for so long + Your heart's been aching but + You're too shy to say it + Inside we both know what's been going on + We know the game and we're gonna play it + + I just wanna tell you how I'm feeling + Gotta make you understand + + Never gonna give you up + Never gonna let you down + Never gonna run around and desert you + Never gonna make you cry + Never gonna say goodbye + Never gonna tell a lie and hurt you + + Never gonna give you up + Never gonna let you down + Never gonna run around and desert you + Never gonna make you cry + Never gonna say goodbye + Never gonna tell a lie and hurt you + + Never gonna give you up + Never gonna let you down + Never gonna run around and desert you + Never gonna make you cry + Never gonna say goodbye + Never gonna tell a lie and hurt you + ''; + };*/ \ No newline at end of file diff --git a/libs/config/default.nix b/libs/config/default.nix new file mode 100644 index 0000000..412bc05 --- /dev/null +++ b/libs/config/default.nix @@ -0,0 +1,18 @@ +{ core, nixpkgs, ... } @ libs: + let + inherit(core) check library string target; + lib = library.load ./lib libs; + tests = check.load ./tests libs lib; + in + { + inherit lib tests; + + stdenv + = target.System.mapStdenv + ( + system: + nixpkgs.legacyPackages.${string system}.stdenv + ); + + checks = check tests {}; + } diff --git a/libs/config/flake.nix b/libs/config/flake.nix new file mode 100644 index 0000000..d780282 --- /dev/null +++ b/libs/config/flake.nix @@ -0,0 +1,28 @@ +{ + description = "Configure and Deploy NixOS"; + inputs + = { + libcore.url = "github:sivizius/nixfiles/development?dir=libs/core"; + libsecrets.url = "github:sivizius/nixfiles/development?dir=libs/secrets"; + libstore.url = "github:sivizius/nixfiles/development?dir=libs/store"; + libweb.url = "github:sivizius/nixfiles/development?dir=libs/web"; + nixpkgs.url = "github:sivizius/nixpkgs/master"; + }; + outputs + = { self, libcore, libsecrets, libstore, libweb, nixpkgs, ... }: + let + core = libcore.lib { inherit self; debug.logLevel = "info"; }; + in + core.path.import ./. + { + inherit core nixpkgs; + secrets = libsecrets.lib { inherit self; }; + store = libstore.lib; + inherit(libsecrets.nixosModules) vault; + web + = libweb.lib { inherit self; } + // { + module = libweb.nixosModules.default; + }; + }; +} diff --git a/libs/config/lib/about/default.nix b/libs/config/lib/about/default.nix new file mode 100644 index 0000000..7177c8c --- /dev/null +++ b/libs/config/lib/about/default.nix @@ -0,0 +1,17 @@ +{ core, ... }: + let + inherit(core) debug string; + + collect = _: []; + prepare + = environment: + host: + about: + { + about = string.expect about; + source = host.source ""; + }; + in + { + inherit collect prepare; + } diff --git a/libs/config/lib/configurations/default.nix b/libs/config/lib/configurations/default.nix new file mode 100644 index 0000000..85f3e1e --- /dev/null +++ b/libs/config/lib/configurations/default.nix @@ -0,0 +1,445 @@ +{ core, nixpkgs, secrets, vault, web, ... } @ libs: + let + inherit(core) context debug derivation lambda library list path set string type; + inherit(secrets.secret) Secret; + inherit(secrets.vault) Vault; + inherit(web.html) HTML; + + Configuration + = let + debug' = debug "Configuration"; + + defaultCall + = { environment, host, ... }: + { arguments, configuration, wrap, ... } @ this: + debug'.error "defaultCall" + { + text + = '' + ${type.format this} should not be a function, that depends on `config`. + ''; + data = this; + when = list.find "config" arguments; + } + wrap + ( + this + // { + configuration = configuration (environment // { inherit host; }); + } + ); + + defaultWrap + = { configuration, ... }: + configuration; + + toLegacy + = theVault: + let + fix + = source: + value: + let + result + = fixDictionary + source + (set.expect value); + in + debug.debug "fix" + { + text = "Config of ${context.formatRelative source}"; + data = value; + showType = false; + } + debug.debug "fix" + { + text = "Secrets of ${context.formatRelative source}"; + data = result.secrets; + nice = true; + when = result.secrets != {}; + } + result.value + // ( + set.ifOrEmpty (result.secrets != {}) + { + vault + = (result.value.vault or {}) + // { + secrets + = if result.value ? vault.secrets + then + Vault.update + result.value.vault.secrets + result.secrets + else + result.secrets; + }; + } + ); + + fixInner + = source: + value: + debug.debug "fixInner" + { + text = "Option ${context.formatRelative source}"; + data = value; + when = !set.isInstanceOf value; + } + type.matchPrimitiveOrDefault value + { + list = fixList source value; + set = fixSet source value; + } + { + secrets = {}; + inherit value; + }; + + fixList + = source: + value: + debug.debug "fixList" + { + text = "Option ${context.formatRelative source}"; + data = value; + } + list.fold + ( + { index, secrets, value }: + entry: + let + result = fixInner (source index) entry; + in + { + secrets = Vault.update secrets result.secrets; + index = index + 1; + value = value ++ [ result.value ]; + } + ) + { + secrets = {}; + index = 0; + value = []; + } + value; + + fixDictionary + = source: + value: + debug.debug "fixDictionary" + { + text = "Option ${context.formatRelative source}"; + data = value; + } + set.fold + ( + { secrets, value }: + attribute: + entry: + let + result = fixInner (source attribute) entry; + in + if debug.Debug.isInstanceOf result + then + "${result}" + else + { + secrets = Vault.update secrets result.secrets; + value = value // { ${attribute} = result.value; }; + } + ) + { + secrets = {}; + value = {}; + } + value; + + fixSet + = source: + { ... } @ value: + debug.debug "fixSet" + { + text = "Option ${context.formatRelative source}"; + data = value; + when = value._type or null == null; + } + ( + if derivation.isInstanceOf' value + || value._type or null != null + || HTML.isInstanceOf value + then + { + inherit value; + secrets = {}; + } + else if type.getType value == null + then + fixDictionary source value + else if debug.Debug.isInstanceOf value + then + abort "${value}" + else if Secret.isInstanceOf value + then + theVault source value + else + debug'.panic [ "toLegacy" "fixSet" ] + { + text = "Got Object in ${context.formatRelative source}:"; + data = value; + } + null + ); + in + args: + { call, configuration, source, wrap, ... } @ this: + let + this' + = this + // { + arguments = set.names (lambda.arguments configuration); + wrap = wrap'; + }; + wrap' = x: fix source (wrap x); + imports + = type.matchPrimitiveOrPanic configuration + { + lambda = [ (call args this') ]; + set = [ (wrap' this') ]; + }; + in + { + #inherit source; + _file = context.formatFileName source; + imports = imports; + }; + in + type "Configuration" + { + from + = variant: + { + call ? defaultCall, + wrap ? defaultWrap, + }: + { configuration, source, ... } @ config: + Configuration.instanciateAs variant + ( + config + // { + inherit call toLegacy wrap; + } + ); + }; + + Configuration' = variant: Configuration variant {}; + + LegacyConfiguration + = Configuration "Legacy" + { + call + = { ... }: + { configuration, ... }: + configuration; + }; + + collect + = let + collectPath + = { source, ... } @ this: + fileName: + collect + ( + this + // { + configuration = path.import fileName; + source = source { inherit fileName; }; + } + ); + in + { configuration, ... } @ this: + type.matchPrimitiveOrPanic configuration + { + lambda = [ this ]; + list + = list.concatMap + (configuration: collect (this // { inherit configuration; }) ) + configuration; + null = []; # Just Ignore + path = collectPath this configuration; + set = [ this ]; + string = collectPath this configuration; + }; + + load = library.import ./load.nix libs; + + mapToArguments + = list.map + ( + config: + let + config' = Configuration.expect config; + arguments = set.names (lambda.arguments config'.configuration); + in + debug.warn "mapToArguments" + { + text = "Unknown Source"; + data = config'; + when = config'.source == null; + } + type.matchPrimitiveOrPanic config'.configuration + { + lambda = "${type.getVariant config'}: { ${string.concatWith ", " arguments} } from ${context.formatRelative config'.source}"; + set = "${type.getVariant config'}: – from ${context.formatRelative config'.source}"; + } + ); + + mapToLegacy + = { configurations, environment, host, modules, ... }: + let + theVault = Vault {}; + + configurations' + = list.map + ( + { toLegacy, ... } @ cfg: + toLegacy theVault + { + inherit host modules; + environment + = environment + // { + inherit(host) users; + inherit(config) config; + inherit(config.config) websites; + }; + } + cfg + ) + configurations; + + modules' + = (set.values modules) + ++ [ web.module vault ] + ++ configurations'; + + config + = debug.info "mapToLegacy" + { + text = "modules'"; + data = modules'; + nice = true; + } + debug.debug "mapToLegacy" + { + text = "environment"; + data = set.names environment; + nice = true; + when = false; + } + debug.debug "mapToLegacy" + { + text = "nixosSystem"; + show = true; + nice = true; + when = false; + } + ( + nixpkgs.lib.nixosSystem + { + baseModules = []; + extraModules = []; + inherit(nixpkgs) lib; + modules = modules'; + modulesLocation = null; + pkgs = null; + prefix = []; + specialArgs = {}; + system = null; + } + ); + in + config; + + sortUniqueChecked + = configurations: + let + configurations' + = list.fold + ( + result: + config: + let + config' = Configuration.expect config; + result' = insert result config'; + in + debug.panic "sortUniqueChecked" + { + text = "Configuration expected"; + data = config; + when = !(Configuration.isInstanceOf config); + } + debug.panic "sortUniqueChecked" + { + text = "Could not insert"; + show = true; + when = debug.Debug.isInstanceOf result'; + } + result' + ) + {} + configurations; + + insert + = { ... } @ result: + { configuration, source, ... } @ config: + let + stringContext = string.getContext key; + key = "${context.formatRelative source}"; + # Should be safe, as long the keys of resulting attribute set are discarded? + key' = "${type.getVariant config} ${string.discardContext key}"; + value = result.${key'} or null; + in + debug.debug "sortUniqueChecked" + { + text = "Remove String-Context of ${key}"; + data = stringContext; + when = stringContext != {}; + } + ( + if configuration == {} + || configuration == null + then + result + else if value == null + then + result + // { + ${key'} = config; + } + else + # Brackets are necessary to compare functions. + # See: https://cs.tvl.fyi/depot/-/blob/tvix/docs/value-pointer-equality.md + if [ value ] == [ config ] + then + result + else + debug.panic "sortUniqueChecked" + { + text = "Confliciting configurations from the same source ${key'} o.O"; + data + = { + prev = value; + next = config; + }; + nice = true; + } + result + ); + in + set.values configurations'; + in + { + inherit Configuration Configuration' LegacyConfiguration; + inherit collect load mapToArguments mapToLegacy sortUniqueChecked; + } diff --git a/libs/config/lib/configurations/load.nix b/libs/config/lib/configurations/load.nix new file mode 100644 index 0000000..96c4e22 --- /dev/null +++ b/libs/config/lib/configurations/load.nix @@ -0,0 +1,86 @@ +{ core, ... }: + let + inherit(core) context debug path set string type; + + loadSet + = config: + environment: + scope: + let + config' + = type.matchPrimitiveOrPanic config + { + lambda = config; + path = importScoped config; + set = config; + string = importScoped config; + }; + importScoped = path.importScoped scope; + in + type.matchPrimitiveOrPanic config' + { + lambda = config' environment; + set = config'; + }; + + loadWithSource + = config: + { ... } @ environment: + { ... } @ scope: + objectType: + let + loadSet' + = config: + loadSet + config + environment + scope; + loadWithSource' + = source: + name: + config: + let + config' = loadSet' config; + fileName + = type.matchPrimitiveOrPanic config + { + lambda = null; + path = config; + set = null; + string = config; + }; + source' + = source + { + attribute = name; + inherit fileName; + }; + in + if type.getType config' != null + then + { source = source'; } + // (objectType.expect config') + // { inherit name; } + else + debug.debug "loadWithSource'" + { + text = name; + data = set.names config'; + } + set.map + (loadWithSource' source') + config'; + in + debug.debug "loadWithSource" + { + text = "Called with:"; + data = { inherit config environment scope; }; + nice = true; + when = false; + } + loadWithSource' + ( context "Peers" ) + null + config; + in + loadWithSource diff --git a/libs/config/lib/default.nix b/libs/config/lib/default.nix new file mode 100644 index 0000000..2800441 --- /dev/null +++ b/libs/config/lib/default.nix @@ -0,0 +1,19 @@ +{ core, nixpkgs, secrets, store, vault, web, ... }: + Library "libconfig" + { inherit core nixpkgs secrets store vault web; } + { + about = ./about; + configurations = ./configurations; + devices = ./devices; + hosts = ./hosts; + #maintainers = ./maintainers; + #modules = ./modules; + networks = ./networks; + packages = ./packages; + peers = ./peers; + profiles = ./profiles; + services = ./services; + systems = ./systems; + users = ./users; + versions = ./versions; + } diff --git a/libs/config/lib/devices/default.nix b/libs/config/lib/devices/default.nix new file mode 100644 index 0000000..a593b0e --- /dev/null +++ b/libs/config/lib/devices/default.nix @@ -0,0 +1,129 @@ +{ configurations, core, ... }: + let + inherit(configurations) Configuration'; + inherit(core) debug list set string type; + + __functor + = self: + extraConfig: + self // extraConfig; + + Device + = type.enum "Device" + { + Disk + = fsType: + label: + device: + { + inherit __functor device fsType label; + configure + = index: + { device, fsType, label, name, source, ... }: + DeviceConfiguration + { + configuration.fileSystems.${name} + = { + inherit fsType label; + device = toDevice device; + }; + inherit source; + }; + }; + + Swap + = device: + { + inherit __functor device; + configure + = index: + { device, name, source, ... }: + DeviceConfiguration + { + configuration.swapDevices + = [ + { + device = toDevice device; + } + ]; + inherit source; + }; + }; + }; + + DeviceConfiguration = Configuration' "Device"; + + collect = list.imap configure; + + configure + = index: + { configure ? null, ... } @ device: + configure index device; + + constructors + = { + inherit Device; + inherit(Device) Disk Swap; + VFAT = Device.Disk "vfat"; + XFS = Device.Disk "xfs"; + }; + + prepare + = environment: + host: + devices: + if set.isInstanceOf devices + then + set.mapToList + ( + name: + device: + { + source = host.source "devices" name; + } + // (Device.expect device) + // { inherit name; } + ) + devices + else if list.isInstanceOf devices + then + list.imap + ( + index: + device: + let + name = "#${string index}"; + in + { + source = host.source "devices" index; + } + // (Device.expect device) + // { inherit name; } + ) + devices + else + debug.panic "prepare" "The option `devices` must be a set or a list."; + + toDevice + = let + toDevice + = { uuid ? null, ... }: + if uuid != null + then + "/dev/disk/by-uuid/${uuid}" + else + debug.panic + "toDevice" + "Need either uuid, … or …."; + in + device: + type.matchPrimitiveOrPanic device + { + string = device; + set = toDevice device; + }; + in + constructors + // { + inherit collect constructors prepare toDevice; + } diff --git a/libs/config/lib/hosts/configure.nix b/libs/config/lib/hosts/configure.nix new file mode 100644 index 0000000..eae9575 --- /dev/null +++ b/libs/config/lib/hosts/configure.nix @@ -0,0 +1,178 @@ +{ about, configurations, core, devices, hosts, networks, profiles, secrets, systems, users, versions, ... }: + let + inherit(configurations) mapToArguments mapToLegacy sortUniqueChecked; + inherit(core) context debug library list set string target; + inherit(hosts) PrepareArgument; + inherit(secrets) secret; + inherit(systems) SystemConfiguration; + + collectAbout = about.collect; + collectConfig = x: x; + collectDevices = devices.collect; + collectNetwork = networks.collect; + collectProfile = profiles.collect; + collectSystem = systems.collect; + collectUsers = users.collect; + collectVersion = versions.collect; + + prepareEnvironment + = { ... } @ arguments: + { ... } @ environment: + debug.debug "prepareEnvironment" + { + text = "(environment // arguments)"; + data = set.names (environment // arguments); + } + set.map + ( + name: + value: + debug.debug "prepareEnvironment" + { + text = name; + data = value; + } + ( + if PrepareArgument.isInstanceOf value + || ( + library.isInstanceOf value + && !value.isInitialised + ) + then + let + value' = value (environment // arguments); + in + debug.debug "prepareEnvironment" + { + text = "value'"; + show = true; + showType = false; + } + value' + else + value + ) + ) + environment; + #inherit(deploy) toNixOSconfiguration; + in + { modules, ... }: + { ... } @ environment: + { about, config ? [], devices, name, network, profile, source, system, users, version, ... } @ host: + let + arguments + = debug.debug "arguments" + { + nice = true; + show = true; + } + (mapToArguments configurations); + + configurations + = debug.debug "configurations" + { + show = true; + nice = true; + } + ( + sortUniqueChecked + ( + [] + ++ ( collectAbout about ) + ++ ( collectConfig config ) + ++ ( collectDevices devices ) + ++ ( collectConfig config ) + ++ ( collectNetwork network ) + ++ ( collectProfile profile ) + ++ ( collectSystem system ) + ++ ( collectUsers users ) + ++ ( collectVersion version ) + ) + ); + + nixosConfiguration + = debug.debug "nixosConfiguration" + { + show = true; + nice = true; + when = false; + } + ( + target.System.mapStdenv + ( + buildSystem: + let + buildPlatform = string buildSystem; + systemConfig + = SystemConfiguration + { + configuration.nixpkgs + = { + inherit buildPlatform; + }; + source = source "buildSystem"; + }; + in + mapToLegacy + { + inherit host modules; + configurations = configurations ++ [ systemConfig ]; + environment + = prepareEnvironment + { + inherit buildSystem secret; + targetSystem + = system; + } + environment; + } + ) + ); + + /* + buildScript + = store.write.shellScript + { + name = "deploy-${name}"; + inherit system; + } + '' + ${scriptHeader} + # Build ${name} + ''; + + builder + = store.write.shellScript + { + inherit name system; + } + '' + source $stdenv/setup + mkdir -p $out + ln -s ${buildScript} $out/build.sh + ln -s ${deployScript} $out/deploy.sh + ''; + + + deployScript + = store.write.shellScript + { + name = "deploy-${name}"; + inherit system; + } + '' + ${scriptHeader} + # Deploy ${name} via ${deployment.method} + #nix copy --to ${deployment.address} ??? + ''; + + scriptHeader + = '' + # Name: ${name} + # Description: ${string.replace [ "\n" ] [ "\n# " ]; about} + '';*/ + in + host + // { + inherit arguments configurations nixosConfiguration; + } diff --git a/libs/config/lib/hosts/default.nix b/libs/config/lib/hosts/default.nix new file mode 100644 index 0000000..9c8f7de --- /dev/null +++ b/libs/config/lib/hosts/default.nix @@ -0,0 +1,104 @@ +{ configurations, core, devices, hosts, networks, peers, services, users, ... } @ libs: + let + inherit(core) debug library set string target type; + + Host + = type "Host" + { + from + = about: + configuration: + debug.debug "Host" + { + data = configuration; + nice = true; + } + Host.instanciate + { + inherit about configuration; + }; + }; + + PrepareArgument + = type "PrepareArgument" + { + __public__ = []; + from + = inner: + PrepareArgument.instanciate + { + inherit inner; + __functor = { inner, ... }: inner; + }; + }; + + configure = library.import ./configure.nix libs; + + constructors + = { + inherit Host PrepareArgument; + }; + + load + = source: + arguments: + environment: + let + config + = configurations.load + source + environment + constructors' + Host; + + configure' + = networkName: + set.map + ( + hostName: + { + about ? null, + configuration ? null, + source ? null, + ... + } @ node: + let + name + = networks.extendName + networkName + hostName; + in + if Host.isInstanceOf node + then + configure + arguments + environment + ( + Host.instanciate + ( + prepare + environment + ( configuration // { inherit about name source; } ) + ) + ) + else + configure' name node + ); + + constructors' + = constructors + // devices.constructors + // peers.constructors + // services.constructors + // users.constructors; + in + configure' + null + config; + + prepare = library.import ./prepare.nix libs; + in + constructors + // { + inherit constructors load; + } diff --git a/libs/config/lib/hosts/prepare.nix b/libs/config/lib/hosts/prepare.nix new file mode 100644 index 0000000..472c934 --- /dev/null +++ b/libs/config/lib/hosts/prepare.nix @@ -0,0 +1,62 @@ +{ about, configurations, core, devices, networks, profiles, systems, users, versions, ... }: +{ ... } @ environment: + let + inherit(configurations) Configuration'; + inherit(core) debug list path type; + + ConfigConfiguration = Configuration' "Config"; + + fail + = hostName: + fieldName: + debug.panic "prepareHost" "Field `${fieldName}` of host `${hostName}` missing!"; + + prepareAbout = about.prepare environment; + prepareConfig + = { source, ... }: + list.map + ( + fileName: + ConfigConfiguration + { + configuration = path.import fileName; + source = source fileName; + } + ); + prepareDevices = devices.prepare environment; + prepareNetwork = networks.prepare environment; + prepareProfile = profiles.prepare environment; + prepareSystem = systems.prepare environment; + prepareUsers = users.prepare environment; + prepareVersion = versions.prepare environment; + in + { + about, + config ? [], + devices ? fail host.name "devices", + name, + network ? fail host.name "network", + profile ? fail host.name "profile", + source, + system ? fail host.name "system", + users ? fail host.name "users", + version ? fail host.name "version", + ... + } @ host: + let + env + = { + inherit name source; + }; + in + { + inherit name source; + about = prepareAbout env about; + config = prepareConfig env config; + devices = prepareDevices env devices; + network = prepareNetwork env network; + profile = prepareProfile env profile; + system = prepareSystem env system; + users = prepareUsers env users; + version = prepareVersion env version; + } \ No newline at end of file diff --git a/libs/config/lib/maintainers/default.nix b/libs/config/lib/maintainers/default.nix new file mode 100644 index 0000000..e816a53 --- /dev/null +++ b/libs/config/lib/maintainers/default.nix @@ -0,0 +1,9 @@ +{ core, ... }: +{ + GitHub = core.debug.unimplemented "…"; + Fingerprint = core.debug.unimplemented "…"; + Maintainer = core.debug.unimplemented "…"; + Team = core.debug.unimplemented "…"; + checkPeople = core.debug.unimplemented "…"; + checkTeams = core.debug.unimplemented "…"; +} diff --git a/libs/config/lib/modules/collect/configurations.nix b/libs/config/lib/modules/collect/configurations.nix new file mode 100644 index 0000000..8a3b740 --- /dev/null +++ b/libs/config/lib/modules/collect/configurations.nix @@ -0,0 +1,309 @@ +{ core, context, extendPath, ... }: +{ ... } @ env: +{ configuration, options, source } @ self: + let + inherit(core) debug list set string type; + + collect + = { ... } @ state: + { configuration, source }: + debug.info "collect" + { + text = "from ${toString source}"; + data = configuration; + } + ( + let + cfg = import configuration; + src = configuration; + fail + = typeName: + debug.panic + "collect" + "Got ${typeName} ${string configuration}, what should I do with it?"; + in + type.matchPrimitive configuration + { + bool = fail "boolean"; + float = fail "float"; + int = fail "integer"; + lambda = collectRegular state { inherit configuration source; }; + list = collectList state { inherit configuration source; }; + null = state; # Just Ignore + path = collect state { configuration = cfg; source = src; }; + set = collectSet state configuration; + string = collect state { configuration = cfg; source = src; }; + } + ); + + collectImports + = { ... } @ state: + { configuration, source }: + debug.info "collectImports" + { + text = "from ${toString source}"; + data = configuration; + } + ( + let + cfg = import configuration; + src = configuration; + in + type.matchPrimitiveOrPanic configuration + { + lambda = collectLegacy state { inherit configuration source; }; + path = collectImports state { configuration = cfg; source = src; }; + string = collectImports state { configuration = cfg; source = src; }; + } + ); + + collectLegacy + = { ... } @ state: + { configuration, source }: + let + legacyConfig + = configuration + { + inherit(finalState) config; + inherit(env.nixpkgs) lib; + pkgs = env.registries.nix.packages; + }; + state' + = list.fold + (collectImports source) + state + (legacyConfig.imports or []); + in + combine + state' + { + configuration = set.remove legacyConfig [ "imports" ]; + inherit source; + }; + + collectList + = { ... } @ state: + { configuration, source }: + debug.info "collectList" + { + text = "from ${toString source}"; + data = configuration; + ; + } + ( + list.fold + ( + state: + configuration: + collect state { inherit configuration source; } + ) + state + configuration + ); + + collectRegular + = { ... } @ state: + { configuration, source }: + let + regularConfig + = configuration + { + inherit(env) core dateTime host registries; + config + = debug.warn + "collectRegular" + "Use of `config` is deprecated!" + finalState.config; + }; + in + debug.info "collectRegular" + { + text = "from ${toString source}"; + data = configuration; + } + ( + combine + state + { + configuration = regularConfig; + inherit source; + } + ); + + collectService + = { ... } @ state: + { configuration, source }: + let + serviceConfig + = configuration + { + inherit(env) core dateTime host registries; + inherit(finalState.config) services; + }; + in + debug.info "collectService" + { + text = "from ${toString source}"; + data = configuration; + } + ( + type.matchPrimitiveOrPanic configuration + { + lambda = combine state { configuration = serviceConfig; inherit source; }; + set = combine state { inherit configuration source; }; + } + ); + + collectSet + = { ... } @ state: + { __type__ ? null, ... } @ self: + let + source = set.getSource self; + in + if __type__ == "Configuration" then collectSpecial state self + else if __type__ == null then combine state { configuration = self; inherit source; } + else + debug.panic + "collectSet" + "Unexpected Object of type ${__type__}. `Configuration` was expected"; + + collectSpecial + = { ... } @ state: + { + __variant__ ? + ( + debug.panic + "collectSpecial" + "Missing `__variant__`, type `Configuration` is an enum-type!" + ), + source ? null, + ... + } @ self: + debug.info "collectSpecial" + { + text = "from ${toString source}"; + data = __variant__; + } + ( + { + Legacy = collectLegacy state self; + Service = collectService state self; + User = collectUser state self; + }.${__variant__} + ); + + collectUser + = { ... } @ state: + { configuration, source, user }: + let + userConfig + = configuration + { + inherit(env) core dateTime home-manager profile registries; + config = userConfig; + user = user // { config = userConfig; }; + }; + in + debug.info "collectUser" + { + text = "from ${toString source} (${user.name})"; + data = configuration; + } + ( + type.matchPrimitiveOrPanic configuration + { + lambda = combine state { configuration = userConfig; inherit source; }; + set = combine state { inherit configuration source; }; + } + ); + + combine + = { options, path, ... } @ state: + { configuration, source }: + let + combine = set.fold merge; + merge + = { config, options, path, ... } @ state: + name: + value: + let + path' = extendPath path name; + in + debug.info [ "combine" "merge" ] + { + text = path'; + data = value; + } + ( + if set.hasAttribute name options + then + let + configuration = value; + file = source; + option = options.${name}; + values = config.${name} or []; + in + ( + if option.__type__ or null == "Option" + then + config + // { + ${name} + = values + ++ [ { inherit file value; } ]; + } + else + if type.isSet value + then + combine + { + config = config.${name}; + options = option; + path = path'; + } + { inherit configuration source; } + else + debug.panic + [ "combine" "merge" ] + { + text + = '' + Option `${path'}` is an attribute set. + It cannot be combined with a `${type.getPrimitive value}` + ''; + data = option; + } + ) + else + debug.panic + [ "combine" "merge" ] + "Unknown option `${path'}` in ${source}" + ); + in + debug.info "combine" + { + text = "${toString source}"; + data = configuration; + } + ( + state + // { + config = combine state configuration; + } + ); + + finalState + = collect + { + inherit options; + config = {}; + path = null; + } + self; + in + debug.info [] + { + text = "options"; + data = set.names options; + } + finalState diff --git a/libs/config/lib/modules/collect/default.nix b/libs/config/lib/modules/collect/default.nix new file mode 100644 index 0000000..1ad654c --- /dev/null +++ b/libs/config/lib/modules/collect/default.nix @@ -0,0 +1,39 @@ +{ context, core, ... }: + let + inherit(core) list set string type; + debug = core.debug (context ++ [ "collect" ]); + + extendPath + = path: + name: + let + path' + = if path != null + then + "${path}." + else + ""; + this + = string.match + "[A-Za-z_][0-9A-Za-z_'-]*" + name; + name' + = string.replace' + { + "\"" = ''\"''; + "\n" = ''\n''; + "\r" = ''\r''; + "\t" = ''\t''; + } + name; + in + if this == [] then "${path'}${name}" + else "${path'}\"${name'}\""; + + + in + { + __functor = self: collect; + configurations = import ./configurations.nix { inherit core extendPath; context = context ++ [ "collect" "configurations" ]; }; + options = import ./options.nix { inherit core extendPath; context = context ++ [ "collect" "options" ]; }; + } \ No newline at end of file diff --git a/libs/config/lib/modules/collect/options.nix b/libs/config/lib/modules/collect/options.nix new file mode 100644 index 0000000..16f7c5c --- /dev/null +++ b/libs/config/lib/modules/collect/options.nix @@ -0,0 +1,306 @@ +{ core, context, extendPath, ... }: +options: + let + inherit(core) debug list set string type; + + addOption + = { options, ... } @ state: + name: + option: + state + // { + options + = options + // { + ${name} = option; + }; + }; + + collect + = { + __type__, + apply, + default, + documentation, + internal, + optionType, + path, + readOnly, + }: + definitions: + if type.isList definitions + then + let + value + = if definitions == [] + then + if optionType.check default + then + default + else + debug.panic + "collect" + "The default value of `${path}` does not match its type `${optionType.name}`!" + else if list.length definitions == 1 + then + let + first = (list.head definitions).value; + in + if optionType.check first + then + first + else + debug.panic + "collect" + "The value of `${path}` does not match its type `${optionType.name}`!" + else if readOnly + then + debug.panic + "collect" + "The option `${path}` is read-only, but was set multiple times!" + else if list.any ({ value, ... }: optionType.check value) definitions + then + optionType.merge [ path ] definitions + else + debug.panic + "collect" + "A value of `${path}` does not match its type `${optionType.name}`!"; + in + debug.warn + "collect" + { + when = optionType.deprecationMessage != null; + text + = '' + The type `${optionType.name}' of option `${path}' defined is deprecated. + ${optionType.deprecationMessage} + ''; + } + value + else + debug.panic + "collect" + "A list of definitions expected, got ${type.getPrimitive definitions}"; + + collects + = { config, options, ... }: + if type.isSet config + then + set.map + ( + name: + { + __type__ ? null, + ... + } @ option: + if __type__ == "Option" + then + collect + option + (config.${name} or []) + else + collects + { + config = config.${name} or {}; + options = option; + } + ) + options + else + debug.panic + "collects" + "An attribute set of options expected, got ${type.getPrimitive config}"; + + combineLegacy + = { ... } @ state: + options: + debug.info "combineLegacy" + { + text = "mew"; + data = options; + } + ( + set.fold + ( + { options, path, ... } @ state: + name: + option: + let + addOption' = addOption state name; + path' = extendPath path name; + in + debug.debug "combineLegacy" + { + text = "${path'}"; + data = (set.names option); + } + ( + if set.hasAttribute name options + then + if options.${name} ? __type__ + then + debug.panic + "combineLegacy" + "Option `${path'}` already defined" + else if option.__type__ or null == null + then + addOption' + ( + combineLegacy + { + options = options.${name}; + path = path'; + } + option + ).options + else + debug.panic + "combineLegacy" + "Option `${path'}` is already defined as an attribute set, so only attribute sets of options can be added" + else if option._type or null == "option" + then + addOption' (convertLegacy path' option) + else + addOption' + ( + combineLegacy + { + options = {}; + path = path'; + } + option + ).options + ) + ) + state + options + ); + + combineModules + = state: + { + config ? null, + evaluate ? null, + imports ? [], + legacy, + options, + ... + }: + if legacy + then + combineLegacy state options + else + combine state options; + + combine + = state: + options: + set.fold + ( + { options, path, ... } @ state: + name: + option: + let + addOption' = addOption state name; + path' = extendPath path name; + in + if set.hasAttribute name options + then + if options.${name} ? __type__ + then + debug.panic + "combine" + "Option `${path'}` already defined" + else if option.__type__ or null == null + then + addOption' + ( + combine + { + options = options.${name}; + path = path'; + } + option + ).options + else + debug.panic + "combine" + "Option `${path'}` is already defined as an attribute set, so only attribute sets of options can be added" + else + addOption' option + ) + state + options; + + convertLegacy + = path: + { + default ? null, + defaultText ? null, + example ? null, + description ? null, + relatedPackages ? null, + type ? null, + apply ? (x: x), + internal ? false, + value ? null, + visible ? true, + readOnly ? false, + ... + }: + debug.info "convertLegacy" + { + text = "value?"; + when = value != null; + data = value; + } + { + __type__ = "Option"; + documentation + = if visible + then + { + default + = if defaultText != null + then + defaultText + else + string default; + inherit description example relatedPackages; + type = { inherit(type) description descriptionClass name; }; + } + else + null; + inherit apply default internal path readOnly; + optionType = convertLegacyType type; + }; + + convertLegacyType + = { + check, # T -> bool + deprecationMessage, # string? + description, # string + descriptionClass, # irrelevant? + emptyValue, # {} | { value: T; } + functor, # string -> type -> wrapped -> payload: P -> (binop: P -> P -> P) -> + getSubOptions, # T -> { string -> U } + getSubModules, # [ LegacyModule ]? + merge, # [ string ] -> [ { file: path; value: T; } ] -> { string -> T } + name, # string + nestedTypes, # irrelevant? + substSubModules, # T -> U + typeMerge, # T -> T -> T + ... + }: + { + inherit check deprecationMessage merge name; + }; + + options' + = combineLegacy + { + options = {}; + path = null; + } + (set.remove options [ "_module" ]); + in diff --git a/libs/config/lib/modules/default.nix b/libs/config/lib/modules/default.nix new file mode 100644 index 0000000..741e111 --- /dev/null +++ b/libs/config/lib/modules/default.nix @@ -0,0 +1,216 @@ +{ configurations, core, ... } @ libs: + let + inherit(core) debug library list set string type; + + Module#: [ Module ] -> { string -> Option } -> ({ ... } -> { string -> T }) -> Module + = { + __type__ = "Type"; + __variant__ = "Module"; + isInstanceOf = configurations.check Module.__variant__; + __functor + = { __variant__, ... }: + { ... } @ options: + evaluate: + { + __type__ = __variant__; + inherit evaluate options; + extraConfig = {}; + + __functor + = { config, ... } @ self: + { ... } @ extraConfig: + self + // { + config = config // extraConfig; + }; + }; + }; + + Option + = { + __type__ = "Type"; + __variant__ = "Option"; + isInstanceOf = configurations.check Option.__variant__; + + __functor + = { __variant__, ... }: + let + __type__ = __variant__; + in + type: + { default ? null }: + meta: + { + inherit __type__ default type; + meta = toMeta meta; + }; + + ifEnabled + = { enable, ... }: + { ... } @ value: + if enable + then + value + else + {}; + } + // (library.import ./options.nix libs); + + configureModules + = modulePath: + environment: + set.map + ( + moduleName: + { + __type__ ? null, + dependencies ? null, + evaluate ? null, + options ? null, + source ? null, + ... + } @ module: + let + name + = if modulePath != null + then + "${modulePath}.${string.escapeKey moduleName}" + else + string.escapeKey moduleName; + in + if __type__ != null + then + { + inherit __type__ name source; + dependencies + = debug.panic + "configureModules" + { + text = "The dependencies of module ${name} are not of type `[ Module ]`"; + data = dependencies; + nice = true; + when = !(type.isList dependencies); + } + list.map + ( + source: + load source environment + ) + dependencies; + evaluate + = debug.panic + "configureModules" + { + text = "The evaluator of module ${name} ist not of type `T -> U`"; + data = evaluate; + nice = true; + when = !(type.isFunction evaluate); + } + evaluate; + options + = configureOptions + name + environment + ( + loadOptions + options + environment + ); + } + else + configureModules name environment module + ); + + configureOptions + = optionPath: + environment: + set.map + ( + optionName: + { + __type__ ? null, + ... + } @ option: + let + name = "${optionPath}.${string.escapeKey optionName}"; + in + if __type__ != null + then + option // { inherit name; } + else + configureOptions name environment option + ); + + constructors + = { + inherit Module Option; + }; + + expandName + = optionPath: + optionName: + if optionPath != null + then + "${optionPath}.${optionName}" + else + optionName; + + load + = source: + environment: + let + config = loadModules source environment; + config' = configureModules config environment; + in + config'; + + loadModules + = source: + environment: + configurations.load + source + environment + constructors + Module.isInstanceOf; + + loadOptions + = source: + environment: + configurations.load + source + environment + constructors + Option.isInstanceOf; + + toMeta + = let + setToMeta + = { + example ? null, + description ? null, + }: + { + inherit example description; + }; + in + meta: + type.matchPrimitiveOrPanicOrFail meta + { + null + = { + description = null; + example = null; + }; + set = setToMeta meta; + string + = { + description = meta; + example = null; + }; + + }; + in + constructors + // { + inherit load; + } diff --git a/libs/config/lib/modules/doc/common.css b/libs/config/lib/modules/doc/common.css new file mode 100644 index 0000000..e69de29 diff --git a/libs/config/lib/modules/doc/default.nix b/libs/config/lib/modules/doc/default.nix new file mode 100644 index 0000000..e69de29 diff --git a/libs/config/lib/modules/doc/doc.nix b/libs/config/lib/modules/doc/doc.nix new file mode 100644 index 0000000..474ff7e --- /dev/null +++ b/libs/config/lib/modules/doc/doc.nix @@ -0,0 +1,639 @@ +let + # Should be extern + # { + inherit (builtins) + any attrNames concatMap concatStringsSep deepSeq elemAt foldl' genList getFlake head isAttrs + isList isString length map match removeAttrs replaceStrings split stringLength substring + trace toString typeOf; + + foot = list: elemAt list (length list - 1); + + apply + = transformations: + value: + foldl' + ( + value: + transformation: + transformation value + ) + value + transformations; + + ltrim + = list: + if head list == "" + && length list >= 2 + then + genList (x: elemAt list ( x + 2 )) ( length list - 2 ) + else + list; + + rtrim + = list: + if foot list == "" + && length list >= 2 + then + genList (x: elemAt list x) ( length list - 2 ) + else + list; + + splitSpaces = split "([[:space:]]+)"; + + trim = apply [ splitSpaces ltrim rtrim ]; + + collectLines + = apply + [ + ( + foldl' + ( + { line, lines }: + token: + if token != null + then + { + line = line ++ [ token ]; + inherit lines; + } + else + { + line = [ ]; + lines + = lines + ++ ( + if line != [] + then + [ (concatStringsSep "" line) ] + else + [ ] + ); + } + ) + { + line = [ ]; + lines = [ ]; + } + ) + ( + { line, lines }: + if line != [] + then + lines ++ [ (concatStringsSep "" line) ] + else + lines + ) + ]; + + traceDeep = x: y: trace (deepSeq x x) y; + # } + + getOptions + = branch: + modules: + removeAttrs + ( + (getFlake "github:sivizius/nixpkgs/${branch}").lib.nixosSystem { inherit modules; } + ).options + [ "_module" ]; + + getMeta + = value: + let + internal = value.internal or false; + in + { + declarations = value.declarations or null; + default + = if value ? __toString && toString value == "virtualisation.cri-o.package" + then + null + else + value.defaultText or value.default or null; + description = value.description or null; + example = value.example or null; + hasDefault = value ? defaultText || value ? default; + hasExample = value ? example; + type = value.type.description; + visible = value.visible or (!internal); + }; + + parseTree + = root: + options: + foldl' + ( + result: + optionName: + let + name = if root != null then "${root}.${optionName}" else optionName; + value = options.${optionName}; + getOptions + = foldl' + ( + options: + submodules: + if isAttrs submodules + then + let + imports = getOptions (submodules.imports or [ ] ); + in + options // (submodules.options or { } ) // imports + else + options + ) + { }; + + submodules = getOptions value.type.getSubModules or []; + in + if isAttrs value + then + if value ? _type + then + result + // { + ${optionName} + = let + meta = getMeta value; + in + { + tree + = if meta.type == "submodule" + then + parseTree name submodules + else + null; + inherit name meta value; + }; + } + else + result + // { + ${optionName} + = { + inherit name; + meta = null; + tree = parseTree name value; + }; + } + else + result + ) + {} + ( attrNames options ); + + getDocumentation + = branches: + modules: + foldl' + ( + result: + branch: + result + // { + ${branch} = parseTree null (getOptions branch modules); + } + ) + {} + branches; + + renderDescription + = branch: + description: + let + description' + = if isString description + then + renderDocBook branch description + else if isAttrs description + && description ? _type + && description ? text + then + { + "mdDoc" = [ (renderMarkDown description.text) ]; + }.${description._type} or (throw "Unknown type ${description._type}") + else + [ "—" ]; + length' = length description'; + in + if length' == 0 + then + [ "
" ] + else if length' == 1 + then + [ "
${head description'}
" ] + else + [ + "
" + description' + "
" + ]; + + renderDefault = renderExample; + + renderCode = code: "
${code}
"; + + escapeHTML = replaceStrings [ "<" ">" "&" "\"" "'" ] [ "<" ">" "&" """ "'" ]; + + renderDocBook + = branch: + apply + [ + #(text: traceDeep { _ = "DocBook"; inherit text; } text) + trim + ( + text: + concatStringsSep "" + ( + map + ( + token: + if isList token + then + let + token' = head token; + matchBreak = match ".*\n.*\n.*" token'; + in + if matchBreak != null + then + "\n" + else + " " + else + token) + text + ) + ) + (split "<(/?[A-Za-z]+)( [^>]+)?/?>") + ( + concatMap + ( + token: + if isList token + then + let + token' = elemAt token 0; + arguments = elemAt token 1; + in + { + "citerefentry" = [ "" ]; + "code" = [ "" ]; + "/code" = [ "" ]; + "command" = [ "" ]; + "/command" = [ "" ]; + "emphasis" = [ "" ]; + "/emphasis" = [ "" ]; + "envar" = [ "$" ]; + "/envar" = [ "" ]; + "filename" = [ "" ]; + "/filename" = [ "" ]; + "function" = [ "" ]; + "/function" = [ "" ]; + "important" = [ "" ]; + "/important" = [ "" ]; + "link" = [ "
" ]; + "/link" = [ "" ]; + "itemizedlist" = [ "
    " null ]; + "/itemizedlist" = [ "
" ]; + "listitem" = [ "
  • " ]; + "/listitem" = [ "
  • " null ]; + "literal" = [ "" ]; + "/literal" = [ "" ]; + "literallayout" = [ "" ]; + "/literallayout" = [ "" ]; + "manvolnum" = [ "(" ]; + "/manvolnum" = [ ")" ]; + "member" = [ "
  • " ]; + "/member" = [ "
  • " null ]; + "note" = [ "" ]; + "/note" = [ "" ]; + "option" = [ "" ]; + "/option" = [ "" ]; + "package" = [ "" ]; + "/package" = [ "" ]; + "para" = [ "

    " ]; + "/para" = [ "

    " ]; + "productname" = [ "" ]; + "/productname" = [ "™" ]; + "programlisting" = [ null "
    " ];
    +                    "/programlisting"   =   [ "
    " null ]; + "prompt" = [ null ]; + "/prompt" = [ ]; + "quote" = [ "" ]; + "/quote" = [ "" ]; + "refentrytitle" = [ " class=\"manpage\">" ]; + "/refentrytitle" = [ ]; + "replaceable" = [ ]; + "/replaceable" = [ ]; + "screen" = [ null "
    " ];
    +                    "/screen"           =   [ "
    " null ]; + "simplelist" = [ "
      " null ]; + "/simplelist" = [ "
    " ]; + "term" = [ "
    " ]; + "/term" = [ "
    " null ]; + "title" = [ "" ]; + "/title" = [ "" ]; + "variablelist" = [ "
    " null ]; + "/variablelist" = [ "
    " ]; + "varlistentry" = [ "
    "]; + "/varlistentry" = [ "
    " null ]; + "varname" = [ "" ]; + "/varname" = [ "" ]; + "warning" = [ "" ]; + "/warning" = [ "" ]; + "xref" = [ "${arguments}" ]; + "/xref" = [ "
    " ]; + }.${token'} or ( throw { inherit token' arguments; } ) + else + [ (escapeHTML token) ] + ) + ) + collectLines + ]; + + renderMarkDown + = text: + #traceDeep { _ = "MarkDown"; inherit text; } + text; + + renderExpression + = branch: + optionName: + expression: + if isAttrs expression + && expression ? _type + && expression ? text + then + let + splitLines + = apply + [ + (split "(\n)") + ltrim + rtrim + (foldl' (result: token: if isList token then result else result ++ [token]) []) + ]; + lines = splitLines expression.text; + expression' + = if length lines == 1 + then + head lines + else + concatStringsSep "\n" lines; + in + { + "literalDocBook" = concatStringsSep "\n" (renderDocBook branch expression'); + "literalExpression" = renderCode expression'; + "literalMD" = renderMarkDown expression'; + }.${expression._type} or (throw "Unknown type ${expression._type}") + else + renderCode (renderExpression' "" optionName expression); + + renderExpression' + = indentation: + optionName: + expression: + { + "bool" = if expression then "true" else "false"; + "float" = toString expression; + "int" = toString expression; + "lambda" = "_: …"; + "list" + = let + indentation' = "${indentation} "; + content = map (renderExpression' indentation' optionName) expression; + content' = concatStringsSep " " content; + isLarge = ( length content > 16 ) || any (item: isAttrs item && item != {}) expression; + in + if expression == [] + then + "[]" + else if isLarge + then + "[\n${indentation'}${concatStringsSep "\n${indentation'}" content}\n${indentation}]" + else + "[ ${concatStringsSep " " content} ]"; + "null" = "null"; + "path" = toString expression; + "set" + = let + indentation' = "${indentation} "; + escapeName + = name: + let + validMatch = match "[0-9A-Za-z'_-]+" name; + in + if validMatch != null + then + name + else + "\"${replaceStrings [ "\n" "\r" "\t" "\\" "\"" "\${" ] [ "\\n" "\\r" "\\t" "\\\\" "\\\"" "\\\${" ] name}\""; + content + = map + ( + name: + let + value = renderExpression' indentation' optionName expression.${name}; + in + "${escapeName name} = ${value};" + ) + ( attrNames expression ); + content' = concatStringsSep "\n${indentation'}" content; + in + if expression == {} + then + "{}" + else if expression.type or null == "derivation" + && expression ? name + then + "«derivation ${expression.name}»" + else + "{\n${indentation'}${content'}\n${indentation}}"; + "string" + = let + indentation' = "${indentation} "; + splitLines + = apply + [ + (split "(\n)") + ltrim + rtrim + (foldl' (result: token: if isList token then result else result ++ [token]) []) + ]; + lines = splitLines expression; + in + if length lines == 1 + then + "\"${head lines}\"" + else + "''\n${indentation'}${concatStringsSep "\n${indentation'}" lines}\n${indentation}''"; + }.${typeOf expression}; + + renderExample + = branch: + hasExample: + optionName: + example: + if hasExample + then + renderExpression branch optionName example + else + null; + + renderMeta + = branch: + value: + if value.meta != null + then + [ + "
    " + ( + [ + "
    Name
    " + "
    ${value.name}
    " + ] + ++ ( + if value.meta.description != null + then + [ + "
    Description
    " + ] + ++ (renderDescription branch value.meta.description) + else + [] + ) + ++ [ + "
    Type
    " + "
    ${value.meta.type}
    " + ] + ++ ( + let + default = renderDefault branch value.meta.hasDefault value.name value.meta.default; + in + if default != null + then + [ + "
    Default
    " + "
    ${default}
    " + ] + else + [] + ) + ++ ( + let + example = renderExample branch value.meta.hasExample value.name value.meta.example; + in + if example != null + then + [ + "
    Example
    " + "
    ${example}
    " + ] + else + [] + ) + ) + "
    " + ] + else + []; + + renderDocumentation' + = branch: + documentation: + map + ( + option: + let + value = documentation.${option}; + in + [ + "
    " + ( + [ + "${option}" + (renderMeta branch value) + ] + ++ ( + if value.tree != null + then + [ (renderDocumentation' branch value.tree) ] + else + [] + ) + ) + "
    " + ] + ) + ( attrNames documentation ); + + indent + = indentation: + lines: + concatMap + ( + line: + if isList line + then + indent "${indentation} " line + else + [ "${indentation}${line}" ] + ) + lines; + + renderDocumentation + = documentation: + let + lines + = foldl' + ( + result: + branch: + result + ++ [ + "
    " + [ + "${branch}" + (renderDocumentation' branch documentation.${branch}) + ] + "
    " + ] + ) + [] + ( attrNames documentation ); + in + concatStringsSep "\n" + ( + [ + "" + "" + "" + " " + " Options of NixOS-Modules" + " " + " " + " " + ] + ++ ( indent " " lines ) + ++ [ + " " + "" + ] + ); + + documentation + = getDocumentation + [ + "master" + "nixpkgs-unstable" + "nixos-22.05" + ] []; +in + renderDocumentation + documentation diff --git a/libs/config/lib/modules/foobar/checks.nix b/libs/config/lib/modules/foobar/checks.nix new file mode 100644 index 0000000..808ae1b --- /dev/null +++ b/libs/config/lib/modules/foobar/checks.nix @@ -0,0 +1,84 @@ +{ extendPath, ... }: +let + inherit(builtins) all attrValues dirOf elem false storeDir substring true throw typeOf; + + maxI8 = maxU8 / 2; + maxI16 = maxU16 / 2; + maxI32 = maxU32 / 2; + + maxU8 = 255; + maxU16 = 65535; + maxU32 = 4294967295; + + minI8 = 0 - maxI8 - 1; + minI16 = 0 - maxI16 - 1; + minI32 = 0 - maxI32 - 1; + + #isCoercibleToPath = x: isCoercibleToString x && isAbsolutePath x; + #isSetCoercibleToString = x: x ? outPath || x ? __toString; + #isSetOf = { elemType, ... }: x: isSet x && all elemType.check (attrValues x); + + implementsToString = { __toString ? null, ... }: __toString != null; + + isAbsolutePath = x: isInstanceOf [ "String" "Path" ] x && (substring 0 1 x.value) == "/"; + isAny = _: true; + isBool = isInstanceOf "Bool"; + isDictionary = isInstanceOf "Dictionary"; + isDictionaryOf = { elemType, ... }: x: isDictionary x && all elemType.check (attrValues x.value); + isDerivation = isInstanceOf "Derivation"; + isFloat = isInstanceOf "Float"; + isFloatBetween = { from, till }: x: isFloat x && x.value >= from && x.value <= till; + isFunction = isInstanceOf "Function"; + isInList = list: x: elem x list; + isInstanceOf + = type: + { __type__, ... }: + { + list = elem __type__ type; + string = __type__ == type; + }.${typeOf type} or (throw "isInstanceOf expects list of strings or a string"); + isInteger = isInstanceOf "Integer"; + isIntegerBetween = { from, till }: x: isInteger x && x.value >= from && x.value <= till; + isList = isInstanceOf "List"; + isListOf = mightBeEmpty: { elemType, ... }: x: isList x && (x.value != [] || mightBeEmpty) && all elemType.check x.value; + isNever = _: false; + isNonEmptyString = x: isString x && match "[ \t\n]*" x.value == null; + isNonNegativeNumber = x: isNumber x && x.value >= 0; + isNull = isInstanceOf "Null"; + isNumber = isInstanceOf [ "Float" "Integer" ]; + isNumberBetween = { from, till }: x: isNumber x && x.value >= from && x.value <= till; + isOptionType = isInstanceOf "OptionType"; + isPackage = x: isDerivation x || isStorePath x; + isPath = isInstanceOf "Path"; + isPositiveInteger = x: isInteger x && x.value > 0; + isPositiveNumber = x: isNumber x && x.value > 0; + isSignedByte = x: isInteger x && x.value >= minI8 && x.value <= maxI8; + isSignedLong = x: isInteger x && x.value >= minI32 && x.value <= maxI32; + isSignedWord = x: isInteger x && x.value >= minI16 && x.value <= maxI16; + isStorePath + = x: + if !(isList x) + && implementsToString x + then + let + x' = toString x; + in + isAbsolutePath x' && dirOf x' == storeDir + else + false; + isString = isInstanceOf "String"; + isStringMatching = regex: x: isString x && (match regex x.value) != null; + isUnsignedInteger = x: isInteger x && x.value >= 0; + isUnsignedByte = x: isUnsignedInteger x && x.value <= maxU8; + isUnsignedLong = x: isUnsignedInteger x && x.value <= maxU32; + isUnsignedWord = x: isUnsignedInteger x && x.value <= maxU16; +in +{ + inherit implementsToString; + inherit isAbsolutePath isAny isBool isDictionary isDictionaryOf isDerivation isFloat + isFloatBetween isFunction isInList isInstanceOf isInteger isIntegerBetween isList + isListOf isNever isNonEmptyString isNonNegativeNumber isNull isNumber isNumberBetween + isOptionType isPackage isPath isPositiveInteger isPositiveNumber isSignedByte + isSignedLong isSignedWord isStorePath isString isStringMatching isUnsignedInteger + isUnsignedByte isUnsignedLong isUnsignedWord; +}; diff --git a/libs/config/lib/modules/foobar/default.nix b/libs/config/lib/modules/foobar/default.nix new file mode 100644 index 0000000..a4595a6 --- /dev/null +++ b/libs/config/lib/modules/foobar/default.nix @@ -0,0 +1,57 @@ +let + # Methods + inherit(builtins) attrNames foldl' getFlake import match removeAttrs replaceStrings trace; + + lib + = { + extendPath + = path: + name: + let + path' + = if path != null + then + "${path}." + else + ""; + this + = match + "[A-Za-z_][0-9A-Za-z_'-]*" + name; + name' + = replaceStrings + [ "\"" "\n" "\r" "\t" ] + [ "\\\"" "\\n" "\\r" "\\t" ] + name; + in + if this == [] then "${path'}${name}" + else "${path'}\"${name'}\""; + }; + + format = import ./format.nix lib; + toObject = import ./toObjext.nix lib; + + modules + = nixpkgs.lib.evalModules + { + modules + = (import "${nixpkgs}/nixos/modules/module-list.nix") + ++ [ + { + nixpkgs.hostPlatform = "x86_64-linux"; + } + ]; + }; + nixpkgs = getFlake "github:sivizius/nixpkgs/master"; + + options + = toObject null + ( + removeAttrs + (modules.options) + [ "_module" "assertions" "warnings" + ); + + output = format options; +in + options diff --git a/libs/config/lib/modules/foobar/format.nix b/libs/config/lib/modules/foobar/format.nix new file mode 100644 index 0000000..9306e58 --- /dev/null +++ b/libs/config/lib/modules/foobar/format.nix @@ -0,0 +1,93 @@ +{ extendPath, ... }: +let + inherit(builtins) all attrNames attrValues concatMap concatStringsSep dirOf elem elemAt filter foldl' + fromJSON functionArgs genList getFlake head listToAttrs isAttrs isBool isFloat + isFunction isInt isList isPath isString map match removeAttrs replaceStrings + split storeDir stringLength substring toString tryEval trace typeOf + unsafeGetAttrPos; + + format + = path: + tab: + options: + #trace path + concatMap + ( + name: + let + path' = extendPath path name; + option = tryEval options.${name}; + option' = option.value; + source = unsafeGetAttrPos name options; + in + if option.success + then + if option'.__type__ or null == "Option" + then + [ "${tab}${name}" ] + ++ (formatOption tab option') + else + [ + "${tab}${name}" + "${tab}= {" + ] + ++ (format path' "${tab} " option') + ++ [ "${tab} };" ] + else + [ + "${tab}# ${toString source.file}:${toString source.line}:${toString source.column}" + "${tab}${name} = ;" + ] + ) + (attrNames options); + + format' + = options: + concatStringsSep "\n" + ( + [ + "{" + " options" + " = {" + ] + ++ (format null " " options) + ++ [ + " };" + "}" + ] + ); + + formatOption + = tab: + { + source, + ... + }: + let + tab' = "${tab} "; + source' + = if source != null + then + [ + "${tab'}source = \"${toString source.file}:${toString source.line}:${toString source.column}\";" + ] + else + []; + in + [ + "${tab}= Option" + "${tab} {" + ] + ++ [] + ++ [ + "${tab'}description" + "${tab'}= ''" + "${tab'} " + "${tab'} '';" + ] + ++ source' + ++ [ + "${tab} };" + ]; +in + format' diff --git a/libs/config/lib/modules/foobar/merge.nix b/libs/config/lib/modules/foobar/merge.nix new file mode 100644 index 0000000..8d982e0 --- /dev/null +++ b/libs/config/lib/modules/foobar/merge.nix @@ -0,0 +1,118 @@ +{ extendPath, ... }: +let + inherit(builtins) all attrNames attrValues concatMap concatStringsSep dirOf elem elemAt filter foldl' + fromJSON functionArgs genList getFlake head listToAttrs isAttrs isBool isFloat + isFunction isInt isList isPath isString map match removeAttrs replaceStrings + split storeDir stringLength substring toString tryEval trace typeOf + unsafeGetAttrPos; + + anything + = { path, previous, value, ... } @ args: + let + type = typeOf previous + in + if previous == null + then + value + else if value == null + then + previous + else if type == typeOf value + then + { + lambda = throw "Cannot merge functions yet."; + list = previous ++ value; + set + }.${type} or (equal args) + else + throw "The option `${path}' has conflicting types of definition values."; + default + = { path, previous, value, ... }: + throw "Not implemented yet!"; + + equal + = { path, previous, value, ... }: + if previous == value + then + value + else + throw "The option `${path}' has conflicting definition values."; + + functions + = { merge, ... }: + { path, previous, value, ... }: + args: merge (previous args) (value args); + + line + = { previous, value, ... }: + let + previous' = head (split "\n" previous); + in + "${previous}${value}"; + + lists + = { path, previous, value, ... }: + previous ++ value; + + never + = { path, previous, value, ... }: + throw "The option `${path}' is defined multiple times."; + + nullOr + = { merge, ... }: + { path, previous, value, ... } @ self: + if previous == null + then + value + else if value != null + then + merge self + else + throw "The option `${path}` is defined both null and not null"; + + sets + = { path, previous, value, ... }: + let + values = value; + in + foldl' + ( + { ... } @ result: + name: + let + value = value.${name}; + mergedSet + = attrs + { + path = extendPath path name; + previous = previous.${name}; + inherit value; + }; + value' + = if hasAttribute name previous + then + if isSet previous.${name} + && isSet value + then + mergedSet + else + throw "Cannot merge values of `${path}`, because of conflicting definition values of field `${name}`." + else + value; + in + result + // { + ${name} = value'; + }; + ) + previous + (attrNames value); + + stringsWith + = seperator: + { previous, value, ... }: + "${previous}${seperator}${value}"; +in +{ + inherit anything default equal functions line lists never nullOr sets stringsWith; +} diff --git a/libs/config/lib/modules/foobar/toObject.nix b/libs/config/lib/modules/foobar/toObject.nix new file mode 100644 index 0000000..b8610f5 --- /dev/null +++ b/libs/config/lib/modules/foobar/toObject.nix @@ -0,0 +1,506 @@ +{ extendPath, ... } @ lib: +let + inherit(builtins) all attrNames attrValues concatMap concatStringsSep dirOf elem elemAt filter foldl' + fromJSON functionArgs genList getFlake head listToAttrs isAttrs isBool isFloat + isFunction isInt isList isPath isString map match removeAttrs replaceStrings + split storeDir stringLength substring toString tryEval trace typeOf + unsafeGetAttrPos; + + checks = import ./checks.nix lib; + merge = import ./merge.nix lib; + + coerceToString + = { + bool + = { value, ... }: + if value + then + "true" + else + "false"; + default + = { value, ... }: + toString value; + dictionary + = { value, ... }: + let + keyValuePairs + = attrValues + ( + mapAttrs + ( + name: + value: + "${extendPath null name} = ${toObject value};" + ) + value + ); + in + "{ ${concatStringsSep " " keyValuePairs} }"; + string + = { value, ... }: + "\"${value}\""; + }; + + convertLegacy + = { + "abi" + = context: + { ... } @ value: + { + __type__ = "ApplicationBinaryInterface"; + abi = value.abi or null; + assertions = value.assertions or []; + family = value.family; + float = value.float or null; + name = value.name; + }; + "cpuType" + = context: + { ... } @ value: + { + __type__ = "CPUType"; + arch = value.arch or null; + bits = value.bits; + endianess = toObject (extendPath context "significantByte") value.significantByte; + name = value.name; + version = value.version or null; + }; + "exec-format" + = context: + { ... } @ value: + { + __type__ = "ExecutableFormat"; + __toString = { name, ... }: name; + name = value.name; + }; + "if" + = context: + { ... } @ value: + { + __type__ = "ConfigureIf"; + condition = value.condition; + content = value.content; + }; + "kernel" + = context: + { ... } @ value: + { + __type__ = "Kernel"; + executables = toObject (extendPath context "execFormat") value.execFormat; + families + = let + context' = extendPath context "families"; + in + mapAttr + (name: toObject (extendPath context' name)) + value.families; + name = value.name; + version = value.version or null; + }; + "literalDocBook" + = context: + { ... } @ value: + { + __type__ = "LiteralDocBook"; + __toString = { text, ... }: text; + text = value.text; + }; + "literalExpression" + = context: + { ... } @ value: + { + __type__ = "LiteralExpression"; + __toString = { text, ... }: text; + text = value.text; + }; + "literalMD" + = context: + { ... } @ value: + { + __type__ = "LiteralMarkdown"; + __toString = { text, ... }: text; + text = value.text; + }; + "mdDoc" + = context: + { ... } @ value: + { + __type__ = "Markdown"; + __toString = { text, ... }: text; + text = value.text; + }; + "merge" + = context: + { ... } @ value: + { + __type__ = "MergeConfigurations"; + contents = values.contents; + }; + "option" + = context: + { + default ? null, + defaultText ? null, + example ? null, + description ? null, + relatedPackages ? null, + type ? null, + apply ? (x: x), + internal ? false, + value ? null, + visible ? true, + readOnly ? false, + ... + } @ option: + { + __type__ = "Option"; + documentation + = if visible + then + { + default + = if defaultText != null + then + defaultText + else + toString default; + inherit description example relatedPackages; + type = { inherit(type) description descriptionClass name; }; + } + else + null; + inherit apply default internal readOnly; + path = context; + optionType = toObject context type; + source + = if option ? description + then + unsafeGetAttrPos "description" option + else if option ? example + then + unsafeGetAttrPos "example" option + else + unsafeGetAttrPos (head (attrNames option)) option; + }; + "option-type" + = path: + { + check, # T -> bool + deprecationMessage, # string? + description, # string + descriptionClass, # string? + emptyValue, # {} | { value: T; } + functor, # { name: string, type: OptionType?, wrappend: any, payload: any, binOp: T -> T -> T }, + # getSubOptions, # T -> { string -> U } + # getSubModules, # [ LegacyModule ]? + # merge, # [ string ] -> [ { file: path; value: T; } ] -> { string -> T } + name, # string + nestedTypes, # { elemType: OptionType } | { freeformType: OptionType } | { left: OptionType, right: OptionType } | { coercedType: OptionType, finalType: OptionType } + # substSubModules, # T -> U + # typeMerge, # T -> T -> T + ... + }: + let + inherit(functor) payload; + + applyFn + = { check, name, ... }: + self: + ( + args: + let + result = self args; + in + if check result + then + result + else + throw "Function application did not result in return-value of type `${name}`." + ); + + documentation + = { + inherit name description descriptionClass; + }; + + empty = emptyValue != {}; + + inner + = mapAttrs + (name: toObject (extendPath path name)) + nestedTypes; + + name' + = let + variant = match "([^ ]*) (.*)" name; + in + if variant != null + then + { + name = elemAt 0 variant; + variant = elemAt 1 variant; + } + else + { + inherit name variant; + }; + + new + = { + check, + documentation ? documentation, + merge, + ... + }: + { + inherit check documentation; + }; + + pattern + = let + len = stringLength description - 28; + in + substring 28 len description; + + range + = let + parts = split "(.+between | and | [(].+)" description; + from = elemAt parts 2; + till = elemAt parts 4; + in + { + from = fromJSON from; + till = fromJSON till; + }; + + variants + = { + anything = new { check = checks.isAny; merge = merge.anything; }; + attrs = new { check = checks.isSet; merge = merge.sets; }; + attrsOf = new { check = checks.isSetOf inner; merge = merge.sets; }; + bool = new { check = checks.isBool; merge = merge.equal; }; + deferredModule = new { check = checks.isNever; merge = merge.never; }; + either = new { check = checks.isEitherOr either; merge = merge.eitherOr inner; }; + enum = new { check = checks.isInList payload; merge = merge.equal; }; + float = new { check = checks.isFloat; merge = merge.equal; }; + functionTo = new { apply = applyFn inner; check = checks.isFunction; merge = merge.functions inner; }; + int = new { check = checks.isInteger; merge = merge.equal; }; + intBetween = new { check = checks.isIntegerBetween range; inherit(variants.int) merge; }; + lazyAttrsOf = new { check = checks.isSetOf inner; merge = merge.sets; }; + listOf = new { check = checks.isListOf empty inner; merge = merge.lists; }; + nonEmptyStr = new { check = checks.isNonEmptyString; inherit(variants.str) merge; }; + nullOr = new { check = checks.isNullOr inner; merge = merge.nullOr inner; }; + numberBetween = new { check = checks.isNumberBetween range; merge = merge.equal; }; + numberNonnegative = new { check = checks.isNonNegativeNumber; merge = merge.equal; }; + numberPositive = new { check = checks.isPositiveNumber; merge = merge.equal; }; + optionType = new { check = checks.isOptionType; merge = merge.null; }; + package = new { check = checks.isPackage; merge = merge.never; }; + passwdEntry = new { inherit check; merge = merge.never; }; + path = new { check = checks.isPath; merge = merge.equal; }; + positiveInt = new { check = checks.isPositiveInteger; inherit(variants.int) merge; }; + raw = new { check = checks.isAny; merge = merge.never; }; + separatedString = new { check = checks.isString; merge = merge.stringsWith payload; }; + signedInt8 = new { check = checks.isSignedByte; inherit(variants.int) merge; }; + signedInt16 = new { check = checks.isSignedWord; inherit(variants.int) merge; }; + signedInt32 = new { check = checks.isSignedLong; inherit(variants.int) merge; }; + singleLineStr = new { check = checks.isStringMatching "[^\n\r]*\n?"; merge = merge.line; }; + str = new { check = checks.isString; merge = merge.equal; }; + string = new { check = checks.isString; merge = merge.stringsWith ""; }; + strMatching = new { check = checks.isStringMatching pattern; inherit(variants.str) merge; }; + submodule = new { check = checks.isNever; merge = merge.never; }; + uniq = new { inherit(inner) check; merge = merge.never; }; + unique = new { inherit(inner) check; merge = merge.never; }; + unsignedInt = new { check = checks.isUnsignedInteger; inherit(variants.int) merge; }; + unsignedInt8 = new { check = checks.isSignedByte; inherit(variants.int) merge; }; + unsignedInt16 = new { check = checks.isSignedWord; inherit(variants.int) merge; }; + unsignedInt32 = new { check = checks.isSignedLong; inherit(variants.int) merge; }; + unspecified = new { check = checks.isAny; merge = merge.default; }; + }; + in + { + __type__ = "OptionType"; + } + // ( + variants.${name'.name} + or ( + throw + "Type-Conversion of legacy option-type `${name}` not implemented yet!." + ); + ); + "order" + = context: + { ... } @ value: + { + __type__ = "ConfigurationOrder"; + content = value.content; + priority = value.priority; + }; + "override" + = context: + { ... } @ value: + { + __type__ = "ConfigurationOverride"; + content = value.content; + priority = value.priority; + }; + "param" + = context: + { ... } @ value: + { + __type__ = "ConfigurationParameter"; + option = toObject (extendPath context "option") values.option; + render = value.render; + }; + "significant-byte" + = context: + { ... } @ value: + { + __type__ = "Endianess"; + __toString = { name, ... }: name; + name = value.name; + }; + "system" + = context: + { ... } @ value: + { + __type__ = "System"; + abi = toObject (extendPath context "abi") values.abi; + cpu = toObject (extendPath context "cpu") values.cpu; + kernel = toObject (extendPath context "kernel") values.kernel; + vendor = toObject (extendPath context "vendor") values.vendor; + }; + "vendor" + = context: + { ... } @ value: + { + __type__ = "Vendor"; + __toString = { name, ... }: name; + name = value.name; + }; + }; + + functionToObject + = context: + value: + { + __type__ = "Function"; + __functor + = { value, ... }: + argument: + toObject context (value argument); + inherit value; + }; + + listToObject + = context: + value: + { + __type__ = "List"; + __functor + = { value, ... }: + index: + let + type = typeOf index; + max = length value; + in + if type == "int" + then + if index >= 0 && index < max + then + elemAt index value + else + throw "Index ${toString index} out of bounds (0–${toString max})!" + else + throw "Integer as index expected, got `${type}`!"; + __toString + = { value, ... }: + let + value' + = map + ( + { __type__, ... } @ value: + if value ? __toString + then + "${value}" + else + throw "Cannot coerce object of type `${__type__}` to string!" + ) + value; + in + "[ ${concatStringsSep ", " value'} ]"; + value + = genList + ( + index: + toObject + "${context}[${toString index}]" + (elemAt index value) + ) + (length value); + }; + + setToObject + = context: + { + __type__ ? null, + _type ? null, + type ? null, + ... + } @ value: + if __type__ + then + value + else if _type != null + then + let + convert + = convertLegacy.${_type} + or (throw "No wrapper for type `${type}` implemented."); + in + convert context value + else if type == "derivation" + then + value + // { + __type__ = "Derivation"; + __toString = { outPath, ... }: ""; + } + else + { + __type__ = "Dictionary"; + __functor + = { value, ... }: + name: + let + name' = toObject null name; + key = "${name'}"; + in + if name' ? __toString + then + value.${key} or (throw "Missing field `${key}` in dictionary.") + else + throw "Cannot coerce key to string."; + __toString = dictionaryToString; + value + = mapAttrs + (name: toObject "${context}[\"${name}\"]") + value; + }; + + toObject + = context: + value: + { + bool = { __type__ = "Bool"; inherit value; __toString = coerceToString.bool; }; + float = { __type__ = "Float"; inherit value; __toString = coerceToString.default; }; + int = { __type__ = "Integer"; inherit value; __toString = coerceToString.default; }; + lambda = functionToObject context value; + list = listToObject context value; + null = { __type__ = "Null"; __toString = _: "null"; }; + path = { __type__ = "Path"; inherit value; __toString = coerceToString.default; }; + set = setToObject context value; + string = { __type__ = "String"; inherit value; __toString = coerceToString.string; }; + }.${typeOf value}; +in + toObject diff --git a/libs/config/lib/modules/foobar/types.nix b/libs/config/lib/modules/foobar/types.nix new file mode 100644 index 0000000..7daa1c1 --- /dev/null +++ b/libs/config/lib/modules/foobar/types.nix @@ -0,0 +1,114 @@ +{ lib, ... }: + let + inherit(lib) types; + in + { + addCheck + = foo: + bar: + (types.addCheck foo bar) + // { + }; + attrs + = types.attrs + // { + }; + attrsOf + = legacy: + (types.attrsOf legacy) + // { + }; + bool + = types.bool + // { + }; + coercedTo + = foo: + bar: + baz: + (types.coercedTo foo bar baz) + // { + }; + either + = foo: + bar: + (types.either foo bar) + // { + }; + enum + = legacy: + (types.enum legacy) + // { + }; + int + = types.int + // { + }; + lines + = types.lines + // { + }; + listOf + = legacy: + (types.listOf legacy) + // { + }; + nonEmptyListOf + = legacy: + (types.nonEmptyListOf legacy) + // { + }; + nullOr + = legacy: + (types.nullOr legacy) + // { + }; + oneOf + = legacy: + (types.oneOf legacy) + // { + }; + path + = types.path + // { + }; + package + = types.package + // { + }; + port + = types.port + // { + }; + raw + = types.raw + // { + }; + singleLineStr + = types.singleLineStr + // { + }; + str + = types.str + // { + }; + strMatching + = legacy: + (types.strMatching legacy) + // { + }; + submodule + = legacy: + (types.submodule legacy) + // { + }; + submoduleWith + = legacy: + (types.submoduleWith legacy) + // { + }; + unspecified + = types.unspecified + // { + }; + } diff --git a/libs/config/lib/modules/options.nix b/libs/config/lib/modules/options.nix new file mode 100644 index 0000000..4883b47 --- /dev/null +++ b/libs/config/lib/modules/options.nix @@ -0,0 +1,82 @@ +{ toMeta, types, ... }: + let + # Primitive Types + Bool = Option types.bool {}; + Float = Option types.float {}; + Integer = Option types.integer {}; + Lines = Option types.lines {}; + List = Option types.list {}; + Null = Option types.null {}; + Number = Option types.number {}; + Path = Option types.path {}; + PositiveInteger = Option types.positiveInteger {}; + PositiveNumber = Option types.positiveNumber {}; + String = Option types.string {}; + UnsignedInteger = Option types.unsignedInteger {}; + + # Composed Types + Either = this: that: Option (types.either this that) {}; + Enum = variants: Option (types.enum variants) {}; + ListOf = subtype: Option (types.listOf subtype) {}; + NullOr = subtype: Option (types.nullOr subtype) {}; + SetOf = subtype: Option (types.setOf subtype) {}; + in + { + inherit Bool Float Integer Lines List Null Number Path PositiveInteger PositiveNumber String UnsignedInteger; + inherit Either Enum ListOf NullOr SetOf; + + # Primitive Types + Bool' + = default: + meta: + let + this = Bool meta; + in + this + // { + inherit default; + meta + = this.meta + // { + example = !default; + }; + }; + + Disable + = meta: + Option types.bool { default = true; } + ( + (toMeta meta) + // { + example = false; + } + ); + + Enable + = meta: + Option types.bool { default = false; } + ( + (toMeta meta) + // { + example = true; + } + ); + + Float' = default: meta: (Float meta) // { inherit default; }; + Integer' = default: meta: (Integer meta) // { inherit default; }; + Lines' = default: meta: (Lines meta) // { inherit default; }; + List' = default: meta: (List meta) // { inherit default; }; + Null' = default: meta: (Null meta) // { inherit default; }; + Number' = default: meta: (Number meta) // { inherit default; }; + Path' = default: meta: (Path meta) // { inherit default; }; + PositiveInteger' = default: meta: (PositiveInteger meta) // { inherit default; }; + PositiveNumber' = default: meta: (PositiveNumber meta) // { inherit default; }; + String' = default: meta: (String meta) // { inherit default; }; + UnsignedInteger' = default: meta: (UnsignedInteger meta) // { inherit default; }; + + # Composed Types + Enum' = variants: default: meta: (Enum variants meta) // { inherit default; }; + ListOf' = subtype: default: meta: (ListOf subtype meta) // { inherit default; }; + NullOr' = subtype: default: meta: (NullOr subtype meta) // { inherit default; }; + SetOf' = subtype: default: meta: (SetOf subtype meta) // { inherit default; }; + } diff --git a/libs/config/lib/modules/types.nix b/libs/config/lib/modules/types.nix new file mode 100644 index 0000000..d2455c2 --- /dev/null +++ b/libs/config/lib/modules/types.nix @@ -0,0 +1,84 @@ +{ core, ... }: + let + inherit(core) debug; + + positiveInteger + = { + isInstanceOf = value: integer.isInstanceOf value && value > 0; + }; + + positiveNumber + = { + isInstanceOf = value: number.isInstanceOf value && value > 0; + }; + + maxI8 = maxU8 / 2; + maxI16 = maxU16 / 2; + maxI32 = maxU32 / 2; + + maxU8 = 255; + maxU16 = 65535; + maxU32 = 4294967295; + + minI8 = 0 - maxI8 - 1; + minI16 = 0 - maxI16 - 1; + minI32 = 0 - maxI32 - 1; + in + set.mapValues + ( + value: + debug.panic [] + { + text = "Type expected."; + when + = !set.isInstanceOf value + || value.__type__ or null != "Type"; + } + value + ) + { + inherit(core) any bool float integer never null number path set string; + + + + positiveInteger = primitive positiveInteger.isInstanceOf; + positiveNumber = primitive positiveNumber.isInstanceOf; + } + +/* + [ + ( foo: bar: { name = "either"; check = checks.isEitherOr either; merge = merge.eitherOr inner; } ) + ( variants: { name = "enum"; check = checks.isInList payload; merge = merge.equal; } ) + ( subtype: { name = "listOf"; check = checks.isListOf empty inner; merge = merge.lists; } ) + ( subtype: { name = "nullOr"; check = checks.isNullOr inner; merge = merge.nullOr inner; } ) + ( subtype: { name = "setOf"; check = checks.isSetOf inner; merge = merge.sets; } ) + + ( { name = "deferredModule"; check = checks.isNever; merge = merge.never; } ) + ( { name = "functionTo"; check = checks.isFunction; merge = merge.functions inner; apply = applyFn inner; } ) + ( { name = "intBetween"; check = checks.isIntegerBetween range; inherit(variants.int) merge; } ) + ( { name = "lazyAttrsOf"; check = checks.isSetOf inner; merge = merge.sets; } ) + ( { name = "nonEmptyStr"; check = checks.isNonEmptyString; inherit(variants.str) merge; } ) + ( { name = "numberBetween"; check = checks.isNumberBetween range; merge = merge.equal; } ) + ( { name = "numberNonnegative"; check = checks.isNonNegativeNumber; merge = merge.equal; } ) + ( { name = "numberPositive"; check = checks.isPositiveNumber; merge = merge.equal; } ) + ( { name = "optionType"; check = checks.isOptionType; merge = merge.null; } ) + ( { name = "package"; check = checks.isPackage; merge = merge.never; } ) + ( { name = "passwdEntry"; check = checks.isNever; merge = merge.never; } ) + ( { name = "positiveInt"; check = checks.isPositiveInteger; inherit(variants.int) merge; } ) + ( { name = "raw"; check = checks.isAny; merge = merge.never; } ) + ( { name = "separatedString"; check = checks.isString; merge = merge.stringsWith payload; } ) + ( { name = "signedInt8"; check = checks.isSignedByte; inherit(variants.int) merge; } ) + ( { name = "signedInt16"; check = checks.isSignedWord; inherit(variants.int) merge; } ) + ( { name = "signedInt32"; check = checks.isSignedLong; inherit(variants.int) merge; } ) + ( { name = "singleLineStr"; check = checks.isStringMatching "[^\n\r]*\n?"; merge = merge.line; } ) + ( { name = "strMatching"; check = checks.isStringMatching pattern; inherit(variants.str) merge; } ) + ( { name = "submodule"; inherit(subtype) check; merge = merge.never; } ) + ( { name = "uniq"; inherit(subtype) check; merge = merge.never; } ) + ( { name = "unique"; inherit(subtype) check; merge = merge.never; } ) + ( { name = "unsignedInt"; check = checks.isUnsignedInteger; inherit(variants.int) merge; } ) + ( { name = "unsignedInt8"; check = checks.isSignedByte; inherit(variants.int) merge; } ) + ( { name = "unsignedInt16"; check = checks.isSignedWord; inherit(variants.int) merge; } ) + ( { name = "unsignedInt32"; check = checks.isSignedLong; inherit(variants.int) merge; } ) + ( { name = "unspecified"; check = checks.isAny; merge = merge.default; } ) + ] +*/ diff --git a/libs/config/lib/networks/default.nix b/libs/config/lib/networks/default.nix new file mode 100644 index 0000000..8fc34c5 --- /dev/null +++ b/libs/config/lib/networks/default.nix @@ -0,0 +1,212 @@ +{ configurations, core, peers, ... } @ lib: + let + inherit(configurations) Configuration'; + inherit(core) debug list path set string type; + inherit(peers) Peer PeerConfiguration; + + NetworkConfiguration = Configuration' "Network"; + + collect + = { allowedTCPPorts, allowedUDPPorts, hostName, interfaces, peers, source, wireless, ... }: + debug.debug "collect" + { + text = "peers"; + data = peers; + } + [ + ( + NetworkConfiguration + { + configuration + = { secret, ... }: + { + networking + = { + inherit hostName interfaces; + firewall + = { + enable = true; + inherit allowedTCPPorts allowedUDPPorts; + }; + wireless + = wireless + // { + environmentFile + = secret.generateEnvFile' "wireless"; + }; + }; + }; + inherit source; + } + ) + ] + ++ ( + list.map + PeerConfiguration + peers + ); + + extendName + = networkName: + peerName: + if networkName != null + then + "${peerName}.${networkName}" + else + peerName; + + prepare + = environment: + host: + network: + if set.isInstanceOf network + then + prepareNetwork environment host network + else + debug.panic + "prepare" + { + text = "The option `network` must be a set."; + data = network; + }; + + prepareNetwork + = { ... } @ environment: + host: + let + checkIP + = { + addresses ? [ ], + routes ? [ ], + }: + { + inherit addresses routes; + }; + + checkPort + = port: + if port >= 0 && port < 65356 + then + port + else + debug.panic + [ "prepareNetwork" "checkPort" ] + "Invalid Port ${string port}. must be between including 0 and 65355"; + collectPorts + = ports: + list.concat + ( + set.mapToList + ( + name: + port: + type.matchPrimitiveOrPanic port + { + int = [ (checkPort port) ]; + list = list.map checkPort port; + set = collectPorts port; + } + ) + ports + ); + loadPeer + = peer: + peers.load + peer + environment; + mapPeers + = networkName: + peers: + list.concat + ( + set.mapToList + ( + peerName: + peer: + let + loadedPeer = loadPeer peer; + + name + = extendName + networkName + peerName; + namedPeer = { inherit name; } // loadedPeer; + + source = host.source "network" "peers" namedPeer.name; + in + if Peer.isInstanceOf loadedPeer + then + [ ({ inherit source; } // namedPeer) ] + else + mapPeers name loadedPeer + ) + peers + ); + mapPeers' = mapPeers null; + in + { + allowLegacyTLS ? true, + domain ? null, + interfaces ? { }, + ips ? [ ], + peers ? [ ], + tcp ? { }, + udp ? { }, + wireless ? { }, + }: + { + inherit allowLegacyTLS domain ips tcp udp wireless; + allowedTCPPorts = collectPorts (tcp.ports or {}); + allowedUDPPorts = collectPorts (udp.ports or {}); + hostName = host.name; + interfaces + = set.map + ( + name: + { + ipv4 ? {}, + ipv6 ? {}, + macAddress ? null, + mtu ? null, + proxyARP ? false, + # tempAddress + useDHCP ? true, + virtual ? false, + virtualOwner ? "root", + # virtualType + wakeOnLan ? { enable = false; }, + ... + } @ config: + config + // { + inherit macAddress mtu name proxyARP useDHCP virtual virtualOwner wakeOnLan; + ipv4 = checkIP ipv4; + ipv6 = checkIP ipv6; + } + ) + interfaces; + peers + = type.matchPrimitiveOrPanic peers + { + list + = mapPeers' + ( + list.imapValuesToSet + ( + index: + peer: + { + name = string index; + value = peer; + } + ) + peers + ); + set = mapPeers' peers; + }; + source = host.source "network"; + }; + in + { + inherit collect extendName prepare; + } diff --git a/libs/config/lib/packages/default.nix b/libs/config/lib/packages/default.nix new file mode 100644 index 0000000..31545e0 --- /dev/null +++ b/libs/config/lib/packages/default.nix @@ -0,0 +1,217 @@ +{ nixpkgs, core, ... }: + let + inherit(core) context debug derivation error expression list path set string target type; + + checkPackage + = name: + package: + let + inherit(expression.tryEval package) success value; + in + debug.info "checkPackage" "Check Package `${name}`…" + ( + if debug.Debug.isInstanceOf package + then + abort "${package}" + else if success + && derivation.isInstanceOf' value + then + value + else if !success + then + debug.panic [ "checkPackage" name ] + { + text = "${name} does not evaluate!"; + data = value; + } + else + debug.panic [ "checkPackage" ] "${name} is not a package, but a ${type.getPrimitive value}" + ); + + defaultAllowPredicate + = predicateName: + allowAll: + allowedPackages: + { + name ? null, + pname ? (extractPackageName name), + ... + } @ pkg: + if pname != null + then + let + allowed = list.find pname allowedPackages; + allowed' = if allowed then "allowed" else "not allowed"; + in + debug.warn [ "defaultAllowPredicate" ] + { + text = "${predicateName} package `${pname}` ${allowed'}."; + } + allowed + else + debug.panic [ "defaultAllowPredicate" ] + { + text = "Cannot determine pname of ${predicateName} package"; + data = pkg; + nice = true; + } + false; + + defaultHandleEvalIssue + = reason: + message: + debug.panic "defaultHandleEvalIssue" + { + text = reason; + data = message; + } + null; + + extractPackageName + = name: + if name != null + then + list.head (string.split "-" name) + else + null; + + fixConfig + = { + allowBroken ? false, + allowedInsecurePackages ? [], + allowedNonSourcePackages ? [], + allowedUnfreePackages ? [], + allowInsecure ? false, + allowInsecurePredicate ? (defaultAllowPredicate "insecure" allowInsecure allowedInsecurePackages), + allowlistedLicenses ? [], + allowNonSource ? false, + allowNonSourcePredicate ? (defaultAllowPredicate "non-source" allowNonSource allowedNonSourcePackages), + allowUnfree ? false, + allowUnfreePredicate ? (defaultAllowPredicate "unfree" allowUnfree allowedUnfreePackages), + allowUnsupportedSystem ? false, + blocklistedLicenses ? [], + checkMeta ? true, + handleEvalIssue ? defaultHandleEvalIssue, + inHydra ? false, + showDerivationWarnings ? [], + }: + { + inherit allowBroken + allowInsecurePredicate + allowlistedLicenses + allowNonSource allowNonSourcePredicate + allowUnfree allowUnfreePredicate + allowUnsupportedSystem + blocklistedLicenses + checkMeta + handleEvalIssue + inHydra + showDerivationWarnings; + }; + + fromNixpkgs + = { config ? {}, nixpkgs ? nixpkgs }: + registry: + let + legacyPackages = path.import' "${nixpkgs}/default.nix"; + in + target.System.mapStdenv + ( + system: + let + legacyPackages' + = legacyPackages + { + config = fixConfig config; + system = string system; + }; + in + if registry != null + then + legacyPackages'.${registry} + else + legacyPackages' + ); + + load + = fileName: + registries: + let + loadPackage + = source: + package: + let + environment = registries // { inherit source; }; + source' = source package; + in + type.matchPrimitiveOrPanic package + { + lambda = loadPackage source (package environment); + list = loadPackages source package; + null = []; + path = loadPackage source' (path.import package); + set + = debug.trace [ "load" "loadPackage" ] + { + text = "Package:"; + data = package; + nice = false; + } + [ package ]; + }; + + loadPackages + = source: + list.concatIMap + ( + index: + loadPackage (source index) + ); + + packageList + = loadPackage + (context fileName) + fileName; + + packages + = list.fold + ( + { ... } @ result: + { name, ... } @ package: + if !(set.hasAttribute name result) + then + result + // { + ${name} = package; + } + else if result.${name} == package + then + result + else + debug.panic [ "load" "packages" ] + { + text = "Package already in set"; + data = package; + } + result + ) + {} + packageList; + in + debug.debug "load" + { + text = "Loaded Packages"; + data = packages; + nice = true; + } + (set.values packages); + + load' + = fileName: + registries: + target.System.mapStdenv + (targetSystem: load fileName (registries { inherit targetSystem; })); + in + { + inherit extractPackageName fromNixpkgs load load'; + } diff --git a/libs/config/lib/peers/default.nix b/libs/config/lib/peers/default.nix new file mode 100644 index 0000000..d7d5030 --- /dev/null +++ b/libs/config/lib/peers/default.nix @@ -0,0 +1,105 @@ +{ configurations, core, networks, ... }: + let + inherit(core) debug set type; + inherit(configurations) Configuration; + + Peer + = type "Peer" + { + from + = about: + { + configuration ? {}, + network ? {}, + type ? {}, + }: + Peer.instanciate + { + inherit about configuration network type; + }; + }; + + PeerConfiguration + = Configuration "Peer" + { + call + = { environment, host, ... }: + { configuration, wrap, ... }: + let + environment' + = environment + // { inherit(host) network profile system version; }; + in + wrap + { + configuration = configuration environment'; + }; + }; + + constructors + = { + inherit Peer; + }; + + load + = source: + environment: + let + config + = configurations.load + source + environment + constructors + Peer; + configure' + = networkName: + set.map + ( + peerName: + { ... } @ node: + let + domain + = networks.extendName + networkName + peerName; + nodes = configure' domain node; + in + if Peer.isInstanceOf node + then + debug.debug "configure'" + { + text = "peer ${domain} from ${node.source}"; + data = node; + } + { inherit domain; } // node + else + debug.debug "configure'" + { + text = "network ${domain}"; + show = true; + } + nodes + ); + in + if Peer.isInstanceOf config + then + config + else + debug.debug "configure" + { + text = "result"; + show = true; + nice = true; + } + ( + configure' + null + config + ); + + in + constructors + // { + inherit PeerConfiguration; + inherit constructors load; + } diff --git a/libs/config/lib/profiles/default.nix b/libs/config/lib/profiles/default.nix new file mode 100644 index 0000000..a57d06e --- /dev/null +++ b/libs/config/lib/profiles/default.nix @@ -0,0 +1,136 @@ +{ configurations, core, services, ... }: + let + inherit(configurations) LegacyConfiguration Configuration; + inherit(core) context debug list path set string type; + + Profile + = type "Profile" + { + from + = about: + { + configuration ? null, + isDesktop ? false, + legacy ? false, + name ? null, + parents ? [], + services ? [], + source ? null, + ... + }: + Profile.instanciate + ( + { + inherit about configuration isDesktop legacy name services; + parents = list.map Profile.expect parents; + } + // ( + if source != null + then + { inherit source; } + else + { } + ) + ); + }; + + ProfileConfiguration + = Configuration "Profile" + { + call + = { environment, host, ... }: + { arguments, configuration, wrap, ... }: + let + environment' + = environment + // { inherit(host) network system version; }; + in + wrap + { + configuration + = configuration + ( + environment' + // { + config + = debug.warn + "ProfileConfiguration" + "Argument `config` is deprecated!" + environment.config; + } + ); + }; + }; + + collect + = { configuration, legacy, name, parents, services, source, ... } @ this: + let + args = { inherit configuration name source; }; + in + if legacy + then + [ (LegacyConfiguration args) ] + else + debug.debug "collect" + { + text = "Non-Legacy Profile"; + data = this; + nice = true; + } + ( + list.map + ProfileConfiguration + (configurations.collect args) + ) + ++ (collectParents parents) + ++ (collectServices services); + + collectParents = list.concatMap collect; + collectServices = services.collect; + + constructors + = { + inherit Profile; + }; + + load + = source: + environment: + configurations.load + source + environment + (constructors // services.constructors) + Profile; + + prepare + = environment: + host: + profile: + { + name = ""; + source = host.source "profile"; + } + // (Profile.expect profile); + in + constructors + // { + inherit collect constructors load prepare; + + importLegacy + = { nixpkgs, ... }: + list.mapNamesToSet + ( + name: + Profile "${name} (legacy)." + { + inherit name; + legacy = true; + configuration = path.import "${nixpkgs}/nixos/modules/profiles/${name}.nix"; + source + = context "nixpkgs/nixos/modules/profiles" + { + fileName = "${nixpkgs}/nixos/modules/profiles/${name}.nix"; + }; + } + ); + } \ No newline at end of file diff --git a/libs/config/lib/services/default.nix b/libs/config/lib/services/default.nix new file mode 100644 index 0000000..e44c40d --- /dev/null +++ b/libs/config/lib/services/default.nix @@ -0,0 +1,108 @@ +{ configurations, core, ... }: + let + inherit(configurations) Configuration; + inherit(core) debug list path set string type; + + Service + = type "Service" + { + from + = about: + { + configuration, + legacy ? false, + }: + Service.instanciate + { + inherit about configuration legacy; + }; + }; + + ServiceConfiguration + = Configuration "Service" + { + call + = { environment, host, ... }: + { arguments, configuration, legacy, wrap, ... }: + let + environment' + = environment + // { + inherit(host) network profile system version; + }; + in + wrap + { + inherit legacy; + configuration + = configuration + ( + environment' + // { + inherit(environment.config) services websites; + } + ); + }; + wrap + = { configuration, legacy, ... }: + if legacy + then + configuration + else + { + services = configuration; + }; + }; + + collect = list.concatMap configure; + + configure + = { about, configuration, legacy, name, source, ... }: + list.map + ServiceConfiguration + ( + configurations.collect + { + inherit configuration legacy source; + } + ); + + constructors + = { + inherit Service; + }; + + load + = source: + environment: + configurations.load + source + environment + constructors + Service; + + prepare + = environment: + host: + services: + if set.isInstanceOf services + then + set.map (prepareService environment host) services + else + debug.panic "prepare" "The option `services` must be a set."; + + prepareService + = environment: + host: + name: + service: + { + source = host.source "services" name; + } + // (Service.expect service) + // { inherit name; }; + in + constructors + // { + inherit collect constructors load prepare; + } diff --git a/libs/config/lib/systems/default.nix b/libs/config/lib/systems/default.nix new file mode 100644 index 0000000..8554c07 --- /dev/null +++ b/libs/config/lib/systems/default.nix @@ -0,0 +1,49 @@ +{ configurations, core, nixpkgs, ... }: + let + inherit(configurations) Configuration'; + inherit(core) debug list path set string target type; + + SystemConfiguration = Configuration' "System"; + + collect + = hostSystem: + [ + ( + SystemConfiguration + { + configuration + = { registries, ... }: + { + nixpkgs + = debug.info "collectSystem" + { + text = "registries"; + data = set.names registries; + nice = true; + } + { + hostPlatform = string hostSystem; + pkgs = registries.nix; + }; + }; + inherit(hostSystem) source; + } + ) + ]; + + prepare + = environment: + host: + system: + let + system' = target.System system; + in + { + source = host.source "system"; + } + // system'; + in + { + inherit SystemConfiguration; + inherit collect prepare; + } diff --git a/libs/config/lib/users/default.nix b/libs/config/lib/users/default.nix new file mode 100644 index 0000000..b3c6b3f --- /dev/null +++ b/libs/config/lib/users/default.nix @@ -0,0 +1,210 @@ +{ configurations, core, packages, ... }: + let + inherit(configurations) Configuration; + inherit(core) debug list path set string time type; + + loadKey + = { hostName, realName }: + key: + let + convert + = { contact ? null, date ? null, key, method, ... }: + let + contact' + = if contact != null + then + " contact = \"${contact}\";" + else + ""; + date' = time date; + pad = value: if value < 10 then "0${string value}" else string value; + date'' + = if date != null + then + " date = \"${string date'.year}-${pad date'.month}-${pad date'.day}\";" + else + ""; + in + ''ssh-${method} ${key} { host = "${hostName}"; owner = "${realName}";${contact'}${date''} }''; + in + if path.isInstanceOf key + then + convert (path.import key) + else + convert key; + + User + = type "User" + { + from + = realName: + { + configuration ? {}, + dates ? {}, + extra ? {}, + keys ? {}, + }: + User.instanciate + { + inherit configuration; + trusted = false; + user + = { + inherit dates extra realName; + keys + = set.map + ( + hostName: + hostKeys: + if hostKeys == null + then + [] + else if list.isInstanceOf hostKeys + then + list.map (loadKey { inherit hostName realName; }) hostKeys + else + [ (loadKey { inherit hostName realName; } hostKeys) ] + ) + keys; + }; + }; + }; + + UserConfiguration + = Configuration "User" + { + call + = { environment, host, modules, ... }: + { arguments, configuration, user, wrap, ... }: + let + environment' + = environment + // { + inherit packages; + user + = user + // { + extra + = set.mapValues + ( + extra: + extra."${host.system}" or extra + ) + user.extra; + }; + inherit(host) profile system version; + }; + hasHomeManager = modules.home-manager or null != null; + in + wrap + { + inherit hasHomeManager host user; + configuration + = configuration + ( + environment' + // { + config + = if hasHomeManager + then + environment.config.home-manager.users.${user.name} + else + debug.error + "UserConfiguration" + "Empty `config`, because home-manager is missing." + {}; + } + ); + }; + wrap + = { configuration, hasHomeManager, host, user, ... }: + { + users.users.${user.name} + = configuration.host + // { + isNormalUser = true; + openssh.authorizedKeys + = { + keys + = debug.info [ "UserConfiguration" "openssh.authorizedKeys" ] + { + text = "${user.name}@${host.network.hostName}"; + show = true; + } + user.keys.${host.network.hostName} or []; + }; + }; + } + // ( + if hasHomeManager + then + { + home-manager.users.${user.name} + = set.remove + configuration + [ "host" ]; + } + else + debug.error + "UserConfiguration" + "Module `home-manager` is missing." + {} + ); + }; + + collect = users: list.concatMap configure (set.values users); + + configure + = { configuration, user, source, trusted, ... }: + list.map + UserConfiguration + ( + configurations.collect + { + inherit configuration user source; + } + ); + + constructors + = { + inherit User; + }; + + load + = source: + environment: + configurations.load + source + environment + constructors + User; + + prepare + = environment: + host: + users: + if set.isInstanceOf users + then + set.map (prepareUser environment host) users + else + debug.panic "prepare" "The option `users` must be a set."; + + prepareUser + = environment: + host: + name: + user: + { + source = host.source "users" name; + } + // (User.expect user) + // { + user + = user.user + // { inherit name; }; + }; + in + constructors + // { + inherit collect constructors load prepare; + } diff --git a/libs/config/lib/versions/default.nix b/libs/config/lib/versions/default.nix new file mode 100644 index 0000000..28fe66a --- /dev/null +++ b/libs/config/lib/versions/default.nix @@ -0,0 +1,43 @@ +{ core, systems, ... }: + let + inherit(core) debug string time type version; + inherit(systems) SystemConfiguration; + + config + = stateVersion: + { dateTime, host, ... }: + { + boot.loader.grub + = { + configurationName = "${host.network.hostName}-${version.deriveVersion dateTime}"; + }; + system + = { + inherit stateVersion; + }; + }; + + collect + = { source, version, ... }: + [ + ( + SystemConfiguration + { + configuration = config version; + inherit source; + } + ) + ]; + + prepare + = environment: + host: + version: + { + version = string.expect version; + source = host.source "version"; + }; + in + { + inherit collect prepare; + } \ No newline at end of file diff --git a/libs/config/tests/default.nix b/libs/config/tests/default.nix new file mode 100644 index 0000000..1b9bc54 --- /dev/null +++ b/libs/config/tests/default.nix @@ -0,0 +1,14 @@ +{ core, ... }: +{ ... } @ lib: + let + inherit(core) set; + in + { + deepSeqAll + = set.mapValues + ( + module: + ({ ... }: module) + ) + lib; + } \ No newline at end of file diff --git a/libs/core/flake.nix b/libs/core/flake.nix new file mode 100644 index 0000000..d183de1 --- /dev/null +++ b/libs/core/flake.nix @@ -0,0 +1,82 @@ +{ + description = "Core library of general-purpose expressions worth implementing as intrinsics"; + inputs + = { + libintrinsics.url = "github:sivizius/nixfiles/development?dir=libs/intrinsics"; + }; + outputs + = { self, libintrinsics, ... }: + let + intrinsics = libintrinsics.lib; + + adjustArguments + = { arguments, fileName, moduleName, source, ... }: + intrinsics.mapAttrs + ( + moduleName: + module: + let + initialisationData' + = { + inherit fileName moduleName; + source + = source + { + inherit fileName; + attribute + = if moduleName != null + then + moduleName + else + intrinsics.baseNameOf fileName; + }; + }; + in + if module.__type__ or null == "NeedInitialisation" + then + module.initialise module.body initialisationData' + else + module + ) + arguments; + + minimal + = intrinsics.scopedImport + { inherit Library; } + ./lib + { inherit intrinsics; }; + + Library + = { + __functor + = { ... }: + libraryName: + { ... } @ environment: + { ... } @ modules: + let + arguments + = library + // environment; + library + = intrinsics.mapAttrs + ( + moduleName: + fileName: + intrinsics.import fileName + (adjustArguments { inherit arguments fileName moduleName source; }) + ) + modules; + source = library.context libraryName; + in + library; + }; + + env = { inherit intrinsics; }; + lib = minimal.library.load ./lib env; + tests = lib.check.load ./tests env lib; + in + { + inherit lib tests; + checks = lib.check tests {}; + }; +} \ No newline at end of file diff --git a/libs/core/lib/ansi/default.nix b/libs/core/lib/ansi/default.nix new file mode 100644 index 0000000..5783960 --- /dev/null +++ b/libs/core/lib/ansi/default.nix @@ -0,0 +1,135 @@ +{ bool, debug, integer, set, string, type, ... }: + let + inherit(string) char; + + colours + = { + background + = { + black = 40; + red = 41; + green = 42; + yellow = 43; + blue = 44; + magenta = 45; + cyan = 46; + darkGrey = 47; + # select = 48; + default = 49; + lightGrey = 100; + brightRed = 101; + brightGreen = 102; + brightYellow = 103; + brightBlue = 104; + brightMagenta = 105; + brightCyan = 106; + white = 107; + }; + foreground + = { + black = 30; + red = 31; + green = 32; + yellow = 33; + blue = 34; + magenta = 35; + cyan = 36; + darkGrey = 37; + # select = 38; + default = 39; + lightGrey = 90; + brightRed = 91; + brightGreen = 92; + brightYellow = 93; + brightBlue = 94; + brightMagenta = 95; + brightCyan = 96; + white = 97; + }; + }; + + concatAttributes + = attributes: + let + attributes' + = type.matchPrimitiveOrPanic attributes + { + bool = bool.select attributes "1" "0"; + int = integer.toString attributes; + list = string.concatWith ";" attributes; + null = ""; + path = "${attributes}"; + string = attributes; + }; + in + attributes'; + + displayAttributes + = { + reset = 0; + bold = 1; + faint = 2; + italic = 3; + underline = 4; + slowBlink = 5; + rapidBlink = 6; + invert = 7; + conceal = 8; + crossedOut = 9; + font + = { + default = 10; + alternative + = number: + debug.panic [ "displayAttributes" "font" "alternative" ] + { + text = "Alternative Font must be an integer in 1…9"; + data = number; + when + = !(integer.isInstanceOf number) + || number < 1 + || number > 9; + } + number + 10; + }; + fraktur = 20; + doubleUnderline = 21; + normalIntensity = 22; + #… + notCrossedOut = 29; + # … + } + // colours; + + mapToSGR + = set.mapValues + ( + attributes: + type.matchPrimitiveOrDefault attributes + { + lambda = args: SGR (attributes args); + set = mapToSGR attributes; + } + (SGR attributes) + ); + + APC = "${char.escape}_"; + CSI = "${char.escape}["; + DCS = "${char.escape}P"; + OSC = "${char.escape}]"; + PM = "${char.escape}^"; + SOS = "${char.escape}X"; + SS2 = "${char.escape}N"; + SS3 = "${char.escape}O"; + ST = "${char.escape}\\"; + + SGR + = attributes: + "${CSI}${concatAttributes attributes}m"; + in + { + inherit APC CSI DCS OSC PM SOS SS2 SS3 ST; + inherit SGR; + inherit colours concatAttributes displayAttributes; + } + // mapToSGR displayAttributes diff --git a/libs/core/lib/any/default.nix b/libs/core/lib/any/default.nix new file mode 100644 index 0000000..1134d24 --- /dev/null +++ b/libs/core/lib/any/default.nix @@ -0,0 +1,5 @@ +{ type, ... }: + type "any" + { + isInstanceOf = x: true; + } \ No newline at end of file diff --git a/libs/core/lib/bool/default.nix b/libs/core/lib/bool/default.nix new file mode 100644 index 0000000..3cc435a --- /dev/null +++ b/libs/core/lib/bool/default.nix @@ -0,0 +1,47 @@ +{ intrinsics, type, ... }: + let + bool + = type "bool" + { + inherit(intrinsics) false true; + + and#: bool -> bool -> bool + = a: b: ( bool.expect a ) && ( bool.expect b ); + + equivalent#: bool -> bool -> bool + = a: b: ( bool.expect a ) == ( bool.expect b ); + + format + = condition: + bool.select condition "true" "false"; + + formatLegacy + = condition: + bool.select condition "1" ""; + + implies#: bool -> bool -> bool + = a: b: ( bool.expect a ) -> ( bool.expect b ); + + isInstanceOf = intrinsics.isBool or (value: value == true || value == false); + isPrimitive = true; + + not#: bool -> bool + = a: !( bool.expect a ); + + or#: bool -> bool -> bool + = a: b: ( bool.expect a ) || ( bool.expect b ); + + orNull + = value: + bool.isInstanceOf value || value == null; + + select#: bool -> T -> T -> T + # where T: Any + = condition: + ifTrue: + ifFalse: + if condition then ifTrue + else ifFalse; + }; + in + bool diff --git a/libs/core/lib/check/default.nix b/libs/core/lib/check/default.nix new file mode 100644 index 0000000..5cfcf89 --- /dev/null +++ b/libs/core/lib/check/default.nix @@ -0,0 +1,276 @@ +{ ansi, context, debug, derivation, expression, library, list, path, set, string, target, type, ... }: + let + TestCase + = type "TestCase" + { + from + = { success, value } @ result: + TestCase.instanciate result; + }; + + TestResult + = type "TestResult" + { + from + = variant: + { success, value } @ result: + TestResult.instanciateAs variant result; + }; + + check + = value: + arguments: + let + result = expression.tryEval value; + in + type.matchPrimitiveOrDefault result.value + { + list = checkList result.value; + set = checkTests arguments result.value; + lambda = checkValue (result.value arguments); + } + (TestResult "Value" result); + + checkList + = list.fold + ( + { success, value, ... } @ state: + entry: + let + result = checkValue entry; + in + state + // { + success = success && result.success; + value = value ++ [ entry ]; + } + ) + ( + TestResult "List" + { + success = true; + value = []; + } + ); + + checkSet + = set.fold + ( + { success, value, ... } @ state: + name: + entry: + let + result = checkValue entry; + in + debug.info "checkSet" + { + text = "Entry ${name} failed:"; + data = entry; + when = !result.success; + } + state + // { + success = success && result.success; + value = value // { ${name} = entry; }; + } + ) + ( + TestResult "Set" + { + success = true; + value = {}; + } + ); + + checkTests + = arguments: + set.fold + ( + { success, value, ... } @ state: + name: + entry: + let + result = check entry arguments; + in + state + // { + success = success && result.success; + value = value // { ${name} = result; }; + } + ) + ( + TestCase + { + success = true; + value = {}; + } + ); + + checkValue + = value: + let + result = expression.tryEval value; + in + type.matchPrimitiveOrDefault result.value + { + list = checkList result.value; + set + = if !(string.DoNotFollow.isInstanceOf result.value) + then + checkSet result.value + else + result; + } + (TestResult "Value" result); + + format + = system: + fullName: + { success, value, ... } @ this: + if !(TestResult.isInstanceOf this) + then + string.concatLines + ( + set.mapToList + ( + name: + testCases: + let + fullName' + = if fullName != null + then + "${fullName} → ${name}" + else + name; + in + format system fullName' testCases + ) + value + ) + else + let + inherit(ansi) foreground; + fullName' + = if fullName != null + then + " ${fullName}" + else + ""; + value' + = string.from + { + legacy = false; + display = true; + maxDepth = null; + nice = true; + showType = true; + } + value; + verdict + = if success + then + "${foreground.green}[passed]" + else + "${foreground.red}[failed]"; + formatLine + = line: + "echo -e \"${verdict}${fullName'} @ ${system}${line}${ansi.reset}\""; + in + if success && true + then + formatLine "" + else + string.concatMappedLines + ( + line: + let + line' + = let + inherit(string.char) escape; + in + string.replace' + { + "\"" = ''\"''; + "\\" = ''\\''; + "$" = ''\$''; + "`" = ''\`''; + ${escape} = "\\e"; + } + line; + in + formatLine ": ${line'}" + ) + (string.splitLines value'); + + testsToChecks + = { fileName, lib, source, tests }: + buildSystem: + arguments: + let + lib' = library.initialise lib (arguments' // { inherit fileName source; }); + arguments' = arguments // { inherit buildSystem; }; + tests' = check (tests lib') arguments'; + builder + = path.toFile "builder.sh" + '' + #!/usr/bin/env sh + ${format buildSystem null tests'} + ${ + if tests'.success + then + '' + echo -e "\e[32mall tests were successful!\e[0m" + echo "1" > $out + exit 0 + '' + else + '' + echo -e "\e[31msome tests failed!\e[0m" + exit 1 + '' + } + ''; + in + debug.debug [] + { + text = "Builder for ${buildSystem}"; + data = builder; + } + derivation + { + args = [ builder ]; + builder = "/bin/sh"; + name = "libcore-test"; + system = "${buildSystem}"; + }; + + in + { + load + = fileName: + { ... } @ env: + { ... } @ lib: + { + inherit fileName lib; + tests = path.import fileName env; + source = context "tests" fileName; + }; + + __functor + = { ... }: + { ... } @ tests: + arguments: + if false + then + target.System.mapAll + ( + buildSystem: + { + default = testsToChecks tests buildSystem arguments; + } + ) + else + { + x86_64-linux.default = testsToChecks tests "x86_64-linux" arguments; + }; + } diff --git a/libs/core/lib/context/default.nix b/libs/core/lib/context/default.nix new file mode 100644 index 0000000..cb18b6b --- /dev/null +++ b/libs/core/lib/context/default.nix @@ -0,0 +1,165 @@ +{ debug, integer, list, path, string, type, ... }: + let + Item + = ( + type.enum "Item" + { + Attribute = string; + Index = integer; + File = string; + Root = string; + } + ) + // { + format + = self: + Item.match self + { + Attribute = { value, ... }: ".${string.escapeKey value}"; + File = { value, ... }: "@(${value})"; + Index = { value, ... }: "[${integer.toString value}]"; + Root = { value, ... }: "<${value}>"; + }; + format' + = self: + Item.match self + { + Attribute = { value, ... }: ".${string.escapeKey value}"; + File = { value, ... }: ""; + Index = { value, ... }: "[${integer.toString value}]"; + Root = { value, ... }: "<${value}>"; + }; + }; + + Context + = type "Context" + { + inherit from; + __public__ = [ ]; + }; + + getFileName + = fileName: + let + ext + = string.slice + ((string.length fileName') - extLength) + extLength + fileName'; + extLength = 4; + fileName' = string.toString fileName; + in + if ext == ".nix" then fileName' + else "${fileName'}/default.nix"; + + extend + = let + addAttribute + = { absolute, relative, ... } @ self: + attribute: + self + // { + absolute = absolute ++ [ (Item.Attribute attribute) ]; + relative = relative ++ [ (Item.Attribute attribute) ]; + }; + + addFile + = { absolute, relative, ... } @ self: + fileName: + let + fileName' = getFileName fileName; + in + self + // { + absolute = absolute ++ [ (Item.File fileName') ]; + fileName = fileName'; + relative = [ (Item.File fileName') ]; + }; + + addIndex + = { absolute, relative, ... } @ self: + index: + self + // { + absolute = absolute ++ [ (Item.Index index) ]; + relative = relative ++ [ (Item.Index index) ]; + }; + + extendWith + = { ... } @ self: + { + attribute ? null, + fileName ? null, + index ? null, + }: + let + self' + = if attribute != null + then + addAttribute self attribute + else + self; + self'' + = if index != null + then + addIndex self' index + else + self'; + in + if fileName != null + then + addFile self'' fileName + else + self''; + in + { ... } @ self: + source: + if Context.isInstanceOf source + then + source + else + type.matchPrimitiveOrPanic source + { + int = addIndex self source; + list = list.fold extend self source; + path = addFile self source; + set = extendWith self source; + string = addAttribute self source; + }; + + format = string.concatMapped Item.format; + format' = string.concatMapped Item.format'; + formatAbsolute = { absolute, ... }: format absolute; + formatAbsolute' = { absolute, ... }: format' absolute; + formatFileName = { fileName, ... }: string.toString fileName; + formatRelative = { relative, ... }: format relative; + formatRelative' = { relative, ... }: "$${format' relative}"; + + from + = root: + Context.instanciate + { + absolute = [ (Item.Root (toRoot root)) ]; + fileName + = if path.isInstanceOf root + then + root + else + "$"; + relative = [ (Item.Root (toRoot root)) ]; + __functor = extend; + __toString = formatAbsolute; + }; + + toRoot + = root: + type.matchPrimitiveOrPanic root + { + path = getFileName root; + string = root; + }; + in + Context + // { + inherit formatAbsolute formatAbsolute' formatFileName formatRelative formatRelative'; + } diff --git a/libs/core/lib/debug/default.nix b/libs/core/lib/debug/default.nix new file mode 100644 index 0000000..b945226 --- /dev/null +++ b/libs/core/lib/debug/default.nix @@ -0,0 +1,358 @@ +{ + ansi, context, debug, error, intrinsics, library, list, set, string, type, + logLevel ? debug.levels.info, + fatalLevel ? debug.levels.error, + ... +}: + let + Body + = string + || [ string ] + || { + # depth: integer? = null, + # fatal: bool = false, + # text: ([ string ] | string)? = [], + # when: bool = true, + # show: bool = false, + # data: any = null, + } + || null; + + Debug + = type "Debug" + { + from#: + # { colour: string, level: integer } + # -> { body: [ string ]; fatal: bool; nice: bool; show: bool; showType: bool; when: bool; } + # -> Debug + = { active, colour, fatal, level, source, ... } @ self: + { + body, + hex ? false, + maxDepth ? null, + nice ? false, + show ? false, + showType ? true, + trace ? false, + when ? true + }: + let + body' = list.map string.expect body; + fail + = if level == 0 + then + error.abort + else + error.panic; + message + = let + format = context.formatAbsolute'; + in + [ "[${self.getVariant}] {${format source} @ ${context.formatFileName source}}" ] ++ body'; + toDebug + = isFatal: + from: + Debug.instanciateAs (self.getVariant) + { + inherit from isFatal; + body = body'; + __functor = _: from; + __toString + = { body, ... }: + intrinsics.trace (string.concatLines body) + error.abort "???"; + }; + in + if when + && ( active || fatal ) + then + if fatal + then + toDebug true + ( + intrinsics.trace + (ansiFormat colour message) + (fail "See Error Message Above") + ) + else if show + then + toDebug false + ( + value: + let + additionalLines + = string.splitLines + ( + string.toTrace + { inherit hex maxDepth nice showType trace; } + value + ); + in + intrinsics.trace + (ansiFormat colour (message ++ additionalLines)) + value + ) + else + toDebug false + ( + intrinsics.trace + (ansiFormat colour message) + ) + else + toDebug false (x: x); + }; + + DebugLevel + = let + print + = let + toLines + = text: + string.splitLines (string.trim text); + toLines' + = text: + type.matchPrimitiveOrPanic text + { + null = [ ]; + list = text; + string = toLines text; + }; + fromList + = lines: + { + body = list.map string.expect lines; + }; + fromSet + = { + data ? null, + hex ? false, + maxDepth ? null, + nice ? false, + show ? false, + showType ? true, + text ? [ ], + trace ? false, + when ? true, + } @ this: + { + inherit hex maxDepth nice show showType trace when; + body + = ( toLines' text ) + ++ ( + if this ? data + then + string.splitLines + ( + string.toTrace + { inherit hex maxDepth nice showType trace; } + data + ) + else + [ ] + ); + }; + in + self: + source: + body: + Debug + ( + self + // { + source = self.source source; + } + ) + ( + type.matchPrimitiveOrPanic body + { + null = { body = [ ]; }; + list = fromList body; + set = fromSet body; + string = { body = toLines body; }; + } + ); + in + type "DebugLevel" + { + from + = variant: + { colour, level }: + DebugLevel.instanciateAs variant + { + inherit colour level print; + __functor = print; + active = level <= logLevel.level; + fatal = level <= fatalLevel.level; + message = null; + }; + }; + + Source + = string + || [ string ] + || null; + + ansiFormat + = let + backspaces = "${string.repeat string.char.backspace 7}"; + in + color: + lines: + let + concatLines = string.concatMapped (line: "\n${color}| ${line}"); + head = list.head lines; + tail = concatLines (list.tail lines); + in + "${backspaces}${color}${ansi.bold}${head}${ansi.reset}${tail}${ansi.reset}"; + + minimal + = set.mapValues + ( + logger: + source: + body: + if body.when or true + then + ( + if body ? data + then + intrinsics.trace body.data + else + (x: x) + ) + logger (body.text or body) + else + (x: x) + ) + { + dafuq = message: error.abort "[dafuq] ${string.toString message}"; + panic = message: error.throw "[panic] ${string.toString message}"; + error = message: intrinsics.trace "[error] ${string.toString message}"; + warn = message: intrinsics.trace "[warn] ${string.toString message}"; + info = message: intrinsics.trace "[info] ${string.toString message}"; + debug = message: intrinsics.trace "[debug] ${string.toString message}"; + trace = message: intrinsics.trace "[trace] ${string.toString message}"; + silent = message: x: x; + }; + + levels + = let + inherit(ansi) foreground; + in + { + dafuq = { colour = foreground.brightMagenta; level = 0; }; # This should not even happen. + panic = { colour = foreground.red; level = 1; }; # You will not get a result. + error = { colour = foreground.brightRed; level = 2; }; # You will not get, what you expect. + warn = { colour = foreground.brightYellow; level = 3; }; # You might not get, what you expect. + info = { colour = foreground.brightGreen; level = 4; }; # Usefull information, which are fine. + debug = { colour = foreground.brightCyan; level = 5; }; # Specific Information. + trace = { colour = foreground.lightGrey; level = 6; }; # Single code paths. + silent = { colour = foreground.white; level = 7; }; # Silent. + }; + + printers = set.map DebugLevel levels; + + updatePrinters + = self: + { + debug ? null, + source, + ... + }: + ( + set.map + ( + name: + method: + if DebugLevel.isInstanceOf method + then + method + // { + inherit source; + } + // ( + if debug != null + then + { + active = method.level <= (debug.logLevel or levels.info).level or levels.${debug.logLevel}.level; + fatal = method.level <= (debug.fatalLevel or levels.error).level or levels.${debug.fatalLevel}.level; + } + else + {} + ) + else + method + ) + self + ) + // { inherit source; }; + + withFunction + = debugLevel: + call: + debugLevel + // { + inherit call; + __functor + = { call, print, ... } @ self: + source: + call + ( + self + // { + __functor = _: print self source; + } + ); + }; + + withMessage + = debugLevel: + message: + debugLevel + // { + inherit message; + __functor + = { message, print, ... } @ self: + source: + print self source message; + }; + in + library.NeedInitialisation + ( + { ... } @ self: + { ... } @ args: + updatePrinters self args + ) + ( + printers + // { + __functor + = { ... } @ self: + source: + updatePrinters self { source = self.source source; }; + + inherit Debug DebugLevel levels; + + deprecated + = withFunction + printers.warn + ( + { ... } @ print: + other: + print + ( + if other ? source + then + let + format = context.formatAbsolute'; + in + "Deprecated: Use ${format other.source} instead!" + else + "Deprecated!" + ) + other + ); + unimplemented = withMessage printers.panic "Not implemented yet, please be patient!"; + unreachable = withMessage printers.dafuq "Unreachable…or at least should not have been o.O!"; + } + ) diff --git a/libs/core/lib/default.nix b/libs/core/lib/default.nix new file mode 100644 index 0000000..1a01e76 --- /dev/null +++ b/libs/core/lib/default.nix @@ -0,0 +1,40 @@ +{ + checked ? false, # enable e.g. type-checks + intrinsics ? builtins, # intrinsic/builtin functions, variables, etc. + ... +}: + Library "libcore" + { + inherit checked intrinsics; + } + { + ansi = ./ansi; + any = ./any; + bool = ./bool; + check = ./check; + context = ./context; + debug = ./debug; + derivation = ./derivation; + dictionary = ./dictionary; + environment = ./environment; + error = ./error; + expression = ./expression; + flake = ./flake; + float = ./float; + function = ./function; + indentation = ./indentation; + integer = ./integer; + lambda = ./lambda; + library = ./library; + list = ./list; + never = ./never; + null = ./null; + number = ./number; + path = ./path; + set = ./set; + string = ./string; + target = ./target; + time = ./time; + type = ./type; + version = ./version; + } diff --git a/libs/core/lib/derivation/default.nix b/libs/core/lib/derivation/default.nix new file mode 100644 index 0000000..570d4d5 --- /dev/null +++ b/libs/core/lib/derivation/default.nix @@ -0,0 +1,75 @@ +{ any, debug, expression, function, intrinsics, never, set, type, ... }: + let + Derivation + = type "Derivation" + { + inherit from fromStrict isInstanceOf isInstanceOf' parseName; + }; + + from + = function "from" + [ any Derivation ] + ( + { name, builder, system, ... } @ drvAttrs: + Derivation.instanciate + ( + if intrinsics ? derivation + then + intrinsics.derivation drvAttrs + else + { + inherit name drvAttrs; + all = never.never; # ToDo! + builder = builder; # ToDo: Check! + drvPath = never.never; # ToDo! + out = never.never; # ToDo! + outPath = never.never; # ToDo! + outputName = "out"; + system = system; # ToDo: Check! + type = "derivation"; + } + ) + ); + + fromStrict + = function "fromStrict" + [ any any ] + ( + { name, builder, system, ... } @ drvAttrs: + Derivation.instanciate + ( + intrinsics.derivationStrict drvAttrs + ) + ); + + isInstanceOf + = value: + let + legacy = isLegacy value; + in + (type.defaultInstanceOf "Derivation" value) + || ( + debug.error "isInstanceOf" + { + text = "Legacy Derivation detected!"; + data = { keys = set.names value; inherit(value) name pname outPath; }; + when = legacy; + } + legacy + ); + + isInstanceOf' + = value: + (type.defaultInstanceOf "Derivation" value) || (isLegacy value); + + isLegacy + = value: + let + value' = expression.tryEval value; + in + value'.value.type or null == "derivation"; + + parseName + = intrinsics.parseDrvName; + in + Derivation diff --git a/libs/core/lib/dictionary/default.nix b/libs/core/lib/dictionary/default.nix new file mode 100644 index 0000000..d1359c9 --- /dev/null +++ b/libs/core/lib/dictionary/default.nix @@ -0,0 +1,344 @@ +{ intrinsics, list, type, ... }: + let + Dictionary + = type "Dictionary" + { + from#: { T... } -> { string -> T } + = dictionary: + Dictionary.instanciate + { + inherit dictionary; + __functor + = { dictionary, ... }: + key: + dictionary.${key} or null; + }; + }; + + filter# (string -> T -> bool) -> { string -> T } -> { string -> T } + = predicate: + filterMap predicate (x: x); + + filterKeys# (string -> bool) -> { string -> T } -> { string -> T } + = predicate: + filter (key: value: predicate key); + + filterMap# (string -> T -> bool) -> (string -> T -> U) -> { string -> T } -> { string -> U } + = predicate: + mapping: + { ... } @ dictionary: + list.fold + ( + { ... } @ dictionary': + { key, value }: + if (predicate key value) + then + dictionary' + // { + ${key} = mapping value; + } + else + dictionary' + ) + {} + (getKeys dictionary); + + filterValues# (T -> bool) -> { string -> T } -> { string -> T } + = predicate: + filter (key: predicate); + + fold#: (S -> { key: string, value: T } -> S) -> S -> { string -> T } -> S + = function: + state: + dictionary: + list.fold function state (toList dictionary); + + fromList#: [ { key: string, value: T } ] -> { string -> T } + = list.fold + ( + { ... } @ dictionary: + { key, value }: + if dictionary.${key} or false != dictionary.${key} or true + then + dictionary + // { + ${key} = value; + } + else + throw "Key »${key}« already in dictionary!" + ) + { }; + + get#: + = intrinsics.getAttr + or ( + key: + dictionary: + dictionary.${key} + ); + + getOr#: string -> { string -> T } -> T -> T + = key: + dictionary: + default: + dictionary.${key} or default; + + getKeys#: { string -> T } -> [ string ] + = intrinsics.attrNames; + + # string -> { ... } -> bool + hasKey#: + = intrinsics.hasAttr + or ( + name: + dictionary: + dictionary.${name} or true == dictionary.${name} or false + ); + + map#: (string -> T -> U) -> { string -> T } -> { string -> U } + = intrinsics.mapAttrs + or ( + mapping: + { ... } @ dictionary: + list.fold + ( + { ... } @ dictionary': + key: + dictionary' + // { + ${key} = mapping key dictionary.${key}; + } + ) + { } + ( getKeys dictionary ) + ); + + new = Dictionary {}; + + toList#: { string -> T } -> [ { key: string, value: T } ] + = dictionary: + list.fold + ( + pairs: + key: + pairs + ++ [ + { + inherit key; + value = dictionary.${key}; + } + ] + ) + [] + (getKeys dictionary); + in + Dictionary + // { + inherit Dictionary; + inherit filter map getKeys; + inherit fromList toList; + } + + /* + + # string -> [ { T... } ] -> [ T ] + # where T: Any + collect + = intrinsics.catAttrs + or ( + name: + pairs: + list.fold + ( + result: + { ... } @ entry: + if hasAttribute name entry + then + result ++ [ entry.${name} ] + else + result + ) + [ ] + pairs + ); + + # { T } -> [ string ] -> { T... } + # where T: Any: + filterByName + = { ... } @ dictionary: + keys: + fromList (list.map (name: { inherit name; value = dictionary.${name}; }) keys); + + filterKeys# F -> { T } -> { T } + # where + # F: string -> bool, + # T: Any + = predicate: + { ... } @ dictionary: + filterByName dictionary (list.filter predicate (names dictionary)); + + filterValue# F -> { T } -> { T } + # where + # F: T -> bool, + # T: Any + = predicate: + { ... } @ dictionary: + filterByName dictionary (list.filter (name: predicate dictionary.${name}) (names dictionary)); + + + + # D -> [ T ] -> { D... } + # where + # F: T -> R, + # T, R: Any: + fromListDefault + = value: + list: + fromList (list.map (name: { inherit name value; })); + + # F -> [ T ] -> { R... } + # where + # F: T -> { name: string, value: R }, + # T, R: Any: + fromListMapped + = function: + list: + fromList (list.map function list); + + # F -> [ T ] -> { R... } + # where + # F: int -> T -> { name: string, value: R }, + # T, R: Any: + fromListIMapped + = function: + list: + fromList (list.imap function list); + + # F -> [ T ] -> { R... } + # where + # F: T -> R, + # T, R: Any: + fromListMappedValue + = function: + list: + fromList (list.map (name: { inherit name; value = function name; }) list); + + # F -> [ T ] -> { R... } + # where + # F: int -> T -> R, + # T, R: Any: + fromListIMappedValue + = function: + list: + fromList (list.imap (index: name: { inherit name; value = function index name; }) list); + + + + + # { ... } -> { ... } -> { ... } + intersect + = intrinsics.intersectAttrs + or ( + left: + right: + list.fold + ( + result: + entry: + if hasAttribute entry right + then + result // { ${entry} = right.${entry}; } + else + result + ) + { } + (names left) + ); + + mapNamesAndValues#: F -> { T... } -> { R... } + # where + # F: string -> T -> { name: string, value: R } + # T, R: Any, + = function: + dictionary: + fromList ( mapToList function dictionary ); + + # F -> { T... } -> { R... } + # where + # F: T -> R, + # T, R: Any: + mapValues + = function: + map + ( + _: + value: + function value + ); + + # F -> { T... } -> [ R ] + # where + # F: string -> T -> R, + # T, R: Any: + mapToList + = function: + { ... } @ dictionary: + values ( map function dictionary ); + + + pair#: n, T @ n:[ string ] -> n:[ T ] -> { T } + = names: + values: + if isList names + && isList values + && length names == length values + then + fromListIMappedValue (index: name: list.get values index) names + else + debug'.panic "pair" "Names and Values must be two lists of same length!"; + + pairNameWithValue + = name: value: { inherit name value; }; + + # { ... } -> [ string ] -> { ... }: + remove + = intrinsics.removeAttrs + or ( + { ... } @ dictionary: + list: + list.fold + ( + result: + name: + if !( find list name ) + then + result + // { + ${name} = dictionary.${name}; + } + else + result + ) + { } + (names dictionary) + ); + + # { T... } -> string -> T + # where T: Any: + select = { ... } @ dictionary: field: dictionary.${field}; + + # { ... } -> [ T ] + # where T: Any + values + = intrinsics.attrValues + or ( + { ... } @ dictionary: + list.map (name: dictionary.${name}) (names dictionary) + ); + in + { + inherit collect filter filterByName filterKeys filterValue fold fromList fromListDefault fromListMapped mapNamesAndValues + fromListMappedValue get getOr hasAttribute intersect map mapToList mapValues names pair pairNameWithValue + remove select values; + } + */ \ No newline at end of file diff --git a/libs/core/lib/environment/default.nix b/libs/core/lib/environment/default.nix new file mode 100644 index 0000000..cc16377 --- /dev/null +++ b/libs/core/lib/environment/default.nix @@ -0,0 +1,12 @@ +{ intrinsics, ... }: + let + # string -> string | null: + get + = intrinsics.getEnv or ( _: null ); + + home = get "HOME"; + user = get "USER"; + in + { + inherit get home user; + } \ No newline at end of file diff --git a/libs/core/lib/error/default.nix b/libs/core/lib/error/default.nix new file mode 100644 index 0000000..d0d6b01 --- /dev/null +++ b/libs/core/lib/error/default.nix @@ -0,0 +1,5 @@ +{ intrinsics, ... }: +{ + panic = intrinsics.throw; + inherit(intrinsics) abort throw; +} \ No newline at end of file diff --git a/libs/core/lib/expression/default.nix b/libs/core/lib/expression/default.nix new file mode 100644 index 0000000..693152d --- /dev/null +++ b/libs/core/lib/expression/default.nix @@ -0,0 +1,4 @@ +{ intrinsics, ... }: +{ + inherit(intrinsics) addErrorContext deepSeq fromJSON fromTOML seq toJSON toXML tryEval; +} \ No newline at end of file diff --git a/libs/core/lib/flake/default.nix b/libs/core/lib/flake/default.nix new file mode 100644 index 0000000..40983d8 --- /dev/null +++ b/libs/core/lib/flake/default.nix @@ -0,0 +1,4 @@ +{ intrinsics, ... }: +{ + get = intrinsics.getFlake; +} \ No newline at end of file diff --git a/libs/core/lib/float/default.nix b/libs/core/lib/float/default.nix new file mode 100644 index 0000000..44ca721 --- /dev/null +++ b/libs/core/lib/float/default.nix @@ -0,0 +1,13 @@ +{ intrinsics, type, ... }: + let + isInstanceOf = intrinsics.isFloat or (value: type.getPrimitive value == "float"); + in + type "float" + { + inherit isInstanceOf; + isPrimitive = true; + + orNull + = value: + isInstanceOf value || value == null; + } diff --git a/libs/core/lib/function/default.nix b/libs/core/lib/function/default.nix new file mode 100644 index 0000000..2e2eaef --- /dev/null +++ b/libs/core/lib/function/default.nix @@ -0,0 +1,89 @@ +{ debug, lambda, library, list, set, string, type, ... }: + let + Function + = type.TypeConstructor "Function" + ( + functionName: + signature: + { + functionName = string.expect functionName; + signature + = debug.panic "Function" + { + text = "Signature must be a list of type with at least two elements!"; + data + = { + inherit functionName signature; + isList = list.isInstanceOf signature; + length = list.length signature; + all = list.all type.isInstanceOf signature; + }; + nice = true; + when + = !(list.isInstanceOf signature) + || (list.length signature < 2) + || !(list.all type.isInstanceOf signature); + } + list.map + ( + argumentType: + { + inherit(argumentType) __traits__ __type__ __variant__ + isInstanceOf mergeWith + expect instanciate instanciateAs; + } + ) + signature; + } + ) + ( + { source, ... }: + { functionName, signature }: + let + call + = { function, signature, ... } @ self: + argument: + let + function' = function ((list.head signature).expect argument); + signature' = list.tail signature; + in + if list.length signature' > 1 + then + self + // { + function = lambda.expect function'; + signature = signature'; + } + else + (list.head signature').expect function'; + from + = function: + self.instanciate + { + inherit signature; + function = lambda.expect function; + __functor = call; + isFunction = true; + source = source'; + }; + self = type "${source'}" { inherit from; }; + source' = source functionName; + in + self + ); + in + library.NeedInitialisation + ( + { ... } @ self: + { source, ... }: + self + // { + inherit source; + } + ) + ( + Function + // { + inherit Function; + } + ) diff --git a/libs/core/lib/indentation/default.nix b/libs/core/lib/indentation/default.nix new file mode 100644 index 0000000..122ea88 --- /dev/null +++ b/libs/core/lib/indentation/default.nix @@ -0,0 +1,90 @@ +{ debug, list, string, type, ... }: + let + Indentation + = type.enum "Indentation" + { + less = null; + more = null; + }; + in + { + inherit(Indentation) less more; + + # string -> string | [ string | bool | null ] -> string + __functor#: self -> string | [ string | Indentation | null ] -> string + = self: + { initial ? "", tab ? " ", ... }: + body: + ( + list.fold + ( + # S -> null | string | bool -> S + # where S: { depth: uint, indent: string, result: string } + { cache, depth, indent, lineNumber, result, tab } @ state: + line: + type.matchPrimitiveOrPanic line + { + null = state; + string + = state + // { + lineNumber = lineNumber + 1; + result = "${result}${indent}${line}\n"; + }; + set + = state + // ( + if Indentation.isInstanceOf line + then + Indentation.match line + { + more + = let + depth' = depth + 1; + cache' + = if list.length cache <= depth' + then + cache ++ [ "${list.foot cache}${tab}" ] + else + cache; + in + { + cache = cache'; + depth = depth'; + indent = list.get cache' depth'; + }; + less + = if depth > 0 + then + let + depth'= depth - 1; + in + { + depth = depth'; + indent= list.get cache depth'; + } + else + debug.panic [] "Cannot indent less than zero." null; + } + else + debug.panic [] "Got set, but either string or Indentation was expected!" null + ); + } + ) + { + cache = [ initial ]; + depth = 0; + indent = initial; + lineNumber = 0; + result = ""; + inherit tab; + } + ( + type.matchPrimitiveOrPanic body + { + list = body; + string = string.splitLines body; + } + ) + ).result; + } diff --git a/libs/core/lib/integer/default.nix b/libs/core/lib/integer/default.nix new file mode 100644 index 0000000..d671484 --- /dev/null +++ b/libs/core/lib/integer/default.nix @@ -0,0 +1,137 @@ +{ bool, debug, expression, float, intrinsics, list, string, type, ... }: + let + inherit(intrinsics) toString; + + abs = x: bool.select (x >= 0) x (-x); + + from#: int | float | string -> int + = value: + type.matchPrimitiveOrDefault value + { + float = float.round' value; + int = value; + string + = let + result = toInteger value; + in + if result != null + then + result + else + debug.panic "from" "Could not convert string ${value} to int!"; + } + ( + debug.panic + "from" + { + text = "Could not convert type ${type.get value} to int!"; + data = value; + } + ); + + isInstanceOf = intrinsics.isInt or (value: type.getPrimitive value == "int"); + + divmod + = value: + modulus: + let + value' = value / modulus; + in + { + value = value'; + rest = value - value' * modulus; + }; + + orNull + = value: + isInstanceOf value || value == null; + + and = intrinsics.bitAnd; + or = intrinsics.bitOr; + xor = intrinsics.bitXor; + + toInteger#: string -> int | null + = value: + let + value' = string.match "([+-])?0*(.+)" value; + result = expression.fromJSON ( list.get value' 1); + sign = list.head value'; + in + if isInstanceOf result + then + if sign == "-" + then + ( 0 - result ) + else + result + else + null; + + formatHexByte + = value: + let + lsNibble = and value 15; + msNibble = value / 16; + in + "${formatHexNibble msNibble}${formatHexNibble lsNibble}"; + + formatHexDWord + = value: + let + lsWord = and value 65535; + msWord = value / 65536; + in + "${formatHexWord msWord}${formatHexWord lsWord}"; + + formatHexNibble = list.get [ "0" "1" "2" "3" "4" "5" "6" "7" "8" "9" "a" "b" "c" "d" "e" "f" ]; + + formatHexQWord + = value: + let + lsDWord = and value 4294967295; + msDWord = value / 4294967296; + in + "${formatHexDWord msDWord}${formatHexDWord lsDWord}"; + + formatHexWord + = value: + let + lsByte = and value 255; + msByte = value / 256; + in + "${formatHexByte msByte}${formatHexByte lsByte}"; + + integer + = type "integer" + { + isPrimitive = true; + + signed + = type "SignedInteger" + { + #isInstanceOf = value: isInstanceOf value; + }; + + unsigned + = type "UnsignedInteger" + { + #isInstanceOf = value: isInstanceOf value && value >= 0; + }; + + inherit abs and divmod from isInstanceOf or orNull toInteger toString xor; + inherit formatHexByte formatHexDWord formatHexNibble formatHexQWord formatHexWord; + formatHexaDecimal + = value: + let + sign = bool.select (value < 0) "-" ""; + value' = abs (integer.expect value); + format + = if value' < 256 then formatHexByte + else if value' < 65536 then formatHexWord + else if value' < 4294967296 then formatHexDWord + else formatHexQWord; + in + "${sign}0x${format value'}"; + }; + in + integer diff --git a/libs/core/lib/lambda/default.nix b/libs/core/lib/lambda/default.nix new file mode 100644 index 0000000..dd1c71f --- /dev/null +++ b/libs/core/lib/lambda/default.nix @@ -0,0 +1,35 @@ +{ intrinsics, type, ... }: + let + arguments#: F -> { bool... } + # where + # F: { ... } -> T, + # T: Any + = intrinsics.functionArgs; + + fixPointOf#: F -> T + # where + # F: T -> T + = self: + let + fixPoint = self fixPoint; + in + fixPoint; + + identity#: T -> T + = x: x; + + isInstanceOf = intrinsics.isFunction; + + orNull + = value: + isInstanceOf value || value == null; + in + type "lambda" + { + isCallable = x: true; + isPrimitive = true; + + fix = fixPointOf; + id = identity; + inherit arguments fixPointOf isInstanceOf orNull; + } \ No newline at end of file diff --git a/libs/core/lib/library/default.nix b/libs/core/lib/library/default.nix new file mode 100644 index 0000000..6532f5d --- /dev/null +++ b/libs/core/lib/library/default.nix @@ -0,0 +1,132 @@ +{ context, debug, path, set, type, ... }: + let + adjustArguments + = { arguments, fileName, moduleName ? null, ... }: + let + source + = arguments.source + { + inherit fileName; + attribute + = if moduleName != null + then + moduleName + else + path.getBaseName fileName; + }; + in + (initialise arguments { inherit fileName moduleName source; }) + // { inherit source; }; + + initialise + = { ... } @ self: + { ... } @ initialisationData: + ( + set.map + ( + name: + module: + if NeedInitialisation.isInstanceOf module + then + debug.debug "initialise" + { + text = "Initialise module ${name}:"; + data = initialisationData; + when = name != "debug"; + } + module.initialise module.body + ( + initialisationData // { inherit name; } + ) + else if Library.isInstanceOf module + then + debug.debug "initialise" + { + text = "Initialise library ${name}:"; + data = initialisationData; + } + initialise module + ( + initialisationData // { inherit name; } + ) + else + module + ) + self + ) // { isInitialised = true; }; + + Library + = type "Library" + { + inherit adjustArguments initialise; + + from + = libraryName: + { ... } @ environment: + { ... } @ modules: + let + __functor + = this: + { self, ... } @ initialisationData: + initialise this + ( + environment + // initialisationData + // { + source = context self.outPath; + } + ); + arguments + = library + // environment + // { + source = context libraryName; + }; + library + = ( + set.map + ( + moduleName: + fileName: + path.import fileName + (adjustArguments { inherit arguments fileName moduleName; }) + ) + modules + ) + // { + inherit __functor; + isInitialised = false; + }; + in + Library.instanciateAs libraryName library; + + import + = fileName: + arguments: + path.import fileName + (adjustArguments { inherit arguments fileName; }); + + load + = fileName: + path.importScoped { inherit Library; } fileName; + }; + + NeedInitialisation + = type "NeedInitialisation" + { + from + = initialise: + body: + NeedInitialisation.instanciate + { + inherit body initialise; + __functor + = { initialise, body, ... }: + initialise body; + }; + }; + in + Library + // { + inherit Library NeedInitialisation; + } diff --git a/libs/core/lib/list/default.nix b/libs/core/lib/list/default.nix new file mode 100644 index 0000000..d71a24e --- /dev/null +++ b/libs/core/lib/list/default.nix @@ -0,0 +1,567 @@ +{ debug, intrinsics, library, path, type, ... } @ libs: + let + all#: T, F: T -> bool @ F -> [ T ] -> bool + = intrinsics.all + or ( + predicate: + fold + ( + state: + entry: + state && ( predicate entry ) + ) + true + ); + + any#: T, F: T -> bool @ F -> [ T ] -> bool + = intrinsics.any + or ( + predicate: + fold + ( + state: + entry: + state || ( predicate entry ) + ) + false + ); + + body#: T @ [ T ] -> [ T ] | ! + = self: + generate + ( index: get self index ) + ( ( length self ) - 1 ); + + bodyOr#: T, D @ [ T ] -> D -> [ T ] | [ D ] + = self: + default: + if isEmpty self + then + [ default ] + else + body self; + + call + = argument: + map (value: value argument); + + chain# T, U @ [ T ] -> [ U ] -> [ T | U ] + = left: + right: + left ++ right; + + # F -> [ T ] -> [ U ] -> [ R ] + # where + # F: T -> U -> R, + # T, U, R: Any: + combine + = operator: + left: + right: + concatMap (value: map (value': operator value value') right) left; + + # F -> [ T ] -> [ T ] -> [ T ] + # where + # F: T -> T -> int, /* -1: l < r, 0: l == r, 1: l > r */ + # T: Ordable: + compare + = compareElements: + left: + right: + let + compareLists + = compare: + left: + right: + len: + ( + fold + ( + result: + index: + if result == 0 + then + compareElements + (get left index) + (get right index) + else + result + ) + 0 + ( range 0 len ) + ).result; + lengthLeft = length left; + lengthRight = length right; + in + if lengthLeft == lengthRight + then + compareLists compare left right lengthRight + else if lengthLeft > lengthRight + then + let + result = compareLists compare left right lengthRight; + in + if result == 0 then 1 else result + else + let + result = compareLists compare left right lengthLeft; + in + if result == 0 then (-1) else result; + + # [ [ T ] ] -> [ T ] + # where T: Any: + concat + = intrinsics.concatLists + or ( + fold + ( + result: + entry: + result ++ entry + ) + [ ] + ); + + # F -> [ T ] -> [ U ] + # where + # F: integer -> T -> U, + # T, U: Any: + concatIMap + = convert: + self: + concat ( imap convert self ); + + # F -> [ T ] -> [ U ] + # where + # F: T -> U, + # T, U: Any: + concatMap + = intrinsics.concatMap + or ( + convert: + self: + concat ( map convert self ) + ); + + # int -> [ null ]: + empty + = generate (_: null); + + # F -> [ T ] -> [ T ] + # where + # F: T -> bool, + # T: Any: + filter + = intrinsics.filter + or ( + predicate: + fold + ( + result: + entry: + if predicate entry + then + result ++ [ entry ] + else + result + ) + [ ] + ); + + # [ T ] -> T -> bool + # where T: Any: + find + = intrinsics.elem + or ( + self: + value: + if isEmpty self then false + else if head self == value then true + else find (tail self) value + ); + + flat#: T, U: ![ ... ] @ [ [ T ] | U ] -> [ T | U ] + = fold + ( + result: + entry: + if isInstanceOf entry + then + result ++ entry + else + result ++ [ entry ] + ) + [ ]; + + flatDeep#: T, U: ![ ... ] @ [ [ T ] | U ] -> [ U ] + = fold + ( + result: + entry: + if isInstanceOf entry + then + result ++ ( flatDeep entry ) + else + result ++ [ entry ] + ) + [ ]; + + # F -> S -> [ T ] -> S + # where + # F: S -> T -> S, + # S, T: Any: + fold + = fold'; + + # F -> S -> [ T ] -> S + # where + # F: S -> T -> S, + # S, T: Any: + fold' + = intrinsics.foldl' + or ( + next: + init: + self: + if self != [ ] + then + fold' + next + ( next init ( head self ) ) + ( tail self ) + else + init + ); + + # F -> S -> [ T ] -> S + # where + # F: S -> T -> S, + # S, T: Any: + foldReversed + = let + fold' + = next: + init: + self: + if self != [ ] + then + fold' + next + ( next init ( foot self ) ) + ( body self ) + else + init; + in + fold'; + + # [ T ] -> T + # where T: Any: + foot + = self: + get self (length self - 1); + + # [ T... ] | [ ] -> D -> T | D + # where T, D: Any: + footOr + = self: + default: + if isEmpty self + then + default + else + foot self; + + # F -> int -> [ T ] + # where F: int -> T: + generate + = intrinsics.genList + or ( + generator: + let + generate' + = len: + index: + if len > 0 + then + [ ( generator index ) ] + ++ ( generate' ( len - 1 ) ( index + 1 ) ) + else + [ ]; + in + len: + generate' len 0 + ); + + genericClosure = intrinsics.genericClosure; + + # [ T ] -> int -> T: + get = intrinsics.elemAt; + + # F -> [ T ] -> { ... } + # where + # F: T -> string, + # T: Any: + groupBy + = intrinsics.groupBy + or ( + toName: + fold + ( + result: + entry: + let + name = toName entry; + in + result + // { + ${name} + = ( result.${name} or [ ] ) + ++ [ entry ]; + } + ) + { } + ); + + # [ T ] -> T + # where T: Any: + head + = intrinsics.head + or ( + self: + get self 0 + ); + + # [ T ... ] | [ ] -> D -> T | D + # where T, D: Any: + headOr + = self: + default: + if isEmpty self + then + default + else + head self; + + ifOrEmpty + = condition: + value: + if condition + then + [ value ] + else + [ ]; + + ifOrEmpty' + = condition: + value: + if condition + then + if isInstanceOf value + then + value + else + [ value ] + else + []; + + # F -> [ T ] -> [ R ] + # where + # F: int -> T -> R, + # T, R: Any: + imap + = convert: + self: + generate (index: convert index (get self index)) (length self); + + # F -> [ T ] -> { string -> U } + # where + # F: T -> { name: string, value: U }, + # T, U: Any: + imapValuesToSet + = convert: + self: + toSet (generate (index: convert index (get self index)) (length self)); + + isEmpty#: T @ [ T ] -> bool + = self: self == [ ]; + + isInstanceOf = intrinsics.isList; + + length#: T @ [ T ] -> int + = intrinsics.length; + + # F -> [ T ] -> [ U ] + # where + # F: T -> U, + # T, U: Any: + map + = intrinsics.map + or ( + convert: + self: + generate (index: convert (get self index)) (length self) + ); + + # F -> [ string ] -> { string -> T } + # where + # F: string -> T, + # T: Any: + mapNamesToSet + = convert: + names: + toSet (map (name: { inherit name; value = convert name; }) names); + + # F -> [ T ] -> { string -> U } + # where + # F: T -> { name: string, value: U }, + # T, U: Any: + mapValuesToSet + = convert: + self: + toSet (map convert self); + + # [ T ] where T: Any: + new = []; + + optional#: T | null -> [ T ] + = value: + if value != null + then + [ value ] + else + [ ]; + + optional'#: T | null -> [ T ] + = value: + if isInstanceOf value + then + value + else + optional value; + + orNull + = value: + isInstanceOf value || value == null; + + # F -> [ T ] -> { right: [ T ], wrong: [ T ] } + # where + # F: T -> bool, + # T: Any: + partition + = intrinsics.partition + or ( + predicate: + groupBy + ( + value: + if predicate value + then + "right" + else + "wrong" + ) + ); + + range#: int -> int -> [ int ] + = from: + till: + generate (x: x + from) (till - from + 1); + + # [ T ] -> [ T ] + # where T: Any: + reverse + = self: + let + len = ( length self ) - 1; + in + generate (x: get self ( len - x)) self; + + sort = intrinsics.sort; + + sorting = library.import ./sorting.nix libs; + + # [ T ] -> [ T ] + # where T: Any: + tail + = intrinsics.tail + or ( + self: + generate + ( index: get self ( index + 1 ) ) + ( ( length self ) - 1 ) + ); + + # [ ... ] | [ ] -> D -> [ ... ] | D + # where T, D: Any: + tailOr + = self: + default: + if isEmpty self + then + default + else + tail self; + + # [ { name: string, value: T } ] -> { T... } + # where T: Any: + toSet + = intrinsics.listToAttrs + or ( + fold + ( + result: + { name, value }: + result // { ${name} = value; } + ) + { } + ); + + # [ T ] -> [ U ] -> [ [ T U ] ] + # where T, U: Any: + zip + = left: + right: + generate (x: [ (get left x) (get right x) ] ) (length left); + + + zipWith#: F -> [ T ] -> [ U ] -> [ V ] + # where + # F: T -> U -> V, + # T, U, V: Any + = combine: + left: + right: + generate (x: combine (get left x) (get right x) ) (length left); + in + type "list" + { + isPrimitive = true; + of + = subtype: + let + __inner__ = type.expect subtype; + in + type "SetOf" + { + isInstanceOf = value: isInstanceOf value && all (_: __inner__.isInstanceOf) value; + inherit __inner__; + }; + + inherit all any + body bodyOr + call chain combine compare concat concatIMap concatMap + empty + filter find flat flatDeep fold fold' foldReversed foot footOr + generate genericClosure get groupBy + head headOr + ifOrEmpty ifOrEmpty' imapValuesToSet isEmpty imap isInstanceOf + length + map mapNamesToSet mapValuesToSet + new + optional optional' orNull + partition + range reverse + sort sorting + tail tailOr toSet + zip zipWith; + } diff --git a/libs/core/lib/list/sorting.nix b/libs/core/lib/list/sorting.nix new file mode 100644 index 0000000..15960f1 --- /dev/null +++ b/libs/core/lib/list/sorting.nix @@ -0,0 +1,120 @@ +{ list, type, ... }: + let + # F -> [ T ] -> [ T ] + # where + # F: T -> T -> bool, + # T: Any: + funnySort + = let + maxInsertion = 20; + in + lessThan: + parts: + let + len = list.length parts; + in + if len < 2 + then + # Empty list or just one element + parts + else if len <= maxInsertion + then + # Insertion Sort, average: O(n²), maximum is O(400), so…fine? + insertionSort lessThan parts + else + # Merge Sort, average: O(n log(n)) + mergeSort lessThan parts; + + # F -> [ T ] -> [ T ] + # where + # F: T -> T -> bool, + # T: Any: + insertionSort + = let + # F -> T -> [ T ] -> [ T ] + # where + # F: T -> T -> bool, + # T: Any + insert + = lessThan: + first: + rest: + if rest == [ ] + then + [ first ] + else + let + second = list.head rest; + in + if lessThan first second + then + [ first ] ++ rest + else + [ second ] ++ (insert lessThan first (list.tail rest)); + in + lessThan: + parts: + if parts == [ ] + then + [ ] + else + insert lessThan (list.head parts) (insertionSort (list.tail parts)); + + # F -> [ T ] -> [ T ] + # where + # F: T -> T -> bool, + # T: Any: + mergeSort + = lessThan: + parts: + let + len = list.length parts; + half = len / 2; + half' = len - half; + left = list.generate (x: list.get parts x ) half; + right = list.generate (x: list.get parts ( x + half ) ) half'; + in + ( + list.fold + ( + { done, left ? null, right ? null, result } @ state: + _: + if done + then + state + else if left == [ ] + then + { + done = true; + result = result ++ right; + } + else if right == [ ] + then + { + done = true; + result = result ++ left; + } + else if lessThan (list.head left) (list.head right) + then + { + inherit right; + left = list.tail left; + result = result ++ (list.head left); + } + else + { + inherit left; + right = list.tail right; + result = result ++ (list.head right); + } + ) + { + done = false; + left = funnySort lessThan left; + right = funnySort lessThan right; + result = [ ]; + } + (list.empty len) + ).result; + in + { inherit funnySort insertionSort mergeSort; } diff --git a/libs/core/lib/never/default.nix b/libs/core/lib/never/default.nix new file mode 100644 index 0000000..00fc860 --- /dev/null +++ b/libs/core/lib/never/default.nix @@ -0,0 +1,6 @@ +{ error, type, ... } @ core: + type "never" + { + isInstanceOf = x: false; + #never = error.panic "Cannot assign the bottom type to anything!"; + } \ No newline at end of file diff --git a/libs/core/lib/null/default.nix b/libs/core/lib/null/default.nix new file mode 100644 index 0000000..4502468 --- /dev/null +++ b/libs/core/lib/null/default.nix @@ -0,0 +1,17 @@ +{ intrinsics, type, ... }: + type "null" + { + isInstanceOf = value: value == null; + isPrimitive = true; + + default + = value: + other: + if value != null + then + value + else + other; + + inherit(intrinsics) null; + } \ No newline at end of file diff --git a/libs/core/lib/number/default.nix b/libs/core/lib/number/default.nix new file mode 100644 index 0000000..e4abea4 --- /dev/null +++ b/libs/core/lib/number/default.nix @@ -0,0 +1,287 @@ +{ debug, expression, float, integer, intrinsics, list, string, type, ... }: + let + assertNumber#: int | float -> int | float | ! + = value: + matchNumber value + { + float = value; + int = value; + }; + + matchNumber#: T -> { int: R, float: R } -> R | ! + # where T, R: Any + = value: + { int, float } @ select: + type.matchPrimitiveOrDefault + value + select + ( debug.panic "matchNumber" "Value is not a number: Neither int nor float!" ); + + abs#: int | float -> int | float + = value: + let + value' = assertNumber value; + in + if value' < 0 + then + ( 0 - value' ) + else + value'; + + add#: int | float -> int | float -> int | float + = intrinsics.add or (a: b: ( assertNumber a ) + ( assertNumber b )); + + and#: int -> int -> int + = intrinsics.bitAnd; + + ceil#: int | float -> int + = intrinsics.ceil; + + div#: int | float -> int | float -> int | float + = intrinsics.div or (a: b: ( assertNumber a ) / ( assertNumber b )); + + floor#: int | float -> int + = intrinsics.floor; + + isInstanceOf + = value: + integer.isInstanceOf value + || float.isInstanceOf value; + + lessThan#: int | float -> int | float -> int | float + = intrinsics.lessThan or (a: b: ( assertNumber a ) < ( assertNumber b )); + + moreThan#: int | float -> int | float -> int | float + = a: b: ( assertNumber a ) > ( assertNumber b ); + + mul#: int | float -> int | float -> int | float + = intrinsics.mul or (a: b: ( assertNumber a ) * ( assertNumber b )); + + neg#: int | float -> int | float + = value: ( 0 - ( assertNumber value ) ); + + or#: int -> int -> int + = intrinsics.bitOr; + + orNull + = value: + isInstanceOf value || value == null; + + pow#: int -> int | float -> int | float + = let + pow#: int -> int | float -> int | float + = base: + exp: + list.fold + (y: x: x*y) + 1.0 + (list.generate (x: base) exp); + in + base: + exp: + if exp < 0.0 + then + pow ( 1.0 / base ) ( 0 - exp ) + else + pow ( 1.0 * base ) exp; + + round#: int | float -> int + = value: + #debug.info "round" { data = { inherit value; value' = value + 0.5; round = floor ( value + 0.5 ); }; } + matchNumber value + { + int = value; + float = round' value; + }; + + round'#: float -> int + = value: floor ( value + 0.5 ); + + sub#: int | float -> int | float -> int | float + = intrinsics.sub or (a: b: (assertNumber a) - (assertNumber b)); + + sum#: [ int | float ] -> int | float + = list.fold (result: value: result + value) 0; + + toFloat#: int | float | string -> float + = value: + type.matchPrimitiveOrDefault value + { + int = 1.0 * value; + float = value; + /*string + = let + parts = string.match "([0-9]*)[.](0*)([0-9]*)" value; + len = string.length parts.dec; + in + ( ( 1.0 * ( toInteger parts.dec ) ) / ( pow 10 len ) ) + + ( toInteger parts.int );*/ + } + ( debug.panic "toFloat" "Cannot convert ${type.getPrimitive value} to float." ); + + toInteger#: int | float | string -> int + = value: + type.matchPrimitiveOrDefault value + { + float = round' value; + int = value; + string + = let + result = toInteger' value; + in + if result != null + then + result + else + debug.panic "toInteger" "Could not convert string ${value} to int!"; + } + ( debug.panic "toInteger" "Could not convert type ${type value} to int!" ); + + toInteger'#: string -> int | null + = value: + let + value' = string.match "([+-])?0*([0-9.][0-9]+)" value; + result = expression.fromJSON ( list.get value' 1); + sign = list.head value'; + in + if value' != null + && integer.isInstanceOf result + then + if sign == "-" + then + ( - result ) + else + result + else + null; + + toStringWithMaximumPrecision#: int | float -> int -> string + = value: + precision: + if precision > 0 + then + list.foldReversed + ( + state: + character: + if state != null then "${character}${state}" + else if character == "." then "" + else if character != "0" then character + else null + ) + null + ( string.toCharacters ( toStringWithPrecision value precision ) ) + else + toStringWithPrecision value precision; + + splitFloat + = value: + precision: + let + factor = pow 10 precision; + value' = string ( round ( value * factor ) ); + length = string.length value'; + padding = string.concat (list.generate (_: "0") (precision - length)); + in + debug.debug "splitFloat" + { + text = "called with/calculated:"; + data + = { + inherit value precision factor value' length; + }; + } + ( + if length > precision + then + let + mid = length - precision; + integer = string.slice 0 mid value'; + decimal = string.slice mid precision value'; + in + debug.debug "splitFloat" + { + text = "length > precision"; + data = { inherit integer decimal mid; }; + } + { inherit decimal integer; } + else + let + integer = "0"; + decimal = "${padding}${value'}"; + in + debug.debug "splitFloat" + { + text = "length <= precision"; + data = { inherit integer decimal padding; }; + } + { inherit decimal integer; } + ); + + toStringWithPrecision#: int | float -> int -> string + = value: + precision: + let + precision' + = type.matchPrimitiveOrDefault precision + { + int = precision; + null = getPrecision value; + } + ( debug.panic "toStringWithPrecision" "Invalid Precision: Int or null expected!" ); + valuePos = splitFloat (0.0 + value) precision'; + valueNeg = splitFloat (0.0 - value) precision'; + valueWithPrecision + = debug.info "toStringWithPrecision" { text = "value"; data = value; } + debug.info "toStringWithPrecision" { text = "precision"; data = [ precision precision' ]; } + ( + if precision' == 0 + then + "${string (round value)}" + else if value >= 0 + then + "${valuePos.integer}.${valuePos.decimal}" + else + "-${valueNeg.integer}.${valueNeg.decimal}" + ); + in + type.matchPrimitiveOrDefault value + { + float = valueWithPrecision; + int = valueWithPrecision; + list = string.concatMappedWith (x: toStringWithPrecision x precision) ", " value; + set + = ( + { from, till }: + "${toStringWithPrecision from precision}–${toStringWithPrecision till precision}" + ) + value; + } + ( debug.panic "toStringWithPrecision" "Value must be a numeric value like int or float!" ); + + toSignificantString#: int | float -> string + = value: + toStringWithPrecision value null; + + getPrecision + = value: + debug.info "getPrecision" { text = "value"; data = value; } + ( + if value == 0.0 + || value >= 2.0 + || value <= -2.0 + then + 0 + else + (getPrecision (value * 10)) + 1 + ); + + xor#: int -> int -> int + = intrinsics.bitXor; + in + type "number" + { + inherit isInstanceOf orNull; + inherit abs add and ceil div floor lessThan moreThan mul neg or pow round round' sub sum xor; + inherit toFloat toInteger toInteger' toSignificantString toStringWithMaximumPrecision toStringWithPrecision; + } diff --git a/libs/core/lib/operators/default.nix b/libs/core/lib/operators/default.nix new file mode 100644 index 0000000..7fff99e --- /dev/null +++ b/libs/core/lib/operators/default.nix @@ -0,0 +1,129 @@ +{ debug, intrinsics, number, type, ... }: +{ + add + = x: + y: + if number.isInstanceOf x + && number.isInstanceOf Y + then + intrinsic.add x y + else + debug.panic "add" + { + text = "Cannot add ${type.get x} with ${type.get y}:"; + data = { inherit x y; }; + }; + and + = x: + y: + if bool.isInstanceOf x + && bool.isInstanceOf Y + then + x && y + else + debug.panic "and" + { + text = "Cannot and ${type.get x} with ${type.get y}:"; + data = { inherit x y; }; + }; + div + = x: + y: + if number.isInstanceOf x + && number.isInstanceOf Y + then + intrinsic.div x y + else + debug.panic "div" + { + text = "Cannot divide ${type.get x} with ${type.get y}:"; + data = { inherit x y; }; + }; + equal + = x: + y: + if number.isInstanceOf x + && number.isInstanceOf Y + then + x == y + else + debug.panic "equal" + { + text = "Cannot compare ${type.get x} with ${type.get y}:"; + data = { inherit x y; }; + }; + lessThan + = x: + y: + if number.isInstanceOf x + && number.isInstanceOf Y + then + intrinsic.lessThan x y + else + debug.panic "lessThan" + { + text = "Cannot compare ${type.get x} with ${type.get y}:"; + data = { inherit x y; }; + }; + mul + = x: + y: + if number.isInstanceOf x + && number.isInstanceOf Y + then + intrinsic.sub x y + else + debug.panic "mul" + { + text = "Cannot multiply ${type.get x} with ${type.get y}:"; + data = { inherit x y; }; + }; + neg + = x: + if number.isInstanceOf x + then + 0 - x + else + debug.panic "neg" + { + text = "Cannot negate ${type.get x}:"; + data = { inherit x; }; + }; + not + = x: + if bool.isInstanceOf x + then + !x + else + debug.panic "not" + { + text = "Cannot not ${type.get x}:"; + data = { inherit x; }; + }; + or + = x: + y: + if bool.isInstanceOf x + && bool.isInstanceOf Y + then + x || y + else + debug.panic "or" + { + text = "Cannot or ${type.get x} with ${type.get y}:"; + data = { inherit x y; }; + }; + sub + = x: + y: + if number.isInstanceOf x + && number.isInstanceOf Y + then + intrinsic.sub x y + else + debug.panic "sub" + { + text = "Cannot subtract ${type.get x} with ${type.get y}:"; + data = { inherit x y; }; + }; +} \ No newline at end of file diff --git a/libs/core/lib/path/default.nix b/libs/core/lib/path/default.nix new file mode 100644 index 0000000..ee8fafb --- /dev/null +++ b/libs/core/lib/path/default.nix @@ -0,0 +1,110 @@ +{ debug, intrinsics, list, number, set, string, type, ... } @ libs: + let + exists#: path -> bool + = intrinsics.pathExists; + + fetchGit#: { ... } -> path + = intrinsics.fetchGit; + + fetchMercurial#: { ... } -> path + = intrinsics.fetchMercurial; + + fetchTarball#: { ... } -> path + = intrinsics.fetchTarball; + + fetchURL#: string | { url: string, sha256: string } -> path + = intrinsics.fetchurl; + + filterSource#: (path -> string -> bool) -> path -> path + = intrinsics.filterSource; + + find + = intrinsics.findFile; + + from#: path | { path: path, name: string?, filter: F?, recursive: bool = true, sha256: string? } | ToString -> path + = this: + if isInstanceOf this + then + this + else if set.isInstanceOf this + && this ? path + && intrinsics ? path + then + intrinsics.path this + else + ./${string this}; + + fromSet#: string -> (string -> T -> string) -> { string -> T } -> path + = fileName: + converter: + { ... } @ dictionary: + toFile fileName ( string.concat ( set.values ( set.map converter dictionary ) ) ); + + getBaseName#: path -> string + = intrinsics.baseNameOf; + + getDirectory#: path -> string + = intrinsics.dirOf; + + getPlaceholder#: string -> string + = intrinsics.placeholder; + + hash#: string -> path -> string + = intrinsics.hashFile; + + import#: path -> any + = fileName: + intrinsics.scopedImport + (intrinsics.import ./scope.nix libs fileName) + fileName; + + import' = intrinsics.import; + + importScoped#: path -> { ... } -> any + = { ... } @ scope: + fileName: + intrinsics.scopedImport + ((intrinsics.import ./scope.nix libs fileName) // scope) + fileName; + + isInstanceOf = intrinsics.isPath or (value: type.getPrimitive value == "path"); + + nixPaths#: [ { path: string, prefix: string } ]? + = intrinsics.nixPath or null; + + orNull + = value: + isInstanceOf value || value == null; + + readDirectory#: path -> { string -> string } + = intrinsics.readDir; + + readFile#: path -> string + = intrinsics.readFile; + + storeDirectory#: string? + = intrinsics.storeDir or null; + + storePath#: path -> string + = intrinsics.storePath; + + toFile#: string -> string -> path + = intrinsics.toFile; + + toStore#: path -> string + = file: + if isInstanceOf file + then + "${file}" + else + debug.panic "toStore" "Path expected!"; + in + type "path" + { + isPrimitive = true; + + inherit(intrinsics) path; + + inherit getBaseName getDirectory exists fetchGit fetchTarball fetchURL filterSource find from fromSet getPlaceholder hash import + import' importScoped isInstanceOf nixPaths orNull readDirectory readFile storeDirectory storePath toFile toStore; + } diff --git a/libs/core/lib/path/scope.nix b/libs/core/lib/path/scope.nix new file mode 100644 index 0000000..0fd2848 --- /dev/null +++ b/libs/core/lib/path/scope.nix @@ -0,0 +1,168 @@ +{ debug, intrinsics, list, set, string, ... } @ libs: +fileName: + set.map + ( + key: + value: + if list.isInstanceOf value + then + debug.warn [ fileName key ] + "Use .${string.concatWith "." value} instead!" + ( + list.fold + (libs: name: libs.${name}) + libs + value + ) + else + value + ) + { + __add + = x: + y: + debug.trace [ fileName "(+)" ] + { + text = "Add"; + data = { inherit x y; }; + } + (intrinsics.add x y); + __addErrorContext = [ "expression" "addErrorContext" ]; + __all = [ "list" "all" ]; + __any = [ "list" "any" ]; + __appendContext = [ "string" "appendContext" ]; + __attrNames = [ "set" "names" ]; + __attrValues = [ "set" "values" ]; + __bitAnd = [ "integer" "and" ]; + __bitOr = [ "integer" "or" ]; + __bitXor = [ "integer" "xor" ]; + __catAttrs = [ "set" "collect" ]; + __ceil = [ "number" "ceil" ]; + __compareVersions = [ "version" "compare" ]; + __concatLists = [ "list" "concat" ]; + __concatMap = [ "list" "concatMap" ]; + __concatStringsSep = [ "string" "concatWith" ]; + __currentSystem = debug.error [ fileName "__currentSystem" ] "Unavailable in flake!" null; + __currentTime = debug.error [ fileName "__currentTime" ] "Unavailable in flake!" null; + __deepSeq = [ "expression" "deepSeq" ]; + __div + = x: + y: + debug.trace [ fileName "(/)" ] + { + text = "Divide"; + data = { inherit x y; }; + } + (intrinsics.div x y); + __elem = [ "list" "find" ]; + __elemAt = [ "list" "get" ]; + __fetchurl = [ "path" "fetchURL" ]; + __filter = [ "list" "filter" ]; + __filterSource = [ "path" "filterSource" ]; + __findFile = [ "path" "find" ]; + __floor = [ "number" "floor" ]; + __foldl' = [ "list" "fold" ]; + __fromJSON = [ "expression" "fromJSON" ]; + __functionArgs = [ "lambda" "arguments" ]; + __genList = [ "list" "generate" ]; + __genericClosure = [ "list" "genericClosure" ]; + __getAttr = [ "set" "get" ]; + __getContext = [ "string" "getContext" ]; + __getEnv = [ "environment" "get" ]; + __getFlake = [ "flake" "get" ]; + __groupBy = [ "list" "groupBy" ]; + __hasAttr = [ "set" "hasAttribute" ]; + __hasContext = [ "string" "hasContext" ]; + __hashFile = [ "path" "hash" ]; + __hashString = [ "string" "hash" ]; + __head = [ "list" "head" ]; + __intersectAttrs = [ "set" "intersect" ]; + __isAttrs = [ "set" "isInstanceOf" ]; + __isBool = [ "bool" "isInstanceOf" ]; + __isFloat = [ "float" "isInstanceOf" ]; + __isFunction = [ "lambda" "isInstanceOf" ]; + __isInt = [ "integer" "isInstanceOf" ]; + __isList = [ "list" "isInstanceOf" ]; + __isPath = [ "path" "isInstanceOf" ]; + __isString = [ "string" "isInstanceOf" ]; + __langVersion = [ "version" "language" ]; + __length = [ "list" "length" ]; + __lessThan + = x: + y: + debug.trace [ fileName "(<)" ] + { + text = "Less Than"; + data = { inherit x y; }; + } + (intrinsics.lessThan x y); + __listToAttrs = [ "list" "toSet" ]; + __mapAttrs = [ "set" "map" ]; + __match = [ "string" "match" ]; + __mul + = x: + y: + debug.trace [ fileName "(*)" ] + { + text = "Multiply"; + data = { inherit x y; }; + } + (intrinsics.mul x y); + __nixPath = [ "path" "nixPaths" ]; + __nixVersion = [ "version" "nix" ]; + __parseDrvName = [ "derivation" "parseName" ]; + __partition = [ "list" "partition" ]; + __path = [ "path" "path" ]; + __pathExists = [ "path" "exists" ]; + __readDir = [ "path" "readDirectory" ]; + __readFile = [ "path" "readFile" ]; + __replaceStrings = [ "string" "replace" ]; + __seq = [ "expression" "seq" ]; + __sort = [ "list" "sort" ]; + __split = [ "string" "split" ]; + __splitVersion = [ "version" "split" ]; + __storeDir = [ "path" "storeDirectory" ]; + __storePath = [ "path" "storePath" ]; + __stringLength = [ "string" "length" ]; + __sub + = x: + y: + debug.trace [ fileName "(-)" ] + { + text = "Subtract"; + data = { inherit x y; }; + } + (intrinsics.sub x y); + __substring = [ "string" "slice" ]; + __tail = [ "list" "tail" ]; + __toFile = [ "path" "toFile" ]; + __toJSON = [ "expression" "toJSON" ]; + __toPath = debug.warn [ fileName "__toPath" ] "Deprecated, use `/. + \"/absolute/path\"`!" (x: /. + x); + __toXML = [ "expression" "toXML" ]; + __trace = debug.warn [ fileName "__trace" ] "Use printers of .debug instead!" intrinsics.trace; + __tryEval = [ "expression" "tryEval" ]; + __typeOf = [ "type" "getPrimitive" ]; + __unsafeDiscardOutputDependency = [ "string" "discardOutputDependency" ]; + __unsafeDiscardStringContext = [ "string" "discardContext" ]; + __unsafeGetAttrPos = [ "set" "getKeySource" ]; + __zipAttrsWith = [ "set" "zip" ]; + abort = [ "error" "abort" ]; + baseNameOf = [ "path" "getBaseName" ]; + builtins = debug.warn [ fileName "builtins" ] "Use instead!" intrinsics; + derivation = [ "derivation" ]; + derivationStrict = [ "derivation" "fromStrict" ]; + dirOf = [ "path" "getDirectory" ]; + fetchGit = [ "path" "fetchGit" ]; + fetchMercurial = [ "path" "fetchMercurial" ]; + fetchTarball = [ "path" "fetchTarball" ]; + fetchTree = [ "path" "fetchTree" ]; + fromTOML = [ "expression" "fromTOML" ]; + import = [ "path" "import" ]; + isNull = debug.warn [ fileName "isNull" ] "Deprecated, use `x == null`!" (x: x == null); + map = [ "list" "map" ]; + placeholder = [ "path" "getPlaceholder" ]; + removeAttrs = [ "set" "remove" ]; + scopedImport = [ "path" "importScoped" ]; + throw = [ "error" "throw" ]; + toString = [ "string" "toString" ]; + } \ No newline at end of file diff --git a/libs/core/lib/set/default.nix b/libs/core/lib/set/default.nix new file mode 100644 index 0000000..6549f82 --- /dev/null +++ b/libs/core/lib/set/default.nix @@ -0,0 +1,425 @@ +{ debug, intrinsics, list, type, ... }: + let + all + = predicate: + dictionary: + (partition predicate dictionary).wrong == {}; + + all' + = predicate: + dictionary: + (partition' predicate dictionary).wrong == {}; + + any + = predicate: + dictionary: + (partition predicate dictionary).right != {}; + + any' + = predicate: + dictionary: + (partition' predicate dictionary).right != {}; + + callValues + = argument: + mapValues (value: value argument); + + # string -> [ { T... } ] -> [ T ] + # where T: Any + collect + = intrinsics.catAttrs; + + filter# F -> { T } -> { T } + # where + # F: string -> T -> bool, + # T: Any + = predicate: + { ... } @ self: + (partition predicate self).right; + + # { T } -> [ string ] -> { T... } + # where T: Any: + filterByName + = { ... } @ self: + keys: + fromList + ( + list.map + ( + name: + { + inherit name; + value = self.${name}; + } + ) + keys + ); + + filterKeys# F -> { T } -> { T } + # where + # F: string -> bool, + # T: Any + = predicate: + { ... } @ self: + (partitionByName predicate self).right; + + filterValue# F -> { T } -> { T } + # where + # F: T -> bool, + # T: Any + = predicate: + { ... } @ self: + (partitionByValue predicate self).right; + + # F -> S -> { T... } -> S + # where + # F: S -> string -> T -> S, + # T, S: Any: + fold + = next: + state: + { ... } @ self: + list.fold + ( + state: + name: + next state name self.${name} + ) + state + ( names self ); + + # F -> S -> { T... } -> S + # where + # F: S -> { name: string; value: T; } -> S, + # T, S: Any: + fold' + = next: + fold + ( + state: + name: + value: + next + state + { inherit name value; } + ); + + # F -> S -> { T... } -> S + # where + # F: S -> string -> T -> S, + # T, S: Any: + foldValues + = next: + state: + { ... } @ self: + list.fold + ( + state: + name: + next state self.${name} + ) + state + ( names self ); + + # [ { name: string, value: T } ] -> { string -> T } + # where T: Any: + fromList + = intrinsics.listToAttrs; + + # D -> [ string ] -> { string -> D } + fromListDefault + = value: + listOfKeys: + fromList + ( + list.map + (name: { inherit name value; }) + listOfKeys + ); + + # F -> [ T ] -> { R... } + # where + # F: int -> T -> { name: string, value: R }, + # T, R: Any: + fromListIMapped + = convert: + input: + fromList (list.imap convert input); + + # F -> [ T ] -> { R... } + # where + # F: int -> T -> R, + # T, R: Any: + fromListIMappedValue + = convert: + input: + fromList + ( + list.imap + ( + index: + name: + { + inherit name; + value = convert index name; + } + ) + input + ); + + # F -> [ T ] -> { R... } + # where + # F: T -> { name: string, value: R }, + # T, R: Any: + fromListMapped + = convert: + keyValuePairs: + fromList (list.map convert keyValuePairs); + + # F -> [ T ] -> { R... } + # where + # F: T -> R, + # T, R: Any: + fromListMappedValue + = convert: + input: + fromList + ( + list.map + ( + name: + { + inherit name; + value = convert name; + } + ) + input + ); + + generate + = generator: + count: + fromList (list.generate generator count); + + # string -> { T... } -> T + # where T: Any: + get + = intrinsics.getAttr + or ( + name: + self: + self.${name} + ); + + getKeySource#: string -> { string -> T } -> { column: int; file: string; line: int; } + = intrinsics.unsafeGetAttrPos; + + # string -> { T... } -> D -> T | D + # where T, D: Any: + getOr + = name: + self: + default: + self.${name} or default; + + getSource + = { ... } @ self: + if self != {} + then + getKeySource (list.head (names self)) self + else + null; + + # string -> { ... } -> bool + hasAttribute + = intrinsics.hasAttr + or ( + name: + self: + self.${name} or true == self.${name} or false + ); + + ifOrEmpty + = condition: + value: + if condition + then + value + else + {}; + + # { string -> T } -> { string -> U } -> { string -> U } + intersect + = intrinsics.intersectAttrs; + + isInstanceOf = intrinsics.isAttrs; + + map = intrinsics.mapAttrs; + + mapFold + = convert: + operator: + fold + ( + state: + name: + value: + operator state (convert name value) + ); + + mapFold' + = convert: + operator: + fold' + ( + state: + entry: + operator state (convert entry) + ); + + mapNamesAndValues#: F -> { T... } -> { R... } + # where + # F: string -> T -> { name: string, value: R } + # T, R: Any, + = convert: + self: + fromList (mapToList convert self); + + # F -> { T... } -> [ R ] + # where + # F: string -> T -> R, + # T, R: Any: + mapToList + = convert: + { ... } @ self: + values (map convert self); + + # F -> { T... } -> [ R ] + # where + # F: string -> T -> R, + # T, R: Any: + mapToListConcatted + = convert: + { ... } @ self: + list.concat (values (map convert self)); + + # F -> { T... } -> { R... } + # where + # F: T -> R, + # T, R: Any: + mapValues + = convert: + map (_: convert); + + name + = map + ( + name: + value: + value // { inherit name; } + ); + + names = intrinsics.attrNames; + + orNull + = value: + isInstanceOf value || value == null; + + pair#: n, T @ n:[ string ] -> n:[ T ] -> { T } + = listOfNames: + listOfValues: + if list.isInstanceOf listOfNames + && list.isInstanceOf listOfValues + && list.length listOfNames == list.length listOfValues + then + fromListIMappedValue (index: name: list.get listOfValues index) listOfNames + else + debug.panic "pair" "Names and Values must be two lists of same length!"; + + pairNameWithValue + = name: value: { inherit name value; }; + + partition + = predicate: + dictionary: + list.fold + ( + { right, wrong }: + name: + let + value = dictionary.${name}; + in + if predicate name dictionary.${name} + then + { + inherit wrong; + right = right // { ${name} = value; }; + } + else + { + inherit right; + wrong = wrong // { ${name} = value; }; + } + ) + { + right = {}; + wrong = {}; + } + (names dictionary); + + partition' + = predicate: + partition (name: value: predicate { inherit name value; }); + + partitionByName + = predicate: + partition (name: _: predicate name); + + partitionByValue + = predicate: + partition (_: predicate); + + # { ... } -> [ string ] -> { ... }: + remove = intrinsics.removeAttrs; + + # { T... } -> string -> T + # where T: Any: + select = { ... } @ self: field: self.${field}; + select' = { ... } @ self: field: self.${field} or null; + + selectOr = { ... } @ self: field: default: self.${field} or default; + + values = intrinsics.attrValues; + + zip = intrinsics.zipAttrsWith; + in + type "set" + { + isPrimitive = true; + of + = subtype: + let + inner = type.expect subtype; + in + type "SetOf" + { + isInstanceOf = value: isInstanceOf value && all (_: inner.isInstanceOf) value; + inherit inner; + }; + + inherit all all' any any' + callValues collect + filter filterByName filterKeys filterValue fold fold' foldValues + fromList fromListDefault fromListIMapped fromListIMappedValue fromListMapped fromListMappedValue + generate get getOr getKeySource getSource + hasAttribute + ifOrEmpty intersect isInstanceOf + map mapFold mapFold' mapNamesAndValues mapToList mapToListConcatted mapValues + name names + orNull + pair pairNameWithValue partition partitionByName partitionByValue + remove + select select' selectOr + values + zip; + } diff --git a/libs/core/lib/string/default.nix b/libs/core/lib/string/default.nix new file mode 100644 index 0000000..e4ebbf8 --- /dev/null +++ b/libs/core/lib/string/default.nix @@ -0,0 +1,739 @@ +{ bool, debug, derivation, expression, integer, intrinsics, library, list, set, type, ... } @ libs: + let + veryDeep#: { depth: int, panic: bool } + = { + depth = 64; + panic = false; + }; + + DoNotFollow + = type "DoNotFollow" + { + from = value: DoNotFollow.instanciate { inherit value; }; + }; + + combine = list.combine (a: b: "${a}${b}"); + hexChars = [ "0" "1" "2" "3" "4" "5" "6" "7" "8" "9" "a" "b" "c" "d" "e" "f" ]; + hexPairs = combine hexChars hexChars; + + appendContext + = intrinsics.appendContext; + + ascii = list.generate (index: getChar index) 128; + lowerAscii = list.generate (index: getChar ( 97 + index)) 26; + upperAscii = list.generate (index: getChar ( 65 + index)) 26; + char + = { + backspace = getChar' "0008"; + carriageReturn = "\r"; + delete = getChar' "007f"; + escape = getChar' "001b"; + horizontalTab = "\t"; + lineFeed = "\n"; + null = ""; + }; + + concat#: [ string ] -> string + = concatWith ""; + + concatIndexMapped#: F -> [ T ] -> string + # where + # F: int -> T -> string, + # T: Any + = convert: + concatIndexMappedWith convert ""; + + concatIndexMappedWith#: F -> string -> [ T ] -> string + # where + # F: int -> T -> string, + # T: Any: + = convert: + seperator: + parts: + concatWith seperator (list.imap convert parts); + + concatLines#: [ string ] -> string + = concatWith "\n"; + + concatMapped#: F -> [ T ] -> string + # where + # F: T -> string, + # T: Any + = convert: + concatMappedWith convert ""; + + concatMapped'#: F -> [ T ] -> string + # where + # F: string -> T -> string, + # T: Any + = convert: + concatMappedWith' convert ""; + + concatMappedLines#: F -> [ T ] -> string + # where + # F: T -> string, + # T: Any + = convert: + concatMappedWith convert "\n"; + + concatMappedLines'#: F -> [ T ] -> string + # where + # F: string -> T -> string, + # T: Any + = convert: + concatMappedWith' convert "\n"; + + concatMappedWith#: F -> string -> [ T ] -> string + # where + # F: T -> string, + # T: Any + = convert: + seperator: + parts: + concatWith seperator (list.map convert parts); + + concatMappedWith'#: F -> string -> [ T ] -> string + # where + # F: string -> T -> string, + # T: Any + = convert: + seperator: + parts: + concatWith seperator (set.mapToList convert parts); + + concatMappedWithFinal#: F -> string -> string -> [ T ] -> string + # where + # F: T -> string, + # T: Any + = convert: + seperator: + final: + parts: + concatWithFinal + seperator + final + (list.map convert parts); + + concatMappedWithFinal'#: F -> string -> string -> [ T ] -> string + # where + # F: string -> T -> string, + # T: Any + = convert: + seperator: + final: + parts: + concatWithFinal + seperator + final + (set.mapToList convert parts); + + concatWith#: string -> [ string ] -> string + = intrinsics.concatStringsSep + or ( + seperator: + parts: + list.fold + ( + result: + entry: + "${result}${seperator}${entry}" + ) + (list.head parts) + (list.tail parts) + ); + + concatWithFinal#: string -> string -> [ string ] -> string + = seperator: + final: + parts: + if list.length parts > 1 + then + "${concatWith seperator (list.body parts)}${final}${list.foot parts}" + else + list.head parts; + + concatWords#: [ string ] -> string + = concatWith " "; + + discardContext + = intrinsics.unsafeDiscardStringContext; + + discardOutputDependency + = intrinsics.unsafeDiscardOutputDependency; + + escape + = replace + [ "\"" "\\" "\n" "\r" "\t" char.escape ] + [ "\\\"" "\\\\" "\\n" "\\r" "\\t" "\\e" ]; + + escapeKey + = key: + if (match "[A-Za-z_][-'0-9A-Za-z_]*" key) != null + then + key + else + "\"${escape key}\""; + + format#: T -> string + # where T: Any + = { + display ? false, + hex ? false, + legacy ? false, + maxDepth ? null, + nice ? false, + showType ? false, + trace ? false, + }: + formatValue + { + inherit display hex legacy maxDepth nice showType trace; + attrPath = []; + depth = 0; + indent = ""; + seen = []; + }; + + formatAttrPath + = concatMapped + ( + key: + bool.select + (integer.isInstanceOf key) + "[${integer.toString key}]" + ".${key}" + ); + + formatBool = { legacy, ... }: (bool.select legacy bool.formatLegacy bool.format); + + formatFloat = { ... }: intrinsics.toString; + + formatInteger = { hex, ... }: bool.select hex integer.formatHexaDecimal integer.toString; + + formatLambda + = let + mapArgument + = key: + value: + "${escapeKey key}${bool.select value "?" ""}"; + mapArguments = set.mapToList mapArgument; + in + { depth, display, maxDepth, legacy, ... }: + value: + let + args = intrinsics.functionArgs value; + value' + = bool.select (args != {}) + "{ ${concatWith ", " (mapArguments args)} }: ..." + "_: ..."; + in + if depth == maxDepth + then + "_: ..." + else if display + then + bool.select legacy "" value' + else + debug.panic [ "formatLambda" ] + { + text = "cannot coerse a function to a string"; + data = value'; + }; + + formatList + = { depth, indent, legacy, maxDepth, nice, ... } @ env: + value: + let + body = list.imap (formatValue' env) value; + in + if depth == maxDepth then "[ ... ]" + else if value == [] then bool.select legacy "" "[]" + else if legacy then "[ ${concatMappedWith (value: "(${value})") " " body} ]" + else if nice then "[\n${indent} ${concatWith ",\n${indent} " body}\n${indent}]" + else "[ ${concatWith ", " body} ]"; + + formatNull = { legacy, ... }: _: bool.select legacy "" "null"; + + formatPath + = { depth, maxDepth, ... }: + value: + if depth == maxDepth then "" + else intrinsics.toString value; #"${value}"; + + formatSet + = { depth, display, indent, legacy, maxDepth, nice, ... } @ env: + { ... } @ value: + let + body + = set.mapToList format + ( + bool.select + (value.__public__ or null != null) + (set.filterByName value value.__public__) + (set.remove value [ "__public__" "__type__" "__variant__" ]) + ); + format + = key: + value: + let + key' = escapeKey key; + in + "${key'} = ${formatValue' env key' value};"; + niceText = "{\n${indent} ${concatWith "\n${indent} " body}\n${indent}}"; + niceText' + = if body != [] + then + bool.select + (type.getType value != null) + "<${typeName} ${niceText}>" + niceText + else + "{}"; + typeName = type.format value; + value' + = if debug.Debug.isInstanceOf value then "" + else if derivation.isInstanceOf' value then "" + else if library.isInstanceOf value then "" + else if value._type or null != null then "<${value._type}>" + else if nice && !legacy then niceText' + else if legacy || type.getType value == null then "{ ${concatWith " " (set.mapToList format value)} }" + else if body != [] then "<${typeName} { ${concatWith " " body} }>" + else "<${typeName}>"; + in + if depth == maxDepth then "{ ... }" + else if value == {} then "{}" + else if display then value' + else if value ? outPath then value.outPath + else if value ? __toString then value.__toString value + else + debug.panic "formatSet" + { + text = "cannot coerse this set to a string"; + data = value; + }; + + formatString + = { depth, display, indent, maxDepth, nice, ... }: + value: + let + value' = escape value; + in + if depth == maxDepth + then + "" + else if nice + then + let + lines = splitLines value; + lines' + = concatMapped + ( + line: + bool.select + (match "[ \n\r\t]*" line != null) + "\n${indent}" + "\n${indent} ${replace [ "\${" "''" ] [ "''\${" "'''" ] line}" + ) + lines; + in + if list.length lines > 1 then "''${lines'}''" + else "\"${value'}\"" + else if display || depth > 0 then "\"${value'}\"" + else value; + + formatValue + = { attrPath, depth, display, legacy, maxDepth, seen, showType, trace, ... } @ env: + input: + let + env' + = env + // { + seen = seen ++ [ value ]; + }; + + format + = type.matchPrimitive value + { + bool = formatBool; + float = formatFloat; + int = formatInteger; + lambda = formatLambda; + list = formatList; + null = formatNull; + path = formatPath; + set = formatSet; + string = formatString; + }; + + doNotFormat + = !showType + && maxDepth != null + && depth >= maxDepth; + + valueIfUnsuccessful + = debug.panic [ "formatValue" "valueIfUnsuccessful" ] + { + text = "Panic occured while evaluation input value."; + when = !display || legacy; + } + ""; + + valueIfVeryDeep + = debug.panic [ "formatValue" "valueIfVeryDeep" ] + { + text = "Very deep o.O"; + when = veryDeep.panic; + data = formatAttrPath attrPath; + } + ""; + + inherit(expression.tryEval input) success value; + value' + = if doNotFormat then "..." + else if !success then valueIfUnsuccessful + else if list.find value seen then "" + else if depth >= veryDeep.depth then valueIfVeryDeep + else format env' value; + in + if trace + then + intrinsics.trace "<$>${formatAttrPath attrPath}" value' + else + value'; + + formatValue' + = { attrPath, depth, indent, seen, ... } @ env: + key: + formatValue + ( + env + // { + attrPath = attrPath ++ [ key ]; + depth = depth + 1; + indent = "${indent} "; + } + ); + + from = format {}; + + getByte#: string -> int + = text: getByte' (slice 0 1 text); + + getByte'#: string -> int + = let + get#: string -> int -> string + = text: index: slice index 1 text; + + head#: string -> char + = text: get text 0; + + bytes + = intrinsics.listToAttrs + ( + ( list.generate ( value: { name = getChar value; inherit value; } 127 ) ) + ++ [ + { name = head ( getChar' "0080" ); value = 194; } + { name = head ( getChar' "00c0" ); value = 195; } + ] + ++ ( + list.combine + ( + a: b: + { + name = head ( getChar' "0${list.get hexChars a}${list.get hexChars (4 * b)}0" ); + value = 192 + 4 * a + b; + } + ) + ( list.range 1 7 ) + ( list.range 0 3 ) + ) + ++ ( + list.map + ( + a: + { + name = head ( getChar' "${list.get hexChars a}800" ); + value = 224 + a; + } + ) + ( list.range 0 15 ) + ) + ++ ( + list.combine + ( + a: + b: + { + name = get ( getChar' "00${list.get hexChars (8 + a)}${list.get hexChars b}" ) 1; + value = 128 + 16 * a + b; + } + ) + ( list.range 0 3 ) + ( list.range 0 15 ) + ) + ); + in + bytes.${char}; + + getChar'#: string -> char + = index: expression.fromJSON "\"\\u${index}\""; + + getChar#: int -> char + = index: list.get ( list.map getChar' (combine hexPairs hexPairs) ) index; + + getContext + = intrinsics.getContext; + + getFinalChar + = self: + slice ((length self) - 1) 1 self; + + hasContext + = intrinsics.hasContext; + + hash#: string -> string -> string + = intrinsics.hashString; + + ifOrEmpty + = condition: + text: + if condition + then + text + else + ""; + + isEmpty#: string -> bool + = text: text == ""; + + isInstanceOf = intrinsics.isString or (value: type.getPrimitive value == "string"); + + length#: string -> int + = intrinsics.stringLength + or ( + text: + let + rest = slice 1 9223372036854775807 text; + in + if text == "" then 0 + else ( length rest ) + 1 + ); + + lengthUTF8#: string -> int + = text: list.length ( toUTF8characters text ); + + match#: string -> string -> [ T ] + # where T: null | string | [ T ] + = intrinsics.match; + + orNull + = value: + isInstanceOf value || value == null; + + repeat#: string -> int -> string + = text: + multiplier: + concat ( list.generate (_: text) multiplier ); + + replace#: [ string ] -> [ string ] -> string -> string + = intrinsics.replaceStrings; /* should be possible to construct, but ahhh */ + + replace' + = { ... } @ substitutions: + replace + (set.names substitutions) + (set.values substitutions); + + slice#: int -> int -> string -> string + = intrinsics.substring; + + split#: string -> string -> [ T ] + # where T: null | string | [ T ] + = intrinsics.split; + + splitAt#: string -> string -> [ string ] + = regex: + text: + list.filter + ( line: isInstanceOf line ) + ( split regex text ); + + splitAt'#: string -> string -> [ string ] + = regex: + text: + list.filter + ( line: isInstanceOf line && line != "") + ( split regex text ); + + splitLines#: string -> [ string ] + = splitAt "\n"; + + splitSpaces + = splitAt "([[:space:]]+)"; + + splitTabs#: string -> [ string ] + = splitAt "\t"; + + toBytes#: string -> [ u8 ] + = text: list.map getByte' (toCharacters text); + + toCharacters#: string -> [ asciiChar ] + = text: + list.generate (index: slice index 1 text) (length text); + + toPath#: string -> path + = path: "./${path}"; + + toLowerCase#: string -> string + = let + caseMap + = set.pair + ( upperAscii ++ [ "Ä" "Ö" "Ü" "ẞ" ] ) + ( lowerAscii ++ [ "ä" "ö" "ü" "ß" ] ); + in + text: + list.fold + ( + text: + char: + "${text}${caseMap.${char} or char}" + ) + "" + ( toUTF8characters text ); + + toString#: T -> string + = intrinsics.toString + or ( + format + { + display = false; + hex = false; + legacy = true; + maxDepth = null; + nice = false; + showType = false; + trace = false; + } + ); + + toTrace#: T -> string + # where T: Any + = { hex, maxDepth, nice, showType, trace }: + format + { + inherit hex maxDepth nice showType trace; + display = true; + legacy = false; + }; + + toTraceDeep#: T -> string + # where T: Any + = { hex, nice, showType, trace }: + format + { + inherit hex nice showType trace; + display = true; + legacy = false; + maxDepth = null; + }; + + toTraceShallow#: T -> string + # where T: Any + = { hex, nice, showType, trace }: + format + { + inherit hex nice showType trace; + display = true; + legacy = false; + maxDepth = 1; + }; + + toUpperCase#: string -> string + = let + # The german letter ß (sz) cannot be at the start of a word and + # therefore does not have a capital form. + # However in uppercase text, the letter ẞ is allowed, + # but the unicode standard still defaults to SS. + # I do not care about that, I prefer ẞ instead. + caseMap + = set.pair + ( lowerAscii ++ [ "ä" "ö" "ü" "ß" ] ) + ( upperAscii ++ [ "Ä" "Ö" "Ü" "ẞ" ] ); + in + text: + concatMapped + (char: "${caseMap.${char} or char}") + (toUTF8characters text); + + toUTF8characters#: string -> [ utf8char ] + = text: + let + this + = list.fold + ( + { result, text }: + character: + if character <= char.delete + then + { + text = ""; + result + = result + ++ ( if text != "" then [ text ] else [ ] ) + ++ [ character ]; + } + else + { + # Does not validate! + # E.g. C2 A3 A3 would be considered one char, + # even though this is invalid utf8! + text = "${text}${character}"; + inherit result; + } + ) + { + text = ""; + result = [ ]; + } + (toCharacters text); + in + this.result + ++ ( + if this.text != "" + then + [ this.text ] + else + [ ] + ); + + trim = library.import ./trim.nix libs; + in + type "string" + { + inherit DoNotFollow; + inherit appendContext ascii + char + concat concatLines + concatIndexMapped concatIndexMappedWith + concatMapped concatMapped' + concatMappedLines concatMappedLines' + concatMappedWith concatMappedWith' + concatMappedWithFinal concatMappedWithFinal' + concatWith concatWithFinal concatWords + discardContext discardOutputDependency + escapeKey + from + getByte getChar getContext getFinalChar + hasContext hash + ifOrEmpty isEmpty isInstanceOf + length lengthUTF8 + match + orNull + replace replace' repeat + slice split splitAt splitAt' + splitLines splitSpaces splitTabs + toBytes toCharacters toLowerCase toPath toString toTrace toTraceDeep toTraceShallow toUpperCase toUTF8characters trim; + inherit(trim) ltrim ltrim' rtrim rtrim' trim'; + + isPrimitive = true; + } diff --git a/libs/core/lib/string/hashing/default.nix b/libs/core/lib/string/hashing/default.nix new file mode 100644 index 0000000..1fdd5a9 --- /dev/null +++ b/libs/core/lib/string/hashing/default.nix @@ -0,0 +1,183 @@ +{ intrinsics, list, string, ... }: +let + inherit (list) fold get range; + + # string -> string + md5sum + = intrinsics.hashString "md5" + orr ( + let + and = intrinsics.bitAnd; + not = xor 4294967295; + orr = intrinsics.bitOr; + xor = intrinsics.bitXor; + add = a: b: and (a+b) 4294967295; + mod16 = value: and value 15; + + s + = [ + 7 12 17 22 7 12 17 22 7 12 17 22 7 12 17 22 + 5 9 14 20 5 9 14 20 5 9 14 20 5 9 14 20 + 4 11 16 23 4 11 16 23 4 11 16 23 4 11 16 23 + 6 10 15 21 6 10 15 21 6 10 15 21 6 10 15 21 + ]; + + pow + = [ + 1 2 4 8 16 32 64 128 + 256 512 1024 2048 4096 8192 16384 32768 + 65536 131072 262144 524288 1048576 2097152 4194304 8388608 + ]; + + rotate + = value: + index: + let + amount = get s index; + shift = get pow amount; + in + orr (and (value * shift) 4294967295) (value / shift); + + K + = [ + 3614090360 3905402710 606105819 3250441966 + 4118548399 1200080426 2821735955 4249261313 + 1770035416 2336552879 4294925233 2304563134 + 1804603682 4254626195 2792965006 1236535329 + 4129170786 3225465664 643717713 3921069994 + 3593408605 38016083 3634488961 3921069994 + 568446438 3275163606 4107603335 1163531501 + 2850285829 4243563512 1735328473 2368359562 + 4294588738 2272392833 1839030562 4259657740 + 2763975236 1272893353 4139469664 4259657740 + 681279174 3936430074 3572445317 76029189 + 3654602809 3873151461 530742520 3299628645 + 4096336452 1126891415 2878612391 4237533241 + 1873313359 2399980690 4293915773 2240044497 + 1873313359 4264355552 2734768916 1309151649 + 4149444226 317475691 2734768916 3951481745 + ]; + + next + = { A, B, C, D, message }: + index: + F: + word: + let + F' = add F (add A (add (get K index) (get message word))); + in + { + A = D; + B = add B (rotate F' index); + C = B; + D = C; + inherit M; + }; + + mapBlock + = message: + fold + ( + { A, B, C, D, ... } @ state: + index: + if index < 16 + then + next state index (orr (and B C) (and (not B) D)) index + else if index < 32 + then + next state index (orr (and D B) (and (not D) C)) (mod16 (5 * index + 1)) + else if index < 48 + then + next state index (xor B (xor C D)) (mod16 (3 * index + 5)) + else + next state index (xor C (orr B (not D))) (mod16 (7 * index)) + ) + { + A = 1732584193; + B = 4023233417; + C = 2562383102; + D = 271733878; + inherit message; + } + ( range 0 63 ); + in + text: + fold + ( + state: + block: + ) + { + A = 1732584193; + B = 4023233417; + C = 2562383102; + D = 271733878; + } + ( + let + length = string.length text; + length' + = [ + ( and length 255 ) + ( and ( length / 256 ) 255 ) + ( and ( length / 256 / 256 ) 255 ) + ( and ( length / 256 / 256 / 256 ) 255 ) + ( and ( length / 256 / 256 / 256 / 256 ) 255 ) + ( and ( length / 256 / 256 / 256 / 256 / 256 ) 255 ) + ( and ( length / 256 / 256 / 256 / 256 / 256 / 256 ) 255 ) + ( and ( length / 256 / 256 / 256 / 256 / 256 / 256 / 256 ) 255 ) + ]; + in + fold + ( + { count, temp, word, result }: + byte: + let + temp' = [ byte ] ++ temp; + word' = word ++ [ (fold (a: b: 256 * a + b) 0 temp') ]; + in + if count == 15 + then + { + count = 0; + temp = [ ]; + word = [ ]; + result = result ++ [ word' ]; + } + else if lists.length temp' == 4 + then + { + count = count + 1; + temp = [ ]; + word = word'; + inherit result; + } + else + { + count = count + 1; + temp = temp'; + inherit word result; + } + ) + { + count = 0; + temp = [ ]; + word = [ ]; + result = [ ]; + } + ( + ( string.toBytes text ) + ++ [ 128 ] + ++ ( + generate (x: 0) + ( 16 - ( mod16 length + 9 ) ) + ) + ++ length' + ).result + ) + + ); +in +{ + inherit md5sum; +} diff --git a/libs/core/lib/string/trim.nix b/libs/core/lib/string/trim.nix new file mode 100644 index 0000000..d706c1f --- /dev/null +++ b/libs/core/lib/string/trim.nix @@ -0,0 +1,30 @@ +{ list, string, ... }: + let + concat = splits: string.concat (list.flat splits); + splitSpaces = string.split "([[:space:]]+)"; + + ltrim' + = parts: + if list.head parts == "" + && parts != [ "" ] + then + list.generate (x: list.get parts ( x + 2 )) ( list.length parts - 2 ) + else + parts; + rtrim' + = parts: + if list.foot parts == "" + && parts != [ "" ] + then + list.generate (x: list.get parts x) ( list.length parts - 2 ) + else + parts; + trim' = text: list.flat ( rtrim' ( ltrim' ( splitSpaces text ) ) ); + trim = text: string.concat ( trim' text ); + in + { + __functor = self: trim; + ltrim = text: concat (ltrim' (splitSpaces text)); + rtrim = text: concat (rtrim' (splitSpaces text)); + inherit ltrim' rtrim' trim trim'; + } diff --git a/libs/core/lib/target/architecture.nix b/libs/core/lib/target/architecture.nix new file mode 100644 index 0000000..657f0a8 --- /dev/null +++ b/libs/core/lib/target/architecture.nix @@ -0,0 +1,138 @@ +{ debug, integer, intrinsics, list, set, string, type, ... }: + let + Architecture#: struct { bits: integer, endianness: Endianness, family: Family } + = type "Architecture" + { + inherit Endianness Family; + inherit all families; + + from#: type -> (string | Architecture)? -> Architecture + = architecture: + if !(Architecture.isInstanceOf architecture) + then + type.matchPrimitiveOrPanic architecture + { + null = all.unknown; + string = all.${architecture} or (debug.panic "Architecture" "Unknown architecture »${architecture}«!"); + } + else + architecture; + }; + + Endianness#: enum { big, little, none } + = type.enum "Endianness" + { + big = 1; + little = 2; + none = 3; + }; + + Family#: type + = type "Family" + {};#{ name = string; arch = string || null; version = integer || null; }; + + all#: { string -> Architecture } + = let + new#: integer -> Endianness -> Family -> Architecture + = bits: + endianness: + family: + Architecture.instanciate + { + __toString = { name, ... }: name; + inherit bits endianness family; + }; + all + = { + aarch64 = new 64 Endianness.little families.arm8-a; + aarch64_be = new 64 Endianness.big families.arm8-a; + alpha = new 64 Endianness.little families.alpha; + amd64 = new 64 Endianness.little families.amd64; + arm = new 32 Endianness.little families.arm; + armv5tel = new 32 Endianness.little families.arm5t; + armv6m = new 32 Endianness.little families.arm6-m; + armv6l = new 32 Endianness.little families.arm6; + armv7a = new 32 Endianness.little families.arm7-a; + armv7r = new 32 Endianness.little families.arm7-r; + armv7m = new 32 Endianness.little families.arm7-m; + armv7l = new 32 Endianness.little families.arm7; + armv8a = new 32 Endianness.little families.arm8-a; + armv8r = new 32 Endianness.little families.arm8-a; + armv8m = new 32 Endianness.little families.arm8-m; + avr = new 8 Endianness.none families.avr; + i386 = new 32 Endianness.little families.i386; + i486 = new 32 Endianness.little families.i486; + i586 = new 32 Endianness.little families.i586; + i686 = new 32 Endianness.little families.i686; + js = new 32 Endianness.little families.js; + m68k = new 32 Endianness.big families.m68k; + microblaze = new 32 Endianness.big families.microblaze; + microblazeel = new 32 Endianness.little families.microblaze; + mips = new 32 Endianness.big families.mips; + mips64 = new 64 Endianness.big families.mips; + mips64el = new 64 Endianness.little families.mips; + mipsel = new 32 Endianness.little families.mips; + mmix = new 64 Endianness.big families.mmix; + msp430 = new 16 Endianness.little families.msp430; + or1k = new 32 Endianness.big families.or1k; + powerpc = new 32 Endianness.big families.power; + powerpc64 = new 64 Endianness.big families.power; + powerpc64le = new 64 Endianness.little families.power; + powerpcle = new 32 Endianness.little families.power; + riscv32 = new 32 Endianness.little families.riscv; + riscv64 = new 64 Endianness.little families.riscv; + rx = new 32 Endianness.little families.rx; + s390 = new 32 Endianness.big families.s390; + s390x = new 64 Endianness.big families.s390; + sparc = new 32 Endianness.big families.sparc; + sparc64 = new 64 Endianness.big families.sparc; + unknown = new null Endianness.none families.unknown; + vc4 = new 32 Endianness.little families.vc4; + wasm32 = new 32 Endianness.little families.wasm; + wasm64 = new 64 Endianness.little families.wasm; + x86_64 = all.amd64; + }; + in + set.name all; + + families#: { string -> Family } + = { + alpha = { name = "alpha"; }; + amd64 = families.x86 // { arch = "amd64"; }; + arm = { name = "arm"; }; + arm5 = families.arm // { arch = "armv5"; version = 5; }; + arm5t = families.arm5 // { arch = "armv5t"; }; + arm6 = families.arm // { arch = "armv6"; version = 6; }; + arm6-m = families.arm6 // { arch = "armv6-m"; }; + arm7 = families.arm // { arch = "armv7"; version = 7; }; + arm7-a = families.arm7 // { arch = "armv7-a"; }; + arm7-m = families.arm7 // { arch = "armv7-m"; }; + arm7-r = families.arm7 // { arch = "armv7-r"; }; + arm8 = families.arm // { arch = "armv8"; version = 8; }; + arm8-a = families.arm8 // { arch = "armv8-a"; }; + arm8-m = families.arm8 // { arch = "armv8-m"; }; + avr = { name = "avr"; }; + i386 = families.x86 // { arch = "i386"; }; + i486 = families.x86 // { arch = "i486"; }; + i586 = families.x86 // { arch = "i586"; }; + i686 = families.x86 // { arch = "i686"; }; + js = { name = "js"; }; + m68k = { name = "m68k"; }; + microblaze = { name = "microblaze"; }; + mips = { name = "mips"; }; + mmix = { name = "mmix"; }; + msp430 = { name = "msp430"; }; + or1k = { name = "or1k"; }; + power = { name = "power"; }; + riscv = { name = "riscv"; }; + rx = { name = "rx"; }; + s390 = { name = "s390"; }; + sparc = { name = "sparc"; }; + unknown = { name = "unknown"; }; + vc4 = { name = "vc4"; }; + wasm = { name = "wasm"; }; + x86 = { name = "x86"; }; + x86_64 = families.amd64; + }; + in + Architecture diff --git a/libs/core/lib/target/default.nix b/libs/core/lib/target/default.nix new file mode 100644 index 0000000..337048c --- /dev/null +++ b/libs/core/lib/target/default.nix @@ -0,0 +1,6 @@ +{ library, ... } @ libs: +{ + Architecture = library.import ./architecture.nix libs; + Kernel = library.import ./kernel.nix libs; + System = library.import ./system.nix libs; +} diff --git a/libs/core/lib/target/kernel.nix b/libs/core/lib/target/kernel.nix new file mode 100644 index 0000000..c26bf64 --- /dev/null +++ b/libs/core/lib/target/kernel.nix @@ -0,0 +1,89 @@ +{ debug, integer, intrinsics, list, set, string, type, ... }: + let + ExecutableFormat#: Enum { elf, macho, pe, unknown, wasm } + = type.enum "ExecutableFormat" + { + elf = 1; + macho = 2; + pe = 3; + unknown = 4; + wasm = 5; + }; + + Family = null;# || { parent = Family; }; + + Kernel# struct { executableFormat: ExecutableFormat, family: Family } + = type "Kernel" + { + inherit ExecutableFormat Family; + inherit all families; + + isDarwin#: System -> bool + = { kernel, ... } @ self: + kernel == all.darwin; + + isLinux#: System -> bool + = { kernel, ... } @ self: + kernel == all.linux; + + from#: type -> (string | Kernel)? -> Kernel + = kernel: + if !(Kernel.isInstanceOf kernel) + then + type.matchPrimitiveOrPanic kernel + { + null = all.none; + string = all.${kernel} or (debug.panic "Kernel" "Unknown kernel »${kernel}«!"); + } + else + kernel; + }; + + families#: { string -> Family } + = { + bsd = { parent = families.unix; }; + darwin = { parent = families.bsd; }; + linux = { parent = families.unix; }; + none = { parent = null; }; + unix = { parent = families.none; }; + windows = { parent = families.none; }; + }; + + all#: { string -> Kernel } + = let + new#: ExecutableFormat -> Family -> Kernel + = executableFormat: + family: + Kernel.instanciate + { + __toString = { name, ... }: name; + inherit executableFormat family; + }; + + all + = { + cygwin = new ExecutableFormat.elf families.linux; + darwin = new ExecutableFormat.macho families.darwin; + freebsd = new ExecutableFormat.elf families.bsd; + ios = new ExecutableFormat.macho families.darwin; + linux = new ExecutableFormat.elf families.linux; + ghcjs = new ExecutableFormat.unknown families.none; + genode = new ExecutableFormat.elf families.none; + macos = all.darwin; + mmixware = new ExecutableFormat.unknown families.none; + netbsd = new ExecutableFormat.elf families.bsd; + none = new ExecutableFormat.unknown families.none; + openbsd = new ExecutableFormat.elf families.bsd; + redox = new ExecutableFormat.elf families.none; + solaris = new ExecutableFormat.elf families.unix; + tvos = all.ios; + wasi = new ExecutableFormat.wasm families.none; + watchos = all.ios; + win32 = all.windows; + win64 = all.windows; + windows = new ExecutableFormat.pe families.windows; + }; + in + set.name all; + in + Kernel diff --git a/libs/core/lib/target/system.nix b/libs/core/lib/target/system.nix new file mode 100644 index 0000000..546ea51 --- /dev/null +++ b/libs/core/lib/target/system.nix @@ -0,0 +1,128 @@ +{ debug, integer, intrinsics, list, set, string, target, type, ... }: + let + inherit(target) Architecture Kernel; + + System#: struct { architecture: Architecture, kernel: Kernel } + = type "System" + { + inherit all stdenv; + + current = fromString ( intrinsics.currentSytem or "unknown-none" ); + + mapAll#: T: ( System -> T ) -> { string -> T } + = map all; + + mapStdenv#: T: ( System -> T ) -> { string -> T } + = map stdenv; + + from#: type -> string | { architecture: string? = null, kernel: string? = null } -> System | ! + = system: + type.matchPrimitiveOrPanic system + { + set = fromSet system; + string = fromString system; + }; + }; + + all#: { string -> System } + = list.mapNamesToSet fromString + [ + # Cygwin + "i686-cygwin" "x86_64-cygwin" + + # Darwin + "x86_64-darwin" "i686-darwin" "aarch64-darwin" "armv7a-darwin" + + # FreeBSD + "i686-freebsd" "x86_64-freebsd" + + # Genode + "aarch64-genode" "i686-genode" "x86_64-genode" + + # illumos + "x86_64-solaris" + + # JS + "js-ghcjs" + + # Linux + "aarch64-linux" "armv5tel-linux" "armv6l-linux" "armv7a-linux" + "armv7l-linux" "i686-linux" "m68k-linux" "microblaze-linux" + "microblazeel-linux" "mipsel-linux" "mips64el-linux" "powerpc64-linux" + "powerpc64le-linux" "riscv32-linux" "riscv64-linux" "s390-linux" + "s390x-linux" "x86_64-linux" + + # MMIXware + "mmix-mmixware" + + # NetBSD + "aarch64-netbsd" "armv6l-netbsd" "armv7a-netbsd" "armv7l-netbsd" + "i686-netbsd" "m68k-netbsd" "mipsel-netbsd" "powerpc-netbsd" + "riscv32-netbsd" "riscv64-netbsd" "x86_64-netbsd" + + # none + "aarch64_be-none" "aarch64-none" "arm-none" "armv6l-none" "avr-none" "i686-none" + "microblaze-none" "microblazeel-none" "msp430-none" "or1k-none" "m68k-none" + "powerpc-none" "powerpcle-none" "riscv32-none" "riscv64-none" "rx-none" + "s390-none" "s390x-none" "vc4-none" "x86_64-none" + + # OpenBSD + "i686-openbsd" "x86_64-openbsd" + + # Redox + "x86_64-redox" + + # WASI + "wasm64-wasi" "wasm32-wasi" + + # Windows + "x86_64-windows" "i686-windows" + ]; + + stdenv + = { + inherit(all) aarch64-linux aarch64-darwin + x86_64-linux x86_64-darwin; + }; + + fromSet#: { architecture: ToArchitecture? = null, kernel: ToKernel = null } -> System + = { architecture ? null, kernel ? null }: + System.instanciate + { + __toString#: { architecture: Architecture, kernel: Kernel } -> string + = { architecture, kernel, ... }: + "${string architecture}-${string kernel}"; + architecture = Architecture architecture; + kernel = Kernel kernel; + }; + + fromString#: string -> System | ! + = name: + let + parts = string.match "(.*)-(.*)" name; + in + if parts != null + then + fromSet + { + architecture = list.get parts 0; + kernel = list.get parts 1; + } + else + debug.panic + "fromString" + { + text + = '' + Cannot convert »${name}« to System! + A name must be »architecture-kernel«. + ''; + data = name; + }; + + map#: T: { string -> System } -> ( System -> T ) -> { string -> T } + = systems: + convert: + set.mapValues convert systems; + in + System diff --git a/libs/core/lib/time/default.nix b/libs/core/lib/time/default.nix new file mode 100644 index 0000000..95066d4 --- /dev/null +++ b/libs/core/lib/time/default.nix @@ -0,0 +1,735 @@ +{ debug, float, integer, intrinsics, list, string, type, ... }: + let + daysPerYear = 365; + secondsPerMinute = 60; + secondsPerHour = 60 * secondsPerMinute; + secondsPerDay = 24 * secondsPerHour; + yearsPerEra = 400; + yearsPerCentury = 100; + yearsPerCycle = 4; + monthsPerYear = 12; + dayOfWeekOfEraBegin = 0; #0: Monday, 6: Sunday + + DateTime + = type "DateTime" + { + inherit secondsPerMinute secondsPerHour secondsPerDay + daysPerYear + monthsPerYear + yearsPerEra yearsPerCentury yearsPerCycle; + + inherit after before from fromSet + format formatDate formatDateTime formatYearMonth formatYearShortMonth + formatISO8601 formatISO8601' + getDayName getDayShortName getMonthName getMonthShortName + parseDateTime parseISO8601 parseUnixTime + tryParseISO8601; + + current = from (intrinsics.currentTime or 0); + }; + + # DateTime -> DateTime -> bool: + after + = left: + right: + let + left' = DateTime.expect left; + right' = DateTime.expect right; + orZero = value: if value != null then value else 0; + lYear = left'.year; + rYear = right'.year; + lMonth = orZero left'.month; + rMonth = orZero right'.month; + lDay = orZero left'.day; + rDay = orZero right'.day; + lHour = orZero left'.hour; + rHour = orZero right'.hour; + lMinute = orZero left'.minute; + rMinute = orZero right'.minute; + lSecond = orZero left'.second; + rSecond = orZero right'.second; + in + if lYear == rYear + then + if lMonth == rMonth + then + if lDay == rDay + then + if lHour == rHour + then + if lMinute == rMinute + then + lSecond > rSecond + else + lMinute > rMinute + else + lHour > rHour + else + lDay > rDay + else + lMonth > rMonth + else + lYear > rYear; + + # DateTime -> DateTime -> bool: + before + = left: + right: + let + left' = DateTime.expect left; + right' = DateTime.expect right; + orZero = value: if value != null then value else 0; + lYear = left'.year; + rYear = right'.year; + lMonth = orZero left'.month; + rMonth = orZero right'.month; + lDay = orZero left'.day; + rDay = orZero right'.day; + lHour = orZero left'.hour; + rHour = orZero right'.hour; + lMinute = orZero left'.minute; + rMinute = orZero right'.minute; + lSecond = orZero left'.second; + rSecond = orZero right'.second; + in + if lYear == rYear + then + if lMonth == rMonth + then + if lDay == rDay + then + if lHour == rHour + then + if lMinute == rMinute + then + lSecond < rSecond + else + lMinute < rMinute + else + lHour < rHour + else + lDay < rDay + else + lMonth < rMonth + else + lYear < rYear; + + format#: D: ToDateTime @ D -> string -> string -> string + = dateTime: + language: + format: + let + date = from dateTime; + handle + = token: + if list.isInstanceOf token + then + let + parts + = string.match + "%([-_0+^#])*([EO]?[A-Za-y%]|(:{0,3})z)" + (list.head token); + config + = list.fold + ( + state: + token: + { + "^" = state // { upper = true; }; + "#" = state // { opposite = true; }; + "-" = state // { padding = ""; }; + "_" = state // { padding = " "; }; + "0" = state // { padding = "0"; }; + "+" = state // { padding = "0"; plus = true; }; + }.${token} + ) + { + opposite = false; + padding = null; + plus = false; + upper = false; + } + (list.get parts 0); + pad + = value: + length: + default: + let + padding = if config.padding != null then config.padding else default; + text = if value != null then string value else string.repeat "?" length; + len = ( string.length text ) - length; + padding' = string.repeat padding len; + in + if padding != "" && len > 0 then "${padding'}${text}" + else if config.plus && len < 0 then "+${text}" + else text; + adjustCase + = text: + maybeLower: + if maybeLower && config.opposite then string.toLowerCase text + else if config.upper then string.toUpperCase text + else text; + control = list.get parts 1; + suffix = list.get parts 2; + suffix' = string.length suffix; + + modulo = y: x: x - ( x / y ) * y; + mod7 = modulo 7; + mod12 = modulo 12; + mod60 = modulo 60; + mod100 = modulo 100; + + quarter = ( ( date.month - 1 ) / 4 ) + 1; + isAM = date.hour < 12; + dayOfWeekMonday = date.dayOfWeek; + dayOfWeekSunday = if date.dayOfWeek == 6 then 0 else date.dayOfWeek + 1; + startOfWeek = date.dayOfYear - dayOfWeekMonday; + startOfWeek' = date.dayOfYear - dayOfWeekSunday; + mondayWeek = if startOfWeek <= 0 then 0 else (startOfWeek + 6) / 7; + sundayWeek = if startOfWeek <= 0 then 0 else (startOfWeek' + 6) / 7; + isoWeek = ( startOfWeek + 6 ) / 7 + 1; + isoYear + = if startOfWeek <= 0 + then + date.year - 1 + else + date.year; + + hour = pad date.hour 2 "0"; + minute = pad date.minute 2 "0"; + second = pad date.second 2 "0"; + year = pad date.year 4 "0"; + year' = pad (mod100 date.year) 2 "0"; + month = pad date.month 2 "0"; + day = pad date.day 2 "0"; + day' = pad date.day 2 " "; + + dayShortName = adjustCase ( getDayShortName dayOfWeekMonday ) false; + monthShortName = adjustCase ( getMonthShortName date.month ) false; + + zone = if date.zone != null then date.zone else 0; + zoneSign = if zone < 0 then "-" else "+"; + zone' = if zone < 0 then 0 - zone else zone; + zoneSeconds = pad ( mod60 zone' ) 2 "0"; + zoneMinutes = pad ( mod60 ( zone' / secondsPerMinute ) ) 2 "0"; + zoneHours = pad ( mod60 ( zone' / secondsPerHour ) ) 2 "0"; + zoneHours' = "${zoneSign}${zoneHours}"; + + zone0 = "${zoneSign}${pad ( zone' / secondsPerMinute ) 4 "0"}"; + zone1 = "${zoneHours'}:${zoneMinutes}"; + zone2 = "${zoneHours'}:${zoneMinutes}:${zoneSeconds}"; + zone3 + = if zoneSeconds != 0 then zone2 + else if zoneMinutes != 0 then zone1 + else zoneHours'; + in + if suffix == null + then + { + "%" = "%"; + "a" = dayShortName; + "A" = adjustCase ( getDayName dayOfWeekMonday ) false; + "b" = monthShortName; + "B" = adjustCase ( getMonthName date.month ) false; + "c" = "${dayShortName} ${monthShortName} ${day'} ${hour}:${minute}:${second} ${year}"; + "C" = pad ( date.year / 100 ) 2 "0"; + "d" = day; + "D" = "${month}/${day}/${year'}"; + "e" = day'; + "F" = "${year}-${month}-${day}"; + "g" = pad (mod100 isoYear) 2 "0"; + "G" = pad isoYear 4 "0"; + "h" = adjustCase ( getMonthShortName date.month ) false; + "H" = hour; + "I" = pad ( mod12 date.hour ) 2 "0"; + "j" = pad date.dayOfYear 3 "0"; + "k" = pad date.hour 2 " "; + "l" = pad ( mod12 date.hour ) 2 " "; + "m" = month; + "M" = minute; + "n" = "\n"; + "N" = pad date.nanosecond 9 "0"; + "p" = if isAM then "AM" else "PM"; + "P" = if isAM then "am" else "pm"; + "q" = pad quarter 1 "0"; + "r" = null; # Locale 12-hour clock time, e.g. "%I:%M%S %p" + "R" = "${hour}:${minute}"; + "s" = pad date.unix 2 "0"; + "S" = second; + "t" = "\t"; + "T" = "${hour}:${minute}:${second}"; + "u" = pad ( dayOfWeekMonday + 1 ) 2 "0"; + "U" = sundayWeek; + "V" = pad isoWeek 2 ""; + "w" = pad dayOfWeekSunday 2 "0"; + "W" = mondayWeek; + "x" = null; # Locale Date + "X" = null; # Locale Time + "y" = year'; + "Y" = year; + "z" = zone0; + ":z" = zone1; + "::z" = zone2; + ":::z" = zone3; + "Z" = null; # TZ + }.${control} or "%${control}" + else + "" + else + token; + in + if date != null + then + list.fold + ( + result: + token: + "${result}${handle token}" + ) + "" + ( string.split "%[-_0+^#]*([EO]?[A-Za-y%]|:{0,3}z)" format ) + else + debug.panic "format" "Invalid date: ${date}"; + + formatDate#: D -> string -> string + # where D: ToDateTime + = dateTime: + language: + let + date = from dateTime; + in + if date != null + then + "${string date.day}. ${getMonthName date.month language} ${string date.year}" + else + debug.panic "formatDate" "Invalid date: ${date}"; + + formatDateTime#: D -> string -> string + # where D: ToDateTime + = dateTime: + language: + let + date = from dateTime; + pad#: int -> string + = value: + if value < 10 + then + "0${string value}" + else + string value; + in + if date != null + then + "${string date.day}. ${getMonthName date.month language} ${string date.year} ${pad date.hour}:${pad date.minute}:${pad date.second}" + else + debug.panic "formatDateTime" "Invalid date: ${date}"; + + formatISO8601#: D -> string -> string + # where D: ToDateTime + = dateTime: + let + date = from dateTime; + pad#: int -> string + = value: + if value == null + then + "00" + else if value < 10 + then + "0${string value}" + else + string value; + in + if date != null + then + "${string date.year}-${pad date.month}-${pad date.day}" + else + debug.panic "formatISO8601" "Invalid date: ${date}"; + + formatISO8601'#: D -> string -> string + # where D: ToDateTime + = dateTime: + let + date = from dateTime; + pad#: int -> string + = value: + if value == null + then + "00" + else if value < 10 + then + "0${string value}" + else + string value; + in + if date != null + then + "${string date.year}-${pad date.month}-${pad date.day}T${pad date.hour}:${pad date.minute}:${pad date.second}" + else + debug.panic "formatISO8601'" "Invalid date: ${date}"; + + formatYearMonth#: string -> string -> string + = dateTime: + language: + let + dateTime' = from dateTime; + in + if dateTime' != null + then + "${getMonthName dateTime'.month language} ${string dateTime'.year}" + else + debug.panic "formatYearMonth" "Invalid date: ${dateTime}"; + + formatYearShortMonth#: string -> string -> string + = dateTime: + language: + let + dateTime' = from dateTime; + in + if dateTime' != null + then + "${getMonthShortName dateTime'.month language} ${string dateTime'.year}" + else + debug.panic "formatYearShortMonth" "Invalid date: ${dateTime}"; + + from#: int | set | string -> DateTime + = dateTime: + ( + type.matchPrimitiveOrPanic dateTime + { + int = parseUnixTime dateTime; + set = fromSet dateTime; + string + = let + dateTime' = tryParseISO8601 dateTime; + in + if dateTime' != null + then + parseISO8601 dateTime + else + parseDateTime dateTime; + } + ) + // { + __toString + = let + string' + = value: + if value == null + then + "00" + else if value < 10 + then + "0${string value}" + else + string value; + in + { year, month, day, hour, minute, second, ... }: + "${string year}-${string' month}-${string' day}T${string' hour}:${string' minute}:${string' second}"; + }; + + fromSet#: + # { + # year: int, + # month: int?, + # day: int?, + # dayOfWeek: int?, + # dayOfYear: int?, + # hour: int?, + # minute: int?, + # second: int?, + # nanosecond: int?, + # unix: int?, + # zone: int?, + # zoneName: string?, + # } + # -> DateTime: + = { + year, month ? null, day ? null, dayOfWeek ? null, dayOfYear ? null, + hour ? null, minute ? null, second ? null, nanosecond ? null, + zone ? null, zoneName ? null, + unix ? null, + ... + } @ data: + if integer.isInstanceOf year + && integer.orNull month + && integer.orNull day + && integer.orNull dayOfWeek + && integer.orNull dayOfYear + && integer.orNull hour + && integer.orNull minute + && integer.orNull second + && integer.orNull nanosecond + && integer.orNull zone + && string.orNull zoneName + then + DateTime.instanciate + { inherit year month day hour minute second nanosecond zone zoneName; } + else + debug.panic "DateTime" + { + text = "Value cannot be a DateTime!"; + inherit data; + }; + + getDayName#: int -> string -> string + = dayOfWeek: + language: + let + days + = { + eng = [ "Monday" "Thuesday" "Wednesday" "Thursday" "Friday" "Saturday" "Sunday" ]; + deu = [ "Montag" "Dienstag" "Mittwoch" "Donnerstag" "Freitag" "Samstag" "Sonntag" ]; + }; + days' + = if language == null + then + days.eng + else + ( days.${language} or days.eng); + in + list.get days' ( dayOfWeek - 1 ); + + getDayShortName#: int -> string -> string + = dayOfWeek: + language: + let + days + = { + eng = [ "Mon" "Thu" "Wed" "Thu" "Fri" "Sat" "Sun" ]; + deu = [ "Mo" "Di" "Mi" "Do" "Fr" "Sa" "So" ]; + }; + days' + = if language == null + then + days.eng + else + ( days.${language} or days.eng); + in + list.get days' ( dayOfWeek - 1 ); + + getMonthName#: int -> string -> string + = month: + language: + let + months + = { + eng + = [ + "January" "February" "March" "April" + "May" "June" "July" "August" + "September" "October" "November" "December" + ]; + deu + = [ + "Januar" "Februar" "März" "April" + "Mai" "Juni" "Juli" "August" + "September" "Oktober" "November" "Dezember" + ]; + }; + months' + = if language == null + then + months.eng + else + ( months.${language} or months.eng); + in + list.get months' ( month - 1 ); + + getMonthShortName#: int -> string -> string + = month: + language: + let + months + = { + eng + = [ + "Jan" "Feb" "Mar" "Apr" + "May" "Jun" "Jul" "Aug" + "Sep" "Oct" "Nov" "Dec" + ]; + deu + = [ + "Jan" "Feb" "Mär" "Apr" + "Mai" "Jun" "Jul" "Aug" + "Sep" "Okt" "Nov" "Dez" + ]; + }; + months' + = if language == null + then + months.eng + else + ( months.${language} or months.eng); + in + list.get months' ( month - 1 ); + + parseDateTime#: + # Y = "([0-9]{4})", + # m = "([0-9]{2})", + # d = "([0-9]{2})", + # H = "([0-9]{2})", + # M = "([0-9]{2})", + # S = "([0-9]{2})" + # @ "${Y}${m}${d}${H}${M}${S}" -> { year, month, day, hour, minute, second } + = dateTime: + let + dateTime' = string.match "([0-9]{4})([0-9]{2})([0-9]{2})([0-9]{2})([0-9]{2})([0-9]{2})" dateTime; + field = list.get dateTime'; + in + if dateTime' != null + then + { + year = integer (field 0); + month = integer (field 1); + day = integer (field 2); + hour = integer (field 3); + minute = integer (field 4); + second = integer (field 5); + } + else + null; + + parseISO8601#: string -> DateTime | ! + = iso8601: + let + dateTime = tryParseISO8601 iso8601; + in + if dateTime != null + then + dateTime + else + debug.panic "parseISO8601" + { + text = "Cannot parse as ISO 8601-Date:"; + data = iso8601; + }; + + parseUnixTime#: int -> int | float | null | string -> DateTime + = unix: + zoneOrName: + let + zone + = type.matchPrimitiveOrPanic zoneOrName + { + int = zoneOrName * secondsPerHour; + float = float.floor ( zoneOrName * secondsPerHour ); + null = 0; + string + = secondsPerHour + * { + # ToDo: https://en.wikipedia.org/wiki/List_of_time_zone_abbreviations + cest = 2; + cet = 1; + utc = 0; + }.${zoneOrName} or ( debug.panic "parseUnixTime" "Unknown Zone »${zoneOrName}«!" ); + }; + adjustedUnix = zone + unix; + zoneName + = if string.isInstanceOf zoneOrName + then + zoneOrName + else + null; + + correctYear#: int -> int + = month: if month <= march then 1 else 0; + shiftMonth#: int -> int + = month: month + march + 1 - ( if month < ( monthsPerYear - march ) then 0 else monthsPerYear ); + + # For whatever reason, the months are from march (0) to february (11) + # Therefor the month must be shifted to january (1) to december (12) and the year must be corrected. + leapYearsPerEra + = ( yearsPerEra / yearsPerCycle ) # + Regular leap years, e.g. 2004, 2008, 2012 + - ( yearsPerEra / yearsPerCentury ) # - Except those divisible by 100, e.g. 1700, 1800, 1900 + + ( yearsPerEra / yearsPerEra ); # + But those divisible by 400, e.g. 1600, 2000, 2400 + leapYearsPerRegularCentury = yearsPerCentury / yearsPerCycle - 1; + daysPerEra = yearsPerEra * daysPerYear + leapYearsPerEra; + daysBetweenMarchZeroAndEpoch + = 1970 * daysPerYear # Regular Days since 0000-01-01 + + 17 # Leap Years in 1900–1970 + + 3 * leapYearsPerRegularCentury # Leap Years in 1600–1900 + + 4 * leapYearsPerEra # Leap Years in 0–1600 + - 31 # Days January + - 28; # Days in February of year 0 + daysPerCycle = yearsPerCycle * daysPerYear + 1; + daysPerCentury = yearsPerCentury * daysPerYear + leapYearsPerRegularCentury; + daysFromMarchTillAugust = 31 + 30 + 31 + 30 + 31; + march = 2; + daysSinceEpoch = adjustedUnix / secondsPerDay; + daysSinceMarchZero = daysSinceEpoch + daysBetweenMarchZeroAndEpoch; + positiveEra + = if daysSinceMarchZero >= 0 + then + daysSinceMarchZero + else + daysSinceMarchZero - daysPerEra + 1; + era = positiveEra / daysPerEra; + dayOfEra = daysSinceMarchZero - era * daysPerEra; + yearOfEra + = ( + dayOfEra + - dayOfEra / ( daysPerCycle - 1 ) + + dayOfEra / daysPerCentury + - dayOfEra / ( daysPerEra - 1 ) + ) / daysPerYear; + numberOfLeapYears = yearOfEra / yearsPerCycle - yearOfEra / yearsPerCentury; + dayOfYear = dayOfEra - ( daysPerYear * yearOfEra + numberOfLeapYears ); + month' = ( 5 * dayOfYear + march ) / daysFromMarchTillAugust; + day = dayOfYear - ( daysFromMarchTillAugust * month' + march ) / 5 + 1; + month = shiftMonth month'; + year = yearOfEra + era * yearsPerEra + correctYear month; + + secondsToday = adjustedUnix - daysSinceEpoch * secondsPerDay; + hour = secondsToday / secondsPerHour; + secondsThisHour = secondsToday - hour * secondsPerHour; + minute = secondsThisHour / secondsPerMinute; + second = secondsThisHour - minute * secondsPerMinute; + nanosecond = 0; + + modulo7 = x: x - ( x / 7 ) * 7; + dayOfWeek = modulo7 ( dayOfEra + dayOfWeekOfEraBegin ); + in + DateTime { inherit unix year month day hour minute second nanosecond dayOfWeek dayOfYear zone zoneName; }; + + tryParseISO8601#: string -> DateTime | null + = iso8601: + let + year = "([+-]?[0-9]{4})"; + zone = "(Z|Z?([+-]?[0-9]{2}))?"; + a = "([0-9]{1,2})"; + # This neither matches milliseconds, intervals nor durations, but YYYYMM + regex = "${year}(-?${a}(-?${a}([T_ ]?${a}(:?(${a}(:?${a})?))?)?)?)?${zone}"; + matched = string.match regex iso8601; + toInteger'#: string | null -> int | null + = value: + if value != null + then + integer value + else + null; + in + if string.isInstanceOf iso8601 + && matched != null + then + DateTime + { + year = toInteger' ( list.get matched 0 ); + month = toInteger' ( list.get matched 2 ); + day = toInteger' ( list.get matched 4 ); + dayOfWeek = null; + dayOfYear = null; + hour = toInteger' ( list.get matched 6 ); + minute = toInteger' ( list.get matched 9 ); + second = toInteger' ( list.get matched 11 ); + nanosecond = 0; + zone = toInteger' ( list.get matched 13 ); + zoneName = null; + } + else + null; + in + DateTime + // { + inherit DateTime; + } \ No newline at end of file diff --git a/libs/core/lib/type/default.nix b/libs/core/lib/type/default.nix new file mode 100644 index 0000000..3201ae3 --- /dev/null +++ b/libs/core/lib/type/default.nix @@ -0,0 +1,479 @@ +{ any, debug, expression, function, intrinsics, lambda, set, ... }: + let + TypeConstructor + = type "TypeConstructor" + { + from + = let + __functor + = { apply, instanciate, ... } @ self: + argument: + let + result = apply argument; + in + if lambda.isInstanceOf result + then + self + // { + apply = result; + } + else + instanciate self result; + in + kind: + apply: + instanciate: + TypeConstructor.instanciateAs kind + { + inherit apply instanciate; + inherit __functor; + }; + }; + + applyFunction + = from: + value: + let + value' = from value; + in + # Check if the same function? + if value'.isFunction or false + then + applyFunction value' + else + value'; + + applyLambda + = { expect, from, ... } @ self: + value: + let + value' = from value; + in + if lambda.isInstanceOf value' + then + applyLambda (self // { from = value'; }) + else + expect value'; + + defaultFunctor + = { expect, from ? null, ... } @ self: + value: + if lambda.isInstanceOf from + then + applyLambda self value + else if from.isFunction or false + then + applyFunction from value + else + expect value; + + defaultInstanceOf + = this: + value: + get value == this; + + defaultMergeWith + = variant: + prev: + next: + debug.panic [ variant "defaultMergeWith" ] + { + text = "Could not merge values of ${variant}, because they are not equal!"; + data = { inherit prev next; }; + when = prev != next; + } + prev; + + defaultToString + = self: + debug.panic [ (format self) "defaultToString" ] + { + text = "Cannot coerce value of type ${format self} to string!"; + data = self; + nice = true; + }; + + enum + = let + constructEnum + = { __variant__, ... } @ self: + variantName: + value: + let + constructor + = function: + TypeConstructor + "${enumName}::${variantName}" + function + (_: instanciate); + enumName = __variant__; + instanciate = self.instanciateAs variantName; + in + if type.isInstanceOf value + then + constructor value.expect + else if lambda.isInstanceOf value + then + constructor value + else + instanciate value; + in + TypeConstructor "enum" + ( + enumName: + { ... } @ variants: + { inherit enumName variants; } + ) + ( + { ... }: + { enumName, variants, ... }: + let + from + = variantName: + debug.panic [ "enum" enumName "from" ] + { + text + = '' + There is no variant `${variantName}` in enum `${enumName}`. + Valid variants are: + ''; + data = variants; + when = !(set.hasAttribute variants variantName); + } + (constructEnum self variantName variants.${variantName}); + match + = value: + { ... } @ cases: + let + case = cases.${getVariant value'}; + case' + = if lambda.isInstanceOf case + then + case value' + else + case; + missing = set.remove variants (set.names cases); + unexpected = set.remove cases (set.names variants); + value' = self.expect value; + in + debug.panic [ "enum" enumName "match" ] + { + text = "Unexpected variants:"; + data = unexpected; + when = unexpected != {}; + } + debug.panic [ "enum" enumName "match" ] + { + text = "The following variants are not covered:"; + data = missing; + when = missing != {}; + } + case'; + self + = type enumName + ( + (set.map (constructEnum self) variants) + // { inherit from match; } + ); + in + self + ); + + extend + = { __variant__, ... } @ self: + { + __functor ? (self.__functor or defaultFunctor), + __toString ? (self.__toString or defaultToString), + isInstanceOf ? (self.isInstanceOf or (defaultInstanceOf __variant__)), + mergeWith ? (self.mergeWith or defaultMergeWith), + __public__ ? self.__public__ or null, + ... + } @ definition: + let + expect + = value: + if isInstanceOf value + then + value + else if debug.Debug.isInstanceOf value + then + abort "${value}" + else + debug.dafuq [ __variant__ "expect" ] + { + text = "Value of `${__variant__}` expected, got: `${get value}`!"; + data = value; + nice = true; + } + (abort "???"); + instanciate = instanciateAs null; + instanciateAs + = variantName: + value: + let + value' + = if set.isInstanceOf value + then + value + else + { inherit value; }; + in + value' + // { + __type__ = __variant__; + __variant__ = variantName; + getType = __variant__; + getVariant = variantName; + inherit __public__; + }; + in + self + // definition + // { + inherit(self) __traits__ __type__ __variant__; + inherit __functor __toString __public__ + isInstanceOf mergeWith; + inherit expect instanciate instanciateAs; + }; + + format + = self: + let + typeName = getType self; + variantName = getVariant self; + in + if typeName != null + then + if variantName != null + then + "${typeName}::${variantName}" + else + typeName + else + "primitive ${getPrimitive self}"; + + from + = typeName: + { ... } @ definition: + extend + { + __public__ = null; + __traits__ = {}; + __type__ = "type"; + __variant__ = typeName; + } + definition; + + # Get Type + get#: T: Introspection @ T -> string + = value: + let + typeName = getType value; + in + if typeName != null + then + typeName + else + getPrimitive value; + + getPrimitive#: T: Introspection @ T -> string + = intrinsics.typeOf; + + getType + = this: + let + this' = expression.tryEval this; + in + if this'.success + then + this'.value.__type__ or null + else + "never"; + + getVariant + = this: + this.__variant__ or null; + + isReserved + = name: + { + # special methods, hardcoded into nix + __functor = true; + __toString = true; + # custom type system + __traits__ = true; + __type__ = true; + __variant__ = true; + }.${name} or false; + + # Type Checks + matchPrimitive# T: Introspection, R1, R2, R3, R4, R5, R6, R7, R8, R9 + #@ T + #-> { bool: R1, float: R2, int: R3, lambda: R4, list: R5, null: R6, path: R7, set: R8, string: R9 } + #-> R + = value: + { bool, float, int, lambda, list, null, path, set, string } @ select: + select.${getPrimitive value}; + + matchPrimitive' + = function "matchPrimitive" + [ any any any ] + matchPrimitive; + + matchPrimitiveOrDefault# T: Introspection, D, R1, R2, R3, R4, R5, R6, R7, R8, R9 + #@ T + #-> { bool: R1, float: R2, int: R3, lambda: R4, list: R5, null: R6, path: R7, set: R8, string: R9 } + #-> D + #-> R | D + = value: + { ... } @ select: + default: + select.${getPrimitive value} or default; + + matchPrimitiveOrDefault' + = function "matchPrimitiveOrDefault" + [ any any any any ] + matchPrimitiveOrDefault; + + matchPrimitiveOrPanic + = value: + select: + matchPrimitiveOrDefault value select + ( + debug.panic "matchPrimitiveOrPanic" + { + text = "Primitive Type ${getPrimitive value} was not handled"; + data = value; + } + ); + + matchPrimitiveOrPanic' + = function "matchPrimitiveOrPanic" + [ any any any ] + matchPrimitiveOrPanic; + + struct#: string -> { string } -> type + = let + checkFields + = structName: + fields: + signatures: + let + unexpected = set.remove fields (set.names signatures); + in + set.map + ( + name: + { expect, ... } @ signature: + expect + ( + fields.${name} + or signature.default + or ( + debug.panic [ "struct" structName "checkFields" ] + { + text = "Field `${name}` is empty and type `${getVariant signature}` does not provide a default!"; + data = signature; + } + ) + ) + ) + ( + debug.panic [ "struct" structName "checkFields" ] + { + text = "Unexpected fields:"; + data = unexpected; + when = unexpected != {}; + nice = true; + } + signatures + ); + in + TypeConstructor "struct" + ( + structName: + { ... } @ definition: + let + inner = set.partitionByValue type.isInstanceOf definition; + in + { + inherit structName; + types = inner.right; + values = inner.wrong; + } + ) + ( + { ... }: + { structName, types, values }: + let + self + = type structName + ( + values + // { + from + = fields: + self.instanciate + ( + checkFields + structName + fields + types + ); + } + ); + in + self + ); + + trait#: string -> ({ ... } -> { ... }) -> trait + = traitName: + methods: + type traitName + ( + methods + // { + from + = object: + if type.isInstanceOf object + then + { ... } @ required: + object + // { + __traits__ + = object.__traits__ + // { + ${traitName} + = required + // (methods required); + }; + } + else + method: + let + methods = (object.__traits__ or {}).${traitName} or null; + in + debug.panic [ "trait" traitName "from" ] + { + text = "Object of type `${get object}` does not implement `${traitName}`"; + data = object; + when = methods != null; + } + methods.${method} object; + } + ); + + type + = from "type" + { + inherit TypeConstructor; + __functor + = { ... }: + from; + inherit defaultInstanceOf; + inherit format get getPrimitive getType getVariant; + inherit matchPrimitive matchPrimitiveOrDefault matchPrimitiveOrPanic; + inherit enum struct trait; + }; + in + type diff --git a/libs/core/lib/type/trait.nix b/libs/core/lib/type/trait.nix new file mode 100644 index 0000000..66f5413 --- /dev/null +++ b/libs/core/lib/type/trait.nix @@ -0,0 +1,21 @@ +{ ... }: + let + # trait -> { ... } -> T -> T + implementFor + = trait: + { ... } @ methods: + { __traits__ ? {}, ... } @ struct: + struct + // { + __traits__ + = __traits__ + // ( trait methods ); + }; + + # { __traits__: T } -> T + # where T: { ... } | null + getTraits = { __traits__ ? null, ... }: __traits__; + in + { + inherit implementFor getTraits; + } \ No newline at end of file diff --git a/libs/core/lib/version/default.nix b/libs/core/lib/version/default.nix new file mode 100644 index 0000000..3f053f6 --- /dev/null +++ b/libs/core/lib/version/default.nix @@ -0,0 +1,84 @@ +{ intrinsics, list, string, time, type, ... }: + let + Version# { major: string, minor: string, patch: string } -> Version + = type "Version" + { + from + = { major, minor, patch }: + Version.instanciate + { + inherit major minor patch; + }; + }; + in + { + compare#: string -> string -> int + = intrinsics.compareVersions; + + deriveVersion#: ? + = dateTime: + let + dateTime' = time dateTime; + pad + = value: + if value == null + then + "00" + else if value < 10 + then + "0${string value}" + else + string value; + month = pad dateTime'.month; + day = pad dateTime'.day; + hour = pad dateTime'.hour; + minute = pad dateTime'.minute; + second = pad dateTime'.second; + in + if dateTime' != null + then + "${string dateTime'.year}-${month}-${day}T${hour}:${minute}:${second}" + else + "dev"; + + language#: string? + = intrinsics.langVersion or null; + + main#: string -> string + = version: "${string version.major}.${string version.minor}"; + + nix#: string? + = intrinsics.nixVersion or null; + + parseDerivationName#: string -> { name: string, version: string } + = intrinsics.parseDrvName + or ( + derivationName: + let + result = string.match "(([^-]|-[^0-9])*)-([0-9].*)" derivationName; + in + { + name = list.get result 0; + version = list.get result 2; + } + ); + + split#: string -> Version + = version: + let + result = string.split "[.]" version; + in + Version + { + major = list.get result 0; + minor = list.get result 1; + patch = list.get result 2; + }; + + split'#: string -> [ string ] + = intrinsics.splitVersion + or ( + version: + string.splitAt "[.]" version + ); + } diff --git a/libs/core/tests/default.nix b/libs/core/tests/default.nix new file mode 100644 index 0000000..8e335a2 --- /dev/null +++ b/libs/core/tests/default.nix @@ -0,0 +1,29 @@ +{ ... }: +{ ansi, debug, error, expression, set, target, ... } @ lib: +{ + deepSeqAll + = let + lib' + = lib + // { + never = null; + }; + in + set.mapValues + ( + module: + ({ ... }: module) + ) + lib'; + foo + = { + bar + = { + hmm = [ { a = 1; } ]; + mew = [ 1 2 ]; + miau = foo: true; + ohh = { a = true; b = { c = true; }; }; + }; + success = true && true; + }; +} diff --git a/libs/intrinsics/flake.nix b/libs/intrinsics/flake.nix new file mode 100644 index 0000000..9a69c38 --- /dev/null +++ b/libs/intrinsics/flake.nix @@ -0,0 +1,804 @@ +{ + description = "Nix builtins/intrinsics."; + inputs = {}; # No Inputs! + outputs + = { ... }: + let + # Cannot use import, because import is itself an intrinsic function. + lib + = { + #! Abort Nix expression evaluation and print the error message. + abort#: string -> ! + = builtins.abort; + + #! Return the sum of two numbers. + add#: number -> number -> number + = builtins.add + or (p: q: p + q); + + #! TODO: Documentation + addErrorContext#: T -> T + = builtins.addErrorContext; + + #! Return `true` if the function returns `true` for all elements of the list, and `false` otherwise. + all#: (T -> bool) -> [ T ] -> bool + = builtins.all; + + #! Return `true` if the function returns `true` for at least one element of the list, and `false` otherwise. + any#: (T -> bool) -> [ T ] -> bool + = builtins.any; + + #! TODO: Documentation + appendContext#: T -> T + = builtins.appendContext; + + #! Return the names of the attributes in the set in an alphabetically sorted list. + #! For instance, `attrNames { y = 1; x = "foo"; }` evaluates to `[ "x" "y" ]`. + attrNames#: { string -> T } -> [ string ] + = builtins.attrNames; + + #! Return the values of the attributes in the set in the order corresponding to the sorted attribute names. + attrValues#: { string -> T } -> [ T ] + = builtins.attrValues; + + #! Return the base name of an expression that can be coerced to a string. + #! That is, everything following the final slash in the string, or the full string, if no slash is present. + #! This is similar to the GNU basename command. + baseNameOf#: ToString -> string + = builtins.baseNameOf; + + #! Return the bitwise conjunction of two integers. + bitAnd#: integer -> integer -> integer + = builtins.bitAnd; + + #! Return the bitwise disjunction of two integers. + bitOr#: integer -> integer -> integer + = builtins.bitOr; + + #! Return the bitwise exclusive disjunction of two integers. + bitXor#: integer -> integer -> integer + = builtins.bitXor; + + #! In debug mode (enabled using `--debugger`), + #! pause Nix expression evaluation and enter the REPL. + #! Otherwise, return the argument `v`. + break#: T -> T + = builtins.break + or (x: x); + + #! Collect each attribute named attr from a list of attribute sets. + #! Attrsets that do not contain the named attribute are ignored. + #! For example, + #! ``` + #! catAttrs "a" [{a = 1;} {b = 0;} {a = 2;}] + #! ``` + #! evaluates to `[1 2]`. + catAttrs#: string -> [ { string -> T } ] -> [ T ] + = builtins.catAttrs; + + #! Converts an IEEE-754 double-precision floating-point number (double) to the next higher integer. + #! If the datatype is neither an `integer` nor a `float`, an evaluation error will be thrown. + ceil#: integer | float -> integer + = builtins.ceil; + + #! Compare two strings representing versions and return + #! * `-1` if the first version is older than the second version, + #! * `0` if they are the same, and + #! * `1` if the first is newer than the second. + #! The version comparison algorithm is the same + #! as the one used by `nix-env -u ../command-ref/nix-env.md#operation---upgrade`. + compareVersions#: string -> string -> integer + = builtins.compareVersions; + + #! Concatenate a list of lists into a single list. + concatLists#: [ [ T ] ] -> [ T ] + = builtins.concatLists; + + #! This function is equivalent to `f: list: concatLists (map f list)` but is more efficient. + concatMap#: (T -> U) -> [ T ] -> U + = builtins.concatMap; + + #! Concatenate a list of strings with a separator between each element, + #! e.g. `concatStringsSep "/" ["usr" "local" "bin"]` returns `"usr/local/bin"`. + concatStringsSep#: string -> [ string ] -> string + = builtins.concatStringsSep; + + #! This is like `seq e1 e2`, except that `e1` is evaluated deeply: + #! if it is a `list` or `set`, its elements or attributes are also evaluated recursively. + deepSeq#: T -> T + = builtins.deepSeq; + + #! TODO: Documentation + derivation#: + = builtins.derivation; + + #! Construct (as a unobservable side effect) a Nix derivation expression + #! that performs the derivation described by the argument set. + #! Returns the original set extended with the following attributes: + #! * `outPath' containing the primary output path of the derivation; + #! * `drvPath' containing the path of the Nix expression; and + #! * `type' set to `derivation' to indicate that this is a derivation. + derivationStrict#: T -> T + = builtins.derivationStrict; + + #! Return the base name of an expression that can be coerced to a string. + #! That is, everything before the final slash in the string. + #! This is similar to the GNU `dirname` command. + dirOf#: T -> T + = builtins.dirOf; + + #! Return the quotient of the numbers e1 and e2. + div#: number -> number -> number + = builtins.div + or (p: q: p / q); + + #! Return true if a given value occurs in the list, and false otherwise. + elem#: T -> [ T ] -> bool + = builtins.elem; + + #! Return element by index from the list. + #! Elements are counted starting from 0. + #! A fatal error occurs if the index is out of bounds. + elemAt#: [ T ] -> integer -> T | ! + = builtins.elemAt; + + #! Contradiction + false#: bool + = builtins.false + or (1 != 1); + + /*#! TODO: Documentation + fetchClojure + = builtins.fetchClojure or (builtins.throw "Not available yet");*/ + + #! Fetch a path from git. + #! Arguments can be a URL, in which case the HEAD of the repo at that URL is fetched. + #! Otherwise, it can be an attribute with the following attributes (all except url optional): + #! *[url] The URL of the repo. + #! *[name] The name of the directory the repo should be exported to in the store. + #! Defaults to the basename of the URL. + #! *[rev] The git revision to fetch. + #! Defaults to the tip of ref. + #! *[ref] The git ref to look for the requested revision under. + #! This is often a branch or tag name. Defaults to HEAD. + #! By default, the ref value is prefixed with refs/heads/. + #! As of Nix 2.3.0 Nix will not prefix refs/heads/ if ref starts with refs/. + #! *[submodules] A Boolean parameter that specifies whether submodules should be checked out. + #! Defaults to false. + #! *[allRefs] Whether to fetch all refs of the repository. + #! With this argument being true, it is possible to load a rev from any ref. + #! By default only revs from the specified ref are supported. + #! # Examples + #! Here are some examples of how to use fetchGit: + #! * To fetch a private repository over SSH: + #! ``` + #! fetchGit { + #! url = "git@github.com:my-secret/repository.git"; + #! ref = "master"; + #! rev = "adab8b916a45068c044658c4158d81878f9ed1c3"; + #! } + #! ``` + #! * To fetch an arbitrary reference: + #! ``` + #! fetchGit { + #! url = "https://github.com/NixOS/nix.git"; + #! ref = "refs/heads/0.5-release"; + #! } + #! ``` + #! * If the revision you are looking for is in the default branch of the git repository + #! you do not strictly need to specify the branch name in the ref attribute. + #! However, if the revision you are looking for is in a future branch for the non-default branch + #! you will need to specify the the ref attribute as well. + #! ``` + #! fetchGit { + #! url = "https://github.com/nixos/nix.git"; + #! rev = "841fcbd04755c7a2865c51c1e2d3b045976b7452"; + #! ref = "1.11-maintenance"; + #! } + #! ``` + #! It is nice to always specify the branch which a revision belongs to. + #! Without the branch being specified, the fetcher might fail if the default branch changes. + #! Additionally, it can be confusing to try a commit from a non-default branch and see the fetch fail. + #! If the branch is specified the fault is much more obvious. + #! If the revision you are looking for is in the default branch of the git repository + #! you may omit the ref attribute. + #! ``` + #! fetchGit { + #! url = "https://github.com/nixos/nix.git"; + #! rev = "841fcbd04755c7a2865c51c1e2d3b045976b7452"; + #! } + #! ``` + #! * To fetch a specific tag: + #! ``` + #! fetchGit { + #! url = "https://github.com/nixos/nix.git"; + #! ref = "refs/tags/1.9"; + #! } + #! ``` + #! * To fetch the latest version of a remote branch: + #! ``` + #! fetchGit { + #! url = "ssh://git@github.com/nixos/nix.git"; + #! ref = "master"; + #! } + #! ``` + #! Nix will refetch the branch in accordance with the option tarball-ttl. + #! This behavior is disabled in Pure evaluation mode. + fetchGit#: { + # allRefs: bool = false; + # name: string?; + # ref: string?; + # rev: string?; + # submodules: bool = false; + # url: string; + # } | string -> path + = builtins.fetchGit; + + #! TODO: Documentation + fetchMercurial#: T -> T + = builtins.fetchMercurial; + + #! Download the specified URL, unpack it and return the path of the unpacked tree. + #! The file must be a tape archive (.tar) compressed with gzip, bzip2 or xz. + #! The top-level path component of the files in the tarball is removed, + #! so it is best if the tarball contains a single directory at top level. + #! The typical use of the function is to obtain external Nix expression dependencies, + #! such as a particular version of Nixpkgs, e.g. + #! ``` + #! with import (fetchTarball "https://github.com/NixOS/nixpkgs/archive/nixos-14.12.tar.gz") {}; + #! stdenv.mkDerivation { … } + #! ``` + #! The fetched tarball is cached for a certain amount of time (1 hour by default) in ~/.cache/nix/tarballs/. + #! You can change the cache timeout either on the command line with `--tarball-ttl number-of-seconds` or + #! in the Nix configuration file by adding the line `tarball-ttl = number-of-seconds`. + #! Note that when obtaining the hash with nix-prefetch-url the option `--unpack` is required. + #! This function can also verify the contents against a hash. + #! In that case, the function takes a set instead of a URL. + #! The set requires the attribute url and the attribute `sha256`, e.g. + #! ``` + #! with import (fetchTarball { + #! url = "https://github.com/NixOS/nixpkgs/archive/nixos-14.12.tar.gz"; + #! sha256 = "1jppksrfvbk5ypiqdz4cddxdl8z6zyzdb2srq8fcffr327ld5jj2"; + #! }) {}; + #! stdenv.mkDerivation { … } + #! ``` + #! This function is not available if restricted evaluation mode ../command-ref/conf-file.md is enabled. + fetchTarball#: { + # url: string; + # sha256: string; + # } | string -> path + = builtins.fetchTarball; + + #! TODO: Documentation + fetchTree#: T -> T + = builtins.fetchTree; + + #! Download the specified URL and return the path of the downloaded file. + #! This function is not available if restricted evaluation mode ../command-ref/conf-file.md is enabled. + fetchurl#: { + # url: string; + # sha256: string; + # } | string -> path + = builtins.fetchurl; + + #! Return a list consisting of the elements of the list for which the function returns true + filter#: (T -> bool) -> [ T ] -> [ T ] + = builtins.filter; + + #! TODO: Documentation, too long for now + filterSource#: T -> T + = builtins.filterSource; + + #! TODO: Documentation + findFile#: T -> T + = builtins.findFile; + + #! Converts an IEEE-754 double-precision floating-point number (double) to the next lower integer. + #! If the datatype is neither an integer nor a float, an evaluation error will be thrown. + floor#: integer | float -> integer + = builtins.floor; + + #! Reduce a list by applying a binary operator, from left to right, + #! e.g. `foldl' op nul [x0 x1 x2 ...]` returns `op (op (op nul x0) x1) x2) …`. + #! The operator is applied strictly, i.e., + #! its arguments are evaluated first. + #! For example, `foldl' (x: y: x + y) 0 [1 2 3]` evaluates to `6`. + foldl'#: (S -> T -> S) -> S -> [ T ] -> S + = builtins.foldl'; + + #! Convert a JSON string to a Nix value. + #! For example, + #! ``` + #! fromJSON ''{"x": [1, 2, 3], "y": null}'' + #! ``` + #! returns the value `{ x = [ 1 2 3 ]; y = null; }`. + fromJSON#: string -> T + = builtins.fromJSON; + + #! Convert a TOML string to a Nix value. + fromTOML#: string -> T + = builtins.fromTOML; + + #! Return a set containing the names of the formal arguments expected by the function f. + #! The value of each attribute is a bool denoting whether the corresponding argument has a default value. + #! For instance, `functionArgs ({ x, y ? 123}: ...)` returns `{ x = false; y = true; }`. + #! "Formal argument" here refers to the attributes pattern-matched by the function. + #! Plain lambdas are not included, e.g. `functionArgs (x: ...)` returns `{ }`. + functionArgs#: (T -> U) -> { string: bool } + = builtins.functionArgs; + + #! Generate list of size length, with each element i equal to the value returned by generator i. + #! For example, `genList (x: x * x) 5` returns the list `[ 0 1 4 9 16 ]`. + genList#: T -> T + = builtins.genList; + + #! Take an attrset with values named startSet and operator in order to return a list of attrsets + #! by starting with the startSet, recursively applying the operator function to each element. + #! The attrsets in the startSet and produced by the operator must each contain value named key, + #! which are comparable to each other. + #! The result is produced by repeatedly calling the operator for each element encountered with a unique key, + #! terminating when no new elements are produced. + #! For example, + #! ``` + #! genericClosure { + #! startSet = [ {key = 5;} ]; + #! operator = item: [{ + #! key = if (item.key / 2 ) * 2 == item.key + #! then item.key / 2 + #! else 3 * item.key + 1; + #! }]; + #! } + #! ``` + #! evaluates to `[ { key = 5; } { key = 16; } { key = 8; } { key = 4; } { key = 2; } { key = 1; } ]`. + genericClosure#: { + # startSet: [ { key: T; ... } ]; + # operator: T -> [ { key: T; ... } ] + # } -> [ { key: T; ... } ] + = builtins.genericClosure; + + #! Returns a attribute from set. + #! Evaluation aborts if the attribute does not exist. + #! This is a dynamic version of the . operator, since the attribute is an expression rather than an identifier. + getAttr#: string -> { string -> T } -> T | ! + = builtins.getAttr; + + #! TODO: Documentation + getContext#: T -> T + = builtins.getContext; + + #! Returns the value of an environment variable, or an empty string if the variable does not exist. + #! This function should be used with care, + #! as it can introduce all sorts of nasty environment dependencies in your Nix expression. + #! It is used in Nix Packages to locate the file ~/.nixpkgs/config.nix, + #! which contains user-local settings for Nix Packages. + #! That is, it does a getEnv "HOME" to locate the user’s home directory. + getEnv#: string -> string + = builtins.getEnv; + + #! Fetch a flake from a flake reference, and return its output attributes and some metadata. + #! For example: + #! ``` + #! (getFlake "nix/55bc52401966fbffa525c574c14f67b00bc4fb3a").packages.x86_64-linux.nix + #! ``` + #! Unless impure evaluation is allowed (--impure), the flake reference must be "locked", + #! e.g. contain a Git revision or content hash. + #! An example of an unlocked usage is: + #! ``` + #! (getFlake "github:edolstra/dwarffs").rev + #! ``` + #! This function is only available if you enable the experimental feature flakes. + getFlake#: { ... } | string -> flake + = builtins.getFlake; + + #! Groups elements of list together by the string returned from the function f called on each element. + #! It returns an attribute set + #! where each attribute value contains the elements of list + #! that are mapped to the same corresponding attribute name returned by f. + #! For example, `groupBy (substring 0 1) ["foo" "bar" "baz"]` + #! evaluates to `{ b = [ "bar" "baz" ]; f = [ "foo" ]; }` + groupBy#: (T -> string) -> [ T ] -> { string -> [ T ] } + = builtins.groupBy; + + #! hasAttr returns true if set has an attribute named s, and false otherwise. + #! This is a dynamic version of the ? operator, since s is an expression rather than an identifier. + hasAttr#: string -> { string -> T } -> bool + = builtins.hasAttr + or (name: attrs: attrs.${name} or true == attrs.${name} or false); + + #! TODO: Documentation + hasContext#: T -> bool + = builtins.hasContext; + + #! Return a base-16 representation of the cryptographic hash of the file at given path. + #! The hash algorithm specified must be one of "md5", "sha1", "sha256" or "sha512". + hashFile#: algorithm: string -> path -> T where algorithm in [ "md5" "sha1" "sha256" "sha512" ] + = builtins.hashFile; + + #! Return a base-16 representation of the cryptographic hash of given string. + #! The hash algorithm specified must be one of "md5", "sha1", "sha256" or "sha512". + hashString#: algorithm: string -> string -> T where algorithm in [ "md5" "sha1" "sha256" "sha512" ] + = builtins.hashString; + + #! Return the first element of a list; abort evaluation if the argument is not a list or is an empty list. + #! You can test whether a list is empty by comparing it with []. + head#: [ T ] -> T | ! + = builtins.head; + + #! TODO: Too long for now + import#: path -> T + = builtins.import; + + #! Return a set consisting of the attributes in the second set that also exist in the first set. + intersectAttrs#: { string -> T } -> { string -> U } -> { string -> U } + = builtins.intersectAttrs; + + #! Return true if e evaluates to a set, and false otherwise. + isAttrs#: T -> bool + = builtins.isAttrs; + + #! Return true if e evaluates to a bool, and false otherwise. + isBool#: T -> bool + = builtins.isBool + or (x: x == true || x == false); + + #! Return true if e evaluates to a float, and false otherwise. + isFloat#: T -> bool + = builtins.isFloat; + + #! Return true if e evaluates to a function, and false otherwise. + isFunction#: T -> bool + = builtins.isFunction; + + #! Return true if e evaluates to an integer, and false otherwise. + isInt#: T -> bool + = builtins.isInt; + + #! Return true if e evaluates to a list, and false otherwise. + isList#: T -> bool + = builtins.isList; + + #! DEPRECATED: + #! Return true if e evaluates to null, and false otherwise. + #! Just write e == null instead. + isNull#: T -> bool + = builtins.isNull + or (x: x == null); + + #! Return true if e evaluates to a path, and false otherwise. + isPath#: T -> bool + = builtins.isPath; + + #! Return true if e evaluates to a string, and false otherwise. + isString#: T -> bool + = builtins.isString; + + #! TODO: Documentation + langVersion#: integer + = builtins.langVersion; + + #! Return the length of a list. + length#: [ T ] -> integer + = builtins.length; + + #! Return true if the first number is less than the second number, and false otherwise. + lessThan#: number -> number -> bool + = builtins.lessThan + or (p: q: p < q); + + #! Construct a set from a list specifying the names and values of each attribute. + #! Each element of the list should be a set consisting of a string-valued attribute name + #! specifying the name of the attribute, and an attribute value specifying its value. + #! # Example + #! ``` + #! listToAttrs + #! [ { name = "foo"; value = 123; } + #! { name = "bar"; value = 456; } + #! ] + #! ``` + #! evaluates to `{ foo = 123; bar = 456; }`. + listToAttrs#: [ { name: string; value: T; } ] -> { string -> T } + = builtins.listToAttrs; + + #! Apply the function to each element in the list. + #! # Example + #! ``` + #! map (x: "foo" + x) [ "bar" "bla" "abc" ] + #! ``` + #! evaluates to `[ "foobar" "foobla" "fooabc" ]`. + map#: (T -> U) -> [ T ] -> [ U ] + = builtins.map; + + #! Apply function to every element of attrset. + #! # Example + #! ``` + #! mapAttrs (name: value: value * 10) { a = 1; b = 2; } + #! ``` + #! evaluates to `{ a = 10; b = 20; }`. + mapAttrs#: (string -> T -> U) -> { string -> T } -> { string -> U } + = builtins.mapAttrs; + + #! TODO: Too long for now + match#: regex -> string -> [ T ] | null where T: string | [ T ] + = builtins.match; + + #! Return the product of the two numbers. + mul#: number -> number -> number + = builtins.mul + or (p: q: p * q); + + #! TODO: Documentation + nixPath#: [ { path: string; prefix: string; } ] + = builtins.nixPath; + + #! TODO: Documentation + nixVersion#: string + = builtins.nixVersion; + + #! The value of the unit type. + null#: null + = builtins.null; + + #! Split the string into a package name and version. + #! The package name is everything up to but not including the first dash followed by a digit, + #! and the version is everything following that dash. + #! The result is returned in a set `{ name, version }`. + #! Thus, `parseDrvName "nix-0.12pre12876"` returns `{ name = "nix"; version = "0.12pre12876"; }`. + parseDrvName#: string -> { name: string; version: string; } + = builtins.parseDrvName; + + #! Given a predicate function, + #! this function returns an attrset containing a list named right, + #! containing the elements in list for which the predicate returned true, + #! and a list named wrong, + #! containing the elements for which it returned false. + #! # Examples + #! ``` + #! partition (x: x > 10) [1 23 9 3 42] + #! ``` + #! evaluates to + #! ``` + #! { right = [ 23 42 ]; wrong = [ 1 9 3 ]; } + #! ``` + partition#: (T -> bool) -> [ T ] -> { right: [ T ]; wrong: [ T ]; } + = builtins.partition; + + #! TODO: Too long for now + path#: T -> path + = builtins.path; + + #! Return true if the path path exists at evaluation time, and false otherwise. + pathExists#: path -> bool + = builtins.pathExists; + + #! Return a placeholder string for the specified output + #! that will be substituted by the corresponding output path at build time. + #! Typical outputs would be "out", "bin" or "dev". + placeholder#: string -> string + = builtins.placeholder; + + #! Return the contents of the directory path as a set mapping directory entries to the corresponding file type. + #! For instance, if directory A contains a regular file B and another directory C, + #! then `readDir ./A` will return the set `{ B = "regular"; C = "directory"; }`. + #! The possible values for the file type are "regular", "directory", "symlink" and "unknown". + readDir#: path -> { string -> string } + = builtins.readDir; + + #! Return the contents of the file path as a string. + readFile#: path -> string + = builtins.readFile; + + #! Remove the attributes listed in list from set. The attributes don’t have to exist in set. + #! # Example + #! ``` + #! removeAttrs { x = 1; y = 2; z = 3; } [ "a" "x" "z" ] + #! ``` + #! evaluates to `{ y = 2; }`. + removeAttrs#: { string -> T } -> [ string ] -> { string -> T } + = builtins.removeAttrs; + + #! Given string, replace every occurrence of the strings + #! in the first list + #! with the corresponding string in second list. + #! # Example + #! ``` + #! builtins.replaceStrings ["oo" "a"] ["a" "i"] "foobar" + #! ``` + #! evaluates to `"fabir"`. + replaceStrings#: [ string ] -> [ string ] -> string -> string + = builtins.replaceStrings; + + #! TODO: Documentation + scopedImport#: path -> T -> T + = builtins.scopedImport; + + #! Evaluate the first expression, + #! then evaluate and return the second. + #! This ensures that a computation is strict in the value of the first expression. + seq#: T -> U -> U + = builtins.seq; + + #! Return list in sorted order. + #! It repeatedly calls the function comparator with two elements. + #! The comparator should return true if the first element is less than the second, and false otherwise. + #! # Example + #! ``` + #! sort lessThan [ 483 249 526 147 42 77 ] + #! ``` + #! evaluates to `[ 42 77 147 249 483 526 ]`. + #! This is a stable sort: + #! It preserves the relative order of elements deemed equal by the comparator. + sort#: (T -> bool) -> [ T ] -> [ T ] + = builtins.sort; + + #! TODO: Too long for now + split#: regex -> string -> [ T ] where T: string | [ T ] + = builtins.split; + + #! Split a string representing a version into its components, + #! by the same version splitting logic underlying the version comparison + #! in `nix-env -u ../command-ref/nix-env.md#operation---upgrade`. + #! It basically splits the string at `.` and `-`. + splitVersion#: string -> [ string ] + = builtins.splitVersion; + + #! TODO: Documentation + storeDir + = builtins.storeDir; + + #! This function allows you to define a dependency on an already existing store path. + #! For example, + #! the derivation attribute `src = storePath /nix/store/f1d18v1y…-source` + #! causes the derivation to depend on the specified path, + #! which must exist or be substitutable. + #! Note that this differs from a plain path (e.g. `src = /nix/store/f1d18v1y…-source`) + #! in that the latter causes the path to be copied again to the Nix store, + #! resulting in a new path (e.g. `/nix/store/ld01dnzc…-source-source`). + #! This function is not available in pure evaluation mode. + storePath#: path -> path + = builtins.storePath; + + #! Return the length of the string in bytes. + #! Note that it does not know about unicode. + stringLength#: string -> integer + = builtins.stringLength; + + #! Return the difference between the two numbers. + sub#: number -> number -> number + = builtins.sub + or (p: q: p - q); + + #! Return the substring of a given string from character zero-based position start up to but not including start + len. + #! If start is greater than the length of the string, + #! an empty string is returned, and + #! if start + len lies beyond the end of the string, + #! only the substring up to the end of the string is returned. + #! The offset start must be non-negative. + #! For example `substring 0 3 "nixos"` evaluates to `"nix"`. + substring#: integer -> integer -> string -> string | ! + = builtins.substring; + + #! Return the second to last elements of a list; abort evaluation if the argument is an empty list. + #! Warning: This function should generally be avoided since it is inefficient: + #! Unlike Haskell's tail, it takes O(n) time, + #! so recursing over a list by repeatedly calling tail takes O(n^2) time. + tail#: [ T ] -> [ T ] | ! + = builtins.tail; + + #! Throw an error message. + #! This usually aborts Nix expression evaluation, + #! but in nix-env -qa and other commands that try to evaluate a set of derivations + #! to get information about those derivations, + #! a derivation that throws an error is silently skipped (which is not the case for abort). + throw#: string -> ! + = builtins.throw; + + #! TODO: Too long for now + toFile#: T -> path + = builtins.toFile; + + #! Return a string containing a JSON representation the given expression. + #! Strings, integers, floats, booleans, nulls and lists are mapped to their JSON equivalents. + #! Sets (except derivations) are represented as objects. + #! Derivations are translated to a JSON string containing the derivation’s output path. + #! Paths are copied to the store and represented as a JSON string of the resulting store path. + toJSON#: T -> string + = builtins.toJSON; + + #! DEPRECATED. + #! Use /. + "/path" to convert a string into an absolute path. + #! For relative paths, use ./. + "/path". + toPath#: T -> path + = builtins.toPath; + + #! Convert the expression to a string. + #! The expression can be: + #! * A string (in which case the string is returned unmodified). + #! * A path (e.g., toString /foo/bar yields "/foo/bar".) + #! * A set containing { __toString = self: ...; } or { outPath = ...; }. + #! * An integer or float. + #! * A list, in which case the string representations of its elements are joined with spaces. + #! * A bool (false yields "", true yields "1"). + #! * null, which yields the empty string. + #! Note that `toString` does not return an actual store path for paths, + #! even if the path is a store-path, e.g. when building a flake. + #! To ensure a path is copied to the nix store, use `"${fileName}"`. + toString#: T -> string where T: bool | float integer | null | path | string | [ T ] | { string -> T } + = builtins.toString; + + #! TODO: Too long for now + toXML#: T -> string + = builtins.toXML; + + #! Evaluate the first expression and print its abstract syntax representation on standard error. + #! Then return the second expression. + #! This function is useful for debugging. + trace#: T -> U -> U + = builtins.trace + or (x: x); + + #! Tautology + true#: bool + = builtins.true + or (1 == 1); + + #! Try to shallowly evaluate the expression. + #! Return a set containing the attributes + #! *[success] true if e evaluated successfully, false if an error was thrown + #! *[value] equalling the expression if successful and false otherwise. + #! `tryEval` will only prevent errors created by throw or assert from being thrown. + #! Errors tryEval will not catch are for example those created by abort and type errors generated by builtins. + #! Also note that this does not evaluate the expression deeply, + #! so `let e = { x = throw ""; }; in (tryEval e).success` will be true. + #! Using `deepSeq` one can get the expected result: + #! ``` + #! let + #! e = { x = throw ""; }; + #! in + #! (tryEval (deepSeq e e)).success + #! ``` + #! will be evaluated to false. + tryEval#: T -> { success: bool; value: T; } + = builtins.tryEval; + + #! Return a string representing the type of the value, + #! namely "int", "bool", "string", "path", "null", "set", "list", "lambda" or "float". + typeOf#: T -> string + = builtins.typeOf; + + #! TODO: Documentation + unsafeDiscardOutputDependency#: T -> T + = builtins.unsafeDiscardOutputDependency; + + #! TODO: Documentation + unsafeDiscardStringContext#: T -> T + = builtins.unsafeDiscardStringContext; + + #! TODO: Documentation + unsafeGetAttrPos#: T -> T + = builtins.unsafeGetAttrPos; + + #! Transpose a list of attribute sets into an attribute set of lists, then apply mapAttrs. + #! The function receives two arguments: + #! The attribute name and + #! a non-empty list of all values encountered for that attribute name. + #! The result is an attribute set where the attribute names are the union of the attribute names in each element of the list. + #! The attribute values are the return values of the function. + #! # Examples + #! ``` + #! zipAttrsWith + #! (name: values: { inherit name values; }) + #! [ { a = "x"; } { a = "y"; b = "z"; } ] + #! ``` + #! evaluates to + #! ``` + #! { + #! a = { name = "a"; values = [ "x" "y" ]; }; + #! b = { name = "b"; values = [ "z" ]; }; + #! } + #! ``` + zipAttrsWith#: T -> T + = builtins.zipAttrsWith; + }; + in + { inherit lib; }; +} \ No newline at end of file diff --git a/libs/secrets/default.nix b/libs/secrets/default.nix new file mode 100644 index 0000000..02269d0 --- /dev/null +++ b/libs/secrets/default.nix @@ -0,0 +1,23 @@ +{ core, store, ... } @ libs: + let + inherit(core) check library path target; + lib = library.load ./lib libs; + module = path.import ./module libs; + tests = check.load ./tests libs lib; + in + { + inherit lib tests; + + checks + = check tests + { + inherit store; + targetSystem = target.System.all.x86_64-linux; + }; + + nixosModules + = { + default = module; + vault = module; + }; + } \ No newline at end of file diff --git a/libs/secrets/flake.nix b/libs/secrets/flake.nix new file mode 100644 index 0000000..8b526a4 --- /dev/null +++ b/libs/secrets/flake.nix @@ -0,0 +1,16 @@ +{ + description = "Secrets"; + inputs + = { + libcore.url = "github:sivizius/nixfiles/development?dir=libs/core"; + libstore.url = "github:sivizius/nixfiles/development?dir=libs/store"; + #registries.url = "github:sivizius/nixfiles/development?dir=registries"; + }; + outputs + = { self, libcore, libstore, ... }: + let + core = libcore.lib { inherit self; debug.logLevel = "info"; }; + store = libstore.lib; + in + core.path.import ./. { inherit core self store; }; +} \ No newline at end of file diff --git a/libs/secrets/lib/default.nix b/libs/secrets/lib/default.nix new file mode 100644 index 0000000..fe944f3 --- /dev/null +++ b/libs/secrets/lib/default.nix @@ -0,0 +1,7 @@ +{ core, ... }: + Library "libsecrets" + { inherit core; } + { + secret = ./secret; + vault = ./vault; + } diff --git a/libs/secrets/lib/secret/default.nix b/libs/secrets/lib/secret/default.nix new file mode 100644 index 0000000..d7a3f90 --- /dev/null +++ b/libs/secrets/lib/secret/default.nix @@ -0,0 +1,311 @@ +{ core, ... }: + let + inherit(core) debug type; + + cannotMerge + = { type, ... } @ secret: + { ... } @ secret': + debug.panic [ "cannotMerge" type ] + { + text = "Cannot merge secrets:"; + data = { inherit secret secret'; }; + nice = true; + } + null; + + decrypt + = { + toSecret + = { encryptedFile, group, owner, ... }: + { + inherit encryptedFile group owner; + inherit(decrypt) type; + }; + + merge = cannotMerge; + + type = "decrypt"; + __functor + = { toSecret, type, ... }: + { encryptedFile, group ? null, owner ? null }: + Secret.instanciateAs type + { + inherit encryptedFile group owner; + + __functor + = { encryptedFile, ... } @ args: + { hash, vaultBasePath, ... }: + let + secret = hash encryptedFile; + in + { + secrets = { ${secret} = toSecret args; }; + value = loadPath.toValue { inherit secret vaultBasePath; }; + }; + }; + }; + + decryptGrafanaSecret + = { encryptedFile, group ? null, owner ? "grafana" }: + Secret.instanciateAs "decryptGrafanaSecret" + { + inherit encryptedFile group owner; + + merge = cannotMerge; + + __functor + = { encryptedFile, group, owner, ... } @ args: + { hash, vaultBasePath, ... }: + let + secret = hash encryptedFile; + in + { + secrets = { ${secret} = decrypt.toSecret args; }; + value = loadGrafanaSecret.toValue { inherit secret vaultBasePath; }; + }; + }; + + decryptVariable + = environment: + { encryptedFile, group ? null, owner ? null }: + Secret.instanciateAs "decryptVariable" + { + inherit encryptedFile environment group owner; + + merge = cannotMerge; + + __functor + = { encryptedFile, environment, ... } @ args: + { hash, vaultBasePath, ... }: + let + secret = hash encryptedFile; + secret' = hash environment; + in + { + secrets + = { + ${secret} = decrypt.toSecret args; + ${secret'} = generateEnvFile.toSecret { variables = [ secret ]; }; + }; + value = loadVariable.toValue { inherit secret vaultBasePath; }; + }; + }; + + generateEnvFile + = { + toSecret + = { group ? null, owner ? null, variables, ... }: + { + inherit group owner variables; + inherit(generateEnvFile) type; + }; + + type = "generateEnvFile"; + + merge + = { variables, ... } @ secret: + { ... } @ secret': + if secret.type == generateEnvFile.type + && secret'.type == generateEnvFile.type + then + secret + // { + variables + = variables + ++ secret'.variables; + } + else + cannotMerge secret secret'; + + __functor + = { toSecret, type, merge, ... }: + environment: + { group ? null, owner ? null, variables ? [] }: + Secret.instanciateAs type + { + inherit environment group owner merge variables; + + __functor + = { environment, ... } @ args: + { hash, vaultBasePath, ... }: + let + secret = hash environment; + in + { + secrets = { ${secret} = toSecret args; }; + value = loadPath.toValue { inherit secret vaultBasePath; }; + }; + }; + }; + + generateToken + = { + toSecret + = { generator ? null, group ? null, length ? null, owner ? null, ... } @ args: + debug.warn [ "generateToken" "toSecret" ] + { + text = "No owner set!"; + when = owner == null; + data = args; + } + { + inherit generator group length owner; + inherit(generateToken) type; + }; + + type = "generateToken"; + + merge = cannotMerge; + + __functor + = { toSecret, type, ... }: + identifier: + { generator ? null, group ? null, length ? null, owner ? null }: + Secret.instanciateAs type + { + inherit generator group identifier length owner; + + __functor + = { identifier, ... } @ args: + { hash, vaultBasePath, ... }: + let + secret = hash identifier; + in + { + secrets = { ${secret} = toSecret (args // { inherit secret; }); }; + value = loadPath.toValue { inherit secret vaultBasePath; }; + }; + }; + }; + + loadGrafanaSecret + = { + toValue + = { secret, vaultBasePath, ... }: + "$__file{${vaultBasePath}/${secret}}"; + + type = "loadGrafanaSecret"; + + merge = cannotMerge; + + __functor + = { toValue, type, ... }: + secret: + Secret.instanciateAs type + { + inherit secret; + + __functor + = { secret, ... }: + { vaultBasePath, ... }: + { + secrets = { ${secret} = null; }; + value = toValue { inherit secret vaultBasePath; }; + }; + }; + }; + + loadPath + = { + toValue + = { secret, vaultBasePath, ... }: + "${vaultBasePath}/${secret}"; + + type = "loadPath"; + + merge = cannotMerge; + + __functor + = { toValue, type, ... }: + secret: + Secret.instanciateAs type + { + inherit secret; + + __functor + = { secret, ... }: + { vaultBasePath, ... }: + { + secrets = { ${secret} = null; }; + value = toValue { inherit secret vaultBasePath; }; + }; + }; + }; + + loadTokenPath + = identifier: + Secret.instanciateAs "loadTokenPath" + { + inherit identifier; + + merge = cannotMerge; + + __functor + = { identifier, ... }: + { hash, vaultBasePath, ... }: + let + secret = hash identifier; + in + { + secrets = { ${secret} = null; }; + value = loadPath.toValue { inherit secret vaultBasePath; }; + }; + }; + + loadVariable + = { + toValue + = { secret, vaultBasePath, ... }: + "@_${secret}_@"; + + type = "loadVariable"; + + merge = cannotMerge; + + __functor + = { toValue, type, ... }: + secret: + Secret.instanciateAs type + { + inherit secret; + + __functor + = { secret, ... }: + { vaultBasePath, ... }: + { + secrets = { ${secret} = null; }; + value = toValue { inherit secret vaultBasePath; }; + }; + }; + }; + + Secret + = type "Secret" + { + inherit decrypt decryptGrafanaSecret decryptVariable + generateEnvFile generateToken + loadGrafanaSecret loadPath loadTokenPath loadVariable; + + decrypt' + = encryptedFile: + Secret.decrypt { inherit encryptedFile; }; + + decryptGrafanaSecret' + = encryptedFile: + Secret.decryptGrafanaSecret { inherit encryptedFile; }; + + decryptVariable' + = environment: + encryptedFile: + Secret.decryptVariable environment { inherit encryptedFile; }; + + generateEnvFile' + = environment: + Secret.generateEnvFile environment {}; + + generateToken' + = identifier: + Secret.generateToken identifier {}; + }; + in + Secret // { inherit Secret; } diff --git a/libs/secrets/lib/vault/default.nix b/libs/secrets/lib/vault/default.nix new file mode 100644 index 0000000..9e20171 --- /dev/null +++ b/libs/secrets/lib/vault/default.nix @@ -0,0 +1,57 @@ +{ core, secret, ... }: + let + inherit(core) debug list path set string type; + inherit(secret) Secret; + + defaultHasher + = value: + if path.isInstanceOf value + then + path.hash "sha256" value + else + string.hash "sha256" (string value); + + Vault + = type "Vault" + { + from + = { + hash ? defaultHasher, + vaultBasePath ? "/run/vault", + ... + }: + Vault.instanciate + { + inherit hash vaultBasePath; + __functor + = { hash, vaultBasePath, ... } @ self: + source: + this: + (Secret.expect this) { inherit hash source vaultBasePath; }; + }; + + update + = set.fold + ( + { ... } @ secrets: + name: + secret': + let + secret = secrets.${name} or null; + in + secrets + // { + ${name} + = if secret' == null || secret == secret' + then + secret + else if secret == null + then + secret' + else + Secret.${secret.type}.merge secret secret'; + } + ); + }; + in + Vault // { inherit Vault; } diff --git a/libs/secrets/module/config.nix b/libs/secrets/module/config.nix new file mode 100644 index 0000000..44bbe44 --- /dev/null +++ b/libs/secrets/module/config.nix @@ -0,0 +1,23 @@ +{ core, ... } @ libs: +{ config, lib, ... } @ env: + let + inherit(core) list path; + inherit(initVault { inherit(config.vault) key secrets vault; }) errors vault; + initVault = path.import ./vault.nix libs env; + in + lib.mkIf (config.vault.secrets != {}) + { + assertions + = list.map + (message: { assertion = false; inherit message; }) + errors; + environment.loginShellInit + = '' + echo "Check vault of user: $USER..." + ''; + system.activationScripts.initialise-vault + = { + deps = [ "users" "groups" ]; + text = vault; + }; + } diff --git a/libs/secrets/module/default.nix b/libs/secrets/module/default.nix new file mode 100644 index 0000000..67372d9 --- /dev/null +++ b/libs/secrets/module/default.nix @@ -0,0 +1,9 @@ +{ core, ... } @ libs: +{ config, lib, pkgs, ... } @ env: + let + inherit(core) path; + in + { + options.vault = path.import ./options.nix libs env; + config = path.import ./config.nix libs env; + } diff --git a/libs/secrets/module/gpg.nix b/libs/secrets/module/gpg.nix new file mode 100644 index 0000000..7049dc8 --- /dev/null +++ b/libs/secrets/module/gpg.nix @@ -0,0 +1,24 @@ +{ ... }: +{ pkgs, ... }: +{ + decrypt + = { homedir, ... }: + encryptedFile: + decryptedFile: + [ + ''${pkgs.gnupg}/bin/gpg --homedir ${homedir} --decrypt "${encryptedFile}" > "${decryptedFile}"'' + ]; + + enableSmartCard + = { homedir, ... }: + [ ''${pkgs.gnupg}/bin/gpg --homedir ${homedir} --card-status > /dev/null 2> /dev/null'' ]; + + importKey + = { homedir, ... }: + key: + [ ''${pkgs.gnupg}/bin/gpg --homedir ${homedir} --batch --passphrase "" --import "${key}"'' ]; + + startAgent + = { daemon, homedir, ... }: + "${pkgs.gnupg}/bin/gpg-agent --homedir ${homedir} --daemon ${daemon}"; +} diff --git a/libs/secrets/module/options.nix b/libs/secrets/module/options.nix new file mode 100644 index 0000000..93e2138 --- /dev/null +++ b/libs/secrets/module/options.nix @@ -0,0 +1,97 @@ +{ ... }: +{ lib, ... }: + let + inherit(lib) types; + + secretType + = types.submodule + { + options + = { + encryptedFile + = lib.mkOption + { + type = types.nullOr types.path; + default = null; + description = "Path to an encrypted secret to decrypt."; + }; + generator + = lib.mkOption + { + type = types.nullOr types.str; + default = "[:graph:]"; + description = "Generator pattern of token."; + example = "[0-9a-f]"; + }; + group + = lib.mkOption + { + type = types.nullOr types.str; + default = null; + description + = '' + The group of this secret. + If not set (default), only the owner can read this secret. + However, the group is set to the owner’s login-group. + ''; + example = "network"; + }; + length + = lib.mkOption + { + type = types.nullOr types.ints.positive; + default = 32; + description = "Length of generated token."; + example = 64; + }; + owner + = lib.mkOption + { + type = types.nullOr types.str; + default = "root"; + description + = '' + The owner of this secret. + ''; + example = "user"; + }; + type + = lib.mkOption + { + type = types.enum [ "decrypt" "generateEnvFile" "generateToken" ]; + description = "Type of this secret."; + }; + variables + = lib.mkOption + { + type = types.nullOr (types.listOf types.str); + default = null; + description = "List of secrets to generate an environment file from."; + }; + }; + }; + in + { + key + = lib.mkOption + { + type = types.str; + default = "/var/vault.gpg"; + description = "Private pgp-key without passphrase!"; + }; + secrets + = lib.mkOption + { + type = types.attrsOf secretType; + default = {}; + description = "Set of secrets."; + }; + vault + = lib.mkOption + { + type = types.str; + default = "/run/vault"; + example = "/run/secrets"; + description = "Path to the Vault"; + }; + } diff --git a/libs/secrets/module/vault.nix b/libs/secrets/module/vault.nix new file mode 100644 index 0000000..fa5e70e --- /dev/null +++ b/libs/secrets/module/vault.nix @@ -0,0 +1,166 @@ +{ core, self, store, ... } @ libs: +{ config, pkgs, ... } @ env: + let + inherit(core) list path set string type; + gpg = path.import ./gpg.nix libs env; + + checkSecrets + = set.mapToListConcatted + ( + name: + value: + let + expect + = entry: + if value.${entry} != null + then + [] + else + [ "Secret `${name}` is of type `${value.type}`, but is missing `${entry}`." ]; + extra + = entry: + if value.${entry} != null + then + [ "Secret `${name}` is of type `${value.type}`, but `${entry}` was set." ] + else + []; + in + if value.type or null != null + then + { + decrypt = (expect "encryptedFile") ++ (extra "variables"); + generateEnvFile = (extra "encryptedFile") ++ (expect "variables"); + generateToken = (extra "encryptedFile") ++ (extra "variables"); + }.${value.type} or [ "Unknown/unimplemented type `${value.type}`." ] + else if value == null then [ "${name} is null, missing generateToken?" ] + else if list.isInstanceOf value then [ "${name} is a list, missing generateEnvFile?" ] + else [ "${name} is invalid: ${type.getPrimitive value}" ] + ); + + decryptFiles + = { homedir, vaultBasePath } @ args: + set.mapToListConcatted + ( + name: + { group, owner, encryptedFile, type, ... }: + let + fileName = "${vaultBasePath}/${name}"; + in + if type == "decrypt" + then + (gpg.decrypt args encryptedFile fileName) + ++ (setPermissions { inherit fileName group owner; }) + else + [] + ); + + generateEnvFiles + = { vaultBasePath, ... }: + set.mapToListConcatted + ( + name: + { group, owner, type, variables, ... }: + if type == "generateEnvFile" + then + let + fileName = "${vaultBasePath}/${name}"; + in + [ ''echo -n "" > "${fileName}"'' ] + ++ ( + list.map + ( + variable: + ''echo "_${variable}_=\"$(${utils}/cat "${vaultBasePath}/${variable}")\"" >> "${fileName}"'' + ) + variables + ) + ++ (setPermissions { inherit fileName group owner; }) + else + [] + ); + + generateTokens + = { vaultBasePath, ... }: + set.mapToListConcatted + ( + name: + { generator, group, length, owner, type, ... }: + if type == "generateToken" + then + let + generator' = if generator != null then generator else "[:graph:]"; + length' = if length != null then string length else "32"; + getRandom = "${utils}/cat /dev/urandom"; + filterChars = "${utils}/tr --delete --complement \"${generator'}\""; + takeChars = "${utils}/head --bytes \"${length'}\""; + fileName = "${vaultBasePath}/${name}"; + generate = ''${getRandom} | ${filterChars} | ${takeChars} > "${fileName}"''; + in + [ generate ] + ++ (setPermissions { inherit fileName group owner; }) + else + [] + ); + + setPermissions + = { fileName, group, owner }: + let + ifGroup = value: if group != null then value else ""; + owner' = if owner != null then owner else "root"; + in + [ + ''${utils}/chmod --changes --recursive u=r,g=${ifGroup "r"},o= "${fileName}"'' + ''${utils}/chown --changes --recursive "${owner'}:${ifGroup group}" "${fileName}"'' + ]; + + utils = "${pkgs.coreutils}/bin"; + in + { + homedir ? "/tmp/keyring", + key, + secrets, + vault + }: + let + args + = { + inherit homedir; + vaultBasePath = vault; + }; + daemon + = pkgs.writeShellScript "initVault.sh" + ( + string.concatLines + ( + [ + ''set -e'' + ''echo "initialise ${vault}..."'' + ''${utils}/install --mode u=rwx,g=x,o=x --directory "${vault}/"'' + ] +# ++ [ ''echo "enable smart card..."'' ] +# ++ ( gpg.enableSmartCard args ) + ++ [ ''echo "import vault key ${key}..."'' ] + ++ ( gpg.importKey args key ) + ++ [ ''echo "decrypt files..."'' ] + ++ ( decryptFiles args secrets ) + ++ [ ''echo "generate tokens..."'' ] + ++ ( generateTokens args secrets ) + ++ [ ''echo "generate environment files..."'' ] + ++ ( generateEnvFiles args secrets ) + ++ [ + ''echo "...done"'' + ''exit 0'' + ] + ) + ); + in + { + errors = checkSecrets secrets; + vault + = '' + ${utils}/rm --recursive --force ${homedir} + ${utils}/install --mode u=rwx,g=,o= --directory ${homedir} + ${gpg.startAgent { inherit daemon homedir; }} + ${utils}/rm --recursive ${homedir} + ''; + } diff --git a/libs/secrets/tests/default.nix b/libs/secrets/tests/default.nix new file mode 100644 index 0000000..8babf9f --- /dev/null +++ b/libs/secrets/tests/default.nix @@ -0,0 +1,14 @@ +{ core, ... }: +{ secret, vault, ... } @ lib: + let + inherit(core) set; + in + { + deepSeqAll + = set.mapValues + ( + module: + ({ ... }: module) + ) + lib; + } \ No newline at end of file diff --git a/libs/store/default.nix b/libs/store/default.nix new file mode 100644 index 0000000..2e562b8 --- /dev/null +++ b/libs/store/default.nix @@ -0,0 +1,15 @@ +{ core, ... } @ libs: + let + inherit(core) check library set target; + lib = library.load ./lib libs; + tests = check.load ./tests libs lib; + in + { + inherit lib tests; + + checks + = check tests + { + targetSystem = target.System.all.x86_64-linux; + }; + } \ No newline at end of file diff --git a/libs/store/flake.nix b/libs/store/flake.nix new file mode 100644 index 0000000..9ee879a --- /dev/null +++ b/libs/store/flake.nix @@ -0,0 +1,13 @@ +{ + description = "Store"; + inputs + = { + libcore.url = "github:sivizius/nixfiles/development?dir=libs/core"; + }; + outputs + = { self, libcore, nixpkgs, ... }: + let + core = libcore.lib { inherit self; debug.logLevel = "info"; }; + in + core.path.import ./. { inherit core; }; +} \ No newline at end of file diff --git a/libs/store/lib/default.nix b/libs/store/lib/default.nix new file mode 100644 index 0000000..1db1e80 --- /dev/null +++ b/libs/store/lib/default.nix @@ -0,0 +1,6 @@ +{ core, ... }: + Library "libstore" + { inherit core; } + { + write = ./write.nix; + } diff --git a/libs/store/lib/write.nix b/libs/store/lib/write.nix new file mode 100644 index 0000000..2e94e55 --- /dev/null +++ b/libs/store/lib/write.nix @@ -0,0 +1,198 @@ +{ core, ... }: + let + inherit(core) debug derivation library list path set string; + + buildTextFile + = { body, fileName, buildSystem, name, permissions, registries }: + let + system = string buildSystem; + pkgs = (registries { targetSystem = buildSystem; }).nix; + directory + = derivation + { + args = [ writeTextFile ]; + builder = "${pkgs.bash}/bin/bash"; + # Environment Variables + coreutils = "${pkgs.coreutils-full}/bin"; + inherit body fileName name permissions system; + }; + in + "${directory}/${fileName}"; + + buildDirectory + = { body, buildSystem, name, registries }: + let + builder + = writeScriptFile + { + name = "${name}-builder"; + inherit buildSystem registries; + body = "${shebang}\n${string.concatLines mkdir}\n${string.concatLines link}"; + fileName = "${name}-builder.sh"; + }; + link + = set.mapToList + (dst: src: ''$coreutils/ln -s "${src}" "$out/${dst}"'') + body; + mkdir + = set.values + ( + list.fold + ( + result: + fileName: + let + dir = path.getDirectory fileName; + in + result + // { + ${dir} = ''$coreutils/mkdir -p "$out/${dir}"''; + } + ) + {} + (set.names body) + ); + pkgs = (registries { targetSystem = buildSystem; }).nix; + shebang = "#!${pkgs.bash}/bin/sh"; + in + debug.info "buildDirectory" + { + text = "${name}"; + data = { inherit builder link mkdir; }; + nice = true; + } + ( + derivation + { + inherit builder name; + coreutils = "${pkgs.coreutils-full}/bin"; + system = "${buildSystem}"; + } + ); + + writeConfigFile + = { ... } @ this: + buildTextFile (this // { permissions = "444"; }); + + writeScriptFile + = { ... } @ this: + buildTextFile (this // { permissions = "555"; }); + + writeTextFile + = path.toFile "writeTextFile.sh" + '' + $coreutils/mkdir $out + echo -n "$body" > $out/$fileName + $coreutils/chmod $permissions $out/$fileName + ''; + in + library.NeedInitialisation + ( + { ... } @ self: + { buildSystem, registries, targetSystem, ... } @ args: + set.callValues args self + ) + { + configFile + = { buildSystem, registries, ... }: + { fileName, name ? null }: + body: + writeConfigFile { inherit body fileName buildSystem name registries; }; + + scriptFile + = { buildSystem, registries, ... }: + { fileName, name ? null }: + body: + writeScriptFile { inherit body fileName buildSystem name registries; }; + + bashScript + = { buildSystem, registries, targetSystem, ... }: + name: + body: + + let + shebang = "#!${(registries { inherit targetSystem; }).nix.bash}/bin/bash"; + in + writeScriptFile + { + inherit buildSystem name registries; + body = "${shebang}\n${body}"; + fileName = "${name}.sh"; + }; + + bashScript' + = { buildSystem, registries, ... }: + name: + body: + let + shebang = "#!${(registries { targetSystem = buildSystem; }).nix.bash}/bin/bash"; + in + writeScriptFile + { + inherit buildSystem name registries; + body = "${shebang}\n${body}"; + fileName = "${name}.sh"; + }; + + directory + = { buildSystem, registries, ... }: + name: + { ... } @ body: + buildDirectory { inherit body buildSystem name registries; }; + + pythonScript + = { buildSystem, registries, targetSystem, ... }: + name: + body: + let + shebang = "#!${(registries { inherit targetSystem; }).nix.bash}/bin/python3"; + in + writeScriptFile + { + inherit buildSystem name registries; + body = "${shebang}\n${body}"; + fileName = "${name}.py"; + }; + + pythonScript' + = { buildSystem, registries, ... }: + name: + body: + let + shebang = "#!${(registries { targetSystem = buildSystem; }).nix.bash}/bin/python3"; + in + writeScriptFile + { + inherit buildSystem name registries; + body = "${shebang}\n${body}"; + fileName = "${name}.py"; + }; + + shellScript + = { buildSystem, registries, targetSystem, ... }: + name: + body: + let + shebang = "#!${(registries { inherit targetSystem; }).nix.bash}/bin/sh"; + in + writeScriptFile + { + inherit buildSystem name registries; + body = "${shebang}\n${body}"; + fileName = "${name}.sh"; + }; + + shellScript' + = { buildSystem, registries, ... }: + name: + body: + let + shebang = "#!${(registries { targetSystem = buildSystem; }).nix.bash}/bin/sh"; + in + writeScriptFile + { + inherit buildSystem name registries; + body = "${shebang}\n${body}"; + fileName = "${name}.sh"; + }; + } diff --git a/libs/store/tests/default.nix b/libs/store/tests/default.nix new file mode 100644 index 0000000..6de92d3 --- /dev/null +++ b/libs/store/tests/default.nix @@ -0,0 +1,10 @@ +{ core, ... }: +{ ... } @ lib: + let + inherit(core) expression; + in + { + deepSeqAll + = { ... }: + expression.deepSeq lib lib; + } diff --git a/libs/web/default.nix b/libs/web/default.nix new file mode 100644 index 0000000..df361aa --- /dev/null +++ b/libs/web/default.nix @@ -0,0 +1,17 @@ +{ core, ... } @ libs: + let + inherit(core) check library path string target; + lib = library.load ./lib libs; + module = path.import ./module libs; + tests = check.load ./tests libs lib; + in + { + inherit lib tests; + checks = check tests {}; + + nixosModules + = { + default = module; + web = module; + }; + } diff --git a/libs/web/flake.nix b/libs/web/flake.nix new file mode 100644 index 0000000..ad8521f --- /dev/null +++ b/libs/web/flake.nix @@ -0,0 +1,18 @@ +{ + description = "Build Websites."; + inputs + = { + libcore.url = "github:sivizius/nixfiles/development?dir=libs/core"; + nixpkgs.url = "github:sivizius/nixpkgs/master"; + }; + outputs + = { self, libcore, nixpkgs, ... }: + let + core = libcore.lib { inherit self; debug.logLevel = "info"; }; + in + core.path.import ./. + { + inherit core; + inherit(nixpkgs) lib; + }; +} diff --git a/libs/web/lib/css/default.nix b/libs/web/lib/css/default.nix new file mode 100644 index 0000000..19882dc --- /dev/null +++ b/libs/web/lib/css/default.nix @@ -0,0 +1,53 @@ +{ core, ... }: + let + inherit(core) debug indentation list path set string type; + + formatAttributes + = prefix: + { ... } @ attributes: + list.concat + ( + set.mapToList + ( + name: + value: + if set.isInstanceOf value + && value.__toString or null == null + then + formatAttributes "${prefix}${name}-" value + else + [ "${prefix}${name}: ${string value};" ] + ) + attributes + ); + + CSS + = type "CSS" + { + from + = { ... } @ definition: + CSS.instanciate + { + inherit definition; + + __toString + = { definition, ... }: + indentation {} + ( + list.concat + ( + set.mapToList + ( + selector: + { ... } @ attributes: + [ "${selector} {" indentation.more ] + ++ (formatAttributes "" attributes) + ++ [ indentation.less "}" ] + ) + definition + ) + ); + }; + }; + in + CSS // { inherit CSS; } diff --git a/libs/web/lib/default.nix b/libs/web/lib/default.nix new file mode 100644 index 0000000..c616e5f --- /dev/null +++ b/libs/web/lib/default.nix @@ -0,0 +1,7 @@ +{ core, ... }: + Library "libweb" + { inherit core; } + { + css = ./css; + html = ./html; + } diff --git a/libs/web/lib/html/default.nix b/libs/web/lib/html/default.nix new file mode 100644 index 0000000..9582037 --- /dev/null +++ b/libs/web/lib/html/default.nix @@ -0,0 +1,229 @@ +{ core, ... }: + let + inherit(core) debug indentation list path set string type; + + flat + = body: + type.matchPrimitiveOrPanic body + { + list = list.concatMap flat body; + null = []; + set + = if Tag.isInstanceOf body + then + Tag.flat body + else + [ body ]; + string = [ body ]; + }; + + formatHead + = { + _blank ? null, + _parent ? null, + _self ? null, + _top ? null, + application-name ? null, + author ? null, + charset ? "UTF-8", + content-security-policy ? null, + content-type ? null, + default-style ? null, + description ? null, + generator ? null, + icon ? null, + keywords ? null, + refresh ? null, + script ? null, + scripts ? [], + style ? null, + stylesheets ? {}, + title ? null, + viewport ? null, + }: + let + inherit(list) ifOrEmpty; + link + = rel: + set.mapToList + ( + href: + { ... } @ attrs: + tags.link (attrs // { inherit href rel; }) + ); + in + flat + ([] + ++ (ifOrEmpty (_blank != null) (tags.base { target = "_blank"; href = _blank; } )) + ++ (ifOrEmpty (_parent != null) (tags.base { target = "_parent"; href = _parent; } )) + ++ (ifOrEmpty (_self != null) (tags.base { target = "_self"; href = _self; } )) + ++ (ifOrEmpty (_top != null) (tags.base { target = "_top"; href = _top; } )) + ++ (ifOrEmpty (icon != null) (tags.link ( icon // { rel = "icon"; } ) )) + ++ (link "stylesheet" stylesheets) + ++ (ifOrEmpty (charset != null) (tags.meta { inherit charset; } )) + ++ (ifOrEmpty (application-name != null) (tags.meta { name = "application-name"; content = application-name; } )) + ++ (ifOrEmpty (author != null) (tags.meta { name = "author"; content = author; } )) + ++ (ifOrEmpty (content-security-policy != null) (tags.meta { http-equiv = "content-security-policy"; content = content-security-policy; } )) + ++ (ifOrEmpty (content-type != null) (tags.meta { http-equiv = "content-type"; content = content-type; } )) + ++ (ifOrEmpty (default-style != null) (tags.meta { http-equiv = "default-style"; content = default-style; } )) + ++ (ifOrEmpty (description != null) (tags.meta { name = "description"; content = description; } )) + ++ (ifOrEmpty (generator != null) (tags.meta { name = "generator"; content = generator; } )) + ++ (ifOrEmpty (keywords != null) (tags.meta { name = "keywords"; content = keywords; } )) + ++ (ifOrEmpty (refresh != null) (tags.meta { http-equiv = "refresh"; content = refresh; } )) + ++ (ifOrEmpty (viewport != null) (tags.meta { name = "viewport"; content = viewport; } )) + ++ (list.map (src: tags.script { inherit src; } null) scripts) + ++ (ifOrEmpty (script != null) (tags.script script )) + ++ (ifOrEmpty (style != null) (tags.style style )) + ++ (ifOrEmpty (title != null) (tags.title title )) + ); + + formatHead' + = head: + type.matchPrimitiveOrPanic head + { + list = flat head; + set = formatHead head; + }; + + tags + = set.map + ( + name: + { ... } @ data: + data // (Tag name) + ) + (path.import ./tags.nix); + + Comment + = body: + if list.isInstanceOf body + then + [ "" ] + else + [ "" ]; + + HTML + = type "HTML" + { + from + = { language ? null, ... }: + HTML.instanciate + { + inherit language; + lines = [ "" ]; + + __functor + = { language, lines, ... } @ self: + { head ? {}, body ? [] }: + self + // { + __functor = null; + lines + = lines + ++ ( + flat + ( + tags.html + ( + if language != null + then + { lang = language; } + else + {} + ) + [ + (tags.head (formatHead head)) + (tags.body (flat body)) + ] + ) + ); + }; + + __toString + = { lines, ... }: + indentation {} lines; + }; + }; + + Tag + = let + mapAttributes + = string.concatMapped' + ( + name: + value: + if value != null + then + " ${name}=\"${string value}\"" + else + " ${name}" + ); + in + type "Tag" + { + flat + = { attributes, body, name, ... } @ tag: + if list.isInstanceOf body + then + [ "<${name}${mapAttributes attributes}>" indentation.more ] + ++ (flat body) + ++ [ indentation.less "" ] + else + [ "${tag}" ]; + + from + = name: + Tag.instanciate + { + inherit name; + attributes = {}; + body = null; + expectBody = false; + + __functor + = { attributes, body, expectBody, name, ... } @ self: + attrsOrBody: + let + isAttributes + = !expectBody + && set.isInstanceOf attrsOrBody + && attrsOrBody.__type__ or null == null; + in + self + // ( + if isAttributes then { attributes = attrsOrBody; } + else if attrsOrBody == null then {} + else if body == null then { body = attrsOrBody; } + else if string.isInstanceOf body then { body = "${body}${string attrsOrBody}"; } + else + debug.panic [ "Tag" "__functor" ] + { + text = "Cannot extend body:"; + data = body; + } + null + ) + // { expectBody = true; }; + + __toString + = { attributes, body, name, ... } @ self: + type.matchPrimitiveOrPanic body + { + null = "<${name}${mapAttributes attributes} />"; + list + = indentation {} + ( + [ "<${name}${mapAttributes attributes}>" indentation.more ] + ++ (flat body) + ++ [ indentation.less "" ] + ); + string = "<${name}${mapAttributes attributes}>${body}"; + }; + }; + }; + in + HTML + // { inherit Comment HTML Tag tags; } + // ( tags ) diff --git a/libs/web/lib/html/tags.nix b/libs/web/lib/html/tags.nix new file mode 100644 index 0000000..106f532 --- /dev/null +++ b/libs/web/lib/html/tags.nix @@ -0,0 +1,113 @@ + +{ + a = { }; + abbr = { }; + address = { }; + area = { }; + article = { }; + aside = { }; + audio = { }; + b = { }; + base = { }; + bdi = { }; + bdo = { }; + blockquote = { }; + body = { }; + br = { }; + button = { }; + canvas = { }; + caption = { }; + cite = { }; + code = { }; + col = { }; + colgroup = { }; + data = { }; + datalist = { }; + dd = { }; + del = { }; + details = { }; + dfn = { }; + dialog = { }; + div = { }; + dl = { }; + dt = { }; + em = { }; + embed = { }; + fieldset = { }; + figcaption = { }; + figure = { }; + footer = { }; + form = { }; + h1 = { }; + h2 = { }; + h3 = { }; + h4 = { }; + h5 = { }; + h6 = { }; + head = { }; + header = { }; + hr = { }; + html = { }; + i = { }; + iframe = { }; + img = { }; + input = { }; + ins = { }; + kbd = { }; + label = { }; + legend = { }; + li = { }; + link = { }; + main = { }; + map = { }; + mark = { }; + meta = { }; + meter = { }; + nav = { }; + noscript = { }; + object = { }; + ol = { }; + optgroup = { }; + option = { }; + output = { }; + p = { }; + param = { }; + picture = { }; + pre = { }; # TODO: Disable indentation? + progress = { }; + q = { }; + rp = { }; + rt = { }; + ruby = { }; + s = { }; + samp = { }; + script = { }; + section = { }; + select = { }; + small = { }; + source = { }; + span = { }; + strong = { }; + style = { }; + sub = { }; + summary = { }; + sup = { }; + svg = { }; + table = { }; + tbody = { }; + td = { }; + template = { }; + textarea = { }; + tfoot = { }; + th = { }; + thead = { }; + time = { }; + title = { }; + tr = { }; + track = { }; + u = { }; + ul = { }; + var = { }; + video = { }; + wbr = { }; +} diff --git a/libs/web/module/default.nix b/libs/web/module/default.nix new file mode 100644 index 0000000..5696dfe --- /dev/null +++ b/libs/web/module/default.nix @@ -0,0 +1,38 @@ +{ lib, ... }: + let + inherit(lib) types; + in + { + config = {}; + options.websites + = lib.mkOption + { + type = types.attrs; + default = {}; + description + = '' + Set of sets of locations. + The subdomains are the keys of the outer set, + while keys of the inner set are paths to individual locations. + ''; + example + = lib.literalExpression + '' + { + www."/" = { + root = { + "index.html" = HTML { language = "en"; } { + head = { + title = "My Homepage"; + }; + body = with HTML; [ + (h1' "Hello World") + (p' "How are you doing?") + ]; + }; + }; + }; + } + ''; + }; + } diff --git a/libs/web/tests/default.nix b/libs/web/tests/default.nix new file mode 100644 index 0000000..eea734d --- /dev/null +++ b/libs/web/tests/default.nix @@ -0,0 +1,7 @@ +{ core, ... }: +{ ... } @ lib: + let + inherit(core); + in + { + } \ No newline at end of file diff --git a/licences/flake.nix b/licences/flake.nix new file mode 100644 index 0000000..16e0ec0 --- /dev/null +++ b/licences/flake.nix @@ -0,0 +1,12 @@ +{ + description = "Licences"; + inputs + = { + nixpkgs.url = "github:NixOS/nixpkgs/master"; + }; + outputs + = { nixpkgs, ... }: + { + licences = nixpkgs.lib.licenses; + }; +} \ No newline at end of file diff --git a/maintainers/flake.nix b/maintainers/flake.nix new file mode 100644 index 0000000..c84a568 --- /dev/null +++ b/maintainers/flake.nix @@ -0,0 +1,26 @@ +{ + description = "Maintainers and Teams"; + inputs + = { + libconfig.url = "github:sivizius/nixfiles/development?dir=libs/config"; + libcore.url = "github:sivizius/nixfiles/development?dir=libs/core"; + }; + outputs + = { libconfig, libcore, ... }: + let + context = [ "maintainers" ]; + inherit(libcore.lib) path; + inherit(libconfig.lib) maintainers; + + import' + = directory: + path.import + directory + { inherit(maintainers) GitHub Fingerprint Maintainer Team; } + { inherit people teams; }; + + people = maintainers.checkPeople (import' ./people); + teams = maintainers.checkTeams (import' ./teams); + in + { inherit people teams; }; +} diff --git a/maintainers/people/default.nix b/maintainers/people/default.nix new file mode 100644 index 0000000..3494f9a --- /dev/null +++ b/maintainers/people/default.nix @@ -0,0 +1,19 @@ +{ Maintainer, GitHub, Fingerprint, ... }: +{ teams, ... }: +{ + _sivizius + = Maintainer "Sebastian Walz" + { + contact + = { + e-mail = "sivizius@sivizius.eu"; + matrix = "@sivizius:matrix.org"; + }; + github = GitHub "sivizius" 1690450; + keys + = [ + (Fingerprint "…") + ]; + teams = with teams; []; + }; +} diff --git a/maintainers/teams/default.nix b/maintainers/teams/default.nix new file mode 100644 index 0000000..c9628fe --- /dev/null +++ b/maintainers/teams/default.nix @@ -0,0 +1,14 @@ +{ Team, ... }: +{ people, ... }: +{ + core + = Team "Core" + { + about = "Inner Circle of the Project"; + founded = "2022-10-03": + }; + library + = Team "Library" + { + }; +} diff --git a/modules/default.nix b/modules/default.nix new file mode 100644 index 0000000..c96b934 --- /dev/null +++ b/modules/default.nix @@ -0,0 +1,9 @@ +{ config, core, foreign, ... } @ libs: + let + inherit(core) path; + inherit(config) modules; + in + { + legacyModules = path.import ./legacyModules libs; + modules = modules.load ./modules; + } \ No newline at end of file diff --git a/modules/flake.nix b/modules/flake.nix new file mode 100644 index 0000000..0e6b29e --- /dev/null +++ b/modules/flake.nix @@ -0,0 +1,36 @@ +{ + description = "Sivizius’ custom (modified) NixOS-modules."; + inputs + = { + libcore.url = "github:sivizius/nixfiles/development?dir=libs/core"; + libconfig.url = "github:sivizius/nixfiles/development?dir=libs/config"; + + nixpkgs.url = "github:sivizius/nixpkgs/master"; + + home-manager.url = "github:nix-community/home-manager/master"; + simple-nix-mailserver.url = "git+https://gitlab.com/simple-nixos-mailserver/nixos-mailserver.git"; + }; + outputs + = { + self, + libcore, + libconfig, + + # Foreign Modules + home-manager, + nixpkgs, + simple-nix-mailserver, + ... + }: + let + core = libcore.lib { inherit self; debug.logLevel = "info"; }; + inherit(core) path; + in + path.import ./. + { + inherit core; + context = [ "modules" ]; + config = libconfig.lib { inherit self; }; + foreign = { inherit home-manager nixpkgs simple-nix-mailserver; }; + }; +} diff --git a/modules/legacyModules/default.nix b/modules/legacyModules/default.nix new file mode 100644 index 0000000..6dc8839 --- /dev/null +++ b/modules/legacyModules/default.nix @@ -0,0 +1,19 @@ +{ core, foreign, ... } @ libs: + let + inherit(core) path; + inherit(foreign) home-manager nixpkgs simple-nix-mailserver; + in + { + nixos + = { + inherit(nixpkgs.nixosModules) notDetected; + inherit(home-manager.nixosModules) home-manager; + default + = { + _file = "${nixpkgs}/nixos/modules/module-list.nix"; + imports = path.import "${nixpkgs}/nixos/modules/module-list.nix"; + }; + #nano = import ./nano.nix; + simple-nix-mailserver = simple-nix-mailserver.nixosModules.mailserver; + }; + } \ No newline at end of file diff --git a/modules/legacyModules/nano.nix b/modules/legacyModules/nano.nix new file mode 100644 index 0000000..7785fe0 --- /dev/null +++ b/modules/legacyModules/nano.nix @@ -0,0 +1,1074 @@ +{ config, lib, pkgs, ... }: +let + cfg = config.programs.nano2; + + colourType = lib.types.submodule { + options = { + bg = lib.mkOption { + type = lib.types.enum [ + "black" + "blue" + "cyan" + "green" + "magenta" + "normal" + "red" + "white" + "yellow" + ]; + default = ""; + description = '' + Set the Background Colour. + Normal means the default background colour. + ''; + }; + fg = lib.mkOption { + type = lib.types.enum [ + "black" + "blue" + "brightblue" + "brightcyan" + "brightgreen" + "brightmagenta" + "brightred" + "brightwhite" + "brightyellow" + "cyan" + "green" + "magenta" + "normal" + "red" + "white" + "yellow" + ]; + default = ""; + description = '' + Set the Foreground Colour. + Normal means the default foreground colour. + ''; + }; + }; + }; + + # used by bindings and unbindings + menuType = lib.types.enum [ + "main" + "search" + "replace" + "replacewith" + "yesno" + "gotoline" + "writeout" + "insert" + "extcmd" + "help" + "spell" + "linter" + "browser" + "whereisfile" + "gotodir" + "all" + ]; + + # used by bindings + functionType = lib.types.enum [ + "help" + "cancel" + "exit" + "writeout" + "savefile" + "insert" + "whereis" + "wherewas" + "findprevious" + "findnext" + "replace" + "cut" + "copy" + "paste" + "zap" + "chopwordleft" + "chopwordright" + "cutrestoffile" + "mark" + "curpos" + "wordcount" + "speller" + "formatter" + "linter" + "justify" + "fulljustify" + "indent" + "unindent" + "comment" + "complete" + "left" + "right" + "up" + "down" + "scrollup" + "scrolldown" + "prevword" + "nextword" + "home" + "end" + "beginpara" + "endpara" + "prevblock" + "nextblock" + "pageup" + "pagedown" + "firstline" + "lastline" + "gotoline" + "findbracket" + "prevbuf" + "nextbuf" + "verbatim" + "tab" + "enter" + "delete" + "backspace" + "recordmacro" + "runmacro" + "undo" + "redo" + "refresh" + "suspend" + "casesens" + "regexp" + "backwards" + "older" + "newer" + "flipreplace" + "flipgoto" + "flipexecute" + "flippipe" + "flipnewbuffer" + "flipconvert" + "dosformat" + "macformat" + "append" + "prepend" + "backup" + "discardbuffer" + "browser" + "gotodir" + "firstfile" + "lastfile" + "nohelp" + "constantshow" + "softwrap" + "linenumbers" + "whitespacedisplay" + "nosyntax" + "smarthome" + "autoindent" + "cutfromcursor" + "nowrap" + "tabstospaces" + "mouse" + "suspendable" + ]; + + syntaxCommandType = lib.types.enum [ + "color" # , "regex" … + "comment" # "string" + "formatter" # program [argument …] + "header" # "regex" + "icolor" # , "regex" … + "linter" # program [argument …] + "magic" # "regex" + "tabgives" # "string" + ]; +in +{ + ###### interface + options = { + programs.nano = { + enable = lib.mkEnableOption "configuration of nano by creating /etc/nanorc"; + + # set afterends + afterEnds = lib.mkOption { + type = lib.types.bool; + default = false; + description = '' + Make Ctrl+Right stop at word ends instead of beginnings. + ''; + }; + + # set allow_insecure_backup + allowInsecureBackup = lib.mkOption { + type = lib.types.bool; + default = false; + description = '' + When backing up files, allow the backup to succeed even if its permissions cannot be (re)set due to special OS considerations. + You should NOT enable this option unless you are sure you need it. + ''; + }; + + # set atblanks + atBlanks = lib.mkOption { + type = lib.types.bool; + default = false; + description = '' + When soft line wrapping is enabled, make it wrap lines at blank characters (tabs and spaces) instead of always at the edge of the screen. + ''; + }; + + # set autoindent + autoIndentation = lib.mkOption { + type = lib.types.bool; + default = false; + description = '' + Automatically indent a newly created line to the same number of tabs and/or spaces as the previous line + or as the next line if the previous line is the beginning of a paragraph. + ''; + }; + + # set backup + backup = lib.mkOption { + type = lib.types.bool; + default = false; + description = '' + When saving a file, create a backup file by adding a tilde (~) to the file’s name. + ''; + }; + + # set backupdir + backupDirectory = lib.mkOption { + type = lib.types.str; + default = ""; + description = '' + Make and keep not just one backup file, + but make and keep a uniquely numbered one every time a file is saved, + when backups are enabled with or −−backup or −B. + The uniquely numbered files are stored in the specified directory. + ''; + }; + + # bind + # bind "string" + bindings = lib.mkOption { + type = lib.types.listOf ( lib.types.submodule { + options = { + key = lib.mkOption { + type = lib.types.str; + default = ""; + description = '' + The format of key should be one of: + + + ^X + where X is a Latin letter or one of several ASCII characters + (@, ], \, ^, _) + or the word Space. + Example: ^C. + + + M−X + where X is any ASCII character except [ or the word Space. + Example: M−8. + + + Sh−M−X + where X is a Latin letter. + Example: Sh−M−U. + By default, each Meta+letter keystroke does the same as the corresponding Shift+Meta+letter. + But when any Shift+Meta bind is made, that will no longer be the case, for all letters. + + + FN + where N is a numeric value from 1 to 24. + Example: F10. + (Often, F13 to F24 can be typed as F1 to F12 with Shift.) + + Ins or Del. + + ''; + }; + function = lib.mkOption { + type = lib.types.nullOr functionType; + default = null; + description = '' + Function which will be executed when is pressed. + This option is mutually exclusive with . + ''; + }; + menu = lib.mkOption { + type = menuType; + default = "all"; + description = '' + Menu where this binding should apply. + ''; + }; + string = lib.mkOption { + type = lib.types.str; + default = ""; + description = '' + String which will be inserted when is pressed. + This option is mutually exclusive with . + ''; + }; + }; + }); + default = []; + description = '' + List of Key-Bindings. + Rebinds the given to the given in the given + or in all menus where the function exists when all is used. + See nanorc5Rebind Keys. + ''; + }; + + # set boldtext + boldText = lib.mkOption { + type = lib.types.bool; + default = false; + description = '' + Use bold instead of reverse video for the title bar, status bar, key combos, function tags, line numbers and selected text. + This can be overridden by setting the options + , + , + , + , + and + . + ''; + }; + + # set brackets "characters" + brackets = lib.mkOption { + type = lib.types.str; + default = ""; + description = '' + Set the characters treated as closing brackets when justifying paragraphs. + This may not include blank characters. + Only closing punctuation (see ), + optionally followed by the specified closing brackets, + can end sentences. + The default value is ""’)>]}". + ''; + }; + + # set breaklonglines + breakLongLines = lib.mkOption { + type = lib.types.bool; + default = false; + description = '' + Automatically hard-wrap the current line when it becomes overlong. + ''; + }; + + # set casesensitive + caseSensitiveSearch = lib.mkOption { + type = lib.types.bool; + default = false; + description = '' + Do case-sensitive searches by default. + ''; + }; + + # set constantshow + constantShow = lib.mkOption { + type = lib.types.bool; + default = false; + description = '' + Constantly display the cursor position in the status bar. + This overrides the option . + ''; + }; + + # set cutfromcursor + cutFromCursor = lib.mkOption { + type = lib.types.bool; + default = false; + description = '' + Use cut-from-cursor-to-end-of-line by default, instead of cutting the whole line. + ''; + }; + + # set emptyline + emptyLine = lib.mkOption { + type = lib.types.bool; + default = false; + description = '' + Do not use the line below the title bar, leaving it entirely blank. + ''; + }; + + # set errorcolor , + errorColour = lib.mkOption { + type = lib.types.nullOr colourType; + default = null; + description = '' + Use this colour combination for the status bar when an error message is displayed. + The default value is brightwhite for foregorund and red for background. + ''; + }; + + # extendsyntax "argument …" + extendSyntax = lib.mkOption { + type = lib.types.listOf ( lib.types.submodule { + options = { + name = lib.mkOption { + type = lib.types.str; + description = '' + Name of syntax to extend. + ''; + }; + command = lib.mkOption { + type = syntaxCommandType; + description = '' + Extension command. + ''; + }; + arguments = lib.mkOption { + type = lib.types.str; + description = '' + Arguments of extension command. + ''; + }; + }; + }); + default = []; + description = '' + Extend the syntax previously defined as with another . + This allows adding a new color, icolor, header, magic, formatter, linter, comment or tabgives command + to an already defined syntax. + Useful when you want to slightly improve a syntax defined in one of the system-installed files + which normally are not writable. + ''; + }; + + extraConfig = lib.mkOption { + type = lib.types.lines; + default = ""; + description = '' + The system-wide nano configuration. + See nanorc5. + ''; + example = '' + set nowrap + set tabstospaces + set tabsize 2 + ''; + }; + + # set fill + fill = lib.mkOption { + type = lib.types.nullOr lib.types.int; + default = null; + description = '' + Set the target width for justifying and automatic hard-wrapping at this number of columns. + If the value is 0 or less, + wrapping will occur at the width of the screen minus number columns, + allowing the wrap point to vary along with the width of the screen if the screen is resized. + The default value is −8. + ''; + }; + + # set functioncolor , + functionColour = lib.mkOption { + type = lib.types.nullOr colourType; + default = null; + description = '' + Specify the colour combination to use for the function descriptions in the two help lines at the bottom of the screen. + ''; + }; + + # set guidestripe + guideStripe = lib.mkOption { + type = lib.types.nullOr lib.types.ints.unsigned; + default = null; + description = '' + Draw a vertical stripe at the given column, to help judge the width of the text. + ''; + }; + + # set historylog + historyLog = lib.mkOption { + type = lib.types.bool; + default = false; + description = '' + Save the last hundred search strings and replacement strings and executed commands, + so they can be easily reused in later sessions. + ''; + }; + + # include "filename" + include = lib.mkOption { + type = lib.types.listOf lib.types.path; + default = []; + description = '' + Additional Files to add to /etc/nanorc. + ''; + }; + + # set jumpyscrolling + jumpyScrolling = lib.mkOption { + type = lib.types.bool; + default = false; + description = '' + Scroll the buffer contents per half-screen instead of per line. + ''; + }; + + # set keycolor , + keyColour = lib.mkOption { + type = lib.types.nullOr colourType; + default = null; + description = '' + Specify the colour combination to use for the shortcut key combos in the two help lines at the bottom of the screen. + ''; + }; + + # set linenumbers + lineNumbers = lib.mkOption { + type = lib.types.bool; + default = false; + description = '' + Display line numbers to the left of the text area. + ''; + }; + + # set locking + locking = lib.mkOption { + type = lib.types.bool; + default = false; + description = '' + Enable vim-style lock-files for when editing files. + ''; + }; + + # set matchbrackets "characters" + matchBrackets = lib.mkOption { + type = lib.types.str; + default = ""; + description = '' + Set the opening and closing brackets that can be found by bracket searches. + This may not include blank characters. + The opening set must come before the closing set and the two sets must be in the same order. + The default value is "(<[{)>]}". + ''; + }; + + # set morespace + # Deprecated as it became default now, use emptyLine to enable the opposite. + + # set mouse + mouse = lib.mkOption { + type = lib.types.bool; + default = false; + description = '' + Enable mouse support, if available for your system. + When enabled, mouse clicks can be used to place the cursor, set the mark (with a double click) and execute shortcuts. + The mouse will work in the X Window System and on the console when gpm is running. + Text can still be selected through dragging by holding down the Shift key. + ''; + }; + + # set multibuffer + multiBuffer = lib.mkOption { + type = lib.types.bool; + default = false; + description = '' + When reading in a file with ^R, insert it into a new buffer by default. + ''; + }; + + # DEPRECATED. + nanorc = lib.mkOption { + type = lib.types.nullOr lib.types.lines; + default = ""; + description = '' + DEPRECATED, please use . + ''; + }; + + # set noconvert + noConvert = lib.mkOption { + type = lib.types.bool; + default = false; + description = '' + Do not convert files from DOS/Mac format. + ''; + }; + + # set nohelp + noHelp = lib.mkOption { + type = lib.types.bool; + default = false; + description = '' + Do not display the two help lines at the bottom of the screen. + ''; + }; + + # set nonewlines + noNewLines = lib.mkOption { + type = lib.types.bool; + default = false; + description = '' + Do not automatically add a newline when a text does not end with one. + This can cause you to save non-POSIX text files. + ''; + }; + + # set nopauses + # Obsolet. + + # set nowrap + # Deprecated as it became default now, use emptyLine to enable the opposite. + + # set numbercolor , + numberColour = lib.mkOption { + type = lib.types.nullOr colourType; + default = null; + description = '' + Specify the colour combination to use for line numbers. + ''; + }; + + # set operatingdir + operatingDirectory = lib.mkOption { + type = lib.types.str; + default = ""; + description = '' + nano will only read and write files inside directory and its subdirectories. + Also, the current directory is changed to here, so files are inserted from this directory. + By default, the operating directory feature is turned off. + ''; + }; + + # set positionlog + positionLog = lib.mkOption { + type = lib.types.bool; + default = false; + description = '' + Save the cursor position of files between editing sessions. + The cursor position is remembered for the 200 most-recently edited files. + ''; + }; + + # set preserve + preserve = lib.mkOption { + type = lib.types.bool; + default = false; + description = '' + Preserve the XON and XOFF keys (^Q and ^S). + ''; + }; + + # set punct "characters" + punctuation = lib.mkOption { + type = lib.types.str; + default = ""; + description = '' + Set the characters treated as closing punctuation when justifying paragraphs. + This may not include blank characters. + Only the specfified closing punctuation, optionally followed by closing brackets (see ), can end sentences. + The default value is "!.?". + ''; + }; + + # set quickblank + quickBlank = lib.mkOption { + type = lib.types.bool; + default = false; + description = '' + Do quick status-bar blanking: status-bar messages will disappear after 1 keystroke instead of 25. + The option overrides this. + ''; + }; + + # set quotestr "regex" + quoteString = lib.mkOption { + type = lib.types.str; + default = ""; + description = '' + Set the regular expression for matching the quoting part of a line. + The default value is "^([ \t]*([!#%:;>|}]|//))+". + Note that \t stands for an actual Tab character. + This makes it possible to rejustify blocks of quoted text when composing email and to rewrap blocks of line comments when writing source code. + ''; + }; + + # set rawsequences + rawSequences = lib.mkOption { + type = lib.types.bool; + default = false; + description = '' + Interpret escape sequences directly instead of asking ncurses to translate them. + If you need this option to get your keyboard to work properly, please report a bug. + Using this option disables nano’s mouse support. + ''; + }; + + # set rebinddelete + rebindDelete = lib.mkOption { + type = lib.types.bool; + default = false; + description = '' + Interpret the Delete and Backspace keys differently so that both Backspace and Delete work properly. + You should only use this option when on your system either Backspace acts like Delete or Delete acts like Backspace. + ''; + }; + + # set regexp + regexSearch = lib.mkOption { + type = lib.types.bool; + default = false; + description = '' + Do regular-expression searches by default. + Regular expressions in nano are of the extended type (ERE). + ''; + }; + + # set selectedcolor , + selectedColour = lib.mkOption { + type = lib.types.nullOr colourType; + default = null; + description = '' + Specify the color combination to use for selected text. + ''; + }; + + # set showcursor + showCursor = lib.mkOption { + type = lib.types.bool; + default = false; + description = '' + Put the cursor on the highlighted item in the file browser, to aid braille users. + ''; + }; + + # set smarthome + smartHome = lib.mkOption { + type = lib.types.bool; + default = false; + description = '' + Make the Home key smarter. + When Home is pressed anywhere but at the very beginning of non-whitespace characters on a line, + the cursor will jump either forwards or backwards to that beginning. + If the cursor is already at that position, it will jump to the true beginning of the line. + ''; + }; + + # set smooth + # Deprecated as it became default now, use jumpyScrolling to enable the opposite. + + # set softwrap + softWrap = lib.mkOption { + type = lib.types.bool; + default = false; + description = '' + Display lines that exceed the screen’s width over multiple screen lines. + You can make this soft-wrapping occur at whitespace instead of rudely at the screen’s edge, by using also . + ''; + }; + + # set speller "program [argument …]" + spellChecker = lib.mkOption { + type = lib.types.str; + default = ""; + description = '' + Use the given program to do spell checking and correcting, instead of using the built-in corrector that calls hunspell or GNU spell. + ''; + }; + + # set statuscolor , + statusColour = lib.mkOption { + type = lib.types.nullOr colourType; + default = null; + description = '' + Specify the colour combination to use for the status bar. + ''; + }; + + # set stripecolor , + stripeColour = lib.mkOption { + type = lib.types.nullOr colourType; + default = null; + description = '' + Specify the colour combination to use for the vertical guiding stripe. + ''; + }; + + # set suspendable + suspendable = lib.mkOption { + type = lib.types.bool; + default = false; + description = '' + Allow nano to be suspended (with ^Z by default). + ''; + }; + + # include "${pkgs.nano}/share/nano/*.nanorc" + syntaxHighlight = lib.mkOption { + type = lib.types.bool; + default = true; + description = '' + Whether to enable syntax highlight for various languages. + ''; + }; + + # set tabsize + tabulatorSize = lib.mkOption { + type = lib.types.ints.unsigned; + default = 0; + description = '' + Use a tab size of number columns. + The value of number must be greater than 0. + The default value is 8. + ''; + }; + + # set tabstospaces + tabulatorToSpaces = lib.mkOption { + type = lib.types.bool; + default = false; + description = '' + Convert typed tabs to spaces. + ''; + }; + + # set tempfile + temporaryFile = lib.mkOption { + type = lib.types.bool; + default = false; + description = '' + Save automatically on exit, don’t prompt. + ''; + }; + + # set titlecolor , + titleColour = lib.mkOption { + type = lib.types.nullOr colourType; + default = null; + description = '' + Specify the color combination to use for the title bar. + ''; + }; + + # set trimblanks + trimBlanks = lib.mkOption { + type = lib.types.bool; + default = false; + description = '' + Remove trailing whitespace from wrapped lines when automatic hard-wrapping occurs or when text is justified. + ''; + }; + + # unbind + unbindings = lib.mkOption { + type = lib.types.listOf ( lib.types.submodule { + options = { + key = lib.mkOption { + type = lib.types.str; + default = ""; + description = '' + The format of key should be one of: + + + ^X + where X is a Latin letter or one of several ASCII characters + (@, ], \, ^, _) + or the word Space. + Example: ^C. + + + M−X + where X is any ASCII character except [ or the word Space. + Example: M−8. + + + Sh−M−X + where X is a Latin letter. + Example: Sh−M−U. + By default, each Meta+letter keystroke does the same as the corresponding Shift+Meta+letter. + But when any Shift+Meta bind is made, that will no longer be the case, for all letters. + + + FN + where N is a numeric value from 1 to 24. + Example: F10. + (Often, F13 to F24 can be typed as F1 to F12 with Shift.) + + Ins or Del. + + ''; + }; + menu = lib.mkOption { + type = menuType; + default = "all"; + description = '' + Menu where this binding should apply. + ''; + }; + }; + }); + default = []; + description = '' + List of Key-Unbindings. + Unbin the given in the given + or in all menus where the function exists when all is used. + See nanorc5Rebind Keys. + ''; + }; + + # set unix + unixFormat = lib.mkOption { + type = lib.types.bool; + default = false; + description = '' + Save a file by default in Unix format. + This overrides nano’s default behavior of saving a file in the format that it had. + (This option has no effect when you also use .) + ''; + }; + + # set view + view = lib.mkOption { + type = lib.types.bool; + default = false; + description = '' + Disallow file modification: read-only mode. + This mode allows the user to open also other files for viewing, + unless −−restricted is given on the command line. + ''; + }; + + # set whitespace + whiteSpace = lib.mkOption { + type = lib.types.str; + default = ""; + description = '' + Set the two characters used to indicate the presence of tabs and spaces. + They must be single-column characters. + The default pair for a UTF-8 locale is "»⋅" and for other locales ">.". + ''; + }; + + # set wordbounds + wordBounds = lib.mkOption { + type = lib.types.bool; + default = false; + description = '' + Detect word boundaries differently by treating punctuation characters as parts of words. + ''; + }; + + # set wordchars "characters" + wordCharacters = lib.mkOption { + type = lib.types.str; + default = ""; + description = '' + Specify which other characters (besides the normal alphanumeric ones) should be considered as parts of words. + This overrides the option . + ''; + }; + + # set zap + zap = lib.mkOption { + type = lib.types.bool; + default = false; + description = '' + Let an unmodified Backspace or Delete erase the marked region + (instead of a single character and without affecting the cutbuffer). + ''; + }; + }; + }; + + ###### implementation + config = lib.mkIf cfg.enable { + environment.etc.nanorc.text = lib.concatStringsSep "\n" ( + [ + "# This File was generated and will be overridden by the nixos-rebuid." + "" + "# == OPTIONS ==" + ] ++ + lib.optional cfg.afterEnds "set afterends" ++ + lib.optional cfg.allowInsecureBackup "set allow_insecure_backup" ++ + lib.optional cfg.atBlanks "set atblanks" ++ + lib.optional cfg.autoIndentation "set autoindent" ++ + lib.optional cfg.backup "set backup" ++ + lib.optional (cfg.backupDirectory != "") "set backupdir \"${cfg.backupDirectory}\"" ++ + lib.optional cfg.boldText "set boldtext" ++ + lib.optional (cfg.brackets != "") "set brackets \"${cfg.brackets}\"" ++ + lib.optional cfg.breakLongLines "set breaklonglines" ++ + lib.optional cfg.caseSensitiveSearch "set casesensitive" ++ + lib.optional cfg.constantShow "set constantshow" ++ + lib.optional cfg.cutFromCursor "set cutfromcursor" ++ + lib.optional cfg.emptyLine "set emptyline" ++ + lib.optional (cfg.errorColour != null) "set errorcolor \"${cfg.errorColour.fg},${cfg.errorColour.bg}\"" ++ + lib.optional (cfg.fill != null) "set fill ${toString cfg.fill}" ++ + lib.optional (cfg.functionColour != null) "set functioncolor \"${cfg.functionColour.fg},${cfg.functionColour.bg}\"" ++ + lib.optional (cfg.guideStripe != null) "set guidestripe ${toString cfg.guideStripe}" ++ + lib.optional cfg.historyLog "set historylog" ++ + lib.optional cfg.jumpyScrolling "set jumpyscrolling" ++ + lib.optional (cfg.keyColour != null) "set keycolor \"${cfg.keyColour.fg},${cfg.keyColour.bg}\"" ++ + lib.optional cfg.lineNumbers "set linenumbers" ++ + lib.optional cfg.locking "set locking" ++ + lib.optional (cfg.matchBrackets != "") "set matchbrackets \"${cfg.matchBrackets}\"" ++ + lib.optional cfg.mouse "set mouse" ++ + lib.optional cfg.multiBuffer "set multibuffer" ++ + lib.optional cfg.noConvert "set noconvert" ++ + lib.optional cfg.noHelp "set nohelp" ++ + lib.optional cfg.noNewLines "set nonewlines" ++ + lib.optional (cfg.numberColour != null) "set numbercolor \"${cfg.numberColour.fg},${cfg.numberColour.bg}\"" ++ + lib.optional (cfg.operatingDirectory != "") "set operatingdir \"${cfg.operatingDirectory}\"" ++ + lib.optional cfg.positionLog "set positionlog" ++ + lib.optional cfg.preserve "set preserve" ++ + lib.optional (cfg.punctuation != "") "set punct \"${cfg.punctuation}\"" ++ + lib.optional cfg.quickBlank "set quickblank" ++ + lib.optional (cfg.quoteString != "") "set quotestr \"${cfg.quoteString}\"" ++ + lib.optional cfg.rawSequences "set rawsequences" ++ + lib.optional cfg.rebindDelete "set rebinddelete" ++ + lib.optional cfg.regexSearch "set regexp" ++ + lib.optional (cfg.selectedColour != null) "set selectedcolor \"${cfg.selectedColour.fg},${cfg.selectedColour.bg}\"" ++ + lib.optional cfg.showCursor "set showcursor" ++ + lib.optional cfg.smartHome "set smarthome" ++ + lib.optional cfg.softWrap "set softwrap" ++ + lib.optional (cfg.spellChecker != "") "set speller \"${cfg.spellChecker}\"" ++ + lib.optional (cfg.statusColour != null) "set statuscolor \"${cfg.statusColour.fg},${cfg.statusColour.bg}\"" ++ + lib.optional (cfg.stripeColour != null) "set stripecolor \"${cfg.stripeColour.fg},${cfg.stripeColour.bg}\"" ++ + lib.optional cfg.suspendable "set suspendable" ++ + lib.optional (cfg.tabulatorSize > 0) "set tabsize ${toString cfg.tabulatorSize}" ++ + lib.optional cfg.tabulatorToSpaces "set tabstospaces" ++ + lib.optional cfg.temporaryFile "set tempfile" ++ + lib.optional (cfg.titleColour != null) "set titlecolor \"${cfg.titleColour.fg},${cfg.titleColour.bg}\"" ++ + lib.optional cfg.trimBlanks "set trimblanks" ++ + lib.optional cfg.unixFormat "set unix" ++ + lib.optional cfg.view "set view" ++ + lib.optional (cfg.whiteSpace != "") "set whitespace \"${cfg.whiteSpace}\"" ++ + lib.optional cfg.wordBounds "set wordbounds" ++ + lib.optional (cfg.wordCharacters != "") "set wordchars \"${cfg.wordCharacters}\"" ++ + lib.optional cfg.zap "set zap" ++ + [ + "" + "# == SYNTAX HIGHLIGHTING ==" + ] ++ + lib.optional cfg.syntaxHighlight "include \"${pkgs.nano}/share/nano/*.nanorc\"" ++ + lib.lists.forEach cfg.include ( file: "include \"${file}\"" ) ++ + lib.lists.forEach cfg.extendSyntax ( this: "extendsyntax ${this.name} ${this.command}" ) ++ + [ + "" + "# == REBINDING KEYS ==" + ] ++ + lib.lists.forEach cfg.unbindings ( this: "unbind ${this.key} ${this.menu}" ) ++ + lib.lists.forEach cfg.bindings + ( + this: + if this.function == null + then "bind ${this.key} \"${this.string}\" ${this.menu}" + else "bind ${this.key} ${this.function} ${this.menu}" + ) ++ + [ + "" + "# == CUSTOM SETTINGS ==" + cfg.extraConfig + ] + ); + }; +} diff --git a/modules/modules/default.nix b/modules/modules/default.nix new file mode 100644 index 0000000..108bf29 --- /dev/null +++ b/modules/modules/default.nix @@ -0,0 +1,3 @@ +{ + nixos = ./nixos; +} \ No newline at end of file diff --git a/modules/modules/nixos/default.nix b/modules/modules/nixos/default.nix new file mode 100644 index 0000000..3c7206d --- /dev/null +++ b/modules/modules/nixos/default.nix @@ -0,0 +1,4 @@ +{ + programs = ./programs; + vault = ./vault; +} diff --git a/modules/modules/nixos/programs/default.nix b/modules/modules/nixos/programs/default.nix new file mode 100644 index 0000000..86c1f5c --- /dev/null +++ b/modules/modules/nixos/programs/default.nix @@ -0,0 +1,3 @@ +{ + nano = ./nano; +} \ No newline at end of file diff --git a/modules/modules/nixos/programs/nano/default.nix b/modules/modules/nixos/programs/nano/default.nix new file mode 100644 index 0000000..8b24f44 --- /dev/null +++ b/modules/modules/nixos/programs/nano/default.nix @@ -0,0 +1,135 @@ +Module + ./options + ( + { core, self, ... }: + let + inherit(core) list string; + + optional + = option: + value: + if option != null + && option != "" + && option != 0 + && option != false + then + [ value ] + else + []; + + setColour + = colour: + "\"${colour.fg},${colour.bg}\""; + + configFile + = string.concatLines + ( + [ + "# This File was generated and will be overridden by the nixos-rebuid." + "" + "# == OPTIONS ==" + ] + ++ optional self.afterEnds "set afterends" + ++ optional self.atBlanks "set atblanks" + ++ optional self.autoIndentation "set autoindent" + ++ optional self.boldText "set boldtext" + ++ optional self.brackets "set brackets \"${self.brackets}\"" + ++ optional self.breakLongLines "set breaklonglines" + ++ optional self.caseSensitiveSearch "set casesensitive" + ++ optional self.constantShow "set constantshow" + ++ optional self.cutFromCursor "set cutfromcursor" + ++ optional self.emptyLine "set emptyline" + ++ optional self.fill "set fill ${string self.fill}" + ++ optional self.guideStripe "set guidestripe ${string self.guideStripe}" + ++ optional self.historyLog "set historylog" + ++ optional self.jumpyScrolling "set jumpyscrolling" + ++ optional self.lineNumbers "set linenumbers" + ++ optional self.locking "set locking" + ++ optional self.matchBrackets "set matchbrackets \"${self.matchBrackets}\"" + ++ optional self.mouse "set mouse" + ++ optional self.multiBuffer "set multibuffer" + ++ optional self.noConvert "set noconvert" + ++ optional self.noHelp "set nohelp" + ++ optional self.noNewLines "set nonewlines" + ++ optional self.operatingDirectory "set operatingdir \"${self.operatingDirectory}\"" + ++ optional self.positionLog "set positionlog" + ++ optional self.preserve "set preserve" + ++ optional self.punctuation "set punct \"${self.punctuation}\"" + ++ optional self.quickBlank "set quickblank" + ++ optional self.quoteString "set quotestr \"${self.quoteString}\"" + ++ optional self.rawSequences "set rawsequences" + ++ optional self.rebindDelete "set rebinddelete" + ++ optional self.regexSearch "set regexp" + ++ optional self.showCursor "set showcursor" + ++ optional self.smartHome "set smarthome" + ++ optional self.softWrap "set softwrap" + ++ optional self.spellChecker "set speller \"${self.spellChecker}\"" + ++ optional self.suspendable "set suspendable" + ++ optional self.tabulator.size "set tabsize ${string self.tabulator.size}" + ++ optional self.tabulator.toSpaces "set tabstospaces" + ++ optional self.temporaryFile "set tempfile" + ++ optional self.trimBlanks "set trimblanks" + ++ optional self.unixFormat "set unix" + ++ optional self.view "set view" + ++ optional self.whiteSpace "set whitespace \"${self.whiteSpace}\"" + ++ optional self.wordBounds "set wordbounds" + ++ optional self.wordCharacters "set wordchars \"${self.wordCharacters}\"" + ++ optional self.zap "set zap" + ++ [ + "" + "# == COLOUR STYLE ==" + ] + ++ optional self.colours.function "set functioncolor ${setColour self.colours.function}" + ++ optional self.colours.error "set errorcolor ${setColour self.colours.error}" + ++ optional self.colours.key "set keycolor ${setColour self.colours.key}" + ++ optional self.colours.number "set numbercolor ${setColour self.colours.number}" + ++ optional self.colours.selected "set selectedcolor ${setColour self.colours.selected}" + ++ optional self.colours.status "set statuscolor ${setColour self.colours.status}" + ++ optional self.colours.stripe "set stripecolor ${setColour self.colours.stripe}" + ++ optional self.colours.title "set titlecolor ${setColour self.colours.title}" + ++ [ + "" + "# == BACKUPS ==" + ] + ++ optional self.backups.enable "set backup" + ++ optional self.backups.allowInsecure "set allow_insecure_backup" + ++ optional self.backups.directory "set backupdir \"${self.backup.directory}\"" + ++ [ + "" + "# == SYNTAX HIGHLIGHTING ==" + ] + ++ optional self.syntaxHighlight "include \"${pkgs.nano}/share/nano/*.nanorc\"" + ++ list.map + (file: "include \"${file}\"") + self.include + ++ list.map + (this: "extendsyntax ${this.name} ${this.command}") + self.extendSyntax + ++ [ + "" + "# == REBINDING KEYS ==" + ] + ++ list.map + (this: "unbind ${this.key} ${this.menu}") + self.unbindings + ++ list.map + ( + this: + if this.function == null + then "bind ${this.key} \"${this.string}\" ${this.menu}" + else "bind ${this.key} ${this.function} ${this.menu}" + ) + self.bindings + ++ [ + "" + "# == CUSTOM SETTINGS ==" + self.extraConfig + ] + ); + in + Option.ifEnabled self + { + environment.etc.nanorc.text + = + } + ) diff --git a/modules/modules/nixos/programs/nano/options/backup.nix b/modules/modules/nixos/programs/nano/options/backup.nix new file mode 100644 index 0000000..ec72705 --- /dev/null +++ b/modules/modules/nixos/programs/nano/options/backup.nix @@ -0,0 +1,32 @@ +{ + # set backup + enable + = Option.Bool' false + '' + the creation of backups when saving a file by adding a tilde (~) to the file’s name. + ''; + + # set allow_insecure_backup + allowInsecure + = Option.Bool' false + '' + When backing up files, allow the backup to succeed even if its permissions cannot be (re)set + due to special OS considerations. + You should NOT enable this option unless you are sure you need it. + ''; + + # set backupdir + directory + = Option.String' "" + { + example = "$HOME/.nanobackups"; + description + = '' + Make and keep not just one backup file, + but make and keep a uniquely numbered one every time a file is saved, + when backups are enabled with or −−backup + or −B. + The uniquely numbered files are stored in the specified directory. + ''; + }; +} diff --git a/modules/modules/nixos/programs/nano/options/bindings.nix b/modules/modules/nixos/programs/nano/options/bindings.nix new file mode 100644 index 0000000..ae65d4b --- /dev/null +++ b/modules/modules/nixos/programs/nano/options/bindings.nix @@ -0,0 +1,280 @@ +let + MenuOption + = Option.Enum' + [ + "main" + "search" + "replace" + "replacewith" + "yesno" + "gotoline" + "writeout" + "insert" + "extcmd" + "help" + "spell" + "linter" + "browser" + "whereisfile" + "gotodir" + "all" + ] + "all"; + + FunctionOption + = Option.Enum + [ + "help" + "cancel" + "exit" + "writeout" + "savefile" + "insert" + "whereis" + "wherewas" + "findprevious" + "findnext" + "replace" + "cut" + "copy" + "paste" + "zap" + "chopwordleft" + "chopwordright" + "cutrestoffile" + "mark" + "curpos" + "wordcount" + "speller" + "formatter" + "linter" + "justify" + "fulljustify" + "indent" + "unindent" + "comment" + "complete" + "left" + "right" + "up" + "down" + "scrollup" + "scrolldown" + "prevword" + "nextword" + "home" + "end" + "beginpara" + "endpara" + "prevblock" + "nextblock" + "pageup" + "pagedown" + "firstline" + "lastline" + "gotoline" + "findbracket" + "prevbuf" + "nextbuf" + "verbatim" + "tab" + "enter" + "delete" + "backspace" + "recordmacro" + "runmacro" + "undo" + "redo" + "refresh" + "suspend" + "casesens" + "regexp" + "backwards" + "older" + "newer" + "flipreplace" + "flipgoto" + "flipexecute" + "flippipe" + "flipnewbuffer" + "flipconvert" + "dosformat" + "macformat" + "append" + "prepend" + "backup" + "discardbuffer" + "browser" + "gotodir" + "firstfile" + "lastfile" + "nohelp" + "constantshow" + "softwrap" + "linenumbers" + "whitespacedisplay" + "nosyntax" + "smarthome" + "autoindent" + "cutfromcursor" + "nowrap" + "tabstospaces" + "mouse" + "suspendable" + ]; +in +{ + # bind + # bind "string" + bindings + = let + options + = types.struct + { + key + = Option.String' "" + { + example = "M-X"; + description + = '' + The format of key should be one of: + + + ^X + where X is a Latin letter or one of several ASCII characters + (@, ], \, ^, _) + or the word Space. + Example: ^C. + + + M−X + where X is any ASCII character except [ + or the word Space. + Example: M−8. + + + Sh−M−X + where X is a Latin letter. + Example: Sh−M−U. + By default, each Meta+letter keystroke does the same + as the corresponding Shift+Meta+letter. + But when any Shift+Meta bind is made, + that will no longer be the case, for all letters. + + + FN + where N is a numeric value from 1 to 24. + Example: F10. + (Often, F13 to F24 can be typed + as F1 to F12 with Shift.) + + Ins or Del. + + ''; + }; + function + = FunctionOption + { + example = "help"; + description + = '' + Function which will be executed when is pressed. + This option is mutually exclusive with . + ''; + }; + menu + = MenuOption + { + example = "main"; + description + = '' + Menu where this binding should apply. + ''; + }; + string + = Option.String' "" + { + example = "foobar"; + description + = '' + String which will be inserted when is pressed. + This option is mutually exclusive with . + ''; + }; + }; + in + Option.ListOf options + '' + List of Key-Bindings. + Rebinds the given to the given + in the given + or in all menus where the function exists when all is used. + See nanorc5Rebind Keys. + ''; + + # unbind + unbindings + = let + options + = types.struct + { + key + = Option.String' "" + { + example = "^X"; + description + = '' + The format of key should be one of: + + + ^X + where X is a Latin letter or one of several ASCII characters + (@, ], \, ^, _) + or the word Space. + Example: ^C. + + + M−X + where X is any ASCII character except [ + or the word Space. + Example: M−8. + + + Sh−M−X + where X is a Latin letter. + Example: Sh−M−U. + By default, each Meta+letter keystroke does the same + as the corresponding Shift+Meta+letter. + But when any Shift+Meta bind is made, + that will no longer be the case, for all letters. + + + FN + where N is a numeric value from 1 to 24. + Example: F10. + (Often, F13 to F24 can be typed + as F1 to F12 with Shift.) + + Ins or Del. + + ''; + }; + menu + = MenuOption + { + example = "help"; + description + = '' + Menu where this binding should apply. + ''; + }; + }; + in + Option.ListOf options + '' + List of Key-Unbindings. + Unbin the given in the given + or in all menus where the function exists when all is used. + See nanorc5Rebind Keys. + ''; +} diff --git a/modules/modules/nixos/programs/nano/options/colours.nix b/modules/modules/nixos/programs/nano/options/colours.nix new file mode 100644 index 0000000..3a55a32 --- /dev/null +++ b/modules/modules/nixos/programs/nano/options/colours.nix @@ -0,0 +1,110 @@ +{ types, ... }: + let + colorOptions + = types.struct + { + bg + = Option.Enum + [ + "black" + "blue" + "cyan" + "green" + "magenta" + "normal" + "red" + "white" + "yellow" + ] + '' + Set the Background Colour. + Normal means the default background colour. + ''; + fg + = Option.Enum + [ + "black" + "blue" + "brightblue" + "brightcyan" + "brightgreen" + "brightmagenta" + "brightred" + "brightwhite" + "brightyellow" + "cyan" + "green" + "magenta" + "normal" + "red" + "white" + "yellow" + ] + '' + Set the Foreground Colour. + Normal means the default foreground colour. + ''; + }; + + ColourOption = Option.NullOr colorOptions; + in + { + # set errorcolor , + error + = ColourOption + '' + Use this colour combination for the status bar when an error message is displayed. + The default value is brightwhite for foregorund and red for background. + ''; + + # set functioncolor , + function + = ColourOption + '' + Specify the colour combination to use for the function descriptions + in the two help lines at the bottom of the screen. + ''; + + # set keycolor , + key + = ColourOption + '' + Specify the colour combination to use for the shortcut key combos + in the two help lines at the bottom of the screen. + ''; + + # set numbercolor , + number + = ColourOption + '' + Specify the colour combination to use for line numbers. + ''; + + # set selectedcolor , + selected + = ColourOption + '' + Specify the colour combination to use for selected text. + ''; + + # set statuscolor , + status + = ColourOption + '' + Specify the colour combination to use for the status bar. + ''; + + # set stripecolor , + stripe + = ColourOption + '' + Specify the colour combination to use for the vertical guiding stripe. + ''; + + # set titlecolor , + title + = ColourOption + '' + Specify the colour combination to use for the title bar. + ''; + } diff --git a/modules/modules/nixos/programs/nano/options/default.nix b/modules/modules/nixos/programs/nano/options/default.nix new file mode 100644 index 0000000..43a860d --- /dev/null +++ b/modules/modules/nixos/programs/nano/options/default.nix @@ -0,0 +1,408 @@ +{ types, ... }: +{ + enable + = Option.Enable + '' + configuration of nano by creating /etc/nanorc + ''; + afterEnds + = Option.Bool' false + '' + Make Ctrl+Right stop at word ends instead of beginnings. + ''; + atBlanks + = Option.Bool' false + '' + When soft line wrapping is enabled, make it wrap lines at blank characters (tabs and spaces) + instead of always at the edge of the screen. + ''; + autoIndentation + = Option.Bool' false + '' + Automatically indent a newly created line to the same number of tabs and/or spaces as the previous line + or as the next line if the previous line is the beginning of a paragraph. + ''; + backup = ./backup.nix; + bindings = ./bindings.nix; + boldText + = Option.Bool' false + '' + Use bold instead of reverse video + for the title bar, status bar, key combos, function tags, line numbers and selected text. + This can be overridden by setting the options + , + , + , + , + and + . + ''; + brackets + = Option.String' "" + { + example = "\"’)>]}"; + description + = '' + Set the characters treated as closing brackets when justifying paragraphs. + This may not include blank characters. + Only closing punctuation (see ), + optionally followed by the specified closing brackets, + can end sentences. + The default value is ""’)>]}". + ''; + }; + breakLongLines + = Option.Bool' false + '' + Automatically hard-wrap the current line when it becomes overlong. + ''; + caseSensitiveSearch + = Option.Bool' false + '' + Do case-sensitive searches by default. + ''; + constantShow + = Option.Bool' false + '' + Constantly display the cursor position in the status bar. + This overrides the option . + ''; + cutFromCursor + = Option.Bool' false + '' + Use cut-from-cursor-to-end-of-line by default, instead of cutting the whole line. + ''; + emptyLine + = Option.Bool' false + '' + Do not use the line below the title bar, leaving it entirely blank. + ''; + colours = ./colours.nix; + extendSyntax + = let + options + = { + name + = Option.String + { + example = "foobar"; + description + = '' + Name of syntax to extend. + ''; + }; + command + = Option.Enum + [ + "color" # , "regex" … + "comment" # "string" + "formatter" # program [argument …] + "header" # "regex" + "icolor" # , "regex" … + "linter" # program [argument …] + "magic" # "regex" + "tabgives" # "string" + ] + { + example = "comment"; + description + = '' + Extension command. + ''; + }; + arguments + = Option.String + '' + Arguments of extension command. + ''; + }; + in + Option.ListOf options + { + description + = '' + Extend the syntax previously defined as with another . + This allows adding a new color, icolor, header, magic, formatter, linter, comment or tabgives command + to an already defined syntax. + Useful when you want to slightly improve a syntax defined in one of the system-installed files + which normally are not writable. + ''; + }; + extraConfig + = Option.Lines + { + description + = '' + The system-wide nano configuration. + See nanorc5. + ''; + example + = '' + set nowrap + set tabstospaces + set tabsize 2 + ''; + }; + fill + = Option.NullOr types.integer + '' + Set the target width for justifying and automatic hard-wrapping at this number of columns. + If the value is 0 or less, + wrapping will occur at the width of the screen minus number columns, + allowing the wrap point to vary along with the width of the screen if the screen is resized. + The default value is −8. + ''; + guideStripe + = Option.NullOr types.integer + { + example = 42; + description + = '' + Draw a vertical stripe at the given column, to help judge the width of the text. + ''; + }; + historyLog + = Option.Bool' false + '' + Save the last hundred search strings and replacement strings and executed commands, + so they can be easily reused in later sessions. + ''; + include + = Option.ListOf types.path + { + description + = '' + Additional Files to add to /etc/nanorc. + ''; + }; + jumpyScrolling + = Option.Bool' false + '' + Scroll the buffer contents per half-screen instead of per line. + ''; + lineNumbers + = Option.Bool' false + '' + Display line numbers to the left of the text area. + ''; + locking + = Option.Bool' false + '' + Enable vim-style lock-files for when editing files. + ''; + matchBrackets + = Option.String' "" + { + example = "(<[{)>]}"; + description + = '' + Set the opening and closing brackets that can be found by bracket searches. + This may not include blank characters. + The opening set must come before the closing set and the two sets must be in the same order. + The default value is "(<[{)>]}". + ''; + }; + mouse + = Option.Bool' false + '' + Enable mouse support, if available for your system. + When enabled, mouse clicks can be used to place the cursor, set the mark (with a double click) + and execute shortcuts. + The mouse will work in the X Window System and on the console when gpm is running. + Text can still be selected through dragging by holding down the Shift key. + ''; + multiBuffer + = Option.Bool' false + '' + When reading in a file with ^R, insert it into a new buffer by default. + ''; + noConvert + = Option.Bool' false + '' + Do not convert files from DOS/Mac format. + ''; + noHelp + = Option.Bool' false + '' + Do not display the two help lines at the bottom of the screen. + ''; + noNewLines + = Option.Bool' false + '' + Do not automatically add a newline when a text does not end with one. + This can cause you to save non-POSIX text files. + ''; + operatingDirectory + = Option.String' "" + { + example = "$HOME/nano"; + description + = '' + nano will only read and write files inside directory and its subdirectories. + Also, the current directory is changed to here, so files are inserted from this directory. + By default, the operating directory feature is turned off. + ''; + }; + positionLog + = Option.Bool' false + '' + Save the cursor position of files between editing sessions. + The cursor position is remembered for the 200 most-recently edited files. + ''; + preserve + = Option.Bool' false + '' + Preserve the XON and XOFF keys (^Q and ^S). + ''; + punctuation + = Option.String' "" + { + example = "!.?"; + description + = '' + Set the characters treated as closing punctuation when justifying paragraphs. + This may not include blank characters. + Only the specfified closing punctuation, + optionally followed by closing brackets (see ), + can end sentences. + The default value is "!.?". + ''; + }; + quickBlank + = Option.Bool' false + '' + Do quick status-bar blanking: status-bar messages will disappear after 1 keystroke instead of 25. + The option overrides this. + ''; + quoteString + = Option.String' "" + { + example = "^([ \\t]*([!#%:;>|}]|//))+"; + description + = '' + Set the regular expression for matching the quoting part of a line. + The default value is "^([ \t]*([!#%:;>|}]|//))+". + Note that \t stands for an actual Tab character. + This makes it possible to rejustify blocks of quoted text when composing email + and to rewrap blocks of line comments when writing source code. + ''; + }; + rawSequences + = Option.Bool' false + '' + Interpret escape sequences directly instead of asking ncurses to translate them. + If you need this option to get your keyboard to work properly, please report a bug. + Using this option disables nano’s mouse support. + ''; + rebindDelete + = Option.Bool' false + '' + Interpret the Delete and Backspace keys differently so that both Backspace and Delete work properly. + You should only use this option + when on your system either Backspace acts like Delete or Delete acts like Backspace. + ''; + regexSearch + = Option.Bool' false + '' + Do regular-expression searches by default. + Regular expressions in nano are of the extended type (ERE). + ''; + showCursor + = Option.Bool' false + '' + Put the cursor on the highlighted item in the file browser, to aid braille users. + ''; + smartHome + = Option.Bool' false + '' + Make the Home key smarter. + When Home is pressed anywhere but at the very beginning of non-whitespace characters on a line, + the cursor will jump either forwards or backwards to that beginning. + If the cursor is already at that position, it will jump to the true beginning of the line. + ''; + softWrap + = Option.Bool' false + '' + Display lines that exceed the screen’s width over multiple screen lines. + You can make this soft-wrapping occur at whitespace instead of rudely at the screen’s edge, + by using also . + ''; + spellChecker + = Option.String' "" + { + example = "aspell"; + description + = '' + Use the given program to do spell checking and correcting, + instead of using the built-in corrector that calls hunspell or GNU spell. + ''; + }; + suspendable + = Option.Bool' false + '' + Allow nano to be suspended (with ^Z by default). + ''; + syntaxHighlight + = Option.Bool' true + '' + Whether to enable syntax highlight for various languages. + ''; + tabulator = ./tabulator.nix; + temporaryFile + = Option.Bool' false + '' + Save automatically on exit, don’t prompt. + ''; + trimBlanks + = Option.Bool' false + '' + Remove trailing whitespace from wrapped lines when automatic hard-wrapping occurs or when text is justified. + ''; + unixFormat + = Option.Bool' false + '' + Save a file by default in Unix format. + This overrides nano’s default behavior of saving a file in the format that it had. + (This option has no effect when you also use .) + ''; + view + = Option.Bool' false + '' + Disallow file modification: read-only mode. + This mode allows the user to open also other files for viewing, + unless −−restricted is given on the command line. + ''; + whiteSpace + = Option.String' "" + { + example = "»⋅"; + description + = '' + Set the two characters used to indicate the presence of tabs and spaces. + They must be single-column characters. + The default pair for a UTF-8 locale is "»⋅" and for other locales ">.". + ''; + }; + wordBounds + = Option.Bool' false + '' + Detect word boundaries differently by treating punctuation characters as parts of words. + ''; + wordCharacters + = Option.String' "" + { + example = "ÄÖÜäöüß"; + description + = '' + Specify which other characters (besides the normal alphanumeric ones) + should be considered as parts of words. + This overrides the option . + ''; + }; + zap + = Option.Bool' false + '' + Let an unmodified Backspace or Delete erase the marked region + (instead of a single character and without affecting the cutbuffer). + ''; +} diff --git a/modules/modules/nixos/programs/nano/options/tabulator.nix b/modules/modules/nixos/programs/nano/options/tabulator.nix new file mode 100644 index 0000000..449e8b4 --- /dev/null +++ b/modules/modules/nixos/programs/nano/options/tabulator.nix @@ -0,0 +1,18 @@ +{ + size + = Option.UnsignedInteger' 0 + { + example = 4; + description + = '' + Use a tab size of number columns. + The value of number must be greater than 0. + The default value is 8. + ''; + }; + toSpaces + = Option.Bool' false + '' + Convert typed tabs to spaces. + ''; +} \ No newline at end of file diff --git a/modules/modules/nixos/vault/config.nix b/modules/modules/nixos/vault/config.nix new file mode 100644 index 0000000..7c6079b --- /dev/null +++ b/modules/modules/nixos/vault/config.nix @@ -0,0 +1,221 @@ +{ self, lib, registries, ...}: +let + inherit (lib.intrinsics) abort map mapAttrs attrNames attrValues length dirOf toString toFile; + inherit (lib.nixlib) mkIf; + inherit(registries.nix) coreutils gnupg runtimeShell; + + pinentry + = if self.pinentry != null + then + "pinentry-program ${self.pinentry}/bin/pinentry" + else + ""; + + loopback + = if self.pinentry == null + then + " --pinentry-mode loopback" + else + ""; + + quiet + = if self.quiet + then + " --quiet" + else + ""; + + homedir = "/tmp/keyring"; + utils = "${coreutils}/bin/"; + + mapSecrets + = secrets: + attrValues + ( + mapAttrs + ( + name: + value: + let + setPermissions + = fileName: + owner: + group: + if owner != null + then + if group != null + then + '' + ${utils}/chown "${owner}:${group}" "${fileName}" + ${utils}/chmod u=r,g=r,o= "${fileName}" + '' + else + '' + ${utils}/chown "${owner}" "${fileName}" + ${utils}/chmod u=r,g=,o= "${fileName}" + '' + else + if group != null + then + '' + ${utils}/chgrp "${group}" "${fileName}" + ${utils}/chmod u=r,g=r,o= "${fileName}" + '' + else + '' + ${utils}/chmod u=r,g=,o= "${fileName}" + ''; + in + if value.decrypt != null + then + let + encrypted = "\"${value.decrypt}\""; + in + '' + ${gnupg}/bin/gpg --homedir ${homedir}${loopback}${quiet} --decrypt ${encrypted} --output "${value.path}" + ${setPermissions value.path value.owner value.group} + '' + else if value.generate != null + then + let + set = "\"${value.generate.set}\""; + length = "\"${value.generate.length}\""; + in + '' + ${utils}/cat /dev/urandom | ${utils}/tr --delete --complement ${set} | ${utils}/head --bytes ${length} > "${value.path}" + ${setPermissions value.path value.owner value.group} + '' + else + abort "Either option `decrypt` or `generate` must be set!" + ) + secrets + ); + + hostDefaultKey + = if self.host.keys.default != null + then + [ "\"${self.host.keys.default}\"" ] + else + [ ]; + + mandatoryKeys = hostDefaultKey ++ self.host.keys.mandatory; + importMandatoryKeys + = map + ( + key: + "${gnupg}/bin/gpg --homedir ${homedir}${quiet} --batch --import \"${key}\"\n" + ); + + makeUserDirectories + = map + ( + userName: + "${utils}/install --owner \"${userName}\" --mode u=rwx,g=x,o=x --directory \"${self.vault}/user/${userName}\"" + ); + + importOptionalKeys + = keys: + if keys != [ ] + then + '' + PS3="Select optional key to import or 0: " + select key in ${toString (map (key: "\"${key}\"") keys)} + do + if [ "$key" != "" ] + then + ${gnupg}/bin/gpg --homedir ${homedir}${quiet} --batch --import "$key" + else + break + fi + done + '' + else + ""; + + initVault + = toFile "initVault.sh" + '' + #!${runtimeShell} + # set up the confidential and ephemeral vault-directory as the secrets-store + echo "initialise ${self.vault}…" + # root will be able to create files and list the directory + # everyone else can only access certain files by path + ${utils}/install --mode u=rwx,g=x,o=x --directory ${self.vault}/host + ${toString (makeUserDirectories (attrNames self.user))} + # import mandatory keys and ask for optional keys to import + ${toString (importMandatoryKeys mandatoryKeys)}${importOptionalKeys self.host.keys.optional} + # decrypt or generate secrets + ${toString (mapSecrets self.host.secrets)} + ''; + + startAgent + = let + gpgConfig + = toFile "startAgent.config" + '' + default-cache-ttl 34560000 + max-cache-ttl 34560000 + ${pinentry} + ''; + in + task: + toFile "startAgent.sh" + '' + #!${runtimeShell} + # initialise a temporary keyring, start the agent to initialise the vault and then clean up afterwards + ${utils}/rm --recursive --force ${homedir} + ${utils}/install --mode u=rwx,g=,o= --directory ${homedir} + ${gnupg}/bin/gpg-agent --homedir ${homedir}${quiet} --options ${gpgConfig} --daemon ${task} + ${utils}/rm --recursive ${homedir} + ''; + + generateDefaultKey + = name: + owner: + path: + let + gpgConfig + = toFile "generateDefaultKey.config" + '' + Key-Type: eddsa + Key-Curve: Ed25519 + Key-Usage: sign,auth + Subkey-Type: ecdh + Subkey-Curve: Curve25519 + Subkey-Usage: encrypt + Name: ${name} + Name-Comment: default vault-key + Preferences: SHA512 AES256 Uncompressed + Expire-Date: 0 + ''; + in + toFile + '' + #!${runtimeShell} + # generate a default-key for host/user ${name} (${owner}) + echo "generate default-key ${name}…" + ${utils}/install --mode u=r,g=,o= --owner "${owner}" --directory "${dirOf path}" + ${gnupg}/bin/gpg ${quiet}--batch --generate-key ${gpgConfig} + ${gnupg}/bin/gpg ${quiet}--export --armor "${name}" --output "${path}" + ''; + + mayGenerateHostDefaultKey + = if self.host.keys.default != null + then + '' + if [ ! -f "${self.host.keys.default}" ] + then + ${startAgent (generateDefaultKey config.network.hostName "root" self.host.keys.default)} + fi + '' + else + ""; +in + mkIf self.enable + { + system.activationScripts.initialise-vault + = { + deps = [ "users" "groups" ]; + text = "${mayGenerateHostDefaultKey}${startAgent initVault}"; + }; + } diff --git a/modules/modules/nixos/vault/default.nix b/modules/modules/nixos/vault/default.nix new file mode 100644 index 0000000..f6aa72f --- /dev/null +++ b/modules/modules/nixos/vault/default.nix @@ -0,0 +1,4 @@ +{ + config = ./config.nix; + options = ./options.nix; +} \ No newline at end of file diff --git a/modules/modules/nixos/vault/options.nix b/modules/modules/nixos/vault/options.nix new file mode 100644 index 0000000..a3dd870 --- /dev/null +++ b/modules/modules/nixos/vault/options.nix @@ -0,0 +1,226 @@ +{ lib, registries, ... }: +let + inherit (lib.instrinsics) mapAttrs; + inherit (lib.nixlib) mkEnableOption mkOption types; + + secretOptions + = { + decrypt + = mkOption + { + type = types.nullOr types.path; + default = null; + description = "Decrypt encrypted secret. Mutually exclusive with `generate`."; + }; + generate + = let + options + = { + length + = mkOption + { + type = types.ints.unsigned; + default = 32; + example = 64; + description = "Lengt of generated token."; + }; + set + = mkOption + { + type = types.str; + default = "[:graph:]"; + example = "[:alnum:]"; + description = "Set of allowed characters, see `tr --help`."; + }; + }; + in + mkOption + { + type = types.nullOr ( types.submodule { inherit options; } ); + default = null; + description = "Generate a random token. Mutually exclusive with `decrypt`."; + }; + group + = mkOption + { + type = types.nullOr types.str; + default = null; + example = "metrics"; + description = "Set group of secret."; + }; + owner + = mkOption + { + type = types.nullOr types.str; + default = null; + example = "root"; + description = "Set user of secret."; + }; + path + = mkOption + { + type = types.nullOr types.str; + internal = true; + default = null; + }; + }; + + keyOptions + = { + default + = mkOption + { + type = types.nullOr types.str; + default = null; + example = "/var/keys/host.gpg"; + description = "Path to the default-key, which will be generated on activation, if necessary."; + }; + mandatory + = mkOption + { + type = types.listOf types.path; + default = [ ]; + description = "List of mandatory secret-keys to import"; + }; + optional + = mkOption + { + type = types.listOf types.path; + default = [ ]; + description + = '' + List of optional secret-keys to import + Usefull if multile users should unlock the vault, + so only the keys the user knows the password of will be imported. + Otherwise the user might get asked for the password of multiple keys + which they do not know to unlock. + ''; + }; + }; + + vaultType + = types.submodule + ( + { ... } @ env: + { + options + = { + keys + = mkOption + { + type = types.submodule { options = keyOptions; }; + default = { }; + description = "List of private pgp-keys available to gpg to initialise the vault."; + }; + secrets + = mkOption + { + type = types.attrsOf ( types.submodule { options = secretOptions; } ); + default = { }; + description = "List of named secrets."; + }; + }; + } + ); + secretExample + = { + keys + = { + mandatory + = [ + ./optionalKey.gpg + ]; + optional + = [ + ./hostKey.gpg + ]; + }; + secrets + = { + foo = { generate = { set = "A-Z"; length = 8; }; }; + bar = { decrypt = ./secret.gpg; }; + }; + }; +in + mkOption + { + type + = types.submodule + { + options + = { + enable = mkEnableOption "confidential managment of secrets."; + enableSSH = mkEnableOption "initialising the vault via an ssh-connection."; + host + = mkOption + { + type = vaultType; + default = { }; + example = secretExample; + description = "Configure host-secrets"; + }; + pinentry + = mkOption + { + type = types.nullOr types.package; + default = (registries.nix.pinentry).tty; + example = (registries.nix.pinentry).curses; + description = "Pinentry to use. Loopback if false."; + }; + quiet + = mkOption + { + type = types.bool; + default = true; + example = false; + description = "Make gpg as silent as possible."; + }; + user + = mkOption + { + type = types.attrsOf vaultType; + default = { }; + example = secretExample; + description = "Configure user-secrets."; + }; + vault + = mkOption + { + type = types.str; + default = "/run/vault"; + example = "/run/secrets"; + description = "Path to the Vault"; + }; + }; + }; + apply + = let + mapSecrets + = directory: + mapAttrs + ( + name: + secret: + secret // { path = "${directory}/${name}"; } + ); + in + ( + { vault, host, user, ... } @ cfg: + cfg + // { + host.secrets = mapSecrets "${vault}/host" host.secrets; + user + = mapAttrs + ( + user: + secrets: + mapSecrets "${vault}/user/${user}/" secrets.secrets + ) + user; + } + ); + description + = '' + The vault-module. + ''; + } diff --git a/packages/fork-awesome/default.nix b/packages/fork-awesome/default.nix new file mode 100644 index 0000000..cd8fc35 --- /dev/null +++ b/packages/fork-awesome/default.nix @@ -0,0 +1,60 @@ +{ lib, fetchFromGitHub, stdenv }: + +let + inherit(builtins) filter foldl' head isString match readFile split; + + version = "8e30d063c283f87043adca087f0897d210dc8717"; + + fork-awesome = fetchFromGitHub { + owner = "sivizius"; + repo = "Fork-Awesome"; + rev = version; + sha256 = "sha256-50iWohxQ2AhO8oQ9hM5AJRCyes9gXvzSTXMDBTYiDHo="; + }; + + splitLines = text: filter isString (split "\n" text); + lines = splitLines (readFile "${fork-awesome}/src/icons/icons.yml"); + + parsedIcons = foldl' ( + { icons, id, unicode } @ state: + line: + let + nameLine = match " - name: +(.*)" line; + idLine = match " id: +(.*)" line; + unicodeLine = match " unicode: +(.*)" line; + in + if nameLine != null then { + icons = icons // { ${id} = unicode; }; + id = null; + unicode = null; + } + else if idLine != null then state // { id = head idLine; } + else if unicodeLine != null then state // { unicode = head unicodeLine; } + else state + ) + { + icons = {}; + id = null; + unicode = null; + } + lines; +in (stdenv.mkDerivation { + pname = "fork-awesome"; + inherit version; + + src = fork-awesome; + + installPhase = '' + install -m444 -Dt $out/share/fonts/truetype/fork-awesome ${fork-awesome}/fonts/forkawesome-webfont.ttf + + ''; + + meta = let + inherit(lib) licenses platforms; + in { + description = "Fork Awesome Icon Font"; + license = licenses.ofl; + maintainers = [ ]; + platforms = platforms.all; + }; +}) // { inherit(parsedIcons) icons; } diff --git a/packages/fork-awesome/flake.nix b/packages/fork-awesome/flake.nix new file mode 100644 index 0000000..94d4fe7 --- /dev/null +++ b/packages/fork-awesome/flake.nix @@ -0,0 +1,33 @@ +{ + description = "Fork Awesome Icons"; + inputs + = { + libcore.url = "github:sivizius/nixfiles/development?dir=libs/core"; + nixpkgs.url = "github:sivizius/nixpkgs/master"; + }; + outputs + = { self, libcore, nixpkgs, ... }: + let + core = libcore.lib { inherit self; debug.logLevel = "info"; }; + inherit(core) path target; + in + { + packages + = target.System.mapStdenv + ( + system: + let + fork-awesome + = path.import ./. + { + inherit(nixpkgs) lib; + inherit(nixpkgs.legacyPackages."${system}") fetchFromGitHub stdenv; + }; + in + { + inherit fork-awesome; + default = fork-awesome; + } + ); + }; +} diff --git a/packages/redshift-wayland/flake.nix b/packages/redshift-wayland/flake.nix new file mode 100644 index 0000000..f44d531 --- /dev/null +++ b/packages/redshift-wayland/flake.nix @@ -0,0 +1,33 @@ +{ + description = "Redshift for wayland"; + inputs + = { + libcore.url = "github:sivizius/nixfiles/development?dir=libs/core"; + nixpkgs.url = "github:sivizius/nixpkgs/master"; + redshift-wayland + = { + type = "github"; + owner = "minus7"; + repo = "redshift"; + rev = "7da875d34854a6a34612d5ce4bd8718c32bec804"; + # sha256 = "0rs9bxxrw4wscf4a8yl776a8g880m5gcm75q06yx2cn3lw2b7v22"; + flake = false; + }; + }; + outputs + = { self, libcore, nixpkgs, redshift-wayland, ... }: + { + packages + = (libcore.lib { inherit self; debug.logLevel = "info"; }).target.System.mapStdenv + ( + system: + nixpkgs.legacyPackages."${system}".redshift.overrideAttrs + ( + oldAttrs: + { + src = redshift-wayland; + } + ) + ); + }; +} diff --git a/packages/rz-ghidra/default.nix b/packages/rz-ghidra/default.nix new file mode 100644 index 0000000..9c699a8 --- /dev/null +++ b/packages/rz-ghidra/default.nix @@ -0,0 +1,48 @@ +{ fetchFromGitHub, pkgs, stdenv }: + let + pname = "rz-ghidra"; + version = "0.2.0"; + sha256 = "sha256-SnRNOv2rGGUX+/0zHIPptpt+t7c9FGJ9mFQT6Y16IxM="; + in + stdenv.mkDerivation + { + inherit pname version; + + src + = fetchFromGitHub + { + inherit sha256; + owner = "rizinorg"; + repo = pname; + rev = "v${version}"; + fetchSubmodules = true; + }; + + nativeBuildInputs + = with pkgs; + [ + cmake + pkg-config + libsForQt5.wrapQtAppsHook + ]; + + buildInputs + = with pkgs; + [ + cutter + rizin + ]; + + cmakeFlags + = [ + "-DBUILD_CUTTER_PLUGIN=ON" + ]; + + postPhases = [ "fixLibraries" ]; + + fixLibraries + = '' + file=$out/share/rizin/cutter/plugins/native/librz_ghidra_cutter.so + patchelf --set-rpath $(patchelf --print-rpath $file):$out/share/rizin/plugins $file + ''; + } diff --git a/packages/rz-ghidra/flake.nix b/packages/rz-ghidra/flake.nix new file mode 100644 index 0000000..e915de1 --- /dev/null +++ b/packages/rz-ghidra/flake.nix @@ -0,0 +1,33 @@ +{ + description = "Ghidra-Decompiler for Cutter"; + inputs + = { + libcore.url = "github:sivizius/nixfiles/development?dir=libs/core"; + nixpkgs.url = "github:sivizius/nixpkgs/master"; + }; + outputs + = { self, libcore, nixpkgs, ... }: + let + core = libcore.lib { inherit self; debug.logLevel = "info"; }; + inherit(core) path target; + in + { + packages + = target.System.mapStdenv + ( + system: + let + rz-ghidra + = path.import ./. + { + pkgs = nixpkgs.legacyPackages."${system}"; + inherit(nixpkgs.legacyPackages."${system}") fetchFromGitHub stdenv; + }; + in + { + inherit rz-ghidra; + default = rz-ghidra; + } + ); + }; +} diff --git a/packages/wofi-unpatched/flake.nix b/packages/wofi-unpatched/flake.nix new file mode 100644 index 0000000..972c6c3 --- /dev/null +++ b/packages/wofi-unpatched/flake.nix @@ -0,0 +1,25 @@ +{ + description = "Unpatched wofi"; + inputs + = { + libcore.url = "github:sivizius/nixfiles/development?dir=libs/core"; + nixpkgs.url = "github:sivizius/nixpkgs/master"; + }; + outputs + = { self, libcore, nixpkgs, ... }: + { + packages + = (libcore.lib { inherit self; debug.logLevel = "info"; }).target.System.mapStdenv + ( + system: + nixpkgs.legacyPackages."${system}".wofi.overrideAttrs + ( + oldAttrs: + { + # Remove the do_not_follow_symlinks-patch + patches = []; + } + ) + ); + }; +} diff --git a/peers/chaos/Chaosnetz.asc b/peers/chaos/Chaosnetz.asc new file mode 100644 index 0000000..0a7d515 --- /dev/null +++ b/peers/chaos/Chaosnetz.asc @@ -0,0 +1,10 @@ +-----BEGIN PGP MESSAGE----- + +hF4DQpmXgCyyA4oSAQdAD+24lyNB6L765Y8AVuh+nGd/U7Ha1GaoktIdDCBaoisw +mZ/QXk/DwJpfE0E+lPk/eIueHW9CRvNzJMCeSXdK3TIgqa5kXSuGyn6+PqkEiCUA +hF4DxiX3uH/9xDgSAQdAEV11k1EFjTAtXJ/VJqSsYiEIf2vSbhZmWTx8XjAKRx0w +HTI/NWKkwfciO4ACAPIy90WZO3DcXPHuVyX9UVB7eOR/Xa/NVp2IWMkzXLNOL2Po +0kIBDieXE2927c6d8OJ46PAG2Ejs+pTuN3posooA6SUGhe0QwwKeKiTNpFe9Vi7U +LTKVhaFzP4hKc8khG2f+VXMfbyQ= +=akPQ +-----END PGP MESSAGE----- diff --git a/peers/chaos/Geekz.Karibik.asc b/peers/chaos/Geekz.Karibik.asc new file mode 100644 index 0000000..b1061f7 --- /dev/null +++ b/peers/chaos/Geekz.Karibik.asc @@ -0,0 +1,8 @@ +-----BEGIN PGP MESSAGE----- + +hF4DxiX3uH/9xDgSAQdAkI811K4aERLcDVtx/EDFC+mcSRZCAPz+Dm7t+3fulygw +u24dZDVJGqBXRgtGfCaizV/UIU0uin4Iyhpx+BQiGuxAl+UuMmSWmiCxD+fjUiCJ +0k4BRPlzf15IVz1Xxy4vJMxm3iG+Tl39eyCVaTNEvHymnmwlhNdHfExWpppXfeH6 +b4EJ25PL4TANwofv8Bc0YKG5yU4mGXa4DTJNc9w/Jwk= +=kR1O +-----END PGP MESSAGE----- diff --git a/peers/chaos/default.nix b/peers/chaos/default.nix new file mode 100644 index 0000000..2bedc13 --- /dev/null +++ b/peers/chaos/default.nix @@ -0,0 +1,16 @@ +{ + wireless + = Peer "Wireless Lan chaos" + { + configuration + = { secret, ... }: + { + networking.wireless.networks + = { + "c3loc-guest" = {}; + "Chaosnetz".psk = secret.decryptVariable' "wireless" ./Chaosnetz.asc; + "Geekz.Karibik".psk = secret.decryptVariable' "wireless" ./Geekz.Karibik.asc; + }; + }; + }; +} diff --git a/peers/default.nix b/peers/default.nix new file mode 100644 index 0000000..ca37f24 --- /dev/null +++ b/peers/default.nix @@ -0,0 +1,12 @@ +{ + chaos = ./chaos; + deutsche-bahn = ./deutsche-bahn; + eduroam = ./eduroam; + fluepke = ./fluepke; + google = ./google; + hetzner = ./hetzner; + mum = ./mum; + petabytedev = ./petabytedev; + sivizius = ./sivizius; + tuc = ./tuc; +} diff --git a/peers/deutsche-bahn/default.nix b/peers/deutsche-bahn/default.nix new file mode 100644 index 0000000..cf2cc7e --- /dev/null +++ b/peers/deutsche-bahn/default.nix @@ -0,0 +1,11 @@ +{ + wireless + = Peer "Wireless Lan bahn" + { + configuration.networking.wireless.networks + = { + "WIFI@DB" = {}; + "WIFIonICE" = {}; + }; + }; +} diff --git a/peers/eduroam/default.nix b/peers/eduroam/default.nix new file mode 100644 index 0000000..782a6cb --- /dev/null +++ b/peers/eduroam/default.nix @@ -0,0 +1,23 @@ +{ + wireless + = Peer "Wireless Lan eduroam" + { + configuration + = { secret, ... }: + { + networking.wireless.networks."eduroam".extraConfig + = '' + ca_cert="${./eduroam.pem}" + key_mgmt=WPA-EAP + pairwise=CCMP + group=CCMP TKIP + eap=PEAP + identity="@id_eduroam@" + domain_suffix_match="radius2030.tu-chemnitz.de" + phase2="auth=MSCHAPV2" + password="@psk_eduroam@" + anonymous_identity="wpasupplicantconfapp_ca2030@tu-chemnitz.de" + ''; + }; + }; +} diff --git a/peers/eduroam/eduroam.pem b/peers/eduroam/eduroam.pem new file mode 100644 index 0000000..5881a54 --- /dev/null +++ b/peers/eduroam/eduroam.pem @@ -0,0 +1,36 @@ +-----BEGIN CERTIFICATE----- +MIIGLjCCBBagAwIBAgIJAONOGbgO3/24MA0GCSqGSIb3DQEBCwUAMIGjMQswCQYD +VQQGEwJERTEQMA4GA1UECAwHU2FjaHNlbjERMA8GA1UEBwwIQ2hlbW5pdHoxKTAn +BgNVBAoMIFRlY2huaXNjaGUgVW5pdmVyc2l0YWV0IENoZW1uaXR6MSMwIQYDVQQL +DBpVbml2ZXJzaXRhZXRzcmVjaGVuemVudHJ1bTEfMB0GA1UEAwwWVFUgQ2hlbW5p +dHogV0xBTiBDQSBHMTAeFw0xODAyMjgxNzMwMjVaFw00MzAyMjcxNzMwMjVaMIGj +MQswCQYDVQQGEwJERTEQMA4GA1UECAwHU2FjaHNlbjERMA8GA1UEBwwIQ2hlbW5p +dHoxKTAnBgNVBAoMIFRlY2huaXNjaGUgVW5pdmVyc2l0YWV0IENoZW1uaXR6MSMw +IQYDVQQLDBpVbml2ZXJzaXRhZXRzcmVjaGVuemVudHJ1bTEfMB0GA1UEAwwWVFUg +Q2hlbW5pdHogV0xBTiBDQSBHMTCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoC +ggIBAONA+4woOCrp8AHHnV7FAdx948GI268HnzCqQ35IBXyecTaMHmszSvUiKn28 +7ppBMictYRZbyrd5xZG0vZbKOywuA9824EXMMV8K5Un94lBjAwGKlTwWMSPLvrUB +z98jMdUBpU3c+Cg6JWRbSjU7ZlbjvCtwfdzBLRlAt+Ikkdo82CQRMCQkxhs+qhh/ +wkNR3Pt45V9oxBZxz61QQ4EzlGkw6n4kovFiMkMFebgwVFkg8L8A+BxR9K1Q0IUJ +jEaBTXq22vfBAUxjAertOD2320oJUi95GKZFCOyyE6JMNNuBMIiq7Q9mbfcXq8TR +sQYqmr+vOK28iSlwTAdnsrlovskazyllZdqZcNjDHiMWX/mJpJbi3HeMHiidYB+9 +ISJuwnLuhtwUuIdx7z3+ZP8BpV+gGlhySisWjA3Bm6ZwBea0IeUrTtf81safbEeB +yYalonw3EGuNzCsSy88CwLEmGADfOdSaayYN7gxROAlBl3/HDCASpWMDNr5bPKeA +rL/o1edKtvQpEqayIaZbXZbKnenZk1r/fETcgoHwCmFfRGtGW+zODzRKqDxdfARs +MyASypnm1aDR1mPi9b7zjqdbyytA0Mmu65hbjXhkWjR0hX8b25XvKPIeqyGxQ3O0 +IKr+JcRmyda9tTAFeyy7j3kncE4rfTrA0kt0AlKKafBUdZJ1AgMBAAGjYzBhMB0G +A1UdDgQWBBQo6EEXTfXh7Ppr32TVSh/5K5U63TAfBgNVHSMEGDAWgBQo6EEXTfXh +7Ppr32TVSh/5K5U63TAPBgNVHRMBAf8EBTADAQH/MA4GA1UdDwEB/wQEAwIBhjAN +BgkqhkiG9w0BAQsFAAOCAgEAfXy4v2XDILgXahSWhkGFUxJtdWPNbjzkgAjLMJvB +F+xcEOsUnQ3E2nOR2rLuFLWDs4f1X2MQWoMIyHvEHB0qbcd34is91r2nRYZ5+i91 +8bC0lVwiyHEaALVLJ1Hs86F/Ii6i6Oc+SWEapFDHLyBWUG2ZymgUknN+5LdtveCL +K/5vNc4VO2sP3ZVKVMCh/2ct1WZneHQ0RFb47WrFuwavyJy/q3YGKLRlhHt5QyNi +gvilBpmP1CFgz0SFrVuHsVMMUPZDQKP4mfJ7ELnUaFu4VkIv61Wo9lF85oaQ0mfl +oJmqWyKpd7/Fzfz1SdkyXGMfUdegHEMVoN1CkjBIZqhzz1iEAaZDF5gNOmWNARk6 +ObMGpvnCYYsPTqt0UQgr6n9EGpXUNxaCgl3CdNCQ+mFCO6MVpDSEc+mkjCNFNt8x +9K1pzlVLG9B0bLdB8cD+oOair6pqfqM+ulpdW7NORkzvZPIO/VV82wfJDTnDenU3 +dZFptv+LFjeqgXDv/PmcliAWkEs9ZE/slC6OzdGHjZWLFb8DfA/rctn+5iM3gvNv +FEMfZ0XQ9D4RvautPx15fEP1w/Zs9QYAyyAaSoO7rV6wuXZqqJX5ZuyLarndgB8B +OGa3TKHpP27EoUIaFYl/+ZsLtOWvHdOFZxbRxVjPpvn5Svo15j4WVWSIjaGzic7H +Bf8= +-----END CERTIFICATE----- diff --git a/peers/flake.nix b/peers/flake.nix new file mode 100644 index 0000000..a723045 --- /dev/null +++ b/peers/flake.nix @@ -0,0 +1,30 @@ +{ + description = "Sivizius’ peers."; + inputs + = { + libconfig.url = "github:sivizius/nixfiles/development?dir=libs/config"; + libcore.url = "github:sivizius/nixfiles/development?dir=libs/core"; + libsecrets.url = "github:sivizius/nixfiles/development?dir=libs/secrets"; + }; + outputs + = { self, libconfig, libcore, libsecrets, ... }: + let + config = libconfig.lib { inherit self; }; + core = libcore.lib { inherit self; debug.logLevel = "info"; }; + in + { + peers + = core.debug.debug "peers" + { + nice = true; + show = true; + } + ( + config.peers.load ./. + { + inherit core; + inherit(libsecrets.lib { inherit self; }) secret; + } + ); + }; +} diff --git a/peers/fluepke/Paketschleuder.asc b/peers/fluepke/Paketschleuder.asc new file mode 100644 index 0000000..8d59d76 --- /dev/null +++ b/peers/fluepke/Paketschleuder.asc @@ -0,0 +1,9 @@ +-----BEGIN PGP MESSAGE----- + +hF4DxiX3uH/9xDgSAQdAiITq6UIXnXnuryJ0sSHGSm+FBc9WYSUVAklydqfplGMw +hJ402wadFNDgil20LTwbEv97W02fZgLlHVWHw4NaXt07iKibsFXSY1Gfgku731ZF +0l8BBEUBi46EF3Iwm64BaDDhEtt+AFjdiQN2dYxI0jjBCRYdmlsq+EM0kIkvziOw +l7lL0qdVJi+VY7rg0qclIcE12NmmCRTFOK5Mwt+Iw6Y2HN1tyrJYW9lN99YxZJ5c +5A== +=ERdI +-----END PGP MESSAGE----- diff --git a/peers/fluepke/Vodafone-F88C.asc b/peers/fluepke/Vodafone-F88C.asc new file mode 100644 index 0000000..e26214e --- /dev/null +++ b/peers/fluepke/Vodafone-F88C.asc @@ -0,0 +1,8 @@ +-----BEGIN PGP MESSAGE----- + +hF4DxiX3uH/9xDgSAQdAfeg23HfeV0laZpgIgtJvXYi3nf3B84C8eoVdWQQQDhIw +oLzCMeuMWk3w85fqNWe1qstcFD8WLo01uxk0gYIagOQlqeCakL80qMRD1EsIMZZw +0lYBhcDikqjZU8iBZ1PEBkwVTOEP3xNHhUJnginxfIAze82OwJyAtF4kqLxyeEQi +nfLibESJt2E+fxquhEztbnz00R5OcD7gl45QW1aGvTpMWzOON3mW4Q== +=qXGA +-----END PGP MESSAGE----- diff --git a/peers/fluepke/default.nix b/peers/fluepke/default.nix new file mode 100644 index 0000000..d0bf1ed --- /dev/null +++ b/peers/fluepke/default.nix @@ -0,0 +1,41 @@ +{ + wireguard + = Peer "Wireguard-Tunnel to …?" + { + configuration + = { secret, ... }: + { + networking.wg-quick.interfaces."fluepke" + = { + address + = [ + "45.158.43.132/32" + ]; + autostart = false; + peers + = [ + { + allowedIPs = [ "0.0.0.0/0" ]; + endpoint = "45.158.43.1:51213"; + publicKey = "PZlXawIBMsmOkesNbwSsiufvicbNgKaeyQ560novDHY="; + } + ]; + privateKeyFile = secret.decrypt' ./wgToken.asc; + }; + }; + }; + wireless + = Peer "Wireless Lan fluepke" + { + configuration + = { secret, ... }: + { + networking.wireless.networks + = { + Paketschleuder.psk = secret.decryptVariable' "wireless" ./Paketschleuder.asc; + Vodafone-F88C.psk = secret.decryptVariable' "wireless" ./Vodafone-F88C.asc; + "wifi.fluep.ke".psk = secret.decryptVariable' "wireless" ./wifi.fluep.ke.asc; + }; + }; + }; +} diff --git a/peers/fluepke/wgToken.asc b/peers/fluepke/wgToken.asc new file mode 100644 index 0000000..b31dbdc --- /dev/null +++ b/peers/fluepke/wgToken.asc @@ -0,0 +1,11 @@ +-----BEGIN PGP MESSAGE----- + +hF4DQpmXgCyyA4oSAQdAsyrI114ht6yG0btsvBREcPc9vits4YMlo9t18NcYoHQw +EtC8pF/zGvntk2s2EK0uoqLXbiBEX6YYqGZ8v55CpQ6v2T8jddFjnQ6DmuJ6ore+ +hF4DxiX3uH/9xDgSAQdANk0FofrPAZvHXU8ZLydZ1xhaLl8Nxofw1wXIlosEACww +y46fFl7ytxSCXY+hQbvWB896TXDQ7OGiCy6Qdsi9xaZGXLd+0MuScQnX63af86Nq +0mUBG14n4d2vCy9uKGpC4ulBuvUFBdKmU4GSZ9XXWiYJBfLeNSMueX6bYqeFNK5D +bGZI+tF+dQb8tepO0cojiyK8kOXgMAubZKW5JYs7HJ9EFrnazZeAkMBOfbOEfTKj +U5CxM52dbQ== +=9TjB +-----END PGP MESSAGE----- diff --git a/peers/fluepke/wifi.fluep.ke.asc b/peers/fluepke/wifi.fluep.ke.asc new file mode 100644 index 0000000..91ca7eb --- /dev/null +++ b/peers/fluepke/wifi.fluep.ke.asc @@ -0,0 +1,9 @@ +-----BEGIN PGP MESSAGE----- + +hF4DxiX3uH/9xDgSAQdAyL7yvw2kAR1pfI0Lt+RIw0UgT+ItvuxGtgdeivJtpzIw +2t4/6Dlq4rLQeq51CRZB7A5btPFW24TahJ26G+I/IF90fNzMV2GSjV066SQsOoXt +0mYBRu/GZ9syW/OpRDSRUJSzFyGWFokyAtpAfV7IyUE6IHPnsEKx+E5usGRWR4+d +OdS59mOSVt2A1L2MIuYhCidgP6XFwQUEipUEzC6sO04Hnh0fTe2Ga9tS7JGoGZ0d +UWUkh3fxIe8= +=wzI2 +-----END PGP MESSAGE----- diff --git a/peers/google/default.nix b/peers/google/default.nix new file mode 100644 index 0000000..874784e --- /dev/null +++ b/peers/google/default.nix @@ -0,0 +1,24 @@ +{ core, ... }: + let + inherit(core) set; + in + set.map + ( + name: + ips: + let + domain = "dns.google"; + in + Peer "${domain} (${name})." + { + type.dns-forwarder = true; + network + = { + inherit domain ips; + }; + } + ) + { + ns1 = [ "2001:4860:4860::8888" "8.8.8.8" ]; + ns2 = [ "2001:4860:4860::8844" "8.8.4.4" ]; + } diff --git a/peers/hetzner/default.nix b/peers/hetzner/default.nix new file mode 100644 index 0000000..5f2ad4c --- /dev/null +++ b/peers/hetzner/default.nix @@ -0,0 +1,25 @@ +{ core, ... }: + let + inherit(core) set; + in + set.map + ( + name: + ips: + let + domain = "${name}.hetzner.de"; + in + Peer "${domain}." + { + type.dns-forwarder = true; + network + = { + inherit domain ips; + }; + } + ) + { + ns1-coloc = [ "2a01:4f8:0:1::add:9898" "213.133.98.98" ]; + ns2-coloc = [ "2a01:4f8:0:1::add:9999" "213.133.99.99" ]; + ns3-coloc = [ "2a01:4f8:0:1::add:1010" "213.133.100.100" ]; + } diff --git a/peers/mum/Webbot.asc b/peers/mum/Webbot.asc new file mode 100644 index 0000000..0d353fe --- /dev/null +++ b/peers/mum/Webbot.asc @@ -0,0 +1,9 @@ +-----BEGIN PGP MESSAGE----- + +hF4DxiX3uH/9xDgSAQdArs+Crp2WZdm3fX/sXChV7ungaGV2gz2ZB3Hq+3acTQEw +gT4gyxhJUGdXso4rRdY0oZyja6qZCrZ6Abspj0W8/rqGcWaK3XOE+6bdPb4H20Xv +0msB8n20nkdi598qZFhWExwAHkgH0SprcLpWi8a0CW2mEEQMQ3yOCf2qAbttdyaG +F8XfFn1uDgS9UGL74KYUpsKyCjnsdjpn0v8wkIf1qEOAqGZBreIDOKUQ6FcL4yD/ +MJnT/WUQ/RJHQZWwmQ== +=lV6R +-----END PGP MESSAGE----- diff --git a/peers/mum/default.nix b/peers/mum/default.nix new file mode 100644 index 0000000..f35ea43 --- /dev/null +++ b/peers/mum/default.nix @@ -0,0 +1,14 @@ +{ + webbot + = Peer "Webbot Wireless LAN" + { + configuration + = { secret, ... }: + { + networking.wireless.networks + = { + "Webbot".psk = secret.decryptVariable' "wireless" ./Webbot.asc; + }; + }; + }; +} diff --git a/peers/petabytedev/default.nix b/peers/petabytedev/default.nix new file mode 100644 index 0000000..84c7668 --- /dev/null +++ b/peers/petabytedev/default.nix @@ -0,0 +1,19 @@ +{ core, ... }: + let + inherit(core) string; + + Peer' + = number: + domain: + ips: + Peer "Domain Name Server ${string number}" + { + network = { inherit domain ips; }; + type.dns-secondary = true; + }; + in + { + dns1 = Peer' 1 "ns1.pbb.lc" [ "2a01:4f8:c0c:473f::1" ]; + dns2 = Peer' 2 "ns2.pbb.lc" [ "2a0f:4ac0:0:1::1" ]; + dns3 = Peer' 3 "ns3.pbb.lc" [ "2a0f:4ac0::3" ]; + } diff --git a/peers/sivizius/SiviPhone.asc b/peers/sivizius/SiviPhone.asc new file mode 100644 index 0000000..e0c0b09 --- /dev/null +++ b/peers/sivizius/SiviPhone.asc @@ -0,0 +1,8 @@ +-----BEGIN PGP MESSAGE----- + +hF4DxiX3uH/9xDgSAQdA52/8jOZo7z88Lq6FuycaYZh4k4HtRchzQUoeFsrtPRww +f8KvJhxiZnpjkELT7VhLnUZPf606vgwMac1WZ6YsNxx0HpjizLze7vgOLUpQkTVp +0koBYqht/H+ozOe2iGOc6IVjHt1aNnRDGpwdBAa6qOP/g+UVkKQbdLDfTB3fF5MZ +y0Pl/5mImhlA+hTyzPv+wDpkpTietLc0j6xwqg== +=oEco +-----END PGP MESSAGE----- diff --git a/peers/sivizius/default.nix b/peers/sivizius/default.nix new file mode 100644 index 0000000..764a41f --- /dev/null +++ b/peers/sivizius/default.nix @@ -0,0 +1,18 @@ +{ + phone + = Peer "Siviphone" + { + configuration + = { secret, ... }: + { + networking.wireless.networks + = { + "SiviPhone" + = { + psk = secret.decryptVariable' "wireless" ./SiviPhone.asc; + authProtocols = [ "WPA-PSK" "WPA-EAP" "FT-PSK" "FT-EAP" ]; + }; + }; + }; + }; +} diff --git a/peers/tuc/default.nix b/peers/tuc/default.nix new file mode 100644 index 0000000..8612d66 --- /dev/null +++ b/peers/tuc/default.nix @@ -0,0 +1,31 @@ +{ + kerberos + = Peer "Kerberos-Server" + { + configuration.krb5 + = { + domain_realm + = { + ".tu-chemnitz.de" = "TU-CHEMNITZ.DE"; + }; + enable = true; + libdefaults + = { + default_ccache_name = "KEYRING:persistent:%{uid}"; + default_realm = "TU-CHEMNITZ.DE"; + + dns_lookup_kdc = true; + dns_lookup_realm = false; + forwardable = true; + rdns = false; + renew_lifetime = "30d"; + ticket_lifetime = "30d"; + }; + realms."TU-CHEMNITZ.DE" + = { + admin_server = "kerberos-adm.tu-chemnitz.de"; + kdc = "kerberos.tu-chemnitz.de"; + }; + }; + }; +} diff --git a/profiles/common/assets/arstotzka.txt b/profiles/common/assets/arstotzka.txt new file mode 100644 index 0000000..c02d7b3 --- /dev/null +++ b/profiles/common/assets/arstotzka.txt @@ -0,0 +1,20 @@ + ________ ___ ________ + ________________________________ \ \ _/ / / / ________________________________ +| \ \ \ | / /| / / / | +| \ \ | | \/ / | / / | +|__________________________________\ \ |__| |__| / /__________________________________| + ____________________________________ \ / ____________________________________ +| \ \ |\___/\___/| / / | +| \ \ | /\ | / / | +|______________________________________\ \ | / / | / /______________________________________| + ________________________________________ \ \ / / / / ________________________________________ +| \ \ \ \/ / / / | +| \ \ \ / / / | +|__________________________________________\ _| \____/ |_ /__________________________________________| + |/\ /\| + /_ _\ + \ / + \ / + \__/ + GLORY TO ARSTOTZKA + Welcome to Arstotzka – All your actions will be monitored and reported to the Ministry of Information! diff --git a/profiles/common/assets/background.png b/profiles/common/assets/background.png new file mode 100755 index 0000000..a3b90d0 Binary files /dev/null and b/profiles/common/assets/background.png differ diff --git a/profiles/common/assets/bg-628x535-anarchy.png b/profiles/common/assets/bg-628x535-anarchy.png new file mode 100644 index 0000000..b1a62f2 Binary files /dev/null and b/profiles/common/assets/bg-628x535-anarchy.png differ diff --git a/profiles/common/assets/bg-628x535-anarchy.xcf b/profiles/common/assets/bg-628x535-anarchy.xcf new file mode 100644 index 0000000..f655f9b Binary files /dev/null and b/profiles/common/assets/bg-628x535-anarchy.xcf differ diff --git a/profiles/common/assets/bg-628x535.png b/profiles/common/assets/bg-628x535.png new file mode 100644 index 0000000..515eb9c Binary files /dev/null and b/profiles/common/assets/bg-628x535.png differ diff --git a/profiles/common/boot.nix b/profiles/common/boot.nix new file mode 100644 index 0000000..6d52991 --- /dev/null +++ b/profiles/common/boot.nix @@ -0,0 +1,7 @@ +{ + boot + = { + enableContainers = true; + tmpOnTmpfs = true; + }; +} diff --git a/profiles/common/default.nix b/profiles/common/default.nix new file mode 100644 index 0000000..5dccf21 --- /dev/null +++ b/profiles/common/default.nix @@ -0,0 +1,11 @@ +{ services, ... }: + Profile "Common." + { + configuration + = [ + ./boot.nix + ./environment.nix + ./system.nix + ]; + services = with services; [ gnupg openssh ]; + } diff --git a/profiles/common/environment.nix b/profiles/common/environment.nix new file mode 100644 index 0000000..26362be --- /dev/null +++ b/profiles/common/environment.nix @@ -0,0 +1,14 @@ +{ + console + = { + keyMap = "de"; + }; + i18n.defaultLocale = "C.UTF-8"; + time.timeZone = "Europe/Berlin"; + environment.pathsToLink + = [ + "/share/bash-completion" + "/share/fish" + "/share/zsh" + ]; +} diff --git a/profiles/common/system.nix b/profiles/common/system.nix new file mode 100644 index 0000000..10771c5 --- /dev/null +++ b/profiles/common/system.nix @@ -0,0 +1,52 @@ +{ registries, ... }: +{ + nix + = { + extraOptions + = '' + experimental-features = nix-command flakes + ''; + gc + = { + automatic = true; + options = "--delete-older-than 14d"; + }; + optimise + = { + automatic = true; + dates = [ "23:42" ]; + }; + settings + = { + auto-optimise-store = true; + trusted-users + = [ + "root" + "@wheel" + ]; + }; + }; + + security.sudo.extraConfig + = '' + Defaults lecture = always + Defaults lecture_file = ${./assets/arstotzka.txt} + ''; + + system + = { + autoUpgrade + = { + allowReboot = false; + dates = "04:20"; + enable = false; + flake = "github:sivizius/nixfiles/stable"; + }; + }; + + programs.zsh.enable = true; + users + = { + defaultUserShell = registries.nix.zsh; + }; +} diff --git a/profiles/default.nix b/profiles/default.nix new file mode 100644 index 0000000..b5ba74f --- /dev/null +++ b/profiles/default.nix @@ -0,0 +1,5 @@ +{ + common = ./common; + desktop = ./desktop; + hetznerCloudServer = ./hetznerCloudServer; +} diff --git a/profiles/desktop/default.nix b/profiles/desktop/default.nix new file mode 100644 index 0000000..fa17b02 --- /dev/null +++ b/profiles/desktop/default.nix @@ -0,0 +1,28 @@ +{ profiles, services, ... }: + Profile "Desktop." + { + configuration + = [ + ./fonts + ./hardware + { + documentation + = { + enable = true; + dev.enable = true; + doc.enable = true; + info.enable = true; + man.enable = true; + nixos.enable = false; + }; + security.pam.services + = { + # To make Swaylock unlockable. + swaylock = { /* empty */ }; + }; + } + ]; + isDesktop = true; + parents = with profiles; [ common ]; + services = with services; [ docker printing ]; + } diff --git a/profiles/desktop/fonts/default.nix b/profiles/desktop/fonts/default.nix new file mode 100644 index 0000000..249091d --- /dev/null +++ b/profiles/desktop/fonts/default.nix @@ -0,0 +1,30 @@ +{ core, registries, ... }: +{ + fonts + = { + fonts + = with registries.nix; + [ + dejavu_fonts + font-awesome_5 + liberation_ttf + noto-fonts + noto-fonts-emoji + roboto + roboto-mono + roboto-slab + unifont + ]; + fontconfig + = { + localConf = core.path.readFile ./fontconfig.xml; + defaultFonts + = { + emoji = [ "Noto Color Emoji" ]; + serif = [ "Dejavu Serif" ]; + sansSerif = [ "Roboto Condensed" ]; + monospace = [ "Roboto Mono" ]; + }; + }; + }; +} diff --git a/profiles/desktop/fonts/fontconfig.xml b/profiles/desktop/fonts/fontconfig.xml new file mode 100644 index 0000000..f3f6bb3 --- /dev/null +++ b/profiles/desktop/fonts/fontconfig.xml @@ -0,0 +1,22 @@ + + + + + monospace + + emoji + + + + sans-serif + + emoji + + + + serif + + emoji + + + diff --git a/profiles/desktop/hardware/bluetooth.nix b/profiles/desktop/hardware/bluetooth.nix new file mode 100644 index 0000000..a9aa765 --- /dev/null +++ b/profiles/desktop/hardware/bluetooth.nix @@ -0,0 +1,10 @@ +{ + hardware.bluetooth + = { + enable = true; + settings + = { + General.Enable = "Source,Sink,Media,Socket"; + }; + }; +} diff --git a/profiles/desktop/hardware/boot.nix b/profiles/desktop/hardware/boot.nix new file mode 100644 index 0000000..1e5d2c9 --- /dev/null +++ b/profiles/desktop/hardware/boot.nix @@ -0,0 +1,38 @@ +{ registries, ... }: +{ + boot + = { + extraModulePackages = with registries.linux; [ acpi_call ]; + initrd + = { + availableKernelModules + = [ + "ahci" + "ehci_pci" + "firewire_ohci" + "rtsx_pci_sdmmc" + "nvme" + "sd_mod" + "sdhci_pci" + "sr_mod" + "usb_storage" + "xhci_pci" + ]; + kernelModules = [ "acpi_call" ]; + luks.devices."nixos" + = { + device = "/dev/disk/by-label/encrypted"; + }; + }; + kernelModules = [ "kvm-intel" ]; + loader.grub + = { + device = "nodev"; + efiSupport = true; + efiInstallAsRemovable = true; + enable = true; + memtest86.enable = true; + version = 2; + }; + }; +} diff --git a/profiles/desktop/hardware/default.nix b/profiles/desktop/hardware/default.nix new file mode 100644 index 0000000..c1ecf9b --- /dev/null +++ b/profiles/desktop/hardware/default.nix @@ -0,0 +1,15 @@ +[ + ./bluetooth.nix + ./boot.nix + ./pulseaudio.nix + ./scanner.nix + ./trackpoint.nix + { + hardware.gpgSmartcards.enable = true; + services.pcscd.enable = true; + + hardware.opengl.enable = true; + nix.settings.max-jobs = 8; + powerManagement.cpuFreqGovernor = "powersave"; + } +] diff --git a/profiles/desktop/hardware/pulseaudio.nix b/profiles/desktop/hardware/pulseaudio.nix new file mode 100644 index 0000000..dfccf80 --- /dev/null +++ b/profiles/desktop/hardware/pulseaudio.nix @@ -0,0 +1,15 @@ +{ registries, ... }: +{ + hardware.pulseaudio + = { + enable = true; + extraModules = [ ]; + extraConfig + = '' + load-module module-switch-on-connect + ''; + package = registries.nix.pulseaudioFull; + }; + nixpkgs.config.pulseaudio = true; + sound.enable = true; +} diff --git a/profiles/desktop/hardware/scanner.nix b/profiles/desktop/hardware/scanner.nix new file mode 100644 index 0000000..9e94d9d --- /dev/null +++ b/profiles/desktop/hardware/scanner.nix @@ -0,0 +1,16 @@ + +{ registries, ... }: +{ + environment.systemPackages + = with registries.nix; + [ + sane-backends + xsane + ]; + hardware.sane + = { + enable = true; + extraBackends = with registries.nix; [ epkowa hplipWithPlugin sane-airscan ]; + }; + services.ipp-usb.enable = true; +} diff --git a/profiles/desktop/hardware/trackpoint.nix b/profiles/desktop/hardware/trackpoint.nix new file mode 100644 index 0000000..3945342 --- /dev/null +++ b/profiles/desktop/hardware/trackpoint.nix @@ -0,0 +1,7 @@ +{ + hardware.trackpoint + = { + enable = true; + sensitivity = 112; + }; +} diff --git a/profiles/flake.nix b/profiles/flake.nix new file mode 100644 index 0000000..360ca97 --- /dev/null +++ b/profiles/flake.nix @@ -0,0 +1,50 @@ +{ + description = "Sivizius’ profiles."; + inputs + = { + libcore.url = "github:sivizius/nixfiles/development?dir=libs/core"; + libconfig.url = "github:sivizius/nixfiles/development?dir=libs/config"; + nixpkgs.url = "github:sivizius/nixpkgs/master"; + services.url = "github:sivizius/nixfiles/development?dir=services"; + }; + outputs + = { self, libcore, libconfig, nixpkgs, services, ... }: + let + core = libcore.lib { inherit self; debug.logLevel = "info"; }; + config = libconfig.lib { inherit self; }; + legacyProfiles + = config.profiles.importLegacy { inherit nixpkgs; } + [ + "all-hardware" + "base" + "clone-config" + "demo" + "docker-container" + "graphical" + "hardened" + "headless" + "installation-device" + "minimal" + "qemu-guest" + ]; + profiles + = legacyProfiles + // ( + config.profiles.load ./. + { + inherit core profiles; + inherit(services) services; + } + ); + in + { + profiles + = core.debug.debug "profiles" + { + nice = true; + show = true; + when = false; + } + profiles; + }; +} diff --git a/profiles/hetznerCloudServer/default.nix b/profiles/hetznerCloudServer/default.nix new file mode 100644 index 0000000..6f08b59 --- /dev/null +++ b/profiles/hetznerCloudServer/default.nix @@ -0,0 +1,14 @@ +{ profiles, services, ... }: + Profile "Hetzner Cloud-Server." + { + configuration + = [ + ./hardware + { + documentation.enable = false; + } + ]; + isDesktop = false; + parents = with profiles; [ common qemu-guest ]; + services = with services; [ bind gitea monitoring nginx simple-nix-mail static ]; + } diff --git a/profiles/hetznerCloudServer/hardware/boot.nix b/profiles/hetznerCloudServer/hardware/boot.nix new file mode 100644 index 0000000..f210382 --- /dev/null +++ b/profiles/hetznerCloudServer/hardware/boot.nix @@ -0,0 +1,32 @@ +{ + boot + = { + extraModulePackages = [ ]; + initrd + = { + availableKernelModules + = [ + "ata_piix" + "sd_mod" + "sr_mod" + "virtio_pci" + "xhci_pci" + ]; + kernelModules = [ ]; + luks.devices."encrypted" + = { + #device = "/dev/disk/by-label/encrypted"; + #device = "/dev/disk/by-uuid/09675dae-475b-47ff-8969-c5dee915b943"; + device = "/dev/sda2"; + }; + network.ssh.enable = true; + }; + kernelModules = [ ]; + loader.grub + = { + devices = [ "/dev/sda" ]; + enable = true; + version = 2; + }; + }; +} diff --git a/profiles/hetznerCloudServer/hardware/default.nix b/profiles/hetznerCloudServer/hardware/default.nix new file mode 100644 index 0000000..ff13ed0 --- /dev/null +++ b/profiles/hetznerCloudServer/hardware/default.nix @@ -0,0 +1,7 @@ +[ + ./boot.nix + ./network.nix + { + nix.settings.max-jobs = 1; + } +] diff --git a/profiles/hetznerCloudServer/hardware/network.nix b/profiles/hetznerCloudServer/hardware/network.nix new file mode 100644 index 0000000..6470ef6 --- /dev/null +++ b/profiles/hetznerCloudServer/hardware/network.nix @@ -0,0 +1,53 @@ +{ core, network, users, ... }: + let + inherit(core) set; + in + { + boot.initrd.network + = { + enable = true; + postCommands + = '' + echo 'cryptsetup-askpass' >> /root/.profile + ''; + ssh + = { + # TODO: We might not trust every user. + authorizedKeys + = set.foldValues + ( + authorizedKeys: + { trusted, user, ... }: + if trusted + then + authorizedKeys ++ (user.keys.${network.hostName} or []) + else + authorizedKeys + ) + [] + users; + enable = true; + # List of Paths to Private Keys as Strings. + hostKeys = [ "/etc/initrdSecret.ssh" ]; + port = network.tcp.ports.initrd.ssh; + }; + }; + + networking + = { + defaultGateway6 + = { + address = "fe80::1"; + interface = "ens3"; + }; + }; + + security.acme + = { + acceptTerms = true; + defaults + = { + email = "cert@${network.domain}"; + }; + }; + } diff --git a/registries/default.nix b/registries/default.nix new file mode 100644 index 0000000..1ae3869 --- /dev/null +++ b/registries/default.nix @@ -0,0 +1,141 @@ +{ + agda = "agdaPackages"; + androidStudio = "androidStudioPackages"; + apacheHttpd = "apacheHttpdPackages"; + arcan = "arcanPackages"; + aspell = "aspellDicts"; + atom = "atomPackages"; + beam = "beamPackages"; + beets = "beetsPackages"; + build = "buildPackages"; + chicken = "chickenPackages"; + connman = "connmanPackages"; + coq = "coqPackages"; + cuda = "cudaPackages"; + defaultPkgConfig = "defaultPkgConfigPackages"; + dhall = "dhallPackages"; + dotnetCore = "dotnetCorePackages"; + dotnet = "dotnetPackages"; + dwarf-fortress = "dwarf-fortress-packages"; + elm = "elmPackages"; + emacs28 = "emacs28Packages"; + emacs = "emacsPackages"; + emscripten = "emscriptenPackages"; + fdb = "fdbPackages"; + firefox = "firefoxPackages"; + flutter = "flutterPackages"; + fuse = "fusePackages"; + gnome = "gnome"; + gns3 = "gns3Packages"; + gnuradio3_8 = "gnuradio3_8Packages"; + gnuradio3_9 = "gnuradio3_9Packages"; + gnuradio = "gnuradioPackages"; + graalvmCE = "graalvmCEPackages"; + gradle = "gradle-packages"; + hare = "harePackages"; + haskell = "haskellPackages"; + haxe = "haxePackages"; + hspell = "hspellDicts"; + hunspell = "hunspellDicts"; + idris = "idrisPackages"; + java = "javaPackages"; + kodi = "kodiPackages"; + linux = "linuxPackages"; + linuxKernel = "linuxKernel"; + lisp = "lispPackages"; + lisp' = "lispPackages_new"; + llvm = "llvmPackages"; + lua51 = "lua51Packages"; + lua52 = "lua52Packages"; + lua53 = "lua53Packages"; + lua54 = "lua54Packages"; + lua = "luaPackages"; + luajit = "luajitPackages"; + mailman = "mailmanPackages"; + mkCoq = "mkCoqPackages"; + mopidy = "mopidyPackages"; + nextcloud24 = "nextcloud24Packages"; + nextcloud25 = "nextcloud25Packages"; + nextcloud26 = "nextcloud26Packages"; + nim = "nimPackages"; + nix = null; + node = "nodePackages"; + node' = "nodePackages_latest"; + ocaml = "ocamlPackages"; + octave = "octavePackages"; + openconnect = "openconnectPackages"; + openra = "openraPackages"; + openssh = "opensshPackages"; + optifine = "optifinePackages"; + perl534 = "perl534Packages"; + perl536 = "perl536Packages"; + perl = "perlPackages"; + perldevel = "perldevelPackages"; + php73 = "php73Packages"; + php74 = "php74Packages"; + php80 = "php80Packages"; + php81 = "php81Packages"; + php82 = "php82Packages"; + php = "phpPackages"; + plasma5 = "plasma5Packages"; + platformio = "platformioPackages"; + postgresql11 = "postgresql11Packages"; + postgresql12 = "postgresql12Packages"; + postgresql13 = "postgresql13Packages"; + postgresql14 = "postgresql14Packages"; + postgresql15 = "postgresql15Packages"; + postgresql = "postgresqlPackages"; + pulumi = "pulumiPackages"; + pypy27 = "pypy27Packages"; + pypy2 = "pypy2Packages"; + pypy37 = "pypy37Packages"; + pypy38 = "pypy38Packages"; + pypy39 = "pypy39Packages"; + pypy3 = "pypy3Packages"; + pypy = "pypyPackages"; + python27 = "python27Packages"; + python2 = "python2Packages"; + python310 = "python310Packages"; + python311 = "python311Packages"; + python312 = "python312Packages"; + python38 = "python38Packages"; + python39 = "python39Packages"; + python3 = "python3Packages"; + pythonConda = "pythonCondaPackages"; + pythonManylinux = "pythonManylinuxPackages"; + python = "pythonPackages"; + qt6 = "qt6Packages"; + quicklisp = "quicklispPackages"; + quicklispClisp = "quicklispPackagesClisp"; + r = "rPackages"; + ruby = "rubyPackages"; + ruby_3_0 = "rubyPackages_3_0"; + ruby_3_1 = "rubyPackages_3_1"; + rust = "rustPackages"; + scons = "sconsPackages"; + skaware = "skawarePackages"; + sourceHan = "sourceHanPackages"; + sourceHanSans = "sourceHanSansPackages"; + sourceHanSerif = "sourceHanSerifPackages"; + splice = "splicePackages"; + steam = "steamPackages"; + sublime3 = "sublime3Packages"; + swift = "swiftPackages"; + target = "targetPackages"; + texlive = "texlive"; + thunderbird = "thunderbirdPackages"; + torch = "torchPackages"; + uefitool = "uefitoolPackages"; + ut2004 = "ut2004Packages"; + varnish60 = "varnish60Packages"; + varnish72 = "varnish72Packages"; + varnish = "varnishPackages"; + vscode-fhs = "vscode-fhsWithPackages"; + vscodium-fhs = "vscodium-fhsWithPackages"; + wine64 = "wine64Packages"; + wine = "winePackages"; + wineWow = "wineWowPackages"; + wordpress = "wordpressPackages"; + xen = "xenPackages"; + zeroad = "zeroadPackages"; +} diff --git a/registries/flake.nix b/registries/flake.nix new file mode 100644 index 0000000..1ecec05 --- /dev/null +++ b/registries/flake.nix @@ -0,0 +1,106 @@ +{ + description = "Packages"; + inputs + = { + fork-awesome.url = "github:sivizius/nixfiles/development?dir=packages/fork-awesome"; + libconfig.url = "github:sivizius/nixfiles/development?dir=libs/config"; + libcore.url = "github:sivizius/nixfiles/development?dir=libs/core"; + nixpkgs.url = "github:sivizius/nixpkgs/master"; + redshift-wayland.url = "github:sivizius/nixfiles/development?dir=packages/redshift-wayland"; + wofi-unpatched.url = "github:sivizius/nixfiles/development?dir=packages/wofi-unpatched"; + }; + outputs + = { self, fork-awesome, libconfig, libcore, nix, nixpkgs, redshift-wayland, wofi-unpatched, ... }: + let + inherit(libconfig.lib { inherit self; }) packages; + inherit(libcore.lib { inherit self; debug.logLevel = "info"; }) path set target; + + config + = { + allowedNonSourcePackages + = [ + "adoptopenjdk-hotspot-bin" + "ant" + "discord" + "electron" + "ghidra" + "gradle" + "hplip" + "i2p" + "iscan" + "iscan-data" + "iscan-gt-f720-bundle" + "iscan-gt-s80-bundle" + "iscan-gt-x770-bundle" + "iscan-gt-x820-bundle" + "iscan-nt-bundle" + "libreoffice" + "libreoffice-7.3.7.2-wrapped" + "pdftk" + "signal-desktop" + "sof-firmware" + "spotify" + "tor-browser-bundle-bin" + "vscodium" + "wine" + ]; + allowedUnfreePackages + = [ + "discord" + "hopper" + "memtest86-efi" + "spotify" + "hplip" + "iscan" + "iscan-data" + "iscan-gt-f720-bundle" + "iscan-gt-s80-bundle" + "iscan-gt-x770-bundle" + "iscan-gt-x820-bundle" + "iscan-nt-bundle" + ]; + }; + + custom + = target.System.mapStdenv + ( + system: + { + fork-awesome = fork-awesome.packages."${system}"; + redshift-wayland = redshift-wayland.packages."${system}"; + wofi-unpatched = wofi-unpatched.packages."${system}"; + } + ); + + registries + = { inherit custom; } + // ( + set.mapValues + (packages.fromNixpkgs { inherit config nixpkgs; }) + (path.import ./.) + ); + in + #builtins.trace self._type + #debug.debug "registries" { text = "Hello World"; when = true; } + { + registries + = ( + target.System.mapStdenv + ( + system: + set.mapValues + ( + { ... } @ registry: + registry."${system}" + ) + registries + ) + ) + // { + __functor + = { ... } @ registries: + { targetSystem, ... }: + registries."${targetSystem}"; + }; + }; +} diff --git a/services/bind/default.nix b/services/bind/default.nix new file mode 100644 index 0000000..70123e2 --- /dev/null +++ b/services/bind/default.nix @@ -0,0 +1,110 @@ +Service "BIND: DNS-Server" +{ + configuration + = { core, network, ... }: + let + inherit(core) list string; + inherit(network) domain hostName ips peers tcp; + inherit(tcp) ports; + + hostDomain = "${hostName}.${domain}"; + master = true; + masters = [ ]; + /*domainList + = [ + domain + hostDomain + "blog.${domain}" + "git.${domain}" + "grafana.${domain}" + "prometheus.${domain}" + "static.${domain}" + ]; + systemdAfterList + = list.mapValuesToSet + ( + domain: + { + name = "$acme-{domain}"; + value = { after = [ "bind.service" ]; }; + } + ) + domainList;*/ + ipsFromPeer + = list.concatMap + ({ network, ... }: network.ips); + allowedIPs + = string.concatMappedLines + (ip: "allow ${ip};") + ips; + extraConfig + = '' + ${allowedIPs} + deny all; + ''; + in + { + bind + = { + enable = true; + forwarders + = ipsFromPeer + ( + list.filter + ({ type ? {}, ... }: type.dns-forwarder or false) + peers + ); + cacheNetworks + = [ + "127.0.0.0/8" + "::/64" + ]; + zones + = [ + { + name = domain; + # TODO: Generate Zone-File + file = "${./zones}/${domain}"; + inherit master masters; + slaves + = ipsFromPeer + ( + list.filter + ({ type, ... }: type.dns-secondary or false) + peers + ); + } + ]; + }; + + nginx.virtualHosts.${hostDomain}.locations."/metrics/bind" + = { + inherit extraConfig; + proxyPass = "http://localhost:${string ports.exporters.bind}/metrics"; + }; + + prometheus + = { + exporters.bind + = { + enable = true; + port = ports.exporters.bind; + }; + scrapeConfigs + = [ + { + job_name = "bind"; + metrics_path = "/metrics/bind"; + scheme = "https"; + scrape_interval = "30s"; + static_configs + = [ + { + targets = [ hostDomain ]; + } + ]; + } + ]; + }; + }; +} diff --git a/services/bind/zones/sivizius.eu b/services/bind/zones/sivizius.eu new file mode 100644 index 0000000..4a8ee11 --- /dev/null +++ b/services/bind/zones/sivizius.eu @@ -0,0 +1,51 @@ +$ORIGIN sivizius.eu. +$TTL 3600 +@ A 95.217.131.201 ; IPv4 + AAAA 2a01:4f9:c010:6bf5::23 ; IPv6 + CAA ( + 0 ; flags + issue "letsencrypt.org" ; authority + ) + NS ns1.sivizius.eu. ; primary + NS ns1.pbb.lc. ; secondaries + NS ns2.pbb.lc. + NS ns3.pbb.lc. + SOA ( + ns1.sivizius.eu. ; primary dns-server + dns.sivizius.eu. ; e-mail + 2021031200 ; serial: YYYYMMDDxx + 1d ; refresh + 2h ; retry + 4w ; expire + 1h ; minimum TTL + ) + +; =#= mail-stuff =#= +@ MX ( + 10 ; priority + sivizius.eu. ; domain of webserver + ) + TXT "v=spf1 ip4:95.217.131.201 ip6:2a01:4f9:c010:6bf5::23 -all" +mail._domainkey TXT "v=DKIM1; k=rsa; p=MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDL44g8A5mH06tScjiaiY5UUK14lxiuIefyFhS5+BQFq6oaZEn9xfJQU8R3b+WpGrM3sbBUyl5IziS95x+0LwnAxs9p9mCYm72ffhvhKD5qvR5C3f5vWcWXaGqvZ6xe+vABa0huIfj3laXje3M9muokqDUg3SZN1Ccabznnd8XvoQIDAQAB" +_dmarc TXT "v=DMARC1;p=reject;pct=100;ruf=mailto:dmarc@sivizius.eu;adkim=s;aspf=s" +_token._dnswl TXT "c960bmrmw5qp5gnrjlufyjbuw29art04" + +; =#= services/applications =#= +api CNAME @ +blog CNAME @ +git CNAME @ +grafana CNAME @ +mail CNAME @ +prometheus CNAME @ +static CNAME @ +www CNAME @ + +; =#= hosts =#= +aleph CNAME @ +;bet +gimel A 95.217.131.201 + AAAA 2a01:4f9:c010:6bf5::23 + +; =#= nameservers =#= +ns1 A 95.217.131.201 + AAAA 2a01:4f9:c010:6bf5::23 diff --git a/services/bind/zones/sivizius.nix b/services/bind/zones/sivizius.nix new file mode 100644 index 0000000..0f22136 --- /dev/null +++ b/services/bind/zones/sivizius.nix @@ -0,0 +1,59 @@ +{ + enable = true; + domain = "sivizius.eu"; + ttl = 3600; + + + "@" + = +} + + +$ORIGIN sivizius.eu. +$TTL 3600 +@ A 95.217.131.201 ; IPv4 + AAAA 2a01:4f9:c010:6bf5::23 ; IPv6 + CAA ( + 0 ; flags + issue "letsencrypt.org" ; authority + ) + NS ns1.sivizius.eu. ; primary + NS ns1.pbb.lc. ; secondaries + NS ns2.pbb.lc. + NS ns3.pbb.lc. + SOA ( + ns1.sivizius.eu. ; primary dns-server + dns.sivizius.eu. ; e-mail + 2020052400 ; serial: YYYYMMDDxx + 1d ; refresh + 2h ; retry + 4w ; expire + 1h ; minimum TTL + ) + +; =#= mail-stuff =#= +@ MX ( + 10 ; priority + sivizius.eu. ; domain of webserver + ) + TXT "v=spf1 ip4:95.217.131.201 ip6:2a01:4f9:c010:6bf5::23 -all" +mail._domainkey TXT "v=DKIM1; k=rsa; p=MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDL44g8A5mH06tScjiaiY5UUK14lxiuIefyFhS5+BQFq6oaZEn9xfJQU8R3b+WpGrM3sbBUyl5IziS95x+0LwnAxs9p9mCYm72ffhvhKD5qvR5C3f5vWcWXaGqvZ6xe+vABa0huIfj3laXje3M9muokqDUg3SZN1Ccabznnd8XvoQIDAQAB" +_dmarc TXT "v=DMARC1;p=reject;pct=100;ruf=mailto:dmarc@sivizius.eu;adkim=s;aspf=s" +_token._dnswl TXT "c960bmrmw5qp5gnrjlufyjbuw29art04" + +; =#= services/applications =#= +blog CNAME @ +git CNAME @ +grafana CNAME @ +mail CNAME @ +prometheus CNAME @ + +; =#= hosts =#= +aleph CNAME @ +;bet +gimel A 95.217.131.201 + AAAA 2a01:4f9:c010:6bf5::23 + +; =#= nameservers =#= +ns1 A 95.217.131.201 + AAAA 2a01:4f9:c010:6bf5::23 diff --git a/services/default.nix b/services/default.nix new file mode 100644 index 0000000..8753642 --- /dev/null +++ b/services/default.nix @@ -0,0 +1,15 @@ +{ + bind = ./bind; + #blog = ./blog; + docker = ./docker; + gitea = ./gitea; + gnupg = ./gnupg; + kubernetesMaster = ./kubernetesMaster; + monitoring = ./monitoring; + nginx = ./nginx; + openssh = ./openssh; + printing = ./printing; + restic = ./restic; + simple-nix-mail = ./simple-nix-mail; + static = ./static; +} diff --git a/services/docker/default.nix b/services/docker/default.nix new file mode 100644 index 0000000..2972e5b --- /dev/null +++ b/services/docker/default.nix @@ -0,0 +1,25 @@ +Service "Docker" +{ + configuration + = { core, registries, ... }: + { + virtualisation.docker + = { + autoPrune + = { + dates = "weekly"; + enable = false; + flags = []; + }; + daemon.settings = {}; + enable = true; + enableNvidia = false; + enableOnBoot = false; + extraOptions = ""; + listenOptions = []; + liveRestore = true; + logDriver = "journald"; + }; + }; + legacy = true; +} diff --git a/services/flake.nix b/services/flake.nix new file mode 100644 index 0000000..c442da6 --- /dev/null +++ b/services/flake.nix @@ -0,0 +1,60 @@ +{ + description = "Sivizius’ services."; + inputs + = { + libconfig.url = "github:sivizius/nixfiles/development?dir=libs/config"; + libweb.url = "github:sivizius/nixfiles/development?dir=libs/web"; + }; + outputs + = { self, libconfig, libweb, ... }: + { + services + = let + commonHeaders + = '' + add_header Cache-Control $cacheable_types; + add_header Feature-Policy "accelerometer none; camera none; geolocation none; gyroscope none; magnetometer none; microphone none; payment none; usb none;"; + add_header Referrer-Policy "no-referrer-when-downgrade" always; + add_header Strict-Transport-Security $hsts_header always; + add_header X-Content-Type-Options "nosniff"; + add_header X-Frame-Options "SAMEORIGIN"; + add_header X-Xss-Protection "1; mode=block"; + ''; + + commonHttpConfig + = '' + charset utf-8; + map $scheme $hsts_header + { + https "max-age=31536000; includeSubdomains; preload"; + } + map $sent_http_content_type $cacheable_types + { + "text/html" "public; max-age=3600; must-revalidate"; # 1.0 h + "text/plain" "public; max-age=3600; must-revalidate"; # 1.0 h + "text/css" "public; max-age=15778800; immutable"; # 0.5 a + "application/javascript" "public; max-age=15778800; immutable"; # 0.5 a + "font/woff2" "public; max-age=15778800; immutable"; # 0.5 a + "application/xml" "public; max-age=3600; must-revalidate"; # 1.0 h + "image/jpeg" "public; max-age=15778800; immutable"; # 0.5 a + "image/png" "public; max-age=15778800; immutable"; # 0.5 a + "image/webp" "public; max-age=15778800; immutable"; # 0.5 a + default "public; max-age=1209600"; # 2.0 w + } + ''; + + extraConfig + = '' + ${commonHeaders} + add_header Content-Security-Policy "default-src 'self'; frame-ancestors 'none'; object-src 'none'" always; + ''; + in + (libconfig.lib { inherit self; }).services.load ./. + { + inherit commonHeaders commonHttpConfig extraConfig; + enableACME = true; + forceSSL = true; + web = libweb.lib { inherit self; }; + }; + }; +} diff --git a/services/gitea/default.nix b/services/gitea/default.nix new file mode 100644 index 0000000..1b82b1f --- /dev/null +++ b/services/gitea/default.nix @@ -0,0 +1,126 @@ + +{ commonHeaders, enableACME, forceSSL, ... }: + Service "Gitea: Hosting git-repositories" + { + configuration + = let + attachment + = { + ALLOWED_TYPES = "*/*"; + }; + log + = { + LEVEL = "Warn"; + }; + metrics + = { + ENABLED = true; + # TOKEN = "INTERNAL_TOKEN_URI"; + }; + picture + = { + DISABLE_GRAVATAR = true; + }; + repository + = { + PREFERRED_LICENSES = "AGPL-3.0,GPL-3.0,GPL-2.0,LGPL-3.0,LGPL-2.1"; + }; + server + = { + START_SSH_SERVER = true; + BUILTIN_SSH_SERVER_USER = "gitea"; + SSH_PORT = 2222; + SSH_LISTEN_PORT = 2222; + }; + service + = { + DISABLE_REGISTRATION = false; + }; + sessions + = { + COOKIE_SECURE = true; + }; + ui + = { + DEFAULT_THEME = "arc-green"; + THEMES = "gitea,arc-green"; + THEME_COLOR_META_TAG = "#222222"; + }; + settings + = { + inherit attachment repository log metrics picture server service sessions ui; + }; + in + { core, network, secret, ... }: + let + inherit(core) string; + domain = "git.${network.domain}"; + port = string network.tcp.ports.gitea.http; + in + { + gitea + = { + inherit domain settings; + appName = "_sivizius’ Gitea"; + database + = { + type = "postgres"; + name = "gitea"; + passwordFile = secret.generateToken "gitea-dbpass" { owner = "gitea"; }; + user = "gitea"; + }; + enable = true; + httpAddress = "localhost"; + rootUrl = "https://${domain}/"; + #stateDir? + #mailerPasswordFile? + }; + + nginx.virtualHosts.${domain} + = { + inherit enableACME forceSSL; + extraConfig = commonHeaders; + locations + = { + "/" + = { + proxyPass = "http://localhost:${port}/"; + }; + "/metrics" + = { + proxyPass = "http://localhost:${port}/metrics"; + }; + }; + }; + + postgresql + = { + enable = true; + authentication + = '' + local gitea all ident map=gitea-users + ''; + identMap + = '' + gitea-users gitea gitea + ''; + }; + + prometheus.scrapeConfigs + = [ + { + bearer_token_file = secret.generateToken' "prometheus/scrapeConfigs"; + job_name = "gitea"; + metrics_path = "/metrics"; + scheme = "https"; + scrape_interval = "30s"; + static_configs + = [ + { + targets = [ domain ]; + } + ]; + } + ]; + }; + } diff --git a/services/gnupg/default.nix b/services/gnupg/default.nix new file mode 100644 index 0000000..2bfa538 --- /dev/null +++ b/services/gnupg/default.nix @@ -0,0 +1,21 @@ +Service "GNU Privacy Guard" +{ + configuration + = { registries, ... }: + { + programs.gnupg + = { + agent + = { + enable = true; + enableBrowserSocket = false; + enableExtraSocket = false; + enableSSHSupport = true; + pinentryFlavor = "qt"; + }; + dirmngr.enable = false; + package = registries.nix.gnupg; + }; + }; + legacy = true; +} diff --git a/services/kubernetesMaster/default.nix b/services/kubernetesMaster/default.nix new file mode 100644 index 0000000..0b59997 --- /dev/null +++ b/services/kubernetesMaster/default.nix @@ -0,0 +1,27 @@ +Service "Kubernetes Master" +{ + configuration + = { core, registries, ... }: + { + kubernetes + = let + inherit(core) string; + masterIP = "10.1.1.2"; + masterAddress = "api.kube"; + masterPort = 6443; + in + { + inherit masterAddress; + addons.dns.enable = true; + apiserverAddress = "https://${masterAddress}:${string masterPort}"; + apiserver + = { + securePort = masterPort; + advertiseAddress = masterIP; + }; + easyCerts = true; + kubelet.extraOpts = "--fail-swap-on=false"; + roles = [ "master" "node" ]; + }; + }; +} diff --git a/services/monitoring/admin.asc b/services/monitoring/admin.asc new file mode 100644 index 0000000..531544b --- /dev/null +++ b/services/monitoring/admin.asc @@ -0,0 +1,9 @@ +-----BEGIN PGP MESSAGE----- + +hF4DQpmXgCyyA4oSAQdAB/KsoadzTDHPuGOa19kTRJXpfrSSBQJIKTL/nE5CDQow +uGnTmld10/91HX2cd8wo94+gU1vY2l3qcSq8X4XaDmiN7o2Ye65gV1XeoOQoznS5 +0nIB/7jq2pnKMNxsl3wjXXu593zKzk9md6clpAIeAt20mIL6QMZt30Yeor3UuCdy +7FJjQ+18uxpjXlBpuhR3OK8tfR4Ghc5bFhmZCKUQbgohibeEHBHtAa2vbvVYAjDN +LyjdTNN8DGQQ2LNSZXxfBF3IOig= +=iMdc +-----END PGP MESSAGE----- diff --git a/services/monitoring/dashboards/bind.json b/services/monitoring/dashboards/bind.json new file mode 100644 index 0000000..0be48a0 --- /dev/null +++ b/services/monitoring/dashboards/bind.json @@ -0,0 +1,1632 @@ +{ + "__inputs": [ + { + "name": "DS_PROMETHEUS", + "label": "Prometheus", + "description": "", + "type": "datasource", + "pluginId": "prometheus", + "pluginName": "Prometheus" + } + ], + "__requires": [ + { + "type": "grafana", + "id": "grafana", + "name": "Grafana", + "version": "4.1.2" + }, + { + "type": "panel", + "id": "graph", + "name": "Graph", + "version": "" + }, + { + "type": "datasource", + "id": "prometheus", + "name": "Prometheus", + "version": "1.0.0" + }, + { + "type": "panel", + "id": "singlestat", + "name": "Singlestat", + "version": "" + } + ], + "annotations": { + "list": [] + }, + "description": "Bind DNS Service Statistics.\r\n", + "editable": true, + "gnetId": 1666, + "graphTooltip": 0, + "hideControls": false, + "id": null, + "links": [], + "rows": [ + { + "collapse": false, + "height": "150px", + "panels": [ + { + "cacheTimeout": null, + "colorBackground": false, + "colorValue": false, + "colors": [ + "rgba(245, 54, 54, 0.9)", + "rgba(237, 129, 40, 0.89)", + "rgba(50, 172, 45, 0.97)" + ], + "datasource": "${DS_PROMETHEUS}", + "decimals": 1, + "format": "s", + "gauge": { + "maxValue": 100, + "minValue": 0, + "show": false, + "thresholdLabels": false, + "thresholdMarkers": true + }, + "height": "150", + "id": 1, + "interval": null, + "links": [], + "mappingType": 1, + "mappingTypes": [ + { + "name": "value to text", + "value": 1 + }, + { + "name": "range to text", + "value": 2 + } + ], + "maxDataPoints": 100, + "nullPointMode": "connected", + "nullText": null, + "postfix": "s ago", + "postfixFontSize": "80%", + "prefix": "", + "prefixFontSize": "50%", + "rangeMaps": [ + { + "from": "null", + "text": "N/A", + "to": "null" + } + ], + "span": 3, + "sparkline": { + "fillColor": "rgba(31, 118, 189, 0.18)", + "full": false, + "lineColor": "rgb(31, 120, 193)", + "show": false + }, + "targets": [ + { + "expr": "max(node_time{alias=\"openwatt-dns-slave\"}) - max(bind_boot_time_seconds{alias=\"openwatt-dns-slave\"})", + "interval": "5m", + "intervalFactor": 2, + "refId": "A", + "step": 600, + "target": "" + } + ], + "thresholds": "", + "title": "Restarted", + "type": "singlestat", + "valueFontSize": "80%", + "valueMaps": [ + { + "op": "=", + "text": "N/A", + "value": "null" + } + ], + "valueName": "avg" + }, + { + "cacheTimeout": null, + "colorBackground": false, + "colorValue": false, + "colors": [ + "rgba(245, 54, 54, 0.9)", + "rgba(237, 129, 40, 0.89)", + "rgba(50, 172, 45, 0.97)" + ], + "datasource": "${DS_PROMETHEUS}", + "decimals": 1, + "format": "s", + "gauge": { + "maxValue": 100, + "minValue": 0, + "show": false, + "thresholdLabels": false, + "thresholdMarkers": true + }, + "height": "150px", + "id": 2, + "interval": null, + "links": [], + "mappingType": 1, + "mappingTypes": [ + { + "name": "value to text", + "value": 1 + }, + { + "name": "range to text", + "value": 2 + } + ], + "maxDataPoints": 100, + "nullPointMode": "connected", + "nullText": null, + "postfix": "s ago", + "postfixFontSize": "80%", + "prefix": "", + "prefixFontSize": "50%", + "rangeMaps": [ + { + "from": "null", + "text": "N/A", + "to": "null" + } + ], + "span": 3, + "sparkline": { + "fillColor": "rgba(31, 118, 189, 0.18)", + "full": false, + "lineColor": "rgb(31, 120, 193)", + "show": false + }, + "targets": [ + { + "expr": "max(node_time{alias=\"openwatt-dns-slave\"}) - max(bind_config_time_seconds{alias=\"openwatt-dns-slave\"})", + "interval": "5m", + "intervalFactor": 2, + "refId": "A", + "step": 600, + "target": "" + } + ], + "thresholds": "", + "title": "Reconfigured", + "type": "singlestat", + "valueFontSize": "80%", + "valueMaps": [ + { + "op": "=", + "text": "N/A", + "value": "null" + } + ], + "valueName": "avg" + }, + { + "aliasColors": {}, + "bars": false, + "datasource": "${DS_PROMETHEUS}", + "fill": 3, + "id": 3, + "legend": { + "avg": false, + "current": false, + "max": false, + "min": false, + "show": false, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 3, + "links": [], + "nullPointMode": "null", + "percentage": false, + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [], + "span": 6, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "increase(bind_process_cpu_seconds_total{alias=\"$alias\"}[120s])", + "intervalFactor": 2, + "legendFormat": "", + "refId": "A", + "step": 10, + "target": "" + } + ], + "thresholds": [], + "timeFrom": null, + "timeShift": null, + "title": "Named CPU Time", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "s", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ] + }, + { + "aliasColors": {}, + "bars": false, + "datasource": "${DS_PROMETHEUS}", + "fill": 1, + "id": 16, + "legend": { + "alignAsTable": false, + "avg": false, + "current": false, + "max": false, + "min": false, + "rightSide": false, + "show": true, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 1, + "links": [], + "nullPointMode": "null", + "percentage": true, + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [], + "span": 4, + "stack": true, + "steppedLine": false, + "targets": [ + { + "expr": "sum(rate(node_cpu{alias=\"$alias\"}[120s])) by (mode) * 100 / count_scalar(node_cpu{mode=\"user\", alias=\"$alias\"}) or sum(irate(node_cpu{alias=\"$alias\"}[120s])) by (mode) * 100 / count_scalar(node_cpu{mode=\"user\", alias=\"$alias\"})", + "intervalFactor": 2, + "legendFormat": "{{ mode }}", + "refId": "A", + "step": 10, + "target": "" + } + ], + "thresholds": [], + "timeFrom": null, + "timeShift": null, + "title": "", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "percent", + "label": null, + "logBase": 1, + "max": "100", + "min": "0", + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": false + } + ] + }, + { + "aliasColors": { + "Load 15m": "#CCA300", + "Load 1m": "#890F02", + "Load 5m": "#C15C17" + }, + "bars": false, + "datasource": "${DS_PROMETHEUS}", + "fill": 1, + "id": 17, + "legend": { + "alignAsTable": false, + "avg": false, + "current": false, + "max": false, + "min": false, + "rightSide": false, + "show": true, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 2, + "links": [], + "nullPointMode": "null", + "percentage": true, + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [], + "span": 4, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "node_load1{alias=\"$alias\"}", + "intervalFactor": 2, + "legendFormat": "Load 1m", + "refId": "A", + "step": 10, + "target": "" + }, + { + "expr": "node_load5{alias=\"$alias\"}", + "intervalFactor": 2, + "legendFormat": "Load 5m", + "refId": "B", + "step": 10, + "target": "" + }, + { + "expr": "node_load15{alias=\"$alias\"}", + "intervalFactor": 2, + "legendFormat": "Load 15m", + "refId": "C", + "step": 10, + "target": "" + } + ], + "thresholds": [], + "timeFrom": null, + "timeShift": null, + "title": "", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": "0", + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": false + } + ] + }, + { + "aliasColors": { + "Load 15m": "#CCA300", + "Load 1m": "#890F02", + "Load 5m": "#C15C17" + }, + "bars": false, + "datasource": "${DS_PROMETHEUS}", + "fill": 5, + "id": 18, + "legend": { + "alignAsTable": false, + "avg": false, + "current": false, + "max": false, + "min": false, + "rightSide": false, + "show": true, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 1, + "links": [], + "nullPointMode": "null", + "percentage": false, + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [], + "span": 4, + "stack": true, + "steppedLine": false, + "targets": [ + { + "expr": "node_memory_MemTotal{alias=\"$alias\"} - (node_memory_MemFree{alias=\"$alias\"} + node_memory_Buffers{alias=\"$alias\"} + node_memory_Cached{alias=\"$alias\"})", + "intervalFactor": 2, + "legendFormat": "Used", + "refId": "A", + "step": 10, + "target": "" + }, + { + "expr": "node_memory_MemFree{alias=\"$alias\"}", + "intervalFactor": 2, + "legendFormat": "Free", + "refId": "B", + "step": 10, + "target": "" + }, + { + "expr": "node_memory_Buffers{alias=\"$alias\"}", + "intervalFactor": 2, + "legendFormat": "Buffers", + "refId": "C", + "step": 10, + "target": "" + }, + { + "expr": "node_memory_Cached{alias=\"$alias\"}", + "intervalFactor": 2, + "legendFormat": "Cached", + "refId": "D", + "step": 10, + "target": "" + } + ], + "thresholds": [], + "timeFrom": null, + "timeShift": null, + "title": "", + "tooltip": { + "shared": true, + "sort": 2, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "mode": "time", + "name": null, + "show": true, + "values": [ + "total" + ] + }, + "yaxes": [ + { + "format": "bytes", + "label": null, + "logBase": 1, + "max": null, + "min": "0", + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": false + } + ] + } + ], + "repeat": null, + "repeatIteration": null, + "repeatRowId": null, + "showTitle": false, + "title": "Dashboard Row", + "titleSize": "h6" + }, + { + "collapse": false, + "height": 250, + "panels": [ + { + "aliasColors": {}, + "bars": false, + "datasource": "${DS_PROMETHEUS}", + "fill": 1, + "id": 4, + "legend": { + "avg": false, + "current": false, + "max": false, + "min": false, + "show": true, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 2, + "links": [], + "nullPointMode": "null", + "percentage": false, + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [ + { + "alias": "Max File Descriptors", + "fill": 0 + } + ], + "span": 6, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "bind_process_max_fds{alias=\"$alias\"}", + "intervalFactor": 2, + "legendFormat": "Max", + "refId": "A", + "step": 10, + "target": "" + }, + { + "expr": "bind_process_open_fds{alias=\"$alias\"}", + "intervalFactor": 2, + "legendFormat": "Open", + "refId": "B", + "step": 10, + "target": "" + } + ], + "thresholds": [], + "timeFrom": null, + "timeShift": null, + "title": "File Descriptors", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "short", + "label": null, + "logBase": 32, + "max": null, + "min": null, + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ] + }, + { + "aliasColors": { + "Resident": "#890F02", + "Virtual": "#0A437C", + "Virtual Memory": "#0A437C" + }, + "bars": false, + "datasource": "${DS_PROMETHEUS}", + "fill": 2, + "id": 5, + "legend": { + "avg": false, + "current": false, + "max": false, + "min": false, + "show": true, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 3, + "links": [], + "nullPointMode": "null", + "percentage": false, + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [], + "span": 6, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "bind_process_virtual_memory_bytes{alias=\"$alias\"}", + "intervalFactor": 2, + "legendFormat": "Virtual", + "refId": "A", + "step": 10, + "target": "" + }, + { + "expr": "bind_process_resident_memory_bytes{alias=\"$alias\"}", + "intervalFactor": 2, + "legendFormat": "Resident", + "refId": "B", + "step": 10, + "target": "" + } + ], + "thresholds": [], + "timeFrom": null, + "timeShift": null, + "title": "Memory", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "bytes", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ] + } + ], + "repeat": null, + "repeatIteration": null, + "repeatRowId": null, + "showTitle": false, + "title": "Dashboard Row", + "titleSize": "h6" + }, + { + "collapse": false, + "height": 250, + "panels": [ + { + "aliasColors": {}, + "bars": false, + "datasource": "${DS_PROMETHEUS}", + "fill": 1, + "id": 6, + "legend": { + "alignAsTable": true, + "avg": false, + "current": false, + "max": false, + "min": false, + "rightSide": true, + "show": true, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 1, + "links": [], + "nullPointMode": "null", + "percentage": false, + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [], + "span": 6, + "stack": true, + "steppedLine": false, + "targets": [ + { + "expr": "increase(bind_incoming_queries_total{alias=\"$alias\"}[120s])", + "intervalFactor": 2, + "legendFormat": "{{ type }}", + "refId": "A", + "step": 10, + "target": "" + } + ], + "thresholds": [], + "timeFrom": null, + "timeShift": null, + "title": "Incoming Queries", + "tooltip": { + "shared": true, + "sort": 2, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ] + }, + { + "aliasColors": {}, + "bars": false, + "datasource": "${DS_PROMETHEUS}", + "fill": 1, + "id": 7, + "legend": { + "alignAsTable": true, + "avg": false, + "current": false, + "max": false, + "min": false, + "rightSide": true, + "show": true, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 1, + "links": [], + "nullPointMode": "null", + "percentage": false, + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [], + "span": 6, + "stack": true, + "steppedLine": false, + "targets": [ + { + "expr": "increase(bind_incoming_requests_total{alias=\"$alias\"}[120s])", + "intervalFactor": 2, + "legendFormat": "{{ opcode }}", + "refId": "A", + "step": 10, + "target": "" + } + ], + "thresholds": [], + "timeFrom": null, + "timeShift": null, + "title": "Incoming Request Opcodes", + "tooltip": { + "shared": true, + "sort": 2, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ] + }, + { + "aliasColors": {}, + "bars": false, + "datasource": "${DS_PROMETHEUS}", + "fill": 1, + "id": 8, + "legend": { + "alignAsTable": true, + "avg": false, + "current": false, + "max": false, + "min": false, + "rightSide": true, + "show": true, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 1, + "links": [], + "nullPointMode": "null", + "percentage": false, + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [], + "span": 12, + "stack": true, + "steppedLine": false, + "targets": [ + { + "expr": "increase(bind_responses_total{alias=\"$alias\"}[120s])", + "intervalFactor": 2, + "legendFormat": "{{ result }}", + "refId": "A", + "step": 4, + "target": "" + } + ], + "thresholds": [], + "timeFrom": null, + "timeShift": null, + "title": "Response Results", + "tooltip": { + "shared": true, + "sort": 2, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ] + } + ], + "repeat": null, + "repeatIteration": null, + "repeatRowId": null, + "showTitle": false, + "title": "Dashboard Row", + "titleSize": "h6" + }, + { + "collapse": false, + "height": 250, + "panels": [ + { + "aliasColors": {}, + "bars": false, + "datasource": "${DS_PROMETHEUS}", + "fill": 1, + "id": 9, + "legend": { + "avg": false, + "current": false, + "max": false, + "min": false, + "show": true, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 1, + "links": [], + "nullPointMode": "null", + "percentage": false, + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [], + "span": 12, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "increase(bind_query_duplicates_total{alias=\"$alias\"}[120s])", + "intervalFactor": 2, + "legendFormat": "Duplicates", + "refId": "A", + "step": 4, + "target": "" + }, + { + "expr": "increase(bind_query_errors_total{alias=\"$alias\"}[120s])", + "intervalFactor": 2, + "legendFormat": "{{ error }}", + "refId": "B", + "step": 4, + "target": "" + }, + { + "expr": "increase(bind_query_recursions_total{alias=\"$alias\"}[120s])", + "intervalFactor": 2, + "legendFormat": "Recursions", + "refId": "C", + "step": 4, + "target": "" + } + ], + "thresholds": [], + "timeFrom": null, + "timeShift": null, + "title": "Queries", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ] + } + ], + "repeat": null, + "repeatIteration": null, + "repeatRowId": null, + "showTitle": false, + "title": "Dashboard Row", + "titleSize": "h6" + }, + { + "collapse": false, + "height": 250, + "panels": [ + { + "aliasColors": {}, + "bars": false, + "datasource": "${DS_PROMETHEUS}", + "fill": 1, + "id": 10, + "legend": { + "avg": false, + "current": false, + "max": false, + "min": false, + "show": true, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 1, + "links": [], + "nullPointMode": "null", + "percentage": false, + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [], + "span": 6, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "bind_resolver_cache_rrsets{alias=\"$alias\"}", + "intervalFactor": 2, + "legendFormat": "{{ view }} / {{ type }}", + "refId": "A", + "step": 10, + "target": "" + } + ], + "thresholds": [], + "timeFrom": null, + "timeShift": null, + "title": "Resolver Cache RR Sets", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ] + }, + { + "aliasColors": {}, + "bars": false, + "datasource": "${DS_PROMETHEUS}", + "fill": 1, + "id": 11, + "legend": { + "avg": false, + "current": false, + "max": false, + "min": false, + "show": true, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 1, + "links": [], + "nullPointMode": "null", + "percentage": false, + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [], + "span": 6, + "stack": true, + "steppedLine": false, + "targets": [ + { + "expr": "increase(bind_resolver_dnssec_validation_errors_total{alias=\"$alias\"}[120s])", + "intervalFactor": 2, + "legendFormat": "{{ view }} / ValErr", + "refId": "A", + "step": 10, + "target": "" + }, + { + "expr": "increase(bind_resolver_dnssec_validation_success_total{alias=\"$alias\"}[120s])", + "intervalFactor": 2, + "legendFormat": "{{ view }} / {{ result }}", + "refId": "B", + "step": 10, + "target": "" + } + ], + "thresholds": [], + "timeFrom": null, + "timeShift": null, + "title": "DNSSEC Validation", + "tooltip": { + "shared": true, + "sort": 2, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ] + }, + { + "aliasColors": {}, + "bars": false, + "datasource": "${DS_PROMETHEUS}", + "fill": 1, + "id": 12, + "legend": { + "avg": false, + "current": false, + "max": false, + "min": false, + "show": true, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 1, + "links": [], + "nullPointMode": "null", + "percentage": false, + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [], + "span": 4, + "stack": true, + "steppedLine": false, + "targets": [ + { + "expr": "increase(bind_resolver_queries_total{alias=\"$alias\"}[120s])", + "intervalFactor": 2, + "legendFormat": "{{ view }} / {{ type }}", + "refId": "A", + "step": 10, + "target": "" + } + ], + "thresholds": [], + "timeFrom": null, + "timeShift": null, + "title": "Resolver Queries", + "tooltip": { + "shared": true, + "sort": 2, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ] + }, + { + "aliasColors": {}, + "bars": false, + "datasource": "${DS_PROMETHEUS}", + "fill": 1, + "id": 13, + "legend": { + "avg": false, + "current": false, + "max": false, + "min": false, + "show": true, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 1, + "links": [], + "nullPointMode": "null", + "percentage": false, + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [], + "span": 4, + "stack": true, + "steppedLine": false, + "targets": [ + { + "expr": "increase(bind_resolver_query_errors_total{alias=\"$alias\"}[120s])", + "intervalFactor": 2, + "legendFormat": "{{ view }} / {{ error }}", + "refId": "A", + "step": 10, + "target": "" + }, + { + "expr": "increase(bind_resolver_query_edns0_errors_total{alias=\"$alias\"}[120s])", + "intervalFactor": 2, + "legendFormat": "{{ view }} / EDNS0", + "refId": "B", + "step": 10, + "target": "" + }, + { + "expr": "increase(bind_resolver_query_retries_total{alias=\"$alias\"}[120s])", + "intervalFactor": 2, + "legendFormat": "{{ view }} / Retry", + "refId": "C", + "step": 10, + "target": "" + } + ], + "thresholds": [], + "timeFrom": null, + "timeShift": null, + "title": "Query Errors", + "tooltip": { + "shared": true, + "sort": 2, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ] + }, + { + "aliasColors": {}, + "bars": false, + "datasource": "${DS_PROMETHEUS}", + "fill": 1, + "id": 14, + "legend": { + "avg": false, + "current": false, + "max": false, + "min": false, + "show": true, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 1, + "links": [], + "nullPointMode": "null", + "percentage": false, + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [], + "span": 4, + "stack": true, + "steppedLine": false, + "targets": [ + { + "expr": "increase(bind_resolver_query_duration_seconds_bucket{alias=\"$alias\"}[120s])", + "intervalFactor": 2, + "legendFormat": "{{ view }} / {{ le }}", + "refId": "A", + "step": 10, + "target": "" + } + ], + "thresholds": [], + "timeFrom": null, + "timeShift": null, + "title": "Query By Duration", + "tooltip": { + "shared": true, + "sort": 2, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ] + }, + { + "aliasColors": {}, + "bars": false, + "datasource": "${DS_PROMETHEUS}", + "fill": 1, + "id": 15, + "legend": { + "avg": false, + "current": false, + "max": false, + "min": false, + "show": true, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 1, + "links": [], + "nullPointMode": "null", + "percentage": false, + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [], + "span": 12, + "stack": true, + "steppedLine": false, + "targets": [ + { + "expr": "increase(bind_resolver_response_errors_total{alias=\"$alias\"}[120s])", + "intervalFactor": 2, + "legendFormat": "{{ view }} / {{ error }}", + "refId": "A", + "step": 4, + "target": "" + }, + { + "expr": "increase(bind_resolver_response_lame_total{alias=\"$alias\"}[120s])", + "intervalFactor": 2, + "legendFormat": "{{ view }} / LAME", + "refId": "B", + "step": 4, + "target": "" + }, + { + "expr": "increase(bind_resolver_response_mismatch_total{alias=\"$alias\"}[120s])", + "intervalFactor": 2, + "legendFormat": "{{ view }} / MISMATCH", + "refId": "C", + "step": 4, + "target": "" + }, + { + "expr": "increase(bind_resolver_response_truncated_total{alias=\"$alias\"}[120s])", + "intervalFactor": 2, + "legendFormat": "{{ view }} / TRUNCATED", + "refId": "D", + "step": 4, + "target": "" + } + ], + "thresholds": [], + "timeFrom": null, + "timeShift": null, + "title": "Resolver Response Errors", + "tooltip": { + "shared": true, + "sort": 2, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ] + } + ], + "repeat": null, + "repeatIteration": null, + "repeatRowId": null, + "showTitle": true, + "title": "Resolver", + "titleSize": "h6" + } + ], + "schemaVersion": 14, + "style": "dark", + "tags": [ + "dns", + "bind", + "prometheus" + ], + "templating": { + "list": [ + { + "allValue": null, + "current": {}, + "datasource": "${DS_PROMETHEUS}", + "hide": 0, + "includeAll": false, + "label": "Host", + "multi": false, + "name": "alias", + "options": [], + "query": "label_values(bind_up, alias)", + "refresh": 1, + "regex": "", + "sort": 1, + "tagValuesQuery": "", + "tags": [], + "tagsQuery": "", + "type": "query", + "useTags": false + } + ] + }, + "time": { + "from": "now-1h", + "to": "now" + }, + "timepicker": { + "refresh_intervals": [ + "5s", + "10s", + "30s", + "1m", + "5m", + "15m", + "30m", + "1h", + "2h", + "1d" + ], + "time_options": [ + "5m", + "15m", + "1h", + "6h", + "12h", + "24h", + "2d", + "7d", + "30d" + ] + }, + "timezone": "browser", + "title": "Bind DNS", + "version": 29 +} \ No newline at end of file diff --git a/services/monitoring/dashboards/gitea.json b/services/monitoring/dashboards/gitea.json new file mode 100644 index 0000000..8ab9728 --- /dev/null +++ b/services/monitoring/dashboards/gitea.json @@ -0,0 +1,380 @@ +{ + "annotations": { + "list": [ + { + "builtIn": 1, + "datasource": "-- Grafana --", + "enable": true, + "hide": true, + "iconColor": "rgba(0, 211, 255, 1)", + "name": "Annotations & Alerts", + "type": "dashboard" + } + ] + }, + "description": "gitea dashboard for prometheus exporter", + "editable": true, + "gnetId": null, + "graphTooltip": 0, + "id": 12, + "links": [], + "panels": [ + { + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": null, + "description": "Milestones, Follows, Stars, Releases", + "fill": 1, + "fillGradient": 0, + "gridPos": { + "h": 7, + "w": 24, + "x": 0, + "y": 0 + }, + "hiddenSeries": false, + "id": 6, + "legend": { + "avg": false, + "current": false, + "max": false, + "min": false, + "show": true, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 1, + "nullPointMode": "null", + "options": { + "dataLinks": [] + }, + "percentage": false, + "pointradius": 2, + "points": false, + "renderer": "flot", + "seriesOverrides": [], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "gitea_milestones", + "interval": "", + "legendFormat": "Milestones", + "refId": "A" + }, + { + "expr": "gitea_follows", + "interval": "", + "legendFormat": "Follows", + "refId": "B" + }, + { + "expr": "gitea_stars", + "interval": "", + "legendFormat": "Stars", + "refId": "C" + }, + { + "expr": "gitea_releases", + "interval": "", + "legendFormat": "Releases", + "refId": "D" + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "Achievements", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "transparent": true, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "decimals": 0, + "format": "short", + "label": "", + "logBase": 1, + "max": null, + "min": "0", + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": false + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "Prometheus", + "description": "Comments, Issues, Stars, Mirrors", + "fill": 1, + "fillGradient": 0, + "gridPos": { + "h": 8, + "w": 24, + "x": 0, + "y": 7 + }, + "hiddenSeries": false, + "id": 4, + "legend": { + "alignAsTable": false, + "avg": false, + "current": false, + "max": false, + "min": false, + "show": true, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 1, + "nullPointMode": "null", + "options": { + "dataLinks": [] + }, + "percentage": false, + "pointradius": 2, + "points": false, + "renderer": "flot", + "seriesOverrides": [], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "gitea_repositories", + "interval": "", + "legendFormat": "Repositories", + "refId": "B" + }, + { + "expr": "gitea_comments", + "interval": "", + "legendFormat": "Comments", + "refId": "C" + }, + { + "expr": "gitea_issues", + "interval": "", + "legendFormat": "Issues", + "refId": "A" + }, + { + "expr": "gitea_mirrors", + "interval": "", + "legendFormat": "Mirrors", + "refId": "E" + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "Contributions", + "tooltip": { + "shared": true, + "sort": 2, + "value_type": "individual" + }, + "transparent": true, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "decimals": 0, + "format": "short", + "label": "", + "logBase": 1, + "max": null, + "min": "0", + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": false + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": null, + "description": "Users, Organisations, Teams", + "fill": 1, + "fillGradient": 0, + "gridPos": { + "h": 8, + "w": 24, + "x": 0, + "y": 15 + }, + "hiddenSeries": false, + "id": 2, + "legend": { + "alignAsTable": false, + "avg": false, + "current": false, + "max": false, + "min": false, + "show": true, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 1, + "nullPointMode": "null", + "options": { + "dataLinks": [] + }, + "percentage": false, + "pointradius": 2, + "points": false, + "renderer": "flot", + "seriesOverrides": [], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "gitea_users", + "interval": "", + "legendFormat": "Users", + "refId": "A" + }, + { + "expr": "gitea_organizations", + "interval": "", + "legendFormat": "Organisations", + "refId": "B" + }, + { + "expr": "gitea_teams", + "interval": "", + "legendFormat": "Teams", + "refId": "D" + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "Participants", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "transparent": true, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "decimals": 0, + "format": "short", + "label": "", + "logBase": 1, + "max": null, + "min": "0", + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": false + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + } + ], + "schemaVersion": 22, + "style": "dark", + "tags": [ + "gitea", + "git" + ], + "templating": { + "list": [] + }, + "time": { + "from": "now-6h", + "to": "now" + }, + "timepicker": { + "refresh_intervals": [ + "5s", + "10s", + "30s", + "1m", + "5m", + "15m", + "30m", + "1h", + "2h", + "1d" + ] + }, + "timezone": "", + "title": "gitea", + "uid": "llGR7-qZz", + "variables": { + "list": [] + }, + "version": 1 +} diff --git a/services/monitoring/dashboards/nginx.json b/services/monitoring/dashboards/nginx.json new file mode 100644 index 0000000..0eff634 --- /dev/null +++ b/services/monitoring/dashboards/nginx.json @@ -0,0 +1,358 @@ +{ + "annotations": { + "list": [ + { + "builtIn": 1, + "datasource": "-- Grafana --", + "enable": true, + "hide": true, + "iconColor": "rgba(0, 211, 255, 1)", + "name": "Annotations & Alerts", + "type": "dashboard" + } + ] + }, + "description": "nginx stats for prometheus", + "editable": true, + "gnetId": null, + "graphTooltip": 0, + "id": 6, + "links": [], + "panels": [ + { + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "Prometheus", + "description": "Current Connections.", + "fill": 1, + "fillGradient": 0, + "gridPos": { + "h": 11, + "w": 24, + "x": 0, + "y": 0 + }, + "hiddenSeries": false, + "id": 2, + "legend": { + "alignAsTable": true, + "avg": true, + "current": true, + "max": true, + "min": true, + "show": true, + "total": true, + "values": true + }, + "lines": true, + "linewidth": 1, + "nullPointMode": "null", + "options": { + "dataLinks": [] + }, + "percentage": false, + "pointradius": 2, + "points": false, + "renderer": "flot", + "seriesOverrides": [], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "nginx_connections_active", + "interval": "", + "legendFormat": "Active", + "refId": "A" + }, + { + "expr": "nginx_connections_waiting", + "interval": "", + "legendFormat": "Waiting", + "refId": "B" + }, + { + "expr": "nginx_connections_writing", + "interval": "", + "legendFormat": "Writing", + "refId": "C" + }, + { + "expr": "nginx_connections_reading", + "interval": "", + "legendFormat": "Reading", + "refId": "D" + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "Connections", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "transparent": true, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "decimals": 0, + "format": "short", + "label": "", + "logBase": 1, + "max": null, + "min": "0", + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": false + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "Prometheus", + "description": "Connections in the Last Minute.", + "fill": 1, + "fillGradient": 0, + "gridPos": { + "h": 7, + "w": 24, + "x": 0, + "y": 11 + }, + "hiddenSeries": false, + "id": 4, + "legend": { + "alignAsTable": true, + "avg": true, + "current": true, + "max": true, + "min": true, + "rightSide": false, + "show": true, + "total": true, + "values": true + }, + "lines": true, + "linewidth": 1, + "nullPointMode": "null", + "options": { + "dataLinks": [] + }, + "percentage": false, + "pointradius": 2, + "points": false, + "renderer": "flot", + "seriesOverrides": [], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "rate(nginx_connections_handled[1m])", + "interval": "", + "legendFormat": "Handled", + "refId": "A" + }, + { + "expr": "rate(nginx_connections_accepted[1m])", + "interval": "", + "legendFormat": "Accepted", + "refId": "B" + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "Connections", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "transparent": true, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": false + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "Prometheus", + "description": "Requests in the Last Minute.", + "fill": 1, + "fillGradient": 0, + "gridPos": { + "h": 5, + "w": 24, + "x": 0, + "y": 18 + }, + "hiddenSeries": false, + "id": 6, + "legend": { + "alignAsTable": true, + "avg": true, + "current": true, + "max": true, + "min": true, + "show": true, + "total": true, + "values": true + }, + "lines": true, + "linewidth": 1, + "nullPointMode": "null", + "options": { + "dataLinks": [] + }, + "percentage": false, + "pointradius": 2, + "points": false, + "renderer": "flot", + "seriesOverrides": [], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "rate(nginx_http_requests_total[1m])", + "interval": "", + "legendFormat": "Requests", + "refId": "A" + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "Requests", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "transparent": true, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": false + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + } + ], + "refresh": false, + "schemaVersion": 22, + "style": "dark", + "tags": [ + "prometheus", + "nginx", + "http" + ], + "templating": { + "list": [] + }, + "time": { + "from": "now-6h", + "to": "now" + }, + "timepicker": { + "refresh_intervals": [ + "5s", + "10s", + "30s", + "1m", + "5m", + "15m", + "30m", + "1h", + "2h", + "1d" + ] + }, + "timezone": "", + "title": "nginx stats", + "uid": "0oaelb3Zz", + "variables": { + "list": [] + }, + "version": 2 +} diff --git a/services/monitoring/dashboards/node-stats.json b/services/monitoring/dashboards/node-stats.json new file mode 100644 index 0000000..96122f8 --- /dev/null +++ b/services/monitoring/dashboards/node-stats.json @@ -0,0 +1,12281 @@ +{ + "annotations": { + "list": [ + { + "builtIn": 1, + "datasource": "-- Grafana --", + "enable": true, + "hide": true, + "iconColor": "rgba(0, 211, 255, 1)", + "name": "Annotations & Alerts", + "type": "dashboard" + } + ] + }, + "editable": true, + "gnetId": 1860, + "graphTooltip": 0, + "id": 2, + "iteration": 1579895319049, + "links": [], + "panels": [ + { + "collapsed": false, + "datasource": "Prometheus", + "gridPos": { + "h": 1, + "w": 24, + "x": 0, + "y": 0 + }, + "id": 261, + "panels": [], + "repeat": null, + "title": "Quick CPU / Mem / Disk", + "type": "row" + }, + { + "cacheTimeout": null, + "datasource": "Prometheus", + "description": "Busy state of all CPU cores together", + "gridPos": { + "h": 4, + "w": 3, + "x": 0, + "y": 1 + }, + "id": 20, + "links": [], + "options": { + "fieldOptions": { + "calcs": [ + "lastNotNull" + ], + "defaults": { + "mappings": [ + { + "id": 0, + "op": "=", + "text": "N/A", + "type": 1, + "value": "null" + } + ], + "max": 100, + "min": 0, + "nullValueMode": "null", + "thresholds": [ + { + "color": "rgba(50, 172, 45, 0.97)", + "value": null + }, + { + "color": "rgba(237, 129, 40, 0.89)", + "value": 85 + }, + { + "color": "rgba(245, 54, 54, 0.9)", + "value": 95 + } + ], + "unit": "percent" + }, + "override": {}, + "values": false + }, + "orientation": "horizontal", + "showThresholdLabels": false, + "showThresholdMarkers": true + }, + "pluginVersion": "6.5.2", + "targets": [ + { + "expr": "(((count(count(node_cpu_seconds_total{instance=~\"$node:$port\",job=~\"$job\"}) by (cpu))) - avg(sum by (mode)(irate(node_cpu_seconds_total{mode='idle',instance=~\"$node:$port\",job=~\"$job\"}[5m])))) * 100) / count(count(node_cpu_seconds_total{instance=~\"$node:$port\",job=~\"$job\"}) by (cpu))", + "hide": false, + "intervalFactor": 1, + "legendFormat": "", + "refId": "A", + "step": 900 + } + ], + "title": "CPU Busy", + "type": "gauge" + }, + { + "cacheTimeout": null, + "datasource": "Prometheus", + "description": "Busy state of all CPU cores together (5 min average)", + "gridPos": { + "h": 4, + "w": 3, + "x": 3, + "y": 1 + }, + "id": 155, + "links": [], + "options": { + "fieldOptions": { + "calcs": [ + "lastNotNull" + ], + "defaults": { + "mappings": [ + { + "id": 0, + "op": "=", + "text": "N/A", + "type": 1, + "value": "null" + } + ], + "max": 100, + "min": 0, + "nullValueMode": "null", + "thresholds": [ + { + "color": "rgba(50, 172, 45, 0.97)", + "value": null + }, + { + "color": "rgba(237, 129, 40, 0.89)", + "value": 85 + }, + { + "color": "rgba(245, 54, 54, 0.9)", + "value": 95 + } + ], + "unit": "percent" + }, + "override": {}, + "values": false + }, + "orientation": "horizontal", + "showThresholdLabels": false, + "showThresholdMarkers": true + }, + "pluginVersion": "6.5.2", + "targets": [ + { + "expr": "avg(node_load5{instance=~\"$node:$port\",job=~\"$job\"}) / count(count(node_cpu_seconds_total{instance=~\"$node:$port\",job=~\"$job\"}) by (cpu)) * 100", + "format": "time_series", + "hide": false, + "intervalFactor": 1, + "refId": "A", + "step": 900 + } + ], + "title": "Sys Load (5m avg)", + "type": "gauge" + }, + { + "cacheTimeout": null, + "datasource": "Prometheus", + "description": "Busy state of all CPU cores together (15 min average)", + "gridPos": { + "h": 4, + "w": 3, + "x": 6, + "y": 1 + }, + "id": 19, + "links": [], + "options": { + "fieldOptions": { + "calcs": [ + "lastNotNull" + ], + "defaults": { + "mappings": [ + { + "id": 0, + "op": "=", + "text": "N/A", + "type": 1, + "value": "null" + } + ], + "max": 100, + "min": 0, + "nullValueMode": "null", + "thresholds": [ + { + "color": "rgba(50, 172, 45, 0.97)", + "value": null + }, + { + "color": "rgba(237, 129, 40, 0.89)", + "value": 85 + }, + { + "color": "rgba(245, 54, 54, 0.9)", + "value": 95 + } + ], + "unit": "percent" + }, + "override": {}, + "values": false + }, + "orientation": "horizontal", + "showThresholdLabels": false, + "showThresholdMarkers": true + }, + "pluginVersion": "6.5.2", + "targets": [ + { + "expr": "avg(node_load15{instance=~\"$node:$port\",job=~\"$job\"}) / count(count(node_cpu_seconds_total{instance=~\"$node:$port\",job=~\"$job\"}) by (cpu)) * 100", + "hide": false, + "intervalFactor": 1, + "refId": "A", + "step": 900 + } + ], + "title": "Sys Load (15m avg)", + "type": "gauge" + }, + { + "cacheTimeout": null, + "datasource": "Prometheus", + "description": "Non available RAM memory", + "gridPos": { + "h": 4, + "w": 3, + "x": 9, + "y": 1 + }, + "hideTimeOverride": false, + "id": 16, + "links": [], + "options": { + "fieldOptions": { + "calcs": [ + "lastNotNull" + ], + "defaults": { + "decimals": 0, + "mappings": [], + "max": 100, + "min": 0, + "nullValueMode": "null", + "thresholds": [ + { + "color": "rgba(50, 172, 45, 0.97)", + "value": null + }, + { + "color": "rgba(237, 129, 40, 0.89)", + "value": 80 + }, + { + "color": "rgba(245, 54, 54, 0.9)", + "value": 90 + } + ], + "unit": "percent" + }, + "override": {}, + "values": false + }, + "orientation": "horizontal", + "showThresholdLabels": false, + "showThresholdMarkers": true + }, + "pluginVersion": "6.5.2", + "targets": [ + { + "expr": "((node_memory_MemTotal_bytes{instance=~\"$node:$port\",job=~\"$job\"} - node_memory_MemFree_bytes{instance=~\"$node:$port\",job=~\"$job\"}) / (node_memory_MemTotal_bytes{instance=~\"$node:$port\",job=~\"$job\"} )) * 100", + "format": "time_series", + "hide": true, + "intervalFactor": 1, + "refId": "A", + "step": 900 + }, + { + "expr": "100 - ((node_memory_MemAvailable_bytes{instance=~\"$node:$port\",job=~\"$job\"} * 100) / node_memory_MemTotal_bytes{instance=~\"$node:$port\",job=~\"$job\"})", + "format": "time_series", + "hide": false, + "intervalFactor": 1, + "refId": "B", + "step": 900 + } + ], + "title": "RAM Used", + "type": "gauge" + }, + { + "cacheTimeout": null, + "datasource": "Prometheus", + "description": "Used Swap", + "gridPos": { + "h": 4, + "w": 3, + "x": 12, + "y": 1 + }, + "id": 21, + "links": [], + "options": { + "fieldOptions": { + "calcs": [ + "lastNotNull" + ], + "defaults": { + "mappings": [ + { + "id": 0, + "op": "=", + "text": "N/A", + "type": 1, + "value": "null" + } + ], + "max": 100, + "min": 0, + "nullValueMode": "null", + "thresholds": [ + { + "color": "rgba(50, 172, 45, 0.97)", + "value": null + }, + { + "color": "rgba(237, 129, 40, 0.89)", + "value": 10 + }, + { + "color": "rgba(245, 54, 54, 0.9)", + "value": 25 + } + ], + "unit": "percent" + }, + "override": {}, + "values": false + }, + "orientation": "horizontal", + "showThresholdLabels": false, + "showThresholdMarkers": true + }, + "pluginVersion": "6.5.2", + "targets": [ + { + "expr": "((node_memory_SwapTotal_bytes{instance=~\"$node:$port\",job=~\"$job\"} - node_memory_SwapFree_bytes{instance=~\"$node:$port\",job=~\"$job\"}) / (node_memory_SwapTotal_bytes{instance=~\"$node:$port\",job=~\"$job\"} )) * 100", + "intervalFactor": 1, + "refId": "A", + "step": 900 + } + ], + "title": "SWAP Used", + "type": "gauge" + }, + { + "cacheTimeout": null, + "datasource": "Prometheus", + "description": "Used Root FS", + "gridPos": { + "h": 4, + "w": 3, + "x": 15, + "y": 1 + }, + "id": 154, + "links": [], + "options": { + "fieldOptions": { + "calcs": [ + "lastNotNull" + ], + "defaults": { + "mappings": [ + { + "id": 0, + "op": "=", + "text": "N/A", + "type": 1, + "value": "null" + } + ], + "max": 100, + "min": 0, + "nullValueMode": "null", + "thresholds": [ + { + "color": "rgba(50, 172, 45, 0.97)", + "value": null + }, + { + "color": "rgba(237, 129, 40, 0.89)", + "value": 80 + }, + { + "color": "rgba(245, 54, 54, 0.9)", + "value": 90 + } + ], + "unit": "percent" + }, + "override": {}, + "values": false + }, + "orientation": "horizontal", + "showThresholdLabels": false, + "showThresholdMarkers": true + }, + "pluginVersion": "6.5.2", + "targets": [ + { + "expr": "100 - ((node_filesystem_avail_bytes{instance=~\"$node:$port\",job=~\"$job\",mountpoint=\"/\",fstype!=\"rootfs\"} * 100) / node_filesystem_size_bytes{instance=~\"$node:$port\",job=~\"$job\",mountpoint=\"/\",fstype!=\"rootfs\"})", + "format": "time_series", + "intervalFactor": 1, + "refId": "A", + "step": 900 + } + ], + "title": "Root FS Used", + "type": "gauge" + }, + { + "cacheTimeout": null, + "colorBackground": false, + "colorValue": false, + "colors": [ + "rgba(245, 54, 54, 0.9)", + "rgba(237, 129, 40, 0.89)", + "rgba(50, 172, 45, 0.97)" + ], + "datasource": "Prometheus", + "description": "Total number of CPU cores", + "format": "short", + "gauge": { + "maxValue": 100, + "minValue": 0, + "show": false, + "thresholdLabels": false, + "thresholdMarkers": true + }, + "gridPos": { + "h": 2, + "w": 2, + "x": 18, + "y": 1 + }, + "id": 14, + "interval": null, + "links": [], + "mappingType": 1, + "mappingTypes": [ + { + "name": "value to text", + "value": 1 + }, + { + "name": "range to text", + "value": 2 + } + ], + "maxDataPoints": 100, + "maxPerRow": 6, + "nullPointMode": "null", + "nullText": null, + "options": {}, + "postfix": "", + "postfixFontSize": "50%", + "prefix": "", + "prefixFontSize": "50%", + "rangeMaps": [ + { + "from": "null", + "text": "N/A", + "to": "null" + } + ], + "sparkline": { + "fillColor": "rgba(31, 118, 189, 0.18)", + "full": false, + "lineColor": "rgb(31, 120, 193)", + "show": false + }, + "tableColumn": "", + "targets": [ + { + "expr": "count(count(node_cpu_seconds_total{instance=~\"$node:$port\",job=~\"$job\"}) by (cpu))", + "intervalFactor": 1, + "refId": "A", + "step": 900 + } + ], + "thresholds": "", + "title": "CPU Cores", + "type": "singlestat", + "valueFontSize": "50%", + "valueMaps": [ + { + "op": "=", + "text": "N/A", + "value": "null" + } + ], + "valueName": "current" + }, + { + "cacheTimeout": null, + "colorBackground": false, + "colorValue": false, + "colors": [ + "rgba(245, 54, 54, 0.9)", + "rgba(237, 129, 40, 0.89)", + "rgba(50, 172, 45, 0.97)" + ], + "datasource": "Prometheus", + "decimals": 0, + "description": "Total RAM", + "format": "bytes", + "gauge": { + "maxValue": 100, + "minValue": 0, + "show": false, + "thresholdLabels": false, + "thresholdMarkers": true + }, + "gridPos": { + "h": 2, + "w": 2, + "x": 20, + "y": 1 + }, + "id": 75, + "interval": null, + "links": [], + "mappingType": 1, + "mappingTypes": [ + { + "name": "value to text", + "value": 1 + }, + { + "name": "range to text", + "value": 2 + } + ], + "maxDataPoints": 100, + "maxPerRow": 6, + "nullPointMode": "null", + "nullText": null, + "options": {}, + "postfix": "", + "postfixFontSize": "70%", + "prefix": "", + "prefixFontSize": "50%", + "rangeMaps": [ + { + "from": "null", + "text": "N/A", + "to": "null" + } + ], + "sparkline": { + "fillColor": "rgba(31, 118, 189, 0.18)", + "full": false, + "lineColor": "rgb(31, 120, 193)", + "show": false + }, + "tableColumn": "", + "targets": [ + { + "expr": "node_memory_MemTotal_bytes{instance=~\"$node:$port\",job=~\"$job\"}", + "intervalFactor": 1, + "refId": "A", + "step": 900 + } + ], + "thresholds": "", + "title": "RAM Total", + "type": "singlestat", + "valueFontSize": "50%", + "valueMaps": [ + { + "op": "=", + "text": "N/A", + "value": "null" + } + ], + "valueName": "current" + }, + { + "cacheTimeout": null, + "colorBackground": false, + "colorValue": false, + "colors": [ + "rgba(245, 54, 54, 0.9)", + "rgba(237, 129, 40, 0.89)", + "rgba(50, 172, 45, 0.97)" + ], + "datasource": "Prometheus", + "decimals": 0, + "description": "Total SWAP", + "format": "bytes", + "gauge": { + "maxValue": 100, + "minValue": 0, + "show": false, + "thresholdLabels": false, + "thresholdMarkers": true + }, + "gridPos": { + "h": 2, + "w": 2, + "x": 22, + "y": 1 + }, + "id": 18, + "interval": null, + "links": [], + "mappingType": 1, + "mappingTypes": [ + { + "name": "value to text", + "value": 1 + }, + { + "name": "range to text", + "value": 2 + } + ], + "maxDataPoints": 100, + "maxPerRow": 6, + "nullPointMode": "null", + "nullText": null, + "options": {}, + "postfix": "", + "postfixFontSize": "70%", + "prefix": "", + "prefixFontSize": "50%", + "rangeMaps": [ + { + "from": "null", + "text": "N/A", + "to": "null" + } + ], + "sparkline": { + "fillColor": "rgba(31, 118, 189, 0.18)", + "full": false, + "lineColor": "rgb(31, 120, 193)", + "show": false + }, + "tableColumn": "", + "targets": [ + { + "expr": "node_memory_SwapTotal_bytes{instance=~\"$node:$port\",job=~\"$job\"}", + "intervalFactor": 1, + "refId": "A", + "step": 900 + } + ], + "thresholds": "", + "title": "SWAP Total", + "type": "singlestat", + "valueFontSize": "50%", + "valueMaps": [ + { + "op": "=", + "text": "N/A", + "value": "null" + } + ], + "valueName": "current" + }, + { + "cacheTimeout": null, + "colorBackground": false, + "colorValue": false, + "colors": [ + "rgba(245, 54, 54, 0.9)", + "rgba(237, 129, 40, 0.89)", + "rgba(50, 172, 45, 0.97)" + ], + "datasource": "Prometheus", + "decimals": 2, + "description": "System Load (1m avg)", + "format": "short", + "gauge": { + "maxValue": 100, + "minValue": 0, + "show": false, + "thresholdLabels": false, + "thresholdMarkers": true + }, + "gridPos": { + "h": 2, + "w": 2, + "x": 18, + "y": 3 + }, + "id": 17, + "interval": null, + "links": [], + "mappingType": 1, + "mappingTypes": [ + { + "name": "value to text", + "value": 1 + }, + { + "name": "range to text", + "value": 2 + } + ], + "maxDataPoints": 100, + "maxPerRow": 12, + "nullPointMode": "null", + "nullText": null, + "options": {}, + "postfix": "", + "postfixFontSize": "50%", + "prefix": "", + "prefixFontSize": "50%", + "rangeMaps": [ + { + "from": "null", + "text": "N/A", + "to": "null" + } + ], + "sparkline": { + "fillColor": "rgba(31, 118, 189, 0.18)", + "full": false, + "lineColor": "rgb(31, 120, 193)", + "show": false + }, + "tableColumn": "", + "targets": [ + { + "expr": "node_load1{instance=~\"$node:$port\",job=~\"$job\"}", + "hide": false, + "intervalFactor": 1, + "refId": "A", + "step": 900 + } + ], + "thresholds": "", + "title": "Sys Load (1m avg)", + "type": "singlestat", + "valueFontSize": "50%", + "valueMaps": [ + { + "op": "=", + "text": "N/A", + "value": "null" + } + ], + "valueName": "current" + }, + { + "cacheTimeout": null, + "colorBackground": false, + "colorValue": false, + "colors": [ + "rgba(50, 172, 45, 0.97)", + "rgba(237, 129, 40, 0.89)", + "rgba(245, 54, 54, 0.9)" + ], + "datasource": "Prometheus", + "decimals": 0, + "description": "Total RootFS", + "format": "bytes", + "gauge": { + "maxValue": 100, + "minValue": 0, + "show": false, + "thresholdLabels": false, + "thresholdMarkers": true + }, + "gridPos": { + "h": 2, + "w": 2, + "x": 20, + "y": 3 + }, + "id": 23, + "interval": null, + "links": [], + "mappingType": 1, + "mappingTypes": [ + { + "name": "value to text", + "value": 1 + }, + { + "name": "range to text", + "value": 2 + } + ], + "maxDataPoints": 100, + "maxPerRow": 6, + "nullPointMode": "null", + "nullText": null, + "options": {}, + "postfix": "", + "postfixFontSize": "50%", + "prefix": "", + "prefixFontSize": "50%", + "rangeMaps": [ + { + "from": "null", + "text": "N/A", + "to": "null" + } + ], + "sparkline": { + "fillColor": "rgba(31, 118, 189, 0.18)", + "full": false, + "lineColor": "rgb(31, 120, 193)", + "show": false + }, + "tableColumn": "", + "targets": [ + { + "expr": "node_filesystem_size_bytes{instance=~\"$node:$port\",job=~\"$job\",mountpoint=\"/\",fstype!=\"rootfs\"}", + "format": "time_series", + "hide": false, + "intervalFactor": 1, + "refId": "A", + "step": 900 + } + ], + "thresholds": "70,90", + "title": "RootFS Total", + "type": "singlestat", + "valueFontSize": "50%", + "valueMaps": [ + { + "op": "=", + "text": "N/A", + "value": "null" + } + ], + "valueName": "current" + }, + { + "cacheTimeout": null, + "colorBackground": false, + "colorValue": false, + "colors": [ + "rgba(245, 54, 54, 0.9)", + "rgba(237, 129, 40, 0.89)", + "rgba(50, 172, 45, 0.97)" + ], + "datasource": "Prometheus", + "decimals": 1, + "description": "System uptime", + "format": "s", + "gauge": { + "maxValue": 100, + "minValue": 0, + "show": false, + "thresholdLabels": false, + "thresholdMarkers": true + }, + "gridPos": { + "h": 2, + "w": 2, + "x": 22, + "y": 3 + }, + "hideTimeOverride": true, + "id": 15, + "interval": null, + "links": [], + "mappingType": 1, + "mappingTypes": [ + { + "name": "value to text", + "value": 1 + }, + { + "name": "range to text", + "value": 2 + } + ], + "maxDataPoints": 100, + "nullPointMode": "null", + "nullText": null, + "options": {}, + "postfix": "s", + "postfixFontSize": "30%", + "prefix": "", + "prefixFontSize": "50%", + "rangeMaps": [ + { + "from": "null", + "text": "N/A", + "to": "null" + } + ], + "sparkline": { + "fillColor": "rgba(31, 118, 189, 0.18)", + "full": false, + "lineColor": "rgb(31, 120, 193)", + "show": false + }, + "tableColumn": "", + "targets": [ + { + "expr": "node_time_seconds{instance=~\"$node:$port\",job=~\"$job\"} - node_boot_time_seconds{instance=~\"$node:$port\",job=~\"$job\"}", + "intervalFactor": 2, + "refId": "A", + "step": 1800 + } + ], + "thresholds": "", + "title": "Uptime", + "type": "singlestat", + "valueFontSize": "30%", + "valueMaps": [ + { + "op": "=", + "text": "N/A", + "value": "null" + } + ], + "valueName": "current" + }, + { + "collapsed": false, + "datasource": "Prometheus", + "gridPos": { + "h": 1, + "w": 24, + "x": 0, + "y": 5 + }, + "id": 263, + "panels": [], + "repeat": null, + "title": "Basic CPU / Mem / Net / Disk", + "type": "row" + }, + { + "aliasColors": { + "Busy": "#EAB839", + "Busy Iowait": "#890F02", + "Busy other": "#1F78C1", + "Idle": "#052B51", + "Idle - Waiting for something to happen": "#052B51", + "guest": "#9AC48A", + "idle": "#052B51", + "iowait": "#EAB839", + "irq": "#BF1B00", + "nice": "#C15C17", + "softirq": "#E24D42", + "steal": "#FCE2DE", + "system": "#508642", + "user": "#5195CE" + }, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "Prometheus", + "decimals": 2, + "description": "Basic CPU info", + "fill": 4, + "fillGradient": 0, + "gridPos": { + "h": 7, + "w": 12, + "x": 0, + "y": 6 + }, + "hiddenSeries": false, + "id": 77, + "legend": { + "alignAsTable": false, + "avg": false, + "current": false, + "max": false, + "min": false, + "rightSide": false, + "show": true, + "sideWidth": 250, + "sort": null, + "sortDesc": null, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 1, + "links": [], + "maxPerRow": 6, + "nullPointMode": "null", + "options": { + "dataLinks": [] + }, + "percentage": true, + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [ + { + "alias": "Busy Iowait", + "color": "#890F02" + }, + { + "alias": "Idle", + "color": "#7EB26D" + }, + { + "alias": "Busy System", + "color": "#EAB839" + }, + { + "alias": "Busy User", + "color": "#0A437C" + }, + { + "alias": "Busy Other", + "color": "#6D1F62" + } + ], + "spaceLength": 10, + "stack": true, + "steppedLine": false, + "targets": [ + { + "expr": "sum by (instance)(irate(node_cpu_seconds_total{mode=\"system\",instance=~\"$node:$port\",job=~\"$job\"}[5m])) * 100", + "format": "time_series", + "hide": false, + "intervalFactor": 2, + "legendFormat": "Busy System", + "refId": "B", + "step": 240 + }, + { + "expr": "sum by (instance)(irate(node_cpu_seconds_total{mode='user',instance=~\"$node:$port\",job=~\"$job\"}[5m])) * 100", + "format": "time_series", + "hide": false, + "intervalFactor": 2, + "legendFormat": "Busy User", + "refId": "D", + "step": 240 + }, + { + "expr": "sum by (instance)(irate(node_cpu_seconds_total{mode='iowait',instance=~\"$node:$port\",job=~\"$job\"}[5m])) * 100", + "format": "time_series", + "intervalFactor": 2, + "legendFormat": "Busy Iowait", + "refId": "E", + "step": 240 + }, + { + "expr": "sum by (instance)(irate(node_cpu_seconds_total{mode=~\".*irq\",instance=~\"$node:$port\",job=~\"$job\"}[5m])) * 100", + "format": "time_series", + "intervalFactor": 2, + "legendFormat": "Busy IRQs", + "refId": "F", + "step": 240 + }, + { + "expr": "sum (irate(node_cpu_seconds_total{mode!='idle',mode!='user',mode!='system',mode!='iowait',mode!='irq',mode!='softirq',instance=~\"$node:$port\",job=~\"$job\"}[5m])) * 100", + "format": "time_series", + "intervalFactor": 2, + "legendFormat": "Busy Other", + "refId": "A", + "step": 240 + }, + { + "expr": "sum by (mode)(irate(node_cpu_seconds_total{mode='idle',instance=~\"$node:$port\",job=~\"$job\"}[5m])) * 100", + "format": "time_series", + "intervalFactor": 2, + "legendFormat": "Idle", + "refId": "C", + "step": 240 + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "CPU Basic", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "short", + "label": "", + "logBase": 1, + "max": "100", + "min": "0", + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": false + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": { + "Apps": "#629E51", + "Buffers": "#614D93", + "Cache": "#6D1F62", + "Cached": "#511749", + "Committed": "#508642", + "Free": "#0A437C", + "Hardware Corrupted - Amount of RAM that the kernel identified as corrupted / not working": "#CFFAFF", + "Inactive": "#584477", + "PageTables": "#0A50A1", + "Page_Tables": "#0A50A1", + "RAM_Free": "#E0F9D7", + "SWAP Used": "#BF1B00", + "Slab": "#806EB7", + "Slab_Cache": "#E0752D", + "Swap": "#BF1B00", + "Swap Used": "#BF1B00", + "Swap_Cache": "#C15C17", + "Swap_Free": "#2F575E", + "Unused": "#EAB839" + }, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "Prometheus", + "decimals": 2, + "description": "Basic memory usage", + "fill": 4, + "fillGradient": 0, + "gridPos": { + "h": 7, + "w": 12, + "x": 12, + "y": 6 + }, + "hiddenSeries": false, + "id": 78, + "legend": { + "alignAsTable": false, + "avg": false, + "current": false, + "max": false, + "min": false, + "rightSide": false, + "show": true, + "sideWidth": 350, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 1, + "links": [], + "maxPerRow": 6, + "nullPointMode": "null", + "options": { + "dataLinks": [] + }, + "percentage": false, + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [ + { + "alias": "RAM Total", + "color": "#E0F9D7", + "fill": 0, + "stack": false + }, + { + "alias": "RAM Cache + Buffer", + "color": "#052B51" + }, + { + "alias": "RAM Free", + "color": "#7EB26D" + }, + { + "alias": "Avaliable", + "color": "#DEDAF7", + "fill": 0, + "stack": false + } + ], + "spaceLength": 10, + "stack": true, + "steppedLine": false, + "targets": [ + { + "expr": "node_memory_MemTotal_bytes{instance=~\"$node:$port\",job=~\"$job\"}", + "format": "time_series", + "hide": false, + "intervalFactor": 2, + "legendFormat": "RAM Total", + "refId": "A", + "step": 240 + }, + { + "expr": "node_memory_MemTotal_bytes{instance=~\"$node:$port\",job=~\"$job\"} - node_memory_MemFree_bytes{instance=~\"$node:$port\",job=~\"$job\"} - (node_memory_Cached_bytes{instance=~\"$node:$port\",job=~\"$job\"} + node_memory_Buffers_bytes{instance=~\"$node:$port\",job=~\"$job\"})", + "format": "time_series", + "hide": false, + "intervalFactor": 2, + "legendFormat": "RAM Used", + "refId": "D", + "step": 240 + }, + { + "expr": "node_memory_Cached_bytes{instance=~\"$node:$port\",job=~\"$job\"} + node_memory_Buffers_bytes{instance=~\"$node:$port\",job=~\"$job\"}", + "format": "time_series", + "intervalFactor": 2, + "legendFormat": "RAM Cache + Buffer", + "refId": "B", + "step": 240 + }, + { + "expr": "node_memory_MemFree_bytes{instance=~\"$node:$port\",job=~\"$job\"}", + "format": "time_series", + "intervalFactor": 2, + "legendFormat": "RAM Free", + "refId": "F", + "step": 240 + }, + { + "expr": "(node_memory_SwapTotal_bytes{instance=~\"$node:$port\",job=~\"$job\"} - node_memory_SwapFree_bytes{instance=~\"$node:$port\",job=~\"$job\"})", + "format": "time_series", + "intervalFactor": 2, + "legendFormat": "SWAP Used", + "refId": "G", + "step": 240 + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "Memory Basic", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "bytes", + "label": "", + "logBase": 1, + "max": null, + "min": "0", + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": false + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": { + "Recv_bytes_eth2": "#7EB26D", + "Recv_bytes_lo": "#0A50A1", + "Recv_drop_eth2": "#6ED0E0", + "Recv_drop_lo": "#E0F9D7", + "Recv_errs_eth2": "#BF1B00", + "Recv_errs_lo": "#CCA300", + "Trans_bytes_eth2": "#7EB26D", + "Trans_bytes_lo": "#0A50A1", + "Trans_drop_eth2": "#6ED0E0", + "Trans_drop_lo": "#E0F9D7", + "Trans_errs_eth2": "#BF1B00", + "Trans_errs_lo": "#CCA300", + "recv_bytes_lo": "#0A50A1", + "recv_drop_eth0": "#99440A", + "recv_drop_lo": "#967302", + "recv_errs_eth0": "#BF1B00", + "recv_errs_lo": "#890F02", + "trans_bytes_eth0": "#7EB26D", + "trans_bytes_lo": "#0A50A1", + "trans_drop_eth0": "#99440A", + "trans_drop_lo": "#967302", + "trans_errs_eth0": "#BF1B00", + "trans_errs_lo": "#890F02" + }, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "Prometheus", + "description": "Basic network info per interface", + "fill": 4, + "fillGradient": 0, + "gridPos": { + "h": 7, + "w": 12, + "x": 0, + "y": 13 + }, + "hiddenSeries": false, + "id": 74, + "legend": { + "alignAsTable": false, + "avg": false, + "current": false, + "hideEmpty": false, + "hideZero": false, + "max": false, + "min": false, + "rightSide": false, + "show": true, + "sort": "current", + "sortDesc": true, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 1, + "links": [], + "nullPointMode": "null", + "options": { + "dataLinks": [] + }, + "percentage": false, + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [ + { + "alias": "/.*trans.*/", + "transform": "negative-Y" + } + ], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "irate(node_network_receive_bytes_total{instance=~\"$node:$port\",job=~\"$job\"}[5m])*8", + "format": "time_series", + "intervalFactor": 2, + "legendFormat": "recv {{device}}", + "refId": "A", + "step": 240 + }, + { + "expr": "irate(node_network_transmit_bytes_total{instance=~\"$node:$port\",job=~\"$job\"}[5m])*8", + "format": "time_series", + "intervalFactor": 2, + "legendFormat": "trans {{device}} ", + "refId": "B", + "step": 240 + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "Network Traffic Basic", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "bps", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + }, + { + "format": "pps", + "label": "", + "logBase": 1, + "max": null, + "min": null, + "show": false + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "Prometheus", + "decimals": 3, + "description": "Disk space used of all filesystems mounted", + "fill": 4, + "fillGradient": 0, + "gridPos": { + "h": 7, + "w": 12, + "x": 12, + "y": 13 + }, + "height": "", + "hiddenSeries": false, + "id": 152, + "legend": { + "alignAsTable": false, + "avg": false, + "current": false, + "max": false, + "min": false, + "rightSide": false, + "show": true, + "sort": "current", + "sortDesc": false, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 1, + "links": [], + "maxPerRow": 6, + "nullPointMode": "null", + "options": { + "dataLinks": [] + }, + "percentage": false, + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "100 - ((node_filesystem_avail_bytes{instance=~\"$node:$port\",job=~\"$job\",device!~'rootfs'} * 100) / node_filesystem_size_bytes{instance=~\"$node:$port\",job=~\"$job\",device!~'rootfs'})", + "format": "time_series", + "intervalFactor": 2, + "legendFormat": "{{mountpoint}}", + "refId": "A", + "step": 240 + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "Disk Space Used Basic", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "percent", + "label": null, + "logBase": 1, + "max": "100", + "min": "0", + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "collapsed": false, + "datasource": "Prometheus", + "gridPos": { + "h": 1, + "w": 24, + "x": 0, + "y": 20 + }, + "id": 265, + "panels": [], + "repeat": null, + "title": "CPU / Memory / Net / Disk", + "type": "row" + }, + { + "aliasColors": { + "Idle - Waiting for something to happen": "#052B51", + "guest": "#9AC48A", + "idle": "#052B51", + "iowait": "#EAB839", + "irq": "#BF1B00", + "nice": "#C15C17", + "softirq": "#E24D42", + "steal": "#FCE2DE", + "system": "#508642", + "user": "#5195CE" + }, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "Prometheus", + "decimals": 2, + "description": "", + "fill": 4, + "fillGradient": 0, + "gridPos": { + "h": 12, + "w": 12, + "x": 0, + "y": 21 + }, + "hiddenSeries": false, + "id": 3, + "legend": { + "alignAsTable": true, + "avg": true, + "current": true, + "max": true, + "min": true, + "rightSide": false, + "show": true, + "sideWidth": 250, + "sort": null, + "sortDesc": null, + "total": false, + "values": true + }, + "lines": true, + "linewidth": 1, + "links": [], + "maxPerRow": 6, + "nullPointMode": "null", + "options": { + "dataLinks": [] + }, + "percentage": true, + "pointradius": 5, + "points": false, + "renderer": "flot", + "repeat": null, + "seriesOverrides": [], + "spaceLength": 10, + "stack": true, + "steppedLine": false, + "targets": [ + { + "expr": "sum by (mode)(irate(node_cpu_seconds_total{mode=\"system\",instance=~\"$node:$port\",job=~\"$job\"}[5m])) * 100", + "format": "time_series", + "interval": "10s", + "intervalFactor": 2, + "legendFormat": "System - Processes executing in kernel mode", + "refId": "A", + "step": 20 + }, + { + "expr": "sum by (mode)(irate(node_cpu_seconds_total{mode='user',instance=~\"$node:$port\",job=~\"$job\"}[5m])) * 100", + "format": "time_series", + "intervalFactor": 2, + "legendFormat": "User - Normal processes executing in user mode", + "refId": "B", + "step": 240 + }, + { + "expr": "sum by (mode)(irate(node_cpu_seconds_total{mode='nice',instance=~\"$node:$port\",job=~\"$job\"}[5m])) * 100", + "format": "time_series", + "intervalFactor": 2, + "legendFormat": "Nice - Niced processes executing in user mode", + "refId": "C", + "step": 240 + }, + { + "expr": "sum by (mode)(irate(node_cpu_seconds_total{mode='idle',instance=~\"$node:$port\",job=~\"$job\"}[5m])) * 100", + "format": "time_series", + "intervalFactor": 2, + "legendFormat": "Idle - Waiting for something to happen", + "refId": "F", + "step": 240 + }, + { + "expr": "sum by (mode)(irate(node_cpu_seconds_total{mode='iowait',instance=~\"$node:$port\",job=~\"$job\"}[5m])) * 100", + "format": "time_series", + "intervalFactor": 2, + "legendFormat": "Iowait - Waiting for I/O to complete", + "refId": "D", + "step": 240 + }, + { + "expr": "sum by (mode)(irate(node_cpu_seconds_total{mode='irq',instance=~\"$node:$port\",job=~\"$job\"}[5m])) * 100", + "format": "time_series", + "intervalFactor": 2, + "legendFormat": "Irq - Servicing interrupts", + "refId": "G", + "step": 240 + }, + { + "expr": "sum by (mode)(irate(node_cpu_seconds_total{mode='softirq',instance=~\"$node:$port\",job=~\"$job\"}[5m])) * 100", + "format": "time_series", + "intervalFactor": 2, + "legendFormat": "Softirq - Servicing softirqs", + "refId": "H", + "step": 240 + }, + { + "expr": "sum by (mode)(irate(node_cpu_seconds_total{mode='steal',instance=~\"$node:$port\",job=~\"$job\"}[5m])) * 100", + "format": "time_series", + "intervalFactor": 2, + "legendFormat": "Steal - Time spent in other operating systems when running in a virtualized environment", + "refId": "E", + "step": 240 + }, + { + "expr": "sum by (mode)(irate(node_cpu_seconds_total{mode='guest',instance=~\"$node:$port\",job=~\"$job\"}[5m])) * 100", + "format": "time_series", + "intervalFactor": 2, + "legendFormat": "Guest - Time spent running a virtual CPU for a guest operating system", + "refId": "I", + "step": 240 + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "CPU", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "short", + "label": "Percentage", + "logBase": 1, + "max": "100", + "min": "0", + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": false + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": { + "Apps": "#629E51", + "Buffers": "#614D93", + "Cache": "#6D1F62", + "Cached": "#511749", + "Committed": "#508642", + "Free": "#0A437C", + "Hardware Corrupted - Amount of RAM that the kernel identified as corrupted / not working": "#CFFAFF", + "Inactive": "#584477", + "PageTables": "#0A50A1", + "Page_Tables": "#0A50A1", + "RAM_Free": "#E0F9D7", + "Slab": "#806EB7", + "Slab_Cache": "#E0752D", + "Swap": "#BF1B00", + "Swap - Swap memory usage": "#BF1B00", + "Swap_Cache": "#C15C17", + "Swap_Free": "#2F575E", + "Unused": "#EAB839", + "Unused - Free memory unassigned": "#052B51" + }, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "Prometheus", + "decimals": 2, + "description": "", + "fill": 4, + "fillGradient": 0, + "gridPos": { + "h": 12, + "w": 12, + "x": 12, + "y": 21 + }, + "hiddenSeries": false, + "id": 24, + "legend": { + "alignAsTable": true, + "avg": true, + "current": true, + "max": true, + "min": true, + "rightSide": false, + "show": true, + "sideWidth": 350, + "sort": null, + "sortDesc": null, + "total": false, + "values": true + }, + "lines": true, + "linewidth": 1, + "links": [], + "maxPerRow": 6, + "nullPointMode": "null", + "options": { + "dataLinks": [] + }, + "percentage": false, + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [ + { + "alias": "/.*Hardware Corrupted - *./", + "stack": false + } + ], + "spaceLength": 10, + "stack": true, + "steppedLine": false, + "targets": [ + { + "expr": "node_memory_MemTotal_bytes{instance=~\"$node:$port\",job=~\"$job\"} - node_memory_MemFree_bytes{instance=~\"$node:$port\",job=~\"$job\"} - node_memory_Buffers_bytes{instance=~\"$node:$port\",job=~\"$job\"} - node_memory_Cached_bytes{instance=~\"$node:$port\",job=~\"$job\"} - node_memory_Slab_bytes{instance=~\"$node:$port\",job=~\"$job\"} - node_memory_PageTables_bytes{instance=~\"$node:$port\",job=~\"$job\"} - node_memory_SwapCached_bytes{instance=~\"$node:$port\",job=~\"$job\"}", + "format": "time_series", + "hide": false, + "intervalFactor": 2, + "legendFormat": "Apps - Memory used by user-space applications", + "refId": "Q", + "step": 240 + }, + { + "expr": "node_memory_PageTables_bytes{instance=~\"$node:$port\",job=~\"$job\"}", + "format": "time_series", + "hide": false, + "intervalFactor": 2, + "legendFormat": "PageTables - Memory used to map between virtual and physical memory addresses", + "refId": "G", + "step": 240 + }, + { + "expr": "node_memory_SwapCached_bytes{instance=~\"$node:$port\",job=~\"$job\"}", + "format": "time_series", + "intervalFactor": 2, + "legendFormat": "SwapCache - Memory that keeps track of pages that have been fetched from swap but not yet been modified", + "refId": "F", + "step": 240 + }, + { + "expr": "node_memory_Slab_bytes{instance=~\"$node:$port\",job=~\"$job\"}", + "format": "time_series", + "hide": false, + "intervalFactor": 2, + "legendFormat": "Slab - Memory used by the kernel to cache data structures for its own use (caches like inode, dentry, etc)", + "refId": "E", + "step": 240 + }, + { + "expr": "node_memory_Cached_bytes{instance=~\"$node:$port\",job=~\"$job\"}", + "format": "time_series", + "hide": false, + "intervalFactor": 2, + "legendFormat": "Cache - Parked file data (file content) cache", + "refId": "C", + "step": 240 + }, + { + "expr": "node_memory_Buffers_bytes{instance=~\"$node:$port\",job=~\"$job\"}", + "format": "time_series", + "hide": false, + "intervalFactor": 2, + "legendFormat": "Buffers - Block device (e.g. harddisk) cache", + "refId": "B", + "step": 240 + }, + { + "expr": "node_memory_MemFree_bytes{instance=~\"$node:$port\",job=~\"$job\"}", + "format": "time_series", + "hide": false, + "intervalFactor": 2, + "legendFormat": "Unused - Free memory unassigned", + "refId": "D", + "step": 240 + }, + { + "expr": "(node_memory_SwapTotal_bytes{instance=~\"$node:$port\",job=~\"$job\"} - node_memory_SwapFree_bytes{instance=~\"$node:$port\",job=~\"$job\"})", + "format": "time_series", + "hide": false, + "intervalFactor": 2, + "legendFormat": "Swap - Swap space used", + "refId": "I", + "step": 240 + }, + { + "expr": "node_memory_HardwareCorrupted_bytes{instance=~\"$node:$port\",job=~\"$job\"}", + "format": "time_series", + "hide": false, + "intervalFactor": 2, + "legendFormat": "Hardware Corrupted - Amount of RAM that the kernel identified as corrupted / not working", + "refId": "O", + "step": 240 + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "Memory Stack", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "bytes", + "label": "Bytes", + "logBase": 1, + "max": null, + "min": "0", + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": false + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": { + "receive_packets_eth0": "#7EB26D", + "receive_packets_lo": "#E24D42", + "transmit_packets_eth0": "#7EB26D", + "transmit_packets_lo": "#E24D42" + }, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "Prometheus", + "fill": 4, + "fillGradient": 0, + "gridPos": { + "h": 12, + "w": 12, + "x": 0, + "y": 33 + }, + "hiddenSeries": false, + "id": 84, + "legend": { + "alignAsTable": true, + "avg": true, + "current": true, + "max": true, + "min": true, + "rightSide": false, + "show": true, + "total": false, + "values": true + }, + "lines": true, + "linewidth": 1, + "links": [], + "nullPointMode": "null", + "options": { + "dataLinks": [] + }, + "percentage": false, + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [ + { + "alias": "/.*Trans.*/", + "transform": "negative-Y" + } + ], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "irate(node_network_receive_bytes_total{instance=~\"$node:$port\",job=~\"$job\"}[5m])*8", + "format": "time_series", + "intervalFactor": 2, + "legendFormat": "{{device}} - Receive", + "refId": "O", + "step": 240 + }, + { + "expr": "irate(node_network_transmit_bytes_total{instance=~\"$node:$port\",job=~\"$job\"}[5m])*8", + "format": "time_series", + "intervalFactor": 2, + "legendFormat": "{{device}} - Transmit", + "refId": "P", + "step": 240 + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "Network Traffic", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "bps", + "label": "Bits out (-) / in (+)", + "logBase": 1, + "max": null, + "min": null, + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": false + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "Prometheus", + "decimals": 3, + "description": "", + "fill": 4, + "fillGradient": 0, + "gridPos": { + "h": 12, + "w": 12, + "x": 12, + "y": 33 + }, + "height": "", + "hiddenSeries": false, + "id": 156, + "legend": { + "alignAsTable": true, + "avg": true, + "current": true, + "max": true, + "min": true, + "rightSide": false, + "show": true, + "sort": "current", + "sortDesc": false, + "total": false, + "values": true + }, + "lines": true, + "linewidth": 1, + "links": [], + "maxPerRow": 6, + "nullPointMode": "null", + "options": { + "dataLinks": [] + }, + "percentage": false, + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "node_filesystem_size_bytes{instance=~\"$node:$port\",job=~\"$job\",device!~'rootfs'} - node_filesystem_avail_bytes{instance=~\"$node:$port\",job=~\"$job\",device!~'rootfs'}", + "format": "time_series", + "intervalFactor": 2, + "legendFormat": "{{mountpoint}}", + "refId": "A", + "step": 240 + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "Disk Space Used", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "bytes", + "label": "Bytes", + "logBase": 1, + "max": null, + "min": "0", + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": false + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "Prometheus", + "description": "", + "fill": 2, + "fillGradient": 0, + "gridPos": { + "h": 12, + "w": 12, + "x": 0, + "y": 45 + }, + "hiddenSeries": false, + "id": 229, + "legend": { + "alignAsTable": true, + "avg": true, + "current": true, + "hideZero": true, + "max": true, + "min": true, + "rightSide": false, + "show": true, + "total": false, + "values": true + }, + "lines": true, + "linewidth": 1, + "links": [], + "maxPerRow": 6, + "nullPointMode": "null", + "options": { + "dataLinks": [] + }, + "percentage": false, + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [ + { + "alias": "/.*Read.*/", + "transform": "negative-Y" + }, + { + "alias": "/.*sda_.*/", + "color": "#7EB26D" + }, + { + "alias": "/.*sdb_.*/", + "color": "#EAB839" + }, + { + "alias": "/.*sdc_.*/", + "color": "#6ED0E0" + }, + { + "alias": "/.*sdd_.*/", + "color": "#EF843C" + }, + { + "alias": "/.*sde_.*/", + "color": "#E24D42" + }, + { + "alias": "/.*sda1.*/", + "color": "#584477" + }, + { + "alias": "/.*sda2_.*/", + "color": "#BA43A9" + }, + { + "alias": "/.*sda3_.*/", + "color": "#F4D598" + }, + { + "alias": "/.*sdb1.*/", + "color": "#0A50A1" + }, + { + "alias": "/.*sdb2.*/", + "color": "#BF1B00" + }, + { + "alias": "/.*sdb2.*/", + "color": "#BF1B00" + }, + { + "alias": "/.*sdb3.*/", + "color": "#E0752D" + }, + { + "alias": "/.*sdc1.*/", + "color": "#962D82" + }, + { + "alias": "/.*sdc2.*/", + "color": "#614D93" + }, + { + "alias": "/.*sdc3.*/", + "color": "#9AC48A" + }, + { + "alias": "/.*sdd1.*/", + "color": "#65C5DB" + }, + { + "alias": "/.*sdd2.*/", + "color": "#F9934E" + }, + { + "alias": "/.*sdd3.*/", + "color": "#EA6460" + }, + { + "alias": "/.*sde1.*/", + "color": "#E0F9D7" + }, + { + "alias": "/.*sdd2.*/", + "color": "#FCEACA" + }, + { + "alias": "/.*sde3.*/", + "color": "#F9E2D2" + } + ], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "irate(node_disk_reads_completed_total{instance=~\"$node:$port\",job=~\"$job\",device=~\"[a-z]*[a-z]\"}[5m])", + "intervalFactor": 4, + "legendFormat": "{{device}} - Reads completed", + "refId": "A", + "step": 480 + }, + { + "expr": "irate(node_disk_writes_completed_total{instance=~\"$node:$port\",job=~\"$job\",device=~\"[a-z]*[a-z]\"}[5m])", + "intervalFactor": 2, + "legendFormat": "{{device}} - Writes completed", + "refId": "B", + "step": 240 + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "Disk IOps", + "tooltip": { + "shared": false, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "iops", + "label": "IO read (-) / write (+)", + "logBase": 1, + "max": null, + "min": null, + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": false + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": { + "io time": "#890F02" + }, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "Prometheus", + "decimals": 3, + "description": "", + "fill": 4, + "fillGradient": 0, + "gridPos": { + "h": 12, + "w": 12, + "x": 12, + "y": 45 + }, + "hiddenSeries": false, + "id": 42, + "legend": { + "alignAsTable": true, + "avg": true, + "current": true, + "max": true, + "min": true, + "rightSide": false, + "show": true, + "sort": null, + "sortDesc": null, + "total": false, + "values": true + }, + "lines": true, + "linewidth": 1, + "links": [], + "maxPerRow": 6, + "nullPointMode": "null", + "options": { + "dataLinks": [] + }, + "percentage": false, + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [ + { + "alias": "/.*read*./", + "transform": "negative-Y" + }, + { + "alias": "/.*sda.*/", + "color": "#7EB26D" + }, + { + "alias": "/.*sdb.*/", + "color": "#EAB839" + }, + { + "alias": "/.*sdc.*/", + "color": "#6ED0E0" + }, + { + "alias": "/.*sdd.*/", + "color": "#EF843C" + }, + { + "alias": "/.*sde.*/", + "color": "#E24D42" + } + ], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "irate(node_disk_read_bytes_total{instance=~\"$node:$port\",job=~\"$job\",device=~\"[a-z]*[a-z]\"}[5m])", + "format": "time_series", + "hide": false, + "intervalFactor": 2, + "legendFormat": "{{device}} - Successfully read bytes", + "refId": "A", + "step": 240 + }, + { + "expr": "irate(node_disk_written_bytes_total{instance=~\"$node:$port\",job=~\"$job\",device=~\"[a-z]*[a-z]\"}[5m])", + "format": "time_series", + "hide": false, + "intervalFactor": 2, + "legendFormat": "{{device}} - Successfully written bytes", + "refId": "B", + "step": 240 + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "I/O Usage Read / Write", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": false, + "values": [] + }, + "yaxes": [ + { + "format": "bytes", + "label": "Bytes read (-) / write (+)", + "logBase": 1, + "max": null, + "min": null, + "show": true + }, + { + "format": "ms", + "label": "", + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": { + "io time": "#890F02" + }, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "Prometheus", + "decimals": 3, + "description": "", + "fill": 4, + "fillGradient": 0, + "gridPos": { + "h": 12, + "w": 12, + "x": 0, + "y": 57 + }, + "hiddenSeries": false, + "id": 127, + "legend": { + "alignAsTable": true, + "avg": true, + "current": true, + "max": true, + "min": true, + "rightSide": false, + "show": true, + "sort": null, + "sortDesc": null, + "total": false, + "values": true + }, + "lines": true, + "linewidth": 1, + "links": [], + "maxPerRow": 6, + "nullPointMode": "null", + "options": { + "dataLinks": [] + }, + "percentage": false, + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "irate(node_disk_io_time_seconds_total{instance=~\"$node:$port\",job=~\"$job\",device=~\"[a-z]*[a-z]\"} [5m])", + "format": "time_series", + "hide": false, + "intervalFactor": 2, + "legendFormat": "{{device}} - Time spent doing I/Os", + "refId": "C", + "step": 240 + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "I/O Usage Times", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": false, + "values": [] + }, + "yaxes": [ + { + "format": "s", + "label": "Time", + "logBase": 1, + "max": null, + "min": "0", + "show": true + }, + { + "format": "s", + "label": "", + "logBase": 1, + "max": null, + "min": null, + "show": false + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "collapsed": true, + "datasource": "Prometheus", + "gridPos": { + "h": 1, + "w": 24, + "x": 0, + "y": 69 + }, + "id": 266, + "panels": [ + { + "aliasColors": { + "Apps": "#629E51", + "Buffers": "#614D93", + "Cache": "#6D1F62", + "Cached": "#511749", + "Committed": "#508642", + "Free": "#0A437C", + "Hardware Corrupted - Amount of RAM that the kernel identified as corrupted / not working": "#CFFAFF", + "Inactive": "#584477", + "PageTables": "#0A50A1", + "Page_Tables": "#0A50A1", + "RAM_Free": "#E0F9D7", + "Slab": "#806EB7", + "Slab_Cache": "#E0752D", + "Swap": "#BF1B00", + "Swap_Cache": "#C15C17", + "Swap_Free": "#2F575E", + "Unused": "#EAB839" + }, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "Prometheus", + "decimals": 2, + "fill": 2, + "fillGradient": 0, + "gridPos": { + "h": 10, + "w": 12, + "x": 0, + "y": 8 + }, + "hiddenSeries": false, + "id": 136, + "legend": { + "alignAsTable": true, + "avg": true, + "current": true, + "max": true, + "min": true, + "rightSide": false, + "show": true, + "sideWidth": 350, + "total": false, + "values": true + }, + "lines": true, + "linewidth": 1, + "links": [], + "maxPerRow": 2, + "nullPointMode": "null", + "options": { + "dataLinks": [] + }, + "percentage": false, + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [], + "spaceLength": 10, + "stack": true, + "steppedLine": false, + "targets": [ + { + "expr": "node_memory_Inactive_bytes{instance=~\"$node:$port\",job=~\"$job\"}", + "format": "time_series", + "intervalFactor": 2, + "legendFormat": "Inactive - Memory which has been less recently used. It is more eligible to be reclaimed for other purposes", + "refId": "K", + "step": 4 + }, + { + "expr": "node_memory_Active_bytes{instance=~\"$node:$port\",job=~\"$job\"}", + "format": "time_series", + "intervalFactor": 2, + "legendFormat": "Active - Memory that has been used more recently and usually not reclaimed unless absolutely necessary", + "refId": "J", + "step": 4 + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "Memory Active / Inactive", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "cumulative" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "bytes", + "label": "Bytes", + "logBase": 1, + "max": null, + "min": "0", + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": false + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": { + "Apps": "#629E51", + "Buffers": "#614D93", + "Cache": "#6D1F62", + "Cached": "#511749", + "Committed": "#508642", + "Free": "#0A437C", + "Hardware Corrupted - Amount of RAM that the kernel identified as corrupted / not working": "#CFFAFF", + "Inactive": "#584477", + "PageTables": "#0A50A1", + "Page_Tables": "#0A50A1", + "RAM_Free": "#E0F9D7", + "Slab": "#806EB7", + "Slab_Cache": "#E0752D", + "Swap": "#BF1B00", + "Swap_Cache": "#C15C17", + "Swap_Free": "#2F575E", + "Unused": "#EAB839" + }, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "Prometheus", + "decimals": 2, + "fill": 2, + "fillGradient": 0, + "gridPos": { + "h": 10, + "w": 12, + "x": 12, + "y": 8 + }, + "hiddenSeries": false, + "id": 135, + "legend": { + "alignAsTable": true, + "avg": true, + "current": true, + "max": true, + "min": true, + "rightSide": false, + "show": true, + "sideWidth": 350, + "total": false, + "values": true + }, + "lines": true, + "linewidth": 1, + "links": [], + "maxPerRow": 6, + "nullPointMode": "null", + "options": { + "dataLinks": [] + }, + "percentage": false, + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [ + { + "alias": "/.*Committed_AS - *./" + }, + { + "alias": "/.*CommitLimit - *./", + "color": "#BF1B00", + "fill": 0 + } + ], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "node_memory_Committed_AS_bytes{instance=~\"$node:$port\",job=~\"$job\"}", + "format": "time_series", + "intervalFactor": 2, + "legendFormat": "Committed_AS - Amount of memory presently allocated on the system", + "refId": "A", + "step": 4 + }, + { + "expr": "node_memory_CommitLimit_bytes{instance=~\"$node:$port\",job=~\"$job\"}", + "format": "time_series", + "intervalFactor": 2, + "legendFormat": "CommitLimit - Amount of memory currently available to be allocated on the system", + "refId": "M", + "step": 4 + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "Memory Commited", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "cumulative" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "bytes", + "label": "Bytes", + "logBase": 1, + "max": null, + "min": "0", + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": false + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": { + "Apps": "#629E51", + "Buffers": "#614D93", + "Cache": "#6D1F62", + "Cached": "#511749", + "Committed": "#508642", + "Free": "#0A437C", + "Hardware Corrupted - Amount of RAM that the kernel identified as corrupted / not working": "#CFFAFF", + "Inactive": "#584477", + "PageTables": "#0A50A1", + "Page_Tables": "#0A50A1", + "RAM_Free": "#E0F9D7", + "Slab": "#806EB7", + "Slab_Cache": "#E0752D", + "Swap": "#BF1B00", + "Swap_Cache": "#C15C17", + "Swap_Free": "#2F575E", + "Unused": "#EAB839" + }, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "Prometheus", + "decimals": 2, + "fill": 2, + "fillGradient": 0, + "gridPos": { + "h": 10, + "w": 12, + "x": 0, + "y": 18 + }, + "hiddenSeries": false, + "id": 191, + "legend": { + "alignAsTable": true, + "avg": true, + "current": true, + "max": true, + "min": true, + "rightSide": false, + "show": true, + "sideWidth": 350, + "total": false, + "values": true + }, + "lines": true, + "linewidth": 1, + "links": [], + "maxPerRow": 6, + "nullPointMode": "null", + "options": { + "dataLinks": [] + }, + "percentage": false, + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [], + "spaceLength": 10, + "stack": true, + "steppedLine": false, + "targets": [ + { + "expr": "node_memory_Inactive_file_bytes{instance=~\"$node:$port\",job=~\"$job\"}", + "format": "time_series", + "hide": false, + "intervalFactor": 2, + "legendFormat": "Inactive_file - File-backed memory on inactive LRU list", + "refId": "A", + "step": 4 + }, + { + "expr": "node_memory_Inactive_anon_bytes{instance=~\"$node:$port\",job=~\"$job\"}", + "format": "time_series", + "hide": false, + "intervalFactor": 2, + "legendFormat": "Inactive_anon - Anonymous and swap cache on inactive LRU list, including tmpfs (shmem)", + "refId": "D", + "step": 4 + }, + { + "expr": "node_memory_Active_file_bytes{instance=~\"$node:$port\",job=~\"$job\"}", + "format": "time_series", + "hide": false, + "intervalFactor": 2, + "legendFormat": "Active_file - File-backed memory on active LRU list", + "refId": "B", + "step": 4 + }, + { + "expr": "node_memory_Active_anon_bytes{instance=~\"$node:$port\",job=~\"$job\"}", + "format": "time_series", + "hide": false, + "intervalFactor": 2, + "legendFormat": "Active_anon - Anonymous and swap cache on active least-recently-used (LRU) list, including tmpfs", + "refId": "C", + "step": 4 + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "Memory Active / Inactive Detail", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "cumulative" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "bytes", + "label": "Bytes", + "logBase": 1, + "max": null, + "min": "0", + "show": true + }, + { + "format": "bytes", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": { + "Active": "#99440A", + "Buffers": "#58140C", + "Cache": "#6D1F62", + "Cached": "#511749", + "Committed": "#508642", + "Dirty": "#6ED0E0", + "Free": "#B7DBAB", + "Inactive": "#EA6460", + "Mapped": "#052B51", + "PageTables": "#0A50A1", + "Page_Tables": "#0A50A1", + "Slab_Cache": "#EAB839", + "Swap": "#BF1B00", + "Swap_Cache": "#C15C17", + "Total": "#511749", + "Total RAM": "#052B51", + "Total RAM + Swap": "#052B51", + "Total Swap": "#614D93", + "VmallocUsed": "#EA6460" + }, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "Prometheus", + "decimals": 2, + "fill": 2, + "fillGradient": 0, + "gridPos": { + "h": 10, + "w": 12, + "x": 12, + "y": 18 + }, + "hiddenSeries": false, + "id": 130, + "legend": { + "alignAsTable": true, + "avg": true, + "current": true, + "max": true, + "min": true, + "rightSide": false, + "show": true, + "sideWidth": null, + "total": false, + "values": true + }, + "lines": true, + "linewidth": 1, + "links": [], + "maxPerRow": 2, + "nullPointMode": "null", + "options": { + "dataLinks": [] + }, + "percentage": false, + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "node_memory_Writeback_bytes{instance=~\"$node:$port\",job=~\"$job\"}", + "format": "time_series", + "intervalFactor": 2, + "legendFormat": "Writeback - Memory which is actively being written back to disk", + "refId": "J", + "step": 4 + }, + { + "expr": "node_memory_WritebackTmp_bytes{instance=~\"$node:$port\",job=~\"$job\"}", + "format": "time_series", + "intervalFactor": 2, + "legendFormat": "WritebackTmp - Memory used by FUSE for temporary writeback buffers", + "refId": "K", + "step": 4 + }, + { + "expr": "node_memory_Dirty_bytes{instance=~\"$node:$port\",job=~\"$job\"}", + "format": "time_series", + "intervalFactor": 2, + "legendFormat": "Dirty - Memory which is waiting to get written back to the disk", + "refId": "A", + "step": 4 + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "Memory Writeback and Dirty", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "bytes", + "label": "Bytes", + "logBase": 1, + "max": null, + "min": "0", + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": false + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": { + "Apps": "#629E51", + "Buffers": "#614D93", + "Cache": "#6D1F62", + "Cached": "#511749", + "Committed": "#508642", + "Free": "#0A437C", + "Hardware Corrupted - Amount of RAM that the kernel identified as corrupted / not working": "#CFFAFF", + "Inactive": "#584477", + "PageTables": "#0A50A1", + "Page_Tables": "#0A50A1", + "RAM_Free": "#E0F9D7", + "Slab": "#806EB7", + "Slab_Cache": "#E0752D", + "Swap": "#BF1B00", + "Swap_Cache": "#C15C17", + "Swap_Free": "#2F575E", + "Unused": "#EAB839" + }, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "Prometheus", + "decimals": 2, + "fill": 2, + "fillGradient": 0, + "gridPos": { + "h": 10, + "w": 12, + "x": 0, + "y": 28 + }, + "hiddenSeries": false, + "id": 138, + "legend": { + "alignAsTable": true, + "avg": true, + "current": true, + "max": true, + "min": true, + "rightSide": false, + "show": true, + "sideWidth": 350, + "total": false, + "values": true + }, + "lines": true, + "linewidth": 1, + "links": [], + "maxPerRow": 6, + "nullPointMode": "null", + "options": { + "dataLinks": [] + }, + "percentage": false, + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "node_memory_Mapped_bytes{instance=~\"$node:$port\",job=~\"$job\"}", + "format": "time_series", + "intervalFactor": 2, + "legendFormat": "Mapped - Used memory in mapped pages files which have been mmaped, such as libraries", + "refId": "A", + "step": 4 + }, + { + "expr": "node_memory_Shmem_bytes{instance=~\"$node:$port\",job=~\"$job\"}", + "format": "time_series", + "intervalFactor": 2, + "legendFormat": "Shmem - Used shared memory (shared between several processes, thus including RAM disks)", + "refId": "B", + "step": 4 + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "Memory Shared and Mapped", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "cumulative" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "bytes", + "label": "Bytes", + "logBase": 1, + "max": null, + "min": "0", + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": false + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": { + "Active": "#99440A", + "Buffers": "#58140C", + "Cache": "#6D1F62", + "Cached": "#511749", + "Committed": "#508642", + "Dirty": "#6ED0E0", + "Free": "#B7DBAB", + "Inactive": "#EA6460", + "Mapped": "#052B51", + "PageTables": "#0A50A1", + "Page_Tables": "#0A50A1", + "Slab_Cache": "#EAB839", + "Swap": "#BF1B00", + "Swap_Cache": "#C15C17", + "Total": "#511749", + "Total RAM": "#052B51", + "Total RAM + Swap": "#052B51", + "Total Swap": "#614D93", + "VmallocUsed": "#EA6460" + }, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "Prometheus", + "decimals": 2, + "fill": 2, + "fillGradient": 0, + "gridPos": { + "h": 10, + "w": 12, + "x": 12, + "y": 28 + }, + "hiddenSeries": false, + "id": 131, + "legend": { + "alignAsTable": true, + "avg": true, + "current": true, + "max": true, + "min": true, + "rightSide": false, + "show": true, + "sideWidth": null, + "total": false, + "values": true + }, + "lines": true, + "linewidth": 1, + "links": [], + "maxPerRow": 2, + "nullPointMode": "null", + "options": { + "dataLinks": [] + }, + "percentage": false, + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [], + "spaceLength": 10, + "stack": true, + "steppedLine": false, + "targets": [ + { + "expr": "node_memory_SUnreclaim_bytes{instance=~\"$node:$port\",job=~\"$job\"}", + "format": "time_series", + "intervalFactor": 2, + "legendFormat": "SUnreclaim - Part of Slab, that cannot be reclaimed on memory pressure", + "refId": "O", + "step": 4 + }, + { + "expr": "node_memory_SReclaimable_bytes{instance=~\"$node:$port\",job=~\"$job\"}", + "format": "time_series", + "intervalFactor": 2, + "legendFormat": "SReclaimable - Part of Slab, that might be reclaimed, such as caches", + "refId": "N", + "step": 4 + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "Memory Slab", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "bytes", + "label": "Bytes", + "logBase": 1, + "max": null, + "min": "0", + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": false + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": { + "Active": "#99440A", + "Buffers": "#58140C", + "Cache": "#6D1F62", + "Cached": "#511749", + "Committed": "#508642", + "Dirty": "#6ED0E0", + "Free": "#B7DBAB", + "Inactive": "#EA6460", + "Mapped": "#052B51", + "PageTables": "#0A50A1", + "Page_Tables": "#0A50A1", + "Slab_Cache": "#EAB839", + "Swap": "#BF1B00", + "Swap_Cache": "#C15C17", + "Total": "#511749", + "Total RAM": "#052B51", + "Total RAM + Swap": "#052B51", + "VmallocUsed": "#EA6460" + }, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "Prometheus", + "decimals": 2, + "fill": 2, + "fillGradient": 0, + "gridPos": { + "h": 10, + "w": 12, + "x": 0, + "y": 38 + }, + "hiddenSeries": false, + "id": 70, + "legend": { + "alignAsTable": true, + "avg": true, + "current": true, + "max": true, + "min": true, + "rightSide": false, + "show": true, + "sideWidth": null, + "total": false, + "values": true + }, + "lines": true, + "linewidth": 1, + "links": [], + "maxPerRow": 6, + "nullPointMode": "null", + "options": { + "dataLinks": [] + }, + "percentage": false, + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "node_memory_VmallocChunk_bytes{instance=~\"$node:$port\",job=~\"$job\"}", + "format": "time_series", + "hide": false, + "intervalFactor": 2, + "legendFormat": "VmallocChunk - Largest contigious block of vmalloc area which is free", + "refId": "H", + "step": 4 + }, + { + "expr": "node_memory_VmallocTotal_bytes{instance=~\"$node:$port\",job=~\"$job\"}", + "format": "time_series", + "hide": false, + "intervalFactor": 2, + "legendFormat": "VmallocTotal - Total size of vmalloc memory area", + "refId": "I", + "step": 4 + }, + { + "expr": "node_memory_VmallocUsed_bytes{instance=~\"$node:$port\",job=~\"$job\"}", + "format": "time_series", + "hide": false, + "intervalFactor": 2, + "legendFormat": "VmallocUsed - Amount of vmalloc area which is used", + "refId": "O", + "step": 4 + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "Memory Vmalloc", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "bytes", + "label": "Bytes", + "logBase": 1, + "max": null, + "min": "0", + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": false + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": { + "Apps": "#629E51", + "Buffers": "#614D93", + "Cache": "#6D1F62", + "Cached": "#511749", + "Committed": "#508642", + "Free": "#0A437C", + "Hardware Corrupted - Amount of RAM that the kernel identified as corrupted / not working": "#CFFAFF", + "Inactive": "#584477", + "PageTables": "#0A50A1", + "Page_Tables": "#0A50A1", + "RAM_Free": "#E0F9D7", + "Slab": "#806EB7", + "Slab_Cache": "#E0752D", + "Swap": "#BF1B00", + "Swap_Cache": "#C15C17", + "Swap_Free": "#2F575E", + "Unused": "#EAB839" + }, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "Prometheus", + "decimals": 2, + "fill": 2, + "fillGradient": 0, + "gridPos": { + "h": 10, + "w": 12, + "x": 12, + "y": 38 + }, + "hiddenSeries": false, + "id": 159, + "legend": { + "alignAsTable": true, + "avg": true, + "current": true, + "max": true, + "min": true, + "rightSide": false, + "show": true, + "sideWidth": 350, + "total": false, + "values": true + }, + "lines": true, + "linewidth": 1, + "links": [], + "maxPerRow": 6, + "nullPointMode": "null", + "options": { + "dataLinks": [] + }, + "percentage": false, + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "node_memory_Bounce_bytes{instance=~\"$node:$port\",job=~\"$job\"}", + "format": "time_series", + "intervalFactor": 2, + "legendFormat": "Bounce - Memory used for block device bounce buffers", + "refId": "N", + "step": 4 + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "Memory Bounce", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "cumulative" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "bytes", + "label": "Bytes", + "logBase": 1, + "max": null, + "min": "0", + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": false + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": { + "Active": "#99440A", + "Buffers": "#58140C", + "Cache": "#6D1F62", + "Cached": "#511749", + "Committed": "#508642", + "Dirty": "#6ED0E0", + "Free": "#B7DBAB", + "Inactive": "#EA6460", + "Mapped": "#052B51", + "PageTables": "#0A50A1", + "Page_Tables": "#0A50A1", + "Slab_Cache": "#EAB839", + "Swap": "#BF1B00", + "Swap_Cache": "#C15C17", + "Total": "#511749", + "Total RAM": "#052B51", + "Total RAM + Swap": "#052B51", + "VmallocUsed": "#EA6460" + }, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "Prometheus", + "decimals": 2, + "fill": 2, + "fillGradient": 0, + "gridPos": { + "h": 10, + "w": 12, + "x": 0, + "y": 48 + }, + "hiddenSeries": false, + "id": 129, + "legend": { + "alignAsTable": true, + "avg": true, + "current": true, + "max": true, + "min": true, + "rightSide": false, + "show": true, + "sideWidth": null, + "total": false, + "values": true + }, + "lines": true, + "linewidth": 1, + "links": [], + "maxPerRow": 6, + "nullPointMode": "null", + "options": { + "dataLinks": [] + }, + "percentage": false, + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [ + { + "alias": "/.*Inactive *./", + "transform": "negative-Y" + } + ], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "node_memory_AnonHugePages_bytes{instance=~\"$node:$port\",job=~\"$job\"}", + "format": "time_series", + "intervalFactor": 2, + "legendFormat": "AnonHugePages - Memory in anonymous huge pages", + "refId": "D", + "step": 4 + }, + { + "expr": "node_memory_AnonPages_bytes{instance=~\"$node:$port\",job=~\"$job\"}", + "format": "time_series", + "intervalFactor": 2, + "legendFormat": "AnonPages - Memory in user pages not backed by files", + "refId": "G", + "step": 4 + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "Memory Anonymous", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "bytes", + "label": "Bytes", + "logBase": 1, + "max": null, + "min": "0", + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": false + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": { + "Apps": "#629E51", + "Buffers": "#614D93", + "Cache": "#6D1F62", + "Cached": "#511749", + "Committed": "#508642", + "Free": "#0A437C", + "Hardware Corrupted - Amount of RAM that the kernel identified as corrupted / not working": "#CFFAFF", + "Inactive": "#584477", + "PageTables": "#0A50A1", + "Page_Tables": "#0A50A1", + "RAM_Free": "#E0F9D7", + "Slab": "#806EB7", + "Slab_Cache": "#E0752D", + "Swap": "#BF1B00", + "Swap_Cache": "#C15C17", + "Swap_Free": "#2F575E", + "Unused": "#EAB839" + }, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "Prometheus", + "decimals": 2, + "fill": 2, + "fillGradient": 0, + "gridPos": { + "h": 10, + "w": 12, + "x": 12, + "y": 48 + }, + "hiddenSeries": false, + "id": 160, + "legend": { + "alignAsTable": true, + "avg": true, + "current": true, + "max": true, + "min": true, + "rightSide": false, + "show": true, + "sideWidth": 350, + "total": false, + "values": true + }, + "lines": true, + "linewidth": 1, + "links": [], + "maxPerRow": 2, + "nullPointMode": "null", + "options": { + "dataLinks": [] + }, + "percentage": false, + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "node_memory_KernelStack_bytes{instance=~\"$node:$port\",job=~\"$job\"}", + "format": "time_series", + "intervalFactor": 2, + "legendFormat": "KernelStack - Kernel memory stack. This is not reclaimable", + "refId": "N", + "step": 4 + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "Memory Kernel", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "cumulative" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "bytes", + "label": "Bytes", + "logBase": 1, + "max": null, + "min": "0", + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": false + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": { + "Active": "#99440A", + "Buffers": "#58140C", + "Cache": "#6D1F62", + "Cached": "#511749", + "Committed": "#508642", + "Dirty": "#6ED0E0", + "Free": "#B7DBAB", + "Inactive": "#EA6460", + "Mapped": "#052B51", + "PageTables": "#0A50A1", + "Page_Tables": "#0A50A1", + "Slab_Cache": "#EAB839", + "Swap": "#BF1B00", + "Swap_Cache": "#C15C17", + "Total": "#511749", + "Total RAM": "#806EB7", + "Total RAM + Swap": "#806EB7", + "VmallocUsed": "#EA6460" + }, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "Prometheus", + "decimals": 2, + "fill": 2, + "fillGradient": 0, + "gridPos": { + "h": 10, + "w": 12, + "x": 0, + "y": 58 + }, + "hiddenSeries": false, + "id": 140, + "legend": { + "alignAsTable": true, + "avg": false, + "current": true, + "max": true, + "min": true, + "rightSide": false, + "show": true, + "sideWidth": null, + "total": false, + "values": true + }, + "lines": true, + "linewidth": 1, + "links": [], + "maxPerRow": 6, + "nullPointMode": "null", + "options": { + "dataLinks": [] + }, + "percentage": false, + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "node_memory_HugePages_Free{instance=~\"$node:$port\",job=~\"$job\"}", + "format": "time_series", + "intervalFactor": 2, + "legendFormat": "HugePages_Free - Huge pages in the pool that are not yet allocated", + "refId": "I", + "step": 4 + }, + { + "expr": "node_memory_HugePages_Rsvd{instance=~\"$node:$port\",job=~\"$job\"}", + "format": "time_series", + "intervalFactor": 2, + "legendFormat": "HugePages_Rsvd - Huge pages for which a commitment to allocate from the pool has been made, but no allocation has yet been made", + "refId": "J", + "step": 4 + }, + { + "expr": "node_memory_HugePages_Surp{instance=~\"$node:$port\",job=~\"$job\"}", + "format": "time_series", + "intervalFactor": 2, + "legendFormat": "HugePages_Surp - Huge pages in the pool above the value in /proc/sys/vm/nr_hugepages", + "refId": "K", + "step": 4 + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "Memory HugePages Counter", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "short", + "label": "Pages", + "logBase": 1, + "max": null, + "min": "0", + "show": true + }, + { + "format": "short", + "label": "", + "logBase": 1, + "max": null, + "min": null, + "show": false + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": { + "Active": "#99440A", + "Buffers": "#58140C", + "Cache": "#6D1F62", + "Cached": "#511749", + "Committed": "#508642", + "Dirty": "#6ED0E0", + "Free": "#B7DBAB", + "Inactive": "#EA6460", + "Mapped": "#052B51", + "PageTables": "#0A50A1", + "Page_Tables": "#0A50A1", + "Slab_Cache": "#EAB839", + "Swap": "#BF1B00", + "Swap_Cache": "#C15C17", + "Total": "#511749", + "Total RAM": "#806EB7", + "Total RAM + Swap": "#806EB7", + "VmallocUsed": "#EA6460" + }, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "Prometheus", + "decimals": 2, + "fill": 2, + "fillGradient": 0, + "gridPos": { + "h": 10, + "w": 12, + "x": 12, + "y": 58 + }, + "hiddenSeries": false, + "id": 71, + "legend": { + "alignAsTable": true, + "avg": false, + "current": true, + "max": true, + "min": true, + "rightSide": false, + "show": true, + "sideWidth": null, + "total": false, + "values": true + }, + "lines": true, + "linewidth": 1, + "links": [], + "maxPerRow": 2, + "nullPointMode": "null", + "options": { + "dataLinks": [] + }, + "percentage": false, + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "node_memory_HugePages_Total{instance=~\"$node:$port\",job=~\"$job\"}", + "format": "time_series", + "intervalFactor": 2, + "legendFormat": "HugePages - Total size of the pool of huge pages", + "refId": "L", + "step": 4 + }, + { + "expr": "node_memory_Hugepagesize_bytes{instance=~\"$node:$port\",job=~\"$job\"}", + "format": "time_series", + "intervalFactor": 2, + "legendFormat": "Hugepagesize - Huge Page size", + "refId": "D", + "step": 4 + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "Memory HugePages Size", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "bytes", + "label": "Bytes", + "logBase": 1, + "max": null, + "min": "0", + "show": true + }, + { + "format": "short", + "label": "", + "logBase": 1, + "max": null, + "min": null, + "show": false + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": { + "Active": "#99440A", + "Buffers": "#58140C", + "Cache": "#6D1F62", + "Cached": "#511749", + "Committed": "#508642", + "Dirty": "#6ED0E0", + "Free": "#B7DBAB", + "Inactive": "#EA6460", + "Mapped": "#052B51", + "PageTables": "#0A50A1", + "Page_Tables": "#0A50A1", + "Slab_Cache": "#EAB839", + "Swap": "#BF1B00", + "Swap_Cache": "#C15C17", + "Total": "#511749", + "Total RAM": "#052B51", + "Total RAM + Swap": "#052B51", + "VmallocUsed": "#EA6460" + }, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "Prometheus", + "decimals": 2, + "fill": 2, + "fillGradient": 0, + "gridPos": { + "h": 10, + "w": 12, + "x": 0, + "y": 68 + }, + "hiddenSeries": false, + "id": 128, + "legend": { + "alignAsTable": true, + "avg": true, + "current": false, + "hideEmpty": false, + "hideZero": false, + "max": true, + "min": true, + "rightSide": false, + "show": true, + "sideWidth": null, + "total": false, + "values": true + }, + "lines": true, + "linewidth": 1, + "links": [], + "maxPerRow": 6, + "nullPointMode": "null", + "options": { + "dataLinks": [] + }, + "percentage": false, + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "node_memory_DirectMap1G_bytes{instance=~\"$node:$port\",job=~\"$job\"}", + "format": "time_series", + "intervalFactor": 2, + "legendFormat": "DirectMap1G - Amount of pages mapped as this size", + "refId": "J", + "step": 4 + }, + { + "expr": "node_memory_DirectMap2M_bytes{instance=~\"$node:$port\",job=~\"$job\"}", + "format": "time_series", + "interval": "", + "intervalFactor": 2, + "legendFormat": "DirectMap2M - Amount of pages mapped as this size", + "refId": "K", + "step": 4 + }, + { + "expr": "node_memory_DirectMap4k_bytes{instance=~\"$node:$port\",job=~\"$job\"}", + "format": "time_series", + "interval": "", + "intervalFactor": 2, + "legendFormat": "DirectMap4K - Amount of pages mapped as this size", + "refId": "L", + "step": 4 + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "Memory DirectMap", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "bytes", + "label": "Bytes", + "logBase": 1, + "max": null, + "min": "0", + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": false + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": { + "Apps": "#629E51", + "Buffers": "#614D93", + "Cache": "#6D1F62", + "Cached": "#511749", + "Committed": "#508642", + "Free": "#0A437C", + "Hardware Corrupted - Amount of RAM that the kernel identified as corrupted / not working": "#CFFAFF", + "Inactive": "#584477", + "PageTables": "#0A50A1", + "Page_Tables": "#0A50A1", + "RAM_Free": "#E0F9D7", + "Slab": "#806EB7", + "Slab_Cache": "#E0752D", + "Swap": "#BF1B00", + "Swap_Cache": "#C15C17", + "Swap_Free": "#2F575E", + "Unused": "#EAB839" + }, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "Prometheus", + "decimals": 2, + "fill": 2, + "fillGradient": 0, + "gridPos": { + "h": 10, + "w": 12, + "x": 12, + "y": 68 + }, + "hiddenSeries": false, + "id": 137, + "legend": { + "alignAsTable": true, + "avg": true, + "current": true, + "max": true, + "min": true, + "rightSide": false, + "show": true, + "sideWidth": 350, + "total": false, + "values": true + }, + "lines": true, + "linewidth": 1, + "links": [], + "maxPerRow": 6, + "nullPointMode": "null", + "options": { + "dataLinks": [] + }, + "percentage": false, + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "node_memory_Unevictable_bytes{instance=~\"$node:$port\",job=~\"$job\"}", + "format": "time_series", + "intervalFactor": 2, + "legendFormat": "Unevictable - Amount of unevictable memory that can't be swapped out for a variety of reasons", + "refId": "P", + "step": 4 + }, + { + "expr": "node_memory_Mlocked_bytes{instance=~\"$node:$port\",job=~\"$job\"}", + "format": "time_series", + "intervalFactor": 2, + "legendFormat": "MLocked - Size of pages locked to memory using the mlock() system call", + "refId": "C", + "step": 4 + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "Memory Unevictable and MLocked", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "cumulative" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "bytes", + "label": "Bytes", + "logBase": 1, + "max": null, + "min": "0", + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": false + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": { + "Active": "#99440A", + "Buffers": "#58140C", + "Cache": "#6D1F62", + "Cached": "#511749", + "Committed": "#508642", + "Dirty": "#6ED0E0", + "Free": "#B7DBAB", + "Inactive": "#EA6460", + "Mapped": "#052B51", + "PageTables": "#0A50A1", + "Page_Tables": "#0A50A1", + "Slab_Cache": "#EAB839", + "Swap": "#BF1B00", + "Swap_Cache": "#C15C17", + "Total": "#511749", + "Total RAM": "#052B51", + "Total RAM + Swap": "#052B51", + "Total Swap": "#614D93", + "VmallocUsed": "#EA6460" + }, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "Prometheus", + "decimals": 2, + "fill": 2, + "fillGradient": 0, + "gridPos": { + "h": 10, + "w": 12, + "x": 0, + "y": 78 + }, + "hiddenSeries": false, + "id": 132, + "legend": { + "alignAsTable": true, + "avg": true, + "current": true, + "max": true, + "min": true, + "rightSide": false, + "show": true, + "sideWidth": null, + "total": false, + "values": true + }, + "lines": true, + "linewidth": 1, + "links": [], + "maxPerRow": 6, + "nullPointMode": "null", + "options": { + "dataLinks": [] + }, + "percentage": false, + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "node_memory_NFS_Unstable_bytes{instance=~\"$node:$port\",job=~\"$job\"}", + "format": "time_series", + "intervalFactor": 2, + "legendFormat": "NFS Unstable - Memory in NFS pages sent to the server, but not yet commited to the storage", + "refId": "L", + "step": 4 + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "Memory NFS", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "bytes", + "label": "Bytes", + "logBase": 1, + "max": null, + "min": "0", + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": false + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + } + ], + "repeat": null, + "title": "Memory Meminfo", + "type": "row" + }, + { + "collapsed": true, + "datasource": "Prometheus", + "gridPos": { + "h": 1, + "w": 24, + "x": 0, + "y": 70 + }, + "id": 267, + "panels": [ + { + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "Prometheus", + "fill": 2, + "fillGradient": 0, + "gridPos": { + "h": 10, + "w": 12, + "x": 0, + "y": 5 + }, + "hiddenSeries": false, + "id": 176, + "legend": { + "alignAsTable": true, + "avg": true, + "current": true, + "max": true, + "min": true, + "rightSide": false, + "show": true, + "total": false, + "values": true + }, + "lines": true, + "linewidth": 1, + "links": [], + "maxPerRow": 6, + "nullPointMode": "null", + "options": { + "dataLinks": [] + }, + "percentage": false, + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [ + { + "alias": "/.*out/", + "transform": "negative-Y" + } + ], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "irate(node_vmstat_pgpgin{instance=~\"$node:$port\",job=~\"$job\"}[5m])", + "format": "time_series", + "intervalFactor": 2, + "legendFormat": "Pagesin - Page in operations", + "refId": "A", + "step": 4 + }, + { + "expr": "irate(node_vmstat_pgpgout{instance=~\"$node:$port\",job=~\"$job\"}[5m])", + "format": "time_series", + "intervalFactor": 2, + "legendFormat": "Pagesout - Page out operations", + "refId": "B", + "step": 4 + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "Memory Pages In / Out", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "short", + "label": "Pages out (-) / in (+)", + "logBase": 1, + "max": null, + "min": null, + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": false + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "Prometheus", + "fill": 2, + "fillGradient": 0, + "gridPos": { + "h": 10, + "w": 12, + "x": 12, + "y": 5 + }, + "hiddenSeries": false, + "id": 22, + "legend": { + "alignAsTable": true, + "avg": true, + "current": true, + "max": true, + "min": true, + "rightSide": false, + "show": true, + "total": false, + "values": true + }, + "lines": true, + "linewidth": 1, + "links": [], + "maxPerRow": 6, + "nullPointMode": "null", + "options": { + "dataLinks": [] + }, + "percentage": false, + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [ + { + "alias": "/.*out/", + "transform": "negative-Y" + } + ], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "irate(node_vmstat_pswpin{instance=~\"$node:$port\",job=~\"$job\"}[5m])", + "format": "time_series", + "intervalFactor": 2, + "legendFormat": "Pswpin - Pages swapped in", + "refId": "A", + "step": 4 + }, + { + "expr": "irate(node_vmstat_pswpout{instance=~\"$node:$port\",job=~\"$job\"}[5m])", + "format": "time_series", + "intervalFactor": 2, + "legendFormat": "Pswpout - Pages swapped out", + "refId": "B", + "step": 4 + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "Memory Pages Swap In / Out", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "short", + "label": "Pages out (-) / in (+)", + "logBase": 1, + "max": null, + "min": null, + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": false + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": { + "Apps": "#629E51", + "Buffers": "#614D93", + "Cache": "#6D1F62", + "Cached": "#511749", + "Committed": "#508642", + "Free": "#0A437C", + "Hardware Corrupted - Amount of RAM that the kernel identified as corrupted / not working": "#CFFAFF", + "Inactive": "#584477", + "PageTables": "#0A50A1", + "Page_Tables": "#0A50A1", + "RAM_Free": "#E0F9D7", + "Slab": "#806EB7", + "Slab_Cache": "#E0752D", + "Swap": "#BF1B00", + "Swap_Cache": "#C15C17", + "Swap_Free": "#2F575E", + "Unused": "#EAB839" + }, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "Prometheus", + "decimals": 2, + "fill": 2, + "fillGradient": 0, + "gridPos": { + "h": 10, + "w": 12, + "x": 12, + "y": 15 + }, + "hiddenSeries": false, + "id": 175, + "legend": { + "alignAsTable": true, + "avg": true, + "current": true, + "max": true, + "min": true, + "rightSide": false, + "show": true, + "sideWidth": 350, + "total": false, + "values": true + }, + "lines": true, + "linewidth": 1, + "links": [], + "maxPerRow": 6, + "nullPointMode": "null", + "options": { + "dataLinks": [] + }, + "percentage": false, + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [ + { + "alias": "Pgfault - Page major and minor fault operations", + "fill": 0, + "stack": false + } + ], + "spaceLength": 10, + "stack": true, + "steppedLine": false, + "targets": [ + { + "expr": "irate(node_vmstat_pgfault{instance=~\"$node:$port\",job=~\"$job\"}[5m])", + "format": "time_series", + "intervalFactor": 2, + "legendFormat": "Pgfault - Page major and minor fault operations", + "refId": "C", + "step": 4 + }, + { + "expr": "irate(node_vmstat_pgmajfault{instance=~\"$node:$port\",job=~\"$job\"}[5m])", + "format": "time_series", + "intervalFactor": 2, + "legendFormat": "Pgmajfault - Major page fault operations", + "refId": "F", + "step": 4 + }, + { + "expr": "irate(node_vmstat_pgfault{instance=~\"$node:$port\",job=~\"$job\"}[5m]) - irate(node_vmstat_pgmajfault{instance=~\"$node:$port\",job=~\"$job\"}[5m])", + "format": "time_series", + "intervalFactor": 2, + "legendFormat": "Pgminfault - Minor page fault operations", + "refId": "A", + "step": 4 + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "Memory Page Faults", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "cumulative" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "short", + "label": "Faults", + "logBase": 1, + "max": null, + "min": "0", + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": false + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + } + ], + "repeat": null, + "title": "Memory Vmstat", + "type": "row" + }, + { + "collapsed": true, + "datasource": "Prometheus", + "gridPos": { + "h": 1, + "w": 24, + "x": 0, + "y": 71 + }, + "id": 293, + "panels": [ + { + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "Prometheus", + "description": "", + "fill": 2, + "fillGradient": 0, + "gridPos": { + "h": 10, + "w": 12, + "x": 0, + "y": 24 + }, + "hiddenSeries": false, + "id": 260, + "legend": { + "alignAsTable": true, + "avg": true, + "current": true, + "max": true, + "min": true, + "show": true, + "total": false, + "values": true + }, + "lines": true, + "linewidth": 1, + "links": [], + "nullPointMode": "null", + "options": { + "dataLinks": [] + }, + "percentage": false, + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [ + { + "alias": "/.*Variation*./", + "color": "#890F02" + } + ], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "node_timex_estimated_error_seconds{instance=~\"$node:$port\",job=~\"$job\"}", + "format": "time_series", + "hide": false, + "interval": "", + "intervalFactor": 2, + "legendFormat": "Estimated error in seconds", + "refId": "B", + "step": 240 + }, + { + "expr": "node_timex_offset_seconds{instance=~\"$node:$port\",job=~\"$job\"}", + "format": "time_series", + "hide": false, + "interval": "", + "intervalFactor": 2, + "legendFormat": "Time offset in between local system and reference clock", + "refId": "A", + "step": 240 + }, + { + "expr": "node_timex_maxerror_seconds{instance=~\"$node:$port\",job=~\"$job\"}", + "format": "time_series", + "hide": false, + "interval": "", + "intervalFactor": 2, + "legendFormat": "Maximum error in seconds", + "refId": "C", + "step": 240 + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "Time Syncronized Drift", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "s", + "label": "Seconds", + "logBase": 1, + "max": null, + "min": null, + "show": true + }, + { + "format": "short", + "label": "Counter", + "logBase": 1, + "max": null, + "min": null, + "show": false + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "Prometheus", + "description": "", + "fill": 2, + "fillGradient": 0, + "gridPos": { + "h": 10, + "w": 12, + "x": 12, + "y": 24 + }, + "hiddenSeries": false, + "id": 291, + "legend": { + "alignAsTable": true, + "avg": true, + "current": true, + "max": true, + "min": true, + "show": true, + "total": false, + "values": true + }, + "lines": true, + "linewidth": 1, + "links": [], + "nullPointMode": "null", + "options": { + "dataLinks": [] + }, + "percentage": false, + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "node_timex_loop_time_constant{instance=~\"$node:$port\",job=~\"$job\"}", + "format": "time_series", + "interval": "", + "intervalFactor": 2, + "legendFormat": "Phase-locked loop time adjust", + "refId": "B", + "step": 240 + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "Time PLL Adjust", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "short", + "label": "Counter", + "logBase": 1, + "max": null, + "min": null, + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": false + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "Prometheus", + "description": "", + "fill": 2, + "fillGradient": 0, + "gridPos": { + "h": 10, + "w": 12, + "x": 0, + "y": 34 + }, + "hiddenSeries": false, + "id": 168, + "legend": { + "alignAsTable": true, + "avg": true, + "current": true, + "max": true, + "min": true, + "show": true, + "total": false, + "values": true + }, + "lines": true, + "linewidth": 1, + "links": [], + "nullPointMode": "null", + "options": { + "dataLinks": [] + }, + "percentage": false, + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [ + { + "alias": "/.*Variation*./", + "color": "#890F02" + } + ], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "node_timex_sync_status{instance=~\"$node:$port\",job=~\"$job\"}", + "format": "time_series", + "interval": "", + "intervalFactor": 2, + "legendFormat": "Is clock synchronized to a reliable server (1 = yes, 0 = no)", + "refId": "B", + "step": 240 + }, + { + "expr": "node_timex_frequency_adjustment_ratio{instance=~\"$node:$port\",job=~\"$job\"}", + "format": "time_series", + "interval": "", + "intervalFactor": 2, + "legendFormat": "Local clock frequency adjustment", + "refId": "A", + "step": 240 + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "Time Syncronized Status", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "short", + "label": "Counter", + "logBase": 1, + "max": null, + "min": null, + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": false + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "Prometheus", + "description": "", + "fill": 2, + "fillGradient": 0, + "gridPos": { + "h": 10, + "w": 12, + "x": 12, + "y": 34 + }, + "hiddenSeries": false, + "id": 294, + "legend": { + "alignAsTable": true, + "avg": true, + "current": true, + "max": true, + "min": true, + "show": true, + "total": false, + "values": true + }, + "lines": true, + "linewidth": 1, + "links": [], + "nullPointMode": "null", + "options": { + "dataLinks": [] + }, + "percentage": false, + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "node_timex_tick_seconds{instance=~\"$node:$port\",job=~\"$job\"}", + "format": "time_series", + "interval": "", + "intervalFactor": 2, + "legendFormat": "Seconds between clock ticks", + "refId": "B", + "step": 240 + }, + { + "expr": "node_timex_tai_offset_seconds{instance=~\"$node:$port\",job=~\"$job\"}", + "format": "time_series", + "interval": "", + "intervalFactor": 2, + "legendFormat": "International Atomic Time (TAI) offset", + "refId": "A", + "step": 240 + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "Time Misc", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "s", + "label": "Seconds", + "logBase": 1, + "max": null, + "min": null, + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": false + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + } + ], + "title": "System Timesync", + "type": "row" + }, + { + "collapsed": true, + "datasource": "Prometheus", + "gridPos": { + "h": 1, + "w": 24, + "x": 0, + "y": 72 + }, + "id": 269, + "panels": [ + { + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "Prometheus", + "fill": 2, + "fillGradient": 0, + "gridPos": { + "h": 10, + "w": 12, + "x": 0, + "y": 11 + }, + "hiddenSeries": false, + "id": 8, + "legend": { + "alignAsTable": true, + "avg": true, + "current": true, + "max": true, + "min": true, + "show": true, + "total": false, + "values": true + }, + "lines": true, + "linewidth": 1, + "links": [], + "maxPerRow": 6, + "nullPointMode": "null", + "options": { + "dataLinks": [] + }, + "percentage": false, + "pointradius": 5, + "points": false, + "renderer": "flot", + "repeat": null, + "seriesOverrides": [], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "irate(node_context_switches_total{instance=~\"$node:$port\",job=~\"$job\"}[5m])", + "format": "time_series", + "intervalFactor": 2, + "legendFormat": "Context switches", + "refId": "A", + "step": 240 + }, + { + "expr": "irate(node_intr_total{instance=~\"$node:$port\",job=~\"$job\"}[5m])", + "format": "time_series", + "intervalFactor": 2, + "legendFormat": "Interrupts", + "refId": "B", + "step": 240 + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "Context Switches / Interrupts", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "short", + "label": "Counter", + "logBase": 1, + "max": null, + "min": "0", + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": false + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "Prometheus", + "fill": 2, + "fillGradient": 0, + "gridPos": { + "h": 10, + "w": 12, + "x": 12, + "y": 11 + }, + "hiddenSeries": false, + "id": 7, + "legend": { + "alignAsTable": true, + "avg": true, + "current": true, + "max": true, + "min": true, + "show": true, + "total": false, + "values": true + }, + "lines": true, + "linewidth": 1, + "links": [], + "maxPerRow": 6, + "nullPointMode": "null", + "options": { + "dataLinks": [] + }, + "percentage": false, + "pointradius": 5, + "points": false, + "renderer": "flot", + "repeat": null, + "seriesOverrides": [], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "node_load1{instance=~\"$node:$port\",job=~\"$job\"}", + "format": "time_series", + "intervalFactor": 4, + "legendFormat": "Load 1m", + "refId": "A", + "step": 480 + }, + { + "expr": "node_load5{instance=~\"$node:$port\",job=~\"$job\"}", + "format": "time_series", + "intervalFactor": 4, + "legendFormat": "Load 5m", + "refId": "B", + "step": 480 + }, + { + "expr": "node_load15{instance=~\"$node:$port\",job=~\"$job\"}", + "format": "time_series", + "intervalFactor": 4, + "legendFormat": "Load 15m", + "refId": "C", + "step": 480 + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "System Load", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "short", + "label": "Load", + "logBase": 1, + "max": null, + "min": "0", + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": false + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "Prometheus", + "fill": 2, + "fillGradient": 0, + "gridPos": { + "h": 10, + "w": 12, + "x": 0, + "y": 21 + }, + "hiddenSeries": false, + "id": 259, + "legend": { + "alignAsTable": true, + "avg": true, + "current": true, + "max": true, + "min": true, + "show": true, + "total": false, + "values": true + }, + "lines": true, + "linewidth": 1, + "links": [], + "nullPointMode": "null", + "options": { + "dataLinks": [] + }, + "percentage": false, + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [ + { + "alias": "/.*Critical*./", + "color": "#E24D42", + "fill": 0 + }, + { + "alias": "/.*Max*./", + "color": "#EF843C", + "fill": 0 + } + ], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "irate(node_interrupts_total{instance=~\"$node:$port\",job=~\"$job\"}[5m])", + "format": "time_series", + "interval": "", + "intervalFactor": 2, + "legendFormat": "{{ type }} - {{ info }}", + "refId": "A", + "step": 240 + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "Interrupts Detail", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "short", + "label": "Counter", + "logBase": 1, + "max": null, + "min": "0", + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": false + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "Prometheus", + "fill": 2, + "fillGradient": 0, + "gridPos": { + "h": 10, + "w": 12, + "x": 12, + "y": 21 + }, + "hiddenSeries": false, + "id": 64, + "legend": { + "alignAsTable": true, + "avg": true, + "current": true, + "max": true, + "min": true, + "show": true, + "total": false, + "values": true + }, + "lines": true, + "linewidth": 1, + "links": [], + "nullPointMode": "null", + "options": { + "dataLinks": [] + }, + "percentage": false, + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [ + { + "alias": "/.*Max*./", + "color": "#890F02", + "fill": 0 + } + ], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "process_max_fds{instance=~\"$node:$port\",job=~\"$job\"}", + "interval": "", + "intervalFactor": 2, + "legendFormat": "Maximum open file descriptors", + "refId": "A", + "step": 240 + }, + { + "expr": "process_open_fds{instance=~\"$node:$port\",job=~\"$job\"}", + "interval": "", + "intervalFactor": 2, + "legendFormat": "Open file descriptors", + "refId": "B", + "step": 240 + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "File Descriptors", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "short", + "label": "Descriptors", + "logBase": 1, + "max": null, + "min": "0", + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": false + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "Prometheus", + "fill": 2, + "fillGradient": 0, + "gridPos": { + "h": 10, + "w": 12, + "x": 0, + "y": 31 + }, + "hiddenSeries": false, + "id": 151, + "legend": { + "alignAsTable": true, + "avg": true, + "current": true, + "max": true, + "min": true, + "show": true, + "total": false, + "values": true + }, + "lines": true, + "linewidth": 1, + "links": [], + "maxPerRow": 6, + "nullPointMode": "null", + "options": { + "dataLinks": [] + }, + "percentage": false, + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "node_entropy_available_bits{instance=~\"$node:$port\",job=~\"$job\"}", + "format": "time_series", + "intervalFactor": 2, + "legendFormat": "Entropy available to random number generators", + "refId": "C", + "step": 240 + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "Entropy", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "short", + "label": "Entropy", + "logBase": 1, + "max": null, + "min": "0", + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": false + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "Prometheus", + "fill": 2, + "fillGradient": 0, + "gridPos": { + "h": 10, + "w": 12, + "x": 12, + "y": 31 + }, + "hiddenSeries": false, + "id": 62, + "legend": { + "alignAsTable": true, + "avg": true, + "current": true, + "max": true, + "min": true, + "show": true, + "total": false, + "values": true + }, + "lines": true, + "linewidth": 1, + "links": [], + "maxPerRow": 6, + "nullPointMode": "null", + "options": { + "dataLinks": [] + }, + "percentage": false, + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "node_procs_blocked{instance=~\"$node:$port\",job=~\"$job\"}", + "format": "time_series", + "intervalFactor": 2, + "legendFormat": "Processes blocked waiting for I/O to complete", + "refId": "A", + "step": 240 + }, + { + "expr": "node_procs_running{instance=~\"$node:$port\",job=~\"$job\"}", + "format": "time_series", + "intervalFactor": 2, + "legendFormat": "Processes in runnable state", + "refId": "B", + "step": 240 + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "Processes State", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "short", + "label": "Processes", + "logBase": 1, + "max": null, + "min": "0", + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": false + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "Prometheus", + "fill": 2, + "fillGradient": 0, + "gridPos": { + "h": 10, + "w": 12, + "x": 0, + "y": 41 + }, + "hiddenSeries": false, + "id": 148, + "legend": { + "alignAsTable": true, + "avg": true, + "current": true, + "max": true, + "min": true, + "show": true, + "total": false, + "values": true + }, + "lines": true, + "linewidth": 1, + "links": [], + "maxPerRow": 6, + "nullPointMode": "null", + "options": { + "dataLinks": [] + }, + "percentage": false, + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "irate(node_forks_total{instance=~\"$node:$port\",job=~\"$job\"}[5m])", + "format": "time_series", + "hide": false, + "intervalFactor": 2, + "legendFormat": "Processes forks second", + "refId": "C", + "step": 240 + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "Processes Forks", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "short", + "label": "Forks / sec", + "logBase": 1, + "max": null, + "min": "0", + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": false + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "Prometheus", + "fill": 2, + "fillGradient": 0, + "gridPos": { + "h": 10, + "w": 12, + "x": 12, + "y": 41 + }, + "hiddenSeries": false, + "id": 149, + "legend": { + "alignAsTable": true, + "avg": true, + "current": true, + "max": true, + "min": true, + "show": true, + "total": false, + "values": true + }, + "lines": true, + "linewidth": 1, + "links": [], + "nullPointMode": "null", + "options": { + "dataLinks": [] + }, + "percentage": false, + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [ + { + "alias": "/.*Max.*/", + "fill": 0 + } + ], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "irate(process_virtual_memory_bytes{instance=~\"$node:$port\",job=~\"$job\"}[5m])", + "hide": false, + "interval": "", + "intervalFactor": 2, + "legendFormat": "Processes virtual memory size in bytes", + "refId": "C", + "step": 240 + }, + { + "expr": "process_resident_memory_max_bytes{instance=~\"$node:$port\",job=~\"$job\"}", + "hide": false, + "interval": "", + "intervalFactor": 2, + "legendFormat": "Maximum amount of virtual memory available in bytes", + "refId": "A", + "step": 240 + }, + { + "expr": "irate(process_virtual_memory_bytes{instance=~\"$node:$port\",job=~\"$job\"}[5m])", + "hide": false, + "interval": "", + "intervalFactor": 2, + "legendFormat": "Processes virtual memory size in bytes", + "refId": "B", + "step": 240 + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "Processes Memory", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "decbytes", + "label": "Bytes", + "logBase": 1, + "max": null, + "min": "0", + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": false + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "Prometheus", + "fill": 2, + "fillGradient": 0, + "gridPos": { + "h": 10, + "w": 12, + "x": 0, + "y": 51 + }, + "hiddenSeries": false, + "id": 158, + "legend": { + "alignAsTable": true, + "avg": true, + "current": true, + "max": true, + "min": true, + "show": true, + "total": false, + "values": true + }, + "lines": true, + "linewidth": 1, + "links": [], + "nullPointMode": "null", + "options": { + "dataLinks": [] + }, + "percentage": false, + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [ + { + "alias": "/.*Critical*./", + "color": "#E24D42", + "fill": 0 + }, + { + "alias": "/.*Max*./", + "color": "#EF843C", + "fill": 0 + } + ], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "node_hwmon_temp_celsius{instance=~\"$node:$port\",job=~\"$job\"}", + "format": "time_series", + "interval": "", + "intervalFactor": 2, + "legendFormat": "{{ chip }} {{ sensor }} temp", + "refId": "A", + "step": 240 + }, + { + "expr": "node_hwmon_temp_crit_alarm_celsius{instance=~\"$node:$port\",job=~\"$job\"}", + "format": "time_series", + "hide": true, + "interval": "", + "intervalFactor": 2, + "legendFormat": "{{ chip }} {{ sensor }} Critical Alarm", + "refId": "B", + "step": 240 + }, + { + "expr": "node_hwmon_temp_crit_celsius{instance=~\"$node:$port\",job=~\"$job\"}", + "format": "time_series", + "interval": "", + "intervalFactor": 2, + "legendFormat": "{{ chip }} {{ sensor }} Critical", + "refId": "C", + "step": 240 + }, + { + "expr": "node_hwmon_temp_crit_hyst_celsius{instance=~\"$node:$port\",job=~\"$job\"}", + "format": "time_series", + "hide": true, + "interval": "", + "intervalFactor": 2, + "legendFormat": "{{ chip }} {{ sensor }} Critical Historical", + "refId": "D", + "step": 240 + }, + { + "expr": "node_hwmon_temp_max_celsius{instance=~\"$node:$port\",job=~\"$job\"}", + "format": "time_series", + "hide": true, + "interval": "", + "intervalFactor": 2, + "legendFormat": "{{ chip }} {{ sensor }} Max", + "refId": "E", + "step": 240 + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "Hardware temperature monitor", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "celsius", + "label": "Temperature", + "logBase": 1, + "max": null, + "min": "0", + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": false + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + } + ], + "repeat": null, + "title": "System Misc", + "type": "row" + }, + { + "collapsed": true, + "datasource": "Prometheus", + "gridPos": { + "h": 1, + "w": 24, + "x": 0, + "y": 73 + }, + "id": 296, + "panels": [ + { + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "Prometheus", + "fill": 2, + "fillGradient": 0, + "gridPos": { + "h": 10, + "w": 12, + "x": 0, + "y": 12 + }, + "hiddenSeries": false, + "id": 297, + "legend": { + "alignAsTable": true, + "avg": true, + "current": true, + "max": true, + "min": true, + "show": true, + "total": false, + "values": true + }, + "lines": true, + "linewidth": 1, + "links": [], + "nullPointMode": "null", + "options": { + "dataLinks": [] + }, + "percentage": false, + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "irate(node_systemd_socket_accepted_connections_total{instance=~\"$node:$port\",job=~\"$job\"}[5m])", + "format": "time_series", + "interval": "", + "intervalFactor": 2, + "legendFormat": "{{ name }} Connections", + "refId": "A", + "step": 240 + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "Systemd Sockets", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "short", + "label": "Counter", + "logBase": 1, + "max": null, + "min": "0", + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": false + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "Prometheus", + "fill": 2, + "fillGradient": 0, + "gridPos": { + "h": 10, + "w": 12, + "x": 12, + "y": 12 + }, + "hiddenSeries": false, + "id": 298, + "legend": { + "alignAsTable": true, + "avg": true, + "current": true, + "max": true, + "min": true, + "show": true, + "total": false, + "values": true + }, + "lines": true, + "linewidth": 1, + "links": [], + "nullPointMode": "null", + "options": { + "dataLinks": [] + }, + "percentage": false, + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [ + { + "alias": "Failed", + "color": "#F2495C" + }, + { + "alias": "Inactive", + "color": "#FF9830" + }, + { + "alias": "Active", + "color": "#73BF69" + }, + { + "alias": "Deactivating", + "color": "#FFCB7D" + }, + { + "alias": "Activating", + "color": "#C8F2C2" + } + ], + "spaceLength": 10, + "stack": true, + "steppedLine": false, + "targets": [ + { + "expr": "node_systemd_units{instance=~\"$node:$port\",job=~\"$job\",state=\"activating\"}", + "format": "time_series", + "interval": "", + "intervalFactor": 2, + "legendFormat": "Activating", + "refId": "A", + "step": 240 + }, + { + "expr": "node_systemd_units{instance=~\"$node:$port\",job=~\"$job\",state=\"active\"}", + "format": "time_series", + "interval": "", + "intervalFactor": 2, + "legendFormat": "Active", + "refId": "C", + "step": 240 + }, + { + "expr": "node_systemd_units{instance=~\"$node:$port\",job=~\"$job\",state=\"deactivating\"}", + "format": "time_series", + "interval": "", + "intervalFactor": 2, + "legendFormat": "Deactivating", + "refId": "D", + "step": 240 + }, + { + "expr": "node_systemd_units{instance=~\"$node:$port\",job=~\"$job\",state=\"failed\"}", + "format": "time_series", + "interval": "", + "intervalFactor": 2, + "legendFormat": "Failed", + "refId": "E", + "step": 240 + }, + { + "expr": "node_systemd_units{instance=~\"$node:$port\",job=~\"$job\",state=\"inactive\"}", + "format": "time_series", + "interval": "", + "intervalFactor": 2, + "legendFormat": "Inactive", + "refId": "F", + "step": 240 + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "Systemd Units State", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "short", + "label": "Counter", + "logBase": 1, + "max": null, + "min": null, + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": false + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + } + ], + "title": "Systemd", + "type": "row" + }, + { + "collapsed": true, + "datasource": "Prometheus", + "gridPos": { + "h": 1, + "w": 24, + "x": 0, + "y": 74 + }, + "id": 270, + "panels": [ + { + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "Prometheus", + "description": "", + "fill": 2, + "fillGradient": 0, + "gridPos": { + "h": 10, + "w": 12, + "x": 0, + "y": 9 + }, + "hiddenSeries": false, + "id": 9, + "legend": { + "alignAsTable": true, + "avg": true, + "current": true, + "hideZero": true, + "max": true, + "min": true, + "rightSide": false, + "show": true, + "total": false, + "values": true + }, + "lines": true, + "linewidth": 1, + "links": [], + "maxPerRow": 6, + "nullPointMode": "null", + "options": { + "dataLinks": [] + }, + "percentage": false, + "pointradius": 5, + "points": false, + "renderer": "flot", + "repeat": null, + "seriesOverrides": [ + { + "alias": "/.*Read.*/", + "transform": "negative-Y" + }, + { + "alias": "/.*sda_.*/", + "color": "#7EB26D" + }, + { + "alias": "/.*sdb_.*/", + "color": "#EAB839" + }, + { + "alias": "/.*sdc_.*/", + "color": "#6ED0E0" + }, + { + "alias": "/.*sdd_.*/", + "color": "#EF843C" + }, + { + "alias": "/.*sde_.*/", + "color": "#E24D42" + }, + { + "alias": "/.*sda1.*/", + "color": "#584477" + }, + { + "alias": "/.*sda2_.*/", + "color": "#BA43A9" + }, + { + "alias": "/.*sda3_.*/", + "color": "#F4D598" + }, + { + "alias": "/.*sdb1.*/", + "color": "#0A50A1" + }, + { + "alias": "/.*sdb2.*/", + "color": "#BF1B00" + }, + { + "alias": "/.*sdb3.*/", + "color": "#E0752D" + }, + { + "alias": "/.*sdc1.*/", + "color": "#962D82" + }, + { + "alias": "/.*sdc2.*/", + "color": "#614D93" + }, + { + "alias": "/.*sdc3.*/", + "color": "#9AC48A" + }, + { + "alias": "/.*sdd1.*/", + "color": "#65C5DB" + }, + { + "alias": "/.*sdd2.*/", + "color": "#F9934E" + }, + { + "alias": "/.*sdd3.*/", + "color": "#EA6460" + }, + { + "alias": "/.*sde1.*/", + "color": "#E0F9D7" + }, + { + "alias": "/.*sdd2.*/", + "color": "#FCEACA" + }, + { + "alias": "/.*sde3.*/", + "color": "#F9E2D2" + } + ], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "irate(node_disk_reads_completed_total{instance=~\"$node:$port\",job=~\"$job\"}[5m])", + "intervalFactor": 4, + "legendFormat": "{{device}} - Reads completed", + "refId": "A", + "step": 8 + }, + { + "expr": "irate(node_disk_writes_completed_total{instance=~\"$node:$port\",job=~\"$job\"}[5m])", + "intervalFactor": 2, + "legendFormat": "{{device}} - Writes completed", + "refId": "B", + "step": 4 + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "Disk IOps Completed", + "tooltip": { + "shared": false, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "iops", + "label": "IO read (-) / write (+)", + "logBase": 1, + "max": null, + "min": null, + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": false + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "Prometheus", + "description": "", + "fill": 2, + "fillGradient": 0, + "gridPos": { + "h": 10, + "w": 12, + "x": 12, + "y": 9 + }, + "hiddenSeries": false, + "id": 33, + "legend": { + "alignAsTable": true, + "avg": true, + "current": true, + "hideZero": true, + "max": true, + "min": true, + "rightSide": false, + "show": true, + "total": false, + "values": true + }, + "lines": true, + "linewidth": 1, + "links": [], + "maxPerRow": 6, + "nullPointMode": "null", + "options": { + "dataLinks": [] + }, + "percentage": false, + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [ + { + "alias": "/.*Read.*/", + "transform": "negative-Y" + }, + { + "alias": "/.*sda_.*/", + "color": "#7EB26D" + }, + { + "alias": "/.*sdb_.*/", + "color": "#EAB839" + }, + { + "alias": "/.*sdc_.*/", + "color": "#6ED0E0" + }, + { + "alias": "/.*sdd_.*/", + "color": "#EF843C" + }, + { + "alias": "/.*sde_.*/", + "color": "#E24D42" + }, + { + "alias": "/.*sda1.*/", + "color": "#584477" + }, + { + "alias": "/.*sda2_.*/", + "color": "#BA43A9" + }, + { + "alias": "/.*sda3_.*/", + "color": "#F4D598" + }, + { + "alias": "/.*sdb1.*/", + "color": "#0A50A1" + }, + { + "alias": "/.*sdb2.*/", + "color": "#BF1B00" + }, + { + "alias": "/.*sdb3.*/", + "color": "#E0752D" + }, + { + "alias": "/.*sdc1.*/", + "color": "#962D82" + }, + { + "alias": "/.*sdc2.*/", + "color": "#614D93" + }, + { + "alias": "/.*sdc3.*/", + "color": "#9AC48A" + }, + { + "alias": "/.*sdd1.*/", + "color": "#65C5DB" + }, + { + "alias": "/.*sdd2.*/", + "color": "#F9934E" + }, + { + "alias": "/.*sdd3.*/", + "color": "#EA6460" + }, + { + "alias": "/.*sde1.*/", + "color": "#E0F9D7" + }, + { + "alias": "/.*sdd2.*/", + "color": "#FCEACA" + }, + { + "alias": "/.*sde3.*/", + "color": "#F9E2D2" + } + ], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "irate(node_disk_read_bytes_total{instance=~\"$node:$port\",job=~\"$job\"}[5m])", + "format": "time_series", + "intervalFactor": 4, + "legendFormat": "{{device}} - Read bytes", + "refId": "A", + "step": 8 + }, + { + "expr": "irate(node_disk_written_bytes_total{instance=~\"$node:$port\",job=~\"$job\"}[5m])", + "format": "time_series", + "intervalFactor": 2, + "legendFormat": "{{device}} - Written bytes", + "refId": "B", + "step": 4 + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "Disk R/W Data", + "tooltip": { + "shared": false, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "Bps", + "label": "Bytes read (-) / write (+)", + "logBase": 1, + "max": null, + "min": null, + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": false + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "Prometheus", + "description": "", + "fill": 3, + "fillGradient": 0, + "gridPos": { + "h": 10, + "w": 12, + "x": 0, + "y": 19 + }, + "hiddenSeries": false, + "id": 37, + "legend": { + "alignAsTable": true, + "avg": true, + "current": true, + "hideZero": true, + "max": true, + "min": true, + "rightSide": false, + "show": true, + "sort": "current", + "sortDesc": true, + "total": false, + "values": true + }, + "lines": true, + "linewidth": 1, + "links": [], + "maxPerRow": 6, + "nullPointMode": "null", + "options": { + "dataLinks": [] + }, + "percentage": false, + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [ + { + "alias": "/.*Read.*/", + "transform": "negative-Y" + }, + { + "alias": "/.*sda_.*/", + "color": "#7EB26D" + }, + { + "alias": "/.*sdb_.*/", + "color": "#EAB839" + }, + { + "alias": "/.*sdc_.*/", + "color": "#6ED0E0" + }, + { + "alias": "/.*sdd_.*/", + "color": "#EF843C" + }, + { + "alias": "/.*sde_.*/", + "color": "#E24D42" + }, + { + "alias": "/.*sda1.*/", + "color": "#584477" + }, + { + "alias": "/.*sda2_.*/", + "color": "#BA43A9" + }, + { + "alias": "/.*sda3_.*/", + "color": "#F4D598" + }, + { + "alias": "/.*sdb1.*/", + "color": "#0A50A1" + }, + { + "alias": "/.*sdb2.*/", + "color": "#BF1B00" + }, + { + "alias": "/.*sdb3.*/", + "color": "#E0752D" + }, + { + "alias": "/.*sdc1.*/", + "color": "#962D82" + }, + { + "alias": "/.*sdc2.*/", + "color": "#614D93" + }, + { + "alias": "/.*sdc3.*/", + "color": "#9AC48A" + }, + { + "alias": "/.*sdd1.*/", + "color": "#65C5DB" + }, + { + "alias": "/.*sdd2.*/", + "color": "#F9934E" + }, + { + "alias": "/.*sdd3.*/", + "color": "#EA6460" + }, + { + "alias": "/.*sde1.*/", + "color": "#E0F9D7" + }, + { + "alias": "/.*sdd2.*/", + "color": "#FCEACA" + }, + { + "alias": "/.*sde3.*/", + "color": "#F9E2D2" + } + ], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "irate(node_disk_read_time_seconds_total{instance=~\"$node:$port\",job=~\"$job\"}[5m])", + "hide": false, + "intervalFactor": 4, + "legendFormat": "{{device}} - Read time", + "refId": "A", + "step": 8 + }, + { + "expr": "irate(node_disk_write_time_seconds_total{instance=~\"$node:$port\",job=~\"$job\"}[5m])", + "hide": false, + "intervalFactor": 2, + "legendFormat": "{{device}} - Write time", + "refId": "B", + "step": 4 + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "Disk R/W Time", + "tooltip": { + "shared": false, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "s", + "label": "Time. read (-) / write (+)", + "logBase": 1, + "max": null, + "min": null, + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": false + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "Prometheus", + "description": "", + "fill": 2, + "fillGradient": 0, + "gridPos": { + "h": 10, + "w": 12, + "x": 12, + "y": 19 + }, + "hiddenSeries": false, + "id": 35, + "legend": { + "alignAsTable": true, + "avg": true, + "current": true, + "hideZero": true, + "max": true, + "min": true, + "rightSide": false, + "show": true, + "sort": "current", + "sortDesc": true, + "total": false, + "values": true + }, + "lines": true, + "linewidth": 1, + "links": [], + "maxPerRow": 6, + "nullPointMode": "null", + "options": { + "dataLinks": [] + }, + "percentage": false, + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [ + { + "alias": "/.*sda_.*/", + "color": "#7EB26D" + }, + { + "alias": "/.*sdb_.*/", + "color": "#EAB839" + }, + { + "alias": "/.*sdc_.*/", + "color": "#6ED0E0" + }, + { + "alias": "/.*sdd_.*/", + "color": "#EF843C" + }, + { + "alias": "/.*sde_.*/", + "color": "#E24D42" + }, + { + "alias": "/.*sda1.*/", + "color": "#584477" + }, + { + "alias": "/.*sda2_.*/", + "color": "#BA43A9" + }, + { + "alias": "/.*sda3_.*/", + "color": "#F4D598" + }, + { + "alias": "/.*sdb1.*/", + "color": "#0A50A1" + }, + { + "alias": "/.*sdb2.*/", + "color": "#BF1B00" + }, + { + "alias": "/.*sdb3.*/", + "color": "#E0752D" + }, + { + "alias": "/.*sdc1.*/", + "color": "#962D82" + }, + { + "alias": "/.*sdc2.*/", + "color": "#614D93" + }, + { + "alias": "/.*sdc3.*/", + "color": "#9AC48A" + }, + { + "alias": "/.*sdd1.*/", + "color": "#65C5DB" + }, + { + "alias": "/.*sdd2.*/", + "color": "#F9934E" + }, + { + "alias": "/.*sdd3.*/", + "color": "#EA6460" + }, + { + "alias": "/.*sde1.*/", + "color": "#E0F9D7" + }, + { + "alias": "/.*sdd2.*/", + "color": "#FCEACA" + }, + { + "alias": "/.*sde3.*/", + "color": "#F9E2D2" + } + ], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "irate(node_disk_io_time_weighted_seconds_total{instance=~\"$node:$port\",job=~\"$job\"}[5m])", + "intervalFactor": 4, + "legendFormat": "{{device}} - IO time weighted", + "refId": "A", + "step": 8 + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "Disk IOs Weighted", + "tooltip": { + "shared": false, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "s", + "label": "Time", + "logBase": 1, + "max": null, + "min": "0", + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": false + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "Prometheus", + "description": "", + "fill": 2, + "fillGradient": 0, + "gridPos": { + "h": 10, + "w": 12, + "x": 0, + "y": 29 + }, + "hiddenSeries": false, + "id": 133, + "legend": { + "alignAsTable": true, + "avg": true, + "current": true, + "hideZero": true, + "max": true, + "min": true, + "rightSide": false, + "show": true, + "sort": "current", + "sortDesc": true, + "total": false, + "values": true + }, + "lines": true, + "linewidth": 1, + "links": [], + "maxPerRow": 6, + "nullPointMode": "null", + "options": { + "dataLinks": [] + }, + "percentage": false, + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [ + { + "alias": "/.*Read.*/", + "transform": "negative-Y" + }, + { + "alias": "/.*sda_.*/", + "color": "#7EB26D" + }, + { + "alias": "/.*sdb_.*/", + "color": "#EAB839" + }, + { + "alias": "/.*sdc_.*/", + "color": "#6ED0E0" + }, + { + "alias": "/.*sdd_.*/", + "color": "#EF843C" + }, + { + "alias": "/.*sde_.*/", + "color": "#E24D42" + }, + { + "alias": "/.*sda1.*/", + "color": "#584477" + }, + { + "alias": "/.*sda2_.*/", + "color": "#BA43A9" + }, + { + "alias": "/.*sda3_.*/", + "color": "#F4D598" + }, + { + "alias": "/.*sdb1.*/", + "color": "#0A50A1" + }, + { + "alias": "/.*sdb2.*/", + "color": "#BF1B00" + }, + { + "alias": "/.*sdb3.*/", + "color": "#E0752D" + }, + { + "alias": "/.*sdc1.*/", + "color": "#962D82" + }, + { + "alias": "/.*sdc2.*/", + "color": "#614D93" + }, + { + "alias": "/.*sdc3.*/", + "color": "#9AC48A" + }, + { + "alias": "/.*sdd1.*/", + "color": "#65C5DB" + }, + { + "alias": "/.*sdd2.*/", + "color": "#F9934E" + }, + { + "alias": "/.*sdd3.*/", + "color": "#EA6460" + }, + { + "alias": "/.*sde1.*/", + "color": "#E0F9D7" + }, + { + "alias": "/.*sdd2.*/", + "color": "#FCEACA" + }, + { + "alias": "/.*sde3.*/", + "color": "#F9E2D2" + } + ], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "irate(node_disk_reads_merged_total{instance=~\"$node:$port\",job=~\"$job\"}[5m])", + "intervalFactor": 2, + "legendFormat": "{{device}} - Read merged", + "refId": "C", + "step": 4 + }, + { + "expr": "irate(node_disk_writes_merged_total{instance=~\"$node:$port\",job=~\"$job\"}[5m])", + "intervalFactor": 2, + "legendFormat": "{{device}} - Write merged", + "refId": "D", + "step": 4 + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "Disk R/W Merged", + "tooltip": { + "shared": false, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "iops", + "label": "I/Os", + "logBase": 1, + "max": null, + "min": null, + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": false + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "Prometheus", + "description": "", + "fill": 3, + "fillGradient": 0, + "gridPos": { + "h": 10, + "w": 12, + "x": 12, + "y": 29 + }, + "hiddenSeries": false, + "id": 36, + "legend": { + "alignAsTable": true, + "avg": true, + "current": true, + "hideZero": true, + "max": true, + "min": true, + "rightSide": false, + "show": true, + "sort": "current", + "sortDesc": true, + "total": false, + "values": true + }, + "lines": true, + "linewidth": 1, + "links": [], + "maxPerRow": 6, + "nullPointMode": "null", + "options": { + "dataLinks": [] + }, + "percentage": false, + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [ + { + "alias": "/.*sda_.*/", + "color": "#7EB26D" + }, + { + "alias": "/.*sdb_.*/", + "color": "#EAB839" + }, + { + "alias": "/.*sdc_.*/", + "color": "#6ED0E0" + }, + { + "alias": "/.*sdd_.*/", + "color": "#EF843C" + }, + { + "alias": "/.*sde_.*/", + "color": "#E24D42" + }, + { + "alias": "/.*sda1.*/", + "color": "#584477" + }, + { + "alias": "/.*sda2_.*/", + "color": "#BA43A9" + }, + { + "alias": "/.*sda3_.*/", + "color": "#F4D598" + }, + { + "alias": "/.*sdb1.*/", + "color": "#0A50A1" + }, + { + "alias": "/.*sdb2.*/", + "color": "#BF1B00" + }, + { + "alias": "/.*sdb3.*/", + "color": "#E0752D" + }, + { + "alias": "/.*sdc1.*/", + "color": "#962D82" + }, + { + "alias": "/.*sdc2.*/", + "color": "#614D93" + }, + { + "alias": "/.*sdc3.*/", + "color": "#9AC48A" + }, + { + "alias": "/.*sdd1.*/", + "color": "#65C5DB" + }, + { + "alias": "/.*sdd2.*/", + "color": "#F9934E" + }, + { + "alias": "/.*sdd3.*/", + "color": "#EA6460" + }, + { + "alias": "/.*sde1.*/", + "color": "#E0F9D7" + }, + { + "alias": "/.*sdd2.*/", + "color": "#FCEACA" + }, + { + "alias": "/.*sde3.*/", + "color": "#F9E2D2" + } + ], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "irate(node_disk_io_time_seconds_total{instance=~\"$node:$port\",job=~\"$job\"}[5m])", + "intervalFactor": 4, + "legendFormat": "{{device}} - IO time", + "refId": "A", + "step": 8 + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "Time Spent Doing I/Os", + "tooltip": { + "shared": false, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "s", + "label": "Time", + "logBase": 1, + "max": null, + "min": "0", + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": false + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "Prometheus", + "description": "", + "fill": 2, + "fillGradient": 0, + "gridPos": { + "h": 10, + "w": 12, + "x": 0, + "y": 39 + }, + "hiddenSeries": false, + "id": 34, + "legend": { + "alignAsTable": true, + "avg": true, + "current": true, + "hideZero": true, + "max": true, + "min": true, + "rightSide": false, + "show": true, + "sort": "current", + "sortDesc": true, + "total": false, + "values": true + }, + "lines": true, + "linewidth": 1, + "links": [], + "maxPerRow": 6, + "nullPointMode": "null", + "options": { + "dataLinks": [] + }, + "percentage": false, + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [ + { + "alias": "/.*sda_.*/", + "color": "#7EB26D" + }, + { + "alias": "/.*sdb_.*/", + "color": "#EAB839" + }, + { + "alias": "/.*sdc_.*/", + "color": "#6ED0E0" + }, + { + "alias": "/.*sdd_.*/", + "color": "#EF843C" + }, + { + "alias": "/.*sde_.*/", + "color": "#E24D42" + }, + { + "alias": "/.*sda1.*/", + "color": "#584477" + }, + { + "alias": "/.*sda2_.*/", + "color": "#BA43A9" + }, + { + "alias": "/.*sda3_.*/", + "color": "#F4D598" + }, + { + "alias": "/.*sdb1.*/", + "color": "#0A50A1" + }, + { + "alias": "/.*sdb2.*/", + "color": "#BF1B00" + }, + { + "alias": "/.*sdb3.*/", + "color": "#E0752D" + }, + { + "alias": "/.*sdc1.*/", + "color": "#962D82" + }, + { + "alias": "/.*sdc2.*/", + "color": "#614D93" + }, + { + "alias": "/.*sdc3.*/", + "color": "#9AC48A" + }, + { + "alias": "/.*sdd1.*/", + "color": "#65C5DB" + }, + { + "alias": "/.*sdd2.*/", + "color": "#F9934E" + }, + { + "alias": "/.*sdd3.*/", + "color": "#EA6460" + }, + { + "alias": "/.*sde1.*/", + "color": "#E0F9D7" + }, + { + "alias": "/.*sdd2.*/", + "color": "#FCEACA" + }, + { + "alias": "/.*sde3.*/", + "color": "#F9E2D2" + } + ], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "irate(node_disk_io_now{instance=~\"$node:$port\",job=~\"$job\"}[5m])", + "intervalFactor": 4, + "legendFormat": "{{device}} - IO now", + "refId": "A", + "step": 8 + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "Disk IOs Current in Progress", + "tooltip": { + "shared": false, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "iops", + "label": "I/Os", + "logBase": 1, + "max": null, + "min": "0", + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": false + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "Prometheus", + "description": "", + "fill": 2, + "fillGradient": 0, + "gridPos": { + "h": 10, + "w": 12, + "x": 12, + "y": 39 + }, + "hiddenSeries": false, + "id": 66, + "legend": { + "alignAsTable": true, + "avg": true, + "current": true, + "hideZero": false, + "max": true, + "min": true, + "show": true, + "total": false, + "values": true + }, + "lines": true, + "linewidth": 1, + "links": [], + "maxPerRow": 6, + "nullPointMode": "null", + "options": { + "dataLinks": [] + }, + "percentage": false, + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [ + { + "alias": "/.*sda_.*/", + "color": "#7EB26D" + }, + { + "alias": "/.*sdb_.*/", + "color": "#EAB839" + }, + { + "alias": "/.*sdc_.*/", + "color": "#6ED0E0" + }, + { + "alias": "/.*sdd_.*/", + "color": "#EF843C" + }, + { + "alias": "/.*sde_.*/", + "color": "#E24D42" + }, + { + "alias": "/.*sda1.*/", + "color": "#584477" + }, + { + "alias": "/.*sda2_.*/", + "color": "#B7DBAB" + }, + { + "alias": "/.*sda3_.*/", + "color": "#F4D598" + }, + { + "alias": "/.*sdb1.*/", + "color": "#0A50A1" + }, + { + "alias": "/.*sdb2.*/", + "color": "#BF1B00" + }, + { + "alias": "/.*sdb3.*/", + "color": "#E0752D" + }, + { + "alias": "/.*sdc1.*/", + "color": "#962D82" + }, + { + "alias": "/.*sdc2.*/", + "color": "#614D93" + }, + { + "alias": "/.*sdc3.*/", + "color": "#9AC48A" + }, + { + "alias": "/.*sdd1.*/", + "color": "#65C5DB" + }, + { + "alias": "/.*sdd2.*/", + "color": "#F9934E" + }, + { + "alias": "/.*sdd3.*/", + "color": "#EA6460" + }, + { + "alias": "/.*sde1.*/", + "color": "#E0F9D7" + }, + { + "alias": "/.*sdd2.*/", + "color": "#FCEACA" + }, + { + "alias": "/.*sde3.*/", + "color": "#F9E2D2" + } + ], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "node_textfile_scrape_error{instance=~\"$node:$port\",job=~\"$job\"}", + "intervalFactor": 4, + "legendFormat": "Textfile scrape error (1 = true)", + "refId": "A", + "step": 8 + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "Open Error File", + "tooltip": { + "shared": false, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "short", + "label": "Errors", + "logBase": 1, + "max": null, + "min": "0", + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": false + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + } + ], + "repeat": null, + "title": "Storage Disk", + "type": "row" + }, + { + "collapsed": true, + "datasource": "Prometheus", + "gridPos": { + "h": 1, + "w": 24, + "x": 0, + "y": 75 + }, + "id": 271, + "panels": [ + { + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "Prometheus", + "decimals": 3, + "description": "", + "fill": 2, + "fillGradient": 0, + "gridPos": { + "h": 10, + "w": 12, + "x": 0, + "y": 14 + }, + "hiddenSeries": false, + "id": 43, + "legend": { + "alignAsTable": true, + "avg": true, + "current": true, + "max": true, + "min": true, + "rightSide": false, + "show": true, + "total": false, + "values": true + }, + "lines": true, + "linewidth": 1, + "links": [], + "maxPerRow": 6, + "nullPointMode": "null", + "options": { + "dataLinks": [] + }, + "percentage": false, + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "node_filesystem_avail_bytes{instance=~\"$node:$port\",job=~\"$job\",device!~'rootfs'}", + "format": "time_series", + "hide": false, + "intervalFactor": 2, + "legendFormat": "{{mountpoint}} - Available", + "metric": "", + "refId": "A", + "step": 4 + }, + { + "expr": "node_filesystem_free_bytes{instance=~\"$node:$port\",job=~\"$job\",device!~'rootfs'}", + "format": "time_series", + "hide": true, + "intervalFactor": 2, + "legendFormat": "{{mountpoint}} - Free", + "refId": "B", + "step": 2 + }, + { + "expr": "node_filesystem_size_bytes{instance=~\"$node:$port\",job=~\"$job\",device!~'rootfs'}", + "format": "time_series", + "hide": true, + "intervalFactor": 2, + "legendFormat": "{{mountpoint}} - Size", + "refId": "D", + "step": 2 + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "Filesystem space available", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "bytes", + "label": "Bytes", + "logBase": 1, + "max": null, + "min": "0", + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": false + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "Prometheus", + "description": "", + "fill": 2, + "fillGradient": 0, + "gridPos": { + "h": 10, + "w": 12, + "x": 12, + "y": 14 + }, + "hiddenSeries": false, + "id": 41, + "legend": { + "alignAsTable": true, + "avg": true, + "current": true, + "hideZero": true, + "max": true, + "min": true, + "rightSide": false, + "show": true, + "total": false, + "values": true + }, + "lines": true, + "linewidth": 1, + "links": [], + "nullPointMode": "null", + "options": { + "dataLinks": [] + }, + "percentage": false, + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "node_filesystem_files_free{instance=~\"$node:$port\",job=~\"$job\",device!~'rootfs'}", + "format": "time_series", + "hide": false, + "intervalFactor": 2, + "legendFormat": "{{mountpoint}} - Free file nodes", + "refId": "B", + "step": 4 + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "File Nodes Free", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "short", + "label": "File Nodes", + "logBase": 1, + "max": null, + "min": "0", + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": false + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "Prometheus", + "description": "", + "fill": 2, + "fillGradient": 0, + "gridPos": { + "h": 10, + "w": 12, + "x": 0, + "y": 24 + }, + "hiddenSeries": false, + "id": 28, + "legend": { + "alignAsTable": true, + "avg": true, + "current": true, + "max": true, + "min": true, + "show": true, + "total": false, + "values": true + }, + "lines": true, + "linewidth": 1, + "links": [], + "maxPerRow": 6, + "nullPointMode": "null", + "options": { + "dataLinks": [] + }, + "percentage": false, + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "node_filefd_maximum{instance=~\"$node:$port\",job=~\"$job\"}", + "format": "time_series", + "intervalFactor": 4, + "legendFormat": "Max open files", + "refId": "A", + "step": 8 + }, + { + "expr": "node_filefd_allocated{instance=~\"$node:$port\",job=~\"$job\"}", + "format": "time_series", + "intervalFactor": 2, + "legendFormat": "Open files", + "refId": "B", + "step": 4 + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "File Descriptor", + "tooltip": { + "shared": false, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "short", + "label": "Files", + "logBase": 1, + "max": null, + "min": "0", + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": false + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "Prometheus", + "description": "", + "fill": 2, + "fillGradient": 0, + "gridPos": { + "h": 10, + "w": 12, + "x": 12, + "y": 24 + }, + "hiddenSeries": false, + "id": 219, + "legend": { + "alignAsTable": true, + "avg": true, + "current": true, + "hideZero": true, + "max": true, + "min": true, + "rightSide": false, + "show": true, + "total": false, + "values": true + }, + "lines": true, + "linewidth": 1, + "links": [], + "nullPointMode": "null", + "options": { + "dataLinks": [] + }, + "percentage": false, + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "node_filesystem_files{instance=~\"$node:$port\",job=~\"$job\",device!~'rootfs'}", + "format": "time_series", + "hide": false, + "intervalFactor": 2, + "legendFormat": "{{mountpoint}} - File nodes total", + "refId": "A", + "step": 4 + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "File Nodes Size", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "short", + "label": "File Nodes", + "logBase": 1, + "max": null, + "min": "0", + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": false + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": { + "/ ReadOnly": "#890F02" + }, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "Prometheus", + "decimals": null, + "description": "", + "fill": 2, + "fillGradient": 0, + "gridPos": { + "h": 10, + "w": 12, + "x": 0, + "y": 34 + }, + "hiddenSeries": false, + "id": 44, + "legend": { + "alignAsTable": true, + "avg": true, + "current": true, + "hideEmpty": true, + "hideZero": true, + "max": true, + "min": true, + "rightSide": false, + "show": true, + "total": false, + "values": true + }, + "lines": true, + "linewidth": 1, + "links": [], + "maxPerRow": 6, + "nullPointMode": "null", + "options": { + "dataLinks": [] + }, + "percentage": false, + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [], + "spaceLength": 10, + "stack": true, + "steppedLine": false, + "targets": [ + { + "expr": "node_filesystem_readonly{instance=~\"$node:$port\",job=~\"$job\",device!~'rootfs'}", + "format": "time_series", + "intervalFactor": 2, + "legendFormat": "{{mountpoint}} - ReadOnly", + "refId": "C", + "step": 4 + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "Filesystem in ReadOnly", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "short", + "label": "Read Only", + "logBase": 1, + "max": "1", + "min": "0", + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": false + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + } + ], + "repeat": null, + "title": "Storage Filesystem", + "type": "row" + }, + { + "collapsed": true, + "datasource": "Prometheus", + "gridPos": { + "h": 1, + "w": 24, + "x": 0, + "y": 76 + }, + "id": 272, + "panels": [ + { + "aliasColors": { + "receive_packets_eth0": "#7EB26D", + "receive_packets_lo": "#E24D42", + "transmit_packets_eth0": "#7EB26D", + "transmit_packets_lo": "#E24D42" + }, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "Prometheus", + "fill": 2, + "fillGradient": 0, + "gridPos": { + "h": 10, + "w": 12, + "x": 0, + "y": 15 + }, + "hiddenSeries": false, + "id": 60, + "legend": { + "alignAsTable": true, + "avg": true, + "current": true, + "max": true, + "min": true, + "rightSide": false, + "show": true, + "sideWidth": 300, + "total": false, + "values": true + }, + "lines": true, + "linewidth": 1, + "links": [], + "nullPointMode": "null", + "options": { + "dataLinks": [] + }, + "percentage": false, + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [ + { + "alias": "/.*Trans.*/", + "transform": "negative-Y" + } + ], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "irate(node_network_receive_packets_total{instance=~\"$node:$port\",job=~\"$job\"}[5m])", + "format": "time_series", + "intervalFactor": 2, + "legendFormat": "{{device}} - Receive", + "refId": "O", + "step": 4 + }, + { + "expr": "irate(node_network_transmit_packets_total{instance=~\"$node:$port\",job=~\"$job\"}[5m])", + "format": "time_series", + "intervalFactor": 2, + "legendFormat": "{{device}} - Transmit", + "refId": "P", + "step": 4 + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "Network Traffic by Packets", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "pps", + "label": "Packets out (-) / in (+)", + "logBase": 1, + "max": null, + "min": null, + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": false + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "Prometheus", + "fill": 2, + "fillGradient": 0, + "gridPos": { + "h": 10, + "w": 12, + "x": 12, + "y": 15 + }, + "hiddenSeries": false, + "id": 142, + "legend": { + "alignAsTable": true, + "avg": true, + "current": true, + "hideEmpty": false, + "hideZero": false, + "max": true, + "min": true, + "rightSide": false, + "show": true, + "sideWidth": 300, + "sort": "current", + "sortDesc": true, + "total": false, + "values": true + }, + "lines": true, + "linewidth": 1, + "links": [], + "nullPointMode": "null", + "options": { + "dataLinks": [] + }, + "percentage": false, + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [ + { + "alias": "/.*Trans.*/", + "transform": "negative-Y" + } + ], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "irate(node_network_receive_errs_total{instance=~\"$node:$port\",job=~\"$job\"}[5m])", + "format": "time_series", + "intervalFactor": 2, + "legendFormat": "{{device}} - Receive errors", + "refId": "E", + "step": 4 + }, + { + "expr": "irate(node_network_transmit_errs_total{instance=~\"$node:$port\",job=~\"$job\"}[5m])", + "format": "time_series", + "intervalFactor": 2, + "legendFormat": "{{device}} - Rransmit errors", + "refId": "F", + "step": 4 + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "Network Traffic Errors", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "pps", + "label": "Packets out (-) / in (+)", + "logBase": 1, + "max": null, + "min": null, + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": false + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "Prometheus", + "fill": 2, + "fillGradient": 0, + "gridPos": { + "h": 10, + "w": 12, + "x": 0, + "y": 25 + }, + "hiddenSeries": false, + "id": 143, + "legend": { + "alignAsTable": true, + "avg": true, + "current": true, + "hideEmpty": false, + "hideZero": false, + "max": true, + "min": true, + "rightSide": false, + "show": true, + "sideWidth": 300, + "sort": "current", + "sortDesc": true, + "total": false, + "values": true + }, + "lines": true, + "linewidth": 1, + "links": [], + "nullPointMode": "null", + "options": { + "dataLinks": [] + }, + "percentage": false, + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [ + { + "alias": "/.*Trans.*/", + "transform": "negative-Y" + } + ], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "irate(node_network_receive_drop_total{instance=~\"$node:$port\",job=~\"$job\"}[5m])", + "format": "time_series", + "intervalFactor": 2, + "legendFormat": "{{device}} - Receive drop", + "refId": "G", + "step": 4 + }, + { + "expr": "irate(node_network_transmit_drop_total{instance=~\"$node:$port\",job=~\"$job\"}[5m])", + "format": "time_series", + "intervalFactor": 2, + "legendFormat": "{{device}} - Transmit drop", + "refId": "H", + "step": 4 + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "Network Traffic Drop", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "pps", + "label": "Packets out (-) / in (+)", + "logBase": 1, + "max": null, + "min": null, + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": false + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "Prometheus", + "fill": 2, + "fillGradient": 0, + "gridPos": { + "h": 10, + "w": 12, + "x": 12, + "y": 25 + }, + "hiddenSeries": false, + "id": 141, + "legend": { + "alignAsTable": true, + "avg": true, + "current": true, + "hideEmpty": false, + "hideZero": false, + "max": true, + "min": true, + "rightSide": false, + "show": true, + "sideWidth": 300, + "sort": "current", + "sortDesc": true, + "total": false, + "values": true + }, + "lines": true, + "linewidth": 1, + "links": [], + "nullPointMode": "null", + "options": { + "dataLinks": [] + }, + "percentage": false, + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [ + { + "alias": "/.*Trans.*/", + "transform": "negative-Y" + } + ], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "irate(node_network_receive_compressed_total{instance=~\"$node:$port\",job=~\"$job\"}[5m])", + "format": "time_series", + "intervalFactor": 2, + "legendFormat": "{{device}} - Receive compressed", + "refId": "C", + "step": 4 + }, + { + "expr": "irate(node_network_transmit_compressed_total{instance=~\"$node:$port\",job=~\"$job\"}[5m])", + "format": "time_series", + "intervalFactor": 2, + "legendFormat": "{{device}} - Transmit compressed", + "refId": "D", + "step": 4 + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "Network Traffic Compressed", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "pps", + "label": "Packets out (-) / in (+)", + "logBase": 1, + "max": null, + "min": null, + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": false + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "Prometheus", + "fill": 2, + "fillGradient": 0, + "gridPos": { + "h": 10, + "w": 12, + "x": 0, + "y": 35 + }, + "hiddenSeries": false, + "id": 146, + "legend": { + "alignAsTable": true, + "avg": true, + "current": true, + "hideEmpty": false, + "hideZero": false, + "max": true, + "min": true, + "rightSide": false, + "show": true, + "sideWidth": 300, + "sort": "current", + "sortDesc": true, + "total": false, + "values": true + }, + "lines": true, + "linewidth": 1, + "links": [], + "nullPointMode": "null", + "options": { + "dataLinks": [] + }, + "percentage": false, + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [ + { + "alias": "/.*Trans.*/", + "transform": "negative-Y" + } + ], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "irate(node_network_receive_multicast_total{instance=~\"$node:$port\",job=~\"$job\"}[5m])", + "format": "time_series", + "intervalFactor": 2, + "legendFormat": "{{device}} - Receive multicast", + "refId": "M", + "step": 4 + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "Network Traffic Multicast", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "pps", + "label": "Packets out (-) / in (+)", + "logBase": 1, + "max": null, + "min": null, + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": false + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "Prometheus", + "fill": 2, + "fillGradient": 0, + "gridPos": { + "h": 10, + "w": 12, + "x": 12, + "y": 35 + }, + "hiddenSeries": false, + "id": 144, + "legend": { + "alignAsTable": true, + "avg": true, + "current": true, + "hideEmpty": false, + "hideZero": false, + "max": true, + "min": true, + "rightSide": false, + "show": true, + "sideWidth": 300, + "sort": "current", + "sortDesc": true, + "total": false, + "values": true + }, + "lines": true, + "linewidth": 1, + "links": [], + "nullPointMode": "null", + "options": { + "dataLinks": [] + }, + "percentage": false, + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [ + { + "alias": "/.*Trans.*/", + "transform": "negative-Y" + } + ], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "irate(node_network_receive_fifo_total{instance=~\"$node:$port\",job=~\"$job\"}[5m])", + "format": "time_series", + "intervalFactor": 2, + "legendFormat": "{{device}} - Receive fifo", + "refId": "I", + "step": 4 + }, + { + "expr": "irate(node_network_transmit_fifo_total{instance=~\"$node:$port\",job=~\"$job\"}[5m])", + "format": "time_series", + "intervalFactor": 2, + "legendFormat": "{{device}} - Transmit fifo", + "refId": "J", + "step": 4 + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "Network Traffic Fifo", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "pps", + "label": "Packets out (-) / in (+)", + "logBase": 1, + "max": null, + "min": null, + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": false + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "Prometheus", + "fill": 2, + "fillGradient": 0, + "gridPos": { + "h": 10, + "w": 12, + "x": 0, + "y": 45 + }, + "hiddenSeries": false, + "id": 145, + "legend": { + "alignAsTable": true, + "avg": true, + "current": true, + "hideEmpty": false, + "hideZero": false, + "max": true, + "min": true, + "rightSide": false, + "show": true, + "sideWidth": 300, + "sort": "current", + "sortDesc": true, + "total": false, + "values": true + }, + "lines": true, + "linewidth": 1, + "links": [], + "nullPointMode": "null", + "options": { + "dataLinks": [] + }, + "percentage": false, + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [ + { + "alias": "/.*Trans.*/", + "transform": "negative-Y" + } + ], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "irate(node_network_receive_frame_total{instance=~\"$node:$port\",job=~\"$job\"}[5m])", + "format": "time_series", + "hide": false, + "intervalFactor": 2, + "legendFormat": "{{device}} - Receive frame", + "refId": "K", + "step": 4 + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "Network Traffic Frame", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "pps", + "label": "Packets out (-) / in (+)", + "logBase": 1, + "max": null, + "min": null, + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": false + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "Prometheus", + "fill": 2, + "fillGradient": 0, + "gridPos": { + "h": 10, + "w": 12, + "x": 12, + "y": 45 + }, + "hiddenSeries": false, + "id": 231, + "legend": { + "alignAsTable": true, + "avg": true, + "current": true, + "hideEmpty": false, + "hideZero": false, + "max": true, + "min": true, + "rightSide": false, + "show": true, + "sideWidth": 300, + "sort": "current", + "sortDesc": true, + "total": false, + "values": true + }, + "lines": true, + "linewidth": 1, + "links": [], + "nullPointMode": "null", + "options": { + "dataLinks": [] + }, + "percentage": false, + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "irate(node_network_transmit_carrier_total{instance=~\"$node:$port\",job=~\"$job\"}[5m])", + "format": "time_series", + "intervalFactor": 2, + "legendFormat": "{{device}} - Statistic transmit_carrier", + "refId": "C", + "step": 4 + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "Network Traffic Carrier", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "short", + "label": "Counter", + "logBase": 1, + "max": null, + "min": null, + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": false + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "Prometheus", + "fill": 2, + "fillGradient": 0, + "gridPos": { + "h": 10, + "w": 12, + "x": 0, + "y": 55 + }, + "hiddenSeries": false, + "id": 232, + "legend": { + "alignAsTable": true, + "avg": true, + "current": true, + "hideEmpty": false, + "hideZero": false, + "max": true, + "min": true, + "rightSide": false, + "show": true, + "sideWidth": 300, + "sort": "current", + "sortDesc": true, + "total": false, + "values": true + }, + "lines": true, + "linewidth": 1, + "links": [], + "nullPointMode": "null", + "options": { + "dataLinks": [] + }, + "percentage": false, + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [ + { + "alias": "/.*Trans.*/", + "transform": "negative-Y" + } + ], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "irate(node_network_transmit_colls_total{instance=~\"$node:$port\",job=~\"$job\"}[5m])", + "format": "time_series", + "intervalFactor": 2, + "legendFormat": "{{device}} - Transmit colls", + "refId": "C", + "step": 4 + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "Network Traffic Colls", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "short", + "label": "Counter", + "logBase": 1, + "max": null, + "min": null, + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": false + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "Prometheus", + "fill": 2, + "fillGradient": 0, + "gridPos": { + "h": 10, + "w": 12, + "x": 12, + "y": 55 + }, + "hiddenSeries": false, + "id": 61, + "legend": { + "alignAsTable": true, + "avg": true, + "current": true, + "max": true, + "min": true, + "rightSide": false, + "show": true, + "total": false, + "values": true + }, + "lines": true, + "linewidth": 1, + "links": [], + "nullPointMode": "null", + "options": { + "dataLinks": [] + }, + "percentage": false, + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [ + { + "alias": "NF conntrack limit", + "color": "#890F02", + "fill": 0 + } + ], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "node_nf_conntrack_entries{instance=~\"$node:$port\",job=~\"$job\"}", + "format": "time_series", + "intervalFactor": 2, + "legendFormat": "NF conntrack entries", + "refId": "O", + "step": 4 + }, + { + "expr": "node_nf_conntrack_entries_limit{instance=~\"$node:$port\",job=~\"$job\"}", + "format": "time_series", + "intervalFactor": 2, + "legendFormat": "NF conntrack limit", + "refId": "P", + "step": 4 + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "NF Contrack", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "short", + "label": "Entries", + "logBase": 1, + "max": null, + "min": "0", + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": false + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "Prometheus", + "fill": 2, + "fillGradient": 0, + "gridPos": { + "h": 10, + "w": 12, + "x": 0, + "y": 65 + }, + "hiddenSeries": false, + "id": 230, + "legend": { + "alignAsTable": true, + "avg": true, + "current": true, + "max": true, + "min": true, + "rightSide": false, + "show": true, + "total": false, + "values": true + }, + "lines": true, + "linewidth": 1, + "links": [], + "nullPointMode": "null", + "options": { + "dataLinks": [] + }, + "percentage": false, + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "node_arp_entries{instance=~\"$node:$port\",job=~\"$job\"}", + "format": "time_series", + "intervalFactor": 2, + "legendFormat": "{{ device }} - ARP entries", + "refId": "O", + "step": 4 + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "ARP Entries", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "short", + "label": "Entries", + "logBase": 1, + "max": null, + "min": "0", + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": false + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "Prometheus", + "fill": 2, + "fillGradient": 0, + "gridPos": { + "h": 10, + "w": 12, + "x": 12, + "y": 65 + }, + "hiddenSeries": false, + "id": 288, + "legend": { + "alignAsTable": true, + "avg": true, + "current": true, + "max": true, + "min": true, + "rightSide": false, + "show": true, + "total": false, + "values": true + }, + "lines": true, + "linewidth": 1, + "links": [], + "nullPointMode": "null", + "options": { + "dataLinks": [] + }, + "percentage": false, + "pointradius": 1, + "points": false, + "renderer": "flot", + "seriesOverrides": [], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "node_network_mtu_bytes{instance=~\"$node:$port\",job=~\"$job\"}", + "format": "time_series", + "intervalFactor": 2, + "legendFormat": "{{ device }} - Bytes", + "refId": "O", + "step": 4 + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "MTU", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "decimals": 0, + "format": "bytes", + "label": "Bytes", + "logBase": 1, + "max": null, + "min": "0", + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": false + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "Prometheus", + "fill": 2, + "fillGradient": 0, + "gridPos": { + "h": 10, + "w": 12, + "x": 0, + "y": 75 + }, + "hiddenSeries": false, + "id": 280, + "legend": { + "alignAsTable": true, + "avg": true, + "current": true, + "max": true, + "min": true, + "rightSide": false, + "show": true, + "total": false, + "values": true + }, + "lines": true, + "linewidth": 1, + "links": [], + "nullPointMode": "null", + "options": { + "dataLinks": [] + }, + "percentage": false, + "pointradius": 1, + "points": false, + "renderer": "flot", + "seriesOverrides": [], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "node_network_speed_bytes{instance=~\"$node:$port\",job=~\"$job\"}", + "format": "time_series", + "intervalFactor": 2, + "legendFormat": "{{ device }} - Speed", + "refId": "O", + "step": 4 + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "Speed", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "decimals": 0, + "format": "bytes", + "label": "Bytes", + "logBase": 1, + "max": null, + "min": "0", + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": false + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "Prometheus", + "fill": 2, + "fillGradient": 0, + "gridPos": { + "h": 10, + "w": 12, + "x": 12, + "y": 75 + }, + "hiddenSeries": false, + "id": 289, + "legend": { + "alignAsTable": true, + "avg": true, + "current": true, + "max": true, + "min": true, + "rightSide": false, + "show": true, + "total": false, + "values": true + }, + "lines": true, + "linewidth": 1, + "links": [], + "nullPointMode": "null", + "options": { + "dataLinks": [] + }, + "percentage": false, + "pointradius": 1, + "points": false, + "renderer": "flot", + "seriesOverrides": [], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "node_network_transmit_queue_length{instance=~\"$node:$port\",job=~\"$job\"}", + "format": "time_series", + "intervalFactor": 2, + "legendFormat": "{{ device }} - Interface transmit queue length", + "refId": "O", + "step": 4 + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "Queue Length", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "decimals": 0, + "format": "none", + "label": "Packets", + "logBase": 1, + "max": null, + "min": "0", + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": false + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "Prometheus", + "fill": 2, + "fillGradient": 0, + "gridPos": { + "h": 10, + "w": 12, + "x": 12, + "y": 85 + }, + "hiddenSeries": false, + "id": 290, + "legend": { + "alignAsTable": true, + "avg": true, + "current": true, + "hideEmpty": false, + "hideZero": false, + "max": true, + "min": true, + "rightSide": false, + "show": true, + "sideWidth": 300, + "sort": "current", + "sortDesc": true, + "total": false, + "values": true + }, + "lines": true, + "linewidth": 1, + "links": [], + "nullPointMode": "null", + "options": { + "dataLinks": [] + }, + "percentage": false, + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "node_network_up{operstate=\"up\",instance=~\"$node:$port\",job=~\"$job\"}", + "format": "time_series", + "intervalFactor": 2, + "legendFormat": "{{interface}} - Operational state UP", + "refId": "C", + "step": 4 + }, + { + "expr": "node_network_carrier{instance=~\"$node:$port\",job=~\"$job\"}", + "format": "time_series", + "instant": false, + "legendFormat": "{{device}} - Physical link state", + "refId": "A" + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "Network Operational Status", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "short", + "label": "Counter", + "logBase": 1, + "max": null, + "min": null, + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": false + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + } + ], + "repeat": null, + "title": "Network Traffic", + "type": "row" + }, + { + "collapsed": true, + "datasource": "Prometheus", + "gridPos": { + "h": 1, + "w": 24, + "x": 0, + "y": 77 + }, + "id": 273, + "panels": [ + { + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "Prometheus", + "fill": 2, + "fillGradient": 0, + "gridPos": { + "h": 10, + "w": 12, + "x": 0, + "y": 16 + }, + "hiddenSeries": false, + "id": 63, + "legend": { + "alignAsTable": true, + "avg": true, + "current": true, + "hideEmpty": false, + "hideZero": false, + "max": true, + "min": true, + "rightSide": false, + "show": true, + "sideWidth": 300, + "total": false, + "values": true + }, + "lines": true, + "linewidth": 1, + "links": [], + "nullPointMode": "null", + "options": { + "dataLinks": [] + }, + "percentage": false, + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "node_sockstat_TCP_alloc{instance=~\"$node:$port\",job=~\"$job\"}", + "format": "time_series", + "intervalFactor": 2, + "legendFormat": "TCP_alloc - Allocated sockets", + "refId": "D", + "step": 240 + }, + { + "expr": "node_sockstat_TCP_inuse{instance=~\"$node:$port\",job=~\"$job\"}", + "format": "time_series", + "intervalFactor": 2, + "legendFormat": "TCP_inuse - Tcp sockets currently in use", + "refId": "E", + "step": 240 + }, + { + "expr": "node_sockstat_TCP_mem{instance=~\"$node:$port\",job=~\"$job\"}", + "format": "time_series", + "intervalFactor": 2, + "legendFormat": "TCP_mem - Used memory for tcp", + "refId": "F", + "step": 240 + }, + { + "expr": "node_sockstat_TCP_orphan{instance=~\"$node:$port\",job=~\"$job\"}", + "format": "time_series", + "intervalFactor": 2, + "legendFormat": "TCP_orphan - Orphan sockets", + "refId": "H", + "step": 240 + }, + { + "expr": "node_sockstat_TCP_tw{instance=~\"$node:$port\",job=~\"$job\"}", + "format": "time_series", + "intervalFactor": 2, + "legendFormat": "TCP_tw - Sockets wating close", + "refId": "I", + "step": 240 + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "Sockstat TCP", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "short", + "label": "Counter", + "logBase": 1, + "max": null, + "min": "0", + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": false + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "Prometheus", + "fill": 2, + "fillGradient": 0, + "gridPos": { + "h": 10, + "w": 12, + "x": 12, + "y": 16 + }, + "hiddenSeries": false, + "id": 124, + "legend": { + "alignAsTable": true, + "avg": true, + "current": true, + "hideEmpty": false, + "hideZero": false, + "max": true, + "min": true, + "rightSide": false, + "show": true, + "sideWidth": 300, + "total": false, + "values": true + }, + "lines": true, + "linewidth": 1, + "links": [], + "nullPointMode": "null", + "options": { + "dataLinks": [] + }, + "percentage": false, + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "node_sockstat_UDPLITE_inuse{instance=~\"$node:$port\",job=~\"$job\"}", + "format": "time_series", + "intervalFactor": 2, + "legendFormat": "UDPLITE_inuse - Udplite sockets currently in use", + "refId": "J", + "step": 240 + }, + { + "expr": "node_sockstat_UDP_inuse{instance=~\"$node:$port\",job=~\"$job\"}", + "format": "time_series", + "intervalFactor": 2, + "legendFormat": "UDP_inuse - Udp sockets currently in use", + "refId": "K", + "step": 240 + }, + { + "expr": "node_sockstat_UDP_mem{instance=~\"$node:$port\",job=~\"$job\"}", + "format": "time_series", + "intervalFactor": 2, + "legendFormat": "UDP_mem - Used memory for udp", + "refId": "L", + "step": 240 + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "Sockstat UDP", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "short", + "label": "Counter", + "logBase": 1, + "max": null, + "min": "0", + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": false + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "Prometheus", + "fill": 2, + "fillGradient": 0, + "gridPos": { + "h": 10, + "w": 12, + "x": 0, + "y": 26 + }, + "hiddenSeries": false, + "id": 126, + "legend": { + "alignAsTable": true, + "avg": true, + "current": true, + "hideEmpty": false, + "hideZero": false, + "max": true, + "min": true, + "rightSide": false, + "show": true, + "sideWidth": 300, + "total": false, + "values": true + }, + "lines": true, + "linewidth": 1, + "links": [], + "nullPointMode": "null", + "options": { + "dataLinks": [] + }, + "percentage": false, + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "node_sockstat_sockets_used{instance=~\"$node:$port\",job=~\"$job\"}", + "format": "time_series", + "intervalFactor": 2, + "legendFormat": "Sockets_used - Sockets currently in use", + "refId": "N", + "step": 240 + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "Sockstat Used", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "short", + "label": "Sockets", + "logBase": 1, + "max": null, + "min": "0", + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": false + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "Prometheus", + "fill": 2, + "fillGradient": 0, + "gridPos": { + "h": 10, + "w": 12, + "x": 12, + "y": 26 + }, + "hiddenSeries": false, + "id": 220, + "legend": { + "alignAsTable": true, + "avg": true, + "current": true, + "hideEmpty": false, + "hideZero": false, + "max": true, + "min": true, + "rightSide": false, + "show": true, + "sideWidth": 300, + "total": false, + "values": true + }, + "lines": true, + "linewidth": 1, + "links": [], + "nullPointMode": "null", + "options": { + "dataLinks": [] + }, + "percentage": false, + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "node_sockstat_TCP_mem_bytes{instance=~\"$node:$port\",job=~\"$job\"}", + "format": "time_series", + "intervalFactor": 2, + "legendFormat": "TCP_mem_bytes - ", + "refId": "G", + "step": 240 + }, + { + "expr": "node_sockstat_UDP_mem_bytes{instance=~\"$node:$port\",job=~\"$job\"}", + "format": "time_series", + "intervalFactor": 2, + "legendFormat": "UDP_mem_bytes - ", + "refId": "A", + "step": 240 + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "Sockstat Memory Size", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "bytes", + "label": "Bytes", + "logBase": 1, + "max": null, + "min": "0", + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": false + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "Prometheus", + "fill": 2, + "fillGradient": 0, + "gridPos": { + "h": 10, + "w": 12, + "x": 0, + "y": 36 + }, + "hiddenSeries": false, + "id": 125, + "legend": { + "alignAsTable": true, + "avg": true, + "current": true, + "hideEmpty": false, + "hideZero": false, + "max": true, + "min": true, + "rightSide": false, + "show": true, + "sideWidth": 300, + "total": false, + "values": true + }, + "lines": true, + "linewidth": 1, + "links": [], + "nullPointMode": "null", + "options": { + "dataLinks": [] + }, + "percentage": false, + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "node_sockstat_FRAG_inuse{instance=~\"$node:$port\",job=~\"$job\"}", + "format": "time_series", + "intervalFactor": 2, + "legendFormat": "FRAG_inuse - Frag sockets currently in use", + "refId": "A", + "step": 240 + }, + { + "expr": "node_sockstat_FRAG_memory{instance=~\"$node:$port\",job=~\"$job\"}", + "format": "time_series", + "intervalFactor": 2, + "legendFormat": "FRAG_memory - Used memory for frag", + "refId": "B", + "step": 240 + }, + { + "expr": "node_sockstat_RAW_inuse{instance=~\"$node:$port\",job=~\"$job\"}", + "format": "time_series", + "intervalFactor": 2, + "legendFormat": "RAW_inuse - Raw sockets currently in use", + "refId": "C", + "step": 240 + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "Sockstat FRAG / RAW", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "short", + "label": "Sockets", + "logBase": 1, + "max": null, + "min": "0", + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": false + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + } + ], + "repeat": null, + "title": "Network Sockstat", + "type": "row" + }, + { + "collapsed": true, + "datasource": "Prometheus", + "gridPos": { + "h": 1, + "w": 24, + "x": 0, + "y": 78 + }, + "id": 274, + "panels": [ + { + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "Prometheus", + "fill": 2, + "fillGradient": 0, + "gridPos": { + "h": 10, + "w": 12, + "x": 0, + "y": 17 + }, + "height": "", + "hiddenSeries": false, + "id": 221, + "legend": { + "alignAsTable": true, + "avg": true, + "current": true, + "hideEmpty": false, + "hideZero": false, + "max": true, + "min": true, + "rightSide": false, + "show": true, + "sideWidth": 300, + "sort": "current", + "sortDesc": true, + "total": false, + "values": true + }, + "lines": true, + "linewidth": 1, + "links": [], + "maxPerRow": 12, + "nullPointMode": "null", + "options": { + "dataLinks": [] + }, + "percentage": false, + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [ + { + "alias": "/.*Out.*/", + "transform": "negative-Y" + } + ], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "irate(node_netstat_IpExt_InOctets{instance=~\"$node:$port\",job=~\"$job\"}[5m])", + "format": "time_series", + "intervalFactor": 2, + "legendFormat": "InOctets - Received octets", + "refId": "K", + "step": 4 + }, + { + "expr": "irate(node_netstat_IpExt_OutOctets{instance=~\"$node:$port\",job=~\"$job\"}[5m])", + "format": "time_series", + "intervalFactor": 2, + "legendFormat": "OutOctets - Sent octets", + "refId": "Q", + "step": 4 + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "Netstat IP In / Out Octets", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "short", + "label": "Octects out (-) / in (+)", + "logBase": 1, + "max": null, + "min": null, + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": false + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "Prometheus", + "fill": 2, + "fillGradient": 0, + "gridPos": { + "h": 10, + "w": 12, + "x": 12, + "y": 17 + }, + "height": "", + "hiddenSeries": false, + "id": 81, + "legend": { + "alignAsTable": true, + "avg": true, + "current": true, + "hideEmpty": false, + "hideZero": false, + "max": true, + "min": true, + "rightSide": false, + "show": true, + "sideWidth": 300, + "sort": "current", + "sortDesc": true, + "total": false, + "values": true + }, + "lines": true, + "linewidth": 1, + "links": [], + "nullPointMode": "null", + "options": { + "dataLinks": [] + }, + "percentage": false, + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "irate(node_netstat_Ip_Forwarding{instance=~\"$node:$port\",job=~\"$job\"}[5m])", + "format": "time_series", + "intervalFactor": 2, + "legendFormat": "Forwarding - IP forwarding", + "refId": "D", + "step": 4 + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "Netstat IP Forwarding", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "short", + "label": "Datagrams", + "logBase": 1, + "max": null, + "min": "0", + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": false + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "Prometheus", + "decimals": null, + "fill": 2, + "fillGradient": 0, + "gridPos": { + "h": 10, + "w": 12, + "x": 0, + "y": 27 + }, + "height": "", + "hiddenSeries": false, + "id": 115, + "legend": { + "alignAsTable": true, + "avg": true, + "current": true, + "hideZero": false, + "max": true, + "min": true, + "rightSide": false, + "show": true, + "sort": "current", + "sortDesc": true, + "total": false, + "values": true + }, + "lines": true, + "linewidth": 1, + "links": [], + "maxPerRow": 12, + "nullPointMode": "null", + "options": { + "dataLinks": [] + }, + "percentage": false, + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [ + { + "alias": "/.*Out.*/", + "transform": "negative-Y" + } + ], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "irate(node_netstat_Icmp_InMsgs{instance=~\"$node:$port\",job=~\"$job\"}[5m])", + "format": "time_series", + "intervalFactor": 2, + "legendFormat": "InMsgs - Messages which the entity received. Note that this counter includes all those counted by icmpInErrors", + "refId": "J", + "step": 4 + }, + { + "expr": "irate(node_netstat_Icmp_OutMsgs{instance=~\"$node:$port\",job=~\"$job\"}[5m])", + "format": "time_series", + "intervalFactor": 2, + "legendFormat": "OutMsgs - Messages which this entity attempted to send. Note that this counter includes all those counted by icmpOutErrors", + "refId": "W", + "step": 4 + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "ICMP In / Out", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "short", + "label": "Messages out (-) / in (+)", + "logBase": 1, + "max": null, + "min": null, + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": false + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "Prometheus", + "decimals": null, + "fill": 2, + "fillGradient": 0, + "gridPos": { + "h": 10, + "w": 12, + "x": 12, + "y": 27 + }, + "height": "", + "hiddenSeries": false, + "id": 50, + "legend": { + "alignAsTable": true, + "avg": true, + "current": true, + "hideZero": false, + "max": true, + "min": true, + "rightSide": false, + "show": true, + "sort": "current", + "sortDesc": true, + "total": false, + "values": true + }, + "lines": true, + "linewidth": 1, + "links": [], + "maxPerRow": 12, + "nullPointMode": "null", + "options": { + "dataLinks": [] + }, + "percentage": false, + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [ + { + "alias": "/.*Out.*/", + "transform": "negative-Y" + } + ], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "irate(node_netstat_Icmp_InErrors{instance=~\"$node:$port\",job=~\"$job\"}[5m])", + "format": "time_series", + "intervalFactor": 2, + "legendFormat": "InErrors - Messages which the entity received but determined as having ICMP-specific errors (bad ICMP checksums, bad length, etc.)", + "refId": "I", + "step": 4 + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "ICMP Errors", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "short", + "label": "Messages out (-) / in (+)", + "logBase": 1, + "max": null, + "min": null, + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": false + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "Prometheus", + "decimals": null, + "fill": 2, + "fillGradient": 0, + "gridPos": { + "h": 10, + "w": 12, + "x": 0, + "y": 37 + }, + "height": "", + "hiddenSeries": false, + "id": 55, + "legend": { + "alignAsTable": true, + "avg": true, + "current": true, + "hideZero": false, + "max": true, + "min": true, + "rightSide": false, + "show": true, + "sort": "current", + "sortDesc": true, + "total": false, + "values": true + }, + "lines": true, + "linewidth": 1, + "links": [], + "maxPerRow": 12, + "nullPointMode": "null", + "options": { + "dataLinks": [] + }, + "percentage": false, + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [ + { + "alias": "/.*Out.*/", + "transform": "negative-Y" + }, + { + "alias": "/.*Snd.*/", + "transform": "negative-Y" + } + ], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "irate(node_netstat_Udp_InDatagrams{instance=~\"$node:$port\",job=~\"$job\"}[5m])", + "format": "time_series", + "intervalFactor": 2, + "legendFormat": "InDatagrams - Datagrams received", + "refId": "B", + "step": 4 + }, + { + "expr": "irate(node_netstat_Udp_OutDatagrams{instance=~\"$node:$port\",job=~\"$job\"}[5m])", + "format": "time_series", + "intervalFactor": 2, + "legendFormat": "OutDatagrams - Datagrams sent", + "refId": "E", + "step": 4 + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "UDP In / Out", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "short", + "label": "Datagrams out (-) / in (+)", + "logBase": 1, + "max": null, + "min": null, + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": false + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "Prometheus", + "fill": 2, + "fillGradient": 0, + "gridPos": { + "h": 10, + "w": 12, + "x": 12, + "y": 37 + }, + "height": "", + "hiddenSeries": false, + "id": 109, + "legend": { + "alignAsTable": true, + "avg": true, + "current": true, + "hideZero": false, + "max": true, + "min": true, + "rightSide": false, + "show": true, + "sort": "current", + "sortDesc": true, + "total": false, + "values": true + }, + "lines": true, + "linewidth": 1, + "links": [], + "maxPerRow": 12, + "nullPointMode": "null", + "options": { + "dataLinks": [] + }, + "percentage": false, + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "irate(node_netstat_Udp_InErrors{instance=~\"$node:$port\",job=~\"$job\"}[5m])", + "format": "time_series", + "intervalFactor": 2, + "legendFormat": "InErrors - UDP Datagrams that could not be delivered to an application", + "refId": "C", + "step": 4 + }, + { + "expr": "irate(node_netstat_Udp_NoPorts{instance=~\"$node:$port\",job=~\"$job\"}[5m])", + "format": "time_series", + "intervalFactor": 2, + "legendFormat": "NoPorts - UDP Datagrams received on a port with no listener", + "refId": "B", + "step": 4 + }, + { + "expr": "irate(node_netstat_UdpLite_InErrors{instance=~\"$node:$port\",job=~\"$job\"}[5m])", + "legendFormat": "InErrors Lite - UDPLite Datagrams that could not be delivered to an application", + "refId": "A" + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "UDP Errors", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "short", + "label": "Datagrams out (-) / in (+)", + "logBase": 1, + "max": null, + "min": null, + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": false + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "Prometheus", + "decimals": null, + "fill": 2, + "fillGradient": 0, + "gridPos": { + "h": 10, + "w": 12, + "x": 0, + "y": 47 + }, + "height": "", + "hiddenSeries": false, + "id": 299, + "legend": { + "alignAsTable": true, + "avg": true, + "current": true, + "hideZero": false, + "max": true, + "min": true, + "rightSide": false, + "show": true, + "sort": "current", + "sortDesc": true, + "total": false, + "values": true + }, + "lines": true, + "linewidth": 1, + "links": [], + "maxPerRow": 12, + "nullPointMode": "null", + "options": { + "dataLinks": [] + }, + "percentage": false, + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [ + { + "alias": "/.*Out.*/", + "transform": "negative-Y" + }, + { + "alias": "/.*Snd.*/", + "transform": "negative-Y" + } + ], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "irate(node_netstat_Tcp_InSegs{instance=~\"$node:$port\",job=~\"$job\"}[5m])", + "format": "time_series", + "intervalFactor": 2, + "legendFormat": "InSegs - Segments received, including those received in error. This count includes segments received on currently established connections", + "refId": "B", + "step": 4 + }, + { + "expr": "irate(node_netstat_Tcp_OutSegs{instance=~\"$node:$port\",job=~\"$job\"}[5m])", + "format": "time_series", + "intervalFactor": 2, + "legendFormat": "OutSegs - Segments sent, including those on current connections but excluding those containing only retransmitted octets", + "refId": "E", + "step": 4 + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "TCP In / Out", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "short", + "label": "Datagrams out (-) / in (+)", + "logBase": 1, + "max": null, + "min": null, + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": false + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "Prometheus", + "description": "", + "fill": 2, + "fillGradient": 0, + "gridPos": { + "h": 10, + "w": 12, + "x": 12, + "y": 47 + }, + "height": "", + "hiddenSeries": false, + "id": 104, + "legend": { + "alignAsTable": true, + "avg": true, + "current": true, + "hideEmpty": false, + "hideZero": false, + "max": true, + "min": true, + "rightSide": false, + "show": true, + "sort": "current", + "sortDesc": true, + "total": false, + "values": true + }, + "lines": true, + "linewidth": 1, + "links": [], + "maxPerRow": 12, + "nullPointMode": "null", + "options": { + "dataLinks": [] + }, + "percentage": false, + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "irate(node_netstat_TcpExt_ListenOverflows{instance=~\"$node:$port\",job=~\"$job\"}[5m])", + "format": "time_series", + "intervalFactor": 2, + "legendFormat": "ListenOverflows - Times the listen queue of a socket overflowed", + "refId": "I", + "step": 4 + }, + { + "expr": "irate(node_netstat_TcpExt_ListenDrops{instance=~\"$node:$port\",job=~\"$job\"}[5m])", + "format": "time_series", + "intervalFactor": 2, + "legendFormat": "ListenDrops - SYNs to LISTEN sockets ignored", + "refId": "A", + "step": 4 + }, + { + "expr": "irate(node_netstat_TcpExt_TCPSynRetrans{instance=~\"$node:$port\",job=~\"$job\"}[5m])", + "format": "time_series", + "intervalFactor": 2, + "legendFormat": "TCPSynRetrans - SYN-SYN/ACK retransmits to break down retransmissions in SYN, fast/timeout retransmits", + "refId": "B", + "step": 4 + }, + { + "expr": "irate(node_netstat_Tcp_RetransSegs{instance=~\"$node:$port\",job=~\"$job\"}[5m])", + "legendFormat": "RetransSegs - Segments retransmitted - that is, the number of TCP segments transmitted containing one or more previously transmitted octets", + "refId": "C" + }, + { + "expr": "irate(node_netstat_Tcp_InErrs{instance=~\"$node:$port\",job=~\"$job\"}[5m])", + "legendFormat": "InErrs - Segments received in error (e.g., bad TCP checksums)", + "refId": "D" + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "TCP Errors", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "short", + "label": "Counter", + "logBase": 1, + "max": null, + "min": "0", + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": false + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "Prometheus", + "fill": 2, + "fillGradient": 0, + "gridPos": { + "h": 10, + "w": 12, + "x": 0, + "y": 57 + }, + "height": "", + "hiddenSeries": false, + "id": 85, + "legend": { + "alignAsTable": true, + "avg": true, + "current": true, + "hideZero": false, + "max": true, + "min": true, + "rightSide": false, + "show": true, + "sortDesc": true, + "total": false, + "values": true + }, + "lines": true, + "linewidth": 1, + "links": [], + "maxPerRow": 12, + "nullPointMode": "null", + "options": { + "dataLinks": [] + }, + "percentage": false, + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [ + { + "alias": "/.*MaxConn *./", + "color": "#890F02", + "fill": 0 + } + ], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "node_netstat_Tcp_CurrEstab{instance=~\"$node:$port\",job=~\"$job\"}", + "format": "time_series", + "hide": false, + "intervalFactor": 2, + "legendFormat": "CurrEstab - TCP connections for which the current state is either ESTABLISHED or CLOSE- WAIT", + "refId": "C", + "step": 4 + }, + { + "expr": "node_netstat_Tcp_MaxConn{instance=~\"$node:$port\",job=~\"$job\"}", + "format": "time_series", + "hide": false, + "intervalFactor": 2, + "legendFormat": "MaxConn - Limit on the total number of TCP connections the entity can support (Dinamic is \"-1\")", + "refId": "H", + "step": 4 + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "TCP Connections", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "short", + "label": "Connections", + "logBase": 1, + "max": null, + "min": "0", + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": false + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "Prometheus", + "description": "", + "fill": 2, + "fillGradient": 0, + "gridPos": { + "h": 10, + "w": 12, + "x": 12, + "y": 57 + }, + "height": "", + "hiddenSeries": false, + "id": 91, + "legend": { + "alignAsTable": true, + "avg": true, + "current": true, + "hideEmpty": false, + "hideZero": false, + "max": true, + "min": true, + "rightSide": false, + "show": true, + "sort": "current", + "sortDesc": true, + "total": false, + "values": true + }, + "lines": true, + "linewidth": 1, + "links": [], + "maxPerRow": 12, + "nullPointMode": "null", + "options": { + "dataLinks": [] + }, + "percentage": false, + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [ + { + "alias": "/.*Sent.*/", + "transform": "negative-Y" + } + ], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "irate(node_netstat_TcpExt_SyncookiesFailed{instance=~\"$node:$port\",job=~\"$job\"}[5m])", + "format": "time_series", + "hide": false, + "intervalFactor": 2, + "legendFormat": "SyncookiesFailed - Invalid SYN cookies received", + "refId": "R", + "step": 4 + }, + { + "expr": "irate(node_netstat_TcpExt_SyncookiesRecv{instance=~\"$node:$port\",job=~\"$job\"}[5m])", + "format": "time_series", + "hide": false, + "intervalFactor": 2, + "legendFormat": "SyncookiesRecv - SYN cookies received", + "refId": "S", + "step": 4 + }, + { + "expr": "irate(node_netstat_TcpExt_SyncookiesSent{instance=~\"$node:$port\",job=~\"$job\"}[5m])", + "format": "time_series", + "hide": false, + "intervalFactor": 2, + "legendFormat": "SyncookiesSent - SYN cookies sent", + "refId": "T", + "step": 4 + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "TCP SynCookie", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "short", + "label": "Counter out (-) / in (+)", + "logBase": 1, + "max": null, + "min": null, + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": false + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "Prometheus", + "fill": 2, + "fillGradient": 0, + "gridPos": { + "h": 10, + "w": 12, + "x": 0, + "y": 67 + }, + "height": "", + "hiddenSeries": false, + "id": 82, + "legend": { + "alignAsTable": true, + "avg": true, + "current": true, + "hideZero": false, + "max": true, + "min": true, + "rightSide": false, + "show": true, + "sortDesc": true, + "total": false, + "values": true + }, + "lines": true, + "linewidth": 1, + "links": [], + "maxPerRow": 12, + "nullPointMode": "null", + "options": { + "dataLinks": [] + }, + "percentage": false, + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "irate(node_netstat_Tcp_ActiveOpens{instance=~\"$node:$port\",job=~\"$job\"}[5m])", + "format": "time_series", + "intervalFactor": 2, + "legendFormat": "ActiveOpens - TCP connections that have made a direct transition to the SYN-SENT state from the CLOSED state", + "refId": "A", + "step": 4 + }, + { + "expr": "irate(node_netstat_Tcp_PassiveOpens{instance=~\"$node:$port\",job=~\"$job\"}[5m])", + "format": "time_series", + "intervalFactor": 2, + "legendFormat": "PassiveOpens - TCP connections that have made a direct transition to the SYN-RCVD state from the LISTEN state", + "refId": "K", + "step": 4 + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "TCP Direct Transition", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "short", + "label": "Connections", + "logBase": 1, + "max": null, + "min": "0", + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": false + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + } + ], + "repeat": null, + "title": "Network Netstat", + "type": "row" + }, + { + "collapsed": true, + "datasource": "Prometheus", + "gridPos": { + "h": 1, + "w": 24, + "x": 0, + "y": 79 + }, + "id": 279, + "panels": [ + { + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "Prometheus", + "description": "", + "fill": 2, + "fillGradient": 0, + "gridPos": { + "h": 10, + "w": 12, + "x": 0, + "y": 24 + }, + "hiddenSeries": false, + "id": 40, + "legend": { + "alignAsTable": true, + "avg": true, + "current": true, + "max": true, + "min": true, + "show": true, + "total": false, + "values": true + }, + "lines": true, + "linewidth": 1, + "links": [], + "nullPointMode": "null", + "options": { + "dataLinks": [] + }, + "percentage": false, + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [], + "spaceLength": 10, + "stack": true, + "steppedLine": false, + "targets": [ + { + "expr": "node_scrape_collector_duration_seconds{instance=~\"$node:$port\",job=~\"$job\"}", + "format": "time_series", + "hide": false, + "intervalFactor": 2, + "legendFormat": "{{collector}} - Scrape duration", + "refId": "A", + "step": 4 + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "Node Exporter Scrape Time", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "s", + "label": "Seconds", + "logBase": 1, + "max": null, + "min": null, + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": false + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "Prometheus", + "description": "", + "fill": 2, + "fillGradient": 0, + "gridPos": { + "h": 10, + "w": 12, + "x": 12, + "y": 24 + }, + "hiddenSeries": false, + "id": 157, + "legend": { + "alignAsTable": true, + "avg": true, + "current": true, + "max": true, + "min": true, + "show": true, + "total": false, + "values": true + }, + "lines": true, + "linewidth": 1, + "links": [], + "nullPointMode": "null", + "options": { + "dataLinks": [] + }, + "percentage": false, + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "node_scrape_collector_success{instance=~\"$node:$port\",job=~\"$job\"}", + "format": "time_series", + "hide": false, + "intervalFactor": 2, + "legendFormat": "{{collector}} - Scrape success", + "refId": "A", + "step": 4 + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "Node Exporter Scrape Success", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "short", + "label": "Counter", + "logBase": 1, + "max": null, + "min": null, + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": false + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + } + ], + "repeat": null, + "title": "Node Exporter", + "type": "row" + } + ], + "refresh": false, + "schemaVersion": 21, + "style": "dark", + "tags": [], + "templating": { + "list": [ + { + "current": { + "text": "Prometheus", + "value": "Prometheus" + }, + "hide": 0, + "includeAll": false, + "label": "datasource", + "multi": false, + "name": "DS_PROMETHEUS", + "options": [], + "query": "prometheus", + "refresh": 1, + "regex": "", + "skipUrlSync": false, + "type": "datasource" + }, + { + "allValue": null, + "current": { + "text": "nodeexporter", + "value": "nodeexporter" + }, + "datasource": "Prometheus", + "definition": "", + "hide": 0, + "includeAll": false, + "label": "Job", + "multi": false, + "name": "job", + "options": [], + "query": "label_values(node_uname_info, job)", + "refresh": 1, + "regex": "", + "skipUrlSync": false, + "sort": 1, + "tagValuesQuery": "", + "tags": [], + "tagsQuery": "", + "type": "query", + "useTags": false + }, + { + "allValue": null, + "current": { + "text": "hamsterbacke", + "value": "hamsterbacke" + }, + "datasource": "Prometheus", + "definition": "", + "hide": 0, + "includeAll": false, + "label": "Host:", + "multi": false, + "name": "name", + "options": [], + "query": "label_values(node_uname_info{job=~\"$job\"}, nodename)", + "refresh": 1, + "regex": "", + "skipUrlSync": false, + "sort": 1, + "tagValuesQuery": "", + "tags": [], + "tagsQuery": "", + "type": "query", + "useTags": false + }, + { + "allValue": null, + "current": { + "text": "hamsterbacke.ctu.cx", + "value": "hamsterbacke.ctu.cx" + }, + "datasource": "Prometheus", + "definition": "", + "hide": 2, + "includeAll": false, + "label": "Host:", + "multi": false, + "name": "node", + "options": [], + "query": "label_values(node_uname_info{nodename=\"$name\"}, instance)", + "refresh": 1, + "regex": "/([^:]+):.*/", + "skipUrlSync": false, + "sort": 1, + "tagValuesQuery": "", + "tags": [], + "tagsQuery": "", + "type": "query", + "useTags": false + }, + { + "allValue": null, + "current": { + "text": "80", + "value": "80" + }, + "datasource": "Prometheus", + "definition": "", + "hide": 0, + "includeAll": false, + "label": "Port", + "multi": false, + "name": "port", + "options": [], + "query": "label_values(node_uname_info{instance=~\"$node:(.*)\"}, instance)", + "refresh": 1, + "regex": "/[^:]+:(.*)/", + "skipUrlSync": false, + "sort": 3, + "tagValuesQuery": "", + "tags": [], + "tagsQuery": "", + "type": "query", + "useTags": false + } + ] + }, + "time": { + "from": "now-24h", + "to": "now" + }, + "timepicker": { + "refresh_intervals": [ + "5s", + "10s", + "30s", + "1m", + "5m", + "15m", + "30m", + "1h", + "2h", + "1d" + ], + "time_options": [ + "5m", + "15m", + "1h", + "6h", + "12h", + "24h", + "2d", + "7d", + "30d" + ] + }, + "timezone": "browser", + "title": "Node Exporter", + "uid": "rYdddlPWk", + "version": 2 +} diff --git a/services/monitoring/default.nix b/services/monitoring/default.nix new file mode 100644 index 0000000..1b67046 --- /dev/null +++ b/services/monitoring/default.nix @@ -0,0 +1,169 @@ +{ enableACME, forceSSL, ... }: + Service "Monitoring with grafana and prometheus" + { + configuration + = { core, network, secret, ... }: + let + inherit(core) string; + inherit(network) domain hostName ips tcp; + inherit(tcp) ports; + hostDomain = "${hostName}.${domain}"; + + allowedIPs + = string.concatMappedLines + (ip: "allow ${ip};") + ips; + + extraConfig + = '' + ${allowedIPs} + deny all; + ''; + + nginxConfigHost + = { + inherit enableACME extraConfig forceSSL; + locations + = { + "/metrics/nginx" + = { + inherit extraConfig; + proxyPass = "http://localhost:${string ports.exporters.nginx}/metrics"; + }; + "/metrics/node" + = { + inherit extraConfig; + proxyPass = "http://localhost:${string ports.exporters.node}/metrics"; + }; + }; + }; + + nginxConfigGrafana + = { + inherit enableACME forceSSL; + locations."/" + = { + proxyPass = "http://localhost:${string ports.grafana}/"; + }; + }; + + nginxConfigPrometheus + = { + inherit enableACME extraConfig forceSSL; + locations."/" + = { + inherit extraConfig; + proxyPass = "http://localhost:${string ports.prometheus}/"; + proxyWebsockets = true; + }; + }; + settings + = { + "auth.anonymous" + = { + enabled = true; + }; + security + = { + admin_user = "admin"; + admin_password = secret.decryptGrafanaSecret' ./admin.asc; + }; + server + = { + domain = "grafana.${domain}"; + http_port = ports.grafana; + root_url = "https://grafana.${domain}/"; + }; + }; + in + { + grafana + = { + enable = true; + provision + = { + enable = true; + dashboards + = { + path = ./dashboards; + }; + datasources.settings.datasources + = [ + { + isDefault + = true; + name = "Prometheus"; + type = "prometheus"; + url = "https://prometheus.${domain}/"; + } + ]; + }; + inherit settings; + }; + + journald.extraConfig + = '' + MaxFileSec="6h" + MaxRetentionSec="3day" + ''; + + nginx.virtualHosts + = { + ${hostDomain} = nginxConfigHost; + "grafana.${domain}" = nginxConfigGrafana; + "prometheus.${domain}"= nginxConfigPrometheus; + }; + + prometheus + = { + checkConfig = "syntax-only"; + enable = true; + exporters + = { + nginx + = { + enable = true; + port = ports.exporters.nginx; + }; + node + = { + enable = true; + port = ports.exporters.node; + }; + }; + scrapeConfigs + = [ + { + job_name = "nginx"; + metrics_path = "/metrics/nginx"; + scheme = "https"; + scrape_interval + = "30s"; + static_configs + = [ + { + targets + = [ hostDomain ]; + } + ]; + } + { + job_name = "node"; + metrics_path = "/metrics/node"; + scheme = "https"; + scrape_interval + = "30s"; + static_configs + = [ + { + targets + = [ hostDomain ]; + } + ]; + } + ]; + }; + + vnstat.enable = true; + }; + } diff --git a/services/nginx/default.nix b/services/nginx/default.nix new file mode 100644 index 0000000..7722b5a --- /dev/null +++ b/services/nginx/default.nix @@ -0,0 +1,237 @@ +{ commonHttpConfig, enableACME, extraConfig, forceSSL, ... }: + Service "Nginx: HTTP-Server" + { + configuration + = { config, core, network, store, web, ... }: + let + inherit(core) debug list path set string type; + inherit(network) allowLegacyTLS domain hostName ips tcp; + inherit(store) write; + inherit(tcp.ports) exporters; + + websites + = let + importWebsite + = value: + type.matchPrimitiveOrPanic value + { + lambda = value { inherit core store web; } { inherit domain hostName; }; + null = {}; + path = importWebsite (path.import value); + set = value; + }; + in + importWebsite (path.import ./hosts).${hostName}; + + allowedIPs + = string.concatMappedLines + (ip: "allow ${ip};") + ips; + + locations + = let + extraConfig + = '' + ${allowedIPs} + deny all; + ''; + in + { + "/metrics/nginx" + = { + inherit extraConfig; + proxyPass = "http://localhost:${string exporters.nginx}/metrics"; + }; + "/metrics/node" + = { + inherit extraConfig; + proxyPass = "http://localhost:${string exporters.node}/metrics"; + }; + }; + + comments + = { + Acknowledgments = "Our security acknowledgments page"; + Canonical = "Canonical URI for this file"; + Contact = "Our security address"; + Encryption = "Our OpenPGP key"; + Expires = "DO NOT USE this security.txt after this date"; + Hiring = "Open job-positions"; + Policy = "Our security policy"; + Preferred-Languages = "Preferred Languages for security reports"; + }; + + sign + = message: + signature: + let + text = string.concatLines (message ++ [ "" ]); + result + = string.concatLines + ( + [ "-----BEGIN PGP SIGNED MESSAGE-----" "Hash: SHA256\n" ] + ++ message + ++ [ "-----BEGIN PGP SIGNATURE-----\n" ] + ++ [ (string.trim signature) ] + ++ [ "-----END PGP SIGNATURE-----\n" ] + ); + in + debug.panic "sign" + { + text + = '' + Missing signature for message, run: + cat ${path.toFile "message" text} | gpg --clearsign | tail -n 14 | head -n -1 + ''; + when = signature == null; + nice = true; + } + debug.info "sign" + { + text + = '' + Please verify this signed message: + cat ${path.toFile "message" result} | gpg --verify + ''; + } + result; + + mapLocation + = domain: + location: + { + index ? "index.html", + redirect ? null, + root ? null, + tryFiles ? "$uri $uri.html $uri.txt $uri.asc /index.html", + well-known ? {}, + ... + }: + let + foo + = string.replace' + { + "\t" = "_"; + "\n" = "_"; + "\r" = "_"; + " " = "_"; + "@" = "-at-"; + "/" = "-"; + }; + directory + = write.directory (foo (if location == "/" then domain else "${domain}${location}")) + ( + set.map + ( + fileName: + page: + if path.isInstanceOf page + then + "${page}" + else + path.toFile (foo fileName) "${page}" + ) + root + // canary-txt + // security-txt + ); + + canary-txt + = let + inherit(well-known."canary.txt") body signature; + in + set.ifOrEmpty (well-known."canary.txt" or {} != {}) + { + ".well-known/canary.txt" + = path.toFile "canary.txt" (sign body signature); + }; + + security-txt + = let + inherit(well-known."security.txt") body signature; + format + = name: + value: + [ "" "# ${comments.${name}}" ] + ++ ( + if list.isInstanceOf value + then + list.map + ( "${name}: ${value}" ) + value + else + [ "${name}: ${value}" ] + ); + in + set.ifOrEmpty (well-known."security.txt" or {} != {}) + { + ".well-known/security.txt" + = path.toFile "security.txt" + ( + sign + (list.tail (list.concat (set.mapToList format body))) + signature + ); + }; + in + if root != null + then + { + inherit index tryFiles; + root = "${directory}"; + } + else if redirect != null + then + { + return = "301 ${redirect}"; + } + else + debug.panic + "mapLocation" + "Either root or redirect must be set!"; + + sslProtocols + = if allowLegacyTLS + then + "TLSv1.2 TLSv1.3" + else + "TLSv1.3"; + in + { + nginx + = { + inherit commonHttpConfig sslProtocols; + enable = true; + recommendedGzipSettings = true; + recommendedOptimisation = true; + recommendedProxySettings = true; + recommendedTlsSettings = true; + statusPage = true; + virtualHosts + = set.mapNamesAndValues + ( + subdomain: + locations': + let + fqdn + = if subdomain != "" + then + "${subdomain}.${domain}" + else + domain; + in + { + name = fqdn; + value + = { + inherit enableACME extraConfig forceSSL; + locations + = locations + // (set.map (mapLocation fqdn) locations'); + }; + } + ) + websites; + }; + }; + } diff --git a/services/nginx/hosts/aleph/canary.txt.nix b/services/nginx/hosts/aleph/canary.txt.nix new file mode 100644 index 0000000..4e5179d --- /dev/null +++ b/services/nginx/hosts/aleph/canary.txt.nix @@ -0,0 +1,90 @@ +{ core, ... }: +{ domain, ... }: + { + body + = [ + '' + # This is a canary message from _sivizius confirming their identity. + + # I hereby confirm that none of the data I am holding has been requested or seized + # by a government authority or any other third party up to this point in time: + Date: 2023-04-04T13:37:23T+0200 + + # At this point in time, the most recent Monero block hash and height are: + Monero-Block-Hash: 599f5d55dc4363aab3f9a6c2d8bbd2fc697ad8c99673e2c0479045d0c659cedf + Monero-Date-Time: 2023-04-04T13:34:19+0200 + Monero-Height: 2856851 + Monero-URL: https://localmonero.co/blocks/block/2856851 + + # At this point in time, the following article was published in Organometallics + Organometallics-Authors: J.B. Eastwood, L.A. Hammarback, T.J. Burden, I.P. Clark, et. al. + Organometallics-Date: 2023-04-03 + Organometallics-DOI: 10.1021/acs.organomet.3c00004 + Organometallics-URL: https://pubs.acs.org/doi/10.1021/acs.organomet.3c00004 + + # At this point in time, Felix von Leitner published the following post on his blog: + Fefes-Blog-Text: In der Politik lässt man keine Krise ungenutzt verstreichen, [...] + Fefes-Blog-URL: https://blog.fefe.de/?ts=9ad53c01 + + # My pronouns are in order of preference: + Pronouns: they/them, he/him + + # I own the following domains: + Domains: *.sivizius.eu + + # And the following (legacy) IP-addresses: + IP-Addresses: 2a01:4f9:c010:6bf5::23/64, 95.217.131.201 + + # You can contact me via: + Contact: sivizius@sivizius.eu + + # You can find a copy of my pgp-key here: + PGP-Key: https://${domain}/pgp + PGP-Fingerprint: 6A6A 9F7C 47BA 4CBE DCD5 CB74 7BB4 21C6 84E8 21D8 + + # This canary.txt is only valid if and only if signed with this key. + # Any new key must be signed with this key as well. + + # I own the following accounts on plattforms that are not my own: + Duolingo: sivizius + E-Mail: sivizius@ohai.su + GitHub: sivizius + Fediverse: @_sivizius@chaos.social + Reddit: u/_sivizius + Twitter: _sivizius, sivizius + + # Please note that this list of accounts is incomplete. + + # This message is subject to change. + # You can always obtain the most recent version from here: + Canoncial: https://${domain}/.well-known/canary.txt + + # Unless I forget this message will be updated not later than: + Until: 2023-04-11T13:37:23T+0200 + + # If this day and time passed without an updated message, please + # reach out to me e.g. via any of the contact options above. + # You can assume something bad has happened if this message was not + # updated in a day. + + # Have a nice day, stay hydrated! + '' + ]; + signature + = '' + iQIzBAEBCAAdFiEEamqffEe6TL7c1ct0e7QhxoToIdgFAmQsDBcACgkQe7QhxoTo + IdisRQ/+J+VQmGVW2IfqA5CE6K29Tdvy5gN+AqStLgLQYtWnfkrKT9ZtrWRthVP6 + PJZFrGLzqcysJB4/hYH2BFyNHzvVm6uT+KUSg5Ol3jHekb/oplSg1ol9gioj9cDL + Iui5YJWaN6yhG6MJYpFUh4QWVUHQoJvCKnBbScY0GpN1UmaRi7+abjjA57bdHQVa + fp6mpFHOaIv74t7LoNPGe2GxLSyTSpK/Wh0xRiI0iwgRxp26w+mWX5jWyglB1UiR + lApJo7hwaP7UY1IVaY3PkQlxayJMd8A9KgFQvR71F5npzH8r43i1AozDa2m7XnGk + Z3qlYVU1NF1J39dU1NdJZbTQJT3v3UpneoWIZxnvrI5H5+SPthSNyksG1/M32g++ + InP5+pLd6AMwdGIc3KNuEaTBm/WeGHYUvlcy1XGWn+Vk25s+WURhihFpzcgU+0I3 + mHYg3BL8upmEtpLys4gZChhx4VMNqDiAGBhbIoPT+S6BBBKtknY3RwftqZEa21W9 + lFKxjla5he6VXw+qjmjbHtIP4C4KwxuEqImggO0ip+DZlkJ8IZa8CKVrAPocZKUi + keAF5t4sI1FXmhPjNfOyd/k51Lpip5c4tr55UT+8k/bUfMMzIrptobVk13PLCVxM + Jab/ikj9C6aEk7zVEMbEMtox6JiGO87lNquPcR9gQ05cK2z/FeA= + =/3FM + ''; + } + diff --git a/services/nginx/hosts/aleph/common.css.nix b/services/nginx/hosts/aleph/common.css.nix new file mode 100644 index 0000000..5d9a434 --- /dev/null +++ b/services/nginx/hosts/aleph/common.css.nix @@ -0,0 +1,13 @@ +{ web, ... }: +{ ... }: + let + inherit(web.css) CSS; + in + CSS + { + body + = { + background.color = "#222"; + color = "#f80"; + }; + } diff --git a/services/nginx/hosts/aleph/default.nix b/services/nginx/hosts/aleph/default.nix new file mode 100644 index 0000000..4de535d --- /dev/null +++ b/services/nginx/hosts/aleph/default.nix @@ -0,0 +1,56 @@ +{ core, web, ... } @ libs: +{ domain, ... } @ env: + let + inherit(core) path; + + wwwEnv + = { + head + = { + # Metadata + author = "_sivizius"; + description = "Personal Homepage of sivizius"; + keywords = "Organometallic Chemistry, Rust, Nix/NixOS"; + title = "Sivi’s Homepage"; + + _blank = "https://sivizius.eu/"; + stylesheets + = { + "common.css" = { crossorigin = "anonymous"; referrerpolicy = "no-referrer"; }; + }; + viewport = "width=device-width, initial-scale=1.0"; + }; + }; + + well-known + = { + "canary.txt" = path.import ./canary.txt.nix libs env; + "security.txt" = path.import ./security.txt.nix libs env; + }; + + www + = { + "/" + = { + inherit well-known; + root + = { + "common.css" = path.import ./common.css.nix libs wwwEnv; + "index.html" = path.import ./index.html.nix libs wwwEnv; + "resume.html" = path.import ./resume.html.nix libs wwwEnv; + "pgp.asc" = ./pgp.asc; + }; + }; + "/fasm".redirect = "https://github.com/sivizius/dirtycow.fasm"; + "/js".redirect = "https://github.com/sivizius/scihubify"; + "/latex".redirect = "https://github.com/sivizius/nixfiles/tree/development/NixTeX"; + "/nixfiles".redirect = "https://github.com/sivizius/nixfiles"; + "/python".redirect = "https://github.com/sivizius/ameisenRennen"; + "/rust".redirect = "https://github.com/sivizius?tab=repositories&q=&type=source&language=rust&sort="; + "/ti-konnektor".redirect = "https://github.com/sivizius/secunet_ti_konnektor_pin_calculator"; + }; + in + { + inherit www; + "" = www; + } diff --git a/services/nginx/hosts/aleph/index.html.nix b/services/nginx/hosts/aleph/index.html.nix new file mode 100644 index 0000000..d5ec4b8 --- /dev/null +++ b/services/nginx/hosts/aleph/index.html.nix @@ -0,0 +1,45 @@ +{ web, ... }: +{ head, ... }: + let + inherit(web.html) HTML; + in + HTML { language = "eng"; } + { + inherit head; + body + = with web.html; + [ + ( + main + [ + (h1 "sivizius’ website") + (h2 "Who am I?") + ( + p + '' + I am sivizius, a chemist (M.Sc.) with a focus on synthetic organometallic chemistry, + in particularly ferrocene chemistry as well as an + software developer and linux system engineer. + '' + ) + (h2 "My skills") + ( + p + '' + I have practical experience with + the usual development tools like git, + (flat)assembler, + reverse engineering of software and + I am familiar with + theoretical computer science, + cryptography, + Linux and + especially the Nix/NixOS ecosystem. + By operating my own server infrastructure with e-mail, monitoring, DNS, etc. + I was able to gain valuable experience in network and system administration. + '' + ) + ] + ) + ]; + } diff --git a/services/nginx/hosts/aleph/pgp.asc b/services/nginx/hosts/aleph/pgp.asc new file mode 100644 index 0000000..30797f6 --- /dev/null +++ b/services/nginx/hosts/aleph/pgp.asc @@ -0,0 +1,259 @@ +-----BEGIN PGP PUBLIC KEY BLOCK----- + +mQINBFcpD10BEAC/p479Wezsjoh0t/8B7hZLdY9nxvqJ5FItKU8VBBfbCw3OzWy4 +/Nncnu6FGSaRsx4HmLT7zIdgtdwLTMWGvoxvicPPaWmpLVOAwZAbkI3FpQKUbsd5 +AwLDyKj3oiQWDlRuvpdWDWdn2da6qXl9D+LbwAONVEp7h3adpFBk+v7nYp0WUq5J +WImjDlWnoQGaKH9yUa68vGcDnHoePnB96tiX08JCwQaXABG+tSvlXuCM0awVOskw +pXMcnwyEsJgk42XC8VJIhXrMnbM8qigZVKijmKxmHcWbCIPPNRXRXkxCGwIKyOIP +cj1oXDOODe0Ql5utqeoG4vXOmNHxwkdjeD190+eq02WmdBNnJOIkAJjpErcRsEIx +EndUzrAjE1GaZ3Rlf4r4MVtjaib10HsXt+Q22FpMNHDLixAhPcIe+D/MrrTN4EgW +s/ti4p16qiPUVhL96bDDQQ25ZO2kp77Jji1cduj/ZXqbuLE6epkoms2XA7AFOXXl +1B7gHvKKLPzQuGO8xgUjH/jrQLUMJ1/o/owDUBGncEKRoDPwPCDZ1e3qp9SU0m/3 +bo3y3+6O2YOH8R2yQEnHXIGXiEhKPHvwsPuOgcCwSIFMLqdHnwtdCumX6irg+QJI +NgQ/BFtFWFHtiQ09Iyg0eRmLAw6ePhVlyofLKQaPuk8yRygzQdKTEEC9NQARAQAB +tCVTZWJhc3RpYW4gV2FseiA8c2l2aXppdXNAc2l2aXppdXMuZXU+iQJXBBMBCABB +AhsDBQsJCAcCBhUKCQgLAgQWAgMBAh4BAheABQkPG4aLFiEEamqffEe6TL7c1ct0 +e7QhxoToIdgFAl6/yLcCGQEACgkQe7QhxoToIdh9aw//UijqYsHdIy7+wHvllf57 +NFUGHtcJSd7aT07If6SP/t4HahGK9SJveRqz6oT35rKM+rZElIax8gAGJwx/BsgO +Yz28b2uUIfueFVPSjBeR2Fcp1FHPodwbwtmsexjglk/P0WUHPcJb3ttXpnBMyq5v +nFkP0T4cEQIS55nxZnuwFVvZZkFiOfmk+z8b7+vOaHqDzSZlYF0i+bVqZuSnV7dT +V1/pLAG35PUPUaoJdshvN/LapcS5Gn/7930AttWJOFb3JNbnG2YUCq3J7mBsXcR+ +iUua0JeB7rQJzd4GgdkUfGeQgMWWWlof7BdmAinLGd4P6cmg9alqw0Lkf6QqK3y+ +cqgR/xEz1IPDc6nJx0L42d9SSGXg/g4IKzkqRZAF8ou9rOr9bWDGEv5IDpcBZNsc +CwU4cniwbU/3pHm2zQVt4o45qD7KlpbC/jcXeHKixCzDooJNa/2Y4eNsKm+d5u8M +d8U4lsu0/5cQa6hJvo31MzltrudSBokJKwuHqlEpZWnUcS/ONKbN2tdMkk+j56Wa +LeDJ7W3rcB2CP2BmpK+UHWhyosHzrlMpYQ7RSezwdtykv2gsp4QaBIlI0ex1J5tq +IQxSslPeTX0OeQBKLbM0oqoC7PBcdgho97iOOt4OCG2v6YHH2WhsIHk4Bh4N84jE +VLT+Uk1yDlTockQxfqYTcr20HVBvc3RtYXN0ZXIgPHJvb3RAc2l2aXppdXMuZXU+ +iQJUBBMBCAA+AhsDBQsJCAcCBhUKCQgLAgQWAgMBAh4BAheAFiEEamqffEe6TL7c +1ct0e7QhxoToIdgFAl6/x+gFCQ8bhosACgkQe7QhxoToIdjTCg//VkD+p0q6LX6i +wX1T/JgHEk6RRcMcEDaAwbATR3VUytJ8u0YBPv5IxpKCv6J/ZypP16KQdQcurKmL +Nnc6HFSumx2jctSdZInMqTV5vMMZZF5HxokPw9FhDrUKUGV54uRAwlSY0/sT9mzB +4zemClV7CAsGJwJKyOVbtGikNS4Xlujlx5MNjefRFR2+ZCMCJlFplif5L6LNH329 +9smu0d8ObEEPrgq1gVUoYdEuKqkOXNQ5lWUiBZfwmMxfGzTyinknKQT79mB9xE5J +z7tRLCkPtxmb8sahQ7FhKkOTFnsJyLYH0IxpVes/8Cs/qJePi+6fq7+0puJ1ELVB +EBCWwUIBkjUFAw6lCLKthCDSQdJ7qBpFdNsG9XRHK+Jm6E9CNhKiFsySWvKDiRUt +J1BHXLWB0e06lFT1onEEpCBdjCetEgp9fPvNrXLxE3r0yh+y6S651EZfAyMmNsoZ +vhSHKK53xblPeX177wmgt7BE9WE6Fy4+G4zlzL44H5qw2CidRcvEvZtCXx+UuvQ3 +NLGIwwh0UJ30Z91wK8DPq/XKk9o/rKGpCGqTtsRHaaLSdy96swowZ0YJfQIbpob/ +SwIrfROhEnUgViLsAKHQdi2VC+kNTv23h3k6nCMfb8dbqIZe4iaoOZkVz5x7Q8pd +5I83dumXtKKbVImpQa5iiWJd5WNeqwm0NFNlYmFzdGlhbiBXYWx6IDxzZWJhc3Rp +YW4ud2FsekBzMjAxNS50dS1jaGVtbml0ei5kZT6JAlUEEwEIAD8CGwMGCwkIBwMC +BhUIAgkKCwQWAgMBAh4BAheAFiEEamqffEe6TL7c1ct0e7QhxoToIdgFAl6/x+gF +CQ8bhosACgkQe7QhxoToIdiGDg//bOnf7KkeQ9p4Vx8sTeSHVkfdPwmv0ydV0Kdq +klXxRy6bB0qowZUM0XcOHzPrXc/Fu5O2EGeBQ2Qdrb9nXRfDXk+ZwFMu/zYxdFuY +mfziQFtxvV2UO56Tfu1kVWGFnBVwiJySUlzUaeqJtJtjwV13NC6GFOAeqt+b3y+c +b6VkLy+qAHe2vRkAVIRTe8LPsaP8366oY2anPMZ7mrMF36BaNNv6B0Dg79G0r+7R +gJ50HdaHIEIuSgTSib2cj406eNIelFlJBDlEPf2hYN4XLEWd5WpZ3MMT72jtGKAv +55C3et4b0z7zlbaNQDpED+WsbgY2+s2M/XljTrtwdCs6brj0N2MMypcqZpLdr/aV +JqJqk4QCt25oMr4SN/0ZmmzClKi16be2m31s4dNMCUB/nspOs2kAGyFSiagwROL7 +eIscUKhgVw9DD8MdAbxKDpROUS2GKzwWk8Ade3uy5QtP92gCopYqnJ8SX3THSCGv +RaiqfCkZOgf1Hc2SzsNEipcSxgO80d9alcxy1tSYA+WYU4JgVEcdce/s2GQXBR15 +NXoE7z5qGA7pH/dFgbS9O0DTAXllAnAfqWYhSy9KOTgWiLKZggcWeBBnRmaiwl8o +v8lGBnPb4SGPNdLm/ZTXIG1TgiPYeZv4eO7LLbRCZG+h4/sEyW48ZlvKmUL7aYFf +x8g6sMa0LVNlYmFzdGlhbiBXYWx6IChfc2l2aXppdXMpIDxzaXZpeml1c0BvaGFp +LnN1PokCVQQTAQgAPwIbAwYLCQgHAwIGFQgCCQoLBBYCAwECHgECF4AWIQRqap98 +R7pMvtzVy3R7tCHGhOgh2AUCXr/H6AUJDxuGiwAKCRB7tCHGhOgh2A0AD/0Ze5Fm +g6vm09W+XT3jbILT4USXbLnhpbsmsDq87msGsew4R9wgzyHIMnxYLfaxtb2+yzbv +wJ35N5XDR9UKwqSE/PsvRryQjVxivM8RVG5z5jSrqzYQ8iIwIzqLdSAwzkuuHYC3 +VwZBiKgwIRB+DHfkj+7Rq0rFMCssHSOLK0saLiqZ+mAe3BtjfO1WKZoeGAc83NDj +Y7Y46u0SAgCNUhhqcoZa7kMcspEII9R/ycTZ/urKWG6X/jkn2+ag1LilsygdHznq +Cssgm6cXtc4PtPkB8L/G5eRrm10xbksN78CNLpNfaVsPCv0n3TuY7axLIguPOjVO +XF16Z7Rrick/MgIyj8rp+N5CMR07J0rwBDW4glefl9dGbS6HFYtMGnvmLIJeHcAh +7BZfWDPsbCIuD2AntPjtEOn/hwuPwvRCwBsy4lrLcNpXwtqAEj6BCRQxCrKPa1ru +Z5gbR4t9KuOd6bRqeBT5GJsxpHvjMI05UOA9Vn6ur1RG12PZddHoH3soxGCV7yJi +khukffLPvssrDIqeto+Y5l5h9DGnWYa/wh7gdVOSFivQwZgA6G3mPZ7CseR8L4xZ +8DP8hgI/G4OYeU62EnH1/O7Is33sPaecQxAaUVP2umkZm+WV28vw5HWqjIX4KmXP +emIij43OVH4VydXNfdJZ7mqKr9soYZjB8ncT49HcIdwfARAAAQEAAAAAAAAAAAAA +AAD/2P/gABBKRklGAAEBAQFeAV4AAP/bAEMAEAsMDgwKEA4NDhIREBMYKBoYFhYY +MSMlHSg6Mz08OTM4N0BIXE5ARFdFNzhQbVFXX2JnaGc+TXF5cGR4XGVnY//bAEMB +ERISGBUYLxoaL2NCOEJjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2Nj +Y2NjY2NjY2NjY2NjY2NjY//CABEIASAA8AMBEQACEQEDEQH/xAAaAAADAQEBAQAA +AAAAAAAAAAAAAQIDBAUG/8QAGAEBAQEBAQAAAAAAAAAAAAAAAAECAwT/2gAMAwEA +AhADEAAAAenjoKKDTo1nq0AAAMYwxVLMIBEmZpLnXHqZm0azWGpx6nfzcPQxjKLN +UurgFUmMQswhCpASOAmgAEIaMBlKyhlJSoCSSSgMxCBBUAAIAASWMasYyiigRKRs +FmNlWQJYlzVQAJBQEFBJ6vPTJWBXM2FddejYiZZs8o5qtbETY0cunLZBSEc2pnQI +D6vlQzzrJIuM9SdPR06dA5jxIGmrGVWll6zzSVh63HoQiK8bc49ABH1nK55uRncR +qRTrtrs2zPEhtSorAdbazpc1ZwZnRjXdy1jnUWeTuc+jEI+p46xiLjLUVA7elO/b +y7OWaSpWrQV1pc3Zpc8hyZnsc9+fz1Fce5NAhH0nn3FxOs56IYLvZ6G3z9lzSWVa +0JLp2aWaWc8nBHo89c/PUVluRWQhnv8ADRrCsihYMk6Dv28KtreeIrddRHOkWdFd +dTHlSepz1z89RUbmZjQXL7XKVrO1mmpEebLy29knfb5exWJNmcusu1TZgdVjLryc +ve564ueoqN5ztxAuPY5zSzr3NLM5PIl42u6TsXh6MqRNmctze1hcwdFamtedJ0Tc +cbjGG5FQoly+vzzpTZmzJOdcl7JbuuPpN7MZZWSmureSJSjaqTEc1jyuGXJuTQol +y+vjOiTGFQkmq9EVq+fvW+s5SxK6utbKEWXYJK551lymMvJuTTVJcvr8sWBII6qW +qdcm9G5EsSwLU3t1KTSxoJnNThhi5Lyak05VZpHq8s0WCIYx0idWN3GoWR1tTSjW +miTDjrGUjO3n1IpKkuPS55o2FJjSGOmFulc/S5xm0mrs1ubk2q7FJhx1iqzYrLpn +Nc1EcepnOhWGacujqhDNa6Y5+tzlSoutaJKrS5MublqFWbnplvOa5gXL6mcaQszM +59XtrWhc403nROe3ntzmmXVJtYFWGbz8rmqlzMemXZK5S1L6ecaQszIz1fS1dgMw +1kTA59axJKNa0LrVMpeflVmqXKuXpOjWaTlzty+lnGkLMyM9X09XUDMnWUmK56uZ +mWaVrVlHOnkRpHXy3EvHuFMCpfSzi4UmZnq+lbsBkc1nDqedXuKhS6WaVdiUIT5/ +I1KOnGsZoBQvL0Zi4WZmZ6vp6uoGR52p4+o19uChdqqxoKxp4ebzayF2XjZnQoly ++hnFwss0z1e23QZw7nk7mcar6stWI1rSyhQya8jN5LKsRoVz6Chcd/PFiiSLKCuH +q5tGRAejNbJVaVrYwiThl8+xWIoqy8bedAR6PPLCEZ6c+phthoxkgEdS9ca6alEn +HHn2ShVDpRIy5bl9LjaTGzh6MKVAEmghDEM6DpWjKORM6aOmSABCGezw1x9JxbIA +ABFolkYAACGUiVJdImBasUSrOzDk2QAIBgMaQoAwEMARK0dMmGFKVAMAAAEAxoyF +YAdBkQACKSVqwgASoEFYAACAYxpKgAdRmYgBJokjpQAqBBQYAACABjRKhoG8sVmg +oItJogAFQCHBQMBDEAFIlQwGAgQEtIgAFAEKHSGMAEMQFIlBDAAAEStHUwwUAQoK +BjABDARQkFQwQUAESsdkygwBEJQIKoBAMESsBAMaJQARKx2TKI1EBKH/xAApEAAC +AQMEAQMFAAMAAAAAAAAAAQIDEBESEyAxIQQwQBQiMjNBIyRC/9oACAEBAAEFAt1G +6jdRuo3EU6ifOc1E3EbiNxG4jcRuIdQVQ3ESmSkaiMzWTkf2nMyZMmTImKcjckbs +jdkbsjdkOTNTMsyzLMs1M1MyamamZtkyzNs+3ngk2Si18jFseduoh6IvWOZqMeHH +3Ppz6c2DaNo2zSUaOo2KY6EGfTxJ7NEq13UPIkYNDNtn3RMJmwfTmwbBsEo444s+ +NH8bVauhPVN6UuKME6eClU0iw1gwSRX5N2zwou1SWiLzN8lZrw159LU8zeDWSmVX +l8GPlC3qZ5kvYjaQ3plVeYDHxfOAif5rrnG0yQnn04zA1zxZjkU2RZP8+lKZuCmn +ZvA6hmRFsi8lTrPmK/1hiJXjdRNBKBPwNlIh3XWK8hrA8RXgUkjMZD8Cm85+6U9F +R1TzlrHph2leNkRtJlXspGdKnOM60YaZNE1kwQRNZUjQsqJnLKtPMoLbhLtmRu8b +6sDqMcyRgplb9ePudmYEJeNJjBhXl4inmEu5D4Rux2wKIkOOqL7fBYNcY3V5dU1p +TJD4R4YMGDF6kVq/gxlPwOKbFwySlaQ+EfafklHSrpXV31/zaRjhGys2ajUajUZM +j8oZ9wos0s0sjlXfTvKzurKzHbB5tHyLwNYd1xl+N5Wd4ivI7cYmg0DgQj4aGsj4 +K6J9XlbGRwtEV5EfyjeRHqR/RmTInZWqvEE8q0rRkSYyIryIdxvITGzVFWaujF/U +/pl4I1GhNMkPhEV5EO43kZKvqBtyHdLjWjrpSeRCeHr1D4RFeRDuN5FfxTOlb+8v +UR/yXznhHgxdxkajUeorYVqfmV0+LZVeb9i4R44s3hSrSfBPDjPKyZFwbKlQbzbu ++U7ri5JDrodWcuDsm0RqiYrtk5jeXw7vqFK86kYEqsnzfBNojWaFXib8CddMlLPF +86lb2f57i51p/Fj2+/jUqaqE46ZcI9/HolX9vCPfx6bwqjTqcF381d/OffzX87+c +/wD/xAAfEQACAgMBAQADAAAAAAAAAAABEQBAECAwUCECYID/2gAIAQMBAT8B8VRY +UXvPRx9lFu48KKKLIOitg3xByNQcTVHA9HyHA1HgdRusCHC1A5qLT8cqLiKI2e4h +NF/oPyfPWNJ9DePVx3wb4vC+D4Dj/i3/xAAfEQABBAMBAAMAAAAAAAAAAAABABEg +MAIQQBIxUHD/2gAIAQIBAT8BiORtDRm6dOnTp6m+0ZMm01vpel6XpOngyZNQQnXp +el6XpCwW5YvHGwXEIjY68u7LgF2Uyhpk0RcZnYkLijI0iD1mRpF5kahbkZmoIGw8 +Qqy+NHiarKAiahoU5TbRqGhSU0BA1DQrOKIZCJra44xNQ4DA0gcJEDMIDjIoZeE3 +O2xi6GIHWEMe3Eco/W//xAAqEAABAgQEBgIDAQAAAAAAAAABACECETFAECAwURIy +QVBhgXGRImDhwf/aAAgBAQAGPwLsnMftVKqqqqr2Kl1sun+JgCmXTBrR6LlWy6qZ +Drxtmedt5UydCYXhTFlMp9IrgPqy4dtQRLzYn51CFDYxfOdgqZYbGIe8Oi5VRPFJ +SBBTL+qRn9oQkMpcEfoYQDxYTKhiAeXVRPV8nlDCamq4Mmr1s/5noMTEjYS3QGR8 +JE5pbo8VjPLLQaxkq9hqq4c369O1nEw0fYwdwmsZQfa30TDkfXOoSLHhhreTTNdu +V+Imq53sKYvXZbDTZPhVNqyg+73hHvtrmSkDexKP5vYnkSoiKE/vw0P/xAAoEAAC +AQMEAgIBBQEAAAAAAAAAAREQITEgQVFhMHGBkUChscHR8OH/2gAIAQEAAT8h7DsO +wXIPmLJJNJJJoguzsO47juO47hUZEydghihBCICWTmISJckuSRLklyNW9EF/2jsH +YOwOHMey2dh3Hcdx3HYdhLk7DsJEkjuGzomWpMkTJJobHzTEIubs5Np/DQhEUQJH +Bu7DYmkk4Pm7GYDlOxLYkpwM7TypHsaTnMjVrD5Q1MjyjqrKZc4BIW75MYvgJeWw +sC/BDaFbgEmwhimxNnEzvORA3X2hSVmSJkxstRgNIgOBwOCNEq3d8Im2nPNRFEIQ +3Om8Ei/90IhA08MgQEQQTFVjoNjDdEQWolu0NJYdIIIEqFdkwhQXc97y/ahiJjUj +DDY6ozNhSU7v2Yj0oTMhuxnInAQ88DEt+3skdwXsjQ1GOsjjWGmV7m6DolSBEjTS +0SUE8eYU/VMRSIqpSTRqiBooTImUDZuc/ZKlZwYEqdzFMTEC/DGTu7JCHKHZCXjk +g5Sb67lRE5ARA8qDWGHdEfYTaG/QjJfaRrxIfRD3SL0y3Kbhsmyjplnl6JVXtm4l +hcbxsyMm5bxCFNOdtMw0mGLktbL+1MRaOdTKCRCQ0sPJgJLlbZE45INbWS26ez3/ +AGSOTc2HAjSbyeR7sw1vwJs3db8idMhCuT9iu1KFkRMxG265IEizDujEsJK50RKg +PZcXiQcezEsHu7nUustf57Gb4+i/LZkksIkDRKEo9C5H9sT3N7lqRXzTEZjYXCUW +NrhQYGejMQqUIZNuhETBTWO7UNEChKWSSFa6dnwNuLL2G37RAkCGN70hIbCQNLl5 +MDPRnRaFFUTCHorWt7oaoSzWUxE8MGJJvkRkJUZFboW/bIzAz0ZkiYqSSSSN2IQY +wjOaMdyAUDmhUzehrDo2pgMNRXImhOg9IbqFk4sQy/gcl+gmZbLWSQjLuSRGca2g +tHISEo49xJskQE2IwjEwhliJokQles9BaOVCHQlR4Ea0sER8oQYsCEkSUUTeix1T +SgHYyoQ6rGuA4a1DLXSqRCCPmyIhjpgNwxQmDIyqdTjXAiVNup0G7HQgSEFQjL/i +47ZQ4pwSy0oxMhMmmVTqcdC1n8+xnG2jcaXJsJXoJUYhqrLx7HwTs0YDZk4YoIyM +tGWocdB5S3aVhk2Fl1TCJExiG7C+QyJ2EJlieNGQtF40HuRflrZDGKkyJ0ZOrirJ +Aic3V7CCtjRkImjoUko2EWho9ZJq5bWwqZCCoJkkiEi04GNemVsIVqLcR7NpV1yq +ZCq2Y+Qtl7OwoaaQ9kiaYaLGZGMqwroIamZoRJAife1euzqk/CkibkXN/oKlgaeA +nUvi/s7370MeTBVgyqDCJ9HJf0RbvplgkxnVVSpmLShrmwvA2QwnSdKHEIlCcuB2 ++DOXodZb1vCWDZ+JmEeRhfgIWmQ3SVhF4K2h0l+CqPL0TiNnCh/YqSlienALHiWt +UedEKSwobMiYa0bmP8JZo86Eb6bEHl+/w34d6Z/EvC9vDvTZ68S8LxRUWl0esR// +2gAMAwEAAgADAAAAEDWgwAAN1+63pa9AwBQHmpGO3YJlQpkX+kNxgNoks1kltl60 +kFt40t/rMl9nlyUzlKUeZkUlyU0+qVei4JyX3qmH7XSix364PABoSHPK6biX241V +ICo1w0xqb80e8VUZFydGtlIeYhVkpgqClbMR+NWr/FxQq7/rDgbqZW65gEfl61q8 +IQdJCtvu/Nz0fVXNaMbLIdj4pwXJnUEC+aLOlmdIhv7ARHX46qYF6WW11qPxCMYq +L1gxlLJGla0j9tNL7F9BTXSEww3cwNaj+06GTCEu1kbGPrL/ANxYPbFsoMOvAfS/ +/jaMo2LCSlFb8w4kxKBU1PEQvbQyY5vkIJh0SeDo6oyw9dDID3FulunJVyTsQv6D +cei19AldI8yCdSCBllLU86KlCUxSCZAA2BveImtvuQACPCQASNdH4uCyASAJ4SKn +MM3uqSSACQPgITJIfVtiWCACQJoIRJK/n/agARLSTqMuFIM99aRQBYQT6ABJsPth +CcQBKCD4QTJOO0gKaQACABdAUANK7BMyKASAzbAEBEA6psD/xAAfEQEAAwEAAwEB +AQEAAAAAAAABABARICEwQDFRQVD/2gAIAQMBAT8Q5fQewmxfRkyzKZmf8HfqKY2a +zWC/2AfZkyFD4mzZs1m0VWuBkT+T/FgTJkxMj2RYtvAQJlZMiUmzDxN4egixeGwh +DljTFFbyEXIvQQ6YzI8npeghDnYxp5MOFGt9G02lm+kwsipZ5mwds42DNItKTexh +ZGmMeAbE4ZD4ghEVlZNnzaQLLSKoF/qJjMsyB4jMmTI0NcgYzej0rGJvmEGmHhP2 +FLFoedhP5Do9R4ZGEKYOUxs/IHZ6homzaytjwWsLPYUZRYUbYUWw9GTJkyZWwhWW +0w5YWdZ0GDNmzZsWbRyzcscnYvZvJNhaRIEIcnTJnqYMgG8mUcnL1nTGfk/rycnK +8kes8Rtv48HOzZtLZw+n8iyDtnezeD0/kXnAyae8ZvWZHnL0Q/vjfZtaTYvJHpfk +YehflYfOuE3Tlj9r9z9z9z9zD/jf/8QAIBEBAQEBAQADAQEBAQEAAAAAAQARECAh +MDFAQVBRcf/aAAgBAgEBPxDLLLI+gzNllllklkEFkzIX+Qsssss4cddN28yyyyyy +yxYWcyw7n/K3gomLCf8AxYn2atWupBv2zoCy23vzf/b/AFJY+SW+3gRF+fC+jn5B +8z9ks+ktkEHV9JHcy3suEc8rwIPB9JDHGb8cI9BEeCPpI4zfjhHhgg4eV4z0PHwI +8hw4JzJlEcyThZBZbkzFThHkdbL1v1Hdl8HP3jfAv3EeRwbbeLN+45vGxB6fzbdL +9xHkW2222y9Dx4QW5Plgz9vmxHltttttvCL5Hks3h402/wAThHlnM8kSy05nCHy/ +Bb88bEeGCTuWWWWcfznk+kEeGJnhZZ0Nvg7fvd5vj8c/zo8iZiO5wfEnD9H55sxF +nGcEzER1vxP1DpMeHAyzwTMR5XxP1H84LP8Arg8iZiI8DEz6X84T8wnyWeRMxHk+ +cj0/sdJ++RMxHN5/u9fB52/WO6HxJngNs822+TkJ4ekeV2Dzp8ycYk4Q2P8A1BPz +p3LOHhdg+hCd/kTL/ABg8rHkRf7/ACHCfWBr/I36l+f6M8n9H56P6H0f3E/2k/3P +/FL/xAAnEAEAAgICAgEFAQEBAQEAAAABABEhMUFREGFxIIGRobHRweHw8f/aAAgB +AQABPxA6kOpDqToJjYTLCMAljZLlO5TuU7lncpgX1MWkehHoR6k9SehF6JyxLjSD +bIh3AHcUpZ7oA5jIBth2IdiHYw7EE5TRIgND6FCc3ymH/rT/APSj/wCtGUx+mI2p +9tx7Ee5HuR7ke5PYihtA3CnsRTlFNsv3KOfE2D407LlwYMHwDiQcXFRZcLYHuWxW +ru/UtlFqAiP4mWjXcfD9T9DKlQhBi8heK6i+oaLoA1fF1o9x08FBIe7Cqb5R9R2y +ByLdRqbZZA1A5QMkAb4uG0Q2DWNQ8G+E36bi4BThrL9o081K8VKlSowHUB1CNEax +pGFxhuqbK5hIojlVv7g2f5P9j2A+QlNDjFr9tHzLoB61fftiA0V6hgcmVjMM7keW +ZbuP2hRXAXsI1tcY0fiZ6weSPax72e9hVqx1TDys9EAanog6Q9IekquoAQd+VxXG +6PbD2ly2f5DEDPcCEBLXOyXYB+JqJbKz+RiGudgL8BEYDsNMeuesl/iYs8GVBFUq +89fHLBLVufFl1YAbV0RypLttuVMES4QZQjJDUYOIDyqKp9cwBO10WLN/KvzUoWsO +6XufFnllJLXxPPiswTEw0jDKD020fj+ze8seZcGDiXFMMtSZBBmC/mWNRkpmn+So +4pRNA3XqK7l5mBjY8vjc+O0CVKEyjLCxV2Kx7vX/AN14nmVcSU1BMFEANXAyJ6gQ +tX1C7As+SOyV3nlAP7GPiGCEfF6NmV4lLGvgVeA3yN3P+JKFKAjXd/l4h0pfUFCb +jriK/JxMv6YkAsE7vH/kA5S1/Vw6HLUR+BT8sZr4KPgzeZlCNsx6gFUZCLc58pwY +R3Mfj/1cuApC6RYatuHCxc0pfw/sMAQwWP8AszEGywf2RQBNiEhj2rS+jtr7fmGi +nLAA/dyqLllBAG3HBA6nS9vd5iUCjIyKwZ4/McW7hPzxiPPlF9bruIEpGnwI/RT5 +RzFklbmUrcc5lmJaNMXAgaMr0Qa9BFpKmBwluZWNhUKVnDedJnifEwaWOQ3KBTnK +Lm12sSp2LHV0Z+CBxp43Tuo6jHkV933goljdVhY4s8uue7jYhoRyrdWYXf5JUKD5 +jW21ujmZ77ZP0grWqA9Jc3RurxHym5rOAwXMwdxcoNXUpE6DYtnG4Q+UFfOoHknF +la+/wRdgfagain/32wVxFlPFfiAqqwAE2BjUwcV7GftLmK+n/aIbi2BfuX2L8xwR +/wC12okOG9XcFeu/QmzwX9DtNJpG4jIgYDEqwnWu3TxKQbEP23/JlnhzLrjT1G7c +JcEeCOQVYkIk6E5ZiUiaeYWgwKmUMZy7uWfyHGGZFH+RE2MvkSPlIolxvKwR1AJV +ERBQXIhwDn/suz+HwAqoxUNgZlAJurxcMYxUpkuBAFuiazxBUwLiC6s3vUKR4dru +KbvAfQglk0jRKkDAytQ2kqajBFJXIFR1KjBwjq8RhzQncYBrHcYx0S5+2lL+CGDL +8Vjf0Z14WsxSolTuHvD3hjuBrcohuKw6LIKaNTM5cLH+TAf2WbLX4f8AI9Q/x/kB +wptFN/qVCp3MOYrJi3dH7mhKwnjWD6N9JYykmpi8MzBPWxDhgdkc9RQfzGQbrns7 +mO4FIvTHu4Ey8QCXzUu5plmXEGoar7JrKq/Gv0ojaaRZiw+MFCyeqPRCDUEvUogu +gKPZ1MMNXMYRU7kJSCGpc2+0/tNPBmsM6l5Q3BavBtFiKLD4q0mJiE8JRA4nYn5G +ZkTC3EZjcRLuZLmBPjhavdz2bNvDyixoFsXsR3h4lmDiKLDFOvxceUKmDWZYjVoY ++0NNPGGXEuOp6onBGgVFKCuv7U/7ExEiKNMpPSp2fDP5PCfJ5NDTFPPmWYOIsxYZ +/eavLwyz9Q80KYFZ8Bz8xZbCLStSw7Zm4DDcG9QyAceDuIeBDfoiH3qvvBQuCjse +bjgYr0RqQK7NM3w+gWYOIuYsPjWEGXHiOpyoq6OT9VF7/LEvkLZHAHQH4g4lQmOY +eAsxTImI4qx29yiLrbzKM3EZ1qpe4fTRxFmR4oAMwPcr3LDFc77Xy/qMLAwk7TaB +NS2DLxgNoFJVS4UILLKPd6gVLot4hqYbt9QdQ8mpVNeVChhFhuOdyjURyg2zLj2c +vv8A5Frbb3bdzbRm4grXwk2hK4IX5OSGm4HMZs8bfHgqVomMWPXMsX2HUDMbpXBf +cICoayhXMp0urh/0gLgdhZ+oy/kvwA3Y6Fy/BuKV7Rp+N/yFWbgk98wb0y0AXyzF +TSRKdMsIqIQzdmoKADpHcrHXgFzMwwG2MjmjRLxcvRg5hgBo1CgtaOWNWIYK7FHs +aZTNg4cwK1e3++NYjNjhyv36iaBNG/8A89RbVWrarWXLuJMBTriLLq5+xDHuNOGN +S/1GLX0JivnYSlkvl/8ACWNnx/lEwyfQQ0xl1OPfqGtQBmq9xLRcHEeKjmaJcGYi +uAjKuF5vx18xd7vavP0D4SGfght1w3KMMHk33Nh5/sTk14cRYayxZRpiXP4leBz3 +DZLwLWZc6OWG/C8E0lXY5epcfr/pP5QplPDD3B3+yLTLtgVlx8y71deBDcsUcQjz +AzHEYwl5jv6H6ORNq7hg8VDDcpiUJgpYt/qopxJW7LBp+LnENeRxe5dy7i4qEuLH +yPjj6Hzu/EMMFfN9AVkFVLrI18L+pqZAX6a+h3MC+f5MR4YR8rOfCzXm/NzeExfg +lyprK2yi74eyO4qQlNL5YQ/yQxuPl8MfFw3H6KlTR4/l5G5sXGrfMfPMdp0JDRdI +835fLDZHyeEhvxufEIw1Di4uV9/Rw8O37p/IP0EY/RsR+p5j3ObxeYe4cfS6fPjO +51/WPpYw8rJ548Hhg4Jl8GXiZeNiXefpM3Pk+pm0/9mJAlQEEwEIAD4WIQRqap98 +R7pMvtzVy3R7tCHGhOgh2AUCXsAL/gIbAwUJDxuGiwULCQgHAgYVCgkICwIEFgID +AQIeAQIXgAAKCRB7tCHGhOgh2PUoD/oDBmIhyPtfpHwbtIT5z4HG2CLsXfD6i4jX +rVSgU8OIJnaFeDmRxorDkldoBZqa7jPvfKlZ6VLqnWRo5PgMg4D6Kg6+ygpwbZ2U +ZDXC1jkc0HGkuL0NRcslf5+8ZbdMODT5pTt+2UuhfV4r2JGIe7L0SAdY7lU0EffP +Bub2tvXCp8kyVLJC4wzqIFF6aq2YNzNzPNHhchTD2oYgWtB6a+F2ZDTDmLobOX6m +7gNwuHW3Qa9g6ih7f8faJC6BBm3QEWLtah6UZhR0BpOYqZnuM4kXrGYu2MKFnm+9 +zFnHOkiG8gSW+M/AdT/Bf0ndmHkLxVhSB5ok7LKDElxr2ad5F05VLWjlf/X8rhlj +hm57a9QmVn+Vz0ZL2kSHVBRLMvDkKR5x51KjaYoS0EpsrLGWWiQuWeAfP+G5MB3p +At4h5TUM9ZpptOh+Ig8wT+4CAB+Y6/gYIsSOYtH4aTQC3HgcRg7NQCQ5ToNwJC1x +VUT9DoPnGyTR2FMsJxWOxA8aB14q5J0nh2Un/YhW+mkdv7q5A9q+1zhpMl2ry+nm +1HeqwYfyNZLDTs55vNEYp/HqxqEP3oNZeYykaQ4hQnCoKe+U/sC5K5ojdw8hKRw7 +jM+s99d+ChUwNB8TW8kbfs0YiHeQkn+1MR7SSrzzDCzb//GU7MFEH4/ysSBXKP8C +PZGN/d4daLkCDQRXKQ9dARAAqd6qhJj6hnDSWMsyxNmje/SPxGDtza9Af4Z5u4Di +dqFWQ0tJyiDAiO5qmRxwBEM1LxxEZm3u6Ftl3HGBQRMcOj/nfN8PwMrUg48jld03 +8DZHwxINsLLturMHtkvpi/NYq1jZduKemNxG4DAn6N+EFAGSGQy+sUFKxMVuV1kI +RDhlrZ85llk46ihvm3/8JnCvIsoQ5ysY4BE1d5sekOalx2aISsENtKmYh7xBWPEz +26g6Iq8zcJ/9O0c9vvrZVhp86gL7B7F0mFyKAMsjs2cR72kHdIOzW0x3jQYJMSMC +4fRGSCcFstBUsQjUXTW1A8znlKeAosjaJ5AeEO34cgh0KUaEMWrrnOYPYL9xbnNz +dluEjfGQ+IUX5486iknI9CmqmBx699ZtzAmyGtJ8XBtEeYMjZTfJamdURJ389lCp +Ksnt8/zexWOHNrWgkn4A3+3J7NUnhfORBOcydRJNMZVNGChfNqmOuIYR7TRDpzNv +gPxp0lcos07rPPQA1aF1rCWQ7M0WSEjonN9RajptaKeeGRvrd3ga9wb+NcyUTxtu +kRkA5gEsSFeKYitYFJioktLuyaySHHO/nIzwT3jAZrmBOqbPGDcjt8FxQf6unc4M +ql7rPynrgdkBGSC2Pltlk1ZFJ90V51TxbDXTCUlDjMzw6D/0p2FKGhK2Eb9Lnj4s +uDkAEQEAAYkCPAQYAQgAJgIbDBYhBGpqn3xHuky+3NXLdHu0IcaE6CHYBQJev8hj +BQkPG4cGAAoJEHu0IcaE6CHYzDAQAIizHXFiSL+VlEd2Y4ETMKU0k1m+LEN3iCJ1 +O154KOK2pdenrRH5Wzjw4wMc9bywI1zT2q/gT+Ssqirj3i4spqL+wjxOKG1HXKPR +gM7DEZ86ckmd7fF82CkGfA4i6qZ9UxKg39TNcmtyLDwaVBV6PD3kzH3IhXG5rWL0 +/3FnKIRQ7yiv56KjPh6kUFbLVYME4XYWwglPz/fxNx7FPfeue6mrFyhEGl3qcejs +C6YKp7ieQkBgN+sxWCSk8NP7QrQMoNjcU45TOuQEANvUiQt5N+9jULsDwqGaMrNR +/4AhOjYF6E+KZkDbhZJNdKdRXLJjcOYigpCIW+tKhFdLG4HBQNYx0uKhiGAHvXZK +CO6M8H5ZYBHnKs0PuWD2a4ewhX+Dru+ZGDnF5x6XCBNNYEso0eFmPnUIWIlXh7WL +hYE7eiYXbTNKlmx2NxXYnnafjqBnNbXDxjLbA35z7kNpmrKPnuAS39Ob15Jbxx/S +bl3tL6+TqlBArcKty3ot0yAcNln8Z3ibLT/4t4GgL7Jgkkie4LYayqQnoO89tY8i +gEOJ/reK7md89vW7NAvdif0iD1eADW1/yMGjL6NpfR3HfgFG7Ywm2/lTB2/s+VFb +KtsA0e5sI82giBEcLbZMHxf5Py6KlwerilgPhgcWWPLg9A73HfiSyqjBcVDa6+Df +anMm538H +=dmL7 +-----END PGP PUBLIC KEY BLOCK----- diff --git a/services/nginx/hosts/aleph/resume.html.nix b/services/nginx/hosts/aleph/resume.html.nix new file mode 100644 index 0000000..bb7cb17 --- /dev/null +++ b/services/nginx/hosts/aleph/resume.html.nix @@ -0,0 +1,215 @@ +{ web, ... }: +{ head, ... }: + let + inherit(web.html) HTML; + in + HTML { language = "eng"; } + { + inherit head; + body + = with web.html; + [ + ( + main + [ + ( + header + [ + (h1 "Sebastian Walz") + ] + ) + ( + section + [ + (h2 "Summary") + ( + p '' + As a chemist (M.Sc.) with a focus on + synthetic organometallic chemistry, + in particularly ferrocene chemistry, + I was not only able to gain valuable practical experience + in various instrumental analysis techniques and + learn to critically evaluate data and process results during my studies, + but also also expand my skills + in programming languages + of different paradigms + like Nix, Python, C++, Rust and others. + '' + ) + ( + p '' + I have practical experience with + the usual development tools, + assembler, + reverse engineering of software and + I am familiar with + theoretical computer science, + cryptography, + Linux and + especially the Nix/NixOS ecosystem. + By operating my own server infrastructure with e-mail, monitoring, DNS, etc. + I was able to gain valuable experience in network and system administration. + '' + ) + ( + p '' + I am therefore open to opportunities that require + both my knowledge of chemistry and IT and + in which I can use my + mathematical and scientific problem-solving skills and + analytical thinking skills. + '' + ) + ] + ) + ( + section + [ + (h2 "Education") + ( + dl + [ + (dt "Master of Science (M.Sc.) in Chemistry @ Chemnitz University of Technology (2018–2023)") + (dd [ + (p "Grade: 1.6 (Thesis: 1.5)") + ( + p '' + Thesis in the Group Organometallic Chemistry of Prof. Heinrich Lang + »Synthesis and Characterisation of Sulfur-Functionalised Ferrocenyl Pyrenes« + '' + ) + ] + ) + (dt "Bachelor of Science (B.Sc.) in Chemistry @ Chemnitz University of Technology (2015–2018)") + (dd [ + (p "Grade: 2.0 (Thesis: 1.3)") + ( + p '' + Thesis in the Department of Anorganic Chemistry of Prof. Heinrich Lang + »Structural Diversity of Ferrocenyl Functionalised Iron Carbonyl Phosphinyl Clusters« + '' + ) + ] + ) + ] + ) + ] + ) + ( + section + [ + (h2 "Software Development") + ( + dl + [ + (dt "LaTeX") (dd "luaLaTeX, plainTeX, pdfTeX") + (dt "Web/Frontend") (dd "CSS3, HTML5, JavaScript, PHP, TypeScript") + (dt "General Purpose Languages") (dd "C/C++, Go, Java, Nim, PureBasic, Rust") + (dt "Scripting Languages") (dd "Bash, Lua, Nix, Python 3") + (dt "Assembly") (dd "fasm, nasm; amd64, x86, avr") + (dt "Embedded") (dd "Arduino, AVR/ATmega, Raspberry Pi") + ] + ) + ] + ) + ( + section + [ + (h2 "IT-Skills") + ( + dl + [ + (dt "Operating Systems") (dd "Linux (+10 years): Debian, NixOS (+4 years)") + (dt "Server/Networking") (dd "bind, gitea, grafana+prometheus, let's encrypt, nginx, ssh") + (dt "Miscellaneous") (dd "git, gnupg, luks, VS Code/Codium") + ] + ) + ] + ) + ( + section + [ + (h2 "Recreation") + ( + dl + [ + (dt "Diving") (dd "DTSA/CMAS* (ISO 24801-2) since 2021") + (dt "Chess") (dd "For 20+ years, also in a club and regional tournaments for some time") + ] + ) + ] + ) + ( + section + [ + (h2 "Languages") + ( + dl + [ + (dt "German") (dd "Native Speaker") + (dt "English") (dd "Independent User (B2)") + (dt "Ivrit") (dd "Basic User (A1)") + ] + ) + ] + ) + ( + section + [ + (h2 "Committees") + ( + dl + [ + (dt "Study Commission Bachelor/Master Chemistry (2017–2021)") (dd "Student Member") + (dt "Student Council Chemistry Institute (2016–2021)") (dd "Full Member") + (dt "Selection Committee for the W3-Professorship »Organic Chemistry« (2020)") (dd "Student Member") + (dt "Selection Committee for the W2-Professorship »Applied Quantum Chemistry and Computational Chemistry« (2018)") + (dd "Student Member") + ] + ) + ] + ) + ( + section + [ + (h2 "Participation in Competitions") + ( + dl + [ + (dt "Jugend Forscht (»youth researches«) STEM-compition (regional level) in the chemistry-category (Chemnitz 2014)") + (dd "Wet-chemistry electronics based on aluminium.") + (dt "Jugend Forscht (»youth researches«) STEM-compition (regional level) in the engineering-category (Chemnitz 2013)") + (dd "Retrofitting of an light microscope for mlting point analysis with an controller (ATmega 16, BASCOM-AVR), PC-connection (PureBasic) and a camera with image recognition.") + ] + ) + ] + ) + ( + section + [ + (h2 "Publications") + ( + ol + [ + (li '' + M. Korb, L. Xianming, S. Walz, J. Mahrholdt, A. Popov, H. Lang, + »Structural Variety of Iron Carbonyl Clusters Featuring Ferrocenylphosphines«, + ${em "Eur. J. Inorg. Chem."} ${b "2021"}, ${em "2021"}, ${em "2017–2033"}, + ${a { href = "https://chemistry-europe.onlinelibrary.wiley.com/doi/10.1002/ejic.202100097"; } "DOI 10.1002/ejic.202100097"}. + '') + (li '' + M. Korb, L. Xianming, S. Walz, M. Rosenkranz, E. Dmitrieva, A. Popov, H. Lang, + »(Electrochemical) Properties and Computational Investigations of Ferrocenyl-substituted + Fe${sub "3"}(μ${sub "3"}-PFc)${sub "2"}(CO)${sub "9"} and Co${sub "4"}(μ${sub "4"}-PFc)${sub "2"}(CO)${sub "9"} + Clusters and Their Reduced Species«, + ${em "Inorg. Chem."} ${b "2020"}, ${em "59"}, ${em "6147–6160"}, + ${a { href = ""; } "DOI 10.1021/acs.inorgchem.0c00276"}. + '') + ] + ) + ] + ) + ] + ) + ]; + } diff --git a/services/nginx/hosts/aleph/security.txt.nix b/services/nginx/hosts/aleph/security.txt.nix new file mode 100644 index 0000000..59bf663 --- /dev/null +++ b/services/nginx/hosts/aleph/security.txt.nix @@ -0,0 +1,33 @@ +{ core, ... }: +{ domain, ... }: + let + inherit(core) time; + in + { + body + = { + #Acknowledgments = "https://${domain}/hall-of-fame.html"; + Canonical = "https://${domain}/.well-known/security.txt"; + Contact = "mailto:security@${domain}"; + Encryption = "https://${domain}/pgp"; + Expires = "${time.formatISO8601' "2024-04-01"}Z"; + #Policy = "https://${domain}/disclosure-policy.html"; + Preferred-Languages = "de, en"; + }; + signature + = '' + iQIzBAEBCAAdFiEEamqffEe6TL7c1ct0e7QhxoToIdgFAmQrMroACgkQe7QhxoTo + IdgK5A/8C5A81XR7o1Q50MD7wA5LoGnbIkMuyB28kCdx79nYFQFBOcTpj8ipa87W + X9VSw/bqFrpVnvtDHe1Di/twwWNBQurlSgzXxJppZ6keTPX80U4thCjHSOImCKNG + ONnkjs4q2hr12fF+kBeTLn2nyb0I8zkCZmhfO0j21oicALjWbf7vMbDFIbzoU/ny + V5+ewrnqE3n20n3Y6YeCdA60AREyUPfhPx4H0F6t+AkXX982Eps+TGeqNCIee+Nh + byDtBqLVXL1kgyIzHR5S/WfJQvMLLdZo8PzMNafEfHiJcNeQdxDRscGg1LdSDpda + awZuLW+5VYdcdMDKO9eWHxPR9K286MhUxqBlW40I2Aig7ArVMbsO4AbCfmTLqNP5 + +DzDRr36P5KLfSmHI2TLiEjHX996AAfb/9ewYx3CxaznQiSEkhrHp8PcnE+HHTJH + qip9QmVWiXRWX7OAdliJEx+sswnzJwG62PRtIol8WKQ0oU7G6mNUjPVeX9jyVoTA + Gv1XA6fCFoukEgvAIEupaS6w5FK2rC5Q0sNf44DaZeKvjwgP/Ol/dmpCkscUUVHD + Hyll4jnL/2FSKHlEDfViN2/fOcEJmrU8DhO5ZHAE9Bwm7Tr/miCzKo0FX2k/ELxS + djcuJ0HtyN9S8JeZNpN+XJPO9HwLS2cgxIGnxwwdNxlG92gI+n8= + =sy9M + ''; + } diff --git a/services/nginx/hosts/aleph/timestamp.sh b/services/nginx/hosts/aleph/timestamp.sh new file mode 100644 index 0000000..2a38465 --- /dev/null +++ b/services/nginx/hosts/aleph/timestamp.sh @@ -0,0 +1,5 @@ +#!/usr/bin/env bash + +openssl ts -query -data "$1" -no_nonce -sha512 -cert \ +| curl --header "Content-Type: application/timestamp-query" --data-binary @- http://zeitstempel.dfn.de \ +> \ No newline at end of file diff --git a/services/nginx/hosts/default.nix b/services/nginx/hosts/default.nix new file mode 100644 index 0000000..7ba146f --- /dev/null +++ b/services/nginx/hosts/default.nix @@ -0,0 +1,4 @@ +{ + aleph = ./aleph; + bet = {}; +} diff --git a/services/openssh/default.nix b/services/openssh/default.nix new file mode 100644 index 0000000..e1b2904 --- /dev/null +++ b/services/openssh/default.nix @@ -0,0 +1,7 @@ +Service "OpenSSH." +{ + configuration + = { + openssh.enable = true; + }; +} diff --git a/services/printing/default.nix b/services/printing/default.nix new file mode 100644 index 0000000..3a92ac8 --- /dev/null +++ b/services/printing/default.nix @@ -0,0 +1,12 @@ +Service "Printing" +{ + configuration + = { registries, ... }: + { + printing + = { + drivers = [ registries.nix.hplip ]; + enable = true; + }; + }; +} diff --git a/services/restic/default.nix b/services/restic/default.nix new file mode 100644 index 0000000..e98f535 --- /dev/null +++ b/services/restic/default.nix @@ -0,0 +1,42 @@ +Service "Restic: Backups" +{ + configuration + = { store, ... }: + { + restic.backups + = { + "05-1611-07A" + = let + listFiles + = store.write.bashScriptFile "listHomeDirectory" + '' + for f in /home/sivizius/* + do + echo "$f" + done + ''; + in + { + dynamicFilesFrom = "sh ${listFiles}"; + initialize = false; + passwordFile = "/mnt/secrets/05-1611-07A"; + pruneOpts + = [ + "--keep-last=4" + "--keep-hourly=4" + "--keep-daily=4" + "--keep-weekly=4" + "--keep-monthly=4" + "--keep-yearly=4" + "--keep-tag=Save" + ]; + repository = "/mnt/05-1611-07A"; + timerConfig + = { + OnCalendar = "Fri 23:00"; + Persistent = "true"; + }; + }; + }; + }; +} diff --git a/services/simple-nix-mail/default.nix b/services/simple-nix-mail/default.nix new file mode 100644 index 0000000..fb57a3a --- /dev/null +++ b/services/simple-nix-mail/default.nix @@ -0,0 +1,31 @@ +Service "Simple Mail Delivery Agent" +{ + configuration + = { network, ... }: + let + inherit(network) domain; + in + { + mailserver + = { + certificateScheme = 3; + domains = [ domain ]; + enable = true; + enableImap = true; + enableImapSsl = true; + enableManageSieve = true; + enablePop3 = true; + enablePop3Ssl = true; + fqdn = domain; + localDnsResolver = false; + rejectRecipients = [ ]; + rejectSender + = [ + # Fake Mailer + "@emkei.cz" + ]; + virusScanning = false; + }; + }; + legacy = true; +} diff --git a/services/static/default.nix b/services/static/default.nix new file mode 100644 index 0000000..76ed16f --- /dev/null +++ b/services/static/default.nix @@ -0,0 +1,17 @@ +{ enableACME, extraConfig, forceSSL, ... }: + Service "Static Files" + { + configuration + = { network, ... }: + { + nginx + = { + enable = true; + virtualHosts."static.${network.domain}" + = { + inherit enableACME extraConfig forceSSL; + locations."/".root= "/var/static/"; + }; + }; + }; + } diff --git a/services/static/files/common.css b/services/static/files/common.css new file mode 100644 index 0000000..ffd63f6 --- /dev/null +++ b/services/static/files/common.css @@ -0,0 +1,4 @@ +html +{ + background: #000; +} diff --git a/users/fluepke/config/default.nix b/users/fluepke/config/default.nix new file mode 100644 index 0000000..0e0dcd2 --- /dev/null +++ b/users/fluepke/config/default.nix @@ -0,0 +1,3 @@ +{ + +} \ No newline at end of file diff --git a/users/fluepke/default.nix b/users/fluepke/default.nix new file mode 100644 index 0000000..c82b3f3 --- /dev/null +++ b/users/fluepke/default.nix @@ -0,0 +1,4 @@ +User "fluepke" +{ + config = ./config; +} diff --git a/users/fluepke/flake.nix b/users/fluepke/flake.nix new file mode 100644 index 0000000..754b6d8 --- /dev/null +++ b/users/fluepke/flake.nix @@ -0,0 +1,12 @@ +{ + description = "User-Configuration of fluepke"; + inputs + = { + libconfig.url = "github:sivizius/nixfiles/development?dir=libs/config"; + }; + outputs + = { libconfig, ... }: + { + user = libconfig.lib.users.load ./.; + }; +} diff --git a/users/sivizius/config/default.nix b/users/sivizius/config/default.nix new file mode 100644 index 0000000..d5a0f32 --- /dev/null +++ b/users/sivizius/config/default.nix @@ -0,0 +1,91 @@ +{ core, profile, registries, version, ... } @ env: + let + inherit(core) list path; + email = path.import ./email.nix env; + packages = path.import ./packages env; + in + { + accounts + = { + inherit email; + }; + dconf.settings + = { + }; + editorconfig + = { + enable = false; + settings + = { + }; + }; + fonts.fontconfig.enable = true; + home + = { + activation = {}; + enableDebugInfo = true; + enableNixpkgsReleaseCheck = true; + extraOutputsToInstall = [ "doc" "info" "devdoc" ]; + file = {}; + # homeDirectory = "/home/sivizius"; + keyboard + = { + layout = null; + model = null; + options = []; + variant = null; + }; + language + = { + address = null; + base = null; + collate = null; + ctype = null; + measurement = null; + messages = null; + monetary = null; + name = null; + numeric = null; + paper = null; + telephone = null; + time = null; + }; + packages + = packages.common + ++ (list.ifOrEmpty' profile.isDesktop packages.desktop); + sessionVariables + = { + NIX_SSHOPTS = "-t"; + TERM = "xterm"; + }; + shellAliases = path.import ./shellAliases.nix env; + stateVersion = version.version; + }; + host + = { + extraGroups + = [ "wheel" ] + ++ ( + list.ifOrEmpty' profile.isDesktop + [ + "docker" + "lpadmin" + "network" + "scanner" + "video" + ] + ); + # Generate with: mkpasswd -m sha-512 $PASSPHRASE + initialHashedPassword = "$6$mgzs1dRcXi.6t2C4$Uf1be0ppPZwF0iGlxu7im/ff6GzRFeGSrsZfhCSEaQigeuTX6o/1yTYn0Lp2FhY2.LVQRGuy5cGvtIAe3UNbp1"; + shell = registries.nix.zsh; + }; + manual + = { + html.enable = true; + json.enable = true; + manpages.enable = true; + }; + programs = path.import ./programs env { inherit email; }; + services = path.import ./services env; + wayland.windowManager.sway = path.import ./sway env; + } diff --git a/users/sivizius/config/email.nix b/users/sivizius/config/email.nix new file mode 100644 index 0000000..02d5905 --- /dev/null +++ b/users/sivizius/config/email.nix @@ -0,0 +1,71 @@ +{ config, core, registries, store, user, ... } @ libs: + let + inherit(core) bool path set; + accounts = set.map registerAccount mailAccounts; + mailAccounts = path.import ./mailAccounts.nix libs; + + maildirBasePath = "E-Mails"; + registerAccount + = name: + attrs: + { + address = attrs.address or name; + aliases = attrs.aliases or [ ]; + folders + = { + drafts = "Drafts"; + inbox = "INBOX"; + sent = "Sent"; + trash = "Trash"; + }; + gpg = attrs.gpg or null; + imap.host = attrs.imapHost or attrs.host; + mbsync + = { + enable = true; + create = "both"; + patterns = attrs.patterns or [ "*" ]; + }; + neomutt + = { + enable = true; + extraConfig + = let + signature + = bool.select + (attrs.signature or null != null) + (path.toFile "signature.txt" attrs.signature) + "\"fortune |\""; + in + '' + unmailboxes * + mailboxes `find ${maildirBasePath}/${name} -maxdepth 1 -mindepth 1 -printf "=\"%P\" "` + set sidebar_sort_method = path + set signature = ${signature} + ''; + }; + passwordCommand + = let + kinit = attrs.kinit or ""; + passwordCommand + = store.write.shellScript "passwordCommand" + '' + if [ $# -gt 1 ] + then + ${registries.nix.pass}/bin/pass "Communication/E-Mail/$2" | ${registries.nix.krb5}/bin/kinit "$1" + shift 1 + fi + + ${registries.nix.pass}/bin/pass "Communication/E-Mail/$1" + ''; + in + "sh ${passwordCommand} ${kinit} ${name}"; + primary = attrs.primary or false; + realName = attrs.real or user.realName; + smtp.host = attrs.smtpHost or attrs.host; + userName = attrs.user or name; + }; + in + { + inherit accounts maildirBasePath; + } diff --git a/users/sivizius/config/mailAccounts.nix b/users/sivizius/config/mailAccounts.nix new file mode 100644 index 0000000..9dff7cd --- /dev/null +++ b/users/sivizius/config/mailAccounts.nix @@ -0,0 +1,31 @@ +{ ... }: +let + real = "Sebastian Walz"; + gpg + = { + encryptByDefault = false; + key = "6A6A9F7C47BA4CBEDCD5CB747BB421C684E821D8"; + signByDefault = true; + }; +in +{ + "sivizius@ohai.su" + = { + index = 2; + host = "imap.fnoco.eu"; + inherit gpg real; + }; + "sivizius@sivizius.eu" + = { + index = 0; + host = "sivizius.eu"; + primary = true; + inherit gpg real; + }; + "root@sivizius.eu" + = { + index = 1; + host = "sivizius.eu"; + inherit gpg real; + }; +} diff --git a/users/sivizius/config/packages/common/crypto.nix b/users/sivizius/config/packages/common/crypto.nix new file mode 100644 index 0000000..3121549 --- /dev/null +++ b/users/sivizius/config/packages/common/crypto.nix @@ -0,0 +1,10 @@ +{ nix, ... }: + with nix; + [ + cryptsetup + ecdsautils + keyutils + openssl + pwgen-secure + gnupg + ] diff --git a/users/sivizius/config/packages/common/default.nix b/users/sivizius/config/packages/common/default.nix new file mode 100644 index 0000000..b511999 --- /dev/null +++ b/users/sivizius/config/packages/common/default.nix @@ -0,0 +1,12 @@ +{ nix, ... }: + with nix; + [ + mailcap + ./crypto.nix + ./files.nix + ./network.nix + ./processes.nix + ./ranger.nix + ./sync.nix + ./terminal.nix + ] diff --git a/users/sivizius/config/packages/common/files.nix b/users/sivizius/config/packages/common/files.nix new file mode 100644 index 0000000..b3ffeea --- /dev/null +++ b/users/sivizius/config/packages/common/files.nix @@ -0,0 +1,12 @@ +{ nix, ... }: + with nix; + [ + exa + fdupes + file + iotop + lsof + parted + unzip + zstd + ] diff --git a/users/sivizius/config/packages/common/network.nix b/users/sivizius/config/packages/common/network.nix new file mode 100644 index 0000000..3d0e55a --- /dev/null +++ b/users/sivizius/config/packages/common/network.nix @@ -0,0 +1,12 @@ +{ nix, ... }: + with nix; + [ + iftop + inetutils + iperf + mtr + nload + tcpdump + wget + zmap + ] diff --git a/users/sivizius/config/packages/common/processes.nix b/users/sivizius/config/packages/common/processes.nix new file mode 100644 index 0000000..6d16e4a --- /dev/null +++ b/users/sivizius/config/packages/common/processes.nix @@ -0,0 +1,8 @@ +{ nix, ... }: + with nix; + [ + parallel + progress + pv + ] + diff --git a/users/sivizius/config/packages/common/ranger.nix b/users/sivizius/config/packages/common/ranger.nix new file mode 100644 index 0000000..5c02111 --- /dev/null +++ b/users/sivizius/config/packages/common/ranger.nix @@ -0,0 +1,5 @@ +{ nix, ... }: + with nix; + [ + ranger + ] diff --git a/users/sivizius/config/packages/common/sync.nix b/users/sivizius/config/packages/common/sync.nix new file mode 100644 index 0000000..3dd5c82 --- /dev/null +++ b/users/sivizius/config/packages/common/sync.nix @@ -0,0 +1,8 @@ +{ nix, ... }: + with nix; + [ + git + restic + rsync + sshfs + ] diff --git a/users/sivizius/config/packages/common/terminal.nix b/users/sivizius/config/packages/common/terminal.nix new file mode 100644 index 0000000..04e81a0 --- /dev/null +++ b/users/sivizius/config/packages/common/terminal.nix @@ -0,0 +1,13 @@ +{ nix, ... }: + with nix; + [ + bat + hexyl + icdiff + jq + libarchive + ripgrep + screen + skim + tmux + ] diff --git a/users/sivizius/config/packages/default.nix b/users/sivizius/config/packages/default.nix new file mode 100644 index 0000000..12f3b35 --- /dev/null +++ b/users/sivizius/config/packages/default.nix @@ -0,0 +1,11 @@ +{ core, registries, user, ... }: + let + inherit(core) set; + inherit(user.extra.config) packages; + in + set.mapValues + (directory: packages.load directory registries) + { + common = ./common; + desktop = ./desktop; + } diff --git a/users/sivizius/config/packages/desktop/applications/default.nix b/users/sivizius/config/packages/desktop/applications/default.nix new file mode 100644 index 0000000..8aaa491 --- /dev/null +++ b/users/sivizius/config/packages/desktop/applications/default.nix @@ -0,0 +1,4 @@ +[ + ./funny.nix + ./graphical +] diff --git a/users/sivizius/config/packages/desktop/applications/funny.nix b/users/sivizius/config/packages/desktop/applications/funny.nix new file mode 100644 index 0000000..f0e35b6 --- /dev/null +++ b/users/sivizius/config/packages/desktop/applications/funny.nix @@ -0,0 +1,8 @@ +{ nix, ... }: + with nix; + [ + cmatrix + fortune + lolcat + thefuck + ] diff --git a/users/sivizius/config/packages/desktop/applications/graphical/browser.nix b/users/sivizius/config/packages/desktop/applications/graphical/browser.nix new file mode 100644 index 0000000..9399e56 --- /dev/null +++ b/users/sivizius/config/packages/desktop/applications/graphical/browser.nix @@ -0,0 +1,7 @@ +{ nix, ... }: + with nix; + [ + chromium + firefox-wayland + qutebrowser + ] diff --git a/users/sivizius/config/packages/desktop/applications/graphical/chemistry.nix b/users/sivizius/config/packages/desktop/applications/graphical/chemistry.nix new file mode 100644 index 0000000..b6bf270 --- /dev/null +++ b/users/sivizius/config/packages/desktop/applications/graphical/chemistry.nix @@ -0,0 +1,6 @@ +{ nix, ... }: + with nix; + [ + avogadro + #mestrenova + ] diff --git a/users/sivizius/config/packages/desktop/applications/graphical/darkweb.nix b/users/sivizius/config/packages/desktop/applications/graphical/darkweb.nix new file mode 100644 index 0000000..afd80eb --- /dev/null +++ b/users/sivizius/config/packages/desktop/applications/graphical/darkweb.nix @@ -0,0 +1,7 @@ +{ nix, ... }: + with nix; + [ + i2p + tor + tor-browser-bundle-bin + ] diff --git a/users/sivizius/config/packages/desktop/applications/graphical/data.nix b/users/sivizius/config/packages/desktop/applications/graphical/data.nix new file mode 100644 index 0000000..58fb51d --- /dev/null +++ b/users/sivizius/config/packages/desktop/applications/graphical/data.nix @@ -0,0 +1,7 @@ +{ nix, ... }: + with nix; + [ + gnumeric + gnuplot + graphviz + ] diff --git a/users/sivizius/config/packages/desktop/applications/graphical/default.nix b/users/sivizius/config/packages/desktop/applications/graphical/default.nix new file mode 100644 index 0000000..e2ad1a6 --- /dev/null +++ b/users/sivizius/config/packages/desktop/applications/graphical/default.nix @@ -0,0 +1,22 @@ +{ nix, custom, ... }: + with nix; + [ + deluge + custom.redshift-wayland + spotify + system-config-printer + vscodium + xournal + ./browser.nix + ./chemistry.nix + ./darkweb.nix + ./data.nix + ./emulation.nix + ./games.nix + ./gnome.nix + ./media.nix + ./messenger.nix + ./notifications.nix + ./pentesting.nix + xsane + ] diff --git a/users/sivizius/config/packages/desktop/applications/graphical/emulation.nix b/users/sivizius/config/packages/desktop/applications/graphical/emulation.nix new file mode 100644 index 0000000..16bedf0 --- /dev/null +++ b/users/sivizius/config/packages/desktop/applications/graphical/emulation.nix @@ -0,0 +1,6 @@ +{ nix, ... }: + with nix; + [ + qemu + wine + ] diff --git a/users/sivizius/config/packages/desktop/applications/graphical/games.nix b/users/sivizius/config/packages/desktop/applications/graphical/games.nix new file mode 100644 index 0000000..bfd5dd6 --- /dev/null +++ b/users/sivizius/config/packages/desktop/applications/graphical/games.nix @@ -0,0 +1,8 @@ +{ nix, ... }: + with nix; + [ + jdk17 + prismlauncher + sauerbraten + xonotic + ] diff --git a/users/sivizius/config/packages/desktop/applications/graphical/gnome.nix b/users/sivizius/config/packages/desktop/applications/graphical/gnome.nix new file mode 100644 index 0000000..5996623 --- /dev/null +++ b/users/sivizius/config/packages/desktop/applications/graphical/gnome.nix @@ -0,0 +1,11 @@ +{ gnome, nix, ... }: +[ + gnome.adwaita-icon-theme + gnome.nautilus + nix.atk + #nix.gdk-pixbuf + nix.gtk3 + nix.hicolor-icon-theme + nix.libappindicator-gtk3 + nix.pango +] diff --git a/users/sivizius/config/packages/desktop/applications/graphical/media.nix b/users/sivizius/config/packages/desktop/applications/graphical/media.nix new file mode 100644 index 0000000..69581e0 --- /dev/null +++ b/users/sivizius/config/packages/desktop/applications/graphical/media.nix @@ -0,0 +1,28 @@ +{ nix, ... }: + with nix; + [ + # audio + audacity + pavucontrol + + # documents + cairo + evince + #libreoffice + pandoc + pdfpc + pdftk + poppler_utils + qpdf + + # images + feh + gimp + imagemagick + inkscape + librsvg + + # video + ffmpeg + mpv + ] diff --git a/users/sivizius/config/packages/desktop/applications/graphical/messenger.nix b/users/sivizius/config/packages/desktop/applications/graphical/messenger.nix new file mode 100644 index 0000000..dec9716 --- /dev/null +++ b/users/sivizius/config/packages/desktop/applications/graphical/messenger.nix @@ -0,0 +1,11 @@ +{ nix, ... }: + with nix; + [ + dino + discord + mumble + schildichat-desktop + signal-desktop + tdesktop + weechat + ] diff --git a/users/sivizius/config/packages/desktop/applications/graphical/notifications.nix b/users/sivizius/config/packages/desktop/applications/graphical/notifications.nix new file mode 100644 index 0000000..e5676ba --- /dev/null +++ b/users/sivizius/config/packages/desktop/applications/graphical/notifications.nix @@ -0,0 +1,6 @@ +{ nix, ... }: + with nix; + [ + libnotify + mako + ] diff --git a/users/sivizius/config/packages/desktop/applications/graphical/pentesting.nix b/users/sivizius/config/packages/desktop/applications/graphical/pentesting.nix new file mode 100644 index 0000000..4c1006f --- /dev/null +++ b/users/sivizius/config/packages/desktop/applications/graphical/pentesting.nix @@ -0,0 +1,13 @@ +{ nix, ... }: + with nix; + [ + gdb + ghidra-bin + hopper + john + ltrace + rizin + cutter + strace + z3 + ] diff --git a/users/sivizius/config/packages/desktop/default.nix b/users/sivizius/config/packages/desktop/default.nix new file mode 100644 index 0000000..64fcf7a --- /dev/null +++ b/users/sivizius/config/packages/desktop/default.nix @@ -0,0 +1,11 @@ +{ nix, ... }: + with nix; + [ + pass-wayland + swaybg + wdisplays + wev + wl-clipboard + ./applications + ./tools + ] diff --git a/users/sivizius/config/packages/desktop/tools/default.nix b/users/sivizius/config/packages/desktop/tools/default.nix new file mode 100644 index 0000000..1aefa7b --- /dev/null +++ b/users/sivizius/config/packages/desktop/tools/default.nix @@ -0,0 +1,12 @@ +{ nix, ... }: + with nix; + [ + ./development + ./hardware.nix + ./network.nix + ./spelling.nix + nix-index + nix-prefetch-git + nix-prefetch-github + xdg_utils + ] diff --git a/users/sivizius/config/packages/desktop/tools/development/default.nix b/users/sivizius/config/packages/desktop/tools/development/default.nix new file mode 100644 index 0000000..f28fc1a --- /dev/null +++ b/users/sivizius/config/packages/desktop/tools/development/default.nix @@ -0,0 +1,18 @@ +{ nix, texlive, ... }: +[ + ./python.nix + ./rust.nix + nix.minikube + nix.kubectl + #nix.binutils + nix.clang + #nix.glib + #nix.glibc + nix.lua + nix.patchelf + nix.pkg-config + nix.stdenv + nix.swift + texlive.combined.scheme-full + nix.nil +] diff --git a/users/sivizius/config/packages/desktop/tools/development/python.nix b/users/sivizius/config/packages/desktop/tools/development/python.nix new file mode 100644 index 0000000..222d483 --- /dev/null +++ b/users/sivizius/config/packages/desktop/tools/development/python.nix @@ -0,0 +1,9 @@ +{ python3, ... }: + with python3; + [ + ipython + python + pwntools + pygments + pyserial + ] diff --git a/users/sivizius/config/packages/desktop/tools/development/rust.nix b/users/sivizius/config/packages/desktop/tools/development/rust.nix new file mode 100644 index 0000000..43bfa2c --- /dev/null +++ b/users/sivizius/config/packages/desktop/tools/development/rust.nix @@ -0,0 +1,14 @@ +{ nix, ... }: + with nix; + [ + chit + #clippy + #gir-rs + #rls + rust-analyzer + rust-bindgen + rust-cbindgen + #rustc + #rustfmt + rustup + ] diff --git a/users/sivizius/config/packages/desktop/tools/hardware.nix b/users/sivizius/config/packages/desktop/tools/hardware.nix new file mode 100644 index 0000000..2869f8e --- /dev/null +++ b/users/sivizius/config/packages/desktop/tools/hardware.nix @@ -0,0 +1,15 @@ +{ linux, nix, ... }: +[ + linux.tp_smapi + + nix.brightnessctl + nix.cpufrequtils + nix.cifs-utils + nix.flashrom + nix.gpsd + nix.pciutils + nix.powertop + nix.system-config-printer + nix.tlp + nix.usbutils +] diff --git a/users/sivizius/config/packages/desktop/tools/network.nix b/users/sivizius/config/packages/desktop/tools/network.nix new file mode 100644 index 0000000..c442bb2 --- /dev/null +++ b/users/sivizius/config/packages/desktop/tools/network.nix @@ -0,0 +1,8 @@ +{ nix, ... }: + with nix; + [ + #bind + blueman + openconnect + w3m + ] diff --git a/users/sivizius/config/packages/desktop/tools/spelling.nix b/users/sivizius/config/packages/desktop/tools/spelling.nix new file mode 100644 index 0000000..7931cd1 --- /dev/null +++ b/users/sivizius/config/packages/desktop/tools/spelling.nix @@ -0,0 +1,7 @@ +{ hunspell, nix, ... }: +[ + hunspell.en_GB-large + hunspell.de_DE + nix.aspell + nix.hunspell +] diff --git a/users/sivizius/config/programs/alacritty.nix b/users/sivizius/config/programs/alacritty.nix new file mode 100644 index 0000000..f49c592 --- /dev/null +++ b/users/sivizius/config/programs/alacritty.nix @@ -0,0 +1,47 @@ +{ profile, ... }: +{ + enable = profile.isDesktop; + settings + = { + font.normal + = { + family = "Noto Sans Mono"; + size = 9.0; + }; + + colors + = { + primary + = { + background = "0x000000"; + foreground = "0xeaeaea"; + }; + normal + = { + black = "0x6c6c6c"; + red = "0xe9897c"; + green = "0xb6e77d"; + yellow = "0xecebbe"; + blue = "0xa9cdeb"; + magenta = "0xea96eb"; + cyan = "0xc9caec"; + white = "0xf2f2f2"; + }; + bright + = { + black = "0x747474"; + red = "0xf99286"; + green = "0xc3f786"; + yellow = "0xfcfbcc"; + blue = "0xb6defb"; + magenta = "0xfba1fb"; + cyan = "0xd7d9fc"; + white = "0xe2e2e2"; + }; + }; + window + = { + opacity = 0.6; + }; + }; +} diff --git a/users/sivizius/config/programs/assets/colours.muttrc b/users/sivizius/config/programs/assets/colours.muttrc new file mode 100644 index 0000000..f1c57b0 --- /dev/null +++ b/users/sivizius/config/programs/assets/colours.muttrc @@ -0,0 +1,50 @@ +# Basics +color normal default default +color indicator brightyellow red +color tree default default +color status brightgreen blue +color error brightred default +color message red default +color signature red default +color attachment yellow default +color search brightyellow red +color tilde brightmagenta default +color markers red default +color hdrdefault cyan default +color bold green black +color underline yellow black + +# Index +#color index_flags black white ~D +#color index_flags green default ~g +#color index_flags brightgreen default ~G +#color index_author brightdefault color035 ~P +#color index_author blue brightred ~F +#color index_author yellow default ~l +#color index_flags yellow default ~N +#color index_flags yellow default ~l +#color index_date cyan default +#color index_size cyan default +#color index_number green default + +# Pager +color header brightcyan default '^From:' +color header brightyellow default '^Subject:' +color header black brightgreen '^User-Agent:.*Mutt' +color header black green '^User-Agent: Mozilla/5.0.*Linux' + +color body brightcyan default "[-a-z_0-9.+]+@[-a-z_0-9.]+" +color body cyan default "((ftp|http|https)://|news:)[^ >)\"\t]+" +color body white brightblue "\\[[0-9]+\\]" +color body yellow default "\\[\\.\\.\\.?\\]" + +color quoted magenta default # Quoting Layer 0 +color quoted1 red default # Quoting Layer 1 +color quoted2 green default # Quoting Layer 2 +color quoted3 magenta default # Quoting Layer 3 +color quoted4 blue default # Quoting Layer 4 +color quoted5 cyan default # Quoting Layer 5 +color quoted6 green default # Quoting Layer 6 +color quoted7 red default # Quoting Layer 7 +color quoted8 magenta default # Quoting Layer 8 +color quoted9 blue default # Quoting Layer 9 diff --git a/users/sivizius/config/programs/default.nix b/users/sivizius/config/programs/default.nix new file mode 100644 index 0000000..89ae05f --- /dev/null +++ b/users/sivizius/config/programs/default.nix @@ -0,0 +1,36 @@ +{ core, profile, ... } @ env: +{ ... } @ extra: + let + inherit(core) path; + in + { + abook + = { + enable = true; + extraConfig + = '' + + ''; + }; + alacritty = path.import ./alacritty.nix env; + bash + = { + historyControl = [ "erasedups" "ignoredups" ]; + historyFile = "$HOME/.cache/bash/history.log"; + historyFileSize = 65536; + historyIgnore + = [ + "cd" + "l" "l1" "l2" "l3" "l4" "l5" "l6" "l7" "l8" "l9" "ls" "lt" + "exec" "exit" + ]; + historySize = 65536; + }; + git = path.import ./git.nix env; + htop = path.import ./htop.nix env; + mbsync.enable = profile.isDesktop; + #nano = path.import ./nano env; + neomutt = path.import ./neomutt.nix env extra; + ssh = path.import ./ssh.nix env; + zsh = path.import ./zsh.nix; + } diff --git a/users/sivizius/config/programs/git.nix b/users/sivizius/config/programs/git.nix new file mode 100644 index 0000000..5d42d76 --- /dev/null +++ b/users/sivizius/config/programs/git.nix @@ -0,0 +1,13 @@ +{ user, ... }: +{ + enable = true; + extraConfig.init.defaultBranch = "development"; + delta.enable = true; + signing + = { + key = "6A6A9F7C47BA4CBEDCD5CB747BB421C684E821D8"; + signByDefault = true; + }; + userName = user.realName; + userEmail = "sivizius@sivizius.eu"; +} diff --git a/users/sivizius/config/programs/htop.nix b/users/sivizius/config/programs/htop.nix new file mode 100644 index 0000000..07d3cc4 --- /dev/null +++ b/users/sivizius/config/programs/htop.nix @@ -0,0 +1,74 @@ +{ home-manager, ... }: + let + inherit(home-manager.htop) bar graph led text fields layouts; + in + { + enable = true; + settings + = { + account_guest_in_cpu_meter = false; + cpu_count_from_one = false; + color_scheme = 0; + delay = 9; + detailed_cpu_time = false; + enable_mouse = true; + header_margin = true; + hide_function_bar = false; + hide_kernel_threads = true; + hide_threads = false; + hide_userland_threads = false; + highlight_base_name = false; + highlight_megabytes = true; + highlight_threads = true; + shadow_other_users = true; + show_program_path = true; + show_thread_names = false; + sort_direction = 1; + sort_key = fields.PERCENT_CPU; + tree_view = false; + update_process_names = false; + fields + = with fields; + [ + PID + USER + PRIORITY + NICE + STATE + MAJFLT + IO_READ_RATE + IO_WRITE_RATE + PERCENT_CPU + PERCENT_MEM + M_SWAP + COMM + ]; + } + // ( + layouts.four_25_25_25_25 + [ + [ + ( bar "AllCPUs" ) + ] + [ + ( text "LoadAverage" ) + ( text "Tasks" ) + ( graph "CPU" ) + ( bar "Memory" ) + ( bar "Swap" ) + ] + [ + ( graph "NetworkIO" ) + ( graph "DiskIO" ) + ] + [ + ( led "Clock" ) + ( text "Date" ) + ( text "System" ) + ( text "Hostname" ) + ( text "Uptime" ) + ( text "Systemd" ) + ] + ] + ); + } diff --git a/users/sivizius/config/programs/nano/default.nix b/users/sivizius/config/programs/nano/default.nix new file mode 100644 index 0000000..4a58d34 --- /dev/null +++ b/users/sivizius/config/programs/nano/default.nix @@ -0,0 +1,39 @@ +{ registries, ... }: +{ + environment + = { + shellAliases.n = "${registries.nix.nano}/bin/nano"; + }; + programs.nano + = { + enable = true; + atBlanks = true; + autoIndentation = true; + backup = true; + backupDirectory = "~/.cache/nano/backups/"; + constantShow = true; + historyLog = true; + include + = [ + ./fasm.nanorc + ./purebasic.nanorc + ./yasic.nanorc + ]; + lineNumbers = true; + locking = true; + matchBrackets = "(<[{»›)>]}«‹"; + multiBuffer = true; + noHelp = true; + numberColour = { fg = "brightyellow"; bg = "normal"; }; + punctuation = "–;:,.¿?¡!"; + regexSearch = true; + showCursor = true; + smartHome = true; + spellChecker = "aspell -x -c"; + suspendable = true; + tabulatorSize = 2; + tabulatorToSpaces = true; + whiteSpace = "→·"; + wordBounds = true; + }; +} diff --git a/users/sivizius/config/programs/nano/fasm.nanorc b/users/sivizius/config/programs/nano/fasm.nanorc new file mode 100644 index 0000000..1d323bc --- /dev/null +++ b/users/sivizius/config/programs/nano/fasm.nanorc @@ -0,0 +1,33 @@ +syntax "fasm" "\.f(asm|cfg|dat|inc|lib|mod|nord|obj|res|txt)g?_?(.save)?~?$" +icolor brightmagenta "([[:space:]]`?|\@|\:)[A-Za-z_.#][0-9A-Za-z_.#]*" +icolor brightcyan "[[:space:]](and|bsr|bsr|or|mod|not|plt|rva|shl|shr|xor)[^0-9A-Za-z_.]" +icolor brightgreen "[[:space:]](t?byte|(dq?|f|p|qq?|t|x|y)?word|far|near|short)[[:space:]]" +icolor brightgreen "^[[:space:]]*(macro|struc)?[[:space:]]*[A-Za-z_][0-9A-Za-z_]*([[:space:]]|\@|$)" +icolor brightmagenta "^[[:space:]]*(`|\+|-|\~)?[A-Za-z_.][0-9A-Za-z_.]*[[:space:]]+(=|(a|d|r)(b[^px]|w[^o]|u|d[^ix]|dp|p|f|q|t)|equ|fix|str)([[:space:]]|,|$)" +icolor brightcyan "(^|[[:space:]]|\@)__[0-9A-Za-z_.]*__([[:space:]]|,|\.|$)" +icolor brightgreen "[[:space:]]((a|d|r)(b|w|u|dq?|p|f|q|t)|file|str)[[:space:]]" +icolor brightblue "(^|[[:space:]]|\\)(align|as|at|binary|break|code|common|data|defined?|display(Dec|Hex|Oct|Value)?(1|2|4)?|dup|elf(64?)|else( if)?|end( [A-Za-z_.][0-9A-Za-z_.]*)?)([[:space:]]|$)" +icolor brightblue "(^|[[:space:]]|\\)(entry|equ?|err|extrn|fix|for|format|forward|from|global|heap|if|in|include|invoke|irp(s|v)?|label|lib|load|local|macro|match|offset|org)([[:space:]]|$)" +icolor brightblue "(^|[[:space:]]|\\)(postpone|public|purge|repeat|rept|restore|restruc|resv|reverse|section|segment|stack|stat|store|struc|text|times|use(16|32|64)?|vars|virtual|while)([[:space:]]|$)" +icolor brightblue "(^|[[:space:]]|\\)(yalib|xcode|xresv|xstat|xtext|xvars)([[:space:]]|$)" +icolor brightcyan "[^0-9A-Za-z_.](dynamic|executable|gnuehframe|gnustack|interpreter|locked|readable|shared|writeable)([[:space:]]|,|$)" +color brightcyan "[^0-9A-Za-z_.][A-Z_.][0-9A-Z_.]([[:space:]]|,|$)" +icolor magenta "[[:space:]]cr(0|2|3|4|8)([[:space:]]|,|$)" +icolor magenta "[[:space:]]dr([0-9]|1[0-5])([[:space:]]|,|$)" +icolor magenta "[[:space:]](e|r)?((d|s)(i|p)l?|(b|s)p|bpl|(e|r)?[a-d]x|[a-d](h|l))([[:space:]]|,|$)" +icolor magenta "[[:space:]]r(8|9|1[0-5])(d|w|b|l)?([[:space:]]|,|$)" +icolor magenta "[[:space:]](([c-g]|s)s|st[0-7]?)([[:space:]]|,|$)" +icolor magenta "[[:space:]]mm[0-7]([[:space:]]|,|$)" +icolor magenta "[[:space:]][x-z]mm([0-9]|1[0-5])([[:space:]]|,|$)" +icolor magenta "[[:space:]](sys|lib)[0-5]arg(_(b|d|w))?([[:space:]]|,|$)" +icolor magenta "[[:space:]](sys|lib)[01]ret(_(b|d|h|l|w))?([[:space:]]|,|$)" +icolor magenta "[[:space:]]((sys|lib)2|lib3)arg_(h|l)([[:space:]]|,|$)" +icolor brightcyan "(\@|,|:|#|\[*|\]*|\{|\})|-|\+|\*|\/|=|\||\!|\~|\`|\\|<|<=|<<|>=|>>|=>|>|\&|\(*|\)*)" +icolor brightred "((([A-Za-z_.][0-9A-Za-z_.#]*\:(\:)?)|\@\@\:)([[:space:]]|,|$)|[^0-9A-Za-z_.](\@f|\@b|\@r)|\$|\$\$|\%t?|\?)" +icolor brightyellow "(\[(0([bB][01]+|[xX][0-9a-fA-F]+|[oO][0-7]+|[0-9]*|[01]*[bB]|[0-7]*[oO]|[0-9f-fA-F]*[hH])|[1-9][0-9]*|1[01]*[bB]|[1-7][0-7]*[oO]|[1-9][0-9f-fA-F]*[hH]|\"[^\"]*\"|'[^']*'|<[^=>]*>)\]|([[:space:]]|-|\+)(0([bB][01]+|[xX][0-9a-fA-F]+|[oO][0-7]+|[0-9]*|[01]*[bB]|[0-7]*[oO]|[0-9f-fA-F]*[hH])|[1-9][0-9]*|1[01]*[bB]|[1-7][0-7]*[oO]|[1-9][0-9f-fA-F]*[hH]|\"[^\"]*\"|'[^']*'))" +icolor white ";.*$" +icolor green ";(\{|\[|>|:|\!|\]|\}).*$" +icolor brightwhite ";(\(|=|;|\||\)).*$" +icolor ,green "[[:space:]]+$" +icolor brightred,blue ";<[^>]*>" +icolor red "^[[:space:]]*(#|>|\:).*$" diff --git a/users/sivizius/config/programs/nano/purebasic.nanorc b/users/sivizius/config/programs/nano/purebasic.nanorc new file mode 100644 index 0000000..b2cd2c1 --- /dev/null +++ b/users/sivizius/config/programs/nano/purebasic.nanorc @@ -0,0 +1,52 @@ +syntax "purebasic" "\.(pb|pbi)$" +## variables +icolor green "[A-Za-z_][0-9A-Za-z_]*" +icolor green "[A-Za-z_][0-9A-Za-z_]*\$" +icolor green "\*[A-Za-z_][0-9A-Za-z_]*" +icolor brightgreen "\#[A-Za-z_][0-9A-Za-z_]*" +## keywords +### abc_ +icolor brightred "(includefile|xincludefile|debug|swap|define|dim|redim|array|newlist|list|newmap|map|goto|gosub|compilererror)[[:space:]]" +icolor brightred "(not|declare|if|elseif|select|case|while|for|repeat|procedure|procedurec|procedureunknown|runtime|threaded|global|protected|shared)[[:space:]]" +icolor brightred "(static|procedurereturn|macro|prototype|structure|interface|data|pseudotype|import|with|declaremodule)[[:space:]]" +icolor brightred "(module|usemodule|unusemodule|compilerif|compilerselect|compilercase|compilerelseif|includepath|includebinary)[[:space:]]" +### abc +icolor brightred "(use16|use32|use64|enumeration|compilerendif|compilerendselect|return|fakereturn|default|break|continue|structureunion|datasection|wend)" +icolor brightred "(endselect|until|endprocedure|endprocedurec|endprocedureunknownendmacro|endstructureunion|endstructure|endinterface|enddatasection|else|compilerelse)" +icolor brightred "(calldebugger|debuglevel|disabledebugger|enabledebugger|endenumeration|enddatasection|enddeclaremodule|endmodul|endwith)" +icolor brightred "(next|end|endif|enableexplicit|disableexplicit|enableasm|disableasm|endimport|endmacro)" +### _abc_ +icolor brightred "[[:space:]](to|step|extends)[[:space:]]" +icolor brightred "[[:space:]](or|xor|and)([[:space:]]|$)" +## types +icolor brightgreen "\.[A-Za-z_][0-9A-Za-z_]*" +## special +icolor brightmagenta "([[:space:]]|\@|\?|\[|^)([A-Za-z]|\*self|self|\*this|this|tmp|\*void|void|void\$)([[:space:]]|,|\\|\]|\.|$)" +## number +icolor brightyellow "[[:space:]]\%[01]+" +icolor brightyellow "[[:space:]][0-9]*" +icolor brightyellow "[[:space:]]\$[0-9A-Fa-f]+" +icolor brightyellow "\[\%[01]+\]" +icolor brightyellow "\[[0-9]+\]" +icolor brightyellow "\[\$[0-9A-Fa-f]+\]" +icolor brightyellow "\{\%[01]+\}" +icolor brightyellow "\{[0-9]+\}" +icolor brightyellow "\{\$[0-9A-Fa-f]+\}" +## operators +icolor brightcyan "[A-Za-z_][0-9A-Za-z_]*[[:space:]]*\(\)?" +icolor brightcyan "[[:space:]](-|<|<<|<=|<>|=>|>>|>|\%|\!|\?|\&|\:|\@|\=|\+|\*|\/|[\(]*|[\)]*|\|)" +icolor brightcyan "(,|\.|\\|\[*|\]*)" +## assembler +icolor magenta "^[[:space:]]*\!.*$" +## labels +icolor brightred "[A-Za-z_][0-9A-Za-z_]*\:" +## strings +icolor brightyellow "[[:space:]]\"[^"]*\"" +icolor brightyellow "[[:space:]]\'[^']*\'" +## remarks +icolor white ";.*$" +icolor brightwhite ";(\{|\}|\(|\)|\[|\]|;).*$" +## useless spaces +color ,green "[[:space:]]+$" + +#icolor red "HALLO" diff --git a/users/sivizius/config/programs/nano/yasic.nanorc b/users/sivizius/config/programs/nano/yasic.nanorc new file mode 100644 index 0000000..f2ef146 --- /dev/null +++ b/users/sivizius/config/programs/nano/yasic.nanorc @@ -0,0 +1,15 @@ +syntax "yasic" +header "^#\!sba:(yasic)$" + +icolor brightred "^[[:space:]]*[0-9A-Za-z_.]*$" +icolor brightmagenta "^[[:space:]]*[0-9A-Za-z_.]*[[:space:]]*=" +icolor white "(#|//).*$" +icolor brightgreen "(^|=|\{|;)[[:space:]]*[0-9A-Za-z_.]*[[:space:]]*\(" +icolor brightwhite "^#.*$" +icolor brightyellow "(0([bB][01]+|[xX][0-9a-fA-F]+|[oO][0-7]+|[0-9]*|[01]*[bB]|[0-7]*[oO]|[0-9f-fA-F]*[hH])|[1-9][0-9]*|1[01]*[bB]|[1-7][0-7]*[oO]|[1-9][0-9f-fA-F]*[hH]|'[^']*')" +color ,yellow "\\." +color yellow "\\(0|\\|a|b|d|D|e|f|n|q|Q|r|s|S|t|v|w|W|x[0-9A-Fa-f]*\\?)" +icolor brightblue "<[0-9a-z_.]*>" +icolor brightcyan "(\{|\[|\(|=|,|;|\||\)|\]|\})" +color ,yellow "\\(=|\$|\{|\})" +icolor ,green "[[:space:]]+$" diff --git a/users/sivizius/config/programs/neomutt.nix b/users/sivizius/config/programs/neomutt.nix new file mode 100644 index 0000000..356704b --- /dev/null +++ b/users/sivizius/config/programs/neomutt.nix @@ -0,0 +1,63 @@ +{ config, core, profile, user, ... }: +{ email, ... }: + let + inherit(core) list path set string; + mailDir = email.maildirBasePath; + mailAccounts = email.accounts; + in + { + enable = profile.isDesktop; + binds + = [ + { key = ">"; action = "sidebar-open"; map = [ "index" "pager" ]; } + { key = "<"; action = "sidebar-toggle-visible"; map = [ "index" "pager" ]; } + { key = ""; action = "sidebar-next"; map = [ "index" "pager" ]; } + { key = ""; action = "sidebar-prev"; map = [ "index" "pager" ]; } + { key = ""; action = "sidebar-prev-new"; map = [ "index" "pager" ]; } + { key = ""; action = "sidebar-page-down"; map = [ "index" "pager" ]; } + { key = ""; action = "sidebar-page-up"; map = [ "index" "pager" ]; } + { key = ""; action = "sidebar-next-new"; map = [ "index" "pager" ]; } + { key = "-"; action = "check-stats"; map = [ "index" "pager" ]; } + ]; + checkStatsInterval = 300; + extraConfig + = '' + set date_format = "%Y-%m-%d" + set pipe_decode = yes + set crypt_replyencrypt + set crypt_replysign + set crypt_replysignencrypted + set delete = ask-yes; + ${path.readFile ./assets/colours.muttrc} + ''; + macros + = [ + { + key = "+"; + action = "unset wait_key!mbsync -a &> /dev/null&:echo 'Sync All Mailboxes'"; + map = [ "index" "pager" ]; + } + { + key = ""; + action = "| w3m -T text/html"; + map = [ "pager" ]; + } + ] + ++ list.imap + ( + index: + accountName: + { + key = ""; + action = "${mailDir}/${accountName}/INBOX"; + map = [ "index" ]; + } + ) + ( set.names mailAccounts ); + sidebar + = { + enable = true; + format = "%B%?F? [%F]?%* %?N?%N/?%S"; + }; + sort = "reverse-date-received"; + } diff --git a/users/sivizius/config/programs/ssh.nix b/users/sivizius/config/programs/ssh.nix new file mode 100644 index 0000000..9c6c4bb --- /dev/null +++ b/users/sivizius/config/programs/ssh.nix @@ -0,0 +1,27 @@ +{ /*user,*/ ... }: + /*let + /*default + = { user, hostname, identityFile }: + { + checkHostIP = true; + compression = true; + forwardAgent = false; + forwardX11 = false; + identitiesOnly = false; + sendEnv = [ ]; + user = username; + inherit hostname identityFile; + }; + in*/ + { + enable = true; + controlMaster = "auto"; + controlPersist = "10m"; + hashKnownHosts = true; + matchBlocks + = { +# "aleph" = default { identityFile = ""; user = user.name; hostname = "aleph.sivizius.eu"; }; +# "*.sivizius.eu" = default { identityFile = ""; user = user.name; hostname = "%h"; }; + }; + userKnownHostsFile = "~/.local/share/ssh/known_hosts"; + } diff --git a/users/sivizius/config/programs/zsh.nix b/users/sivizius/config/programs/zsh.nix new file mode 100644 index 0000000..99601a8 --- /dev/null +++ b/users/sivizius/config/programs/zsh.nix @@ -0,0 +1,90 @@ +{ + autocd = true; + cdpath + = [ + ]; + completionInit + = '' + ''; + defaultKeymap = null; + dirHashes + = { + active = "$HOME/Projects/Active"; + foreign = "$HOME/Projects/Foreign"; + keys = "$HOME/Keys"; + }; + dotDir = ".config/zsh"; + enable = true; + enableAutosuggestions = true; + enableCompletion = true; + enableSyntaxHighlighting = true; + enableVteIntegration = false; + envExtra + = '' + NIX_SSHOPTS="-t" + ''; + history + = { + expireDuplicatesFirst = true; + extended = true; + ignoreDups = true; + ignorePatterns + = [ + ]; + ignoreSpace = false; + path = "$HOME/.cache/zsh/history.log"; + save = 65536; + share = true; + size = 65536; + }; + historySubstringSearch + = { + enable = true; + searchDownKey = "^[[B"; + searchUpKey = "^[[A"; + }; + initExtra + = '' + ''; + initExtraBeforeCompInit + = '' + ''; + initExtraFirst + = '' + ''; + localVariables + = { + }; + loginExtra + = '' + ''; + logoutExtra + = '' + ''; + oh-my-zsh + = { + custom = ""; + enable = true; + extraConfig + = '' + ''; + plugins + = [ + "git" + "pass" + ]; + theme = "candy"; + }; + plugins + = [ + ]; + prezto + = { + }; + profileExtra + = '' + ''; + sessionVariables + = { + }; +} diff --git a/users/sivizius/config/services/default.nix b/users/sivizius/config/services/default.nix new file mode 100644 index 0000000..092f6a4 --- /dev/null +++ b/users/sivizius/config/services/default.nix @@ -0,0 +1,31 @@ +{ core, ... } @ env: + let + inherit(core) path; + in + { + gpg-agent + = { + enable = true; + enableBashIntegration = true; + enableExtraSocket = false; + enableScDaemon = true; + enableSshSupport = true; + enableZshIntegration = true; + defaultCacheTtl = 60 * 2; # 2 minutes + defaultCacheTtlSsh = 60 * 2; # 2 minutes + grabKeyboardAndMouse = true; + maxCacheTtl = 60 * 60; # 60 minutes + maxCacheTtlSsh = 60 * 60; # 60 minutes + pinentryFlavor = "gtk2"; + sshKeys + = [ + "DEEE6586C847CF09A204714BFC23BF127D62006C" # sivizius@sivizius.eu, sivizius@aleph.sivizius.eu + "FDCE333287DC03BE9310F4028ADC2A58F7A24CB0" # sivizius@github.com + "52741DDC13174BFDE1C0E7F7C3621FF942446CFF" # sivizius@git.sivizius.eu:2222 + "749401CEE75CEBE3A588273C6A7D24794D6C8229" # infra.run + ]; + verbose = false; + }; + mako = path.import ./mako.nix env; + redshift = path.import ./redshift.nix env; + } diff --git a/users/sivizius/config/services/mako.nix b/users/sivizius/config/services/mako.nix new file mode 100644 index 0000000..cb58d1a --- /dev/null +++ b/users/sivizius/config/services/mako.nix @@ -0,0 +1,11 @@ +{ profile, ... }: +{ + enable = profile.isDesktop; + backgroundColor = "#00000070"; + borderColor = "#ffffffff"; + defaultTimeout = 16000; + font = "pango:\"Font Awesome 5 Free 100\",RobotoMono10,NotoColorEmoji10"; + maxVisible = 2; + sort = "-time"; + textColor = "#ffffffff"; +} diff --git a/users/sivizius/config/services/redshift.nix b/users/sivizius/config/services/redshift.nix new file mode 100644 index 0000000..1cb9d52 --- /dev/null +++ b/users/sivizius/config/services/redshift.nix @@ -0,0 +1,8 @@ +{ profile, registries, ... }: +{ + enable = profile.isDesktop; + package = registries.custom.redshift-wayland; + tray = true; + latitude = "50.85"; + longitude = "12.95"; +} diff --git a/users/sivizius/config/shellAliases.nix b/users/sivizius/config/shellAliases.nix new file mode 100644 index 0000000..4e46e8a --- /dev/null +++ b/users/sivizius/config/shellAliases.nix @@ -0,0 +1,111 @@ +{ core, profile, registries, secret, ... }: + let + inherit(core) bool set string; + lt = "${registries.nix.exa}/bin/exa -lahTL"; + in + { + edit + = bool.select + profile.isDesktop + "${registries.nix.vscodium}/bin/codium" + "${registries.nix.nano}/bin/nano"; + enby = "${registries.nix.man-db}/bin/man"; + frg + = '' + :(){ + unset -f : + if [ "$#" -ne "0" ] + then + regex="$1" + shift 1 + echo "find: $@" + echo "regex: $regex" + ${registries.nix.findutils}/bin/find $@ | ${registries.nix.ripgrep}/bin/rg $regex + else + echo "$0 regex [find-options]" + fi + };:\ + ''; + fuck + = '' + :(){ + unset -f : + TF_PYTHONIOENCODING=$PYTHONIOENCODING; + export TF_SHELL=${registries.nix.zsh}/bin/zsh; + export TF_ALIAS=fuck; + TF_SHELL_ALIASES=$(alias); + export TF_SHELL_ALIASES; + TF_HISTORY="$(fc -ln -10)"; + export TF_HISTORY; + export PYTHONIOENCODING=utf-8; + TF_CMD=$(thefuck THEFUCK_ARGUMENT_PLACEHOLDER $@) && eval $TF_CMD; + unset TF_HISTORY; + export PYTHONIOENCODING=$TF_PYTHONIOENCODING; + test -n "$TF_CMD" && print -s $TF_CMD + };:\ + ''; + l = "${registries.nix.exa}/bin/exa -l@ah"; + inherit lt; + man + = '' + :(){ + unset -f : + echo "Use" + echo " enby $@" + echo "Fight teh cistem!" + };:\ + ''; + nixsh = "${registries.nix.nix}/bin/nix-shell --run ${registries.nix.zsh}/bin/zsh "; + please = "${registries.nix.sudo}/bin/sudo"; + py = "${registries.python3.ipython}/bin/ipython"; + rainbow + = '' + for x in {0..8} + do + for i in {30..37} + do + for a in {40..47} + do + echo -ne "\e[$x;$i;$a""m\\\e[$x;$i;$a""m\e[0;37;40m " + done + echo "" + done + done + ''; + use + = string.concatWords + [ + "${registries.nix.nix}/bin/nix-shell" + "-I nixpkgs=https://github.com/sivizius/nixpkgs/archive/master.tar.gz" + "--run ${registries.nix.zsh}/bin/zsh" + "--packages " + ]; + useFrom + = '' + + "${registries.nix.nix}/bin/nix-shell" + "-I nixpkgs=https://github.com/sivizius/nixpkgs/archive/master.tar.gz" + "--run ${registries.nix.zsh}/bin/zsh" + "--packages " + ''; + usePure + = string.concatWords + [ + "${registries.nix.nix}/bin/nix-shell" + "-I nixpkgs=https://github.com/sivizius/nixpkgs/archive/master.tar.gz" + "--run ${registries.nix.zsh}/bin/zsh" + "--pure" + "--packages " + ]; + } + // ( + set.generate + ( + index: + { + name = "l${string (index + 1)}"; + value = "${lt}${string (index + 1)}"; + } + ) + 9 + ) diff --git a/users/sivizius/config/sway/assets/Crater_Cluster.png b/users/sivizius/config/sway/assets/Crater_Cluster.png new file mode 100644 index 0000000..07c17a3 Binary files /dev/null and b/users/sivizius/config/sway/assets/Crater_Cluster.png differ diff --git a/users/sivizius/config/sway/assets/il.xkb b/users/sivizius/config/sway/assets/il.xkb new file mode 100644 index 0000000..4f30658 --- /dev/null +++ b/users/sivizius/config/sway/assets/il.xkb @@ -0,0 +1,68 @@ +default +xkb_symbols "qwertz" { + name[Group1]="Hebrew (QWERTZ)"; + + # UFB21 /* Wide Alef */ + # UFB22 /* Wide Dalet */ + # UFB23 /* Wide He */ + # UFB24 /* Wide Kaf */ + # UFB25 /* Wide Lamed */ + # UFB26 /* Wide Final Mem */ + # UFB27 /* Wide Resh */ + # UFB28 /* Wide Taw */ + + key { [ 1, exclam, U05BD /* Meteg */, exclamdown ] }; + key { [ 2, quotedbl, U05F4 /* Gereshayim */, NoSymbol ] }; + key { [ 3, section, paragraph, sterling ] }; + key { [ 4, dollar, cent, currency ] }; + key { [ 5, percent, U2030 /* ‰ */, U2031 /* ‱ */ ] }; + key { [ 6, ampersand, notsign, copyleft ] }; + key { [ 7, slash, braceright, yen ] }; + key { [ 8, parenright, bracketright, trademark ] }; + key { [ 9, parenleft, bracketleft, plusminus ] }; + key { [ 0, equal, braceleft, oslash ] }; + key { [ U20AA /* ₪ */, question, backslash, questiondown ] }; + key { [ U05B5 /* Zeire ē */, U05B6 /* Segol é */, U05B1 /* Hataf Segol ĕ */, UFB1E /* Varika */ ] }; + + key { [ hebrew_qoph, UFB47 /* Qof with dagesh */, at, UFB4D /* Kaf with rafe */ ] }; + key { [ hebrew_waw, UFB35 /* Waw with dagesh */, NoSymbol, U05C2 /* Sin dot */ ] }; + key { [ hebrew_ayin, UFB20 /* Alternative Ayin */, EuroSign, U05C1 /* Shin dot */ ] }; + key { [ hebrew_resh, UFB48 /* Resh with dagesh */, U05BF /* Rafe */, registered ] }; + key { [ hebrew_taw, UFB4A /* Taw with dagesh */, hebrew_tet, UFB38 /* Tet with dagesh */ ] }; + key { [ hebrew_zade, UFB46 /* Zade with dagesh */, hebrew_finalzade, NoSymbol ] }; + key { [ hebrew_waw, U05F0 /* Double Waw */, UFB4B /* Waw with holam */, /* Holam for waw ō */ ] }; + key { [ U05F1 /* Waw-Yod */, UFB1D /* Yod with Hiriq */, U05B4 /* Hiriq i */, U05EF /* Yod Triangle */ ] }; + key { [ hebrew_samech, UFB41 /* Samech with dagesh */, NoSymbol, NoSymbol ] }; + key { [ hebrew_pe, UFB44 /* Pe with dagesh */, UFB4E /* Pe with rafe */, U05C3 /* Sof Pasuq ׃ */ ] }; + key { [ U05BE /* Maqaf ־ */, U05BB /* Kubutz ú */, U05BC /* Shuruk û */, NoSymbol ] }; + key { [ plus, asterisk, asciitilde, UFB29 /* Alternative Plus */ ] }; + + key { [ hebrew_aleph, UFB2E /* Aleph Patach */, UFB2F /* Aleph Kamatz */, UFB30 /* Alef Mapiq */ ] }; + key { [ hebrew_shin, UFB49 /* Shin/Sin with dagesh */, UFB2B /* Sin with dot */, UFB2D /* Sin with dagesh */ ] }; + key { [ hebrew_dalet, UFB33 /* Dalet with dagesh */, UFB2A /* Shin with dot */, UFB2C /* Shin with dagesh */ ] }; + key { [ hebrew_finalpe, UFB43 /* Final Pe with dagesh */, masculine, ordfeminine ] }; + key { [ hebrew_gimel, UFB32 /* Gimel with dagesh */, NoSymbol, NoSymbol ] }; + key { [ hebrew_he, UFB34 /* He with mapiq */, U210F /* Planck ℏ */, NoSymbol ] }; + key { [ hebrew_yod, UFB39 /* Yod with dagesh */, U05F2 /* Double Yod */, UFB1F /* Yod Yod Patach */ ] }; + key { [ hebrew_kaph, UFB3B /* Kaf with dagesh */, hebrew_finalkaph, UFB3A /* Final Kaf with dagesh */ ] }; + key { [ hebrew_lamed, UFB3C /* Lamed with dagesh */, NoSymbol, UFB4F /* Alef-Lamed */ ] }; + key { [ U05B9 /* Holam ō */, U05C7 /* Kamatz Katan o */, U05B3 /* Hataf Kamatz ŏ */, NoSymbol ] }; + key { [ U05B8 /* Kamatz Gadol ā */, U05B7 /* Patach á */, U05B2 /* Hataf Patach ă */ NoSymbol ] }; + key { [ dead_circumflex, degree, U05C5 /* Lower dot */, U05C4 /* Upper dot */ ] }; + + key { [ numbersign, apostrophe, U05F3 /* Geresh */, grave ] }; + key { [ U05B0 /* Sh'va */, U05BC /* Dagesh */, guillemotleft, U203A /* › */ ] }; + key { [ hebrew_chet, NoSymbol, guillemotright, U2039 /* ‹ */ ] }; + key { [ hebrew_zain, UFB36 /* Zayin with dagesh */, doublelowquotemark, singlelowquotemark ] }; + key { [ hebrew_bet, UFB4C /* Bet with rafe */, leftdoublequotemark, leftsinglequotemark ] }; + key { [ UFB31 /* Bet with dagesh */, NoSymbol, rightdoublequotemark, rightsinglequotemark ] }; + key { [ hebrew_nun, UFB40 /* Nun with dagesh */, hebrew_finalnun, U05C6 /* Nun Hafukha */ ] }; + key { [ hebrew_mem, UFB3E /* Mem with dagesh */, hebrew_finalmem, masculine ] }; + key { [ comma, semicolon, periodcentered, multiply ] }; + key { [ period, colon, U2026 /* … */, division ] }; + key { [ minus, underscore, endash, emdash ] }; + key { [ less, greater, bar, U05C0 /* Paseq ׀ */ ] }; + + include "kpdl(comma)" + include "level3(ralt_switch)" +} diff --git a/users/sivizius/config/sway/assets/otter.png b/users/sivizius/config/sway/assets/otter.png new file mode 100644 index 0000000..2898913 Binary files /dev/null and b/users/sivizius/config/sway/assets/otter.png differ diff --git a/users/sivizius/config/sway/assets/waybar/config.json b/users/sivizius/config/sway/assets/waybar/config.json new file mode 100644 index 0000000..e561ac8 --- /dev/null +++ b/users/sivizius/config/sway/assets/waybar/config.json @@ -0,0 +1,138 @@ +{ + "layer": "bottom", + "position": "top", + "modules-left": [ "sway/workspaces", "sway/mode", "custom/media" ], + "modules-center": [ "sway/window" ], + "modules-right": [ "tray", "idle_inhibitor", "pulseaudio", "network", "cpu", "memory", "temperature", "backlight", "battery", "clock" ], + "sway/mode": + { + "format": "{}" + }, + "mpd": + { + "format": " {stateIcon} {consumeIcon}{randomIcon}{repeatIcon}{singleIcon}{artist} – {album} – {title} ({elapsedTime:%M:%S}/{totalTime:%M:%S})", + "format-disconnected": " Disconnected", + "format-stopped": " {consumeIcon}{randomIcon}{repeatIcon}{singleIcon}Stopped", + "unknown-tag": "N/A", + "interval": 2, + "consume-icons": + { + "on": " " + }, + "random-icons": + { + "off": " ", + "on": " " + }, + "repeat-icons": + { + "on": " " + }, + "single-icons": + { + "on": "1 " + }, + "state-icons": + { + "paused": "", + "playing": "" + }, + "tooltip-format": "MPD (connected)", + "tooltip-format-disconnected": "MPD (disconnected)" + }, + "idle_inhibitor": + { + "format": "{icon}", + "format-icons": + { + "activated": "", + "deactivated": "" + } + }, + "tray": + { + "spacing": 10 + }, + "clock": + { + "format": "{:%Y-%m-%dT%H:%M:%S%z}", + "interval": 1, + "tooltip-format": "{:%A %e. %B %Y, %H:%M:%S %Z}" + }, + "cpu": + { + "format": " {usage}%", + "tooltip": false + }, + "memory": + { + "format": " {}%" + }, + "temperature": + { + "critical-threshold": 80, + "format": "{icon} {temperatureC}°C", + "format-icons": ["", "", ""] + }, + "backlight": + { + "format": "{icon} {percent}%", + "format-icons": ["", ""], + "on-click": "brightnessctl set +5%", + "on-click-middle": "brightnessctl set 50%", + "on-click-right": "brightnessctl set 5%-" + }, + "battery": + { + "states": + { + "warning": 30, + "critical": 15 + }, + "format": "{icon} {capacity}%", + "format-charging": " {capacity}%", + "format-plugged": " {capacity}%", + "format-alt": "{icon} {time}", + "format-icons": ["", "", "", "", ""] + }, + "bluetooth": + { + "format": "{icon}", + "format-alt": "{icon} {status}", + "format-icons": + { + "enabled": "", + "disabled": "" + }, + "interval": 30, + "tooltip-format": "{status}" + }, + "network": + { + "format-wifi": " {essid} ({signalStrength}%)", + "format-ethernet": " {ifname}: {ipaddr}/{cidr}", + "format-linked": " {ifname} (No IP)", + "format-disconnected": "Disconnected ⚠", + "format-alt": "{ifname}: {ipaddr}/{cidr}" + }, + "pulseaudio": + { + "format": "{icon} {volume}% {format_source}", + "format-bluetooth": "{icon} {volume}% {format_source}", + "format-bluetooth-muted": " {icon} {format_source}", + "format-muted": " {format_source}", + "format-source": " {volume}%", + "format-source-muted": "", + "format-icons": + { + "headphones": "", + "handsfree": "", + "headset": "", + "phone": "", + "portable": "", + "car": "", + "default": ["", "", ""] + }, + "on-click": "pavucontrol" + } +} diff --git a/users/sivizius/config/sway/assets/waybar/mediaplayer.py b/users/sivizius/config/sway/assets/waybar/mediaplayer.py new file mode 100644 index 0000000..cf3df4b --- /dev/null +++ b/users/sivizius/config/sway/assets/waybar/mediaplayer.py @@ -0,0 +1,127 @@ +#!/usr/bin/env python3 +import argparse +import logging +import sys +import signal +import gi +import json +gi.require_version('Playerctl', '2.0') +from gi.repository import Playerctl, GLib + +logger = logging.getLogger(__name__) + + +def write_output(text, player): + logger.info('Writing output') + + output = {'text': text, + 'class': 'custom-' + player.props.player_name, + 'alt': player.props.player_name} + + sys.stdout.write(json.dumps(output) + '\n') + sys.stdout.flush() + + +def on_play(player, status, manager): + logger.info('Received new playback status') + on_metadata(player, player.props.metadata, manager) + + +def on_metadata(player, metadata, manager): + logger.info('Received new metadata') + track_info = '' + + if player.props.player_name == 'spotify' and \ + 'mpris:trackid' in metadata.keys() and \ + ':ad:' in player.props.metadata['mpris:trackid']: + track_info = 'AD PLAYING' + elif player.get_artist() != '' and player.get_title() != '': + track_info = '{artist} - {title}'.format(artist=player.get_artist(), + title=player.get_title()) + else: + track_info = player.get_title() + + if player.props.status != 'Playing' and track_info: + track_info = ' ' + track_info + write_output(track_info, player) + + +def on_player_appeared(manager, player, selected_player=None): + if player is not None and (selected_player is None or player.name == selected_player): + init_player(manager, player) + else: + logger.debug("New player appeared, but it's not the selected player, skipping") + + +def on_player_vanished(manager, player): + logger.info('Player has vanished') + sys.stdout.write('\n') + sys.stdout.flush() + + +def init_player(manager, name): + logger.debug('Initialize player: {player}'.format(player=name.name)) + player = Playerctl.Player.new_from_name(name) + player.connect('playback-status', on_play, manager) + player.connect('metadata', on_metadata, manager) + manager.manage_player(player) + on_metadata(player, player.props.metadata, manager) + + +def signal_handler(sig, frame): + logger.debug('Received signal to stop, exiting') + sys.stdout.write('\n') + sys.stdout.flush() + # loop.quit() + sys.exit(0) + + +def parse_arguments(): + parser = argparse.ArgumentParser() + + # Increase verbosity with every occurence of -v + parser.add_argument('-v', '--verbose', action='count', default=0) + + # Define for which player we're listening + parser.add_argument('--player') + + return parser.parse_args() + + +def main(): + arguments = parse_arguments() + + # Initialize logging + logging.basicConfig(stream=sys.stderr, level=logging.DEBUG, + format='%(name)s %(levelname)s %(message)s') + + # Logging is set by default to WARN and higher. + # With every occurrence of -v it's lowered by one + logger.setLevel(max((3 - arguments.verbose) * 10, 0)) + + # Log the sent command line arguments + logger.debug('Arguments received {}'.format(vars(arguments))) + + manager = Playerctl.PlayerManager() + loop = GLib.MainLoop() + + manager.connect('name-appeared', lambda *args: on_player_appeared(*args, arguments.player)) + manager.connect('player-vanished', on_player_vanished) + + signal.signal(signal.SIGINT, signal_handler) + signal.signal(signal.SIGTERM, signal_handler) + + for player in manager.props.player_names: + if arguments.player is not None and arguments.player != player.name: + logger.debug('{player} is not the filtered player, skipping it' + .format(player=player.name) + ) + continue + + init_player(manager, player) + + loop.run() + + +if __name__ == '__main__': + main() diff --git a/users/sivizius/config/sway/assets/waybar/style.css b/users/sivizius/config/sway/assets/waybar/style.css new file mode 100644 index 0000000..400dea1 --- /dev/null +++ b/users/sivizius/config/sway/assets/waybar/style.css @@ -0,0 +1,227 @@ +* +{ + border: none; + border-radius: 0; + font-family: "Roboto Mono", "Font Awesome 5 Free"; + font-size: 13px; + min-height: 0; +} + +window#waybar +{ + background-color: rgba(43, 48, 59, 0.5); + border-bottom: 3px solid rgba(100, 114, 125, 0.5); + color: #ffffff; + transition-property: background-color; + transition-duration: .5s; +} + +window#waybar.hidden +{ + opacity: 0.2; +} + +window#waybar.termite +{ + background-color: #3f3f3f; +} + +window#waybar.chromium +{ + background-color: #000000; + border: none; +} + +#workspaces button +{ + padding: 0 5px; + background-color: transparent; + color: #ffffff; + border-bottom: 0px solid transparent; +} + +#workspaces button:hover +{ + background: rgba(0, 0, 0, 0.2); + box-shadow: inherit; + border-bottom: 0px solid #ffffff; +} + +#workspaces button.focused +{ + background-color: #64727D; + border-bottom: 0px solid #ffffff; +} + +#workspaces button.urgent +{ + background-color: #eb4d4b; +} + +#mode +{ + background-color: #64727D; + border-bottom: 0px solid #ffffff; +} + +#clock, +#battery, +#cpu, +#memory, +#temperature, +#backlight, +#network, +#pulseaudio, +#custom-media, +#tray, +#mode, +#idle_inhibitor +{ + padding: 0 10px; + margin: 0 4px; + color: #ffffff; +} + +#clock +{ + background-color: #64727D; +} + +#battery +{ + background-color: #ffffff; + color: #000000; +} + +#battery.charging +{ + color: #ffffff; + background-color: #26A65B; +} + +@keyframes blink +{ + to + { + background-color: #ffffff; + color: #000000; + } +} + +#battery.critical:not(.charging) +{ + background-color: #f53c3c; + color: #ffffff; + animation-name: blink; + animation-duration: 0.5s; + animation-timing-function: linear; + animation-iteration-count: infinite; + animation-direction: alternate; +} + +label:focus +{ + background-color: #000000; +} + +#cpu +{ + background-color: #2ecc71; + color: #000000; +} + +#memory +{ + background-color: #9b59b6; +} + +#backlight +{ + background-color: #90b1b1; +} + +#network +{ + background-color: #2980b9; +} + +#network.disconnected +{ + background-color: #f53c3c; +} + +#pulseaudio +{ + background-color: #f1c40f; + color: #000000; +} + +#pulseaudio.muted +{ + background-color: #90b1b1; + color: #2a5c45; +} + +#custom-media +{ + background-color: #66cc99; + color: #2a5c45; + min-width: 100px; +} + +#custom-media.custom-spotify +{ + background-color: #66cc99; +} + +#custom-media.custom-vlc +{ + background-color: #ffa000; +} + +#temperature +{ + background-color: #f0932b; +} + +#temperature.critical +{ + background-color: #eb4d4b; +} + +#tray +{ + background-color: #2980b9; +} + +#idle_inhibitor +{ + background-color: #2d3436; +} + +#idle_inhibitor.activated +{ + background-color: #ecf0f1; + color: #2d3436; +} + +#mpd +{ + background-color: #66cc99; + color: #2a5c45; +} + +#mpd.disconnected +{ + background-color: #f53c3c; +} + +#mpd.stopped +{ + background-color: #90b1b1; +} + +#mpd.paused +{ + background-color: #51a37a; +} diff --git a/users/sivizius/config/sway/assets/wofi.css b/users/sivizius/config/sway/assets/wofi.css new file mode 100644 index 0000000..c51f737 --- /dev/null +++ b/users/sivizius/config/sway/assets/wofi.css @@ -0,0 +1,39 @@ +/* This stylesheet originated by PetaByteBoy https://pbb.lc/ */ + +#input +{ + color: white; + padding: .5em; + margin-bottom: 2em; + border: 1px solid white; + border-radius: 2px; + background-color: rgba(0, 0, 0, 0); +} + +#outer-box +{ + padding: 2em; +} + +#window +{ + background: rgba(0, 0, 0, .8); + color: white; + border: 2px solid white; +} + +expander +{ + margin-left: -15px; +} + +.entry > * +{ + padding: .5em; +} + +#entry:selected +{ + background: rgba(255, 255, 255, .1); + border: none; +} diff --git a/users/sivizius/config/sway/assets/xkb b/users/sivizius/config/sway/assets/xkb new file mode 100644 index 0000000..700c8fd --- /dev/null +++ b/users/sivizius/config/sway/assets/xkb @@ -0,0 +1,69 @@ +default +xkb_symbols "qwertz" { + name[Group1]="Hebrew (QWERTZ)"; + + key { [ 1, exclam, NoSymbol, exclamdown ] }; + key { [ 2, quotedbl, NoSymbol, NoSymbol ] }; + key { [ 3, section, NoSymbol, sterling ] }; + key { [ 4, dollar, NoSymbol, currency ] }; + key { [ 5, percent, U2030 /* ‰ */, U2031 /* ‱ */ ] }; + key { [ 6, ampersand, notsign, NoSymbol ] }; + key { [ 7, slash, braceright, NoSymbol ] }; + key { [ 8, parenright, bracketright, trademark ] }; + key { [ 9, parenleft, bracketleft, plusminus ] }; + key { [ 0, equal, braceleft, degree ] }; + key { [ NoSymbol, question, backslash, questiondown ] }; + key { [ NoSymbol, NoSymbol, NoSymbol, NoSymbol ] }; + + key { [ hebrew_qoph, at, U05BB /* Kubutz */, Greek_OMEGA ] }; + key { [ hebrew_waw, W, NoSymbol, NoSymbol ] }; + key { [ hebrew_ayin, E, EuroSign, cent ] }; + key { [ hebrew_resh, R, paragraph, registered ] }; + key { [ hebrew_taw, T, NoSymbol, NoSymbol ] }; + key { [ hebrew_zain, Z, rightarrow, yen ] }; + key { [ hebrew_waw, U, downarrow, uparrow ] }; + key { [ hebrew_yod, I, leftarrow, NoSymbol ] }; + key { [ hebrew_waw, O, U05B9 /* Holam */, oslash ] }; + key { [ hebrew_pe, hebrew_finalpe, U05B7 /* Patach */, U05B2 /* Hataf Patach */ ] }; + key { [ NoSymbol, NoSymbol, NoSymbol, NoSymbol ] }; + key { [ plus, asterisk, asciitilde, macron ] }; + +# hebrew_samech +# hebrew_tet +# hebrew_shin + +# U05B0 /* Sh'va */ shin +# U05B1 /* Hataf Segol */ samech +# U05B6 /* Segol */ +# U05C2 /* Shin Smalit */ +# U05C1 /* Shin Yimanit */ + + key { [ hebrew_aleph, A, U05B8 /* Kamatz */, U05B3 /* Hataf Kamatz */ ] }; + key { [ hebrew_, S, NoSymbol, section ] }; + key { [ hebrew_dalet, D, U05BC /* Dagesh */, NoSymbol ] }; + key { [ hebrew_pe, hebrew_finalpe, NoSymbol, ordfeminine ] }; + key { [ hebrew_gimel, G, NoSymbol, NoSymbol ] }; + key { [ hebrew_he, U210F /* ℏ */, U05B4 /* Hiriq */, ] }; + key { [ hebrew_yod, J, NoSymbol, NoSymbol ] }; + key { [ hebrew_kaph, hebrew_finalkaph, ] }; + key { [ hebrew_lamed, L, NoSymbol, NoSymbol ] }; + key { [ NoSymbol, NoSymbol, NoSymbol, NoSymbol ] }; + key { [ NoSymbol, NoSymbol, NoSymbol, NoSymbol ] }; + key { [ asciicircum, NoSymbol, NoSymbol, NoSymbol ] }; + + key { [ numbersign, apostrophe, NoSymbol, grave ] }; + key { [ hebrew_zade, hebrew_finalzade, guillemotleft, U203A /* › */ ] }; + key { [ hebrew_chet, X, guillemotright, U2039 /* ‹ */ ] }; + key { [ c, C, U05B5 /* Zeire */, copyleft ] }; + key { [ hebrew_bet, V, doublelowquotemark, singlelowquotemark ] }; + key { [ hebrew_bet, B, rightdoublequotemark, rightsinglequotemark ] }; + key { [ hebrew_nun, hebrew_finalnun, leftdoublequotemark, leftsinglequotemark ] }; + key { [ hebrew_mem, hebrew_finalmem, mu, masculine ] }; + key { [ comma, semicolon, periodcentered, multiply ] }; + key { [ period, colon, U2026 /* … */, division ] }; + key { [ minus, underscore, endash, emdash ] }; + key { [ less, greater, bar, NoSymbol ] }; + + include "kpdl(comma)" + include "level3(ralt_switch)" +} diff --git a/users/sivizius/config/sway/assigns.nix b/users/sivizius/config/sway/assigns.nix new file mode 100644 index 0000000..bdddd77 --- /dev/null +++ b/users/sivizius/config/sway/assigns.nix @@ -0,0 +1,36 @@ +let + wsWebBrowser = "0"; + wsFileBrowser = "1"; + wsMailClient = "2"; + wsMessenger = "3"; + wsDevelopment = "4"; +in +{ + ${wsWebBrowser} + = [ + { app_id = "^firefox$"; } + { class = "^Spotify$"; } + ]; + ${wsFileBrowser} + = [ + { title = "^ranger$"; } + ]; + ${wsMailClient} + = [ + { title = "^neomutt$"; } + ]; + ${wsMessenger} + = [ + { app_id = "^org.telegram.desktop$"; } + { app_id = "^dino$"; } + { title = "^nheko"; } + { class = "^discord$"; } + { class = "^Mumble$"; } + { class = "^Signal$"; } + { class = "^SchildiChat$"; } + ]; + ${wsDevelopment} + = [ + { class = "^VSCodium$"; } + ]; +} diff --git a/users/sivizius/config/sway/config.nix b/users/sivizius/config/sway/config.nix new file mode 100644 index 0000000..3c2abfa --- /dev/null +++ b/users/sivizius/config/sway/config.nix @@ -0,0 +1,113 @@ +{ core, registries, store, profile, ... } @ arguments: + let + inherit(core) path string; + + swaymsg = "${registries.nix.sway}/bin/swaymsg"; + lock = "${registries.nix.swaylock}/bin/swaylock -efu -c 000000 -i ${./assets/otter.png} -s center"; + # timeOutDark = 120; + timeOutLock = 120; + lightsOff = "${swaymsg} 'output * dpms off'"; + lightsOn = "${swaymsg} 'output * dpms on'"; + + lockScreen + = store.write.shellScript "lockScreen" + '' + ${registries.nix.swayidle}/bin/swayidle -w \ + timeout ${string timeOutLock} "${lightsOff}; ${lock}" \ + resume "${lightsOn}" \ + before-sleep "${lock}" \ + lock "${lock}" + ''; + brightnessDelta = "5%"; + volumeDelta = "5%"; + resizeHeight = "10px"; + resizeWidth = "10px"; + + modifier = "Mod4"; + up = "w"; + left = "a"; + down = "s"; + right = "d"; + + terminal = "${registries.nix.alacritty}/bin/alacritty"; + in + { + assigns = path.import ./assigns.nix; + bars = [ ]; + + floating + = { + border = 2; + criteria + = [ + { class = "^Pavucontrol$"; } + ]; + titlebar = true; + inherit modifier; + }; + + fonts + = { + names = [ "FontAwesome" "RobotoMono" ]; + size = 10.0; + }; + + keybindings + = path.import ./keybindings.nix arguments + { + inherit lock terminal; + inherit brightnessDelta volumeDelta; + inherit modifier up down left right; + }; + + input."*" + = { + pointer_accel = "0.0"; + xkb_layout = "de(basic)"; + xkb_options = "compose:caps"; + xkb_variant = "\"\""; + }; + + modes + = path.import ./modes.nix + { + inherit resizeHeight resizeWidth; + inherit up down left right; + }; + + output."*".bg = "\"${./assets/Crater_Cluster.png}\" fill"; + + startup + = let + bar = "${registries.nix.waybar}/bin/waybar -c ${./assets/waybar/config.json} -s ${./assets/waybar/style.css}"; + neomutt + = store.write.shellScript "neomuttWrapper" + '' + ${registries.nix.neomutt}/bin/neomutt 2> ~/.cache/neomutt.log + ''; + in + assert profile.isDesktop; + [ + { command = "${registries.nix.dino}/bin/dino"; always = false; } + { command = "${registries.nix.discord}/bin/Discord"; always = false; } + { command = "${registries.nix.firefox}/bin/firefox"; always = false; } + { command = "${registries.nix.spotify}/bin/spotify"; always = false; } + { command = "${registries.nix.tdesktop}/bin/telegram-desktop"; always = false; } + { command = "${registries.nix.tdesktop}/bin/signal-desktop"; always = false; } + { command = "${registries.nix.schildichat-desktop}/bin/schildichat-desktop"; always = false; } + { command = "${terminal} -t neomutt -e ${neomutt}"; always = false; } + { command = "${terminal} -t ranger -e ${registries.nix.ranger}/bin/ranger"; always = false; } + { command = "${bar}"; always = false; } + { command = "${lockScreen}"; always = true; } + ]; + + window + = { + border = 2; + commands = [ ]; + hideEdgeBorders = "both"; + titlebar = false; + }; + + workspaceAutoBackAndForth = true; + } diff --git a/users/sivizius/config/sway/default.nix b/users/sivizius/config/sway/default.nix new file mode 100644 index 0000000..82acfb8 --- /dev/null +++ b/users/sivizius/config/sway/default.nix @@ -0,0 +1,16 @@ +{ core, profile, ... } @ env: + let + inherit(core) path set string; + in + { + enable = profile.isDesktop; + config = set.ifOrEmpty profile.isDesktop (path.import ./config.nix env); + extraSessionCommands + = string.ifOrEmpty profile.isDesktop + '' + export SDL_VIDEODRIVER=wayland + export QT_QPA_PLATFORM=wayland + export QT_WAYLAND_DISABLE_WINDOWDECORATION=1 + export _JAVA_AWT_WM_NONREPARENTING=1 + ''; + } diff --git a/users/sivizius/config/sway/keybindings.nix b/users/sivizius/config/sway/keybindings.nix new file mode 100644 index 0000000..8ca72e8 --- /dev/null +++ b/users/sivizius/config/sway/keybindings.nix @@ -0,0 +1,211 @@ +{ core, registries, store, ... }: +{ + lock, terminal, + volumeDelta, brightnessDelta, + modifier, up, down, left, right +}: + let + inherit(core) debug string; + bluetoothctl = "${registries.nix.bluez}/bin/bluetoothctl"; + brightnessctl = "${registries.nix.brightnessctl}/bin/brightnessctl"; + htop = "${terminal} -e ${registries.nix.htop}/bin/htop"; + makoctl = "${registries.nix.mako}/bin/makoctl"; + pactl = "${registries.nix.pulseaudio}/bin/pactl"; + playerctl = "${registries.nix.playerctl}/bin/playerctl"; + qutebrowser = "${registries.nix.qutebrowser}/bin/qutebrowser"; + ripgrep = "${registries.nix.ripgrep}/bin/rg"; + sed = "${registries.nix.gnused}/bin/sed"; + swaymsg = "${registries.nix.sway}/bin/swaymsg"; + wpa_cli = "${registries.nix.wpa_supplicant}/bin/wpa_cli"; + woficmd = "${registries.custom.wofi-unpatched}/bin/wofi --style ${./assets/wofi.css} "; + + takeScreenshot + = let + script + = store.write.shellScript "screenshooter" + '' + directory="$HOME/Pictures/Screenshots" + ${registries.nix.coreutils}/bin/mkdir -p "$directory" + OUTPUT="$directory/$(date -Iseconds).png" + ${registries.nix.grim}/bin/grim -g "$(${registries.nix.slurp}/bin/slurp -d)" "$OUTPUT" + ${registries.nix.libnotify}/bin/notify-send -t 10000 "Screenshot saved to" "$OUTPUT" + ''; + in + "sh ${script}"; + + listPasswords + = let + script + = store.write.shellScript "passwords" + '' + cd $HOME/Passwords + for file in $(${registries.nix.findutils}/bin/find . -name "*.gpg") + do + echo "''${file%.gpg}" | ${sed} "s/^.\///g" + done + ''; + in + "sh ${script}"; + + selectNetwork + = string.concatWords + [ + "${wpa_cli} select_network" + "$(" + "${wpa_cli} list_networks" + "| ${registries.nix.coreutils}/bin/tail -n +3" + "| ${ripgrep} -o \"^[^\t]+\t[^\t]+\"" + "| ${woficmd} --show dmenu" + "| ${ripgrep} -o \"^[0-9]+\" | tee -a $HOME/network.log" + ")" + ]; + + killer + = string.concatWords + [ + "kill" + "-SIGKILL" + "$(" + "${registries.nix.procps}/bin/ps -H -u $USER -o pid=,cmd=" + "| ${sed} \"s/^ *\\([1-9][0-9]*\\) \\(.*\\)/\\1\\t\\2/\" " + "| ${woficmd} --show dmenu --insensitive | rg -o \"^\d+\"" + ")" + ]; + + bluetoothConnect + = string.concatWords + [ + "${bluetoothctl} connect" + "$(" + "${bluetoothctl} devices" + "| ${sed} \"s/^Device \\(.*\\) \\(.*\\)/\\1\\t\\2/\"" + "| ${woficmd} --show dmenu --insensitive" + "| ${ripgrep} -o \"^[0-9A-F:]*\"" + ")" + ]; + pass = "${registries.nix.pass}/bin/pass -c $(${listPasswords} | ${woficmd} --show dmenu --insensitive)"; + menu = "${woficmd} --show drun -I --insensitive"; + browser = qutebrowser; + mod = modifier; + in + debug.info "selectNetwork" "»${selectNetwork}«" + { + # Execute Stuff + "${mod}+z" = "exec ${bluetoothConnect}"; + "${mod}+h" = "exec ${htop}"; + "${mod}+k" = "exec ${takeScreenshot}"; + "${mod}+l" = "exec ${lock}"; + "${mod}+n" = "exec ${selectNetwork}"; + "${mod}+p" = "exec ${pass}"; + "${mod}+t" = "exec ${terminal}"; + "${mod}+u" = "exec ${browser}"; + "${mod}+Escape" = "exec ${menu}"; + + "${mod}+Shift+x" = "kill"; + "${mod}+Shift+c" = "reload"; + "${mod}+Shift+q" = "exec ${swaymsg} exit"; + "${mod}+Shift+e" = "exec ${makoctl} dismiss -a"; + "${mod}+Shift+k" = "exec ${killer}"; + + # Tilling + "${mod}+b" = "splith"; + "${mod}+v" = "splitv"; + + "${mod}+q" = "layout stacking"; + "${mod}+e" = "layout tabbed"; + "${mod}+y" = "layout toggle split"; + "${mod}+x" = "fullscreen"; + + "${mod}+c" = "floating toggle"; + "${mod}+j" = "focus mode_toggle"; + "${mod}+m" = "focus parent"; + "${mod}+f" = "move scratchpad"; + "${mod}+g" = "scratchpad show"; + + # Focus + "${mod}+${up}" = "focus up"; + "${mod}+Up" = "focus up"; + "${mod}+${left}" = "focus left"; + "${mod}+Left" = "focus left"; + "${mod}+${down}" = "focus down"; + "${mod}+Down" = "focus down"; + "${mod}+${right}" = "focus right"; + "${mod}+Right" = "focus right"; + + # Moving + "${mod}+Shift+${up}" = "move up"; + "${mod}+Shift+Up" = "move up"; + "${mod}+Shift+${left}" = "move left"; + "${mod}+Shift+Left" = "move left"; + "${mod}+Shift+${down}" = "move down"; + "${mod}+Shift+Down" = "move down"; + "${mod}+Shift+${right}" = "move right"; + "${mod}+Shift+Right" = "move right"; + + # Resizing + "${mod}+r" = "mode \"resize\""; + + # Workspaces + "${mod}+F1" = "workspace 0"; + "${mod}+Shift+F1" = "move container to workspace 0"; + "${mod}+F2" = "workspace 1"; + "${mod}+Shift+F2" = "move container to workspace 1"; + "${mod}+F3" = "workspace 2"; + "${mod}+Shift+F3" = "move container to workspace 2"; + "${mod}+F4" = "workspace 3"; + "${mod}+Shift+F4" = "move container to workspace 3"; + "${mod}+F5" = "workspace 4"; + "${mod}+Shift+F5" = "move container to workspace 4"; + "${mod}+F6" = "workspace 5"; + "${mod}+Shift+F6" = "move container to workspace 5"; + "${mod}+F7" = "workspace 6"; + "${mod}+Shift+F7" = "move container to workspace 6"; + "${mod}+F8" = "workspace 7"; + "${mod}+Shift+F8" = "move container to workspace 7"; + "${mod}+F9" = "workspace 8"; + "${mod}+Shift+F9" = "move container to workspace 8"; + "${mod}+F10" = "workspace 9"; + "${mod}+Shift+F10" = "move container to workspace 9"; + "${mod}+F11" = "workspace a"; + "${mod}+Shift+F11" = "move container to workspace a"; + "${mod}+F12" = "workspace b"; + "${mod}+Shift+F12" = "move container to workspace b"; + "${mod}+1" = "workspace c"; + "${mod}+Shift+1" = "move container to workspace c"; + "${mod}+2" = "workspace d"; + "${mod}+Shift+2" = "move container to workspace d"; + "${mod}+3" = "workspace e"; + "${mod}+Shift+3" = "move container to workspace e"; + "${mod}+4" = "workspace f"; + "${mod}+Shift+4" = "move container to workspace f"; + "${mod}+5" = "workspace g"; + "${mod}+Shift+5" = "move container to workspace g"; + "${mod}+6" = "workspace h"; + "${mod}+Shift+6" = "move container to workspace h"; + "${mod}+7" = "workspace i"; + "${mod}+Shift+7" = "move container to workspace i"; + "${mod}+8" = "workspace j"; + "${mod}+Shift+8" = "move container to workspace j"; + "${mod}+9" = "workspace k"; + "${mod}+Shift+9" = "move container to workspace k"; + "${mod}+0" = "workspace l"; + "${mod}+Shift+0" = "move container to workspace l"; + + # Special Keys + "XF86AudioRaiseVolume" = "exec ${pactl} set-sink-volume @DEFAULT_SINK@ +${volumeDelta}"; + "XF86AudioLowerVolume" = "exec ${pactl} set-sink-volume @DEFAULT_SINK@ -${volumeDelta}"; + "XF86AudioMute" = "exec ${pactl} set-sink-mute @DEFAULT_SINK@ toggle"; + "XF86AudioMicMute" = "exec ${pactl} set-source-mute @DEFAULT_SOURCE@ toggle"; + "XF86MonBrightnessDown" = "exec ${brightnessctl} set ${brightnessDelta}-"; + "XF86MonBrightnessUp" = "exec ${brightnessctl} set +${brightnessDelta}"; + "XF86AudioPlay" = "exec ${playerctl} play-pause"; + "XF86AudioNext" = "exec ${playerctl} next"; + "XF86AudioPrev" = "exec ${playerctl} previous"; + + # Keyboard Layout + "Ctrl+Shift+F1" = "input * xkb_layout de(basic)"; + "Ctrl+Shift+F2" = "input * xkb_layout il(phonetic)"; + "Ctrl+Shift+F3" = "input * xkb_layout bg(phonetic)"; + "Ctrl+Shift+F4" = "input * xkb_layout gr(basic)"; + "Ctrl+Shift+F5" = "input * xkb_layout us(basic)"; + } diff --git a/users/sivizius/config/sway/modes.nix b/users/sivizius/config/sway/modes.nix new file mode 100644 index 0000000..2a11ef4 --- /dev/null +++ b/users/sivizius/config/sway/modes.nix @@ -0,0 +1,16 @@ +{ resizeHeight, resizeWidth, up, down, left, right }: +{ + resize + = { + "Return" = "mode \"default\""; + "Escape" = "mode \"default\""; + "${up}" = "resize shrink height ${resizeHeight}"; + "Up" = "resize shrink height ${resizeHeight}"; + "${left}" = "resize shrink width ${resizeWidth}"; + "Left" = "resize shrink width ${resizeWidth}"; + "${down}" = "resize grow height ${resizeHeight}"; + "Down" = "resize grow height ${resizeHeight}"; + "${right}" = "resize grow width ${resizeWidth}"; + "Right" = "resize grow width ${resizeWidth}"; + }; +} diff --git a/users/sivizius/config/sway/xkb/default.nix b/users/sivizius/config/sway/xkb/default.nix new file mode 100644 index 0000000..e69de29 diff --git a/users/sivizius/config/sway/xkb/latin.nix b/users/sivizius/config/sway/xkb/latin.nix new file mode 100644 index 0000000..ea8b3d6 --- /dev/null +++ b/users/sivizius/config/sway/xkb/latin.nix @@ -0,0 +1,131 @@ +{ core, intrinsics, ... }: + let + inherit (intrinsics) attrNames concatStringsSep; + + Layout + = name: + { ... } @ bindings: + { inherit name bindings; }; + + toXKB + = let + mapKey + = key: + { + "1" = "AE01"; + "2" = "AE02"; + "3" = "AE03"; + "4" = "AE04"; + "5" = "AE05"; + "6" = "AE06"; + "7" = "AE07"; + "8" = "AE08"; + "9" = "AE09"; + "0" = "AE10"; + "-" = "AE11"; + "=" = "AE12"; + "q" = "AD01"; + "w" = "AD02"; + "e" = "AD03"; + "r" = "AD04"; + "t" = "AD05"; + "y" = "AD06"; + "u" = "AD07"; + "i" = "AD08"; + "o" = "AD09"; + "p" = "AD10"; + "[" = "AD11"; + "]" = "AD12"; + "a" = "AC01"; + "s" = "AC02"; + "d" = "AC03"; + "f" = "AC04"; + "g" = "AC05"; + "h" = "AC06"; + "j" = "AC07"; + "k" = "AC08"; + "l" = "AC09"; + ";" = "AC10"; + "'" = "AC11"; + "~" = "TLDE"; + "\\" = "BKSL"; + "z" = "AB01"; + "x" = "AB02"; + "c" = "AB03"; + "v" = "AB04"; + "b" = "AB05"; + "n" = "AB06"; + "m" = "AB07"; + "," = "AB08"; + "." = "AB09"; + "/" = "AB10"; + "<" = "LSGT"; + }.${key}; + mapCharacters + = map + ( + char: + if isString char + then + ( + lib.foldl + ( + result: + char: + result // { ${char} = char; } + ) + {} + [ + "0" "1" "2" "3" "4" "5" "6" "7" "8" "9" + "a" "b" "c" "d" "e" "f" "g" "h" "i" "j" + "k" "l" "m" "n" "o" "p" "q" "r" "s" "t" + "u" "v" "w" "x" "y" "z" + ] + ) + { + "!" = "exclam"; + "¡" = "exclamdown"; + }.${char} + else if char == null then "NoSymbol" + else if char == Grave then "grave" + else null + ); + toXKB + = { ... } @ bindings: + concatStringsSep "\n" + ( + map + ( + key: + " key <${mapKey key}> { [${concatStringsSep ", " (mapCharacters bindings.${key})}] };" + ) + ( attrNames bindings ) + ); + + in + { name, bindings, ... }: + '' + default + xkb_symbols "${name}" { + ${toXKB bindings} + }; + ''; + in + Layout "de" + { + # First + "~" = [ "^" "°" "′" "″" ]; + "1" = [ "1" "!" "¹" "¡" ]; + "2" = [ "2" "\"" "²" "⅛" ]; + "3" = [ "3" "§" "³" "£" ]; + "4" = [ "4" "$" "¼" "¤" ]; + "5" = [ "5" "%" "½" "⅜" ]; + "6" = [ "6" "&" "¬" "⅝" ]; + "7" = [ "7" "/" "{" "⅞" ]; + "8" = [ "8" "(" "[" "™" ]; + "9" = [ "9" ")" "]" "±" ]; + "0" = [ "0" "=" "}" "°" ]; + "-" = [ "ß" "?" "\\" "¿" ]; + "=" = [ "´" "`" "¸" "˛" ]; + "" + } \ No newline at end of file diff --git a/users/sivizius/default.nix b/users/sivizius/default.nix new file mode 100644 index 0000000..3f203eb --- /dev/null +++ b/users/sivizius/default.nix @@ -0,0 +1,14 @@ +{ ... } @ extra: + User "Sebastian Walz" + { + inherit extra; + configuration = ./config; + dates + = { + "1996-10-03" = "Birthday"; + }; + keys + = { + aleph = [ ./keys/ssh/aleph.nix ]; + }; + } diff --git a/users/sivizius/flake.nix b/users/sivizius/flake.nix new file mode 100644 index 0000000..8fad3a5 --- /dev/null +++ b/users/sivizius/flake.nix @@ -0,0 +1,21 @@ +{ + description = "User-Configuration of sivizius"; + inputs + = { + libconfig.url = "github:sivizius/nixfiles/development?dir=libs/config"; + libcore.url = "github:sivizius/nixfiles/development?dir=libs/core"; + }; + outputs + = { self, libconfig, libcore, ... }: + { + user + = let + config = libconfig.lib { inherit self; }; + in + config.users.load ./. + { + inherit config; + core = libcore.lib { inherit self; debug.logLevel = "info"; }; + }; + }; +} diff --git a/users/sivizius/keys/ssh/aleph.nix b/users/sivizius/keys/ssh/aleph.nix new file mode 100644 index 0000000..5c08af1 --- /dev/null +++ b/users/sivizius/keys/ssh/aleph.nix @@ -0,0 +1,7 @@ +{ + contact = "aleph@sivizius.eu"; + date = "2023-04-13"; + expires = "2027-04-12"; + key = "AAAAC3NzaC1lZDI1NTE5AAAAINKD18BECKlnT9HQ5VdBWDU5qbtl3zzliFChr1zRtLD/"; + method = "ed25519"; +}