diff --git a/.github/workflows/check.yml b/.github/workflows/check.yml index e637f8c..add35ef 100644 --- a/.github/workflows/check.yml +++ b/.github/workflows/check.yml @@ -6,7 +6,7 @@ on: paths: - 'keymap/**' - 'QMK' - - 'shell.nix' + - '**/*.nix' - '.github/workflows/check.yml' workflow_dispatch: {} @@ -21,14 +21,14 @@ jobs: submodules: recursive path: ./repo - - name: Set up Nix + - name: "Nix: set up" uses: cachix/install-nix-action@v15 with: nix_path: nixpkgs=channel:nixos-unstable extra_nix_config: | experimental-features = nix-command - - name: Set up cache + - name: "Nix: cache set up" uses: cachix/cachix-action@v10 with: name: kip93 @@ -36,111 +36,72 @@ jobs: extraPullNames: nix-community skipPush: true - - name: Print nixpkgs version + - name: "Nix: version" run: | nix-instantiate --eval -E '"nixpkgs version: ${(import {}).lib.version}"' + nix-env --version - - name: Shellcheck shell.nix - id: shellcheck + - name: "Nix: format" + id: nix-format working-directory: ./repo run: | - ( - printf '#!/bin/bash\n' ; - nix-shell --pure shell.nix --run : >/dev/null ; - nix-instantiate shell.nix 2>/dev/null | xargs -i sed '1,5d' {} ; - ) | nix-shell -p shellcheck --run 'shellcheck -' + nix-build scripts/nix-format.nix | xargs sh -c continue-on-error: true - - name: QMK Format - id: qmk-format + - name: "Nix: lint" + id: nix-lint working-directory: ./repo run: | - nix-shell --run format - git diff --exit-code --name-only + nix-build scripts/nix-lint.nix | xargs sh -c continue-on-error: true - - name: QMK Lint - id: qmk-lint + - name: "Nix: shellcheck" + id: nix-shellcheck working-directory: ./repo run: | - nix-shell --run lint + nix-build scripts/nix-shellcheck.nix | xargs sh -c continue-on-error: true - - name: Check shell.nix format - id: nixpkgs-fmt + - name: "Nix: vulnerabilities" + id: nix-vulnerabilities working-directory: ./repo run: | - nix-shell -p nixpkgs-fmt --run 'nixpkgs-fmt --check shell.nix' + nix-build scripts/nix-vulnerabilities.nix | xargs sh -c continue-on-error: true - - name: Lint shell.nix - id: nix-linter + - name: "Nix: logic" + id: nix-logic working-directory: ./repo run: | - nix-shell -p nix-linter --run ' \ - nix-linter -W no-AlphabeticalArgs \ - -W no-AlphabeticalBindings \ - -W BetaReduction \ - -W DIYInherit \ - -W EmptyInherit \ - -W EmptyLet \ - -W no-EmptyVariadicParamSet \ - -W FreeLetInFunc \ - -W LetInInheritRecset \ - -W no-ListLiteralConcat \ - -W NegateAtom \ - -W SequentialLet \ - -W SetLiteralUpdate \ - -W UnfortunateArgName \ - -W no-UnneededAntiquote \ - -W UnneededRec \ - -W UnusedArg \ - -W UnusedLetBind \ - -W UpdateEmptySet \ - -v shell.nix \ - ' + nix-build scripts/nix-logic.nix | TMPDIR=../tmp xargs sh -c continue-on-error: true - - name: Check shell.nix for vulnerabilities - id: vulnix + - name: "QMK: format" + id: qmk-format working-directory: ./repo run: | - nix-shell -p vulnix --run 'vulnix -f shell.nix' + nix-build scripts/qmk-format.nix | xargs sh -c continue-on-error: true - - name: Validate shell.nix logic - id: validate - working-directory: . + - name: "QMK: lint" + id: qmk-lint + working-directory: ./repo run: | - ( - mkdir -p ./tmp ; - cp ./repo/shell.nix ./tmp/shell.nix ; - sed -i -E 's|\bKEYBOARD\b\s*=\s*".+?"\s*;|KEYBOARD = "ergodox_ez";|' ./tmp/shell.nix ; - cd ./tmp ; - MANPAGER=cat nix-shell --run help ; - nix-shell --pure --run init ; - # nix-shell --pure --run setup ; # No root access, but not needed since we won't be flashing - nix-shell --pure --run format ; - nix-shell --pure --run lint ; - nix-shell --pure --run compile ; - # nix-shell --pure --run flash ; # Can't flash since there is no keyboard attached - nix-shell --pure --run clean ; - ) + nix-build scripts/qmk-lint.nix | xargs sh -c continue-on-error: true - name: Check for failures if: | - steps.shellcheck.outcome != 'success' || - steps.qmk-format.outcome != 'success' || - steps.qmk-lint.outcome != 'success' || - steps.nixpkgs-fmt.outcome != 'success' || - steps.nix-linter.outcome != 'success' || - steps.vulnix.outcome != 'success' || - steps.validate.outcome != 'success' + steps.nix-format.outcome != 'success' || + steps.nix-lint.outcome != 'success' || + steps.nix-shellcheck.outcome != 'success' || + steps.nix-vulnerabilities.outcome != 'success' || + steps.nix-logic.outcome != 'success' || + steps.qmk-format.outcome != 'success' || + steps.qmk-lint.outcome != 'success' run: exit 1 - name: Push to cache working-directory: ./repo run: | - nix-shell --pure shell.nix --run : - nix-store -qR --include-outputs $(nix-instantiate shell.nix 2>/dev/null) | cachix push kip93 + nix-build scripts/nix-cache.nix | xargs -I{} sh -c '{}' kip93 diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index fd87e52..c2ce322 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -99,6 +99,4 @@ jobs: - name: Push to cache run: | - nix-shell --pure shell.nix --run : - nix-shell --pure QMK/shell.nix --run : - nix-store -qR --include-outputs $(nix-instantiate shell.nix QMK/shell.nix 2>/dev/null) | cachix push kip93 + nix-build scripts/nix-cache.nix | xargs -I{} sh -c '{}' kip93 diff --git a/.github/workflows/update.yml b/.github/workflows/update.yml index a618e97..f746173 100644 --- a/.github/workflows/update.yml +++ b/.github/workflows/update.yml @@ -55,5 +55,4 @@ jobs: - name: Push to cache run: | - nix-shell --pure QMK/shell.nix --run : - nix-store -qR --include-outputs $(nix-instantiate QMK/shell.nix 2>/dev/null) | cachix push kip93 + nix-build scripts/nix-cache.nix | xargs -I{} sh -c '{}' kip93 diff --git a/.gitignore b/.gitignore index c92e01d..6f48e5d 100644 --- a/.gitignore +++ b/.gitignore @@ -1,5 +1,7 @@ /**/*[~#] /**/.* +/**/result +/**/result-* !/**/.github !/**/.gitignore !/**/.vscode diff --git a/.vscode/README.md b/.vscode/README.md new file mode 100644 index 0000000..e12fd87 --- /dev/null +++ b/.vscode/README.md @@ -0,0 +1,7 @@ +# VSCodium settings + +[Settings](./settings.json) for +[VSCodium](https://vscodium.com/) / +[VSCode](https://code.visualstudio.com/) / +[Code OSS](https://github.com/Microsoft/vscode) +and [suggested extensions](./extensions.json). diff --git a/.vscode/extensions.json b/.vscode/extensions.json index 44d50e2..b1dcc69 100644 --- a/.vscode/extensions.json +++ b/.vscode/extensions.json @@ -1,6 +1,7 @@ { // Suggested extensions "recommendations": [ // General + "aaron-bond.better-comments", "medo64.render-crlf", "tumido.cron-explained", @@ -16,6 +17,12 @@ "bbenoist.Nix", "jnoortheen.nix-ide", + // Shell + "timonwong.shellcheck", + + // SVG + "jock.svg", + // YAML "redhat.vscode-yaml", ] diff --git a/.vscode/ltex.dictionary.en-GB.txt b/.vscode/ltex.dictionary.en-GB.txt index a6ac5c1..77d204d 100644 --- a/.vscode/ltex.dictionary.en-GB.txt +++ b/.vscode/ltex.dictionary.en-GB.txt @@ -11,3 +11,5 @@ nixos nixpkgs ortholinear QMK +VSCode +VSCodium diff --git a/.vscode/settings.json b/.vscode/settings.json index 882347f..984e952 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -1,9 +1,31 @@ { + // General + "better-comments.multilineComments": true, + "better-comments.tags": [ + { + "tag": "TODO", + "color": "#DF4C9D", + "strikethrough": false, + "underline": false, + "backgroundColor": "transparent", + "bold": true, + "italic": false, + }, + ], + "code-eol.decorateBeforeEol": false, "code-eol.highlightExtraWhitespace": true, "code-eol.highlightNonDefault": true, "cron-explained.codeLens.enabled": true, + "cron-explained.codeLens.showCommentAction": false, + "cron-explained.codeLens.showTranscript": true, + "cron-explained.cronstrueOptions.dayOfWeekStartIndexZero": true, + "cron-explained.cronstrueOptions.monthStartIndexZero": false, + "cron-explained.cronstrueOptions.use24HourTimeFormat": true, + "cron-explained.cronstrueOptions.verbose": false, + "cron-explained.hover.enabled": false, "diffEditor.ignoreTrimWhitespace": false, "editor.insertSpaces": true, + "editor.renderWhitespace": "all", "files.associations": { "*.c": "c", "*.cpp": "cpp", @@ -11,16 +33,39 @@ "*.hpp": "cpp", "*.inc": "c", }, + "files.exclude": { + "**/.DS_Store": false, + "**/Thumbs.db": false, + }, "files.insertFinalNewline": true, "files.trimFinalNewlines": true, "files.trimTrailingWhitespace": true, - "json.maxItemsComputed": 999999, + "search.exclude": { + ".build": true, + "QMK": true, + }, + + // Git + "git.allowForcePush": false, + "git.allowNoVerifyCommit": false, + "git.autofetch": true, + "git.autofetchPeriod": 120, + "git.autoStash": true, + "git.enabled": true, + "git.enableSmartCommit": false, + "git.inputValidationLength": 72, + "git.inputValidationSubjectLength": 50, + "git.pruneOnFetch": true, + "git.pullTags": true, + "git.requireGitUserConfig": true, + "git.suggestSmartCommit": false, + + // MarkDown "ltex.additionalRules.enablePickyRules": true, "ltex.additionalRules.motherTongue": "en-GB", + "ltex.checkFrequency": "edit", "ltex.completionEnabled": true, - "ltex.enabled": [ - "markdown", - ], + "ltex.enabled": ["markdown"], "ltex.language": "en-GB", "ltex.statusBarItem": true, "markyMarkdown.statsAlignment": "Right", @@ -30,4 +75,30 @@ "markyMarkdown.statsShowLines": true, "markyMarkdown.statsShowWords": true, "markyMarkdown.statsWordsPerMinute": 150, + + // Nix + "nix.enableLanguageServer": true, + "nixEnvSelector.suggestion": true, + "nixEnvSelector.nixFile": "${workspaceFolder}/env.nix", + + // Shell + "shellcheck.enable": true, + "shellcheck.enableQuickFix": true, + "shellcheck.run": "onType", + "shellcheck.useWorkspaceRootAsCwd": true, + + // SVG + "svg.completion.showAdvanced": true, + "svg.pathDataHighlight": true, + "svg.preview.background": "dark-transparent", + "svg.preview.mode": "img", + + // YAML + "yaml.completion": true, + "yaml.format.bracketSpacing": true, + "yaml.format.printWidth": 120, + "yaml.format.proseWrap": "preserve", + "yaml.format.singleQuote": false, + "yaml.validate": true, + "yaml.yamlVersion": "1.2", } diff --git a/README.md b/README.md index 6bcb377..c997e36 100644 --- a/README.md +++ b/README.md @@ -39,7 +39,7 @@ First, you'll need to acquire the base components for the build. The board schem bought mine from [Keyhive](https://keyhive.xyz/corne) in a nice kit containing most of the basics. To that I had to add in the MCUs, a TRRS cable, 42 key switches and keycaps, and a USB-A to USB-C cable. -Once you have everything you just have to put it all together. It is intuitive enough, but there is also a +Once you have everything, you just have to put it all together. It is intuitive enough, but there is also a [handy-dandy build guide](https://github.com/foostan/crkbd/blob/master/corne-cherry/doc/v3/buildguide_en.md) that you can follow if needed. diff --git a/env.nix b/env.nix new file mode 100644 index 0000000..aa926e3 --- /dev/null +++ b/env.nix @@ -0,0 +1,11 @@ +{ pkgs ? import { }, ... }: +pkgs.mkShell { + nativeBuildInputs = with pkgs; [ + cacert + git + nix + nix-linter + nixpkgs-fmt + openssh + ]; +} diff --git a/scripts/README.md b/scripts/README.md new file mode 100644 index 0000000..dbcdf81 --- /dev/null +++ b/scripts/README.md @@ -0,0 +1,3 @@ +# Scripts + +A collection of scripts that handle and manipulate the code. Mostly intended for use on the CI. diff --git a/scripts/nix-cache.nix b/scripts/nix-cache.nix new file mode 100644 index 0000000..35a7633 --- /dev/null +++ b/scripts/nix-cache.nix @@ -0,0 +1,15 @@ +{ pkgs ? import { } }: +with pkgs; writeScript "nix-cache" '' + #!${bash}/bin/bash + set -eu + # shellcheck disable=SC2016 + ${findutils}/bin/find '${toString ../.}' -type f -name '*.nix' -a \( -not -path '${toString ../QMK}/*' -o -path '${toString ../QMK}/shell.nix' \) | + ${findutils}/bin/xargs -I{} sh -c ' + set -eu + if [ "$(${nix}/bin/nix-instantiate --eval -E "builtins.hasAttr \"shellHook\" ((import { }).callPackage \"{}\" { })")" == "true" ] ; then + ${nix}/bin/nix-build "{}" --no-out-link -A inputDerivation + else + ${nix}/bin/nix-build "{}" --no-out-link + fi + ' | ${cachix}/bin/cachix push "''${1}" +'' diff --git a/scripts/nix-format.nix b/scripts/nix-format.nix new file mode 100644 index 0000000..88ee70f --- /dev/null +++ b/scripts/nix-format.nix @@ -0,0 +1,7 @@ +{ pkgs ? import { } }: +with pkgs; writeScript "nix-format" '' + #!${bash}/bin/bash + set -eu + ${findutils}/bin/find '${toString ../.}' -type f -name '*.nix' -not -path '${toString ../QMK}/*' | + ${findutils}/bin/xargs ${nixpkgs-fmt}/bin/nixpkgs-fmt --check +'' diff --git a/scripts/nix-lint.nix b/scripts/nix-lint.nix new file mode 100644 index 0000000..9afe454 --- /dev/null +++ b/scripts/nix-lint.nix @@ -0,0 +1,27 @@ +{ pkgs ? import { } }: +with pkgs; writeScript "nix-lint" '' + #!${bash}/bin/bash + set -eu + ${findutils}/bin/find '${toString ../.}' -type f -name '*.nix' -not -path '${toString ../QMK}/*' | + ${findutils}/bin/xargs ${nix-linter}/bin/nix-linter \ + -W no-AlphabeticalArgs \ + -W no-AlphabeticalBindings \ + -W BetaReduction \ + -W DIYInherit \ + -W EmptyInherit \ + -W EmptyLet \ + -W no-EmptyVariadicParamSet \ + -W FreeLetInFunc \ + -W LetInInheritRecset \ + -W no-ListLiteralConcat \ + -W NegateAtom \ + -W SequentialLet \ + -W SetLiteralUpdate \ + -W UnfortunateArgName \ + -W no-UnneededAntiquote \ + -W UnneededRec \ + -W UnusedArg \ + -W UnusedLetBind \ + -W UpdateEmptySet \ + -q +'' diff --git a/scripts/nix-logic.nix b/scripts/nix-logic.nix new file mode 100644 index 0000000..b7a660c --- /dev/null +++ b/scripts/nix-logic.nix @@ -0,0 +1,89 @@ +{ pkgs ? import { } }: # TODO Uncomment some stuff +with pkgs; writeScript "nix-logic" '' + #!${bash}/bin/bash + set -eu + ${coreutils}/bin/printf '# \033[3mStart\033[0m ########################################################################\n' >&2 + WORKDIR="$(${coreutils}/bin/mktemp -d)" + export WORKDIR + OUTPUT="$(${coreutils}/bin/mktemp -d)" + export OUTPUT + trap 'XC=$?; ${coreutils}/bin/rm -rf -- "''${WORKDIR}" "''${OUTPUT}"; exit ''${XC}' EXIT INT QUIT TERM + ${coreutils}/bin/printf '\033[3mWorking directory : %s\033[0m\n' "''${WORKDIR}" >&2 + ${coreutils}/bin/printf '\033[3mOutputs directory : %s\033[0m\n' "''${OUTPUT}" >&2 + ${coreutils}/bin/printf '\n' >&2 + + # shellcheck disable=SC2016 + ( + cd '${toString ../QMK}' && + ${nix}/bin/nix-shell --pure --run 'qmk list-keyboards' 2>/dev/null | ${coreutils}/bin/shuf | ${findutils}/bin/xargs -P"$(${coreutils}/bin/nproc --all)" -I{} ${bash}/bin/bash -c ' + set -eu + + OUTPUT="''${OUTPUT}/$(${coreutils}/bin/printf %s "{}" | ${gnused}/bin/sed -r "s|/|_|g")" + WORKDIR="''${WORKDIR}/$(${coreutils}/bin/printf %s "{}" | ${gnused}/bin/sed -r "s|/|_|g")" + + ${coreutils}/bin/mkdir -p "''${WORKDIR}" + trap '"'"' + XC=$?; + ${coreutils}/bin/printf "\033[3;%sm%s\033[0m\n" "$([ ''${XC} -eq 0 ] && ${coreutils}/bin/printf 32 || ${coreutils}/bin/printf 31)" "{}"; + [ ''${XC} -ne 0 ] && ${coreutils}/bin/cat "''${OUTPUT}" >&2; + ${coreutils}/bin/rm -rf -- "''${WORKDIR}"; + exit ''${XC}; + '"'"' EXIT INT QUIT TERM + ${coreutils}/bin/cp '"'"'${toString ../shell.nix}'"'"' "''${WORKDIR}" + ${gnused}/bin/sed -i -E '"'"'s|\bKEYBOARD\b\s*=\s*".+?"\s*;|KEYBOARD = "{}";|'"'"' "''${WORKDIR}/shell.nix" + cd "''${WORKDIR}" + + # ${coreutils}/bin/printf \ + # "# \033[3mWelcome\033[0m ============================================================================================= #\n" \ + # >>"''${OUTPUT}" + # ${nix}/bin/nix-shell --pure --run welcome >>"''${OUTPUT}" 2>&1 + + # ${coreutils}/bin/printf \ + # "# \033[3mHelp\033[0m ================================================================================================ #\n" \ + # >>"''${OUTPUT}" + # MANPAGER=${coreutils}/bin/cat ${nix}/bin/nix-shell --run help >>"''${OUTPUT}" 2>&1 + + ${coreutils}/bin/printf \ + "# \033[3mInit\033[0m ================================================================================================ #\n" \ + >>"''${OUTPUT}" + ${nix}/bin/nix-shell --pure --run init >>"''${OUTPUT}" 2>&1 + ${coreutils}/bin/test -d "''${WORKDIR}/.git" + ${coreutils}/bin/test -d "''${WORKDIR}/QMK" + ${coreutils}/bin/test -f "''${WORKDIR}/shell.nix" + ${coreutils}/bin/test -d "''${WORKDIR}/keymap" + ${coreutils}/bin/test -f "''${WORKDIR}/keymap/keymap.c" + + ${coreutils}/bin/printf \ + "# \033[3mSetup\033[0m =============================================================================================== #\n" \ + >>"''${OUTPUT}" + ${nix}/bin/nix-shell --pure --run setup >>"''${OUTPUT}" 2>&1 # No root access, but not needed since we will not be flashing + + # ${coreutils}/bin/printf \ + # "# \033[3mFormat\033[0m ============================================================================================== #\n" \ + # >>"''${OUTPUT}" + # ${nix}/bin/nix-shell --pure --run format >>"''${OUTPUT}" 2>&1 + + # ${coreutils}/bin/printf \ + # "# \033[3mLint\033[0m ================================================================================================ #\n" \ + # >>"''${OUTPUT}" + # ${nix}/bin/nix-shell --pure --run lint >>"''${OUTPUT}" 2>&1 + + ${coreutils}/bin/printf \ + "# \033[3mCompile\033[0m ============================================================================================= #\n" \ + >>"''${OUTPUT}" + ${nix}/bin/nix-shell --pure --run compile >>"''${OUTPUT}" 2>&1 + + # ${coreutils}/bin/printf \ + # "# \033[3mFlash\033[0m =============================================================================================== #\n" \ + # >>"''${OUTPUT}" + # ${nix}/bin/nix-shell --pure --run flash >>"''${OUTPUT}" 2>&1 # Cannot flash since there is no keyboard attached + + # ${coreutils}/bin/printf \ + # "# \033[3mClean\033[0m =============================================================================================== #\n" \ + # >>"''${OUTPUT}" + # ${nix}/bin/nix-shell --pure --run clean >>"''${OUTPUT}" 2>&1 + + ${coreutils}/bin/rm -rf -- "''${OUTPUT}" + ' ; + ) +'' diff --git a/scripts/nix-shellcheck.nix b/scripts/nix-shellcheck.nix new file mode 100644 index 0000000..24a4747 --- /dev/null +++ b/scripts/nix-shellcheck.nix @@ -0,0 +1,33 @@ +{ pkgs ? import { } }: +with pkgs; writeScript "nix-shellcheck" '' + #!${bash}/bin/bash + set -eu + # shellcheck disable=SC2016 + ${findutils}/bin/find '${toString ../shell.nix}' '${toString ./.}' -type f -name '*.nix' | + ${findutils}/bin/xargs -I{} sh -c ' + set -eu + if [ "$(${nix}/bin/nix-instantiate --eval -E "builtins.hasAttr \"shellHook\" ((import { }).callPackage \"{}\" { })")" == "true" ] ; then + ${nix}/bin/nix-build "{}" --no-out-link -A inputDerivation >/dev/null + else + ${nix}/bin/nix-build "{}" --no-out-link >/dev/null + fi + ${nix}/bin/nix-instantiate --eval -E " + let + pkgs = import { }; + drv = pkgs.callPackage \"{}\" { }; + in + if (builtins.hasAttr \"shellHook\" drv) then + (\"#!${bash}/bin/bash\n\" + drv.shellHook) + else + (builtins.readFile drv) + " | \ + ${coreutils}/bin/tail -c +2 | \ + ${coreutils}/bin/head -c -2 | \ + ${findutils}/bin/xargs -0 ${coreutils}/bin/printf | \ + ${gnused}/bin/sed "s/\\\\\\$/$/g" | ( + ${shellcheck}/bin/shellcheck -C - && + ${coreutils}/bin/printf "\033[1;32m%s\033[0m\n" "{}" || + (${coreutils}/bin/printf "\033[1;31m%s\033[0m\n" "{}" ; exit 1) + ) + ' +'' diff --git a/scripts/nix-vulnerabilities.nix b/scripts/nix-vulnerabilities.nix new file mode 100644 index 0000000..a7cdc6a --- /dev/null +++ b/scripts/nix-vulnerabilities.nix @@ -0,0 +1,7 @@ +{ pkgs ? import { } }: +with pkgs; writeScript "nix-vulnerabilities" '' + #!${bash}/bin/bash + set -eu + ${findutils}/bin/find '${toString ../.}' -type f -name '*.nix' -not -path '${toString ../QMK}/*' | + ${findutils}/bin/xargs ${vulnix}/bin/vulnix -f +'' diff --git a/scripts/qmk-format.nix b/scripts/qmk-format.nix new file mode 100644 index 0000000..18b47a7 --- /dev/null +++ b/scripts/qmk-format.nix @@ -0,0 +1,8 @@ +{ pkgs ? import { } }: +with pkgs; writeScript "qmk-format" '' + #!${bash}/bin/bash + set -eu + cd '${toString ../.}' + ${nix}/bin/nix-shell --run format + ${git}/bin/git diff --exit-code --name-only +'' diff --git a/scripts/qmk-lint.nix b/scripts/qmk-lint.nix new file mode 100644 index 0000000..2bb4120 --- /dev/null +++ b/scripts/qmk-lint.nix @@ -0,0 +1,7 @@ +{ pkgs ? import { } }: +with pkgs; writeScript "qmk-lint" '' + #!${bash}/bin/bash + set -eu + cd '${toString ../.}' + ${nix}/bin/nix-shell --run lint +'' diff --git a/shell.nix b/shell.nix index 9a0e162..0bc355a 100644 --- a/shell.nix +++ b/shell.nix @@ -23,13 +23,14 @@ let # Name of the folder inside the QMK submodule # e.g., `ergodox_ez`, `0xcb/1337`, et cetera - KEYBOARD = "crkbd"; - - # Number of threads to be used when compiling. - PARALLEL = 16; + KEYBOARD = "crkbd/rev1"; in pkgs.mkShell { + ############### + # Environment # + ############### + nativeBuildInputs = with pkgs; [ cacert git @@ -37,421 +38,662 @@ pkgs.mkShell { openssh ]; + ########### + # Scripts # + ########### + shellHook = with pkgs; '' # Bash configs ################################################################# + + # History management shopt -s histappend shopt -s cmdhist - shopt -s checkwinsize - shopt -s globstar - shopt -s dotglob HISTCONTROL=ignoreboth HISTSIZE=1000 HISTFILESIZE=2000 - # Extra bling for some commands ################################################ - eval "$(SHELL='${bash_5}/bin/bash' '${lesspipe}/bin/lesspipe.sh')" - eval "$('${coreutils}/bin/dircolors' -b)" + # Keep track of window size + shopt -s checkwinsize - # Globals ###################################################################### - _ROOT_DIR='${toString ./.}' + # Globbing + shopt -s globstar + shopt -s dotglob - # Create a dynamic CLI prompt ################################################## - _compute_prompt() { - # First of all, get the exit code of the command before it is lost. - local XC=$? - local XC_colour="$( - if [ "''${XC}" -eq 0 ] ; then - '${coreutils}/bin/printf' 10 ; - elif [ "''${XC}" -lt 128 ] ; then - '${coreutils}/bin/printf' 9 ; - else - '${coreutils}/bin/printf' 11 ; - fi ; - )" - local XC_PS1="\[\033[38;5;''${XC_colour}m\]$('${coreutils}/bin/printf' '0x%02X' "''${XC}")\[\033[1m\]\[$('${ncurses}/bin/tput' sgr0)\]" + # Extra bling for some commands ################################################ - # Compute the path relative to the root of the project (or absolute path if outside of said folder). - local path="$( - '${coreutils}/bin/realpath' -m --relative-to="''${_ROOT_DIR}" "$('${coreutils}/bin/pwd')" - )/" - [[ "''${path}" =~ ^\.\..+$ ]] && path="$('${coreutils}/bin/pwd')" - [[ "''${path}" =~ ^/.+$|^\./$ ]] || path="./''${path}" - local path_PS1="\[\033[1;38;5;12m\]''${path}\[$('${ncurses}/bin/tput' sgr0)\]" + # Add colour to less + eval "$(SHELL=${bash}/bin/bash ${lesspipe}/bin/lesspipe.sh)" + + # Add colour to ls + eval "$(${coreutils}/bin/dircolors -b)" + + # Functions #################################################################### + + #------------------------------------------------------------------------------- + # Check if the system has root access. + # Currently supported methods are sudo, doas, or su. + # + # Return: + # 0 if the root user is accessible, 1 otherwise. + #------------------------------------------------------------------------------- + _can_root() { + if [ "$(${which}/bin/which doas sudo su 2>/dev/null | ${coreutils}/bin/wc -l)" -gt 0 ] ; then + return 0 + else + return 1 + fi + } - # Check the branch of the repo and its status. - local is_git="$( - '${git}/bin/git' -C "''${_ROOT_DIR}" rev-parse --git-dir >/dev/null 2>&1 && - [ "$('${git}/bin/git' -C "''${_ROOT_DIR}" rev-parse --show-toplevel)" -ef "''${_ROOT_DIR}" ] && - '${coreutils}/bin/printf' true ; - )" - local git_status="$( - [ ! -z "''${is_git}" ] && - '${git}/bin/git' -C "''${_ROOT_DIR}" status --porcelain ; - )" - local ref="$( - if [ ! -z "''${is_git}" ] ; then - '${git}/bin/git' -C "''${_ROOT_DIR}" rev-parse --abbrev-ref HEAD 2>/dev/null || true ; + #------------------------------------------------------------------------------- + # Clean the QMK submodule. + #------------------------------------------------------------------------------- + _clean_qmk() { + ${git}/bin/git -C '${toString ./QMK}' clean -df + } + + #------------------------------------------------------------------------------- + # Get the ref of a git repo, or if no status is available. + # + # Args: + # $1 - The repo whose ref is fetched. + # + # Output: + # The git ref. + #------------------------------------------------------------------------------- + _git_ref() { + local ref + ref="$( + if _is_git "''${1}" ; then + ${git}/bin/git -C "''${1}" rev-parse --abbrev-ref HEAD 2>/dev/null || true ; else - '${coreutils}/bin/printf' '' ; + ${coreutils}/bin/printf '' ; fi ; )" + [ "''${ref}" = "HEAD" ] && ref="$( - '${git}/bin/git' -C "''${_ROOT_DIR}" rev-parse --short HEAD 2>/dev/null || - '${git}/bin/git' -C "''${_ROOT_DIR}" branch --show-current ; + ${git}/bin/git -C "''${1}" rev-parse --short HEAD 2>/dev/null || + ${git}/bin/git -C "''${1}" branch --show-current ; )" - local ref_colour="$( - if [ -z "''${is_git}" ] ; then - '${coreutils}/bin/printf' 9 ; + + ${coreutils}/bin/printf '%s\n' "''${ref}" + } + + #------------------------------------------------------------------------------- + # Get the status of a git repo. + # + # Args: + # $1 - The repo whose status is checked. + # + # Output: + # The status of the repo, in a parseable format. + #------------------------------------------------------------------------------- + _git_status() { + _is_git "''${1}" && ${git}/bin/git -C "''${1}" status --porcelain + } + + #------------------------------------------------------------------------------- + # Check if a directory is a git repo. + # + # Args: + # $1 - The path to be checked. + # + # Return: + # 0 if it is a git repo, non-zero otherwise. + #------------------------------------------------------------------------------- + _is_git() { + ${git}/bin/git -C "''${1}" rev-parse --git-dir >/dev/null 2>&1 && + [ "$(${git}/bin/git -C "''${1}" rev-parse --show-toplevel)" -ef "''${1}" ] + } + + #------------------------------------------------------------------------------- + # Get the keymap of an otherwise clean QMK submodule. + # + # Output: + # The full path to the keymap. + #------------------------------------------------------------------------------- + _keymap_path() { + printf '${toString ./QMK}/' + _git_status '${toString ./QMK}' | + ${coreutils}/bin/cut -d' ' -f2 + } + + #------------------------------------------------------------------------------- + # Create a symlink of the keymap. + # + # Args: + # $1 - The name of the keymap to be created. + #------------------------------------------------------------------------------- + _link_keymap() { + _qmk_exec "new-keymap -kb '${KEYBOARD}' -km ''\'''${1}'" >/dev/null 2>&1 + _keymap_path | + ${coreutils}/bin/head -c -2 | + ${findutils}/bin/xargs -I{} ${bash}/bin/bash -c " + ${coreutils}/bin/rm -rf -- '{}' && + ${coreutils}/bin/ln -sf -- '${toString ./keymap}' '{}' ; + " ; + } + + #------------------------------------------------------------------------------- + # Print a header text of fixed width. + # + # Args: + # $1 - The text of the header. + # + # Output: + # An 80 char wide header. + #------------------------------------------------------------------------------- + _print_header() { + ${coreutils}/bin/printf \ + '# ---------------------------------------------------------------------------- #\r# \033[3m%s\033[0m \n' \ + "''${1}" + } + + #------------------------------------------------------------------------------- + # Run a command as root. + # Currently supported methods are sudo, doas, or su. + # + # Args: + # $1 - The command to execute. + #------------------------------------------------------------------------------- + _root_exec() { + if ${which}/bin/which doas >/dev/null 2>&1 ; then + doas ${bash}/bin/bash -c "''${1}" + elif ${which}/bin/which sudo >/dev/null 2>&1 ; then + sudo ${bash}/bin/bash -c "''${1}" + elif ${which}/bin/which su >/dev/null 2>&1 ; then + su -c "''${1}" + fi + } + + #------------------------------------------------------------------------------- + # Execute a QMK command. + # + # Args: + # $1 - The QMK command and its arguments. + #------------------------------------------------------------------------------- + _qmk_exec() { + ( + cd '${toString ./QMK}' && + ${nix}/bin/nix-shell --pure --run "qmk --color ''${1}" ; + ) + } + + #------------------------------------------------------------------------------- + # Create a random UUID. + # + # Output: + # An UUID. + #------------------------------------------------------------------------------- + _uuid() { + ${coreutils}/bin/cat /proc/sys/kernel/random/uuid + } + + # Create a dynamic CLI prompt ################################################## + + #------------------------------------------------------------------------------- + # Create the git status part of the PS1. + # + # Output: + # A coloured git ref, or if no status is git repo is found. + #------------------------------------------------------------------------------- + _compute_git_prompt() { + # Get the repo status + local git_status + git_status="$(_git_status '${toString ./.}')" + + # Get the ref, or + local ref + ref="$(_git_ref '${toString ./.}')" + + # Assign a colour to the "cleaniness" of the repo + local colour + colour="$( + if _is_git '${toString ./.}' ; then + # No repo -> red + ${coreutils}/bin/printf 9 ; elif [ \ "$( - '${coreutils}/bin/printf' '%s\n' "''${git_status}" | - '${gnused}/bin/sed' '/^\s*$/d' | - '${coreutils}/bin/wc' -l ; + ${coreutils}/bin/printf '%s\n' "''${git_status}" | + ${gnused}/bin/sed '/^\s*$/d' | + ${coreutils}/bin/wc -l ; )" -eq 0 \ ] ; then - '${coreutils}/bin/printf' 10 ; + # Clean repo -> green + ${coreutils}/bin/printf 10 ; elif - '${coreutils}/bin/printf' '%s\n' "''${git_status}" | - '${gnugrep}/bin/grep' -q '^.\S' ; then - '${coreutils}/bin/printf' 9 ; + # Unstaged changes -> red + ${coreutils}/bin/printf '%s\n' "''${git_status}" | + ${gnugrep}/bin/grep -q '^.\S' ; then + ${coreutils}/bin/printf 9 ; + else + # Staged changes -> yellow + ${coreutils}/bin/printf 11 ; + fi ; + )" + + # Output + ${coreutils}/bin/printf "\[\033[1;38;5;%sm\]%s\[$(${ncurses}/bin/tput sgr0)\]" "''${colour}" "''${ref}" + } + + #------------------------------------------------------------------------------- + # Create the path part of the PS1. + # + # Output: + # A coloured path string, relative to the root of the project (or absolute + # path if outside of said folder). + #------------------------------------------------------------------------------- + _compute_path_prompt() { + # Get the current relative path + local path + path="$( + ${coreutils}/bin/realpath -m --relative-to='${toString ./.}' "$(${coreutils}/bin/pwd)" + )/" + + # If the path is outside of the root dir, use absoule path instead + [[ "''${path}" =~ ^\.\..+$ ]] && path="$(${coreutils}/bin/pwd)" + + # Make relative paths more readable + [[ "''${path}" =~ ^/.+$|^\./$ ]] || path="./''${path}" + + # Output + ${coreutils}/bin/printf "\[\033[1;38;5;12m\]%s\[$(${ncurses}/bin/tput sgr0)\]" "''${path}" + } + + #------------------------------------------------------------------------------- + # Create the exit code part of the PS1. + # + # Args: + # $1 - Exit code. + # + # Output: + # A coloured HEX exit code. + #------------------------------------------------------------------------------- + _compute_xc_prompt() { + # Assign colour depending on exit code value + local colour + colour="$( + if [ "''${1}" -eq 0 ] ; then + # Success -> green + ${coreutils}/bin/printf 10 ; + elif [ "''${1}" -lt 128 ] ; then + # Error -> red + ${coreutils}/bin/printf 9 ; else - '${coreutils}/bin/printf' 11 ; + # Signal -> yellow + ${coreutils}/bin/printf 11 ; fi ; )" - local ref_PS1="\[\033[1;38;5;''${ref_colour}m\]$ref\[$('${ncurses}/bin/tput' sgr0)\]" - # Nix shell hint. - local nix_PS1='\[\033[1;38;5;13m\]NIX+QMK\[$('${ncurses}/bin/tput' sgr0)\]' + # Output + ${coreutils}/bin/printf "\[\033[38;5;%sm\]0x%02X\[\033[1m\]\[$(${ncurses}/bin/tput sgr0)\]" "''${colour}" "''${1}" + } + + #------------------------------------------------------------------------------- + # Create a dynamic PS1. + #------------------------------------------------------------------------------- + _compute_prompt() { + # First of all, get the exit code of the command before it is lost. + local XC=$? + + # Compute the different parts of the PS1 + local nix_PS1 + # shellcheck disable=SC2016 + nix_PS1='\[\033[1;38;5;13m\]NIX+QMK\[$(${ncurses}/bin/tput sgr0)\]' + local git_PS1 + git_PS1="$(_compute_git_prompt)" + local path_PS1 + path_PS1="$(_compute_path_prompt)" + local XC_PS1 + XC_PS1="$(_compute_xc_prompt "''${XC}")" - # Colour CLI prompt. - PS1="\[$('${ncurses}/bin/tput' sgr0)\][ ''${nix_PS1} @ ''${ref_PS1} : ''${path_PS1} ] ''${XC_PS1} > \[$('${ncurses}/bin/tput' sgr0)\]" + # CLI prompt. + PS1="\[$(${ncurses}/bin/tput sgr0)\][ ''${nix_PS1} @ ''${git_PS1} : ''${path_PS1} ] ''${XC_PS1} > \[$(${ncurses}/bin/tput sgr0)\]" return "''${XC}" # Restore the original exit code } + PROMPT_COMMAND=_compute_prompt # Aliases ###################################################################### - alias ls="'${coreutils}/bin/ls' --color=auto" - alias ll="'${coreutils}/bin/ls' --color=auto -lAh" + + # ls + alias ls="${coreutils}/bin/ls --color=auto" + alias ll="${coreutils}/bin/ls --color=auto -lAh" # Commands ##################################################################### + + #------------------------------------------------------------------------------- + # Initialise the current working directory. + #------------------------------------------------------------------------------- init() { local XC=0 - ( - '${git}/bin/git' -C "''${_ROOT_DIR}" rev-parse --git-dir >/dev/null 2>&1 && \ - [ "$('${git}/bin/git' -C "''${_ROOT_DIR}" rev-parse --show-toplevel)" -ef "''${_ROOT_DIR}" ] ; - ) || ( - '${coreutils}/bin/printf' \ - '# \033[3mInitialise repo\033[0m ------------------------------------------------------------------------------------- #\n' ; + local KEYMAP_ID + KEYMAP_ID="$(_uuid)" + + if ! _is_git '${toString ./.}' ; then + _print_header 'Initialise repo' ( - '${git}/bin/git' -C "''${_ROOT_DIR}" init -b main - ) || XC="$(( "''${XC}" + 0x01 ))" ; - '${coreutils}/bin/printf' '\n' ; - ) + ${git}/bin/git -C '${toString ./.}' init -b main ; + ) || XC="$(( "''${XC}" + 0x01 ))" + ${coreutils}/bin/printf '\n' + fi - [ -d "''${_ROOT_DIR}/QMK/" ] && ( - '${coreutils}/bin/printf' \ - '# \033[3mClean up submodule\033[0m ---------------------------------------------------------------------------------- #\n' ; + if [ -d '${toString ./QMK}' ] ; then + _print_header 'Clean up submodule' ( - '${coreutils}/bin/rm' -rf -- "''${_ROOT_DIR}/QMK/" && - '${coreutils}/bin/printf' "Submodule path 'QMK': deleted\n" ; - ) || XC="$(( "''${XC}" + 0x02 ))" ; - '${coreutils}/bin/printf' '\n' ; - ) + _clean_qmk ; + ) || XC="$(( "''${XC}" + 0x02 ))" + ${coreutils}/bin/printf '\n' + fi - ( - '${git}/bin/git' -C "''${_ROOT_DIR}" config --file .gitmodules --get-regexp path | - '${gawk}/bin/awk' '{ print $2 }' | - '${gnugrep}/bin/grep' -q '^QMK$' ; - ) || ( - '${coreutils}/bin/printf' \ - '# \033[3mAdd QMK submodule\033[0m ----------------------------------------------------------------------------------- #\n' ; + if ! ( + ${git}/bin/git -C '${toString ./.}' config --file .gitmodules --get-regexp path | + ${gawk}/bin/awk '{ print $2 }' | + ${gnugrep}/bin/grep -q '^QMK$' ; + ) ; then + _print_header 'Add submodule' ( - '${git}/bin/git' -C "''${_ROOT_DIR}" submodule add --branch master -- 'https://github.com/qmk/qmk_firmware/' QMK ; - ) || XC="$(( "''${XC}" + 0x04 ))" ; - '${coreutils}/bin/printf' '\n' ; - ) + ${git}/bin/git -C '${toString ./.}' submodule add --branch master -- \ + 'https://github.com/qmk/qmk_firmware/' QMK ; + ) || XC="$(( "''${XC}" + 0x04 ))" + ${coreutils}/bin/printf '\n' + fi if [ "''${XC}" -eq 0 ] ; then - '${coreutils}/bin/printf' \ - '# \033[3mInit submodule\033[0m -------------------------------------------------------------------------------------- #\n' ; + _print_header 'Init submodule' ( - '${git}/bin/git' -C "''${_ROOT_DIR}" submodule update --init --recursive --progress ; - ) || XC="$(( "''${XC}" + 0x08 ))" ; - '${coreutils}/bin/printf' '\n' ; + ${git}/bin/git -C '${toString ./.}' submodule update --init --recursive --progress ; + ) || XC="$(( "''${XC}" + 0x08 ))" + ${coreutils}/bin/printf '\n' fi - '${coreutils}/bin/printf' \ - '# \033[3mClean up workspace\033[0m ---------------------------------------------------------------------------------- #\n' ; + _print_header 'Clean up workspace' ( - '${coreutils}/bin/rm' -rf -- "''${_ROOT_DIR}/keymap/" ; - ) || XC="$(( "''${XC}" + 0x10 ))" ; - '${coreutils}/bin/printf' '\n' ; + ${coreutils}/bin/rm -rf -- '${toString ./keymap}' ; + ) || XC="$(( "''${XC}" + 0x10 ))" + ${coreutils}/bin/printf '\n' - '${coreutils}/bin/printf' \ - '# \033[3mCopy default keymap\033[0m --------------------------------------------------------------------------------- #\n' ; + _print_header 'Init workspace' ( - '${coreutils}/bin/cp' -rf -- "''${_ROOT_DIR}/QMK/keyboards/${KEYBOARD}/keymaps/default" "''${_ROOT_DIR}/keymap" ; - ) || XC="$(( "''${XC}" + 0x20 ))" ; - '${coreutils}/bin/printf' '\n' ; + _qmk_exec "new-keymap -kb '${KEYBOARD}' -km ''\'''${KEYMAP_ID}'" && + _keymap_path | + ${findutils}/bin/xargs -I{} ${bash}/bin/bash -c " + ${coreutils}/bin/rm -rf -- '${toString ./keymap}' && + ${coreutils}/bin/cp -rf -- '{}' '${toString ./keymap}' ; + " ; + ) || XC="$(( "''${XC}" + 0x20 ))" + ${coreutils}/bin/printf '\n' + + _print_header 'Clean up submodule' + ( + _clean_qmk ; + ) || XC="$(( "''${XC}" + 0x40 ))" + ${coreutils}/bin/printf '\n' return "''${XC}" } + #------------------------------------------------------------------------------- + # Set up the current machine to ensure other commands work as expected. + # May require a reboot. + #------------------------------------------------------------------------------- setup() { local XC=0 - '${coreutils}/bin/printf' \ - '# \033[3mSet up udev rules\033[0m ----------------------------------------------------------------------------------- #\n' ; + if ! _can_root ; then + ${coreutils}/bin/printf '\033[33mWARNING: No root access, skipping setup.\033[0m\n' + return 0 + fi + + _print_header 'Set up udev rules' ( - '${coreutils}/bin/printf' 'Set up /etc/udev/rules.d/\n' && - $( - (${which}/bin/which doas >/dev/null 2>/dev/null && ${coreutils}/bin/printf 'doas bash') || - (${which}/bin/which sudo >/dev/null 2>/dev/null && ${coreutils}/bin/printf 'sudo bash') || - (${coreutils}/bin/printf 'su') - ) -c " - '${coreutils}/bin/mkdir' -p '/etc/udev/rules.d/' && - '${coreutils}/bin/cp' -rf \"''${_ROOT_DIR}/QMK/util/udev/\"* '/etc/udev/rules.d/' - " && - '${coreutils}/bin/printf' '/etc/udev/rules.d/ set up successfully\n' ; - ) || XC="$(( "''${XC}" + 0x01 ))" ; - '${coreutils}/bin/printf' '\n' ; - - '${coreutils}/bin/printf' \ - '# \033[3mResize /run/user/$UID\033[0m ------------------------------------------------------------------------------- #\n' ; + _root_exec " + ${coreutils}/bin/mkdir -p '/etc/udev/rules.d/' && + ${coreutils}/bin/cp -rf '${toString ./QMK/util/udev}/'* '/etc/udev/rules.d/' ; + " && ${coreutils}/bin/printf '/etc/udev/rules.d/ set up successfully\n' ; + ) || XC="$(( "''${XC}" + 0x01 ))" + ${coreutils}/bin/printf '\n' + + # shellcheck disable=SC2016 + _print_header 'Resize /run/user/$UID' + # shellcheck disable=SC2016 ( - '${coreutils}/bin/printf' 'Set up /etc/udev/rules.d/\n' && - $( - (${which}/bin/which doas >/dev/null 2>/dev/null && ${coreutils}/bin/printf 'doas sh') || - (${which}/bin/which sudo >/dev/null 2>/dev/null && ${coreutils}/bin/printf 'sudo sh') || - (${coreutils}/bin/printf 'su') - ) -c " - '${coreutils}/bin/mkdir' -p '/etc/systemd/logind.conf.d/' && - '${coreutils}/bin/printf' '[Login]\nRuntimeDirectorySize=99%%\n' >'/etc/systemd/logind.conf.d/runtime_directory_size.conf' - " && - '${coreutils}/bin/printf' '/run/user/$UID resized successfully\n' ; - ) || XC="$(( "''${XC}" + 0x02 ))" ; - '${coreutils}/bin/printf' '\n' ; + _root_exec " + ${coreutils}/bin/mkdir -p '/etc/systemd/logind.conf.d/' && + ${coreutils}/bin/printf '[Login]\nRuntimeDirectorySize=99%%\n' >'/etc/systemd/logind.conf.d/runtime_directory_size.conf' + " && ${coreutils}/bin/printf '/run/user/$UID resized successfully\n' ; + ) || XC="$(( "''${XC}" + 0x02 ))" + ${coreutils}/bin/printf '\n' if [ "''${XC}" -eq 0 ] ; then - '${coreutils}/bin/printf' \ - '# \033[3mFinish\033[0m ---------------------------------------------------------------------------------------------- #\n' ; - '${coreutils}/bin/printf' '\033[3mSet up complete.\nPlease reboot your system to ensure that changes take effect.\033[0m\n\n' + _print_header 'Finish' + ${coreutils}/bin/printf '\033[3mSet up complete.\nPlease reboot your system to ensure that changes take effect.\033[0m\n\n' fi return "''${XC}" } + #------------------------------------------------------------------------------- + # Update the QMK submodule. + #------------------------------------------------------------------------------- update() { local XC=0 - '${coreutils}/bin/printf' \ - '# \033[3mUpdate submodules\033[0m ----------------------------------------------------------------------------------- #\n' ; + _print_header 'Update submodule' ( - '${git}/bin/git' -C "''${_ROOT_DIR}" submodule update --remote --progress ; - ) || XC="$(( "''${XC}" + 0x01 ))" ; - '${coreutils}/bin/printf' '\n' ; + ${git}/bin/git -C '${toString ./.}' submodule update --remote --progress -- '${toString ./QMK}' ; + ) || XC="$(( "''${XC}" + 0x01 ))" + ${coreutils}/bin/printf '\n' return "''${XC}" } + #------------------------------------------------------------------------------- + # Clean up the working directory. + #------------------------------------------------------------------------------- clean() { local XC=0 - '${coreutils}/bin/printf' \ - '# \033[3mClean workspace\033[0m ------------------------------------------------------------------------------------- #\n' ; + _print_header 'Clean up submodule' ( - '${git}/bin/git' -C "''${_ROOT_DIR}/QMK" clean -df && - '${git}/bin/git' -C "''${_ROOT_DIR}" clean -dfX ; - ) || XC="$(( "''${XC}" + 0x01 ))" ; - '${coreutils}/bin/printf' '\n' ; + _clean_qmk ; + ) || XC="$(( "''${XC}" + 0x01 ))" + ${coreutils}/bin/printf '\n' + + _print_header 'Clean up repo' + ( + ${git}/bin/git -C '${toString ./.}' clean -dfX ; + ) || XC="$(( "''${XC}" + 0x02 ))" + ${coreutils}/bin/printf '\n' return "''${XC}" } + #------------------------------------------------------------------------------- + # Lint the source code. + #------------------------------------------------------------------------------- lint() { local XC=0 - local KEYMAP_ID="$('${coreutils}/bin/cat' /proc/sys/kernel/random/uuid)" + local KEYMAP_ID + KEYMAP_ID="$(_uuid)" - '${coreutils}/bin/printf' \ - '# \033[3mLink keymap\033[0m ----------------------------------------------------------------------------------------- #\n' ; + _print_header 'Clean up submodule' ( - '${coreutils}/bin/rm' -f -- "''${_ROOT_DIR}"/'QMK/keyboards/${KEYBOARD}/keymaps'/"''${KEYMAP_ID}" && - '${coreutils}/bin/ln' -sf "''${_ROOT_DIR}/keymap" "''${_ROOT_DIR}"/'QMK/keyboards/${KEYBOARD}/keymaps'/"''${KEYMAP_ID}" && - '${coreutils}/bin/printf' 'Linked QMK/keyboards/${KEYBOARD}/keymaps/%s\n' "''${KEYMAP_ID}" ; - ) || XC="$(( "''${XC}" + 0x01 ))" ; - '${coreutils}/bin/printf' '\n' ; + _clean_qmk ; + ) || XC="$(( "''${XC}" + 0x01 ))" + ${coreutils}/bin/printf '\n' + + _print_header 'Link keymap' + ( + _link_keymap "''${KEYMAP_ID}" ; + ) || XC="$(( "''${XC}" + 0x02 ))" + ${coreutils}/bin/printf '\n' if [ "''${XC}" -eq 0 ] ; then - '${coreutils}/bin/printf' \ - '# \033[3mQMK linting\033[0m ----------------------------------------------------------------------------------------- #\n' ; + _print_header 'Lint code' ( - cd "''${_ROOT_DIR}/QMK" && - '${nix}/bin/nix-shell' --pure --run "qmk lint --strict -kb '${KEYBOARD}' -km ''\'''${KEYMAP_ID}'" ; - ) || XC="$(( "''${XC}" + 0x02 ))" ; - '${coreutils}/bin/printf' '\n' ; + _qmk_exec "lint --strict -kb '${KEYBOARD}' -km ''\'''${KEYMAP_ID}'" ; + ) || XC="$(( "''${XC}" + 0x04 ))" + ${coreutils}/bin/printf '\n' fi - '${coreutils}/bin/printf' \ - '# \033[3mUnlink keymap\033[0m --------------------------------------------------------------------------------------- #\n' ; + _print_header 'Unlink keymap' ( - '${git}/bin/git' -C "''${_ROOT_DIR}/QMK" clean -df ; - ) || XC="$(( "''${XC}" + 0x04 ))" ; - '${coreutils}/bin/printf' '\n' ; + _clean_qmk ; + ) || XC="$(( "''${XC}" + 0x08 ))" + ${coreutils}/bin/printf '\n' return "''${XC}" } + #------------------------------------------------------------------------------- + # Format the source code. + #------------------------------------------------------------------------------- format() { local XC=0 - local KEYMAP_ID="$('${coreutils}/bin/cat' /proc/sys/kernel/random/uuid)" + local KEYMAP_ID + KEYMAP_ID="$(_uuid)" + + _print_header 'Clean up submodule' + ( + _clean_qmk ; + ) || XC="$(( "''${XC}" + 0x01 ))" + ${coreutils}/bin/printf '\n' - '${coreutils}/bin/printf' \ - '# \033[3mLink keymap\033[0m ----------------------------------------------------------------------------------------- #\n' ; + _print_header 'Link keymap' ( - '${coreutils}/bin/rm' -f -- "''${_ROOT_DIR}"/'QMK/keyboards/${KEYBOARD}/keymaps'/"''${KEYMAP_ID}" && - '${coreutils}/bin/ln' -sf "''${_ROOT_DIR}/keymap" "''${_ROOT_DIR}"/'QMK/keyboards/${KEYBOARD}/keymaps'/"''${KEYMAP_ID}" && - '${coreutils}/bin/printf' 'Linked QMK/keyboards/${KEYBOARD}/keymaps/%s\n' "''${KEYMAP_ID}" ; - ) || XC="$(( "''${XC}" + 0x01 ))" ; - '${coreutils}/bin/printf' '\n' ; + _link_keymap "''${KEYMAP_ID}" ; + ) || XC="$(( "''${XC}" + 0x02 ))" + ${coreutils}/bin/printf '\n' if [ "''${XC}" -eq 0 ] ; then - '${coreutils}/bin/printf' \ - '# \033[3mFormat code\033[0m ----------------------------------------------------------------------------------------- #\n' ; + _print_header 'Format code' ( - cd "''${_ROOT_DIR}/QMK" && - '${nix}/bin/nix-shell' --pure --run "${clang-tools}/bin/clang-format -i --verbose \$( - ${findutils}/bin/find -L 'keyboards/${KEYBOARD}/keymaps'/"''${KEYMAP_ID}" -type f -regextype awk -regex '.+\.(h|hpp|c|cpp|inc)' - )" ; - ) || XC="$(( "''${XC}" + 0x02 ))" ; - '${coreutils}/bin/printf' '\n' ; + cd '${toString ./QMK}' && + ${nix}/bin/nix-shell --pure --run " + ${findutils}/bin/find -L '$(_keymap_path)' -type f -regextype awk -regex '.+\.(h|hpp|c|cpp|inc)' | + ${findutils}/bin/xargs ${clang-tools}/bin/clang-format -i --verbose + " ; + ) || XC="$(( "''${XC}" + 0x04 ))" + ${coreutils}/bin/printf '\n' fi - '${coreutils}/bin/printf' \ - '# \033[3mUnlink keymap\033[0m --------------------------------------------------------------------------------------- #\n' ; + _print_header 'Unlink keymap' ( - '${git}/bin/git' -C "''${_ROOT_DIR}/QMK" clean -df ; - ) || XC="$(( "''${XC}" + 0x04 ))" ; - '${coreutils}/bin/printf' '\n' ; + _clean_qmk ; + ) || XC="$(( "''${XC}" + 0x08 ))" + ${coreutils}/bin/printf '\n' return "''${XC}" } + #------------------------------------------------------------------------------- + # Compile the source code. + #------------------------------------------------------------------------------- compile() { local XC=0 - local KEYMAP_ID="$('${coreutils}/bin/cat' /proc/sys/kernel/random/uuid)" + local KEYMAP_ID + KEYMAP_ID="$(_uuid)" - '${coreutils}/bin/printf' \ - '# \033[3mClean up old builds\033[0m --------------------------------------------------------------------------------- #\n' ; + _print_header 'Clean up submodule' ( - cd "''${_ROOT_DIR}/QMK" && - '${nix}/bin/nix-shell' --pure --run 'qmk clean' && - '${coreutils}/bin/printf' 'Cleaned QMK/.build\n' ; - ) || XC="$(( "''${XC}" + 0x01 ))" ; - '${coreutils}/bin/printf' '\n' ; - - '${coreutils}/bin/printf' \ - '# \033[3mLink keymap\033[0m ----------------------------------------------------------------------------------------- #\n' ; + _clean_qmk && + _qmk_exec "clean" ; + ) || XC="$(( "''${XC}" + 0x01 ))" + ${coreutils}/bin/printf '\n' + + _print_header 'Link keymap' ( - '${coreutils}/bin/rm' -f -- "''${_ROOT_DIR}"/'QMK/keyboards/${KEYBOARD}/keymaps'/"''${KEYMAP_ID}" && - '${coreutils}/bin/ln' -sf "''${_ROOT_DIR}/keymap" "''${_ROOT_DIR}"/'QMK/keyboards/${KEYBOARD}/keymaps'/"''${KEYMAP_ID}" && - '${coreutils}/bin/printf' 'Linked QMK/keyboards/${KEYBOARD}/keymaps/%s\n' "''${KEYMAP_ID}" ; - ) || XC="$(( "''${XC}" + 0x02 ))" ; - '${coreutils}/bin/printf' '\n' ; + _link_keymap "''${KEYMAP_ID}" ; + ) || XC="$(( "''${XC}" + 0x02 ))" + ${coreutils}/bin/printf '\n' if [ "''${XC}" -eq 0 ] ; then - '${coreutils}/bin/printf' \ - '# \033[3mCompile\033[0m --------------------------------------------------------------------------------------------- #\n' ; + _print_header 'Compile code' ( - cd "''${_ROOT_DIR}/QMK" && - '${nix}/bin/nix-shell' --pure --run "qmk compile -j '${builtins.toString PARALLEL}' -kb '${KEYBOARD}' -km ''\'''${KEYMAP_ID}'" ; - ) || XC="$(( "''${XC}" + 0x04 ))" ; - '${coreutils}/bin/printf' '\n' ; + _qmk_exec "compile -j $(${coreutils}/bin/nproc --all) -kb '${KEYBOARD}' -km ''\'''${KEYMAP_ID}'" ; + ) || XC="$(( "''${XC}" + 0x04 ))" + ${coreutils}/bin/printf '\n' fi if [ "''${XC}" -eq 0 ] ; then - '${coreutils}/bin/printf' \ - '# \033[3mExtract HEX file\033[0m ------------------------------------------------------------------------------------ #\n' ; + _print_header 'Extract HEX file' ( - '${coreutils}/bin/mkdir' -p "''${_ROOT_DIR}/.build" && - '${findutils}/bin/find' "''${_ROOT_DIR}/QMK/.build" -type f -regextype awk -iregex '^.*\.(hex|bin)$' | - '${coreutils}/bin/head' -1 | - '${findutils}/bin/xargs' -i cp -f -- '{}' "''${_ROOT_DIR}/.build/firmware.hex" && - '${coreutils}/bin/printf' 'Extracted .build/firmware.hex\n' ; - ) || XC="$(( "''${XC}" + 0x08 ))" ; - '${coreutils}/bin/printf' '\n' + ${coreutils}/bin/mkdir -p '${toString ./.build}' && + ${findutils}/bin/find '${toString ./QMK/.build}' -type f -regextype awk -iregex '^.*\.(hex|bin)$' | + ${coreutils}/bin/head -1 | + ${findutils}/bin/xargs -I{} cp -f -- '{}' '${toString ./.build/firmware.hex}' && + ${coreutils}/bin/printf 'Extracted .build/firmware.hex\n' ; + ) || XC="$(( "''${XC}" + 0x08 ))" + ${coreutils}/bin/printf '\n' fi - '${coreutils}/bin/printf' \ - '# \033[3mUnlink keymap\033[0m --------------------------------------------------------------------------------------- #\n' ; + _print_header 'Unlink keymap' ( - '${git}/bin/git' -C "''${_ROOT_DIR}/QMK" clean -df ; - ) || XC="$(( "''${XC}" + 0x10 ))" ; - '${coreutils}/bin/printf' '\n' ; + _clean_qmk ; + ) || XC="$(( "''${XC}" + 0x10 ))" + ${coreutils}/bin/printf '\n' return "''${XC}" } + #------------------------------------------------------------------------------- + # Flash a keyboard. + #------------------------------------------------------------------------------- flash() { local XC=0 - local KEYMAP_ID="$('${coreutils}/bin/cat' /proc/sys/kernel/random/uuid)" + local KEYMAP_ID + KEYMAP_ID="$(_uuid)" - '${coreutils}/bin/printf' \ - '# \033[3mClean up old builds\033[0m --------------------------------------------------------------------------------- #\n' ; + _print_header 'Clean up submodule' ( - cd "''${_ROOT_DIR}/QMK" && - '${nix}/bin/nix-shell' --pure --run 'qmk clean' && - '${coreutils}/bin/printf' 'Cleaned QMK/.build\n' ; - ) || XC="$(( "''${XC}" + 0x01 ))" ; - '${coreutils}/bin/printf' '\n' ; - - '${coreutils}/bin/printf' \ - '# \033[3mLink keymap\033[0m ----------------------------------------------------------------------------------------- #\n' ; + _clean_qmk && + _qmk_exec "clean" ; + ) || XC="$(( "''${XC}" + 0x01 ))" + ${coreutils}/bin/printf '\n' + + _print_header 'Link keymap' ( - '${coreutils}/bin/rm' -f -- "''${_ROOT_DIR}"/'QMK/keyboards/${KEYBOARD}/keymaps'/"''${KEYMAP_ID}" && - '${coreutils}/bin/ln' -sf "''${_ROOT_DIR}/keymap" "''${_ROOT_DIR}"/'QMK/keyboards/${KEYBOARD}/keymaps'/"''${KEYMAP_ID}" && - '${coreutils}/bin/printf' 'Linked QMK/keyboards/${KEYBOARD}/keymaps/%s\n' "''${KEYMAP_ID}" ; - ) || XC="$(( "''${XC}" + 0x02 ))" ; - '${coreutils}/bin/printf' '\n' ; + _link_keymap "''${KEYMAP_ID}" ; + ) || XC="$(( "''${XC}" + 0x02 ))" + ${coreutils}/bin/printf '\n' if [ "''${XC}" -eq 0 ] ; then - '${coreutils}/bin/printf' \ - '# \033[3mCompile\033[0m --------------------------------------------------------------------------------------------- #\n' ; + _print_header 'Compile code' ( - cd "''${_ROOT_DIR}/QMK" && - '${nix}/bin/nix-shell' --pure --run "qmk compile -j '${builtins.toString PARALLEL}' -kb '${KEYBOARD}' -km ''\'''${KEYMAP_ID}'" ; - ) || XC="$(( "''${XC}" + 0x04 ))" ; - '${coreutils}/bin/printf' '\n' ; + _qmk_exec "compile -j $(${coreutils}/bin/nproc --all) -kb '${KEYBOARD}' -km ''\'''${KEYMAP_ID}'" ; + ) || XC="$(( "''${XC}" + 0x04 ))" + ${coreutils}/bin/printf '\n' fi if [ "''${XC}" -eq 0 ] ; then - '${coreutils}/bin/printf' \ - '# \033[3mFlash\033[0m ----------------------------------------------------------------------------------------------- #\n' ; + _print_header 'Flash keyboard' ( - cd "''${_ROOT_DIR}/QMK" && - '${nix}/bin/nix-shell' --pure --run "qmk flash -j '${builtins.toString PARALLEL}' -kb '${KEYBOARD}' -km ''\'''${KEYMAP_ID}'" ; - ) || XC="$(( "''${XC}" + 0x08 ))" ; - '${coreutils}/bin/printf' '\n' ; + _qmk_exec "flash -kb '${KEYBOARD}' -km ''\'''${KEYMAP_ID}'" ; + ) || XC="$(( "''${XC}" + 0x08 ))" + ${coreutils}/bin/printf '\n' fi - '${coreutils}/bin/printf' \ - '# \033[3mUnlink keymap\033[0m --------------------------------------------------------------------------------------- #\n' ; + _print_header 'Unlink keymap' ( - '${git}/bin/git' -C "''${_ROOT_DIR}/QMK" clean -df ; - ) || XC="$(( "''${XC}" + 0x10 ))" ; - '${coreutils}/bin/printf' '\n' ; + _clean_qmk ; + ) || XC="$(( "''${XC}" + 0x10 ))" + ${coreutils}/bin/printf '\n' return "''${XC}" } + #------------------------------------------------------------------------------- + # Show a man-like help page. + #------------------------------------------------------------------------------- help() { - '${coreutils}/bin/cat' </dev/null + ${coreutils}/bin/cat </dev/null .TH "NIX+QMK" "1" "" "" "Nix+QMK toolbox" .\----------------------------------------------------------------------------\. .SH NAME @@ -581,19 +823,23 @@ pkgs.mkShell { return 0 } + #------------------------------------------------------------------------------- + # Show welcome screen. + #------------------------------------------------------------------------------- welcome() { - '${coreutils}/bin/printf' '\033[0m , , , , , ,\n' - '${coreutils}/bin/printf' '\033[0m \033[1;30m.-------------.\033[0m\n' - '${coreutils}/bin/printf' '\033[0m - \033[1;30m| | \033[0m- \033[3mWelcome to this (unofficial) \033[1mNix+QMK toolbox\033[0;3m.\033[0m\n' - '${coreutils}/bin/printf' '\033[0m - \033[1;30m| \033[0;1m| | |\033[0;1;30m | \033[0m-\n' - '${coreutils}/bin/printf' '\033[0m - \033[1;30m| \033[0;1m| | |\033[0;1;30m | \033[0m- \033[3mAn opinionated set of scripts for standalone QMK keymaps\033[0m\n' - '${coreutils}/bin/printf' '\033[0m - \033[1;30m| \033[0;1m|__|__|\033[0;1;30m | \033[0m-\n' - '${coreutils}/bin/printf' '\033[0m - \033[1;30m| \033[0;1m|\033[0;1;30m | \033[0m-\n' - '${coreutils}/bin/printf' '\033[0m - \033[1;30m|_____________| \033[0m-\n' - '${coreutils}/bin/printf' '\033[0m , , , , , ,\n' - '${coreutils}/bin/printf' '\n' - '${coreutils}/bin/printf' '\033[0m\033[3mType `help` to get info on available commands.\033[0m\n' - '${coreutils}/bin/printf' '\n' + ${coreutils}/bin/printf '\033[0m , , , , , ,\n' + ${coreutils}/bin/printf '\033[0m \033[1;30m.-------------.\033[0m\n' + ${coreutils}/bin/printf '\033[0m - \033[1;30m| | \033[0m- \033[3mWelcome to this (unofficial) \033[1mNix+QMK toolbox\033[0;3m.\033[0m\n' + ${coreutils}/bin/printf '\033[0m - \033[1;30m| \033[0;1m| | |\033[0;1;30m | \033[0m-\n' + ${coreutils}/bin/printf '\033[0m - \033[1;30m| \033[0;1m| | |\033[0;1;30m | \033[0m- \033[3mAn opinionated set of scripts for standalone QMK keymaps\033[0m\n' + ${coreutils}/bin/printf '\033[0m - \033[1;30m| \033[0;1m|__|__|\033[0;1;30m | \033[0m-\n' + ${coreutils}/bin/printf '\033[0m - \033[1;30m| \033[0;1m|\033[0;1;30m | \033[0m-\n' + ${coreutils}/bin/printf '\033[0m - \033[1;30m|_____________| \033[0m-\n' + ${coreutils}/bin/printf '\033[0m , , , , , ,\n' + ${coreutils}/bin/printf '\n' + # shellcheck disable=SC2016 + ${coreutils}/bin/printf '\033[0m\033[3mType `help` to get info on available commands.\033[0m\n' + ${coreutils}/bin/printf '\n' return 0 }