From bf34d2071ff1f660156cd9cb2c79988d6f0afb3b Mon Sep 17 00:00:00 2001 From: Timothy DeHerrera Date: Sat, 13 Feb 2021 19:38:20 -0700 Subject: [PATCH 1/4] doc: new mdbook documentation --- .github/workflows/mdbook_docs.yml | 26 +++++++ .gitignore | 1 + CONTRIBUTING.md | 18 ----- DOC.md | 105 -------------------------- SUMMARY.md | 19 +++++ book.toml | 9 +++ cachix/README.md | 12 +++ doc/.gitignore | 1 + doc/flk/index.md | 1 + doc/introduction.md | 33 ++++++++ doc/layout.md | 4 + doc/start/from-nixos.md | 47 ++++++++++++ doc/start/index.md | 38 ++++++++++ doc/start/iso.md | 11 +++ extern/README.md | 10 +++ extern/default.nix | 2 +- flake.lock | 6 +- flake.nix | 8 +- hosts/README.md | 43 +++++++++++ hosts/default.nix | 13 ++-- lib/default.nix | 8 +- modules/README.md | 79 +++++++++++++++++++ modules/{list.nix => module-list.nix} | 0 overlays/.gitkeep | 0 overlays/README.md | 25 ++++++ overrides/README.md | 46 +++++++++++ {unstable => overrides}/default.nix | 7 +- pkgs/README.md | 59 +++++++++++++++ profiles/README.md | 48 ++++++++++++ secrets/.gitattributes | 1 + secrets/README.md | 18 +++++ shell/default.nix | 1 - suites/README.md | 24 ++++++ users/README.md | 51 +++++++++++++ 34 files changed, 627 insertions(+), 147 deletions(-) create mode 100644 .github/workflows/mdbook_docs.yml delete mode 100644 CONTRIBUTING.md delete mode 100644 DOC.md create mode 100644 SUMMARY.md create mode 100644 book.toml create mode 100644 cachix/README.md create mode 100644 doc/.gitignore create mode 100644 doc/flk/index.md create mode 100644 doc/introduction.md create mode 100644 doc/layout.md create mode 100644 doc/start/from-nixos.md create mode 100644 doc/start/index.md create mode 100644 doc/start/iso.md create mode 100644 extern/README.md create mode 100644 hosts/README.md create mode 100644 modules/README.md rename modules/{list.nix => module-list.nix} (100%) delete mode 100644 overlays/.gitkeep create mode 100644 overlays/README.md create mode 100644 overrides/README.md rename {unstable => overrides}/default.nix (73%) create mode 100644 pkgs/README.md create mode 100644 profiles/README.md create mode 100644 secrets/README.md create mode 100644 suites/README.md create mode 100644 users/README.md diff --git a/.github/workflows/mdbook_docs.yml b/.github/workflows/mdbook_docs.yml new file mode 100644 index 00000000..775d52c8 --- /dev/null +++ b/.github/workflows/mdbook_docs.yml @@ -0,0 +1,26 @@ +name: Deploy Docs to GitHub Pages + +on: + push: + branches: + - doc + +jobs: + deploy: + runs-on: ubuntu-18.04 + steps: + - uses: actions/checkout@v2 + + - name: Setup mdBook + uses: peaceiris/actions-mdbook@v1 + with: + mdbook-version: 'latest' + + - run: mdbook build + + - name: Deploy + uses: peaceiris/actions-gh-pages@v3 + with: + github_token: ${{ secrets.GITHUB_TOKEN }} + publish_branch: gh-pages + publish_dir: ./book diff --git a/.gitignore b/.gitignore index 4e131a1a..509d8695 100644 --- a/.gitignore +++ b/.gitignore @@ -2,3 +2,4 @@ result up hosts/up-* .direnv +book diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md deleted file mode 100644 index a7fc9ebb..00000000 --- a/CONTRIBUTING.md +++ /dev/null @@ -1,18 +0,0 @@ -# Pull Requests - -While much of your work in this template may be idiosyncratic in nature. Anything -that might be generally useful to the broader NixOS community can be synced to -the `template` branch to provide a host of useful NixOS configurations available -"out of the box". If you wish to contribute such an expression please follow -these guidelines: - -* format your code with [`nixpkgs-fmt`][nixpkgs-fmt]. The default devshell - includes a pre-commit hook that does this for you. - -* The commit message follows the same semantics as [nixpkgs][nixpkgs]. - * You can use a `#` symbol to specify ambiguities. For example, - `develop#zsh: ` would tell me that your updating the - `zsh` subprofile living under the `develop` profile. - -[nixpkgs-fmt]: https://github.com/nix-community/nixpkgs-fmt -[nixpkgs]: https://github.com/NixOS/nixpkgs diff --git a/DOC.md b/DOC.md deleted file mode 100644 index e5c0a7aa..00000000 --- a/DOC.md +++ /dev/null @@ -1,105 +0,0 @@ -## Hosts -Module declarations dependant on particular machines should be stored in the -[hosts](hosts) directory. Every file in this directory will be added automatically -to the the `nixosConfigurations` flake output and thus becomes deployable via -`nixos-rebuild` and `flk`. - -See [`hosts/default.nix`](hosts/default.nix) for the implementation. - -## Profiles -A profile is any directory under [profiles](profiles) containing a `default.nix` -defining a function that returns a valid NixOS module, with the added restriction -that no new declarations to the `options` _or_ `config` attributes are allowed -(use [modules](modules) instead). Their purpose is to provide abstract -expressions suitable for reuse by multiple deployments. They are perhaps _the_ -key mechanism by which we keep this repo maintainable. - -Profiles can have subprofiles which are themselves just profiles that live under -another. There's no hard rule that everything in the folder must be imported by -its `default.nix`, so you can also store relevant code that is useful but not -wanted by default in, say, an `alt.nix`. Importantly, every subdirectory in a -profile should be independent of its parent. i.e: - -```nix -{ - # importing `profile` without implicitly importing `some` - imports = [ ./profiles/some/profile ]; -} -``` - -It is okay for profiles to depend on other profiles so long as they are -explicitly loaded via `imports`. - -## Suites - -[Suites](./suites/default.nix) are simple collections of profiles that can be -directly imported from any host like so: -``` -{ suites, ... }: -{ - imports = suites.mySuite; -} -``` - -You can declare any combination of users and profiles that you wish, providing -a nice abstraction, free from the idiosyncratic concerns of specific hardware. - -## Users -User declarations belong in the `users` directory. - -These are actually just a special case of [profiles](#profiles) attached to -a particular interactive user. Its primarily for declarations to -`users.users.` where `.isNormalUser` is true. - -This is a convenient place to import your profiles such that a particular user -always has a reliable stack. Also [user profiles](./users/profiles) are -available to create reusable configs across different users. - -For convenience, [home-manager][home-manager] is available automatically for -home directory setup and should only be used from this directory. - -## Secrets -Anything you wish to keep encrypted goes in the `secrets` directory, which is -created on first entering a `nix-shell`. - -Be sure to run `git crypt init`, before committing anything to this directory. -Be sure to check out git-crypt's [documentation](https://github.com/AGWA/git-crypt) -if your not familiar. The filter is already set up to encrypt everything in this -folder by default. - -To keep [profiles](profiles) reusable across configurations, secrets should -only be imported from the `users` or [`hosts`](hosts) directory. - -## Cachix -When using: -``` -cachix use -``` -A file with be created in `/etc/nixos/cachix/your-cachix.nix`. Simply add this -file to git, and it will be exported so others can use your binary cache -directly from this flake via `nixosModules.cachix.`. - - -## Modules, Packages and Overlays -All expressions in both [modules/list.nix](modules/list.nix) and -[pkgs/default.nix](pkgs/default.nix) are available globally, anywhere else in the -repo. They are additionally included in the `nixosModules` and `overlay` flake -outputs, respectively. Packages are automatically included in the `packages` -output as well. - -The directory structure is identical to nixpkgs to provide a kind of staging area -for any modules or packages we might be wanting to merge there later. If your not -familiar or can't be bothered, simply dropping a valid nix file and pointing the -`default.nix` to it, is all that's really required. - -As for overlays, they should be defined in the [overlays](overlays) directory. -They will be automatically pulled in for use by all configurations. Nix command -line tools will be able to read overlays from here as well since it is set as -`nixpkgs-overlays` in `NIX_PATH`. And of course they will be exported via the -flake output `overlays` as well. - -If you wish to use an overlay from an external flake, simply add it to the -`externOverlays` list in the `let` block of the `outputs` attribute in -[flake.nix](flake.nix). Same for external modules, add them to `externModules`. - -[home-manager]: https://github.com/nix-community/home-manager diff --git a/SUMMARY.md b/SUMMARY.md new file mode 100644 index 00000000..1b95eb5d --- /dev/null +++ b/SUMMARY.md @@ -0,0 +1,19 @@ +# Summary + +- [Introduction](./doc/introduction.md) +- [Quick Start](./doc/start/index.md) + - [ISO](./doc/start/iso.md) + - [From NixOS](./doc/start/from-nixos.md) +- [Layout](./doc/layout.md) + - [Cachix](./cachix/README.md) + - [Extern](./extern/README.md) + - [Hosts](./hosts/README.md) + - [Modules](./modules/README.md) + - [Overlays](./overlays/README.md) + - [Overrides](./overrides/README.md) + - [Packages](./pkgs/README.md) + - [Profiles](./profiles/README.md) + - [Secrets](./secrets/README.md) + - [Suites](./suites/README.md) + - [Users](./users/README.md) +- [flk command](./doc/flk/index.md) diff --git a/book.toml b/book.toml new file mode 100644 index 00000000..e843940c --- /dev/null +++ b/book.toml @@ -0,0 +1,9 @@ +[book] +authors = ["Timothy DeHerrera"] +language = "en" +multilingual = false +src = "." +title = "nixflk docs" + +[output.html] +site-url = "/nixflk/" diff --git a/cachix/README.md b/cachix/README.md new file mode 100644 index 00000000..de732dc7 --- /dev/null +++ b/cachix/README.md @@ -0,0 +1,12 @@ +# Cachix +The cachix directory simple captures the output of `sudo cachix use` for the +developers personal cache, as well as the nix-community cache. You can easily +add your own cache, assuming the template lives in /etc/nixos, by simply +running `sudo cachix use yourcache`. + +These caches are only added to the system after a `nixos-rebuild switch`, so it +is recommended to call `cachix use nrdxp` before the initial deployment, as it +will save a lot of build time. + +In the future, users will be able to skip this step once the ability to define +the nix.conf within the flake is fully fleshed out upstream. diff --git a/doc/.gitignore b/doc/.gitignore new file mode 100644 index 00000000..7585238e --- /dev/null +++ b/doc/.gitignore @@ -0,0 +1 @@ +book diff --git a/doc/flk/index.md b/doc/flk/index.md new file mode 100644 index 00000000..6a441957 --- /dev/null +++ b/doc/flk/index.md @@ -0,0 +1 @@ +# flk command diff --git a/doc/introduction.md b/doc/introduction.md new file mode 100644 index 00000000..9f7b2bd5 --- /dev/null +++ b/doc/introduction.md @@ -0,0 +1,33 @@ +# Introduction +Nixflk is a template which grants a simple way to use, deploy and manage +[NixOS][nixos] systems for personal and productive use. It does this by +providing a sane repository structure, integrating several popular projects +like [home-manager][home-manager], setting clear guidelines, offering useful +conveniences, and eliminating boilerplate so you can focus on deploying your +systems. + +## Community Profiles +There are two branches from which to choose: [core][core] and +[community][community]. The community branch builds on core and includes +several ready-made profiles for discretionary use. + +Every package and NixOS profile declared in community is uploaded to +[cachix](../cachix), so everything provided is available without building +anything. This is especially useful for the packages that are +[overridden](../overrides) from master, as without the cache, rebuilds are +quite frequent. + +### ⚠ Advisory +Nixflk leverages the [flakes][flakes] feature available via an _experimental_ +branch of [nix][nix]. Until nix 3.0 is released, this project should be +considered unstable. + +# License +Nixflk is licensed under the [MIT License](https://mit-license.org). + +[nix]: https://nixos.org/manual/nix/stable +[nixos]: https://nixos.org/manual/nixos/stable +[home-manager]: https://nix-community.github.io/home-manager +[flakes]: https://nixos.wiki/wiki/Flakes +[core]: https://github.com/nrdxp/nixflk +[community]: https://github.com/nrdxp/nixflk/tree/community diff --git a/doc/layout.md b/doc/layout.md new file mode 100644 index 00000000..18831188 --- /dev/null +++ b/doc/layout.md @@ -0,0 +1,4 @@ +# Layout +Each of the following sections is a directory in the root of the project +serving a singular purpose. Select a chapter to read more about its purpose +and usage. diff --git a/doc/start/from-nixos.md b/doc/start/from-nixos.md new file mode 100644 index 00000000..7c37cdc4 --- /dev/null +++ b/doc/start/from-nixos.md @@ -0,0 +1,47 @@ +# From NixOS + +## Generate Configuration +Assuming your happy with your existing partition layout, you can generate a +basic NixOS configuration for your system using: +```sh +flk up +``` + +This will make a new file `hosts/up-$(hostname).nix`, which you can edit to +your liking. + +Make sure your `i18n.defaultLocale` and `time.timeZone` are set properly for +your region. Keep in mind that `networking.hostName` with be automatically +set to the filename of your hosts file, so `hosts/my-host.nix` will have the +hostname `my-host`. + +Now might be a good time to read the docs on [suites](../../suites) and +[profiles](../../profiles) and add or create any that you need. + +> ##### _Note:_ +> While the `up` sub-command is provided as a convenience to quickly set up and +> install a "fresh" NixOS system on current hardware, committing these files is +> discouraged. +> +> They are placed in the git staging area automatically because they would be +> invisible to the flake otherwise, but it is best to move what you need from +> them directly into a host module of your own making, and commit that instead. +# Installation + +Once your ready to deploy `hosts/my-host.nix`: +```sh +flk my-host switch +``` + + +This calls `nixos-rebuild` with sudo to build and install your configuration. + +> ##### _Notes:_ +> - Instead of `switch`, you can pass `build`, `test`, `boot`, etc just as with +> `nixos-rebuild`. +> +> - It is convenient to have the template living at `/etc/nixos` so you can +> simply `sudo nixos-rebuild switch` from anywhere on the system, but it is +> not required. + + diff --git a/doc/start/index.md b/doc/start/index.md new file mode 100644 index 00000000..d74f726b --- /dev/null +++ b/doc/start/index.md @@ -0,0 +1,38 @@ +# Quick Start +The only dependency is nix, so make sure you have it [installed][install-nix]. + +## Get the Template +Here is a snippet that will get you the template without the git history: +```sh +nix-shell https://github.com/nrdxp/nixflk/archive/core.tar.gz -A shell \ + --run "flk get core" + +cd flk + +nix-shell + +git init +git add . +git commit -m init + +cachix use nrdxp +``` + +This will place you in a new folder named `flk` with git initialized, and a +nix-shell that provides all the dependencies, including the unstable nix +version required. + +In addition, the [binary cache](../../cachix) is added for faster deployment. + +> ##### _Notes:_ +> - You can change `core` to [`community`](../introduction.md#community-profiles) +> in the call to `flk get` +> - Flakes ignore files that have not been added to git, so be sure to stage new +> files before building the system. + +## Next Steps: +- [Make installable ISO](./iso.md) +- [Already on NixOS](./from-nixos.md) + + +[install-nix]: https://nixos.org/manual/nix/stable/#sect-multi-user-installation diff --git a/doc/start/iso.md b/doc/start/iso.md new file mode 100644 index 00000000..aa089474 --- /dev/null +++ b/doc/start/iso.md @@ -0,0 +1,11 @@ +# ISO + +Making and writing an installable iso for `hosts/NixOS.nix` is as simple as: +```sh +flk iso NixOS + +dd bs=4M if=result/iso/*.iso of=/dev/$your_installation_device \ + status=progress oflag=sync +``` + +This works for any file matching `hosts/*.nix` excluding `default.nix`. diff --git a/extern/README.md b/extern/README.md new file mode 100644 index 00000000..58f20e23 --- /dev/null +++ b/extern/README.md @@ -0,0 +1,10 @@ +# External Art +When you need to use a module, overlay, or pass a value from one of your inputs +to the rest of your NixOS configuration, [extern][extern] is where you do it. + +Modules and overlays are self explanatory, and the `specialArgs` attribute is +used to extend the arguments passed to all NixOS modules, allowing for +arbitrary values to be passed from flake inputs to the rest of your +configuration. + +[extern]: https://github.com/nrdxp/nixflk/tree/core/extern/default.nix diff --git a/extern/default.nix b/extern/default.nix index 14c3ca80..30cd1897 100644 --- a/extern/default.nix +++ b/extern/default.nix @@ -12,7 +12,7 @@ # passed to all nixos modules specialArgs = { - unstableModulesPath = "${master}/nixos/modules"; + overrideModulesPath = "${override}/nixos/modules"; hardware = nixos-hardware.nixosModules; }; } diff --git a/flake.lock b/flake.lock index d4ada6fe..6fa234f6 100644 --- a/flake.lock +++ b/flake.lock @@ -7,7 +7,7 @@ "nixos" ], "nixos-unstable": [ - "master" + "override" ], "pre-commit-hooks-nix": "pre-commit-hooks-nix" }, @@ -93,7 +93,7 @@ "type": "github" } }, - "master": { + "override": { "locked": { "lastModified": 1612717294, "narHash": "sha256-V3j1rA4a3Lzf5pdbFHzs9jUcOKB91MFO3X8nMY+lK5c=", @@ -174,7 +174,7 @@ "devshell": "devshell", "flake-utils": "flake-utils", "home": "home", - "master": "master", + "override": "override", "nixos": "nixos", "nixos-hardware": "nixos-hardware", "nur": "nur" diff --git a/flake.nix b/flake.nix index e077d377..4a0a5357 100644 --- a/flake.nix +++ b/flake.nix @@ -3,9 +3,7 @@ inputs = { - # Once desired, bump master's locked revision: - # nix flake update --update-input master - master.url = "nixpkgs/master"; + override.url = "nixpkgs/master"; nixos.url = "nixpkgs/release-20.09"; home.url = "github:nix-community/home-manager/release-20.09"; home.inputs.nixpkgs.follows = "nixos"; @@ -14,7 +12,7 @@ nixos-hardware.url = "github:nixos/nixos-hardware"; ci-agent.url = "github:hercules-ci/hercules-ci-agent"; ci-agent.inputs.nixos-20_09.follows = "nixos"; - ci-agent.inputs.nixos-unstable.follows = "master"; + ci-agent.inputs.nixos-unstable.follows = "override"; }; outputs = @@ -22,7 +20,7 @@ , ci-agent , home , nixos - , master + , override , flake-utils , nur , devshell diff --git a/hosts/README.md b/hosts/README.md new file mode 100644 index 00000000..a8f4c9db --- /dev/null +++ b/hosts/README.md @@ -0,0 +1,43 @@ +# Hosts + +Nix flakes contain an output called `nixosConfigurations` declaring an +attribute set of valid NixOS systems. To simplify the management and creation +of these hosts, nixflk automatically imports every _.nix_ file inside this +directory to the mentioned attribute set, applying the projects defaults to +each. The only hard requirement is that the file contain a valid NixOS module. + +As an example, a file `hosts/system.nix` will be available via the flake +output `nixosConfigurations.system`. You can have as many hosts as you want +and all of them will be automatically imported based on their name. + +For each host, the configuration automatically sets the `networking.hostName` +attribute to the name of the file minus the _.nix_ extension. This is for +convenience, since `nixos-rebuild` automatically searches for a configuration +matching the current systems hostname if one is not specified explicitly. + +It is recommended that the host modules only contain configuration information +specific to a particular piece of hardware. Anything reusable across machines +is best saved for [profile modules](../profiles). + +This is a good place to import sets of profiles, called [suites](../suites), +that you intend to use on your machine. + +Additionally, this is the perfect place to import anything you might need from +the [nixos-hardware][nixos-hardware] repository. + +## Example + +`hosts/librem.nix`: +```nix +{ suites, hardware, ... }: +{ + imports = suites.laptop ++ [ hardware.purism-librem-13v3 ]; + + boot.loader.systemd-boot.enable = true; + boot.loader.efi.canTouchEfiVariables = true; + + fileSystems."/" = { device = "/dev/disk/by-label/nixos"; }; +} +``` + +[nixos-hardware]: https://github.com/NixOS/nixos-hardware diff --git a/hosts/default.nix b/hosts/default.nix index 525ef7e2..b5e31a63 100644 --- a/hosts/default.nix +++ b/hosts/default.nix @@ -1,6 +1,6 @@ { lib , nixos -, master +, override , nixos-hardware , pkgs , self @@ -24,15 +24,15 @@ let let core = import ../profiles/core; - modOverrides = { config, unstableModulesPath, ... }: + modOverrides = { config, overrideModulesPath, ... }: let - unstable = import ../unstable; - inherit (unstable) modules disabledModules; + overrides = import ../overrides; + inherit (overrides) modules disabledModules; in { disabledModules = modules ++ disabledModules; imports = map - (path: "${unstableModulesPath}/${path}") + (path: "${overrideModulesPath}/${path}") modules; }; @@ -44,7 +44,7 @@ let networking.hostName = hostName; nix.nixPath = [ - "nixos-unstable=${master}" + "nixos-unstable=${override}" "nixos=${nixos}" "nixpkgs=${nixos}" ]; @@ -52,7 +52,6 @@ let nixpkgs = { inherit pkgs; }; nix.registry = { - master.flake = master; nixflk.flake = self; nixpkgs.flake = nixos; }; diff --git a/lib/default.nix b/lib/default.nix index 857433dd..cde0042e 100644 --- a/lib/default.nix +++ b/lib/default.nix @@ -83,11 +83,11 @@ in (system: let extern = import ../extern { inherit inputs; }; - unstable = pkgImport inputs.master [ ] system; - overrides = (import ../unstable).packages; + overridePkgs = pkgImport inputs.override [ ] system; + overridesOverlay = (import ../overrides).packages; overlays = [ - (overrides unstable) + (overridesOverlay overridePkgs) self.overlay (final: prev: { lib = (prev.lib or { }) // { @@ -173,7 +173,7 @@ in cachixAttrs = { inherit cachix; }; # modules - moduleList = import ../modules/list.nix; + moduleList = import ../modules/module-list.nix; modulesAttrs = pathsToImportedAttrs moduleList; in diff --git a/modules/README.md b/modules/README.md new file mode 100644 index 00000000..5da01cc9 --- /dev/null +++ b/modules/README.md @@ -0,0 +1,79 @@ +# Modules +The modules directory is a replica of nixpkg's NixOS [modules][nixpkgs-modules] +, and follows the same semantics. This allows for trivial upstreaming into +nixpkgs proper once your module is sufficiently stable. + +All modules linked in _module-list.nix_ are automatically exported via +`nixosModules.`, and imported into all [hosts](../hosts). + + +> ##### _Note:_ +> This is reserved for declaring brand new module options. If you just want to +> declare a coherent configuration of already existing and related NixOS options +> , use [profiles](../profiles) instead. + +## Semantics +In case you've never written a module for nixpkgs before, here is a brief +outline of the process. + +### Declaration +modules/services/service-category/my-service.nix: +```nix +{ config, lib, ... }: +let + cfg = config.services.myService; +in +{ + options.services.myService = { + enable = lib.mkEnableOption "Description of my new service."; + + # additional options ... + }; + + config = lib.mkIf cfg.enable { + # implementation ... + }; +} +``` + +### Import +modules/module-list.nix: +```nix +[ + ./services/service-category/my-service.nix +] +``` + +## Usage + +### Internal +profiles/profile-category/my-profile.nix: +```nix +{ ... }: +{ + services.MyService.enable = true; +} +``` + +### External +flake.nix: +```nix +{ + # inputs omitted + + outputs = { self, nixflk, nixpkgs, ... }: { + nixosConfigurations.myConfig = nixpkgs.lib.nixosSystem { + system = "..."; + + modules = [ + nixflk.nixosModules.my-service + ({ ... }: { + services.MyService.enable = true; + }) + ]; + }; + }; +} +``` + +[nixpkgs-modules]: https://github.com/NixOS/nixpkgs/tree/master/nixos/modules diff --git a/modules/list.nix b/modules/module-list.nix similarity index 100% rename from modules/list.nix rename to modules/module-list.nix diff --git a/overlays/.gitkeep b/overlays/.gitkeep deleted file mode 100644 index e69de29b..00000000 diff --git a/overlays/README.md b/overlays/README.md new file mode 100644 index 00000000..7d8ecdb4 --- /dev/null +++ b/overlays/README.md @@ -0,0 +1,25 @@ +# Overlays +Writing overlays is a common occurence when using a NixOS system. Therefore, +we want to keep the process as simple and straightforward as possible. + +Any _.nix_ files declared in this directory will be assumed to be a valid +overlay, and will be automatically imported into all [hosts](../hosts), and +exported via `overlays.` _as well as_ +`packages..` (for valid systems), so all you have to do is +write it. + +## Example +overlays/kakoune.nix: +```nix +final: prev: { + kakoune = prev.kakoune.override { + configure.plugins = with final.kakounePlugins; [ + (kak-fzf.override { fzf = final.skim; }) + kak-auto-pairs + kak-buffers + kak-powerline + kak-vertical-selection + ]; + }; +} +``` diff --git a/overrides/README.md b/overrides/README.md new file mode 100644 index 00000000..ad0670b5 --- /dev/null +++ b/overrides/README.md @@ -0,0 +1,46 @@ +# Overrides +By default, the NixOS systems are based on the latest release. While it is +trivial to change this to nixos-unstable or any other branch of nixpkgs by +changing the flake url, sometimes all we want is a single package from another +branch. + +This is what the overrides are for. By default, they are pulled directly from +nixpkgs/master, but you can change the `override` flake input url to +nixos-unstable, or even a specific sha revision. + + +## Example + +### Packages +The override packages are defined as a regular overlay with an extra arguement +`pkgs`. This refers to the packages built from the `override` flake. + +Pulling the manix package from the override flake: +```nix +{ + packages = pkgs: final: prev: { + inherit (pkgs) manix; + }; +} +``` + +### Modules + +You can also pull modules from override. Simply specify their path relative to +the nixpkgs [modules][nixpkgs-modules] directory. The old version will be added +to `disabledModules` and the new version imported into the configuration. + +Pulling the zsh module from the override flake: +```nix +{ + modules = [ "programs/zsh/zsh.nix" ]; +} +``` + +> ##### _Note:_ +> Sometimes a modules name will change from one branch to another. This is what +> the `disabledModules` list is for. If the module name changes, the old +> version will not automatically be disabled, so simply put it's old name in +> this list to disable it. + +[nixpkgs-modules]: https://github.com/NixOS/nixpkgs/tree/master/nixos/modules diff --git a/unstable/default.nix b/overrides/default.nix similarity index 73% rename from unstable/default.nix rename to overrides/default.nix index ae7858d0..c2432977 100644 --- a/unstable/default.nix +++ b/overrides/default.nix @@ -1,11 +1,12 @@ +# override defaults to nixpkgs/master { - # modules to pull from master, stable version is automatically disabled + # modules to pull from override, stable version is automatically disabled modules = [ ]; - # if a modules name changed in master, add the old name here + # if a modules name changed in override, add the old name here disabledModules = [ ]; - # packages pulled from master + # packages pulled from override packages = pkgs: final: prev: { inherit (pkgs) dhall diff --git a/pkgs/README.md b/pkgs/README.md new file mode 100644 index 00000000..e84c236f --- /dev/null +++ b/pkgs/README.md @@ -0,0 +1,59 @@ +# Packages +Similar to [modules](../modules), the pkgs directory mirrors the upstream +[nixpkgs/pkgs][pkgs], and for the same reason; if you ever want to upstream +your package, it's as simple as dropping it into the nixpkgs/pkgs directory. + +The only minor difference is that, instead of adding the `callPackage` call to +`all-packages.nix`, you just add it the the _default.nix_ in this directory, +which is defined as a simple overlay. + +This overlay is set as the default `overlay` output attribute for the flake. +And all the packages are exported via `packages..`, for all +the supported systems listed in the package's `meta.platforms` attribute. + +And, as usual, every package in the overlay is also available to any NixOS +[host](../hosts). + +## Example +pkgs/development/libraries/libinih/default.nix: +```nix +{ stdenv, meson, ninja, fetchFromGitHub, ... }: +let version = "r50"; +in +stdenv.mkDerivation { + pname = "libinih"; + inherit version; + + src = fetchFromGitHub { + owner = "benhoyt"; + repo = "inih"; + rev = "${version}"; + hash = "sha256-GF+TVEysaXJxSBBjMsTr2IQvRKlzdEu3rlPQ88PE3nI="; + }; + + buildInputs = [ meson ninja ]; + + mesonFlags = '' + -Ddefault_library=shared + -Ddistro_install=true + ''; + + meta = with stdenv.lib; { + description = "Simple .INI file parser in C"; + homepage = "https://github.com/benhoyt/inih"; + maintainers = [ maintainers.nrdxp ]; + license = licenses.bsd3; + platforms = platforms.all; + inherit version; + }; +} +``` + +pkgs/default.nix: +```nix +final: prev: { + libinih = prev.callPackage ./development/libraries/libinih { }; +} +``` + +[pkgs]: https://github.com/NixOS/nixpkgs/tree/master/pkgs diff --git a/profiles/README.md b/profiles/README.md new file mode 100644 index 00000000..d9c4f9f1 --- /dev/null +++ b/profiles/README.md @@ -0,0 +1,48 @@ +# Profiles +Profiles are simply NixOS modules which contain generic expressions suitable +for any host. A good example is the configuration for a text editor, or +window manager. If you need some concrete examples, just checkout the +community [branch](https://github.com/nrdxp/nixflk/tree/community/profiles). + +## Constraints +For the sake of consistency, there are a few minor constraints. First of all, a +profile should always be defined in a `default.nix`, and it should always be a +a function taking a single attribute set as an argument, and returning a NixOS +module which does not define any new module options. If you need to make new +module option declarations, just use [modules](../modules). + +These restrictions help simplify the import logic used to pass profles to +[suites](../suites). + +### Example +#### Correct ✔ +profiles/develop/default.nix: +```nix +{ ... }: +{ + programs.zsh.enable = true; +} +``` + +#### Incorrect ❌ +profiles/develop.nix: +```nix +{ + options = {}; +} +``` + +## Subprofiles +Profiles can also define subprofiles. They follow the same constraints outlined +above. A good top level profile should be a high level concern, such a your +personal development environment, and the subprofiles should be more concrete +program configurations such as your text editor, and shell configs. This way, +you can either pull in the whole development profile, or pick and choose +individual programs. + +## Conclusion +Profiles are the most important concept in nixflk. They allow us to keep our +nix expressions self contained and modular. This way we can maximize reuse +while minimizing boilerplate. Always strive to keep your profiles as generic +and modular as possible. Anything machine specific belongs in your +[host](../hosts) files. diff --git a/secrets/.gitattributes b/secrets/.gitattributes index 5ccf582d..ff69eb2a 100644 --- a/secrets/.gitattributes +++ b/secrets/.gitattributes @@ -1,2 +1,3 @@ * filter=git-crypt diff=git-crypt .gitattributes !filter !diff +README.md !filter !diff diff --git a/secrets/README.md b/secrets/README.md new file mode 100644 index 00000000..107b49f1 --- /dev/null +++ b/secrets/README.md @@ -0,0 +1,18 @@ +# Secrets +Secrets are managed using [git-crypt][git-crypt] so you can keep your flake in +a public repository like GitHub without exposing your password or other +sensitive data. + +By default, everything in the secrets folder is automatically encrypted. Just +be sure to run `git-crypt init` before putting anything in here. + +> ##### _Note:_ +> Currently, there is [no mechanism][secrets-issue] in nix to deploy secrets +> within the nix/store so, if they end up in the nix/store after deployment, they +> will be world readable on that machine. +> +> The author of nixflk intends to implement a workaround for this situation in +> the near future, but for the time being, simple be aware of this. + +[git-crypt]: https://github.com/AGWA/git-crypt +[secrets-issue]: https://github.com/NixOS/nix/issues/8 diff --git a/shell/default.nix b/shell/default.nix index 963be9af..caeceed8 100644 --- a/shell/default.nix +++ b/shell/default.nix @@ -23,7 +23,6 @@ pkgs.devshell.mkShell { nixos-install nixos-generate-config nixos-enter - mdbook ]; env = { inherit name; }; diff --git a/suites/README.md b/suites/README.md new file mode 100644 index 00000000..e8f74890 --- /dev/null +++ b/suites/README.md @@ -0,0 +1,24 @@ +# Suites +Suites provide a mechanism for users to easily combine and name collecitons of +profiles. For good examples, check out the suites defined in the community +[branch](https://github.com/nrdxp/nixflk/blob/community/suites/default.nix). + +In the future, we will use suites as a mechanism for deploying various machine +types which don't depend on hardware, such as vm's and containers. + +## Definition +```nix +rec { + workstation = [ profiles.develop profiles.graphical users.nixos ]; + mobileWS = workstation ++ [ profiles.laptop ]; +} +``` + +## Usage +`hosts/my-laptop.nix`: +```nix +{ suites, ... }: +{ + imports = suites.mobileWS; +} +``` diff --git a/users/README.md b/users/README.md new file mode 100644 index 00000000..4963fdfd --- /dev/null +++ b/users/README.md @@ -0,0 +1,51 @@ +# Users + +Users are a special case of [profiles](../profiles) that define system +users and [home-manager][home-manager] configurations. For your convenience, +home manager is wired in by default so all you have to worry about is declaring +your users. For a fully fleshed out example, check out the developers personal +[branch](https://github.com/nrdxp/nixflk/tree/nrd/users/nrd/default.nix). + +## Basic Usage +`users/myuser/default.nix`: +```nix +{ ... }: +{ + users.users.myuser = { + isNormalUser = true; + }; + + home-manager.users.myuser = { + programs.mpv.enable = true; + }; +} + +``` + +## External Usage +You can easily use the defined home-manager configurations outside of NixOS +using the `hmActivations` meta-package defined in the flakes `legacyPackages` +output. The [flk](../doc/flk) helper script makes this even easier. + +This is great for keeping your environment consistent across Unix systems, +including OSX. + +### From within the projects devshell: +```sh +# builds the nixos user defined in the NixOS host +flk home NixOS nixos + +# build and activate +flk home NixOS nixos switch +``` + +### Manually from outside the project: +```sh +# build +nix build "github:nrdxp/nixflk#hmActivationPackages.NixOS.nixos" + +# activate +./result/activate && unlink result +``` + +[home-manager]: https://nix-community.github.io/home-manager From 3a735ce70b49774e9ea35acded53163d89c4c4b1 Mon Sep 17 00:00:00 2001 From: Timothy DeHerrera Date: Sun, 14 Feb 2021 15:50:49 -0700 Subject: [PATCH 2/4] core: pin registry by ref Users may wish to change the default value of override and nixos inputs. If they do so, we want the registry listing to reflect the proper ref names afterwards. Also create a shell alias to easily search every flake in nix.registry. --- hosts/default.nix | 69 +++++++++++++++++++++++++++------------ profiles/core/default.nix | 19 +++++++++-- 2 files changed, 65 insertions(+), 23 deletions(-) diff --git a/hosts/default.nix b/hosts/default.nix index b5e31a63..6bc06e4d 100644 --- a/hosts/default.nix +++ b/hosts/default.nix @@ -1,11 +1,12 @@ -{ lib +{ extern +, home +, lib , nixos -, override , nixos-hardware +, override , pkgs , self , system -, extern , ... }: let @@ -36,29 +37,57 @@ let modules; }; - global = { - home-manager.useGlobalPkgs = true; - home-manager.useUserPackages = true; + global = + let + inherit (lock) nodes; - hardware.enableRedistributableFirmware = lib.mkDefault true; + lock = builtins.fromJSON (builtins.readFile ../flake.lock); + in + { + home-manager.useGlobalPkgs = true; + home-manager.useUserPackages = true; - networking.hostName = hostName; - nix.nixPath = [ - "nixos-unstable=${override}" - "nixos=${nixos}" - "nixpkgs=${nixos}" - ]; + hardware.enableRedistributableFirmware = lib.mkDefault true; - nixpkgs = { inherit pkgs; }; + networking.hostName = hostName; - nix.registry = { - nixflk.flake = self; - nixpkgs.flake = nixos; + nix.nixPath = [ + "nixpkgs=${nixos}" + "nixos-config=${self}/compat/nixos" + "home-manager=${home}" + ]; + + nixpkgs = { inherit pkgs; }; + + nix.registry = { + flk.flake = self; + + nixos = { + exact = true; + from = nodes.nixos.original; + to = { + inherit (nixos) lastModified narHash rev; + + path = override.outPath; + type = "path"; + }; + }; + + override = { + exact = true; + from = nodes.override.original; + to = { + inherit (override) lastModified narHash rev; + + path = override.outPath; + type = "path"; + }; + }; + }; + + system.configurationRevision = lib.mkIf (self ? rev) self.rev; }; - system.configurationRevision = lib.mkIf (self ? rev) self.rev; - }; - local = { require = [ (import "${toString ./.}/${hostName}.nix") diff --git a/profiles/core/default.nix b/profiles/core/default.nix index 51099554..bf96b266 100644 --- a/profiles/core/default.nix +++ b/profiles/core/default.nix @@ -65,8 +65,8 @@ in nr = "np remove"; ns = "n search --no-update-lock-file"; nf = "n flake"; - nepl = "n repl ''"; - srch = "ns nixpkgs"; + nepl = "n repl ''"; + srch = "nsni"; nrb = ifSudo "sudo nixos-rebuild"; mn = '' manix "" | grep '^# ' | sed 's/^# \(.*\) (.*/\1/;s/ (.*//;s/^# //' | sk --preview="manix '{}'" | xargs manix @@ -93,7 +93,20 @@ in dn = ifSudo "s systemctl stop"; jtl = "journalctl"; - }; + } // lib.mapAttrs' + (n: v: + let + prefix = lib.concatStrings (lib.take 2 (lib.stringToCharacters n)); + ref = from: + if from ? ref + then "ns ${from.id}/${from.ref}" + else "ns ${from.id}"; + in + lib.nameValuePair + "ns${prefix}" + (ref v.from) + ) + config.nix.registry; }; From 0405949ec62c47ebd1ae3825f223a071269205c8 Mon Sep 17 00:00:00 2001 From: Timothy DeHerrera Date: Sun, 14 Feb 2021 17:41:15 -0700 Subject: [PATCH 3/4] doc: finish `flk` reference --- README.md | 256 ++++++-------------------------------------- SUMMARY.md | 11 +- doc/CONTRIBUTING.md | 1 + doc/README.md | 26 +++++ doc/flk/get.md | 10 ++ doc/flk/home.md | 8 ++ doc/flk/index.md | 19 ++++ doc/flk/install.md | 12 +++ doc/flk/iso.md | 1 + doc/flk/up.md | 4 + doc/flk/update.md | 6 ++ doc/introduction.md | 33 ------ doc/start/index.md | 2 +- hosts/README.md | 2 +- theme/highlight.js | 6 ++ 15 files changed, 138 insertions(+), 259 deletions(-) create mode 100644 doc/CONTRIBUTING.md create mode 100644 doc/README.md create mode 100644 doc/flk/get.md create mode 100644 doc/flk/home.md create mode 100644 doc/flk/install.md create mode 120000 doc/flk/iso.md create mode 100644 doc/flk/up.md create mode 100644 doc/flk/update.md delete mode 100644 doc/introduction.md create mode 100644 theme/highlight.js diff --git a/README.md b/README.md index a9c463ac..db5dcb02 100644 --- a/README.md +++ b/README.md @@ -1,233 +1,45 @@ -> Since flakes are still quite new, I've listed some learning resources -> [below](#resources). - # Introduction -Herein lies a [NixOS][NixOS] configuration template using the new [flakes][wiki] -mechanism. Its aim is to provide a generic repository which neatly separates -concerns and allows one to get up and running with NixOS faster than ever, while -keeping your code clean and organized. +Nixflk is a template which grants a simple way to use, deploy and manage +[NixOS][nixos] systems for personal and productive use. It does this by +providing a sane repository structure, integrating several popular projects +like [home-manager][home-manager], setting clear guidelines, offering useful +conveniences, and eliminating boilerplate so you can focus on deploying your +systems. -Some key advantages include: -* A single home for all your Nix expressions, easily sharable and portable! -* Skip the boilerplate, simply use the included [nix-shell](./shell.nix) or - [direnv][direnv] profile and get up and running with flakes right away. -* Thanks to flakes, the entire system is more [deterministic](./flake.lock). -* Systems defined under [hosts](./hosts) are automatically imported into - `nixosConfigurations`, ready to deploy. -* [Profiles](./profiles/list.nix) are a simple mechanism for using portable - code across machines. -* Defined [packages](./pkgs/default.nix) and - [modules](./modules/list.nix), are automatically wired and available from - anywhere. They are _also_ sharable via their respective flake outputs. -* Easily [override](./unstable/default.nix) packages from different nixpkgs - versions. -* Keep [user](./users) configuration isolated and easily reusable by taking - advantage of [user profiles](./users/profiles) and [home-manager][home-manager]. -* [Overlay](./overlays) files are automatically available and sharable. -* Automatic [NUR][nur] support. +## Getting Started +Check out the [guide](https://flk.nrdxp.dev/doc/start) to get up and running. -For a more detailed explanation of the code structure, check out the -[docs](./DOC.md). +## Motivation +NixOS provides an amazing abstraction to manage our computers, but that new +power can sometimes bring feelings of overwhelm and confusion. Having a turing +complete programming language can add an unlimited potential for complexity if +we do it wrong. Instead, we should have a community consensus on how to manage +a NixOS system — consider this a first attempt. -### ⚠ Advisory -Flakes are still new, so not everything works yet. However, it has been to -merged in [nixpkgs][nixpkgs] via [`pkgs.nixFlakes`][nixFlakes]. Thus, this -project should be considered _experimental_, until flakes become the default. +___The future is declarative! 🎉___ -Also, flakes are meant to deprecate nix-channels. It's recommended not to -install any. If your really want them, they should work if you hook them into -`NIX_PATH`. +## Community Profiles +There are two branches from which to choose: [core][core] and +[community][community]. The community branch builds on core and includes +several ready-made profiles for discretionary use. -# Setup -There are a few ways to get up and running. You can fork this repo or use it as -a template. There is a [community][community] branch with a bunch of useful -profiles, modules, overlays, etc, already configured for you to use. Please -consider adding your own expressions there if you feel they would be helpful -for others. - -The only hard requirement is nix itself. The `shell.nix` will pull in -everything else. - -## Flake Templates -If you already have [nix-command][nix-command] setup you can: -```sh -# for the core template with no profiles -nix flake new -t "github:nrdxp/nixflk" flk - -# for the community template -nix flake new -t "github:nrdxp/nixflk/community" flk -``` - -## Nix Only -Once you have this repo, you'll want to __move or symlink__ it to `/etc/nixos` -for ease of use. Once inside: -```sh -# probably want to use a separate branch for you config -git checkout -b my-branch - -# This will setup nix-command and pull in the needed tools -nix-shell # or `direnv allow` if you prefer - -# use nixos-generate-config to generate a basic config for your system -# edit hosts/up-$(hostname).nix to modify. -flk up - -# The following should work fine for EFI systems. -# boot.loader.systemd-boot.enable = true; -# boot.loader.efi.canTouchEfiVariables = true; - -# Set your locale -$EDITOR local/locale.nix - -# install NixOS to bare metal -flk install yourConfig # deploys hosts/yourConfig.nix - -# if you already have NixOS and just want to deploy your new setup -flk yourConfig switch -``` - -### Note on `flk up`: -While the `up` sub-command is provided as a convenience to quickly set up and -install a "fresh" NixOS system on current hardware, committing these files is -discouraged. - -They are placed in the git staging area automatically because they would be -invisible to the flake otherwise, but it is best to move what you need from -them directly into your hosts file and commit that instead. - -# Sharing -One of the great benefits of flakes is the ability to easily share your user -defined packages, modules and other nix expressions without having to merge -anything upstream. In that spirit, everything defined in this flake is usable -from other flakes. So even if you don't want to use this project as a template, -you can still pull in any useful modules, packages or profiles defined here. - -From the command line: -```sh -# to see what this flake exports -nix flake show "github:nrdxp/nixflk" - -# run an app -nix run "github:nrdxp/nixflk#someApp" - -# start a dev shell for a given derivation -nix develop "github:nrdxp/nixflk#somePackage" - -# a nix shell with the package in scope -nix shell "github:nrdxp/nixflk#somePackage" -``` - -From within a flake: -```nix -{ - inputs.nixflk.url = "github:nrdxp/nixflk"; - - outputs = { self, nixpkgs, nixflk, ... }: - { - nixosConfigurations.example = nixpkgs.lib.nixosSystem { - # ... - modules = [ - nixflk.nixosModules.someModule - ({ - nixpkgs.overlays = [ nixflk.overlay nixflk.overlays.someOverlay ]; - }) - # ... - ]; - }; - }; -} -``` - -## Home Manager Integration -The home-manager nixos module is available for each host. It is meant -to be used in the user profiles, you can find an example in the nixos user profile - -The home-manager configuration for each user in each system is available in the -outputs as homeConfigurations and the activation packages in hmActivationPackages. - -This allows you to just build the home-manager environment without the rest of the -system configuration. The feature is useful on systems without nixos or root access. - -Lets say you want to activate the home configuration for the user `nixos` in the -host `NixOS`. - -With the flk script: -```sh -# You can build it using -flk home NixOS nixos -# and activate with -./result/activate - -# Or do both like this -flk home NixOS nixos switch -``` - -## Build an ISO - -You can make an ISO out of any config: -```sh -flk iso yourConfig # build an iso for hosts/yourConfig.nix -``` - -## Hardware Specific Profile for a Single Host - -Find out the fitting -[nixos-hardware profile](https://github.com/NixOS/nixos-hardware#list-of-profiles) -for the hardware of your host, then find the corresponding modules in the -[flake](https://github.com/NixOS/nixos-hardware/blob/master/flake.nix) and add -it to the configuration. For example for a Dell XPS 13 9370 the host -configuration would contain: -```nix -{ hardware, ... }: -{ - imports = [ hardware.dell-xps-13-9370 ... ]; - ... -} -``` - -## Use a Package from NUR - -NUR is wired in from the start. For safety, nothing is added from it by default, -but you can easily pull packages from inside your configuration like so: -```nix -{ pkgs, ... }: -{ - environment.systemPackages = with pkgs; [ nur.repos.. ]; -} -``` -# Resources - -## Links -* [Example Repo](https://github.com/colemickens/nixos-flake-example) -* [Tweag.io _Flakes_ Blog Series](https://www.tweag.io/blog/2020-05-25-flakes) -* [NixOS _Flakes_ Wiki](https://nixos.wiki/wiki/Flakes) -* [Zimbatm's _Flakes_ Blog](https://zimbatm.com/NixFlakes) -* [Original RFC](https://github.com/tweag/rfcs/blob/flakes/rfcs/0049-flakes.md) - -## Flake Talk: -[![Flake talk at NixConf][thumb]][video] +Every package and NixOS profile declared in community is uploaded to +[cachix](./cachix), so everything provided is available without building +anything. This is especially useful for the packages that are +[overridden](./overrides) from master, as without the cache, rebuilds are +quite frequent. +> #### ⚠ Advisory ⚠ +> Nixflk leverages the [flakes][flakes] feature available via an _experimental_ +> branch of [nix][nix]. Until nix 3.0 is released, this project should be +> considered unstable. # License +Nixflk is licensed under the [MIT License](https://mit-license.org). -This software is licensed under the [MIT License](COPYING). - -Note: MIT license does not apply to the packages built by this configuration, -merely to the files in this repository (the Nix expressions, build -scripts, NixOS modules, etc.). It also might not apply to patches -included here, which may be derivative works of the packages to -which they apply. The aforementioned artifacts are all covered by the -licenses of the respective packages. - +[nix]: https://nixos.org/manual/nix/stable +[nixos]: https://nixos.org/manual/nixos/stable +[home-manager]: https://nix-community.github.io/home-manager +[flakes]: https://nixos.wiki/wiki/Flakes +[core]: https://github.com/nrdxp/nixflk [community]: https://github.com/nrdxp/nixflk/tree/community -[direnv]: https://direnv.net -[home-manager]: https://github.com/nix-community/home-manager -[nix-command]: https://nixos.wiki/wiki/Nix_command -[nixFlakes]: https://github.com/NixOS/nixpkgs/blob/master/pkgs/tools/package-management/nix/default.nix#L211 -[NixOS]: https://nixos.org -[nixpkgs]: https://github.com/NixOS/nixpkgs -[nur]: https://github.com/nix-community/NUR -[wiki]: https://nixos.wiki/wiki/Flakes -[thumb]: https://img.youtube.com/vi/UeBX7Ide5a0/hqdefault.jpg -[video]: https://www.youtube.com/watch?v=UeBX7Ide5a0 -[nur]: https://github.com/nix-community/NUR diff --git a/SUMMARY.md b/SUMMARY.md index 1b95eb5d..410e7973 100644 --- a/SUMMARY.md +++ b/SUMMARY.md @@ -1,6 +1,6 @@ # Summary -- [Introduction](./doc/introduction.md) +- [Introduction](./README.md) - [Quick Start](./doc/start/index.md) - [ISO](./doc/start/iso.md) - [From NixOS](./doc/start/from-nixos.md) @@ -16,4 +16,11 @@ - [Secrets](./secrets/README.md) - [Suites](./suites/README.md) - [Users](./users/README.md) -- [flk command](./doc/flk/index.md) +- [flk](./doc/flk/index.md) + - [up](./doc/flk/up.md) + - [update](./doc/flk/update.md) + - [get](./doc/flk/get.md) + - [iso](./doc/flk/iso.md) + - [install](./doc/flk/install.md) + - [home](./doc/flk/home.md) +- [Contributing](./doc/README.md) diff --git a/doc/CONTRIBUTING.md b/doc/CONTRIBUTING.md new file mode 100644 index 00000000..854139a3 --- /dev/null +++ b/doc/CONTRIBUTING.md @@ -0,0 +1 @@ +# Contributing diff --git a/doc/README.md b/doc/README.md new file mode 100644 index 00000000..b60cd8b1 --- /dev/null +++ b/doc/README.md @@ -0,0 +1,26 @@ +# Pull Requests +If making a change to core, or adding a feature, please be sure to update the +relevant docs. Each directory contains its own README.md, which will +automatically be pulled into the [mdbook](https://flk.nrdxp.dev). The book is +rendered on every change, so the docs should always be up to date. + + +## Community PRs +While much of your work in this template may be idiosyncratic in nature. Anything +that might be generally useful to the broader NixOS community can be synced to +the `community` branch to provide a host of useful NixOS configurations available +"out of the box". + +# Style +If you wish to contribute please follow these guidelines: + +* format your code with [`nixpkgs-fmt`][nixpkgs-fmt]. The default devshell + includes a pre-commit hook that does this for you. + +* The commit message follows the same semantics as [nixpkgs][nixpkgs]. + * You can use a `#` symbol to specify ambiguities. For example, + `develop#zsh: ` would tell me that your updating the + `zsh` subprofile living under the `develop` profile. + +[nixpkgs-fmt]: https://github.com/nix-community/nixpkgs-fmt +[nixpkgs]: https://github.com/NixOS/nixpkgs diff --git a/doc/flk/get.md b/doc/flk/get.md new file mode 100644 index 00000000..bd10d5f5 --- /dev/null +++ b/doc/flk/get.md @@ -0,0 +1,10 @@ +# get +The `get` subcommand is useful for getting a bare copy of nixflk without the +git history. You can pull either the core or community branches. + +## Usage +```sh +flk get BRANCH DEST-DIR +``` + +If DEST-DIR is ommitted, it defaults to _./flk_. diff --git a/doc/flk/home.md b/doc/flk/home.md new file mode 100644 index 00000000..01cb52e3 --- /dev/null +++ b/doc/flk/home.md @@ -0,0 +1,8 @@ +# home +The `home` subcommand is for using your home-manager configurations outside of +NixOS, providing an awesome mechanism for keeping your environments +synchronized, even when using other systems. + +## Usage +The [users](../../users/index.md#external-usage) page contains a good usage +example. diff --git a/doc/flk/index.md b/doc/flk/index.md index 6a441957..04fc1c48 100644 --- a/doc/flk/index.md +++ b/doc/flk/index.md @@ -1 +1,20 @@ # flk command +The devshell for the project incudes a convenient script for managing your +system called `flk`. Each of the following chapters is a reference for one of +its subcommands. + +## Rebuild +Without any of the subcommands, `flk` acts as a convenient shortcut for +`nixos-rebuild`: +```sh +flk NixOS build +``` + +Will build _hosts/NixOS.nix_. You can change out `build` for `switch`, `test`, +etc. Any additional arguments are passed through to the call to +`nixos-rebuild`. + +## Usage +```sh +flk help +``` diff --git a/doc/flk/install.md b/doc/flk/install.md new file mode 100644 index 00000000..3ae52504 --- /dev/null +++ b/doc/flk/install.md @@ -0,0 +1,12 @@ +# install +The `install` subcommand is a simple convenience for `nixos-install`, similar +to the shortcut for `nixos-rebuild`, all additional arguments are passed +through. + +## Example +```sh +flk install NixOS +``` + +This will install _hosts/NixOS.nix_ to /mnt. You can override this directory +using standard `nixos-install` args. diff --git a/doc/flk/iso.md b/doc/flk/iso.md new file mode 120000 index 00000000..fa658ef4 --- /dev/null +++ b/doc/flk/iso.md @@ -0,0 +1 @@ +../start/iso.md \ No newline at end of file diff --git a/doc/flk/up.md b/doc/flk/up.md new file mode 100644 index 00000000..9d795fb4 --- /dev/null +++ b/doc/flk/up.md @@ -0,0 +1,4 @@ +# up +The `up` subcommand is a simple shortcut for `nixos-generate-config` that is +compatible with nixflk. There is a short explanation in the the getting started +[guide](../start/from-nixos.md#generate-configuration). diff --git a/doc/flk/update.md b/doc/flk/update.md new file mode 100644 index 00000000..e3a20e80 --- /dev/null +++ b/doc/flk/update.md @@ -0,0 +1,6 @@ +# update +The `update` subcommand is a simple alias for: +```sh +nix flake update --recreate-lock-file --commit-lock-file +``` +As it sounds, this will update your lock file, and commit it. diff --git a/doc/introduction.md b/doc/introduction.md deleted file mode 100644 index 9f7b2bd5..00000000 --- a/doc/introduction.md +++ /dev/null @@ -1,33 +0,0 @@ -# Introduction -Nixflk is a template which grants a simple way to use, deploy and manage -[NixOS][nixos] systems for personal and productive use. It does this by -providing a sane repository structure, integrating several popular projects -like [home-manager][home-manager], setting clear guidelines, offering useful -conveniences, and eliminating boilerplate so you can focus on deploying your -systems. - -## Community Profiles -There are two branches from which to choose: [core][core] and -[community][community]. The community branch builds on core and includes -several ready-made profiles for discretionary use. - -Every package and NixOS profile declared in community is uploaded to -[cachix](../cachix), so everything provided is available without building -anything. This is especially useful for the packages that are -[overridden](../overrides) from master, as without the cache, rebuilds are -quite frequent. - -### ⚠ Advisory -Nixflk leverages the [flakes][flakes] feature available via an _experimental_ -branch of [nix][nix]. Until nix 3.0 is released, this project should be -considered unstable. - -# License -Nixflk is licensed under the [MIT License](https://mit-license.org). - -[nix]: https://nixos.org/manual/nix/stable -[nixos]: https://nixos.org/manual/nixos/stable -[home-manager]: https://nix-community.github.io/home-manager -[flakes]: https://nixos.wiki/wiki/Flakes -[core]: https://github.com/nrdxp/nixflk -[community]: https://github.com/nrdxp/nixflk/tree/community diff --git a/doc/start/index.md b/doc/start/index.md index d74f726b..14745e71 100644 --- a/doc/start/index.md +++ b/doc/start/index.md @@ -25,7 +25,7 @@ version required. In addition, the [binary cache](../../cachix) is added for faster deployment. > ##### _Notes:_ -> - You can change `core` to [`community`](../introduction.md#community-profiles) +> - You can change `core` to [`community`](../../index.md#community-profiles) > in the call to `flk get` > - Flakes ignore files that have not been added to git, so be sure to stage new > files before building the system. diff --git a/hosts/README.md b/hosts/README.md index a8f4c9db..043f9e90 100644 --- a/hosts/README.md +++ b/hosts/README.md @@ -27,7 +27,7 @@ the [nixos-hardware][nixos-hardware] repository. ## Example -`hosts/librem.nix`: +hosts/librem.nix: ```nix { suites, hardware, ... }: { diff --git a/theme/highlight.js b/theme/highlight.js new file mode 100644 index 00000000..f4fd4fae --- /dev/null +++ b/theme/highlight.js @@ -0,0 +1,6 @@ +/* + Highlight.js 10.1.2 (edd73d24) + License: BSD-3-Clause + Copyright (c) 2006-2020, Ivan Sagalaev +*/ +var hljs=function(){"use strict";function e(n){Object.freeze(n);var t="function"==typeof n;return Object.getOwnPropertyNames(n).forEach((function(r){!Object.hasOwnProperty.call(n,r)||null===n[r]||"object"!=typeof n[r]&&"function"!=typeof n[r]||t&&("caller"===r||"callee"===r||"arguments"===r)||Object.isFrozen(n[r])||e(n[r])})),n}class n{constructor(e){void 0===e.data&&(e.data={}),this.data=e.data}ignoreMatch(){this.ignore=!0}}function t(e){return e.replace(/&/g,"&").replace(//g,">").replace(/"/g,""").replace(/'/g,"'")}function r(e,...n){var t={};for(const n in e)t[n]=e[n];return n.forEach((function(e){for(const n in e)t[n]=e[n]})),t}function a(e){return e.nodeName.toLowerCase()}var i=Object.freeze({__proto__:null,escapeHTML:t,inherit:r,nodeStream:function(e){var n=[];return function e(t,r){for(var i=t.firstChild;i;i=i.nextSibling)3===i.nodeType?r+=i.nodeValue.length:1===i.nodeType&&(n.push({event:"start",offset:r,node:i}),r=e(i,r),a(i).match(/br|hr|img|input/)||n.push({event:"stop",offset:r,node:i}));return r}(e,0),n},mergeStreams:function(e,n,r){var i=0,s="",o=[];function l(){return e.length&&n.length?e[0].offset!==n[0].offset?e[0].offset"}function u(e){s+=""}function d(e){("start"===e.event?c:u)(e.node)}for(;e.length||n.length;){var g=l();if(s+=t(r.substring(i,g[0].offset)),i=g[0].offset,g===e){o.reverse().forEach(u);do{d(g.splice(0,1)[0]),g=l()}while(g===e&&g.length&&g[0].offset===i);o.reverse().forEach(c)}else"start"===g[0].event?o.push(g[0].node):o.pop(),d(g.splice(0,1)[0])}return s+t(r.substr(i))}});const s="",o=e=>!!e.kind;class l{constructor(e,n){this.buffer="",this.classPrefix=n.classPrefix,e.walk(this)}addText(e){this.buffer+=t(e)}openNode(e){if(!o(e))return;let n=e.kind;e.sublanguage||(n=`${this.classPrefix}${n}`),this.span(n)}closeNode(e){o(e)&&(this.buffer+=s)}value(){return this.buffer}span(e){this.buffer+=``}}class c{constructor(){this.rootNode={children:[]},this.stack=[this.rootNode]}get top(){return this.stack[this.stack.length-1]}get root(){return this.rootNode}add(e){this.top.children.push(e)}openNode(e){const n={kind:e,children:[]};this.add(n),this.stack.push(n)}closeNode(){if(this.stack.length>1)return this.stack.pop()}closeAllNodes(){for(;this.closeNode(););}toJSON(){return JSON.stringify(this.rootNode,null,4)}walk(e){return this.constructor._walk(e,this.rootNode)}static _walk(e,n){return"string"==typeof n?e.addText(n):n.children&&(e.openNode(n),n.children.forEach(n=>this._walk(e,n)),e.closeNode(n)),e}static _collapse(e){"string"!=typeof e&&e.children&&(e.children.every(e=>"string"==typeof e)?e.children=[e.children.join("")]:e.children.forEach(e=>{c._collapse(e)}))}}class u extends c{constructor(e){super(),this.options=e}addKeyword(e,n){""!==e&&(this.openNode(n),this.addText(e),this.closeNode())}addText(e){""!==e&&this.add(e)}addSublanguage(e,n){const t=e.root;t.kind=n,t.sublanguage=!0,this.add(t)}toHTML(){return new l(this,this.options).value()}finalize(){return!0}}function d(e){return e?"string"==typeof e?e:e.source:null}const g="(-?)(\\b0[xX][a-fA-F0-9]+|(\\b\\d+(\\.\\d*)?|\\.\\d+)([eE][-+]?\\d+)?)",h={begin:"\\\\[\\s\\S]",relevance:0},f={className:"string",begin:"'",end:"'",illegal:"\\n",contains:[h]},p={className:"string",begin:'"',end:'"',illegal:"\\n",contains:[h]},b={begin:/\b(a|an|the|are|I'm|isn't|don't|doesn't|won't|but|just|should|pretty|simply|enough|gonna|going|wtf|so|such|will|you|your|they|like|more)\b/},m=function(e,n,t={}){var a=r({className:"comment",begin:e,end:n,contains:[]},t);return a.contains.push(b),a.contains.push({className:"doctag",begin:"(?:TODO|FIXME|NOTE|BUG|OPTIMIZE|HACK|XXX):",relevance:0}),a},v=m("//","$"),x=m("/\\*","\\*/"),E=m("#","$");var _=Object.freeze({__proto__:null,IDENT_RE:"[a-zA-Z]\\w*",UNDERSCORE_IDENT_RE:"[a-zA-Z_]\\w*",NUMBER_RE:"\\b\\d+(\\.\\d+)?",C_NUMBER_RE:g,BINARY_NUMBER_RE:"\\b(0b[01]+)",RE_STARTERS_RE:"!|!=|!==|%|%=|&|&&|&=|\\*|\\*=|\\+|\\+=|,|-|-=|/=|/|:|;|<<|<<=|<=|<|===|==|=|>>>=|>>=|>=|>>>|>>|>|\\?|\\[|\\{|\\(|\\^|\\^=|\\||\\|=|\\|\\||~",SHEBANG:(e={})=>{const n=/^#![ ]*\//;return e.binary&&(e.begin=function(...e){return e.map(e=>d(e)).join("")}(n,/.*\b/,e.binary,/\b.*/)),r({className:"meta",begin:n,end:/$/,relevance:0,"on:begin":(e,n)=>{0!==e.index&&n.ignoreMatch()}},e)},BACKSLASH_ESCAPE:h,APOS_STRING_MODE:f,QUOTE_STRING_MODE:p,PHRASAL_WORDS_MODE:b,COMMENT:m,C_LINE_COMMENT_MODE:v,C_BLOCK_COMMENT_MODE:x,HASH_COMMENT_MODE:E,NUMBER_MODE:{className:"number",begin:"\\b\\d+(\\.\\d+)?",relevance:0},C_NUMBER_MODE:{className:"number",begin:g,relevance:0},BINARY_NUMBER_MODE:{className:"number",begin:"\\b(0b[01]+)",relevance:0},CSS_NUMBER_MODE:{className:"number",begin:"\\b\\d+(\\.\\d+)?(%|em|ex|ch|rem|vw|vh|vmin|vmax|cm|mm|in|pt|pc|px|deg|grad|rad|turn|s|ms|Hz|kHz|dpi|dpcm|dppx)?",relevance:0},REGEXP_MODE:{begin:/(?=\/[^/\n]*\/)/,contains:[{className:"regexp",begin:/\//,end:/\/[gimuy]*/,illegal:/\n/,contains:[h,{begin:/\[/,end:/\]/,relevance:0,contains:[h]}]}]},TITLE_MODE:{className:"title",begin:"[a-zA-Z]\\w*",relevance:0},UNDERSCORE_TITLE_MODE:{className:"title",begin:"[a-zA-Z_]\\w*",relevance:0},METHOD_GUARD:{begin:"\\.\\s*[a-zA-Z_]\\w*",relevance:0},END_SAME_AS_BEGIN:function(e){return Object.assign(e,{"on:begin":(e,n)=>{n.data._beginMatch=e[1]},"on:end":(e,n)=>{n.data._beginMatch!==e[1]&&n.ignoreMatch()}})}}),N="of and for in not or if then".split(" ");function w(e,n){return n?+n:function(e){return N.includes(e.toLowerCase())}(e)?0:1}const R=t,y=r,{nodeStream:O,mergeStreams:k}=i,M=Symbol("nomatch");return function(t){var a=[],i=Object.create(null),s=Object.create(null),o=[],l=!0,c=/(^(<[^>]+>|\t|)+|\n)/gm,g="Could not find the language '{}', did you forget to load/include a language module?";const h={disableAutodetect:!0,name:"Plain text",contains:[]};var f={noHighlightRe:/^(no-?highlight)$/i,languageDetectRe:/\blang(?:uage)?-([\w-]+)\b/i,classPrefix:"hljs-",tabReplace:null,useBR:!1,languages:null,__emitter:u};function p(e){return f.noHighlightRe.test(e)}function b(e,n,t,r){var a={code:n,language:e};S("before:highlight",a);var i=a.result?a.result:m(a.language,a.code,t,r);return i.code=a.code,S("after:highlight",i),i}function m(e,t,a,s){var o=t;function c(e,n){var t=E.case_insensitive?n[0].toLowerCase():n[0];return Object.prototype.hasOwnProperty.call(e.keywords,t)&&e.keywords[t]}function u(){null!=y.subLanguage?function(){if(""!==A){var e=null;if("string"==typeof y.subLanguage){if(!i[y.subLanguage])return void k.addText(A);e=m(y.subLanguage,A,!0,O[y.subLanguage]),O[y.subLanguage]=e.top}else e=v(A,y.subLanguage.length?y.subLanguage:null);y.relevance>0&&(I+=e.relevance),k.addSublanguage(e.emitter,e.language)}}():function(){if(!y.keywords)return void k.addText(A);let e=0;y.keywordPatternRe.lastIndex=0;let n=y.keywordPatternRe.exec(A),t="";for(;n;){t+=A.substring(e,n.index);const r=c(y,n);if(r){const[e,a]=r;k.addText(t),t="",I+=a,k.addKeyword(n[0],e)}else t+=n[0];e=y.keywordPatternRe.lastIndex,n=y.keywordPatternRe.exec(A)}t+=A.substr(e),k.addText(t)}(),A=""}function h(e){return e.className&&k.openNode(e.className),y=Object.create(e,{parent:{value:y}})}function p(e){return 0===y.matcher.regexIndex?(A+=e[0],1):(L=!0,0)}var b={};function x(t,r){var i=r&&r[0];if(A+=t,null==i)return u(),0;if("begin"===b.type&&"end"===r.type&&b.index===r.index&&""===i){if(A+=o.slice(r.index,r.index+1),!l){const n=Error("0 width match regex");throw n.languageName=e,n.badRule=b.rule,n}return 1}if(b=r,"begin"===r.type)return function(e){var t=e[0],r=e.rule;const a=new n(r),i=[r.__beforeBegin,r["on:begin"]];for(const n of i)if(n&&(n(e,a),a.ignore))return p(t);return r&&r.endSameAsBegin&&(r.endRe=RegExp(t.replace(/[-/\\^$*+?.()|[\]{}]/g,"\\$&"),"m")),r.skip?A+=t:(r.excludeBegin&&(A+=t),u(),r.returnBegin||r.excludeBegin||(A=t)),h(r),r.returnBegin?0:t.length}(r);if("illegal"===r.type&&!a){const e=Error('Illegal lexeme "'+i+'" for mode "'+(y.className||"")+'"');throw e.mode=y,e}if("end"===r.type){var s=function(e){var t=e[0],r=o.substr(e.index),a=function e(t,r,a){let i=function(e,n){var t=e&&e.exec(n);return t&&0===t.index}(t.endRe,a);if(i){if(t["on:end"]){const e=new n(t);t["on:end"](r,e),e.ignore&&(i=!1)}if(i){for(;t.endsParent&&t.parent;)t=t.parent;return t}}if(t.endsWithParent)return e(t.parent,r,a)}(y,e,r);if(!a)return M;var i=y;i.skip?A+=t:(i.returnEnd||i.excludeEnd||(A+=t),u(),i.excludeEnd&&(A=t));do{y.className&&k.closeNode(),y.skip||y.subLanguage||(I+=y.relevance),y=y.parent}while(y!==a.parent);return a.starts&&(a.endSameAsBegin&&(a.starts.endRe=a.endRe),h(a.starts)),i.returnEnd?0:t.length}(r);if(s!==M)return s}if("illegal"===r.type&&""===i)return 1;if(B>1e5&&B>3*r.index)throw Error("potential infinite loop, way more iterations than matches");return A+=i,i.length}var E=T(e);if(!E)throw console.error(g.replace("{}",e)),Error('Unknown language: "'+e+'"');var _=function(e){function n(n,t){return RegExp(d(n),"m"+(e.case_insensitive?"i":"")+(t?"g":""))}class t{constructor(){this.matchIndexes={},this.regexes=[],this.matchAt=1,this.position=0}addRule(e,n){n.position=this.position++,this.matchIndexes[this.matchAt]=n,this.regexes.push([n,e]),this.matchAt+=function(e){return RegExp(e.toString()+"|").exec("").length-1}(e)+1}compile(){0===this.regexes.length&&(this.exec=()=>null);const e=this.regexes.map(e=>e[1]);this.matcherRe=n(function(e,n="|"){for(var t=/\[(?:[^\\\]]|\\.)*\]|\(\??|\\([1-9][0-9]*)|\\./,r=0,a="",i=0;i0&&(a+=n),a+="(";o.length>0;){var l=t.exec(o);if(null==l){a+=o;break}a+=o.substring(0,l.index),o=o.substring(l.index+l[0].length),"\\"===l[0][0]&&l[1]?a+="\\"+(+l[1]+s):(a+=l[0],"("===l[0]&&r++)}a+=")"}return a}(e),!0),this.lastIndex=0}exec(e){this.matcherRe.lastIndex=this.lastIndex;const n=this.matcherRe.exec(e);if(!n)return null;const t=n.findIndex((e,n)=>n>0&&void 0!==e),r=this.matchIndexes[t];return n.splice(0,t),Object.assign(n,r)}}class a{constructor(){this.rules=[],this.multiRegexes=[],this.count=0,this.lastIndex=0,this.regexIndex=0}getMatcher(e){if(this.multiRegexes[e])return this.multiRegexes[e];const n=new t;return this.rules.slice(e).forEach(([e,t])=>n.addRule(e,t)),n.compile(),this.multiRegexes[e]=n,n}considerAll(){this.regexIndex=0}addRule(e,n){this.rules.push([e,n]),"begin"===n.type&&this.count++}exec(e){const n=this.getMatcher(this.regexIndex);n.lastIndex=this.lastIndex;const t=n.exec(e);return t&&(this.regexIndex+=t.position+1,this.regexIndex===this.count&&(this.regexIndex=0)),t}}function i(e,n){const t=e.input[e.index-1],r=e.input[e.index+e[0].length];"."!==t&&"."!==r||n.ignoreMatch()}if(e.contains&&e.contains.includes("self"))throw Error("ERR: contains `self` is not supported at the top-level of a language. See documentation.");return function t(s,o){const l=s;if(s.compiled)return l;s.compiled=!0,s.__beforeBegin=null,s.keywords=s.keywords||s.beginKeywords;let c=null;if("object"==typeof s.keywords&&(c=s.keywords.$pattern,delete s.keywords.$pattern),s.keywords&&(s.keywords=function(e,n){var t={};return"string"==typeof e?r("keyword",e):Object.keys(e).forEach((function(n){r(n,e[n])})),t;function r(e,r){n&&(r=r.toLowerCase()),r.split(" ").forEach((function(n){var r=n.split("|");t[r[0]]=[e,w(r[0],r[1])]}))}}(s.keywords,e.case_insensitive)),s.lexemes&&c)throw Error("ERR: Prefer `keywords.$pattern` to `mode.lexemes`, BOTH are not allowed. (see mode reference) ");return l.keywordPatternRe=n(s.lexemes||c||/\w+/,!0),o&&(s.beginKeywords&&(s.begin="\\b("+s.beginKeywords.split(" ").join("|")+")(?=\\b|\\s)",s.__beforeBegin=i),s.begin||(s.begin=/\B|\b/),l.beginRe=n(s.begin),s.endSameAsBegin&&(s.end=s.begin),s.end||s.endsWithParent||(s.end=/\B|\b/),s.end&&(l.endRe=n(s.end)),l.terminator_end=d(s.end)||"",s.endsWithParent&&o.terminator_end&&(l.terminator_end+=(s.end?"|":"")+o.terminator_end)),s.illegal&&(l.illegalRe=n(s.illegal)),void 0===s.relevance&&(s.relevance=1),s.contains||(s.contains=[]),s.contains=[].concat(...s.contains.map((function(e){return function(e){return e.variants&&!e.cached_variants&&(e.cached_variants=e.variants.map((function(n){return r(e,{variants:null},n)}))),e.cached_variants?e.cached_variants:function e(n){return!!n&&(n.endsWithParent||e(n.starts))}(e)?r(e,{starts:e.starts?r(e.starts):null}):Object.isFrozen(e)?r(e):e}("self"===e?s:e)}))),s.contains.forEach((function(e){t(e,l)})),s.starts&&t(s.starts,o),l.matcher=function(e){const n=new a;return e.contains.forEach(e=>n.addRule(e.begin,{rule:e,type:"begin"})),e.terminator_end&&n.addRule(e.terminator_end,{type:"end"}),e.illegal&&n.addRule(e.illegal,{type:"illegal"}),n}(l),l}(e)}(E),N="",y=s||_,O={},k=new f.__emitter(f);!function(){for(var e=[],n=y;n!==E;n=n.parent)n.className&&e.unshift(n.className);e.forEach(e=>k.openNode(e))}();var A="",I=0,S=0,B=0,L=!1;try{for(y.matcher.considerAll();;){B++,L?L=!1:(y.matcher.lastIndex=S,y.matcher.considerAll());const e=y.matcher.exec(o);if(!e)break;const n=x(o.substring(S,e.index),e);S=e.index+n}return x(o.substr(S)),k.closeAllNodes(),k.finalize(),N=k.toHTML(),{relevance:I,value:N,language:e,illegal:!1,emitter:k,top:y}}catch(n){if(n.message&&n.message.includes("Illegal"))return{illegal:!0,illegalBy:{msg:n.message,context:o.slice(S-100,S+100),mode:n.mode},sofar:N,relevance:0,value:R(o),emitter:k};if(l)return{illegal:!1,relevance:0,value:R(o),emitter:k,language:e,top:y,errorRaised:n};throw n}}function v(e,n){n=n||f.languages||Object.keys(i);var t=function(e){const n={relevance:0,emitter:new f.__emitter(f),value:R(e),illegal:!1,top:h};return n.emitter.addText(e),n}(e),r=t;return n.filter(T).filter(I).forEach((function(n){var a=m(n,e,!1);a.language=n,a.relevance>r.relevance&&(r=a),a.relevance>t.relevance&&(r=t,t=a)})),r.language&&(t.second_best=r),t}function x(e){return f.tabReplace||f.useBR?e.replace(c,e=>"\n"===e?f.useBR?"
":e:f.tabReplace?e.replace(/\t/g,f.tabReplace):e):e}function E(e){let n=null;const t=function(e){var n=e.className+" ";n+=e.parentNode?e.parentNode.className:"";const t=f.languageDetectRe.exec(n);if(t){var r=T(t[1]);return r||(console.warn(g.replace("{}",t[1])),console.warn("Falling back to no-highlight mode for this block.",e)),r?t[1]:"no-highlight"}return n.split(/\s+/).find(e=>p(e)||T(e))}(e);if(p(t))return;S("before:highlightBlock",{block:e,language:t}),f.useBR?(n=document.createElement("div")).innerHTML=e.innerHTML.replace(/\n/g,"").replace(//g,"\n"):n=e;const r=n.textContent,a=t?b(t,r,!0):v(r),i=O(n);if(i.length){const e=document.createElement("div");e.innerHTML=a.value,a.value=k(i,O(e),r)}a.value=x(a.value),S("after:highlightBlock",{block:e,result:a}),e.innerHTML=a.value,e.className=function(e,n,t){var r=n?s[n]:t,a=[e.trim()];return e.match(/\bhljs\b/)||a.push("hljs"),e.includes(r)||a.push(r),a.join(" ").trim()}(e.className,t,a.language),e.result={language:a.language,re:a.relevance,relavance:a.relevance},a.second_best&&(e.second_best={language:a.second_best.language,re:a.second_best.relevance,relavance:a.second_best.relevance})}const N=()=>{if(!N.called){N.called=!0;var e=document.querySelectorAll("pre code");a.forEach.call(e,E)}};function T(e){return e=(e||"").toLowerCase(),i[e]||i[s[e]]}function A(e,{languageName:n}){"string"==typeof e&&(e=[e]),e.forEach(e=>{s[e]=n})}function I(e){var n=T(e);return n&&!n.disableAutodetect}function S(e,n){var t=e;o.forEach((function(e){e[t]&&e[t](n)}))}Object.assign(t,{highlight:b,highlightAuto:v,fixMarkup:x,highlightBlock:E,configure:function(e){f=y(f,e)},initHighlighting:N,initHighlightingOnLoad:function(){window.addEventListener("DOMContentLoaded",N,!1)},registerLanguage:function(e,n){var r=null;try{r=n(t)}catch(n){if(console.error("Language definition for '{}' could not be registered.".replace("{}",e)),!l)throw n;console.error(n),r=h}r.name||(r.name=e),i[e]=r,r.rawDefinition=n.bind(null,t),r.aliases&&A(r.aliases,{languageName:e})},listLanguages:function(){return Object.keys(i)},getLanguage:T,registerAliases:A,requireLanguage:function(e){var n=T(e);if(n)return n;throw Error("The '{}' language is required, but not loaded.".replace("{}",e))},autoDetection:I,inherit:y,addPlugin:function(e){o.push(e)}}),t.debugMode=function(){l=!1},t.safeMode=function(){l=!0},t.versionString="10.1.2";for(const n in _)"object"==typeof _[n]&&e(_[n]);return Object.assign(t,_),t}({})}();"object"==typeof exports&&"undefined"!=typeof module&&(module.exports=hljs);hljs.registerLanguage("xml",function(){"use strict";return function(e){var n={className:"symbol",begin:"&[a-z]+;|&#[0-9]+;|&#x[a-f0-9]+;"},a={begin:"\\s",contains:[{className:"meta-keyword",begin:"#?[a-z_][a-z1-9_-]+",illegal:"\\n"}]},s=e.inherit(a,{begin:"\\(",end:"\\)"}),t=e.inherit(e.APOS_STRING_MODE,{className:"meta-string"}),i=e.inherit(e.QUOTE_STRING_MODE,{className:"meta-string"}),c={endsWithParent:!0,illegal:/`]+/}]}]}]};return{name:"HTML, XML",aliases:["html","xhtml","rss","atom","xjb","xsd","xsl","plist","wsf","svg"],case_insensitive:!0,contains:[{className:"meta",begin:"",relevance:10,contains:[a,i,t,s,{begin:"\\[",end:"\\]",contains:[{className:"meta",begin:"",contains:[a,s,i,t]}]}]},e.COMMENT("\x3c!--","--\x3e",{relevance:10}),{begin:"<\\!\\[CDATA\\[",end:"\\]\\]>",relevance:10},n,{className:"meta",begin:/<\?xml/,end:/\?>/,relevance:10},{className:"tag",begin:")",end:">",keywords:{name:"style"},contains:[c],starts:{end:"",returnEnd:!0,subLanguage:["css","xml"]}},{className:"tag",begin:")",end:">",keywords:{name:"script"},contains:[c],starts:{end:"<\/script>",returnEnd:!0,subLanguage:["javascript","handlebars","xml"]}},{className:"tag",begin:"",contains:[{className:"name",begin:/[^\/><\s]+/,relevance:0},c]}]}}}());hljs.registerLanguage("markdown",function(){"use strict";return function(n){const e={begin:"<",end:">",subLanguage:"xml",relevance:0},a={begin:"\\[.+?\\][\\(\\[].*?[\\)\\]]",returnBegin:!0,contains:[{className:"string",begin:"\\[",end:"\\]",excludeBegin:!0,returnEnd:!0,relevance:0},{className:"link",begin:"\\]\\(",end:"\\)",excludeBegin:!0,excludeEnd:!0},{className:"symbol",begin:"\\]\\[",end:"\\]",excludeBegin:!0,excludeEnd:!0}],relevance:10},i={className:"strong",contains:[],variants:[{begin:/_{2}/,end:/_{2}/},{begin:/\*{2}/,end:/\*{2}/}]},s={className:"emphasis",contains:[],variants:[{begin:/\*(?!\*)/,end:/\*/},{begin:/_(?!_)/,end:/_/,relevance:0}]};i.contains.push(s),s.contains.push(i);var c=[e,a];return i.contains=i.contains.concat(c),s.contains=s.contains.concat(c),{name:"Markdown",aliases:["md","mkdown","mkd"],contains:[{className:"section",variants:[{begin:"^#{1,6}",end:"$",contains:c=c.concat(i,s)},{begin:"(?=^.+?\\n[=-]{2,}$)",contains:[{begin:"^[=-]*$"},{begin:"^",end:"\\n",contains:c}]}]},e,{className:"bullet",begin:"^[ \t]*([*+-]|(\\d+\\.))(?=\\s+)",end:"\\s+",excludeEnd:!0},i,s,{className:"quote",begin:"^>\\s+",contains:c,end:"$"},{className:"code",variants:[{begin:"(`{3,})(.|\\n)*?\\1`*[ ]*"},{begin:"(~{3,})(.|\\n)*?\\1~*[ ]*"},{begin:"```",end:"```+[ ]*$"},{begin:"~~~",end:"~~~+[ ]*$"},{begin:"`.+?`"},{begin:"(?=^( {4}|\\t))",contains:[{begin:"^( {4}|\\t)",end:"(\\n)$"}],relevance:0}]},{begin:"^[-\\*]{3,}",end:"$"},a,{begin:/^\[[^\n]+\]:/,returnBegin:!0,contains:[{className:"symbol",begin:/\[/,end:/\]/,excludeBegin:!0,excludeEnd:!0},{className:"link",begin:/:\s*/,end:/$/,excludeBegin:!0}]}]}}}());hljs.registerLanguage("perl",function(){"use strict";return function(e){var n={$pattern:/[\w.]+/,keyword:"getpwent getservent quotemeta msgrcv scalar kill dbmclose undef lc ma syswrite tr send umask sysopen shmwrite vec qx utime local oct semctl localtime readpipe do return format read sprintf dbmopen pop getpgrp not getpwnam rewinddir qq fileno qw endprotoent wait sethostent bless s|0 opendir continue each sleep endgrent shutdown dump chomp connect getsockname die socketpair close flock exists index shmget sub for endpwent redo lstat msgctl setpgrp abs exit select print ref gethostbyaddr unshift fcntl syscall goto getnetbyaddr join gmtime symlink semget splice x|0 getpeername recv log setsockopt cos last reverse gethostbyname getgrnam study formline endhostent times chop length gethostent getnetent pack getprotoent getservbyname rand mkdir pos chmod y|0 substr endnetent printf next open msgsnd readdir use unlink getsockopt getpriority rindex wantarray hex system getservbyport endservent int chr untie rmdir prototype tell listen fork shmread ucfirst setprotoent else sysseek link getgrgid shmctl waitpid unpack getnetbyname reset chdir grep split require caller lcfirst until warn while values shift telldir getpwuid my getprotobynumber delete and sort uc defined srand accept package seekdir getprotobyname semop our rename seek if q|0 chroot sysread setpwent no crypt getc chown sqrt write setnetent setpriority foreach tie sin msgget map stat getlogin unless elsif truncate exec keys glob tied closedir ioctl socket readlink eval xor readline binmode setservent eof ord bind alarm pipe atan2 getgrent exp time push setgrent gt lt or ne m|0 break given say state when"},t={className:"subst",begin:"[$@]\\{",end:"\\}",keywords:n},s={begin:"->{",end:"}"},r={variants:[{begin:/\$\d/},{begin:/[\$%@](\^\w\b|#\w+(::\w+)*|{\w+}|\w+(::\w*)*)/},{begin:/[\$%@][^\s\w{]/,relevance:0}]},i=[e.BACKSLASH_ESCAPE,t,r],a=[r,e.HASH_COMMENT_MODE,e.COMMENT("^\\=\\w","\\=cut",{endsWithParent:!0}),s,{className:"string",contains:i,variants:[{begin:"q[qwxr]?\\s*\\(",end:"\\)",relevance:5},{begin:"q[qwxr]?\\s*\\[",end:"\\]",relevance:5},{begin:"q[qwxr]?\\s*\\{",end:"\\}",relevance:5},{begin:"q[qwxr]?\\s*\\|",end:"\\|",relevance:5},{begin:"q[qwxr]?\\s*\\<",end:"\\>",relevance:5},{begin:"qw\\s+q",end:"q",relevance:5},{begin:"'",end:"'",contains:[e.BACKSLASH_ESCAPE]},{begin:'"',end:'"'},{begin:"`",end:"`",contains:[e.BACKSLASH_ESCAPE]},{begin:"{\\w+}",contains:[],relevance:0},{begin:"-?\\w+\\s*\\=\\>",contains:[],relevance:0}]},{className:"number",begin:"(\\b0[0-7_]+)|(\\b0x[0-9a-fA-F_]+)|(\\b[1-9][0-9_]*(\\.[0-9_]+)?)|[0_]\\b",relevance:0},{begin:"(\\/\\/|"+e.RE_STARTERS_RE+"|\\b(split|return|print|reverse|grep)\\b)\\s*",keywords:"split return print reverse grep",relevance:0,contains:[e.HASH_COMMENT_MODE,{className:"regexp",begin:"(s|tr|y)/(\\\\.|[^/])*/(\\\\.|[^/])*/[a-z]*",relevance:10},{className:"regexp",begin:"(m|qr)?/",end:"/[a-z]*",contains:[e.BACKSLASH_ESCAPE],relevance:0}]},{className:"function",beginKeywords:"sub",end:"(\\s*\\(.*?\\))?[;{]",excludeEnd:!0,relevance:5,contains:[e.TITLE_MODE]},{begin:"-\\w\\b",relevance:0},{begin:"^__DATA__$",end:"^__END__$",subLanguage:"mojolicious",contains:[{begin:"^@@.*",end:"$",className:"comment"}]}];return t.contains=a,s.contains=a,{name:"Perl",aliases:["pl","pm"],keywords:n,contains:a}}}());hljs.registerLanguage("plaintext",function(){"use strict";return function(t){return{name:"Plain text",aliases:["text","txt"],disableAutodetect:!0}}}());hljs.registerLanguage("ini",function(){"use strict";function e(e){return e?"string"==typeof e?e:e.source:null}function n(...n){return n.map(n=>e(n)).join("")}return function(a){var s={className:"number",relevance:0,variants:[{begin:/([\+\-]+)?[\d]+_[\d_]+/},{begin:a.NUMBER_RE}]},i=a.COMMENT();i.variants=[{begin:/;/,end:/$/},{begin:/#/,end:/$/}];var t={className:"variable",variants:[{begin:/\$[\w\d"][\w\d_]*/},{begin:/\$\{(.*?)}/}]},r={className:"literal",begin:/\bon|off|true|false|yes|no\b/},l={className:"string",contains:[a.BACKSLASH_ESCAPE],variants:[{begin:"'''",end:"'''",relevance:10},{begin:'"""',end:'"""',relevance:10},{begin:'"',end:'"'},{begin:"'",end:"'"}]},c={begin:/\[/,end:/\]/,contains:[i,r,t,l,s,"self"],relevance:0},g="("+[/[A-Za-z0-9_-]+/,/"(\\"|[^"])*"/,/'[^']*'/].map(n=>e(n)).join("|")+")";return{name:"TOML, also INI",aliases:["toml"],case_insensitive:!0,illegal:/\S/,contains:[i,{className:"section",begin:/\[+/,end:/\]+/},{begin:n(g,"(\\s*\\.\\s*",g,")*",n("(?=",/\s*=\s*[^#\s]/,")")),className:"attr",starts:{end:/$/,contains:[i,c,r,t,l,s]}}]}}}());hljs.registerLanguage("json",function(){"use strict";return function(n){var e={literal:"true false null"},i=[n.C_LINE_COMMENT_MODE,n.C_BLOCK_COMMENT_MODE],t=[n.QUOTE_STRING_MODE,n.C_NUMBER_MODE],a={end:",",endsWithParent:!0,excludeEnd:!0,contains:t,keywords:e},l={begin:"{",end:"}",contains:[{className:"attr",begin:/"/,end:/"/,contains:[n.BACKSLASH_ESCAPE],illegal:"\\n"},n.inherit(a,{begin:/:/})].concat(i),illegal:"\\S"},s={begin:"\\[",end:"\\]",contains:[n.inherit(a)],illegal:"\\S"};return t.push(l,s),i.forEach((function(n){t.push(n)})),{name:"JSON",contains:t,keywords:e,illegal:"\\S"}}}());hljs.registerLanguage("ruby",function(){"use strict";return function(e){var n="[a-zA-Z_]\\w*[!?=]?|[-+~]\\@|<<|>>|=~|===?|<=>|[<>]=?|\\*\\*|[-/+%^&*~`|]|\\[\\]=?",a={keyword:"and then defined module in return redo if BEGIN retry end for self when next until do begin unless END rescue else break undef not super class case require yield alias while ensure elsif or include attr_reader attr_writer attr_accessor",literal:"true false nil"},s={className:"doctag",begin:"@[A-Za-z]+"},i={begin:"#<",end:">"},r=[e.COMMENT("#","$",{contains:[s]}),e.COMMENT("^\\=begin","^\\=end",{contains:[s],relevance:10}),e.COMMENT("^__END__","\\n$")],c={className:"subst",begin:"#\\{",end:"}",keywords:a},t={className:"string",contains:[e.BACKSLASH_ESCAPE,c],variants:[{begin:/'/,end:/'/},{begin:/"/,end:/"/},{begin:/`/,end:/`/},{begin:"%[qQwWx]?\\(",end:"\\)"},{begin:"%[qQwWx]?\\[",end:"\\]"},{begin:"%[qQwWx]?{",end:"}"},{begin:"%[qQwWx]?<",end:">"},{begin:"%[qQwWx]?/",end:"/"},{begin:"%[qQwWx]?%",end:"%"},{begin:"%[qQwWx]?-",end:"-"},{begin:"%[qQwWx]?\\|",end:"\\|"},{begin:/\B\?(\\\d{1,3}|\\x[A-Fa-f0-9]{1,2}|\\u[A-Fa-f0-9]{4}|\\?\S)\b/},{begin:/<<[-~]?'?(\w+)(?:.|\n)*?\n\s*\1\b/,returnBegin:!0,contains:[{begin:/<<[-~]?'?/},e.END_SAME_AS_BEGIN({begin:/(\w+)/,end:/(\w+)/,contains:[e.BACKSLASH_ESCAPE,c]})]}]},b={className:"params",begin:"\\(",end:"\\)",endsParent:!0,keywords:a},d=[t,i,{className:"class",beginKeywords:"class module",end:"$|;",illegal:/=/,contains:[e.inherit(e.TITLE_MODE,{begin:"[A-Za-z_]\\w*(::\\w+)*(\\?|\\!)?"}),{begin:"<\\s*",contains:[{begin:"("+e.IDENT_RE+"::)?"+e.IDENT_RE}]}].concat(r)},{className:"function",beginKeywords:"def",end:"$|;",contains:[e.inherit(e.TITLE_MODE,{begin:n}),b].concat(r)},{begin:e.IDENT_RE+"::"},{className:"symbol",begin:e.UNDERSCORE_IDENT_RE+"(\\!|\\?)?:",relevance:0},{className:"symbol",begin:":(?!\\s)",contains:[t,{begin:n}],relevance:0},{className:"number",begin:"(\\b0[0-7_]+)|(\\b0x[0-9a-fA-F_]+)|(\\b[1-9][0-9_]*(\\.[0-9_]+)?)|[0_]\\b",relevance:0},{begin:"(\\$\\W)|((\\$|\\@\\@?)(\\w+))"},{className:"params",begin:/\|/,end:/\|/,keywords:a},{begin:"("+e.RE_STARTERS_RE+"|unless)\\s*",keywords:"unless",contains:[i,{className:"regexp",contains:[e.BACKSLASH_ESCAPE,c],illegal:/\n/,variants:[{begin:"/",end:"/[a-z]*"},{begin:"%r{",end:"}[a-z]*"},{begin:"%r\\(",end:"\\)[a-z]*"},{begin:"%r!",end:"![a-z]*"},{begin:"%r\\[",end:"\\][a-z]*"}]}].concat(r),relevance:0}].concat(r);c.contains=d,b.contains=d;var g=[{begin:/^\s*=>/,starts:{end:"$",contains:d}},{className:"meta",begin:"^([>?]>|[\\w#]+\\(\\w+\\):\\d+:\\d+>|(\\w+-)?\\d+\\.\\d+\\.\\d(p\\d+)?[^>]+>)",starts:{end:"$",contains:d}}];return{name:"Ruby",aliases:["rb","gemspec","podspec","thor","irb"],keywords:a,illegal:/\/\*/,contains:r.concat(g).concat(d)}}}());hljs.registerLanguage("yaml",function(){"use strict";return function(e){var n="true false yes no null",a="[\\w#;/?:@&=+$,.~*\\'()[\\]]+",s={className:"string",relevance:0,variants:[{begin:/'/,end:/'/},{begin:/"/,end:/"/},{begin:/\S+/}],contains:[e.BACKSLASH_ESCAPE,{className:"template-variable",variants:[{begin:"{{",end:"}}"},{begin:"%{",end:"}"}]}]},i=e.inherit(s,{variants:[{begin:/'/,end:/'/},{begin:/"/,end:/"/},{begin:/[^\s,{}[\]]+/}]}),l={end:",",endsWithParent:!0,excludeEnd:!0,contains:[],keywords:n,relevance:0},t={begin:"{",end:"}",contains:[l],illegal:"\\n",relevance:0},g={begin:"\\[",end:"\\]",contains:[l],illegal:"\\n",relevance:0},b=[{className:"attr",variants:[{begin:"\\w[\\w :\\/.-]*:(?=[ \t]|$)"},{begin:'"\\w[\\w :\\/.-]*":(?=[ \t]|$)'},{begin:"'\\w[\\w :\\/.-]*':(?=[ \t]|$)"}]},{className:"meta",begin:"^---s*$",relevance:10},{className:"string",begin:"[\\|>]([0-9]?[+-])?[ ]*\\n( *)[\\S ]+\\n(\\2[\\S ]+\\n?)*"},{begin:"<%[%=-]?",end:"[%-]?%>",subLanguage:"ruby",excludeBegin:!0,excludeEnd:!0,relevance:0},{className:"type",begin:"!\\w+!"+a},{className:"type",begin:"!<"+a+">"},{className:"type",begin:"!"+a},{className:"type",begin:"!!"+a},{className:"meta",begin:"&"+e.UNDERSCORE_IDENT_RE+"$"},{className:"meta",begin:"\\*"+e.UNDERSCORE_IDENT_RE+"$"},{className:"bullet",begin:"\\-(?=[ ]|$)",relevance:0},e.HASH_COMMENT_MODE,{beginKeywords:n,keywords:{literal:n}},{className:"number",begin:"\\b[0-9]{4}(-[0-9][0-9]){0,2}([Tt \\t][0-9][0-9]?(:[0-9][0-9]){2})?(\\.[0-9]*)?([ \\t])*(Z|[-+][0-9][0-9]?(:[0-9][0-9])?)?\\b"},{className:"number",begin:e.C_NUMBER_RE+"\\b"},t,g,s],c=[...b];return c.pop(),c.push(i),l.contains=c,{name:"YAML",case_insensitive:!0,aliases:["yml","YAML"],contains:b}}}());hljs.registerLanguage("haskell",function(){"use strict";return function(e){var n={variants:[e.COMMENT("--","$"),e.COMMENT("{-","-}",{contains:["self"]})]},i={className:"meta",begin:"{-#",end:"#-}"},a={className:"meta",begin:"^#",end:"$"},s={className:"type",begin:"\\b[A-Z][\\w']*",relevance:0},l={begin:"\\(",end:"\\)",illegal:'"',contains:[i,a,{className:"type",begin:"\\b[A-Z][\\w]*(\\((\\.\\.|,|\\w+)\\))?"},e.inherit(e.TITLE_MODE,{begin:"[_a-z][\\w']*"}),n]};return{name:"Haskell",aliases:["hs"],keywords:"let in if then else case of where do module import hiding qualified type data newtype deriving class instance as default infix infixl infixr foreign export ccall stdcall cplusplus jvm dotnet safe unsafe family forall mdo proc rec",contains:[{beginKeywords:"module",end:"where",keywords:"module where",contains:[l,n],illegal:"\\W\\.|;"},{begin:"\\bimport\\b",end:"$",keywords:"import qualified as hiding",contains:[l,n],illegal:"\\W\\.|;"},{className:"class",begin:"^(\\s*)?(class|instance)\\b",end:"where",keywords:"class family instance where",contains:[s,l,n]},{className:"class",begin:"\\b(data|(new)?type)\\b",end:"$",keywords:"data family type newtype deriving",contains:[i,s,l,{begin:"{",end:"}",contains:l.contains},n]},{beginKeywords:"default",end:"$",contains:[s,l,n]},{beginKeywords:"infix infixl infixr",end:"$",contains:[e.C_NUMBER_MODE,n]},{begin:"\\bforeign\\b",end:"$",keywords:"foreign import export ccall stdcall cplusplus jvm dotnet safe unsafe",contains:[s,e.QUOTE_STRING_MODE,n]},{className:"meta",begin:"#!\\/usr\\/bin\\/env runhaskell",end:"$"},i,a,e.QUOTE_STRING_MODE,e.C_NUMBER_MODE,s,e.inherit(e.TITLE_MODE,{begin:"^[_a-z][\\w']*"}),n,{begin:"->|<-"}]}}}());hljs.registerLanguage("nix",function(){"use strict";return function(e){var n={keyword:"rec with let in inherit assert if else then",literal:"true false or and null",built_in:"import abort baseNameOf dirOf isNull builtins map removeAttrs throw toString derivation"},i={className:"subst",begin:/\$\{/,end:/}/,keywords:n},t={className:"string",contains:[i],variants:[{begin:"''",end:"''"},{begin:'"',end:'"'}]},s=[e.NUMBER_MODE,e.HASH_COMMENT_MODE,e.C_BLOCK_COMMENT_MODE,t,{begin:/[a-zA-Z0-9-_]+(\s*=)/,returnBegin:!0,relevance:0,contains:[{className:"attr",begin:/\S+/}]}];return i.contains=s,{name:"Nix",aliases:["nixos"],keywords:n,contains:s}}}());hljs.registerLanguage("bash",function(){"use strict";return function(e){const s={};Object.assign(s,{className:"variable",variants:[{begin:/\$[\w\d#@][\w\d_]*/},{begin:/\$\{/,end:/\}/,contains:[{begin:/:-/,contains:[s]}]}]});const t={className:"subst",begin:/\$\(/,end:/\)/,contains:[e.BACKSLASH_ESCAPE]},n={className:"string",begin:/"/,end:/"/,contains:[e.BACKSLASH_ESCAPE,s,t]};t.contains.push(n);const a={begin:/\$\(\(/,end:/\)\)/,contains:[{begin:/\d+#[0-9a-f]+/,className:"number"},e.NUMBER_MODE,s]},i=e.SHEBANG({binary:"(fish|bash|zsh|sh|csh|ksh|tcsh|dash|scsh)",relevance:10}),c={className:"function",begin:/\w[\w\d_]*\s*\(\s*\)\s*\{/,returnBegin:!0,contains:[e.inherit(e.TITLE_MODE,{begin:/\w[\w\d_]*/})],relevance:0};return{name:"Bash",aliases:["sh","zsh"],keywords:{$pattern:/\b-?[a-z\._]+\b/,keyword:"if then else elif fi for while in do done case esac function",literal:"true false",built_in:"break cd continue eval exec exit export getopts hash pwd readonly return shift test times trap umask unset alias bind builtin caller command declare echo enable help let local logout mapfile printf read readarray source type typeset ulimit unalias set shopt autoload bg bindkey bye cap chdir clone comparguments compcall compctl compdescribe compfiles compgroups compquote comptags comptry compvalues dirs disable disown echotc echoti emulate fc fg float functions getcap getln history integer jobs kill limit log noglob popd print pushd pushln rehash sched setcap setopt stat suspend ttyctl unfunction unhash unlimit unsetopt vared wait whence where which zcompile zformat zftp zle zmodload zparseopts zprof zpty zregexparse zsocket zstyle ztcp",_:"-ne -eq -lt -gt -f -d -e -s -l -a"},contains:[i,e.SHEBANG(),c,a,e.HASH_COMMENT_MODE,n,{className:"",begin:/\\"/},{className:"string",begin:/'/,end:/'/},s]}}}());hljs.registerLanguage("shell",function(){"use strict";return function(s){return{name:"Shell Session",aliases:["console"],contains:[{className:"meta",begin:"^\\s{0,3}[/\\w\\d\\[\\]()@-]*[>%$#]",starts:{end:"$",subLanguage:"bash"}}]}}}());hljs.registerLanguage("python",function(){"use strict";return function(e){var n={keyword:"and elif is global as in if from raise for except finally print import pass return exec else break not with class assert yield try while continue del or def lambda async await nonlocal|10",built_in:"Ellipsis NotImplemented",literal:"False None True"},a={className:"meta",begin:/^(>>>|\.\.\.) /},i={className:"subst",begin:/\{/,end:/\}/,keywords:n,illegal:/#/},s={begin:/\{\{/,relevance:0},r={className:"string",contains:[e.BACKSLASH_ESCAPE],variants:[{begin:/(u|b)?r?'''/,end:/'''/,contains:[e.BACKSLASH_ESCAPE,a],relevance:10},{begin:/(u|b)?r?"""/,end:/"""/,contains:[e.BACKSLASH_ESCAPE,a],relevance:10},{begin:/(fr|rf|f)'''/,end:/'''/,contains:[e.BACKSLASH_ESCAPE,a,s,i]},{begin:/(fr|rf|f)"""/,end:/"""/,contains:[e.BACKSLASH_ESCAPE,a,s,i]},{begin:/(u|r|ur)'/,end:/'/,relevance:10},{begin:/(u|r|ur)"/,end:/"/,relevance:10},{begin:/(b|br)'/,end:/'/},{begin:/(b|br)"/,end:/"/},{begin:/(fr|rf|f)'/,end:/'/,contains:[e.BACKSLASH_ESCAPE,s,i]},{begin:/(fr|rf|f)"/,end:/"/,contains:[e.BACKSLASH_ESCAPE,s,i]},e.APOS_STRING_MODE,e.QUOTE_STRING_MODE]},l={className:"number",relevance:0,variants:[{begin:e.BINARY_NUMBER_RE+"[lLjJ]?"},{begin:"\\b(0o[0-7]+)[lLjJ]?"},{begin:e.C_NUMBER_RE+"[lLjJ]?"}]},t={className:"params",variants:[{begin:/\(\s*\)/,skip:!0,className:null},{begin:/\(/,end:/\)/,excludeBegin:!0,excludeEnd:!0,contains:["self",a,l,r,e.HASH_COMMENT_MODE]}]};return i.contains=[r,l,a],{name:"Python",aliases:["py","gyp","ipython"],keywords:n,illegal:/(<\/|->|\?)|=>/,contains:[a,l,{beginKeywords:"if",relevance:0},r,e.HASH_COMMENT_MODE,{variants:[{className:"function",beginKeywords:"def"},{className:"class",beginKeywords:"class"}],end:/:/,illegal:/[${=;\n,]/,contains:[e.UNDERSCORE_TITLE_MODE,t,{begin:/->/,endsWithParent:!0,keywords:"None"}]},{className:"meta",begin:/^[\t ]*@/,end:/$/},{begin:/\b(print|exec)\(/}]}}}()); From b9bcbab130db0feee3b74889c666e10d3b8ac6b4 Mon Sep 17 00:00:00 2001 From: Timothy DeHerrera Date: Sun, 14 Feb 2021 17:44:34 -0700 Subject: [PATCH 4/4] workflows: prepare for merge --- .github/workflows/mdbook_docs.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/mdbook_docs.yml b/.github/workflows/mdbook_docs.yml index 775d52c8..0bc7480f 100644 --- a/.github/workflows/mdbook_docs.yml +++ b/.github/workflows/mdbook_docs.yml @@ -3,7 +3,7 @@ name: Deploy Docs to GitHub Pages on: push: branches: - - doc + - core jobs: deploy: