diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..6f4324d --- /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..c0ca007 --- /dev/null +++ b/NixTeX/default.nix @@ -0,0 +1,237 @@ +{ core, fork-awesome, nixpkgs, stdenv, ... } @ libs: +let + inherit(core) debug lambda library list path set string target type; + nixtex = library.import ./source libs; + + inherit(nixtex) Document Dependencies; + + 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; + system' = string 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..5d10500 --- /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:NixOS/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..c6b39af --- /dev/null +++ b/NixTeX/source/common/chemistry/synthesis.nix @@ -0,0 +1,926 @@ +{ 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; + when = false; + } + ( + 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..189bb1c --- /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.formatTeX "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..a99d197 --- /dev/null +++ b/NixTeX/source/common/physical/default.nix @@ -0,0 +1,330 @@ +{ 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.concatMappedWith + ( + 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..ae1bb28 --- /dev/null +++ b/NixTeX/source/common/urls/default.nix @@ -0,0 +1,11 @@ +{ core, ... }: + let + inherit(core) string; + escape = string.replace [ "_" "%" ] [ "\\_" "\\%" ]; + in + { + formatEmailTeX = href: text: "\\mbox{\\href{mailto:${href}}{${escape text}}}"; + formatHttpsTeX = href: text: "\\mbox{\\href{https://${href}}{${escape text}}}"; + formatHttpsTeX' = href: text: "\\mbox{\\href{https:\\//${href}}{${escape text}}}"; + formatTeX = href: text: "\\mbox{\\href{${href}}{${escape text}}}"; + } diff --git a/NixTeX/source/default.nix b/NixTeX/source/default.nix new file mode 100644 index 0000000..1445d95 --- /dev/null +++ b/NixTeX/source/default.nix @@ -0,0 +1,60 @@ +{ core, ... } @ libs: +let + inherit(core) debug library path string type; + + 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..24a446c --- /dev/null +++ b/NixTeX/source/evaluate.nix @@ -0,0 +1,166 @@ +{ bibliography, chemistry, core, document, ... }: +let + inherit(core) context debug 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.concatMappedWith + ( + { 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 + ) + "\n" + 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.concatMappedWith + ({ context, task }: "${string.concatWith " → " context}: ${task}") + "\n" + 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..067b589 --- /dev/null +++ b/NixTeX/source/prepare.nix @@ -0,0 +1,59 @@ +{ bibliography, chemistry, core, glossaries, ... } @ libs: + let + inherit(core) debug 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..5aac385 --- /dev/null +++ b/NixTeX/source/render/application/tex/default.nix @@ -0,0 +1,191 @@ +{ 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 ) + ++ ( 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..e000162 --- /dev/null +++ b/NixTeX/source/render/application/tex/letter.nix @@ -0,0 +1,284 @@ +{ core, letters, phonenumbers, symbols, toTex, urls, ... }: +{ + body, + closing, + configuration, + copies ? null, + date, + enclosures ? null, + language ? "eng", + logo ? null, + opening, + place, + recipient, + sender, + signature ? null, + subject, + ... +}: + 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.formatEmailTeX address "\\texttt{${address}}"} \\\\"; + + formatPhoneNumber + = label: + number: + list.ifOrEmpty + (number != null) + "${label}: & ${phonenumbers.formatTeX number} \\\\"; + + formatURL + = label: + url: + list.ifOrEmpty + (url != null) + "${label}: & ${urls.formatHttpsTeX 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 "}%" + "\\setkomavar{date}{${time.formatDate date language}}%" + ] + ++ ( + list.ifOrEmpty' (logo != null) + [ + "\\KOMAoptions{fromlogo=true}" + "\\setkomavar{fromlogo}{\\includegraphics[width=${logo.width}]{\\source/${logo.file}}}" + ] + ) + ++ [ + "\\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 "}}%" + "\\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}}%" + "\\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..481f6d9 --- /dev/null +++ b/NixTeX/source/render/application/tex/prelude.nix @@ -0,0 +1,136 @@ +{ core, fonts, ... }: + let + inherit(core) indentation list set string; + in + { acronyms, assets, packages, publications, references, source, substances, ... } @ args: + ( + [ + '' + \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} + '' + + /* + '' + \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..c235dfb --- /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) debug indentation list string time type; + 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..7a7f40b --- /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) debug number indentation list path set string time type; + 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 + ( + [ "\\\\[-2\\normalbaselineskip]${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.0\\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..8dd545a --- /dev/null +++ b/NixTeX/source/render/application/tex/resume/styles/awesome/education.nix @@ -0,0 +1,54 @@ +{ core, helpers, styles, toTex, ... }: +{ ... }: + let + inherit(core) debug indentation list string time type; + 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..bedbaf2 --- /dev/null +++ b/NixTeX/source/render/application/tex/resume/styles/awesome/header.nix @@ -0,0 +1,82 @@ +{ core, helpers, 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\\textwidth}" 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.2em,%" + "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 + ( + [] + ++ (list.ifOrEmpty' (photo != null) (formatPicture "left" photo)) + ++ [ "\\begin{minipage}[c]{${if photo != null then ".75" else ""}\\textwidth}%" 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)) + ) 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..e05a76e --- /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}%" + ] + ) + ) + ) \ No newline at end of file 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..7e37b3a --- /dev/null +++ b/NixTeX/source/render/application/tex/resume/styles/awesome/languages.nix @@ -0,0 +1,203 @@ +{ 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; + + stars' = string.concat (rateHalfStars 0 maxStars); + 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..b78cb3e --- /dev/null +++ b/NixTeX/source/render/application/tex/resume/styles/awesome/motivation.nix @@ -0,0 +1,16 @@ +{ core, helpers, styles, toTex, ... }: +{ ... }: + let + inherit(core) indentation; + inherit(helpers) formatParagraph; + 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..d55dc8c --- /dev/null +++ b/NixTeX/source/render/application/tex/resume/styles/awesome/publications.nix @@ -0,0 +1,25 @@ +{ core, document, helpers, styles, ... }: +{ ... }: + 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..5ee844c --- /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.formatHttpsTeX 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..1e2f826 --- /dev/null +++ b/NixTeX/source/render/application/tex/resume/styles/awesome/social.nix @@ -0,0 +1,168 @@ +{ core, phonenumbers, symbols, styles, urls, ... }: +{ ... }: + let + inherit(core) indentation list string; + 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.formatEmailTeX address "${email-bulk}\\,${address}"; + + formatGit + = { name, domain, isGitea ? false, ... }: + let + icon + = { + "github" = github; + "github.com" = github; + "gitlab" = gitlab; + "gitlab.com" = gitlab; + }.${domain} or null; + icon' + = if isGitea + then + gitea + else + git; + in + if icon != null + then + urls.formatHttpsTeX "${domain}/${name}" "${icon}\\,${name}" + else + urls.formatHttpsTeX "${domain}/${name}" "${icon'}\\,\\texttt{${domain}/${name}}"; + + formatGoogleScholar + = { id, name }: + urls.formatHttpsTeX "scholar.google.com/citations?user=${id}" "${graduation-cap}\\,${id}"; + + formatHomePage + = homepage: + urls.formatHttpsTeX homepage "${globe}\\,\\texttt{${homepage}}"; + + formatLinkedIn + = { id, name }: + urls.formatHttpsTeX "www.linkedin.com/in/${id}" "${linkedin}\\,${id}"; + + formatMatrix + = { name, domain }: + urls.formatHttpsTeX "${domain}/${name}" "${matrix-org}\\,@${name}:${domain}"; + + formatMedium + = { id, name }: + urls.formatHttpsTeX "medium.com/@${id}" "${medium}\\,${name}"; + + formatOrcid + = { id, name }: + urls.formatHttpsTeX "orcid.org/${id}" "${orcid}\\,${id}"; + + formatPGP + = { fingerprint, url }: + urls.formatHttpsTeX url "${gnupg}\\,\\texttt{${url} (\\texttt{${fingerprint}})}"; + + formatPhoneNumber + = icon: + number: + "${icon}\\,${phonenumbers.formatTeX number}"; + + formatReddit + = name: + urls.formatHttpsTeX "www.reddit.com/user/${name}" "${reddit}\\,u/${name}"; + + formatSkype = name: "${skype}\\,${name}"; + + formatStackOverflow + = { id, name }: + urls.formatHttpsTeX "stackoverflow.com/users/${id}" "${stackoverflow}\\,${name}"; + + formatTwitter + = name: + urls.formatHttpsTeX "www.twitter.com/${name}" "${twitter}\\,${name}"; + + + formatWikipedia + = { language ? "en", name }: + urls.formatHttpsTeX "${language}.wikipedia.org/wiki/User:${name}" "${wikipedia}\\,${name}"; + + formatXing + = { id, name }: + urls.formatHttpsTeX "www.xing.com/profile/${id}" "${xing}\\,${name}"; + + mapGit = list.map formatGit; + + mapPhone + = { cell ? null, fax ? null, home ? null }: + [] + ++ (list.ifOrEmpty (cell != null) (formatPhoneNumber mobile cell)) + ++ (list.ifOrEmpty (home != null) (formatPhoneNumber phone home)) + ++ (list.ifOrEmpty (fax != null) (formatPhoneNumber 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..d41d343 --- /dev/null +++ b/NixTeX/source/render/application/tex/resume/styles/awesome/summary.nix @@ -0,0 +1,8 @@ +{ core, helpers, styles, ... }: +{ ... }: + let + inherit(core) indentation 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..8d1b25a --- /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; + } \ No newline at end of file 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..6e5c65f --- /dev/null +++ b/NixTeX/source/render/journal/default.nix @@ -0,0 +1,15 @@ +{ context, ... } @ libs: +let + getFormat + = outputFormat: + if outputFormat != null + then + outputFormat + else + "tex"; + renderTex = import ./tex ( libs // { context = context ++ [ "journal" ]; }); +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..5856681 --- /dev/null +++ b/NixTeX/source/render/journal/tex/default.nix @@ -0,0 +1,103 @@ +{ bibliography, chemistry, context, core, glossaries,... } @ libs: +let + inherit(core) indentation string list set; + libs' + = libs + // { + context = context ++ [ "tex" ]; + 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 = import ./appendix.nix libs'; + beginDocument = import ./beginDocument.nix libs'; + frontMatter = import ./frontMatter.nix libs'; + mainMatter = import ./mainMatter.nix libs'; + prelude = import ./prelude.nix libs'; + titleMatter = import ./titleMatter.nix libs'; +in + { configuration, content, dependencies, resources, style, ... } @ document: + let + document' + = document + // { + style = (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..82e8056 --- /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..150b56a --- /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, ... } @ args: + ( + [ + '' + \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..b4e6d6d --- /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..751815e --- /dev/null +++ b/NixTeX/source/render/letter/default.nix @@ -0,0 +1,133 @@ +{ core, document, ... }: +{ configuration, style, ... }: + let + inherit(core) bibliography chemistry indentation list string type; + inherit(bibliography) callCite loadReferences prepareReferences; + inherit(chemistry) substances; + + 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}" + ] + ); + } \ No newline at end of file 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..5a89aca --- /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"; + } + ]; + } \ No newline at end of file diff --git a/NixTeX/source/render/thesis/tex/appendix.nix b/NixTeX/source/render/thesis/tex/appendix.nix new file mode 100644 index 0000000..98114e6 --- /dev/null +++ b/NixTeX/source/render/thesis/tex/appendix.nix @@ -0,0 +1,49 @@ +{ context, core, ... }: +let + inherit(core) indentation; + + debug = core.debug ( context ++ [ "appendix" ] ); +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..24df47a --- /dev/null +++ b/NixTeX/source/render/thesis/tex/backMatter.nix @@ -0,0 +1,30 @@ +{ context, core, thesis, ... }: +let + inherit(core) indentation; + + debug = core.debug ( context ++ [ "backMatter" ] ); +in + { configuration, ... } @ document: + 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..9abbaf3 --- /dev/null +++ b/NixTeX/source/render/thesis/tex/beginDocument.nix @@ -0,0 +1,100 @@ +{ context, core, thesis, ... }: +let + inherit(core) indentation list string; + inherit(thesis) formatAuthor; + + debug = core.debug ( context ++ [ "beginDocument" ] ); + 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..30b570a --- /dev/null +++ b/NixTeX/source/render/thesis/tex/default.nix @@ -0,0 +1,256 @@ +{ bibliography, chemistry, core, document, glossaries,... } @ libs: + let + inherit(core) debug 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..dcc8828 --- /dev/null +++ b/NixTeX/source/render/thesis/tex/frontMatter.nix @@ -0,0 +1,63 @@ +{ context, core, thesis, ... }: +let + inherit(core) indentation; + inherit(thesis) cleardoublepage; + + debug = core.debug ( context ++ [ "frontMatter" ] ); +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..e605f05 --- /dev/null +++ b/NixTeX/source/render/thesis/tex/mainMatter.nix @@ -0,0 +1,19 @@ +{ context, core, ... }: +let + inherit(core) indentation; + + debug = core.debug ( context ++ [ "mainMatter" ] ); +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..ccd8753 --- /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 "{" +] \ No newline at end of file diff --git a/NixTeX/source/render/thesis/tex/prelude.nix b/NixTeX/source/render/thesis/tex/prelude.nix new file mode 100644 index 0000000..995b4e8 --- /dev/null +++ b/NixTeX/source/render/thesis/tex/prelude.nix @@ -0,0 +1,204 @@ +{ context, core, ... }: +let + inherit(core) indentation set string; + + debug = core.debug ( context ++ [ "prelude" ] ); + + 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, ... } @ args: + ( + [ + '' + \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..3c4c130 --- /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; } \ No newline at end of file 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..08c21b2 --- /dev/null +++ b/NixTeX/source/render/thesis/tex/styles/tuc.nix @@ -0,0 +1,151 @@ +{ context, core, thesis, vanilla, ... }: +let + inherit(core) indentation list string time; + inherit(thesis) formatAuthor formatAuthorTableLine thesisVersion; + + debug = core.debug ( context ++ [ "tuc" ] ); +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..0dfa31d --- /dev/null +++ b/NixTeX/source/render/thesis/tex/styles/vanilla.nix @@ -0,0 +1,52 @@ +{ context, core, thesis, ... }: +let + inherit(core) indentation list string time; + inherit(thesis) formatAuthor formatAuthorTableLine thesisVersion; + + debug = core.debug ( context ++ [ "vanilla" ] ); +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..c3dffdb --- /dev/null +++ b/NixTeX/source/render/thesis/tex/titleMatter.nix @@ -0,0 +1,37 @@ +{ context, core, thesis, ... }: +let + inherit(core) indentation list string time type; + inherit(thesis) formatAuthor; + + debug = core.debug ( context ++ [ "titleMatter" ] ); +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/evaluate.nix b/home-manager/evaluate.nix new file mode 100644 index 0000000..7f7bb77 --- /dev/null +++ b/home-manager/evaluate.nix @@ -0,0 +1,15 @@ +{ core, ... }: +{ config, ... }: + if config.home-manager.shell != null + then + { + homeDirectory.user.${} + = { + home.file.".local/bin/shell" + = { + target = config.home-manager.shell; + }; + }; + } + else + {} \ No newline at end of file diff --git a/home-manager/flake.nix b/home-manager/flake.nix new file mode 100644 index 0000000..d2d048e --- /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; + }; +} \ No newline at end of file diff --git a/home-manager/lib/default.nix b/home-manager/lib/default.nix new file mode 100644 index 0000000..6b483eb --- /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; + } \ No newline at end of file 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..338c9a9 --- /dev/null +++ b/home-manager/options.nix @@ -0,0 +1,27 @@ +{ core, 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. + ''; + }; + }; + } \ No newline at end of file diff --git a/hosts/aleph/default.nix b/hosts/aleph/default.nix new file mode 100644 index 0000000..d5add43 --- /dev/null +++ b/hosts/aleph/default.nix @@ -0,0 +1,74 @@ +{ 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 = 3000; + 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.pgp b/hosts/aleph/vault.pgp new file mode 100644 index 0000000..3af54b3 --- /dev/null +++ b/hosts/aleph/vault.pgp @@ -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.pgp b/hosts/bet/vault.pgp new file mode 100644 index 0000000..8608990 --- /dev/null +++ b/hosts/bet/vault.pgp @@ -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..c7137d5 --- /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": 1680042873, + "narHash": "sha256-OJObF9OYA/nzyG2U8RW5sjVihhzdCo8ydKY8aNMDNm0=", + "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": 1680042873, + "narHash": "sha256-OJObF9OYA/nzyG2U8RW5sjVihhzdCo8ydKY8aNMDNm0=", + "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": 1679684476, + "narHash": "sha256-WTYZFt9cJmOSp1n3hxAS+BQnu7smcBsC98RSgdp2qsE=", + "owner": "nix-community", + "repo": "home-manager", + "rev": "db37c537603d1d45d022cc0666ad45197455b364", + "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": 1679684476, + "narHash": "sha256-WTYZFt9cJmOSp1n3hxAS+BQnu7smcBsC98RSgdp2qsE=", + "owner": "nix-community", + "repo": "home-manager", + "rev": "db37c537603d1d45d022cc0666ad45197455b364", + "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": 1680042873, + "narHash": "sha256-OJObF9OYA/nzyG2U8RW5sjVihhzdCo8ydKY8aNMDNm0=", + "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": 1680042873, + "narHash": "sha256-OJObF9OYA/nzyG2U8RW5sjVihhzdCo8ydKY8aNMDNm0=", + "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": 1680042873, + "narHash": "sha256-OJObF9OYA/nzyG2U8RW5sjVihhzdCo8ydKY8aNMDNm0=", + "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": 1680042873, + "narHash": "sha256-OJObF9OYA/nzyG2U8RW5sjVihhzdCo8ydKY8aNMDNm0=", + "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": 1680042873, + "narHash": "sha256-OJObF9OYA/nzyG2U8RW5sjVihhzdCo8ydKY8aNMDNm0=", + "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": 1680042873, + "narHash": "sha256-OJObF9OYA/nzyG2U8RW5sjVihhzdCo8ydKY8aNMDNm0=", + "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": 1680042873, + "narHash": "sha256-OJObF9OYA/nzyG2U8RW5sjVihhzdCo8ydKY8aNMDNm0=", + "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": 1680042873, + "narHash": "sha256-OJObF9OYA/nzyG2U8RW5sjVihhzdCo8ydKY8aNMDNm0=", + "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": 1680042873, + "narHash": "sha256-OJObF9OYA/nzyG2U8RW5sjVihhzdCo8ydKY8aNMDNm0=", + "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": 1680042873, + "narHash": "sha256-OJObF9OYA/nzyG2U8RW5sjVihhzdCo8ydKY8aNMDNm0=", + "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": 1680042873, + "narHash": "sha256-OJObF9OYA/nzyG2U8RW5sjVihhzdCo8ydKY8aNMDNm0=", + "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": 1680042873, + "narHash": "sha256-OJObF9OYA/nzyG2U8RW5sjVihhzdCo8ydKY8aNMDNm0=", + "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": 1680042873, + "narHash": "sha256-OJObF9OYA/nzyG2U8RW5sjVihhzdCo8ydKY8aNMDNm0=", + "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": 1680042873, + "narHash": "sha256-OJObF9OYA/nzyG2U8RW5sjVihhzdCo8ydKY8aNMDNm0=", + "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": 1680042873, + "narHash": "sha256-OJObF9OYA/nzyG2U8RW5sjVihhzdCo8ydKY8aNMDNm0=", + "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": 1680042873, + "narHash": "sha256-OJObF9OYA/nzyG2U8RW5sjVihhzdCo8ydKY8aNMDNm0=", + "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": 1680042873, + "narHash": "sha256-OJObF9OYA/nzyG2U8RW5sjVihhzdCo8ydKY8aNMDNm0=", + "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": 1680042873, + "narHash": "sha256-OJObF9OYA/nzyG2U8RW5sjVihhzdCo8ydKY8aNMDNm0=", + "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": 1680042873, + "narHash": "sha256-OJObF9OYA/nzyG2U8RW5sjVihhzdCo8ydKY8aNMDNm0=", + "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": 1680042873, + "narHash": "sha256-OJObF9OYA/nzyG2U8RW5sjVihhzdCo8ydKY8aNMDNm0=", + "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": 1680042873, + "narHash": "sha256-OJObF9OYA/nzyG2U8RW5sjVihhzdCo8ydKY8aNMDNm0=", + "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": 1680042873, + "narHash": "sha256-OJObF9OYA/nzyG2U8RW5sjVihhzdCo8ydKY8aNMDNm0=", + "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": 1680042873, + "narHash": "sha256-OJObF9OYA/nzyG2U8RW5sjVihhzdCo8ydKY8aNMDNm0=", + "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": 1680042873, + "narHash": "sha256-OJObF9OYA/nzyG2U8RW5sjVihhzdCo8ydKY8aNMDNm0=", + "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": 1680042873, + "narHash": "sha256-OJObF9OYA/nzyG2U8RW5sjVihhzdCo8ydKY8aNMDNm0=", + "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": 1680042873, + "narHash": "sha256-OJObF9OYA/nzyG2U8RW5sjVihhzdCo8ydKY8aNMDNm0=", + "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": 1680042873, + "narHash": "sha256-OJObF9OYA/nzyG2U8RW5sjVihhzdCo8ydKY8aNMDNm0=", + "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": 1680042873, + "narHash": "sha256-OJObF9OYA/nzyG2U8RW5sjVihhzdCo8ydKY8aNMDNm0=", + "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": 1680042873, + "narHash": "sha256-OJObF9OYA/nzyG2U8RW5sjVihhzdCo8ydKY8aNMDNm0=", + "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": 1680042873, + "narHash": "sha256-OJObF9OYA/nzyG2U8RW5sjVihhzdCo8ydKY8aNMDNm0=", + "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": 1680042873, + "narHash": "sha256-OJObF9OYA/nzyG2U8RW5sjVihhzdCo8ydKY8aNMDNm0=", + "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": 1680042873, + "narHash": "sha256-OJObF9OYA/nzyG2U8RW5sjVihhzdCo8ydKY8aNMDNm0=", + "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": 1680042873, + "narHash": "sha256-OJObF9OYA/nzyG2U8RW5sjVihhzdCo8ydKY8aNMDNm0=", + "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": 1680042873, + "narHash": "sha256-OJObF9OYA/nzyG2U8RW5sjVihhzdCo8ydKY8aNMDNm0=", + "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": 1680042873, + "narHash": "sha256-OJObF9OYA/nzyG2U8RW5sjVihhzdCo8ydKY8aNMDNm0=", + "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": 1680042873, + "narHash": "sha256-OJObF9OYA/nzyG2U8RW5sjVihhzdCo8ydKY8aNMDNm0=", + "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": 1680042873, + "narHash": "sha256-OJObF9OYA/nzyG2U8RW5sjVihhzdCo8ydKY8aNMDNm0=", + "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": 1680042873, + "narHash": "sha256-OJObF9OYA/nzyG2U8RW5sjVihhzdCo8ydKY8aNMDNm0=", + "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": 1680042873, + "narHash": "sha256-OJObF9OYA/nzyG2U8RW5sjVihhzdCo8ydKY8aNMDNm0=", + "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": 1680042873, + "narHash": "sha256-OJObF9OYA/nzyG2U8RW5sjVihhzdCo8ydKY8aNMDNm0=", + "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": 1680042873, + "narHash": "sha256-OJObF9OYA/nzyG2U8RW5sjVihhzdCo8ydKY8aNMDNm0=", + "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": 1680042873, + "narHash": "sha256-OJObF9OYA/nzyG2U8RW5sjVihhzdCo8ydKY8aNMDNm0=", + "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": 1680042873, + "narHash": "sha256-OJObF9OYA/nzyG2U8RW5sjVihhzdCo8ydKY8aNMDNm0=", + "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": 1680042873, + "narHash": "sha256-OJObF9OYA/nzyG2U8RW5sjVihhzdCo8ydKY8aNMDNm0=", + "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": 1680042873, + "narHash": "sha256-OJObF9OYA/nzyG2U8RW5sjVihhzdCo8ydKY8aNMDNm0=", + "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": 1680042873, + "narHash": "sha256-OJObF9OYA/nzyG2U8RW5sjVihhzdCo8ydKY8aNMDNm0=", + "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": 1680042873, + "narHash": "sha256-OJObF9OYA/nzyG2U8RW5sjVihhzdCo8ydKY8aNMDNm0=", + "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": 1680042873, + "narHash": "sha256-OJObF9OYA/nzyG2U8RW5sjVihhzdCo8ydKY8aNMDNm0=", + "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": 1680042873, + "narHash": "sha256-OJObF9OYA/nzyG2U8RW5sjVihhzdCo8ydKY8aNMDNm0=", + "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": 1680042873, + "narHash": "sha256-OJObF9OYA/nzyG2U8RW5sjVihhzdCo8ydKY8aNMDNm0=", + "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": 1680042873, + "narHash": "sha256-OJObF9OYA/nzyG2U8RW5sjVihhzdCo8ydKY8aNMDNm0=", + "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": 1680042873, + "narHash": "sha256-OJObF9OYA/nzyG2U8RW5sjVihhzdCo8ydKY8aNMDNm0=", + "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": 1680042873, + "narHash": "sha256-OJObF9OYA/nzyG2U8RW5sjVihhzdCo8ydKY8aNMDNm0=", + "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": 1680042873, + "narHash": "sha256-OJObF9OYA/nzyG2U8RW5sjVihhzdCo8ydKY8aNMDNm0=", + "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": 1680042873, + "narHash": "sha256-OJObF9OYA/nzyG2U8RW5sjVihhzdCo8ydKY8aNMDNm0=", + "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": 1680042873, + "narHash": "sha256-OJObF9OYA/nzyG2U8RW5sjVihhzdCo8ydKY8aNMDNm0=", + "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": 1680042873, + "narHash": "sha256-OJObF9OYA/nzyG2U8RW5sjVihhzdCo8ydKY8aNMDNm0=", + "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": 1680042873, + "narHash": "sha256-OJObF9OYA/nzyG2U8RW5sjVihhzdCo8ydKY8aNMDNm0=", + "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": 1680042873, + "narHash": "sha256-OJObF9OYA/nzyG2U8RW5sjVihhzdCo8ydKY8aNMDNm0=", + "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": 1680042873, + "narHash": "sha256-OJObF9OYA/nzyG2U8RW5sjVihhzdCo8ydKY8aNMDNm0=", + "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": 1680042873, + "narHash": "sha256-OJObF9OYA/nzyG2U8RW5sjVihhzdCo8ydKY8aNMDNm0=", + "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": 1680042873, + "narHash": "sha256-OJObF9OYA/nzyG2U8RW5sjVihhzdCo8ydKY8aNMDNm0=", + "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": 1680042873, + "narHash": "sha256-OJObF9OYA/nzyG2U8RW5sjVihhzdCo8ydKY8aNMDNm0=", + "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": 1680042873, + "narHash": "sha256-OJObF9OYA/nzyG2U8RW5sjVihhzdCo8ydKY8aNMDNm0=", + "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": 1680042873, + "narHash": "sha256-OJObF9OYA/nzyG2U8RW5sjVihhzdCo8ydKY8aNMDNm0=", + "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": 1680042873, + "narHash": "sha256-OJObF9OYA/nzyG2U8RW5sjVihhzdCo8ydKY8aNMDNm0=", + "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": 1680042873, + "narHash": "sha256-OJObF9OYA/nzyG2U8RW5sjVihhzdCo8ydKY8aNMDNm0=", + "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": 1680042873, + "narHash": "sha256-OJObF9OYA/nzyG2U8RW5sjVihhzdCo8ydKY8aNMDNm0=", + "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": 1680042873, + "narHash": "sha256-OJObF9OYA/nzyG2U8RW5sjVihhzdCo8ydKY8aNMDNm0=", + "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": 1680042873, + "narHash": "sha256-OJObF9OYA/nzyG2U8RW5sjVihhzdCo8ydKY8aNMDNm0=", + "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": 1680042873, + "narHash": "sha256-OJObF9OYA/nzyG2U8RW5sjVihhzdCo8ydKY8aNMDNm0=", + "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": 1680042873, + "narHash": "sha256-OJObF9OYA/nzyG2U8RW5sjVihhzdCo8ydKY8aNMDNm0=", + "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": 1680042873, + "narHash": "sha256-OJObF9OYA/nzyG2U8RW5sjVihhzdCo8ydKY8aNMDNm0=", + "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": 1680042873, + "narHash": "sha256-OJObF9OYA/nzyG2U8RW5sjVihhzdCo8ydKY8aNMDNm0=", + "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": 1680042873, + "narHash": "sha256-OJObF9OYA/nzyG2U8RW5sjVihhzdCo8ydKY8aNMDNm0=", + "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": 1680042873, + "narHash": "sha256-OJObF9OYA/nzyG2U8RW5sjVihhzdCo8ydKY8aNMDNm0=", + "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": 1680042873, + "narHash": "sha256-OJObF9OYA/nzyG2U8RW5sjVihhzdCo8ydKY8aNMDNm0=", + "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": 1680042873, + "narHash": "sha256-OJObF9OYA/nzyG2U8RW5sjVihhzdCo8ydKY8aNMDNm0=", + "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": 1680042873, + "narHash": "sha256-OJObF9OYA/nzyG2U8RW5sjVihhzdCo8ydKY8aNMDNm0=", + "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": 1680042873, + "narHash": "sha256-OJObF9OYA/nzyG2U8RW5sjVihhzdCo8ydKY8aNMDNm0=", + "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": 1680042873, + "narHash": "sha256-OJObF9OYA/nzyG2U8RW5sjVihhzdCo8ydKY8aNMDNm0=", + "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": 1680042873, + "narHash": "sha256-OJObF9OYA/nzyG2U8RW5sjVihhzdCo8ydKY8aNMDNm0=", + "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": 1680042873, + "narHash": "sha256-OJObF9OYA/nzyG2U8RW5sjVihhzdCo8ydKY8aNMDNm0=", + "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": 1680042873, + "narHash": "sha256-OJObF9OYA/nzyG2U8RW5sjVihhzdCo8ydKY8aNMDNm0=", + "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": 1680042873, + "narHash": "sha256-OJObF9OYA/nzyG2U8RW5sjVihhzdCo8ydKY8aNMDNm0=", + "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": 1680042873, + "narHash": "sha256-OJObF9OYA/nzyG2U8RW5sjVihhzdCo8ydKY8aNMDNm0=", + "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": 1680042873, + "narHash": "sha256-OJObF9OYA/nzyG2U8RW5sjVihhzdCo8ydKY8aNMDNm0=", + "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": 1680042873, + "narHash": "sha256-OJObF9OYA/nzyG2U8RW5sjVihhzdCo8ydKY8aNMDNm0=", + "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": 1680042873, + "narHash": "sha256-OJObF9OYA/nzyG2U8RW5sjVihhzdCo8ydKY8aNMDNm0=", + "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": 1680042873, + "narHash": "sha256-OJObF9OYA/nzyG2U8RW5sjVihhzdCo8ydKY8aNMDNm0=", + "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": 1680042873, + "narHash": "sha256-OJObF9OYA/nzyG2U8RW5sjVihhzdCo8ydKY8aNMDNm0=", + "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": 1680042873, + "narHash": "sha256-OJObF9OYA/nzyG2U8RW5sjVihhzdCo8ydKY8aNMDNm0=", + "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": 1680042873, + "narHash": "sha256-OJObF9OYA/nzyG2U8RW5sjVihhzdCo8ydKY8aNMDNm0=", + "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": 1680042873, + "narHash": "sha256-OJObF9OYA/nzyG2U8RW5sjVihhzdCo8ydKY8aNMDNm0=", + "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": 1680042873, + "narHash": "sha256-OJObF9OYA/nzyG2U8RW5sjVihhzdCo8ydKY8aNMDNm0=", + "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": 1680042873, + "narHash": "sha256-OJObF9OYA/nzyG2U8RW5sjVihhzdCo8ydKY8aNMDNm0=", + "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": 1680042873, + "narHash": "sha256-OJObF9OYA/nzyG2U8RW5sjVihhzdCo8ydKY8aNMDNm0=", + "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": 1680042873, + "narHash": "sha256-OJObF9OYA/nzyG2U8RW5sjVihhzdCo8ydKY8aNMDNm0=", + "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": 1680042873, + "narHash": "sha256-OJObF9OYA/nzyG2U8RW5sjVihhzdCo8ydKY8aNMDNm0=", + "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": 1680042873, + "narHash": "sha256-OJObF9OYA/nzyG2U8RW5sjVihhzdCo8ydKY8aNMDNm0=", + "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": 1680042873, + "narHash": "sha256-OJObF9OYA/nzyG2U8RW5sjVihhzdCo8ydKY8aNMDNm0=", + "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": 1680042873, + "narHash": "sha256-OJObF9OYA/nzyG2U8RW5sjVihhzdCo8ydKY8aNMDNm0=", + "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": 1680042873, + "narHash": "sha256-OJObF9OYA/nzyG2U8RW5sjVihhzdCo8ydKY8aNMDNm0=", + "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": 1680042873, + "narHash": "sha256-OJObF9OYA/nzyG2U8RW5sjVihhzdCo8ydKY8aNMDNm0=", + "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": 1680042873, + "narHash": "sha256-OJObF9OYA/nzyG2U8RW5sjVihhzdCo8ydKY8aNMDNm0=", + "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": 1680042873, + "narHash": "sha256-OJObF9OYA/nzyG2U8RW5sjVihhzdCo8ydKY8aNMDNm0=", + "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": 1680042873, + "narHash": "sha256-OJObF9OYA/nzyG2U8RW5sjVihhzdCo8ydKY8aNMDNm0=", + "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": 1680042873, + "narHash": "sha256-OJObF9OYA/nzyG2U8RW5sjVihhzdCo8ydKY8aNMDNm0=", + "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": 1680042873, + "narHash": "sha256-OJObF9OYA/nzyG2U8RW5sjVihhzdCo8ydKY8aNMDNm0=", + "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": 1680042873, + "narHash": "sha256-OJObF9OYA/nzyG2U8RW5sjVihhzdCo8ydKY8aNMDNm0=", + "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": 1680042873, + "narHash": "sha256-OJObF9OYA/nzyG2U8RW5sjVihhzdCo8ydKY8aNMDNm0=", + "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": 1680042873, + "narHash": "sha256-OJObF9OYA/nzyG2U8RW5sjVihhzdCo8ydKY8aNMDNm0=", + "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": 1680042873, + "narHash": "sha256-OJObF9OYA/nzyG2U8RW5sjVihhzdCo8ydKY8aNMDNm0=", + "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": 1680042873, + "narHash": "sha256-OJObF9OYA/nzyG2U8RW5sjVihhzdCo8ydKY8aNMDNm0=", + "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": 1680042873, + "narHash": "sha256-OJObF9OYA/nzyG2U8RW5sjVihhzdCo8ydKY8aNMDNm0=", + "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": 1680042873, + "narHash": "sha256-OJObF9OYA/nzyG2U8RW5sjVihhzdCo8ydKY8aNMDNm0=", + "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": 1680042873, + "narHash": "sha256-OJObF9OYA/nzyG2U8RW5sjVihhzdCo8ydKY8aNMDNm0=", + "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": 1680042873, + "narHash": "sha256-OJObF9OYA/nzyG2U8RW5sjVihhzdCo8ydKY8aNMDNm0=", + "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": 1680042873, + "narHash": "sha256-OJObF9OYA/nzyG2U8RW5sjVihhzdCo8ydKY8aNMDNm0=", + "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": 1680042873, + "narHash": "sha256-OJObF9OYA/nzyG2U8RW5sjVihhzdCo8ydKY8aNMDNm0=", + "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": 1680042873, + "narHash": "sha256-OJObF9OYA/nzyG2U8RW5sjVihhzdCo8ydKY8aNMDNm0=", + "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": 1680042873, + "narHash": "sha256-OJObF9OYA/nzyG2U8RW5sjVihhzdCo8ydKY8aNMDNm0=", + "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": 1680042873, + "narHash": "sha256-OJObF9OYA/nzyG2U8RW5sjVihhzdCo8ydKY8aNMDNm0=", + "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": 1680042873, + "narHash": "sha256-OJObF9OYA/nzyG2U8RW5sjVihhzdCo8ydKY8aNMDNm0=", + "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": 1680042873, + "narHash": "sha256-OJObF9OYA/nzyG2U8RW5sjVihhzdCo8ydKY8aNMDNm0=", + "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": 1680042873, + "narHash": "sha256-OJObF9OYA/nzyG2U8RW5sjVihhzdCo8ydKY8aNMDNm0=", + "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": 1680042873, + "narHash": "sha256-OJObF9OYA/nzyG2U8RW5sjVihhzdCo8ydKY8aNMDNm0=", + "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": 1680042873, + "narHash": "sha256-OJObF9OYA/nzyG2U8RW5sjVihhzdCo8ydKY8aNMDNm0=", + "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": 1680042873, + "narHash": "sha256-OJObF9OYA/nzyG2U8RW5sjVihhzdCo8ydKY8aNMDNm0=", + "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": 1680042873, + "narHash": "sha256-OJObF9OYA/nzyG2U8RW5sjVihhzdCo8ydKY8aNMDNm0=", + "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": 1680042873, + "narHash": "sha256-OJObF9OYA/nzyG2U8RW5sjVihhzdCo8ydKY8aNMDNm0=", + "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": 1680042873, + "narHash": "sha256-OJObF9OYA/nzyG2U8RW5sjVihhzdCo8ydKY8aNMDNm0=", + "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": 1680042873, + "narHash": "sha256-OJObF9OYA/nzyG2U8RW5sjVihhzdCo8ydKY8aNMDNm0=", + "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": 1680042873, + "narHash": "sha256-OJObF9OYA/nzyG2U8RW5sjVihhzdCo8ydKY8aNMDNm0=", + "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": 1680042873, + "narHash": "sha256-OJObF9OYA/nzyG2U8RW5sjVihhzdCo8ydKY8aNMDNm0=", + "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": 1680042873, + "narHash": "sha256-OJObF9OYA/nzyG2U8RW5sjVihhzdCo8ydKY8aNMDNm0=", + "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": 1680042873, + "narHash": "sha256-OJObF9OYA/nzyG2U8RW5sjVihhzdCo8ydKY8aNMDNm0=", + "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": 1680042873, + "narHash": "sha256-OJObF9OYA/nzyG2U8RW5sjVihhzdCo8ydKY8aNMDNm0=", + "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": 1680042873, + "narHash": "sha256-OJObF9OYA/nzyG2U8RW5sjVihhzdCo8ydKY8aNMDNm0=", + "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": 1680042873, + "narHash": "sha256-OJObF9OYA/nzyG2U8RW5sjVihhzdCo8ydKY8aNMDNm0=", + "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": 1680042873, + "narHash": "sha256-OJObF9OYA/nzyG2U8RW5sjVihhzdCo8ydKY8aNMDNm0=", + "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": 1680042873, + "narHash": "sha256-OJObF9OYA/nzyG2U8RW5sjVihhzdCo8ydKY8aNMDNm0=", + "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": 1680042873, + "narHash": "sha256-OJObF9OYA/nzyG2U8RW5sjVihhzdCo8ydKY8aNMDNm0=", + "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": 1680042873, + "narHash": "sha256-OJObF9OYA/nzyG2U8RW5sjVihhzdCo8ydKY8aNMDNm0=", + "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": 1680042873, + "narHash": "sha256-OJObF9OYA/nzyG2U8RW5sjVihhzdCo8ydKY8aNMDNm0=", + "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": 1680042873, + "narHash": "sha256-OJObF9OYA/nzyG2U8RW5sjVihhzdCo8ydKY8aNMDNm0=", + "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": 1680042873, + "narHash": "sha256-OJObF9OYA/nzyG2U8RW5sjVihhzdCo8ydKY8aNMDNm0=", + "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": 1679663238, + "narHash": "sha256-YfcEwIY5wo60Pmn7FkEfUcmoEqtQslyX8Le1Mi6L/vA=", + "owner": "NixOS", + "repo": "nix", + "rev": "e00abd3f566b16bb107d513925cf33b40cca35f4", + "type": "github" + }, + "original": { + "id": "nix", + "type": "indirect" + } + }, + "nixpkgs": { + "locked": { + "lastModified": 1677932085, + "narHash": "sha256-+AB4dYllWig8iO6vAiGGYl0NEgmMgGHpy9gzWJ3322g=", + "owner": "nixos", + "repo": "nixpkgs", + "rev": "3c5319ad3aa51551182ac82ea17ab1c6b0f0df89", + "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": 1679614379, + "narHash": "sha256-2KddLHHmcIlJu0PuS/vISLKxihTyICUwKWGn0R//028=", + "owner": "NixOS", + "repo": "nixpkgs", + "rev": "994e2ef9e9c70b4dd7257f73452a94e871723685", + "type": "github" + }, + "original": { + "id": "nixpkgs", + "type": "indirect" + } + }, + "nixpkgs_11": { + "locked": { + "lastModified": 1679614379, + "narHash": "sha256-2KddLHHmcIlJu0PuS/vISLKxihTyICUwKWGn0R//028=", + "owner": "NixOS", + "repo": "nixpkgs", + "rev": "994e2ef9e9c70b4dd7257f73452a94e871723685", + "type": "github" + }, + "original": { + "id": "nixpkgs", + "type": "indirect" + } + }, + "nixpkgs_12": { + "locked": { + "lastModified": 1680271125, + "narHash": "sha256-d0BMkipUjJu1G6sC1/T6CIT7zWY1z/9BsswVSZ7vwTo=", + "owner": "NixOS", + "repo": "nixpkgs", + "rev": "0c21eefc3662ac0e046f08df5ce71da28d693984", + "type": "github" + }, + "original": { + "owner": "NixOS", + "ref": "master", + "repo": "nixpkgs", + "type": "github" + } + }, + "nixpkgs_13": { + "locked": { + "lastModified": 1679691714, + "narHash": "sha256-zaHxqBPdkw7MjjsSYgngLjBxFgWeESVevdH7js2VE6U=", + "owner": "NixOS", + "repo": "nixpkgs", + "rev": "2e4e45290e8a0e178642ae2414de558ecca0041a", + "type": "github" + }, + "original": { + "owner": "NixOS", + "ref": "master", + "repo": "nixpkgs", + "type": "github" + } + }, + "nixpkgs_14": { + "locked": { + "lastModified": 1679691714, + "narHash": "sha256-zaHxqBPdkw7MjjsSYgngLjBxFgWeESVevdH7js2VE6U=", + "owner": "NixOS", + "repo": "nixpkgs", + "rev": "2e4e45290e8a0e178642ae2414de558ecca0041a", + "type": "github" + }, + "original": { + "owner": "NixOS", + "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": 1679614379, + "narHash": "sha256-2KddLHHmcIlJu0PuS/vISLKxihTyICUwKWGn0R//028=", + "owner": "NixOS", + "repo": "nixpkgs", + "rev": "994e2ef9e9c70b4dd7257f73452a94e871723685", + "type": "github" + }, + "original": { + "id": "nixpkgs", + "type": "indirect" + } + }, + "nixpkgs_17": { + "locked": { + "lastModified": 1679614379, + "narHash": "sha256-2KddLHHmcIlJu0PuS/vISLKxihTyICUwKWGn0R//028=", + "owner": "NixOS", + "repo": "nixpkgs", + "rev": "994e2ef9e9c70b4dd7257f73452a94e871723685", + "type": "github" + }, + "original": { + "id": "nixpkgs", + "type": "indirect" + } + }, + "nixpkgs_18": { + "locked": { + "lastModified": 1680271125, + "narHash": "sha256-d0BMkipUjJu1G6sC1/T6CIT7zWY1z/9BsswVSZ7vwTo=", + "owner": "NixOS", + "repo": "nixpkgs", + "rev": "0c21eefc3662ac0e046f08df5ce71da28d693984", + "type": "github" + }, + "original": { + "owner": "NixOS", + "ref": "master", + "repo": "nixpkgs", + "type": "github" + } + }, + "nixpkgs_19": { + "locked": { + "lastModified": 1679691714, + "narHash": "sha256-zaHxqBPdkw7MjjsSYgngLjBxFgWeESVevdH7js2VE6U=", + "owner": "NixOS", + "repo": "nixpkgs", + "rev": "2e4e45290e8a0e178642ae2414de558ecca0041a", + "type": "github" + }, + "original": { + "owner": "NixOS", + "ref": "master", + "repo": "nixpkgs", + "type": "github" + } + }, + "nixpkgs_2": { + "locked": { + "lastModified": 1679614379, + "narHash": "sha256-2KddLHHmcIlJu0PuS/vISLKxihTyICUwKWGn0R//028=", + "owner": "NixOS", + "repo": "nixpkgs", + "rev": "994e2ef9e9c70b4dd7257f73452a94e871723685", + "type": "github" + }, + "original": { + "id": "nixpkgs", + "type": "indirect" + } + }, + "nixpkgs_20": { + "locked": { + "lastModified": 1679614379, + "narHash": "sha256-2KddLHHmcIlJu0PuS/vISLKxihTyICUwKWGn0R//028=", + "owner": "NixOS", + "repo": "nixpkgs", + "rev": "994e2ef9e9c70b4dd7257f73452a94e871723685", + "type": "github" + }, + "original": { + "id": "nixpkgs", + "type": "indirect" + } + }, + "nixpkgs_21": { + "locked": { + "lastModified": 1679614379, + "narHash": "sha256-2KddLHHmcIlJu0PuS/vISLKxihTyICUwKWGn0R//028=", + "owner": "NixOS", + "repo": "nixpkgs", + "rev": "994e2ef9e9c70b4dd7257f73452a94e871723685", + "type": "github" + }, + "original": { + "id": "nixpkgs", + "type": "indirect" + } + }, + "nixpkgs_22": { + "locked": { + "lastModified": 1679614379, + "narHash": "sha256-2KddLHHmcIlJu0PuS/vISLKxihTyICUwKWGn0R//028=", + "owner": "NixOS", + "repo": "nixpkgs", + "rev": "994e2ef9e9c70b4dd7257f73452a94e871723685", + "type": "github" + }, + "original": { + "id": "nixpkgs", + "type": "indirect" + } + }, + "nixpkgs_23": { + "locked": { + "lastModified": 1680271125, + "narHash": "sha256-d0BMkipUjJu1G6sC1/T6CIT7zWY1z/9BsswVSZ7vwTo=", + "owner": "NixOS", + "repo": "nixpkgs", + "rev": "0c21eefc3662ac0e046f08df5ce71da28d693984", + "type": "github" + }, + "original": { + "owner": "NixOS", + "ref": "master", + "repo": "nixpkgs", + "type": "github" + } + }, + "nixpkgs_24": { + "locked": { + "lastModified": 1679691714, + "narHash": "sha256-zaHxqBPdkw7MjjsSYgngLjBxFgWeESVevdH7js2VE6U=", + "owner": "NixOS", + "repo": "nixpkgs", + "rev": "2e4e45290e8a0e178642ae2414de558ecca0041a", + "type": "github" + }, + "original": { + "owner": "NixOS", + "ref": "master", + "repo": "nixpkgs", + "type": "github" + } + }, + "nixpkgs_25": { + "locked": { + "lastModified": 1679691714, + "narHash": "sha256-zaHxqBPdkw7MjjsSYgngLjBxFgWeESVevdH7js2VE6U=", + "owner": "NixOS", + "repo": "nixpkgs", + "rev": "2e4e45290e8a0e178642ae2414de558ecca0041a", + "type": "github" + }, + "original": { + "owner": "NixOS", + "ref": "master", + "repo": "nixpkgs", + "type": "github" + } + }, + "nixpkgs_26": { + "locked": { + "lastModified": 1679614379, + "narHash": "sha256-2KddLHHmcIlJu0PuS/vISLKxihTyICUwKWGn0R//028=", + "owner": "NixOS", + "repo": "nixpkgs", + "rev": "994e2ef9e9c70b4dd7257f73452a94e871723685", + "type": "github" + }, + "original": { + "id": "nixpkgs", + "type": "indirect" + } + }, + "nixpkgs_27": { + "locked": { + "lastModified": 1679614379, + "narHash": "sha256-2KddLHHmcIlJu0PuS/vISLKxihTyICUwKWGn0R//028=", + "owner": "NixOS", + "repo": "nixpkgs", + "rev": "994e2ef9e9c70b4dd7257f73452a94e871723685", + "type": "github" + }, + "original": { + "id": "nixpkgs", + "type": "indirect" + } + }, + "nixpkgs_28": { + "locked": { + "lastModified": 1680271125, + "narHash": "sha256-d0BMkipUjJu1G6sC1/T6CIT7zWY1z/9BsswVSZ7vwTo=", + "owner": "NixOS", + "repo": "nixpkgs", + "rev": "0c21eefc3662ac0e046f08df5ce71da28d693984", + "type": "github" + }, + "original": { + "owner": "NixOS", + "ref": "master", + "repo": "nixpkgs", + "type": "github" + } + }, + "nixpkgs_29": { + "locked": { + "lastModified": 1679691714, + "narHash": "sha256-zaHxqBPdkw7MjjsSYgngLjBxFgWeESVevdH7js2VE6U=", + "owner": "NixOS", + "repo": "nixpkgs", + "rev": "2e4e45290e8a0e178642ae2414de558ecca0041a", + "type": "github" + }, + "original": { + "owner": "NixOS", + "ref": "master", + "repo": "nixpkgs", + "type": "github" + } + }, + "nixpkgs_3": { + "locked": { + "lastModified": 1679614379, + "narHash": "sha256-2KddLHHmcIlJu0PuS/vISLKxihTyICUwKWGn0R//028=", + "owner": "NixOS", + "repo": "nixpkgs", + "rev": "994e2ef9e9c70b4dd7257f73452a94e871723685", + "type": "github" + }, + "original": { + "id": "nixpkgs", + "type": "indirect" + } + }, + "nixpkgs_30": { + "locked": { + "lastModified": 1680271125, + "narHash": "sha256-d0BMkipUjJu1G6sC1/T6CIT7zWY1z/9BsswVSZ7vwTo=", + "owner": "NixOS", + "repo": "nixpkgs", + "rev": "0c21eefc3662ac0e046f08df5ce71da28d693984", + "type": "github" + }, + "original": { + "owner": "NixOS", + "ref": "master", + "repo": "nixpkgs", + "type": "github" + } + }, + "nixpkgs_31": { + "locked": { + "lastModified": 1679691714, + "narHash": "sha256-zaHxqBPdkw7MjjsSYgngLjBxFgWeESVevdH7js2VE6U=", + "owner": "NixOS", + "repo": "nixpkgs", + "rev": "2e4e45290e8a0e178642ae2414de558ecca0041a", + "type": "github" + }, + "original": { + "owner": "NixOS", + "ref": "master", + "repo": "nixpkgs", + "type": "github" + } + }, + "nixpkgs_32": { + "locked": { + "lastModified": 1679614379, + "narHash": "sha256-2KddLHHmcIlJu0PuS/vISLKxihTyICUwKWGn0R//028=", + "owner": "NixOS", + "repo": "nixpkgs", + "rev": "994e2ef9e9c70b4dd7257f73452a94e871723685", + "type": "github" + }, + "original": { + "id": "nixpkgs", + "type": "indirect" + } + }, + "nixpkgs_33": { + "locked": { + "lastModified": 1679614379, + "narHash": "sha256-2KddLHHmcIlJu0PuS/vISLKxihTyICUwKWGn0R//028=", + "owner": "NixOS", + "repo": "nixpkgs", + "rev": "994e2ef9e9c70b4dd7257f73452a94e871723685", + "type": "github" + }, + "original": { + "id": "nixpkgs", + "type": "indirect" + } + }, + "nixpkgs_34": { + "locked": { + "lastModified": 1680271125, + "narHash": "sha256-d0BMkipUjJu1G6sC1/T6CIT7zWY1z/9BsswVSZ7vwTo=", + "owner": "NixOS", + "repo": "nixpkgs", + "rev": "0c21eefc3662ac0e046f08df5ce71da28d693984", + "type": "github" + }, + "original": { + "owner": "NixOS", + "ref": "master", + "repo": "nixpkgs", + "type": "github" + } + }, + "nixpkgs_35": { + "locked": { + "lastModified": 1679691714, + "narHash": "sha256-zaHxqBPdkw7MjjsSYgngLjBxFgWeESVevdH7js2VE6U=", + "owner": "NixOS", + "repo": "nixpkgs", + "rev": "2e4e45290e8a0e178642ae2414de558ecca0041a", + "type": "github" + }, + "original": { + "owner": "NixOS", + "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": 1679691714, + "narHash": "sha256-zaHxqBPdkw7MjjsSYgngLjBxFgWeESVevdH7js2VE6U=", + "owner": "NixOS", + "repo": "nixpkgs", + "rev": "2e4e45290e8a0e178642ae2414de558ecca0041a", + "type": "github" + }, + "original": { + "owner": "NixOS", + "ref": "master", + "repo": "nixpkgs", + "type": "github" + } + }, + "nixpkgs_38": { + "locked": { + "lastModified": 1679691714, + "narHash": "sha256-zaHxqBPdkw7MjjsSYgngLjBxFgWeESVevdH7js2VE6U=", + "owner": "NixOS", + "repo": "nixpkgs", + "rev": "2e4e45290e8a0e178642ae2414de558ecca0041a", + "type": "github" + }, + "original": { + "owner": "NixOS", + "ref": "master", + "repo": "nixpkgs", + "type": "github" + } + }, + "nixpkgs_39": { + "locked": { + "lastModified": 1679691714, + "narHash": "sha256-zaHxqBPdkw7MjjsSYgngLjBxFgWeESVevdH7js2VE6U=", + "owner": "NixOS", + "repo": "nixpkgs", + "rev": "2e4e45290e8a0e178642ae2414de558ecca0041a", + "type": "github" + }, + "original": { + "owner": "NixOS", + "ref": "master", + "repo": "nixpkgs", + "type": "github" + } + }, + "nixpkgs_4": { + "locked": { + "lastModified": 1680271125, + "narHash": "sha256-d0BMkipUjJu1G6sC1/T6CIT7zWY1z/9BsswVSZ7vwTo=", + "owner": "NixOS", + "repo": "nixpkgs", + "rev": "0c21eefc3662ac0e046f08df5ce71da28d693984", + "type": "github" + }, + "original": { + "owner": "NixOS", + "ref": "master", + "repo": "nixpkgs", + "type": "github" + } + }, + "nixpkgs_40": { + "locked": { + "lastModified": 1679614379, + "narHash": "sha256-2KddLHHmcIlJu0PuS/vISLKxihTyICUwKWGn0R//028=", + "owner": "NixOS", + "repo": "nixpkgs", + "rev": "994e2ef9e9c70b4dd7257f73452a94e871723685", + "type": "github" + }, + "original": { + "id": "nixpkgs", + "type": "indirect" + } + }, + "nixpkgs_41": { + "locked": { + "lastModified": 1679614379, + "narHash": "sha256-2KddLHHmcIlJu0PuS/vISLKxihTyICUwKWGn0R//028=", + "owner": "NixOS", + "repo": "nixpkgs", + "rev": "994e2ef9e9c70b4dd7257f73452a94e871723685", + "type": "github" + }, + "original": { + "id": "nixpkgs", + "type": "indirect" + } + }, + "nixpkgs_42": { + "locked": { + "lastModified": 1680271125, + "narHash": "sha256-d0BMkipUjJu1G6sC1/T6CIT7zWY1z/9BsswVSZ7vwTo=", + "owner": "NixOS", + "repo": "nixpkgs", + "rev": "0c21eefc3662ac0e046f08df5ce71da28d693984", + "type": "github" + }, + "original": { + "owner": "NixOS", + "ref": "master", + "repo": "nixpkgs", + "type": "github" + } + }, + "nixpkgs_43": { + "locked": { + "lastModified": 1679691714, + "narHash": "sha256-zaHxqBPdkw7MjjsSYgngLjBxFgWeESVevdH7js2VE6U=", + "owner": "NixOS", + "repo": "nixpkgs", + "rev": "2e4e45290e8a0e178642ae2414de558ecca0041a", + "type": "github" + }, + "original": { + "owner": "NixOS", + "ref": "master", + "repo": "nixpkgs", + "type": "github" + } + }, + "nixpkgs_5": { + "locked": { + "lastModified": 1679691714, + "narHash": "sha256-zaHxqBPdkw7MjjsSYgngLjBxFgWeESVevdH7js2VE6U=", + "owner": "NixOS", + "repo": "nixpkgs", + "rev": "2e4e45290e8a0e178642ae2414de558ecca0041a", + "type": "github" + }, + "original": { + "owner": "NixOS", + "ref": "master", + "repo": "nixpkgs", + "type": "github" + } + }, + "nixpkgs_6": { + "locked": { + "lastModified": 1679614379, + "narHash": "sha256-2KddLHHmcIlJu0PuS/vISLKxihTyICUwKWGn0R//028=", + "owner": "NixOS", + "repo": "nixpkgs", + "rev": "994e2ef9e9c70b4dd7257f73452a94e871723685", + "type": "github" + }, + "original": { + "id": "nixpkgs", + "type": "indirect" + } + }, + "nixpkgs_7": { + "locked": { + "lastModified": 1679614379, + "narHash": "sha256-2KddLHHmcIlJu0PuS/vISLKxihTyICUwKWGn0R//028=", + "owner": "NixOS", + "repo": "nixpkgs", + "rev": "994e2ef9e9c70b4dd7257f73452a94e871723685", + "type": "github" + }, + "original": { + "id": "nixpkgs", + "type": "indirect" + } + }, + "nixpkgs_8": { + "locked": { + "lastModified": 1680271125, + "narHash": "sha256-d0BMkipUjJu1G6sC1/T6CIT7zWY1z/9BsswVSZ7vwTo=", + "owner": "NixOS", + "repo": "nixpkgs", + "rev": "0c21eefc3662ac0e046f08df5ce71da28d693984", + "type": "github" + }, + "original": { + "owner": "NixOS", + "ref": "master", + "repo": "nixpkgs", + "type": "github" + } + }, + "nixpkgs_9": { + "locked": { + "lastModified": 1677932085, + "narHash": "sha256-+AB4dYllWig8iO6vAiGGYl0NEgmMgGHpy9gzWJ3322g=", + "owner": "nixos", + "repo": "nixpkgs", + "rev": "3c5319ad3aa51551182ac82ea17ab1c6b0f0df89", + "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": 1680042873, + "narHash": "sha256-OJObF9OYA/nzyG2U8RW5sjVihhzdCo8ydKY8aNMDNm0=", + "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": 1680042873, + "narHash": "sha256-OJObF9OYA/nzyG2U8RW5sjVihhzdCo8ydKY8aNMDNm0=", + "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": 1680042873, + "narHash": "sha256-OJObF9OYA/nzyG2U8RW5sjVihhzdCo8ydKY8aNMDNm0=", + "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": 1680042873, + "narHash": "sha256-OJObF9OYA/nzyG2U8RW5sjVihhzdCo8ydKY8aNMDNm0=", + "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": 1680042873, + "narHash": "sha256-OJObF9OYA/nzyG2U8RW5sjVihhzdCo8ydKY8aNMDNm0=", + "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": 1680042873, + "narHash": "sha256-OJObF9OYA/nzyG2U8RW5sjVihhzdCo8ydKY8aNMDNm0=", + "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": 1676283394, + "narHash": "sha256-XX2f9c3iySLCw54rJ/CZs+ZK6IQy7GXNY4nSOyu2QG4=", + "owner": "numtide", + "repo": "flake-utils", + "rev": "3db36a8b464d0c4532ba1c7dda728f4576d6d073", + "type": "github" + }, + "original": { + "owner": "numtide", + "repo": "flake-utils", + "type": "github" + } + }, + "utils_2": { + "locked": { + "lastModified": 1676283394, + "narHash": "sha256-XX2f9c3iySLCw54rJ/CZs+ZK6IQy7GXNY4nSOyu2QG4=", + "owner": "numtide", + "repo": "flake-utils", + "rev": "3db36a8b464d0c4532ba1c7dda728f4576d6d073", + "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": 1680042873, + "narHash": "sha256-OJObF9OYA/nzyG2U8RW5sjVihhzdCo8ydKY8aNMDNm0=", + "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..fd965c6 --- /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) debug derivation list set string target time type; + 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/hosts/result b/hosts/result new file mode 120000 index 0000000..085d231 --- /dev/null +++ b/hosts/result @@ -0,0 +1 @@ +/nix/store/az13hgwvwbshg00a68mlv1qjgj2fli53-nixos-system-aleph-23.05.20230324.2e4e452 \ No newline at end of file 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..d238c59 --- /dev/null +++ b/libs/accounting/lib/common/book.nix @@ -0,0 +1,601 @@ +{ 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; + when = false; + } + 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 = false && (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 = false && 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/ascii.nix b/libs/aes/ascii.nix new file mode 100644 index 0000000..384d8ff --- /dev/null +++ b/libs/aes/ascii.nix @@ -0,0 +1,119 @@ +let + inherit(builtins) bitAnd concatMap elemAt foldl' genList length map split; + + byteAt + = dword: + index: + if index == 0 then bitAnd dword 255 + else if index == 1 then bitAnd (dword / shift1) 255 + else if index == 2 then bitAnd (dword / shift2) 255 + else if index == 3 then dword / shift3 + else null; + + shift1 = 256; + shift2 = 256 * 256; + shift3 = 256 * 256 * 256; + + hexByte + = byte: + let + h = byte / 16; + l = bitAnd byte 15; + x = [ "0" "1" "2" "3" "4" "5" "6" "7" "8" "9" "a" "b" "c" "d" "e" "f" ]; + x' = elemAt x; + in + "${x' h}${x' l}"; + + hex + = dword: + let + dword' = byteAt dword; + a = hexByte (dword' 0); + b = hexByte (dword' 1); + c = hexByte (dword' 2); + d = hexByte (dword' 3); + in + "${a}${b}${c}${d}"; + + + toChars + = text: + concatMap + ( + x: + if x == "" + then + [] + else + x + ) + (split "(.)" text); + + ascii + = toChars + " !\"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstuvwxyz(|)~"; + + char2int + = ( + foldl' + ( + { result, index }: + character: + { + result + = result + // { + ${character} = index; + }; + index = index + 1; + } + ) + { + index = 32; + result + = { + "\t" = 9; + "\n" = 10; + "\r" = 13; + }; + } + ascii + ).result; + + toIntegers + = text: + map + ( + character: + char2int.${character} + ) + (toChars text); + + toDWords + = data: + let + data' + = if __typeOf data == "string" + then + toIntegers data + else + data; + data'' = data' ++ [ 0 0 0 ]; + d = elemAt data''; + in + genList + ( + i: + let + i' = i * 4; + in + (d i') + + (d (i' + 1)) * shift1 + + (d (i' + 2)) * shift2 + + (d (i' + 3)) * shift3 + ) + ((length data'') / 4); +in +{ + inherit hex toIntegers toDWords; +} diff --git a/libs/aes/ascii.nix.save b/libs/aes/ascii.nix.save new file mode 100644 index 0000000..384d8ff --- /dev/null +++ b/libs/aes/ascii.nix.save @@ -0,0 +1,119 @@ +let + inherit(builtins) bitAnd concatMap elemAt foldl' genList length map split; + + byteAt + = dword: + index: + if index == 0 then bitAnd dword 255 + else if index == 1 then bitAnd (dword / shift1) 255 + else if index == 2 then bitAnd (dword / shift2) 255 + else if index == 3 then dword / shift3 + else null; + + shift1 = 256; + shift2 = 256 * 256; + shift3 = 256 * 256 * 256; + + hexByte + = byte: + let + h = byte / 16; + l = bitAnd byte 15; + x = [ "0" "1" "2" "3" "4" "5" "6" "7" "8" "9" "a" "b" "c" "d" "e" "f" ]; + x' = elemAt x; + in + "${x' h}${x' l}"; + + hex + = dword: + let + dword' = byteAt dword; + a = hexByte (dword' 0); + b = hexByte (dword' 1); + c = hexByte (dword' 2); + d = hexByte (dword' 3); + in + "${a}${b}${c}${d}"; + + + toChars + = text: + concatMap + ( + x: + if x == "" + then + [] + else + x + ) + (split "(.)" text); + + ascii + = toChars + " !\"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstuvwxyz(|)~"; + + char2int + = ( + foldl' + ( + { result, index }: + character: + { + result + = result + // { + ${character} = index; + }; + index = index + 1; + } + ) + { + index = 32; + result + = { + "\t" = 9; + "\n" = 10; + "\r" = 13; + }; + } + ascii + ).result; + + toIntegers + = text: + map + ( + character: + char2int.${character} + ) + (toChars text); + + toDWords + = data: + let + data' + = if __typeOf data == "string" + then + toIntegers data + else + data; + data'' = data' ++ [ 0 0 0 ]; + d = elemAt data''; + in + genList + ( + i: + let + i' = i * 4; + in + (d i') + + (d (i' + 1)) * shift1 + + (d (i' + 2)) * shift2 + + (d (i' + 3)) * shift3 + ) + ((length data'') / 4); +in +{ + inherit hex toIntegers toDWords; +} diff --git a/libs/aes/default.nix b/libs/aes/default.nix new file mode 100644 index 0000000..d3b43bb --- /dev/null +++ b/libs/aes/default.nix @@ -0,0 +1,147 @@ +{ + authData ? [ 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ], + counter ? [ 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ], + key, + text +}: + let + inherit(builtins) bitAnd bitXor concatStringsSep elemAt foldl' map trace deepSeq stringLength substring; + inherit(import ./ascii.nix) toDWords hex; + encryptAES = import ./aes.nix; + + trace' + = x: trace (deepSeq x x); + + traceHex + = value: + trace' (map hex value); + + key' = toDWords key; + counter' = toDWords counter; + encryptChunk = encryptAES key'; + + shift1 = 256; + shift2 = 256 * 256; + shift3 = 256 * 256 * 256; + + byteAt + = dword: + index: + if index == 0 then bitAnd dword 255 + else if index == 1 then bitAnd (dword / shift1) 255 + else if index == 2 then bitAnd (dword / shift2) 255 + else if index == 3 then dword / shift3 + else null; + + H = encryptChunk [ 0 0 0 0 ]; + + max = 256 * 256 * 256 * 256 - 1; + increment + = counter: + let + a = elemAt counter 0; + b = elemAt counter 1; + c = elemAt counter 2; + d = elemAt counter 3; + + inc + = value: + let + a = byteAt value 0; + b = byteAt value 1; + c = byteAt value 2; + d = byteAt value 3; + in + if d == 255 + then + if c == 255 + then + if b == 255 + then + if a == 255 + then + { value = 0; carry = true; } + else + { value = bitAnd value (shift1 - 1) + 1; carry = false; } + else + { value = bitAnd value (shift2 - 1) + shift1; carry = false; } + else + { value = bitAnd value (shift3 - 1) + shift2; carry = false; } + else + { value = value + shift3; carry = false; }; + + a' = inc a; + b' = inc b; + c' = inc c; + d' = inc d; + in + if !d'.carry then [ a b c d'.value ] + else if !c'.carry then [ a b c'.value 0 ] + else if !b'.carry then [ a b'.value 0 0 ] + else if !a'.carry then [ a'.value 0 0 0 ] + else [ 0 0 0 0 ]; + + multiply + = authData: + [ 0 0 0 0 ]; # ghash + + encrypted + = foldl' + ( + { auth, authData, cipherText, counter, index, key }: + plain: + let + auth' + = if index == 3 + then + elemAt (multiply authData) + else + auth; + authData' + = if index == 3 + then + [] + else + authData; + counter' + = if index == 3 + then + increment counter + else + counter; + index' + = if index == 3 + then + 0 + else + index + 1; + key' + = if index == 3 + then + elemAt (encryptChunk counter) + else + key; + cipher = bitXor plain ( key' index' ); + in + # trace "${hex plain} ^ ${hex (key' index')} = ${hex cipher}" + { + auth = auth'; + authData = authData ++ [ (bitXor cipher (auth' index')) ]; + cipherText = cipherText ++ [ cipher ]; + counter = counter'; + index = index'; + key = key'; + } + ) + { + auth = elemAt (toDWords authData); + authData = []; + cipherText = []; + counter = counter'; + index = 3; + key = null; + } + (toDWords text); + in +# traceHex key' + substring 0 (stringLength text) (concatStringsSep "" (map hex encrypted.cipherText)) diff --git a/libs/aes/flake.nix b/libs/aes/flake.nix new file mode 100644 index 0000000..e69de29 diff --git a/libs/aes/lib/default.nix b/libs/aes/lib/default.nix new file mode 100644 index 0000000..16353bf --- /dev/null +++ b/libs/aes/lib/default.nix @@ -0,0 +1,257 @@ +{ ... } @ libs: + let + inherit(builtins) bitAnd bitOr bitXor elemAt foldl' genList length; + inherit(import ./serde.nix libs) packDWord unpackDWord; + + foot = this: elemAt this ((length this) - 1); + + repeat + = rounds: + initial: + convert: + foldl' + convert + initial + (genList (x: x) rounds); + + subTE0 = elemAt (import ./te0.nix); + subTE1 = elemAt (import ./te1.nix); + subTE2 = elemAt (import ./te2.nix); + subTE3 = elemAt (import ./te3.nix); + subSBox = elemAt (import ./sbox.nix); + + substituteLine + = { byte0, byte1, byte2, byte3 }: + { + byte0 = subSBox byte0; + byte1 = subSBox byte1; + byte2 = subSBox byte2; + byte3 = subSBox byte3; + }; + + rotateLine + = { byte0, byte1, byte2, byte3 }: + { + byte0 = byte3; + byte1 = byte0; + byte2 = byte1; + byte3 = byte2; + }; + + getRoundConstant = elemAt (import ./rcon.nix); + + expandRoundKey + = length: + key: + round: + let + prevKey = foot key; + finalLine + = bitXor + (getRoundConstant round) + (packDWord (substituteLine (rotateLine (unpackDWord prevKey.final)))); + dword0 = bitXor prevKey.dword0 finalLine; + dword1 = bitXor prevKey.dword1 dword0; + dword2 = bitXor prevKey.dword2 dword1; + dword3 = bitXor prevKey.dword3 dword2; + dword3' + = if length > 6 + then + packDWord (substituteLine (unpackDWord dword3)); + else + dword3; + dword4 = bitXor prevKey.dword4 dword3'; + dword5 = bitXor prevKey.dword5 dword4; + dword6 = bitXor prevKey.dword6 dword5; + dword7 = bitXor prevKey.dword7 dword6; + in + key + ++ [ + { + inherit dword0 dword1 dword2 dword3 dword4 dword5 dword6 dword7; + final + = elemAt + [ dword0 dword1 dword2 dword3 dword4 dword5 dword6 dword7 ] + length; + } + ]; + + expandKey + = { length, rounds }: + key: + let + length' = length / 32; + in + { + __type__ = "AESkey"; + inherit length; + roundKeys + = repeat + length' + [ + { + dword0 = elemAt key 0; + dword1 = elemAt key 1; + dword2 = elemAt key 2; + dword3 = elemAt key 3; + dword4 = elemAt key 4; + dword5 = elemAt key 5; + dword6 = elemAt key 6; + dword7 = elemAt key 7; + final = elemAt key (length - 1); + } + ] + (expandRoundKey length'); + }; + in + { + inherit expandKey; + expand128bitKey = expandKey { length = 128; rounds = 11; }; + expand192bitKey = expandKey { length = 192; rounds = 13; }; + expand256bitKey = expandKey { length = 256; rounds = 15; }; + + encrypt + = key: + message: + let + cipher + = foldl' + ( + data: + round: + applyRoundKey round data + ) + (unpackDWord message) + (genList (r: r) 4); + + + b = round 0 a; + c = round 1 b; + d = round 2 c; + e = round 3 d; + f = last 4 e; + result + = [ + f.a + f.b + f.c + f.d + ]; + in + result + + } + + k = elemAt key'; + + round + = round: + { a, b, c, d }: + let + i = 8 * round; + + a' = bitXor a (k (i + 0)); + b' = bitXor b (k (i + 1)); + c' = bitXor c (k (i + 2)); + d' = bitXor d (k (i + 3)); + + t0 + = bitXor + (bitXor (te0 (byteAt a' 0)) (te1 (byteAt b' 1))) + (bitXor (te2 (byteAt c' 2)) (te3 (byteAt d' 3))); + t1 + = bitXor + (bitXor (te0 (byteAt b' 0)) (te1 (byteAt c' 1))) + (bitXor (te2 (byteAt d' 2)) (te3 (byteAt a' 3))); + t2 + = bitXor + (bitXor (te0 (byteAt c' 0)) (te1 (byteAt d' 1))) + (bitXor (te2 (byteAt a' 2)) (te3 (byteAt b' 3))); + t3 + = bitXor + (bitXor (te0 (byteAt d' 0)) (te1 (byteAt a' 1))) + (bitXor (te2 (byteAt b' 2)) (te3 (byteAt c' 3))); + + t0' = bitXor t0 (k (i + 4)); + t1' = bitXor t1 (k (i + 5)); + t2' = bitXor t2 (k (i + 6)); + t3' = bitXor t3 (k (i + 7)); + in + { + a + = bitXor + (bitXor (te0 (byteAt t0' 0)) (te1 (byteAt t1' 1))) + (bitXor (te2 (byteAt t2' 2)) (te3 (byteAt t3' 3))); + b + = bitXor + (bitXor (te0 (byteAt t1' 0)) (te1 (byteAt t2' 1))) + (bitXor (te2 (byteAt t3' 2)) (te3 (byteAt t0' 3))); + c + = bitXor + (bitXor (te0 (byteAt t2' 0)) (te1 (byteAt t3' 1))) + (bitXor (te2 (byteAt t0' 2)) (te3 (byteAt t1' 3))); + d + = bitXor + (bitXor (te0 (byteAt t3' 0)) (te1 (byteAt t0' 1))) + (bitXor (te2 (byteAt t1' 2)) (te3 (byteAt t2' 3))); + }; + + last + = round: + { a, b, c, d }: + let + i = 8 * round; + + a' = bitXor a (k (i + 0)); + b' = bitXor b (k (i + 1)); + c' = bitXor c (k (i + 2)); + d' = bitXor d (k (i + 3)); + + t0 + = bitXor + (bitXor (te0 (byteAt a' 0)) (te1 (byteAt b' 1))) + (bitXor (te2 (byteAt c' 2)) (te3 (byteAt d' 3))); + t1 + = bitXor + (bitXor (te0 (byteAt b' 0)) (te1 (byteAt c' 1))) + (bitXor (te2 (byteAt d' 2)) (te3 (byteAt a' 3))); + t2 + = bitXor + (bitXor (te0 (byteAt c' 0)) (te1 (byteAt d' 1))) + (bitXor (te2 (byteAt a' 2)) (te3 (byteAt b' 3))); + t3 + = bitXor + (bitXor (te0 (byteAt d' 0)) (te1 (byteAt a' 1))) + (bitXor (te2 (byteAt b' 2)) (te3 (byteAt c' 3))); + + t0' = bitXor t0 (k (i + 4)); + t1' = bitXor t1 (k (i + 5)); + t2' = bitXor t2 (k (i + 6)); + t3' = bitXor t3 (k (i + 7)); + + a'' + = bitXor + (bitXor (te4 (byteAt t0' 0)) (te4 (byteAt t1' 1) * shift1)) + (bitXor (te4 (byteAt t2' 2) * shift2) (te4 (byteAt t3' 3) * shift3)); + b'' + = bitXor + (bitXor (te4 (byteAt t1' 0)) (te4 (byteAt t2' 1) * shift1)) + (bitXor (te4 (byteAt t3' 2) * shift2) (te4 (byteAt t0' 3) * shift3)); + c'' + = bitXor + (bitXor (te4 (byteAt t2' 0)) (te4 (byteAt t3' 1) * shift1)) + (bitXor (te4 (byteAt t0' 2) * shift2) (te4 (byteAt t1' 3) * shift3)); + d'' + = bitXor + (bitXor (te4 (byteAt t3' 0)) (te4 (byteAt t0' 1) * shift1)) + (bitXor (te4 (byteAt t1' 2) * shift2) (te4 (byteAt t2' 3) * shift3)); + + in + { + a = bitXor a'' (k (i + 8)); + b = bitXor b'' (k (i + 9)); + c = bitXor c'' (k (i + 10)); + d = bitXor d'' (k (i + 11)); + }; + in + data: diff --git a/libs/aes/lib/rcon.nix b/libs/aes/lib/rcon.nix new file mode 100644 index 0000000..655a564 --- /dev/null +++ b/libs/aes/lib/rcon.nix @@ -0,0 +1 @@ +[1 2 4 8 16 32 64 128 27 54] diff --git a/libs/aes/lib/serde.nix b/libs/aes/lib/serde.nix new file mode 100644 index 0000000..249cc35 --- /dev/null +++ b/libs/aes/lib/serde.nix @@ -0,0 +1,100 @@ +{ ... }: + let + inherit(builtins) bitAnd bitOr bitXor elemAt foldl' genList; + + splitInteger + = value: + let + value0 = if value >= 0 then value else -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 = bitAnd value0 255; + byte1 = bitAnd value1 255; + byte2 = bitAnd value2 255; + byte3 = bitAnd value3 255; + byte4 = bitAnd value4 255; + byte5 = bitAnd value5 255; + byte6 = bitAnd value6 255; + byte7 = bitAnd value7 255; + + word0 = bitAnd value0 65535; + word1 = bitAnd value2 65535; + word2 = bitAnd value4 65535; + word3 = bitAnd value6 65535; + + dword0 = bitAnd value0 4294967295; + dword1 = bitAnd value4 4294967295; + }; + in + { + unpackWord + = value: + { inherit(splitInteger value) byte0 byte1; }; + + unpackDWord + = value: + { inherit(splitInteger value) byte0 byte1 byte2 byte3; }; + + unpackQWord + = value: + { inherit(splitInteger value) byte0 byte1 byte2 byte3 byte4 byte5 byte6 byte7; }; + + packWord + = { + byte0 ? 0, + byte1 ? 0, + }: + assert byte0 >= 0 && byte0 < 255; + assert byte1 >= 0 && byte1 < 255; + byte0 + byte1 * 256; + + packDWord + = { + byte0 ? 0, + byte1 ? 0, + byte2 ? 0, + byte3 ? 0, + }: + assert byte0 >= 0 && byte0 < 255; + assert byte1 >= 0 && byte1 < 255; + assert byte2 >= 0 && byte2 < 255; + assert byte3 >= 0 && byte3 < 255; + fold' + (result: byte: result * 256 + byte) + byte3 + [ byte2 byte1 byte0 ]; + + packQWord + = { + byte0 ? 0, + byte1 ? 0, + byte2 ? 0, + byte3 ? 0, + byte4 ? 0, + byte5 ? 0, + byte6 ? 0, + byte7 ? 0, + }: + assert byte0 >= 0 && byte0 < 255; + assert byte1 >= 0 && byte1 < 255; + assert byte2 >= 0 && byte2 < 255; + assert byte3 >= 0 && byte3 < 255; + assert byte4 >= 0 && byte4 < 255; + assert byte5 >= 0 && byte5 < 255; + assert byte6 >= 0 && byte6 < 255; + assert byte7 >= 0 && byte7 < 255; + fold' + (result: byte: result * 256 + byte) + byte7 + [ byte6 byte5 byte4 byte3 byte2 byte1 byte0 ]; + + } diff --git a/libs/aes/lib/te0.nix b/libs/aes/lib/te0.nix new file mode 100644 index 0000000..cf3e159 --- /dev/null +++ b/libs/aes/lib/te0.nix @@ -0,0 +1 @@ +[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/te1.nix b/libs/aes/lib/te1.nix new file mode 100644 index 0000000..81a7ac4 --- /dev/null +++ b/libs/aes/lib/te1.nix @@ -0,0 +1 @@ +[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/te2.nix b/libs/aes/lib/te2.nix new file mode 100644 index 0000000..bcb578d --- /dev/null +++ b/libs/aes/lib/te2.nix @@ -0,0 +1 @@ +[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/te3.nix b/libs/aes/lib/te3.nix new file mode 100644 index 0000000..9e9e6f5 --- /dev/null +++ b/libs/aes/lib/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/te4.nix b/libs/aes/lib/te4.nix new file mode 100644 index 0000000..ead995b --- /dev/null +++ b/libs/aes/lib/te4.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/test.nix b/libs/aes/test.nix new file mode 100644 index 0000000..4db3c31 --- /dev/null +++ b/libs/aes/test.nix @@ -0,0 +1,94 @@ +let + 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 + ''; + }; +in +{ + inherit key cipherText; +} 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..251e3f7 --- /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:NixOS/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..f1b7dd1 --- /dev/null +++ b/libs/config/lib/configurations/default.nix @@ -0,0 +1,449 @@ +{ 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; + when = 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; + when = false; + } + 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; + when = false; + } + 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 = "configurations'"; + data = configurations'; + nice = true; + when = false; + } + debug.info "mapToLegacy" + { + text = "environment"; + data = set.names environment; + nice = true; + when = false; + } + debug.info "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..514d6e8 --- /dev/null +++ b/libs/config/lib/hosts/configure.nix @@ -0,0 +1,170 @@ +{ 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); + when = false; + } + set.map + ( + name: + value: + debug.debug "prepareEnvironment" + { + text = name; + data = value; + when = false; + } + ( + 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; + when = false; + } + value' + else + value + ) + ) + environment; + #inherit(deploy) toNixOSconfiguration; + in + { modules, ... }: + { ... } @ environment: + { about, config ? [], devices, name, network, profile, source, system, users, version, ... } @ host: + let + arguments = mapToArguments configurations; + + configurations + = debug.warn "configurations" { data = users; nice = true; } + (sortUniqueChecked + ( + [] + ++ ( collectAbout about ) + ++ ( collectConfig config ) + ++ ( collectDevices devices ) + ++ ( collectConfig config ) + ++ ( collectNetwork network ) + ++ ( collectProfile profile ) + ++ ( collectSystem system ) + ++ ( collectUsers users ) + ++ ( collectVersion version ) + )); + + host' + = host + // { + inherit arguments configurations nixosConfiguration; + }; + + nixosConfiguration + = 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 + debug.debug [] + { + text = "host'"; + data = host'; + nice = true; + when = false; + } + host' diff --git a/libs/config/lib/hosts/default.nix b/libs/config/lib/hosts/default.nix new file mode 100644 index 0000000..544e487 --- /dev/null +++ b/libs/config/lib/hosts/default.nix @@ -0,0 +1,105 @@ +{ 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; + when = false; + } + 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..1bd7c7f --- /dev/null +++ b/libs/config/lib/modules/collect/options.nix @@ -0,0 +1,307 @@ +{ 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); + when = false; + } + ( + 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 = false && 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..faaa993 --- /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:NixOS/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..a0b0170 --- /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:NixOS/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..4dc31aa --- /dev/null +++ b/libs/config/lib/networks/default.nix @@ -0,0 +1,213 @@ +{ 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; + when = false; + } + [ + ( + 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..de48535 --- /dev/null +++ b/libs/config/lib/packages/default.nix @@ -0,0 +1,218 @@ +{ 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; + when = false; + } + (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..849007d --- /dev/null +++ b/libs/config/lib/peers/default.nix @@ -0,0 +1,108 @@ +{ 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; + when = false; + } + { inherit domain; } // node + else + debug.debug "configure'" + { + text = "network ${domain}"; + show = true; + when = false; + } + nodes + ); + in + if Peer.isInstanceOf config + then + config + else + debug.debug "configure" + { + text = "result"; + show = true; + nice = true; + when = false; + } + ( + 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..2f6b567 --- /dev/null +++ b/libs/config/lib/users/default.nix @@ -0,0 +1,204 @@ +{ 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, ... } @ foo: + { + users.users.${user.name} + = configuration.host + // { + isNormalUser = true; + openssh.authorizedKeys + = { + keys = 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..1e67bc9 --- /dev/null +++ b/libs/core/lib/bool/default.nix @@ -0,0 +1,39 @@ +{ 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 ); + + 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..2e575b7 --- /dev/null +++ b/libs/core/lib/check/default.nix @@ -0,0 +1,279 @@ +{ ansi, context, debug, derivation, expression, intrinsics, 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; + depth = 0; + maxDepth = null; + nice = true; + showType = true; + attrPath = []; + } + 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.concatMappedWith + ( + line: + let + line' + = let + inherit(string.char) escape; + in + string.replace' + { + "\"" = ''\"''; + "\\" = ''\\''; + "$" = ''\$''; + "`" = ''\`''; + ${escape} = "\\e"; + } + line; + in + formatLine ": ${line'}" + ) + "\n" + (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..8e597e6 --- /dev/null +++ b/libs/core/lib/context/default.nix @@ -0,0 +1,160 @@ +{ 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; }; + + 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..4c772de --- /dev/null +++ b/libs/core/lib/debug/default.nix @@ -0,0 +1,348 @@ +{ + 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, + depth ? 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, ... } @ self: + 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 depth 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, + depth ? null, + nice ? false, + show ? false, + showType ? true, + text ? [ ], + trace ? false, + when ? true, + } @ this: + { + inherit depth nice show showType when; + body + = ( toLines' text ) + ++ ( + if this ? data + then + string.splitLines + (string.toTrace depth 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..ce3a54b --- /dev/null +++ b/libs/core/lib/integer/default.nix @@ -0,0 +1,81 @@ +{ debug, expression, float, intrinsics, list, string, type, ... }: + let + inherit(intrinsics) toString; + + 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; + + 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; + in + type "integer" + { + isPrimitive = true; + + signed + = type "SignedInteger" + { + #isInstanceOf = value: isInstanceOf value; + }; + + unsigned + = type "UnsignedInteger" + { + #isInstanceOf = value: isInstanceOf value && value >= 0; + }; + + inherit divmod from isInstanceOf orNull toInteger toString; + } 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..7bc40e2 --- /dev/null +++ b/libs/core/lib/list/default.nix @@ -0,0 +1,556 @@ +{ 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: + let + value' + = if isInstanceOf value + then + value + else + [ value ]; + in + ifOrEmpty value'; + + # 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); + 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; + } 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..b399ab6 --- /dev/null +++ b/libs/core/lib/set/default.nix @@ -0,0 +1,420 @@ +{ 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 } ] -> { 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 + ); + + # 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 + 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..7dba803 --- /dev/null +++ b/libs/core/lib/string/default.nix @@ -0,0 +1,775 @@ +{ debug, derivation, expression, integer, intrinsics, library, list, set, type, ... } @ libs: + let + veryDeep + = { + depth = 10; + 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}\""; + + from'#: T -> string + # where T: Any + = { legacy, display, depth, maxDepth, nice, showType, trace, attrPath ? [], typo ? null } @ args: + input: + ( + if trace + then + intrinsics.trace + ( + let + attrPath' + = concatMapped + ( + key: + if integer.isInstanceOf key + then + "[${integer.toString key}]" + else + ".${key}" + ) + attrPath; + in + "${if typo != null then "<${typo}>" else ""}(${if display then "debug" else "string"})${attrPath'}" + ) + else + x: x + ) + ( + let + inherit(expression.tryEval input) success value; + in + if maxDepth != null + && depth >= maxDepth + then + if !showType + then + "…" + else if !success + then + "" + else + type.matchPrimitiveOrDefault value + { + bool = if value then "true" else "false"; + float = intrinsics.toString value; + int = integer.toString value; + } + (type.format value) + else if depth >= veryDeep.depth + then + debug.panic + "from'" + { + text = "Very deep o.O"; + when = veryDeep.panic; + data + = concatMapped + ( + key: + if integer.isInstanceOf key + then + "[${integer.toString key}]" + else + ".${key}" + ) + attrPath; + } + "" + else if !success + then + debug.panic + "from'" + { + text = "Panic occured while evaluation input value."; + when = !display || legacy; + } + "" + else + type.matchPrimitive value + { + bool + = if legacy + then + if value + then + "1" + else + "" + else + if value + then + "true" + else + "false"; + float = intrinsics.toString value; + int = integer.toString value; + lambda + = if display + then + if legacy + then + "" + else + let + mapArguments + = { ... } @ data: + set.mapToList + ( + key: + value: + if value + then + "${escapeKey key}?" + else + escapeKey key + ) + data; + arguments = intrinsics.functionArgs value; + in + if arguments != {} + then + "{ ${concatWith ", " (mapArguments arguments)} }: …" + else + "_: …" + else + debug.panic "from'" "cannot coerse a function to a string"; + list + = if value == [] + then + if legacy + then + "" + else + "[]" + else + let + indent = repeat " " depth; + body + = list.imap + ( + index: + value: + let + value' + = from' + { + inherit display legacy maxDepth nice showType trace typo; + depth = depth + 1; + attrPath = attrPath ++ [ index ]; + } + value; + in + if this != value + then + "${value'}" + else + "" + ) + value; + this = value; + in + if legacy + then + "[ ${concatMappedWith (value: "(${value})") " " body} ]" + else if nice + then + "[\n${indent} ${concatWith ",\n${indent} " body}\n${indent}]" + else + "[ ${concatWith ", " body} ]"; + null + = if legacy + then + "" + else + "null"; + path = toString value;#"${value}"; + set + = if value == {} + then + "{}" + else if display + then + let + body + = set.mapToList format + ( + if value.__public__ or null != null + then + set.filterByName + value + value.__public__ + else + set.remove + value + [ "__public__" "__type__" "__variant__" ] + ); + format + = key: + value: + let + key' = escapeKey key; + value' + = from' + { + inherit legacy display nice showType; + maxDepth + = if !hasUnfix + then + maxDepth + else + depth; + trace + = trace + || (key' == "lib"); + depth = depth + 1; + attrPath = attrPath ++ [ key' ]; + typo + = if type.getType value != null + then + typeName + else + typo; + } + value; + in + if key' != "lib" + then + if value != this + then + "${key'} = ${value'};" + else + "${key'} = ;" + else + ""; + hasUnfix = value ? __unfix__; + indent = repeat " " depth; + niceText = "{\n${indent} ${concatWith "\n${indent} " body}\n${indent}}"; + this = value; + typeName = type.format value; + in + if debug.Debug.isInstanceOf value + then + "" + else if derivation.isInstanceOf' value + then + "" + else if library.isInstanceOf value + then + "" + else if DoNotFollow.isInstanceOf value + then + "" + else if value._type or null != null + then + "<${value._type}>" + else if nice && !legacy + then + if type.getType value != null + then + "<${typeName} ${niceText}>" + else + niceText + else if legacy + || type.getType value == null + then + "{ ${concatWith " " body} }" + else + "<${typeName} { ${concatWith " " body} }>" + else if value ? outPath + then + value.outPath + else if value ? __toString + then + value.__toString value + else + debug.panic "from'" + { + text = "cannot coerse this set to a string"; + data = value; + }; + string + = let + value' = escape value; + in + if nice + then + let + indent = repeat " " depth; + lines = splitLines value; + lines' + = concatMapped + ( + line: + if match "[ \n\r\t]*" line != null + then + "\n${indent}" + else + "\n${indent} ${replace [ "\${" "''" ] [ "''\${" "'''" ] line}" + ) + lines; + in + if list.length lines > 1 + then + "''${lines'}''" + else + "\"${value'}\"" + else if display || depth > 0 + then + "\"${value'}\"" + else + value; + } + ); + + from#: T -> string + # where T: Any + = from' { display = false; legacy = false; maxDepth = null; depth = 0; nice = false; showType = false; trace = false; }; + + 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; + + 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 ( + from' { display = false; legacy = true; maxDepth = null; depth = 0; nice = false; showType = false; trace = false; } + ); + + toTrace#: T -> string + # where T: Any + = maxDepth: nice: showType: trace: from' { display = true; legacy = false; inherit maxDepth nice showType trace; depth = 0; }; + + toTraceDeep#: T -> string + # where T: Any + = toTrace null; + + toTraceShallow#: T -> string + # where T: Any + = toTrace 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 if 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 from' + getByte getChar getContext getFinalChar + hasContext hash + isEmpty isInstanceOf + length lengthUTF8 + match + orNull + replace replace' repeat + slice split splitAt splitAt' + splitLines splitSpaces + 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..b06a4db --- /dev/null +++ b/libs/core/lib/time/default.nix @@ -0,0 +1,690 @@ +{ 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 + 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}"; + + 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..adbd3ff --- /dev/null +++ b/libs/secrets/lib/secret/default.nix @@ -0,0 +1,304 @@ +{ 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, ... }: + { + 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; }; + 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..d03aa66 --- /dev/null +++ b/libs/secrets/module/gpg.nix @@ -0,0 +1,18 @@ +{ ... } @ libs: +{ pkgs, ... }: +{ + decrypt + = homedir: + encryptedFile: + decryptedFile: + [ ''${pkgs.gnupg}/bin/gpg --homedir ${homedir} --decrypt "${encryptedFile}" > "${decryptedFile}"'' ]; + + 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..76be8b7 --- /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.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.ints.positive; + default = 32; + description = "Length of generated token."; + example = 64; + }; + owner + = lib.mkOption + { + type = types.nullOr types.str; + default = null; + 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..47dfdfe --- /dev/null +++ b/libs/secrets/module/vault.nix @@ -0,0 +1,162 @@ +{ 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 }: + set.mapToListConcatted + ( + name: + { group, owner, encryptedFile, type, ... }: + let + fileName = "${vaultBasePath}/${name}"; + in + if type == "decrypt" + then + (gpg.decrypt homedir 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 + getRandom = "${utils}/cat /dev/urandom"; + filterChars = "${utils}/tr --delete --complement \"${generator}\""; + takeChars = "${utils}/head --bytes \"${string 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 "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..f5510be --- /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:NixOS/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..f0c1914 --- /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:NixOS/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..b4644a9 --- /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 maintainers 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..b7bac7d --- /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:NixOS/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; + } + ); + }; +} \ No newline at end of file diff --git a/packages/redshift-wayland/flake.nix b/packages/redshift-wayland/flake.nix new file mode 100644 index 0000000..a8ed6be --- /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:NixOS/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/wofi-unpatched/flake.nix b/packages/wofi-unpatched/flake.nix new file mode 100644 index 0000000..80681e7 --- /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:NixOS/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..dea224a --- /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; + }; + }; + }; +} \ No newline at end of file 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..2870e1c --- /dev/null +++ b/peers/deutsche-bahn/default.nix @@ -0,0 +1,11 @@ +{ + wireless + = Peer "Wireless Lan bahn" + { + configuration.networking.wireless.networks + = { + "WIFI@DB" = {}; + "WIFIonICE" = {}; + }; + }; +} \ No newline at end of file diff --git a/peers/eduroam/default.nix b/peers/eduroam/default.nix new file mode 100644 index 0000000..af91e40 --- /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" + ''; + }; + }; +} \ No newline at end of file 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..d3e8ff8 --- /dev/null +++ b/peers/flake.nix @@ -0,0 +1,29 @@ +{ + 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"; }; + inherit(core) debug; + peers + = config.peers.load ./. + { + inherit core; + inherit(libsecrets.lib { inherit self; }) secret; + }; + in + debug.debug "peers" + { + text = "peers"; + data = peers; + nice = true; + } + { inherit peers; }; +} 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..d8ab5f6 --- /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; + }; + }; + }; +} \ No newline at end of file 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..5e30cbc --- /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" ]; + } \ No newline at end of file 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..a171b2b --- /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" ]; + }; + }; + }; + }; +} \ No newline at end of file diff --git a/peers/tuc/default.nix b/peers/tuc/default.nix new file mode 100644 index 0000000..d7d9fde --- /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"; + }; + }; + }; +} \ No newline at end of file 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..2bddbe0 --- /dev/null +++ b/profiles/common/environment.nix @@ -0,0 +1,8 @@ +{ + console + = { + keyMap = "de"; + }; + i18n.defaultLocale = "C.UTF-8"; + time.timeZone = "Europe/Berlin"; +} 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..d2243c5 --- /dev/null +++ b/profiles/desktop/default.nix @@ -0,0 +1,23 @@ +{ profiles, services, ... }: + Profile "Desktop." + { + configuration + = [ + ./fonts + ./hardware + { + documentation.enable = false; + security.pam.services + = { + # To make Swaylock unlockable. + swaylock = { /* empty */ }; + }; + } + ]; + isDesktop = true; + parents = with profiles; [ common ]; + services = with services; [ 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..983d728 --- /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; + }; + }; +} \ No newline at end of file diff --git a/profiles/desktop/hardware/default.nix b/profiles/desktop/hardware/default.nix new file mode 100644 index 0000000..322e2b3 --- /dev/null +++ b/profiles/desktop/hardware/default.nix @@ -0,0 +1,11 @@ +[ + ./bluetooth.nix + ./boot.nix + ./pulseaudio.nix + ./trackpoint.nix + { + 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/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..7c164db --- /dev/null +++ b/profiles/flake.nix @@ -0,0 +1,49 @@ +{ + 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:NixOS/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"; }; + inherit(core) debug; + 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 + debug.debug "profiles" + { + text = "profiles"; + nice = true; + data = profiles; + when = false; + } + { inherit 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..675d102 --- /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; + }; + }; +} \ No newline at end of file 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..337a5a1 --- /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"; +} \ No newline at end of file diff --git a/registries/flake.nix b/registries/flake.nix new file mode 100644 index 0000000..c170f5a --- /dev/null +++ b/registries/flake.nix @@ -0,0 +1,87 @@ +{ + 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:NixOS/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 host; + inherit(libcore.lib { inherit self; debug.logLevel = "info"; }) debug path set target; + + config + = { + allowedNonSourcePackages + = [ + "adoptopenjdk-hotspot-bin" + "ant" + "discord" + "electron" + "ghidra" + "gradle" + "i2p" + "libreoffice" + "libreoffice-7.3.7.2-wrapped" + "pdftk" + "sof-firmware" + "spotify" + "tor-browser-bundle-bin" + "vscodium" + "wine" + ]; + allowedUnfreePackages + = [ + "discord" + "hopper" + "memtest86-efi" + "spotify" + ]; + }; + + 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 + { + registries + = ( + target.System.mapStdenv + ( + system: + set.mapValues + ( + { ... } @ registry: + registry."${system}" + ) + registries + ) + ) + // { + __functor + = { ... } @ registries: + { targetSystem, ... }: + registries."${targetSystem}"; + }; + }; +} \ No newline at end of file diff --git a/services/bind/default.nix b/services/bind/default.nix new file mode 100644 index 0000000..e693b67 --- /dev/null +++ b/services/bind/default.nix @@ -0,0 +1,111 @@ +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.concatMappedWith + (ip: "allow ${ip};") + "\n" + 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 ]; + } + ]; + } + ]; + }; + }; +} \ No newline at end of file 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..699cc4b --- /dev/null +++ b/services/default.nix @@ -0,0 +1,13 @@ +{ + bind = ./bind; + #blog = ./blog; + gitea = ./gitea; + gnupg = ./gnupg; + monitoring = ./monitoring; + nginx = ./nginx; + openssh = ./openssh; + printing = ./printing; + restic = ./restic; + simple-nix-mail = ./simple-nix-mail; + static = ./static; +} 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..6107dc3 --- /dev/null +++ b/services/gitea/default.nix @@ -0,0 +1,123 @@ +let + settings + = { + 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_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"; + }; + }; +in + { commonHeaders, enableACME, forceSSL, ... }: + Service "Gitea: Hosting git-repositories" + { + configuration + = { core, network, secret, ... }: + let + inherit(core) string; + domain = "git.${network.domain}"; + port = string network.tcp.ports.gitea; + in + { + gitea + = { + inherit domain settings; + appName = "_sivizius’ Gitea"; + database + = { + type = "postgres"; + name = "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; + ensureDatabases = [ "gitea" ]; + ensureUsers + = [ + { + name = "gitea"; + ensurePermissions."DATABASE gitea" + = "ALL PRIVILEGES"; + } + ]; + }; + + 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..8fcf289 --- /dev/null +++ b/services/gnupg/default.nix @@ -0,0 +1,22 @@ +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/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..682ae9d --- /dev/null +++ b/services/monitoring/default.nix @@ -0,0 +1,163 @@ +{ enableACME, extraConfig, forceSSL, ... }: + Service "Monitoring with grafana and prometheus" + { + configuration + = { core, network, ... }: + let + inherit(core) string; + inherit(network) domain hostName ips tcp; + inherit(tcp) ports; + hostDomain = "${hostName}.${domain}"; + + allowedIPs + = string.concatMappedWith + (ip: "allow ${ip};") + "\n" + 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".enable + = true; + server + = { + domain = "grafana.${domain}"; + http_port = ports.grafana; + root_url = "https://grafana.${domain}/"; + }; + }; + in + { + grafana + = { + enable = true; + provision + = { + enable = true; + datasources.settings.datasources + = [ + { + isDefault + = true; + name = "Prometheus"; + type = "prometheus"; + url = "https://prometheus.${domain}/"; + } + ]; + dashboards + = { + path = ./dashboards; + }; + }; + 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..63d6828 --- /dev/null +++ b/services/nginx/default.nix @@ -0,0 +1,134 @@ +{ commonHttpConfig, enableACME, extraConfig, forceSSL, ... }: + Service "Nginx: HTTP-Server" + { + configuration + = { config, core, network, store, web, ... }: + let + inherit(core) derivation 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 hostName store web; }; + null = {}; + path = importWebsite (path.import value); + set = value; + }; + in + importWebsite (path.import ./hosts).${hostName}; + + allowedIPs + = string.concatMappedWith + (ip: "allow ${ip};") + "\n" + 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"; + }; + }; + + mapLocation + = domain: + location: + { + index ? "index.html", + root, + tryFiles ? "$uri $uri.html $uri.txt $uri.asc /index.html", + ... + }: + let + foo + = string.replace' + { + "\t" = "_"; + "\n" = "_"; + "\r" = "_"; + " " = "_"; + "@" = "-at-"; + "/" = "-"; + }; + directory + = write.directory (foo (if location == "/" then domain else "${domain}${location}")) + ( + set.map + ( + fileName: + page: + path.toFile (foo fileName) "${page}" + ) + root + ); + in + { + inherit index tryFiles; + root = "${directory}"; + }; + + 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; + }; + }; + } \ No newline at end of file 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..752f63e --- /dev/null +++ b/services/nginx/hosts/aleph/default.nix @@ -0,0 +1,36 @@ +{ core, web, ... } @ libs: + let + inherit(core) path; + + env + = { + 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"; + }; + }; + + www."/" + = { + root + = { + "common.css" = path.import ./common.css.nix libs env; + "index.html" = path.import ./index.html.nix libs env; + }; + }; + 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..1c0cd55 --- /dev/null +++ b/services/nginx/hosts/aleph/index.html.nix @@ -0,0 +1,20 @@ +{ web, ... }: +{ head, ... }: + let + inherit(web.html) HTML; + in + HTML { language = "eng"; } + { + inherit head; + body + = with web.html; + [ + ( + main + [ + (h1 "Hello World") + (p "How are you doing?") + ] + ) + ]; + } 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..5e18ffe --- /dev/null +++ b/services/openssh/default.nix @@ -0,0 +1,7 @@ +Service "OpenSSH." +{ + configuration + = { + openssh.enable = true; + }; +} \ No newline at end of file diff --git a/services/printing/default.nix b/services/printing/default.nix new file mode 100644 index 0000000..a6d1802 --- /dev/null +++ b/services/printing/default.nix @@ -0,0 +1,12 @@ +Service "Printing" +{ + configuration + = { registries, ... }: + { + printing + = { + drivers = [ registries.nix.hplip ]; + enable = true; + }; + }; +} \ No newline at end of file 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..e7ee679 --- /dev/null +++ b/services/static/default.nix @@ -0,0 +1,18 @@ +{ 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..5c0f955 --- /dev/null +++ b/users/sivizius/config/default.nix @@ -0,0 +1,51 @@ +{ config, core, profile, registries, user, version, ... } @ env: + let + inherit(core) debug path set; + packages = path.import ./packages env; + in + { + accounts + = { + email = path.import ./email.nix env; + }; + home + = { + packages + = packages.common + ++ ( + if profile.isDesktop + then + packages.desktop + else + [] + ); + shellAliases = path.import ./shellAliases.nix env; + /*shellInit + = '' + export TERM=xterm + '';*/ + stateVersion = version.version; + }; + host + = { + extraGroups + = [ "wheel" ] + ++ ( + if profile.isDesktop + then + [ + "lpadmin" + "network" + "scanner" + "video" + ] + else [] + ); + # Generate with: mkpasswd -m sha-512 $PASSPHRASE + initialHashedPassword = "$6$mgzs1dRcXi.6t2C4$Uf1be0ppPZwF0iGlxu7im/ff6GzRFeGSrsZfhCSEaQigeuTX6o/1yTYn0Lp2FhY2.LVQRGuy5cGvtIAe3UNbp1"; + shell = registries.nix.zsh; + }; + programs = path.import ./programs env; + 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..7797c2a --- /dev/null +++ b/users/sivizius/config/email.nix @@ -0,0 +1,71 @@ +{ config, core, registries, store, user, ... } @ libs: + let + inherit(core) path set; + + 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 + = if attrs.signature or null != null + then + path.toFile "signature.txt" attrs.signature + else + "\"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 + { + accounts = set.map registerAccount ( path.import ./mailAccounts.nix libs ); + inherit 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..b528067 --- /dev/null +++ b/users/sivizius/config/packages/default.nix @@ -0,0 +1,11 @@ +{ core, registries, user, ... } @ env: + 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..c12d90e --- /dev/null +++ b/users/sivizius/config/packages/desktop/applications/graphical/browser.nix @@ -0,0 +1,7 @@ +{ nix, ... }: + with nix; + [ + chromium + firefox-wayland + qutebrowser + ] \ No newline at end of file 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..3a432e3 --- /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 + ] \ No newline at end of file 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..58dc809 --- /dev/null +++ b/users/sivizius/config/packages/desktop/applications/graphical/data.nix @@ -0,0 +1,7 @@ +{ nix, ... }: + with nix; + [ + gnumeric + gnuplot + graphviz + ] \ No newline at end of file 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..a2e5aa4 --- /dev/null +++ b/users/sivizius/config/packages/desktop/applications/graphical/default.nix @@ -0,0 +1,21 @@ +{ 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 + ] 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..2c7f406 --- /dev/null +++ b/users/sivizius/config/packages/desktop/applications/graphical/games.nix @@ -0,0 +1,8 @@ +{ nix, ... }: + with nix; + [ + jdk17 + prismlauncher + sauerbraten + xonotic + ] \ No newline at end of file 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..5a296cf --- /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..773c5c6 --- /dev/null +++ b/users/sivizius/config/packages/desktop/applications/graphical/messenger.nix @@ -0,0 +1,10 @@ +{ nix, ... }: + with nix; + [ + dino + discord + mumble + schildichat-desktop-wayland + 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..03942ee --- /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 + ] \ No newline at end of file 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..8531e2c --- /dev/null +++ b/users/sivizius/config/packages/desktop/tools/development/default.nix @@ -0,0 +1,16 @@ +{ nix, texlive, ... }: +[ + ./python.nix + ./rust.nix + #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..a261a1e --- /dev/null +++ b/users/sivizius/config/packages/desktop/tools/development/python.nix @@ -0,0 +1,8 @@ +{ python3, ... }: + with python3; + [ + 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..0764e6d --- /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 + ] \ No newline at end of file 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..acb90e3 --- /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; + }; + }; +} \ No newline at end of file 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..eeba86b --- /dev/null +++ b/users/sivizius/config/programs/default.nix @@ -0,0 +1,14 @@ +{ core, profile, ... } @ env: + let + inherit(core) path; + in + { + alacritty = path.import ./alacritty.nix env; + 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; + 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..71e8713 --- /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"; +} \ No newline at end of file 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..a36adf0 --- /dev/null +++ b/users/sivizius/config/programs/neomutt.nix @@ -0,0 +1,75 @@ +{ config, core, profile, user, ... }: + let + inherit(core) list path; + mailDir = config.accounts.email.maildirBasePath; + 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" ]; + } + ]; + # TODO: Secrets + /*++ list.fold + ( + list: + accountName: + let + index = secrets.mailAccounts.${accountName}.index or null; + in + if index != null + then + list + ++ [ + ( + { + key = "F${__toString 25 + index}"; + action = "${mailDir}/${accountName}/INBOX"; + map = [ "index" ]; + } + ) + ] + else + list + ) + [ ] + ( attrNames secrets.mailAccounts );*/ + sidebar + = { + enable = true; + format = "%B%?F? [%F]?%* %?N?%N/?%S"; + }; + sort = "reverse-date-received"; + } \ No newline at end of file diff --git a/users/sivizius/config/programs/ssh.nix b/users/sivizius/config/programs/ssh.nix new file mode 100644 index 0000000..340987f --- /dev/null +++ b/users/sivizius/config/programs/ssh.nix @@ -0,0 +1,30 @@ +{ user, ... }: + let + default + = username: + hostname: + { + certificateFile = [ "~/Keys/public/ssh/${username}@${hostname}" ]; + checkHostIP = true; + compression = true; + forwardAgent = false; + forwardX11 = false; + identityFile = [ "~/Keys/secret/ssh/${username}@${hostname}" ]; + identitiesOnly = true; + sendEnv = [ ]; + user = username; + inherit hostname; + }; + in + { + enable = true; + controlMaster = "auto"; + controlPersist = "10m"; + hashKnownHosts = true; + matchBlocks + = { + "aleph" = default user.name "aleph.sivizius.eu"; + "*.sivizius.eu" = default user.name "%h"; + }; + userKnownHostsFile = "~/.local/share/ssh/known_hosts"; + } \ No newline at end of file diff --git a/users/sivizius/config/programs/zsh.nix b/users/sivizius/config/programs/zsh.nix new file mode 100644 index 0000000..4654bc5 --- /dev/null +++ b/users/sivizius/config/programs/zsh.nix @@ -0,0 +1,16 @@ +{ + autocd = true; + enable = true; + enableAutosuggestions = true; + enableCompletion = true; + oh-my-zsh + = { + enable = true; + plugins + = [ + "git" + "pass" + ]; + theme = "candy"; + }; +} diff --git a/users/sivizius/config/services/default.nix b/users/sivizius/config/services/default.nix new file mode 100644 index 0000000..1972b69 --- /dev/null +++ b/users/sivizius/config/services/default.nix @@ -0,0 +1,14 @@ +{ core, ... } @ env: + let + inherit(core) path; + in + { + gpg-agent + = { + enable = false; + enableSshSupport = true; + sshKeys = [ "CEF451414076E1DDEAFD25C1E3699CD58D553ACE" ]; + }; + 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..052cb07 --- /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"; +} \ No newline at end of file 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..6c10554 --- /dev/null +++ b/users/sivizius/config/shellAliases.nix @@ -0,0 +1,83 @@ +{ core, registries, secret, ... }: + let + inherit(core) string; + lt = "${registries.nix.exa}/bin/exa -lahTL"; + in + { + token = secret.generateToken' "token"; + c = "${registries.nix.ncurses}/bin/clear"; + 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"; + l2 = "${lt}2"; + l3 = "${lt}3"; + l4 = "${lt}4"; + l5 = "${lt}5"; + l6 = "${lt}6"; + l7 = "${lt}7"; + l8 = "${lt}8"; + l9 = "${lt}9"; + inherit lt; + man = "echo 'Use enby […], Fight teh cistem!'"; + nixsh = "${registries.nix.nix}/bin/nix-shell --run ${registries.nix.zsh}/bin/zsh "; + please = "${registries.nix.sudo}/bin/sudo"; + 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 + ''; + tucVPN + = string.concatWith "" + [ + "${registries.nix.pass}/bin/pass \"Communication/E-Mail/sebastian.walz@s2015.tu-chemnitz.de\"" + " | sudo openconnect" + " --authgroup=\"TU-Chemnitz\"" + " --passwd-on-stdin" + " --protocol=anyconnect" + " --user=sewal" + " vpngate.hrz.tu-chemnitz.de" + ]; + use = "${registries.nix.nix}/bin/nix-shell -I nixpkgs=https://github.com/NixOS/nixpkgs/archive/master.tar.gz --run ${registries.nix.zsh}/bin/zsh -p "; + } 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..d59b61d --- /dev/null +++ b/users/sivizius/config/sway/assigns.nix @@ -0,0 +1,30 @@ +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 = "^telegramdesktop$"; } + { app_id = "^dino$"; } + { title = "^nheko"; } + { class = "^discord$"; } + { class = "^Mumble$"; } + ]; +} diff --git a/users/sivizius/config/sway/config.nix b/users/sivizius/config/sway/config.nix new file mode 100644 index 0000000..e4b8c40 --- /dev/null +++ b/users/sivizius/config/sway/config.nix @@ -0,0 +1,115 @@ +{ 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 + ''; + ranger = "${registries.nix.ranger}/bin/ranger"; + workspace3 = "sleep 2 && ${swaymsg} \"workspace 3; layout tabbed\""; + 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.schildichat-desktop-wayland}/bin/schildichat-desktop"; always = false; } + { command = "${terminal} -t neomutt -e ${neomutt}"; always = false; } + { command = "${terminal} -t ranger -e ${ranger}"; always = false; } + { command = "${bar}"; always = false; } + { command = "${workspace3}"; always = true; } + { 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..b5294a7 --- /dev/null +++ b/users/sivizius/config/sway/default.nix @@ -0,0 +1,24 @@ +{ core, profile, ... } @ env: + let + inherit(core) path; + in + { + enable = profile.isDesktop; + config + = if profile.isDesktop + then + path.import ./config.nix env + else + {}; + extraSessionCommands + = if profile.isDesktop + then + '' + export SDL_VIDEODRIVER=wayland + export QT_QPA_PLATFORM=wayland + export QT_WAYLAND_DISABLE_WINDOWDECORATION=1 + export _JAVA_AWT_WM_NONREPARENTING=1 + '' + else + ""; + } \ No newline at end of file diff --git a/users/sivizius/config/sway/keybindings.nix b/users/sivizius/config/sway/keybindings.nix new file mode 100644 index 0000000..4a161ac --- /dev/null +++ b/users/sivizius/config/sway/keybindings.nix @@ -0,0 +1,209 @@ +{ core, registries, store, ... }: +{ + lock, terminal, + volumeDelta, brightnessDelta, + modifier, up, down, left, right +}: + let + inherit(core) 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 | tee -a $HOME/network.log" + "| ${registries.nix.coreutils}/bin/tail -n +3 | tee -a $HOME/network.log" + "| ${ripgrep} -o \"^[^\t]+\t[^\t]+\" | tee -a $HOME/network.log" + "| ${woficmd} --show dmenu | tee -a $HOME/network.log" + "| ${ripgrep} -o \"^\d+\" | 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 + { + # Execute Stuff + "${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..2a7d51b --- /dev/null +++ b/users/sivizius/default.nix @@ -0,0 +1,14 @@ +{ core, ... } @ 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 b/users/sivizius/keys/ssh/aleph new file mode 100644 index 0000000..4cb75ac --- /dev/null +++ b/users/sivizius/keys/ssh/aleph @@ -0,0 +1 @@ +ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABgQDR1eqjiJKg2fUHpCBQxVyqfaiJMhUsN0UOO6uAzm04bbEOYb+iFGV/6IZ65egQ2UmBzbghU7Wm0ngfk8PNsfZkwtfQGm9VNcU00O7gNxH29/HaRZ1fhjFVTtJCw8AQmgVlz7/bgGb2Tpr9KjuUI/R1Lmp68/2JEhmP1Uztl8mbf82vW8dpIHVlU O+YlCrP03EAFJPnTyYGv74Fw7COJCdUHmfpuOO/38sOe89nSzUskws9CjxJ4D0tG3v323EOPcY2hs0xa1mZQY/FV96Cj6Cr5XH0TKqfe7LI2MDhzven/loANRQaR1YuZ0FW59Hf4V8xBLpVhho5gCx7oJH99K20rc7agDzKy1tt61Yd/nK2Fp5xUkOvKd3ZDdXbrPuK2fPaSyNZHQBBI2zdld/jGsmCFc3sUTIleghUAPNyc/kVmyXqdI3y9UwIN6y5Ed7PwhRiLlQjdI54B9/ANI/WO7phk7d4V6G0sNMeNXFji5hiHGxKfsroVsb3aW3PdUbjfpc= { user = "sivizius"; host = "aleph.sivizius.eu"; contact = "aleph@sivizius.eu"; date = "2022-05-28"; } \ No newline at end of file diff --git a/users/sivizius/keys/ssh/aleph.nix b/users/sivizius/keys/ssh/aleph.nix new file mode 100644 index 0000000..0ea0559 --- /dev/null +++ b/users/sivizius/keys/ssh/aleph.nix @@ -0,0 +1,15 @@ +{ + contact = "aleph@sivizius.eu"; + date = "2022-05-28"; + method = "rsa"; + key + = "AAAAB3NzaC1yc2EAAAADAQABAAABgQDR1eqjiJKg2fUHpCBQxVyqfaiJMhUsN0U" + + "OO6uAzm04bbEOYb+iFGV/6IZ65egQ2UmBzbghU7Wm0ngfk8PNsfZkwtfQGm9VNc" + + "U00O7gNxH29/HaRZ1fhjFVTtJCw8AQmgVlz7/bgGb2Tpr9KjuUI/R1Lmp68/2JE" + + "hmP1Uztl8mbf82vW8dpIHVlUO+YlCrP03EAFJPnTyYGv74Fw7COJCdUHmfpuOO/" + + "38sOe89nSzUskws9CjxJ4D0tG3v323EOPcY2hs0xa1mZQY/FV96Cj6Cr5XH0TKq" + + "fe7LI2MDhzven/loANRQaR1YuZ0FW59Hf4V8xBLpVhho5gCx7oJH99K20rc7agD" + + "zKy1tt61Yd/nK2Fp5xUkOvKd3ZDdXbrPuK2fPaSyNZHQBBI2zdld/jGsmCFc3sU" + + "TIleghUAPNyc/kVmyXqdI3y9UwIN6y5Ed7PwhRiLlQjdI54B9/ANI/WO7phk7d4" + + "V6G0sNMeNXFji5hiHGxKfsroVsb3aW3PdUbjfpc="; +}