411 lines
11 KiB
HTML
411 lines
11 KiB
HTML
<!DOCTYPE html>
|
||
<html lang="en">
|
||
<head>
|
||
<meta charset="UTF-8" />
|
||
<title>NixCon 2023 slides</title>
|
||
<meta
|
||
name="viewport"
|
||
content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no"
|
||
/>
|
||
<link rel="stylesheet" href="node_modules/reveal.js/dist/reset.css" />
|
||
<link rel="stylesheet" href="node_modules/reveal.js/dist/reveal.css" />
|
||
<link
|
||
rel="stylesheet"
|
||
href="node_modules/reveal.js/dist/theme/black.css"
|
||
/>
|
||
<link rel="stylesheet" href="styles.css" />
|
||
<link
|
||
rel="stylesheet"
|
||
href="node_modules/reveal.js/plugin/highlight/monokai.css"
|
||
/>
|
||
<script type="importmap">
|
||
{
|
||
"imports": {
|
||
"reveal.js": "./node_modules/reveal.js/dist/reveal.esm.js",
|
||
"reveal.js/": "./node_modules/reveal.js/",
|
||
"reveal.js/plugin/markdown": "./node_modules/reveal.js/plugin/markdown/markdown.esm.js",
|
||
"reveal.js/plugin/highlight": "./node_modules/reveal.js/plugin/highlight/highlight.esm.js",
|
||
"reveal.js/plugin/notes": "./node_modules/reveal.js/plugin/notes/notes.esm.js"
|
||
}
|
||
}
|
||
</script>
|
||
</head>
|
||
<body>
|
||
<div class="reveal">
|
||
<div class="slides">
|
||
<section class="title-slide">
|
||
<h1>Finding things in nixpkgs and NixOS source</h1>
|
||
|
||
<div class="meta">
|
||
<p>
|
||
Jade Lovelace <jade at jade dot fyi>
|
||
</p>
|
||
<p>
|
||
Get the slides at <a href="https://jade.fyi/nixcon2023/slides">https://jade.fyi/nixcon2023/slides</a>
|
||
</div>
|
||
</section>
|
||
|
||
|
||
<section data-markdown><textarea data-template>
|
||
# whoami
|
||
|
||
* Author of nix-doc (not to be confused with nixdoc)
|
||
* Most involved in Nix for Haskell and Rust packaging
|
||
* I use NixOS as a dev workstation and server
|
||
</textarea>
|
||
</section>
|
||
|
||
<section data-markdown><textarea data-template>
|
||
# the sources are for everyone
|
||
|
||
* We *do* need to improve our documentation
|
||
* Nix is uniquely participatory: a *lot* of us write modules and packages, which means reading sources
|
||
* Navigating the source is a bit of witchcraft, and there's a lot of it
|
||
* With good tooling, the sources of the docs sometimes are faster than the docs
|
||
* We should have more interactive docs!
|
||
</textarea>
|
||
</section>
|
||
|
||
<section data-markdown><textarea data-template>
|
||
# motivation (2.94 million lines of it)
|
||
|
||
<pre><code class="text"><script type="text/template">
|
||
dev/nixpkgs » tokei -t nix .
|
||
=======================================
|
||
Language Files Lines
|
||
=======================================
|
||
Nix 30400 2941526
|
||
=======================================
|
||
Total 30400 2941526
|
||
=======================================
|
||
</script></code></pre>
|
||
</textarea></section>
|
||
|
||
<section data-markdown><textarea data-template>
|
||
# roadmap
|
||
|
||
* nix
|
||
* static analysis
|
||
* nixd
|
||
* ctags
|
||
* dynamic analysis
|
||
* using the repl
|
||
* using nix-doc
|
||
* nixos
|
||
* ctags
|
||
* repl usage
|
||
</textarea>
|
||
</section>
|
||
|
||
|
||
<section data-markdown><textarea data-template>
|
||
# Static analysis
|
||
|
||
* Any method that takes 15 seconds or less and doesn't involve running any code
|
||
* First way to try:
|
||
* Extremely fast
|
||
* Objective: "works most of the time"
|
||
* I am showing the fancy ways of doing it here
|
||
* ripgrep is static analysis too
|
||
* Objective of fancy ways: faster and less stuff to sort through
|
||
</textarea>
|
||
</section>
|
||
|
||
<section data-markdown><textarea data-template>
|
||
# nixd
|
||
|
||
Newish language server, using Nix as a library. In nixpkgs as `nixd`.
|
||
|
||
Good for:
|
||
* need go-to-definition
|
||
* interactive help writing nix code
|
||
|
||
Limitations:
|
||
* does not eval everything
|
||
* needs some setup per-project
|
||
* imperfect go-to-definition
|
||
</textarea>
|
||
</section>
|
||
|
||
<section data-markdown><textarea data-template>
|
||
# nixd setup
|
||
|
||
Install from nixpkgs and configure in your editor. Then:
|
||
|
||
`.nixd.json`:
|
||
|
||
<pre><code class="json"><script type="text/template">
|
||
{
|
||
"eval": {
|
||
"target": {
|
||
"args": [
|
||
"--expr",
|
||
"with import ./. {}; nix-doc"
|
||
]
|
||
}
|
||
}
|
||
}
|
||
</script></code></pre>
|
||
</textarea>
|
||
</section>
|
||
|
||
<section class="video" data-markdown><textarea data-template>
|
||
# demo (nixd)
|
||
|
||
<video class="r-stretch" src="./nixd.mp4" controls>
|
||
</textarea>
|
||
</section>
|
||
|
||
<section data-markdown><textarea data-template>
|
||
# ctags
|
||
|
||
* Very old and simple source code index format
|
||
* Usually gets through abstraction by being too naive to get broken
|
||
* Typically generated by simple parse-tree traversal
|
||
* Wide editor support ([VSCode extension](https://marketplace.visualstudio.com/items?itemName=jaydenlin.ctags-support); also built into vim/emacs)
|
||
|
||
Sample:
|
||
|
||
```text
|
||
boot.initrd.luks.reusePassphrases nixos/modules/system/boot/luksroot.nix 533
|
||
```
|
||
</textarea>
|
||
</section>
|
||
|
||
|
||
<section data-markdown><textarea data-template>
|
||
# ctags on nix
|
||
|
||
* `nix-doc tags .` in nixpkgs, then in vim you can `:tj fixedPoints`, `C-]`, etc.
|
||
* [WIP ctags for NixOS options (#249243)](https://github.com/NixOS/nixpkgs/pull/249243)
|
||
</textarea>
|
||
</section>
|
||
|
||
<section class="video" data-markdown><textarea data-template>
|
||
# demo (ctags on nix)
|
||
|
||
<video class="r-stretch" src="./nix-ctags.mp4" controls>
|
||
</textarea>
|
||
</section>
|
||
|
||
<section data-markdown><textarea data-template>
|
||
# summary (static analysis)
|
||
|
||
First try language server, then ctags, then ripgrep.
|
||
</textarea>
|
||
</section>
|
||
|
||
<section data-markdown><textarea data-template>
|
||
# dynamic analysis
|
||
|
||
* Static analysis often doesn't cut it, power tools time!
|
||
* `nix repl` is your friend
|
||
</textarea>
|
||
</section>
|
||
|
||
<section data-markdown><textarea data-template>
|
||
# using the repl (nix)
|
||
|
||
* `nix repl -f .`, `nix repl -f '<nixpkgs>`
|
||
* `:lf flake-ref` (more on this later)
|
||
* `:e derivation-or-function` to open in editor
|
||
</textarea>
|
||
</section>
|
||
|
||
<section data-markdown><textarea data-template>
|
||
# getting docs in the repl
|
||
|
||
<pre><code class="text"><script type="text/template">
|
||
nix-repl> :doc builtins.head
|
||
Synopsis: builtins.head list
|
||
|
||
Return the first element of a list; abort evaluation if the argument isn’t a list or is
|
||
an empty list. You can test whether a list is empty by comparing it with [].
|
||
</script></code></pre>
|
||
</textarea>
|
||
</section>
|
||
|
||
<section data-markdown><textarea data-template>
|
||
# getting docs in the repl (ii)
|
||
|
||
<pre><code class="text"><script type="text/template">
|
||
nix-repl> :doc haskell.lib.overrideSrc
|
||
error: value does not have documentation
|
||
</script></code></pre>
|
||
|
||
Oops.
|
||
|
||
Related:
|
||
* [RFC 0145](https://github.com/NixOS/rfcs/pull/145)
|
||
* [nix#3904](https://github.com/NixOS/nix/issues/3904)
|
||
|
||
</textarea>
|
||
</section>
|
||
|
||
<section data-markdown><textarea data-template>
|
||
# nix-doc?
|
||
|
||
<pre><code class="nix"><script type="text/template">
|
||
{ pkgs, ... }: {
|
||
nix.extraOptions = ''
|
||
plugin-files = ${pkgs.nix-doc}/lib/libnix_doc_plugin.so
|
||
'';
|
||
}
|
||
</script></code></pre>
|
||
</textarea>
|
||
</section>
|
||
|
||
<section data-markdown><textarea data-template>
|
||
# using nix-doc with the repl
|
||
|
||
<pre><code class="text"><script type="text/template">
|
||
nix-repl> builtins.doc haskell.lib.overrideSrc
|
||
Override the sources for the package and optionally the version.
|
||
This also takes of removing editedCabalFile.
|
||
func = drv: src: ...
|
||
# /nix/store/wl5m5xfayd69ycyspzyd4rilfgl6wmh0-source/pkgs/development/haskell-modules/lib/default.n
|
||
ix:285
|
||
null
|
||
</script></code></pre>
|
||
</textarea>
|
||
</section>
|
||
|
||
<!--
|
||
<section data-markdown><textarea data-template>
|
||
# `builtins.unsafeGetAttrPos`
|
||
|
||
Probably the biggest dynamic analysis hammer.
|
||
|
||
<pre><code class="text"><script type="text/template">
|
||
nix-repl> builtins.doc pkgs.fetchFromGitHub
|
||
error: value is a set while a lambda was expected
|
||
|
||
nix-repl> :e pkgs.fetchFromGitHub
|
||
error: package 'fetchFromGitHub' has no source location information
|
||
|
||
nix-repl> builtins.unsafeGetAttrPos "fetchFromGitHub" pkgs
|
||
{ column = 3; file = "/nix/store/wl5m5xfayd69ycyspzyd4rilfgl6wmh0-source/pkgs/top-level/all-package
|
||
s.nix"; line = 1193; }
|
||
</script></code></pre>
|
||
</textarea>
|
||
</section>
|
||
-->
|
||
|
||
<section class="video" data-markdown><textarea data-template>
|
||
<video class="r-stretch" src="./dynamic-demo.mp4" controls>
|
||
</textarea>
|
||
</section>
|
||
|
||
<section data-markdown><textarea data-template>
|
||
# bonus: using the debugger
|
||
|
||
* pass `--debugger` to nix
|
||
* use `builtins.break (value)` somewhere in the evaluation path
|
||
* NOTE: `(v: builtins.break v) value` may get more locals
|
||
(see [nix#8827](https://github.com/NixOS/nix/issues/8827))
|
||
* then use `unsafeGetAttrPos` and others to figure out the source of a value
|
||
</textarea>
|
||
</section>
|
||
|
||
<section data-markdown><textarea data-template>
|
||
# summary (dynamic analysis)
|
||
|
||
* `:e function/package`
|
||
* \+ works pretty well
|
||
* \+ built-in
|
||
* \- issues with wrappers (e.g. `fetchFromGitHub`: `lib.makeOverridable`)
|
||
* \- doesn't help for attr sets
|
||
* `builtins.doc` (nix-doc)
|
||
* \+ concise output on functions
|
||
* \- issues with wrappers
|
||
</textarea>
|
||
</section>
|
||
|
||
<section data-markdown><textarea data-template>
|
||
# summary (dynamic analysis)
|
||
* `builtins.unsafeGetAttrPos`
|
||
* \+ gets close even with abstraction
|
||
* \- unergonomic args and return value for interactive use
|
||
</textarea>
|
||
</section>
|
||
|
||
<section data-markdown><textarea data-template>
|
||
# NixOS ctags ([PR #249243](https://github.com/NixOS/nixpkgs/pull/249243))
|
||
|
||
With the PR checked out:
|
||
|
||
<pre><code class="text"><script type="text/template">
|
||
$ nix build -f nixos/release.nix optionsCtags -o opts-tags
|
||
</script></code></pre>
|
||
</textarea>
|
||
|
||
Then add `opts-tags` to ctags search path (`:set tags+=opts-tags` in vim).
|
||
</section>
|
||
|
||
<section class="video" data-markdown><textarea data-template>
|
||
# NixOS ctags (demo)
|
||
|
||
<video class="r-stretch" src="./nixos-ctags.mp4" controls>
|
||
</textarea>
|
||
</section>
|
||
|
||
<section data-markdown><textarea data-template>
|
||
# NixOS in the repl
|
||
|
||
Getting the configuration into the repl:
|
||
|
||
* Non-flakes: `nix repl -I nixos-config=/path/to/configuration.nix -f <nixpkgs/nixos>`
|
||
* Flakes: `nix repl` then `:lf .` then `nixosConfigurations.xx.{....}`
|
||
</textarea>
|
||
</section>
|
||
|
||
<section class="video" data-markdown><textarea data-template>
|
||
# NixOS in the repl (demo)
|
||
|
||
<video class="r-stretch" src="./nixos-repl.mp4" controls>
|
||
|
||
<!--
|
||
nix-repl> config.documentation.man.generateCaches
|
||
true
|
||
|
||
nix-repl> options.documentation.man.generateCaches
|
||
{ __toString = «lambda @ /nix/store/wl5m5xfayd69ycyspzyd4rilfgl6wmh0-source/lib/modules.nix:807:22»
|
||
; _type = "option"; declarations = [ ... ]; default = false; definitions = [ ... ]; definitionsWith
|
||
Locations = [ ... ]; description = "Whether to generate the manual page index caches.\nThis allows
|
||
searching for a page or\nkeyword using utilities like {manpage}`apropos(1)`\nand the `-k` option of
|
||
\n{manpage}`man(1)`.\n"; files = [ ... ]; highestPrio = 1000; isDefined = true; loc = [ ... ]; opti
|
||
ons = [ ... ]; type = { ... }; value = true; }
|
||
|
||
nix-repl> options.documentation.man.generateCaches.definitions
|
||
[ true ]
|
||
|
||
nix-repl> options.documentation.man.generateCaches.definitionsWithLocations
|
||
[ { ... } ]
|
||
|
||
nix-repl> :p options.documentation.man.generateCaches.definitionsWithLocations
|
||
[ { file = "/nix/store/wl5m5xfayd69ycyspzyd4rilfgl6wmh0-source/nixos/modules/programs/fish.nix"; va
|
||
lue = true; } ]
|
||
-->
|
||
</textarea>
|
||
</section>
|
||
|
||
|
||
<section data-markdown><textarea data-template>
|
||
# questions?
|
||
|
||
slides: https://jade.fyi/nixcon2023
|
||
|
||
masto: @leftpaddotpy\@hachyderm.io
|
||
|
||
email: jade at jade dot fyi
|
||
|
||
code: https://github.com/LF-
|
||
|
||
github sponsors: https://github.com/sponsors/LF-
|
||
</textarea>
|
||
</section>
|
||
|
||
|
||
<script type="module" src="main.js"></script>
|
||
</body>
|
||
</html>
|