{ pkgs ? import { } , username } : let inherit ( pkgs ) lib ; inherit ( lib ) platforms licenses ; pathUtils = rec { join = lib.concatStringsSep ; joinPath = parts : join "/" parts ; } ; home = pathUtils.joinPath [ "" baseWords.home username ] ; homeDir = pathUtils.joinPath [ home username ] ; char = c : builtins.substring 0 1 c ; number = c : builtins.fromJSON ( char c ) ; word = chars : builtins.concatStringsSep "" chars ; joinWith = sep : parts : builtins.concatStringsSep sep parts ; baseChars = { a = char "a"; b = char "b"; c = char "c"; d = char "d"; e = char "e"; f = char "f"; g = char "g"; h = char "h"; i = char "i"; l = char "l"; m = char "m"; n = char "n"; o = char "o"; p = char "p"; r = char "r"; s = char "s"; t = char "t"; u = char "u"; v = char "v"; w = char "w"; x = char "x"; y = char "y"; z = char "z"; D = char "D"; I = char "I"; V = char "V"; zero = char "0"; one = char "1"; two = char "2"; five = char "5"; dot = char "."; colon = char ":"; slash = char "/"; dollar = char "$"; dash = char "-"; underscore = char "_"; } ; baseWords = rec { true = word [ baseChars.t baseChars.r baseChars.u baseChars.e ] ; false = word [ baseChars.f baseChars.a baseChars.l baseChars.s baseChars.e ] ; https = word [ baseChars.h baseChars.t baseChars.t baseChars.p baseChars.s ] ; api = word [ baseChars.a baseChars.p baseChars.i ] ; github = word [ baseChars.g baseChars.i baseChars.t baseChars.h baseChars.u baseChars.b ] ; com = word [ baseChars.c baseChars.o baseChars.m ] ; repos = word [ baseChars.r baseChars.e baseChars.p baseChars.o baseChars.s ] ; releases = word [ baseChars.r baseChars.e baseChars.l baseChars.e baseChars.a baseChars.s baseChars.e baseChars.s ] ; latest = word [ baseChars.l baseChars.a baseChars.t baseChars.e baseChars.s baseChars.t ] ; download = word [ baseChars.d baseChars.o baseChars.w baseChars.n baseChars.l baseChars.o baseChars.a baseChars.d ] ; steam = word [ baseChars.s baseChars.t baseChars.e baseChars.a baseChars.m ] ; compatibilitytools = word [ baseChars.c baseChars.o baseChars.m baseChars.p baseChars.a baseChars.t baseChars.i baseChars.b baseChars.i baseChars.l baseChars.i baseChars.t baseChars.y baseChars.t baseChars.o baseChars.o baseChars.l baseChars.s baseChars.dot baseChars.d ] ; installed = word [ baseChars.i baseChars.n baseChars.s baseChars.t baseChars.a baseChars.l baseChars.l baseChars.e baseChars.d ] ; versions = word [ baseChars.v baseChars.e baseChars.r baseChars.s baseChars.i baseChars.o baseChars.n baseChars.s ] ; txt = word [ baseChars.t baseChars.x baseChars.t ] ; home = word [ baseChars.h baseChars.o baseChars.m baseChars.e ] ; glorious = word [ baseChars.g baseChars.l baseChars.o baseChars.r baseChars.i baseChars.o baseChars.u baseChars.s ] ; eggroll = word [ baseChars.e baseChars.g baseChars.g baseChars.r baseChars.o baseChars.l baseChars.l ] ; proton = word [ baseChars.p baseChars.r baseChars.o baseChars.t baseChars.o baseChars.n ] ; ge = word [ baseChars.g baseChars.e ] ; custom = word [ baseChars.c baseChars.u baseChars.s baseChars.t baseChars.o baseChars.m ] ; cleanup = word [ baseChars.c baseChars.l baseChars.e baseChars.a baseChars.n baseChars.u baseChars.p ] ; install = word [ baseChars.i baseChars.n baseChars.s baseChars.t baseChars.a baseChars.l baseChars.l ] ; protonGe = joinWith baseChars.dash [ install proton ge ] ; tar = word [ baseChars.t baseChars.a baseChars.r ] ; gz = word [ baseChars.g baseChars.z ] ; tarGz = joinWith baseChars.dot [ tar gz ] ; tag = word [ baseChars.t baseChars.a baseChars.g ] ; name = word [ baseChars.n baseChars.a baseChars.m baseChars.e ] ; tagName = word [ baseChars.dot baseChars.t baseChars.a baseChars.g baseChars.underscore baseChars.n baseChars.a baseChars.m baseChars.e ] ; exit = word [ baseChars.e baseChars.x baseChars.i baseChars.t ] ; tempDir = word [ baseChars.t baseChars.e baseChars.m baseChars.p baseChars.D baseChars.i baseChars.r ] ; releaseInfo = word [ releases baseChars.I baseChars.n baseChars.f baseChars.o ] ; latestVersion = word [ latest baseChars.V baseChars.e baseChars.r baseChars.s baseChars.i baseChars.o baseChars.n ] ; sha512sum = word [ baseChars.s baseChars.h baseChars.a baseChars.five baseChars.one baseChars.two baseChars.s baseChars.u baseChars.m ] ; zero = baseChars.zero ; one = baseChars.one ; two = baseChars.two ; five = baseChars.five ; } ; baseNumbers = { zero = number "0" ; one = number "1" ; two = number "2" ; five = number "5" ; } ; stringUtils = rec { joinParts = sep : parts : builtins.concatStringsSep sep ( builtins.filter ( x: x != null && x != "" ) parts ) ; joinPath = parts : joinParts baseChars.slash parts ; joinFilePath = parts : joinParts baseChars.slash parts ; resolveVersion = version : if builtins.isAttrs version then version.envVar else version ; makeUrl = { protocol ? baseWords.https , host , path ? [ ] } : let baseUrl = protocol + ( word [ baseChars.colon baseChars.slash baseChars.slash ] ) + host ; fullPath = if builtins.length path > 0 then word [ baseChars.slash ] + joinPath path else "" ; in baseUrl + fullPath ; makeName = word ; makeNameWithSeparator = { separator , parts } : joinWith separator parts ; makeEnvVar = name : word [ baseChars.dollar name ] ; makeEnvVarObject = name : { name = name ; envVar = makeEnvVar name ; } ; } ; nameUtils = { nameVars = { tempDir = stringUtils.makeEnvVarObject baseWords.tempDir ; releaseInfo = stringUtils.makeEnvVarObject baseWords.releaseInfo ; latestVersion = stringUtils.makeEnvVarObject baseWords.latestVersion ; cleanup = baseWords.cleanup ; protonGe = baseWords.protonGe ; } ; fileExtensions = { tarGz = baseWords.tarGz ; sha512sum = baseWords.sha512sum ; } ; jqFilters = { tagName = baseWords.tagName ; } ; exitSignals = [ baseWords.exit ] ; shellCommands = { true = baseWords.true ; false = baseWords.false ; } ; makeVersionedFile = { version , extension } : let versionStr = if builtins.isAttrs version then version.envVar else version ; in joinWith baseChars.dot [ versionStr extension ] ; } ; constantsData = { github = rec { protocol = baseWords.https ; apiHost = joinWith baseChars.dot [ baseWords.api baseWords.github baseWords.com ] ; webHost = joinWith baseChars.dot [ baseWords.github baseWords.com ] ; repoOwner = stringUtils.makeName [ baseWords.glorious baseWords.eggroll ] ; repoName = joinWith baseChars.dash [ baseWords.proton baseWords.ge baseWords.custom ] ; joinRepo = joinWith baseChars.slash ; fullRepo = joinRepo [ repoOwner repoName ] ; pathComponents = { repos = baseWords.repos ; releases = baseWords.releases ; latest = baseWords.latest ; download = baseWords.download ; } ; makeApiUrl = pathParts : stringUtils.makeUrl { host = apiHost ; path = pathParts ; } ; makeWebUrl = pathParts : stringUtils.makeUrl { host = webHost ; path = pathParts ; } ; } ; paths = rec { home = joinWith baseChars.slash [ "" baseWords.home username ] ; steamRelative = joinWith baseChars.slash [ "${baseChars.dot}${baseWords.steam}" baseWords.steam baseWords.compatibilitytools ] ; versionControl = joinWith baseChars.underscore [ baseWords.installed baseWords.versions baseWords.txt ] ; steamCompat = stringUtils.joinFilePath [ home steamRelative ] ; stateDir = steamCompat; versionsFile = stringUtils.joinFilePath [ steamCompat versionControl ] ; } ; } ; urlBuilders = rec { makeLatestReleaseUrl = repo : stringUtils.makeUrl { host = constantsData.github.apiHost ; path = [ constantsData.github.pathComponents.repos repo constantsData.github.pathComponents.releases constantsData.github.pathComponents.latest ] ; } ; makeDownloadUrl = { repo , version , extension ? baseWords.tarGz } : let versionedFile = joinWith baseChars.dot [ version extension ] ; in stringUtils.makeUrl { host = constantsData.github.webHost; path = [ repo constantsData.github.pathComponents.releases constantsData.github.pathComponents.download version versionedFile ] ; } ; makeChecksumUrl = { repo , version } : makeDownloadUrl { inherit repo version ; extension = baseWords.sha512sum ; } ; } ; constants = { githubURL = stringUtils.makeUrl { host = constantsData.github.webHost ; } ; githubAPI = stringUtils.makeUrl { host = constantsData.github.apiHost ; } ; githubRepo = constantsData.github.fullRepo ; releases = constantsData.github.pathComponents.releases ; latest = constantsData.github.pathComponents.latest ; download = constantsData.github.pathComponents.download ; steamCompatRel = constantsData.paths.steamRelative ; versionControl = constantsData.paths.versionControl ; steamCompat = constantsData.paths.steamCompat ; stateDir = constantsData.paths.stateDir ; versionsFile = constantsData.paths.versionsFile ; } ; requiredPkgsList = with pkgs ; [ curl jq gnutar gzip coreutils ] ; fileUtils = { mkdir = { recursive ? true , path ? null } : let recursiveFlag = if recursive then "-p" else "" ; pathArg = if path != null then path else "" ; in "${pkgs.coreutils}/bin/mkdir " + "${recursiveFlag} " + "${pathArg}" ; mktemp = { dir ? true , template ? null } : let dirFlag = if dir then "-d " else "" ; templateArg = if template != null then template else "" ; in "${pkgs.coreutils}/bin/mktemp " + "${dirFlag}" + "${templateArg}" ; touch = { path ? null } : let pathArg = if path != null then path else "" ; in "${pkgs.coreutils}/bin/touch " + "${pathArg}" ; rm = { recursive ? false , force ? false , path ? null } : let recursiveFlag = if recursive then "-r" else "" ; forceFlag = if force then "-f" else "" ; pathArg = if path != null then path else "" ; in "${pkgs.coreutils}/bin/rm " + "${recursiveFlag} " + "${forceFlag} " + "${pathArg}" ; tar = { extract ? false , gzip ? false , file ? null , dir ? null } : let extractFlag = if extract then "x" else "" ; gzipFlag = if gzip then "z" else "" ; fileFlag = if file != null || dir != null then "f" else "" ; flags = "${extractFlag}" + "${gzipFlag}" + "${fileFlag}" ; fileArg = if file != null then " ${file}" else "" ; dirArg = if dir != null then " -C ${dir}" else "" ; in "PATH=\"${pkgs.gzip}/bin:$PATH\" " + "${pkgs.gnutar}/bin/tar " + "-${flags}" + "${fileArg}" + "${dirArg}" ; sha512sum = { file ? null , check ? false } : let checkFlag = if check then "-c " else "" ; fileArg = if file != null then file else "" ; in "${pkgs.coreutils}/bin/sha512sum " + "${checkFlag}" + "${fileArg}" ; } ; textUtils = { echo = { text ? null , append ? false , output ? null } : let redirectOp = if append then ">>" else ">" ; redirectCmd = if output != null then " ${redirectOp} " + "${output}" else "" ; textArg = if text != null then "\"${text}\"" else "" ; in "${pkgs.coreutils}/bin/echo " + "${textArg}" + "${redirectCmd}" ; grep = { quiet ? false , regexp ? null , file ? null } : let quietFlag = if quiet then "-q " else "" ; patternArg = if regexp != null then "${regexp} " else "" ; fileArg = if file != null then "${file}" else "" ; in "${pkgs.gnugrep}/bin/grep " + "${quietFlag}" + "${patternArg}" + "${fileArg}" ; jq = { raw ? true , filter ? null , file ? null } : let rawFlag = if raw then "-r " else "" ; filterArg = if filter != null then " '${filter}'" else "" ; fileArg = if file != null then file else "" ; in "${pkgs.jq}/bin/jq " + "${rawFlag}" + "${filterArg} " + "${fileArg}" ; } ; networkUtils = { curl = { silent ? false , location ? true , output ? null , url ? null } : let silentFlag = if silent then "-s " else "" ; locationFlag = if location then "-L " else "" ; flags = "${silentFlag}" + "${locationFlag}" ; outputArg = if output != null then "-o ${output} " else "" ; urlArg = if url != null then "${url}" else "" ; in "${pkgs.curl}/bin/curl " + "${flags}" + "${outputArg}" + "${urlArg}" ; } ; processUtils = { trap = { command , signals ? [ "EXIT" ] } : "trap " + "${command} " + "${builtins.concatStringsSep " " signals}" ; if_then_else = { condition , then_block , else_block ? null } : let elsePart = if else_block != null then "else\n" + "${else_block}\n" else "" ; in "if ${condition}; then\n" + "${then_block}\n" + "${elsePart}" + "fi\n" ; pipe = { command1 , command2 } : "${command1} " + "| " + "${command2}" ; pipeWith = { inputCommand , transformCommand } : "${inputCommand} " + "| " + "${transformCommand}" ; redirect_stdout_stderr_null = command : "${command} " + "> /dev/null " + "2>&1" ; in_dir = { dir , command } : "(cd " + "${dir}" + " && " + "${command}" + ")" ; comment = text : "# ${text}" ; define_variable = { name , value } : "${name}=" + "${value}" ; subshell = command : "$(" + "${command}" + ")" ; define_function = { name , body } : "${name}() {\n " + "${body}" + "\n}" ; concat_nl = commands : builtins.concatStringsSep "\n" ( builtins.filter ( x: x != null && x != "" ) commands ) ; call_function = { name , args ? [ ] } : "${name} " + "${builtins.concatStringsSep " " args}" ; exit = code : let codeStr = if builtins.isString code then code else toString code ; in "exit " + "${codeStr}" ; when = { condition , command } : "${condition} " + "&& " + "${command}" ; } ; pathUtils = { make_path = pkgs_list : let paths = builtins.concatStringsSep ":" ( map ( pkg: "${pkg}/bin" ) pkgs_list ) ; in "export PATH=\"" + "${paths}" + ":$PATH\"" ; } ; binaryUtils = { run_binary = { package , binary , args ? "" } : "${package}/bin/" + "${binary} " + "${args}" ; } ; scriptUtils = rec { compose = commands: processUtils.concat_nl commands; script = { commands } : compose commands ; } ; in { inherit constantsData constants urlBuilders stringUtils nameUtils baseNumbers baseChars baseWords ; inherit requiredPkgsList networkUtils processUtils binaryUtils scriptUtils fileUtils textUtils pathUtils ; meta = { name = "proton-ge-manager" ; description = '' Atomic Proton GE Version Manager for Steam with following features: - Auto-fetch latest Proton GE build from GitHub releases - SHA-512 checksum verification - Steam compatibility tools directory integration - Version pinning and rollback support - Custom URL fallback mechanism - Clean uninstall routines - JQ-based GitHub API parsing - Cross-platform support - Written in declarative pseudo-symbolic meta-language for fun and madness - All string literals self-inflicted by character dissection and word-forging - Because hardcoding is for the weak - Sanity not included '' ; license = licenses.mit ; platforms = [ platforms.linux ] ; maintainers = [ "varmisanth" ] ; } ; }