diff --git a/.envrc b/.envrc new file mode 100644 index 00000000..3550a30f --- /dev/null +++ b/.envrc @@ -0,0 +1 @@ +use flake diff --git a/.forgejo/workflows/check.yml b/.forgejo/workflows/check.yml new file mode 100644 index 00000000..f56dc367 --- /dev/null +++ b/.forgejo/workflows/check.yml @@ -0,0 +1,7 @@ +on: push +jobs: + check: + runs-on: nixos + steps: + - uses: actions/checkout@v4 + - run: nix develop -c just check diff --git a/.forgejo/workflows/update-inputs.yml b/.forgejo/workflows/update-inputs.yml new file mode 100644 index 00000000..c63d914a --- /dev/null +++ b/.forgejo/workflows/update-inputs.yml @@ -0,0 +1,90 @@ +name: update-inputs + +on: + schedule: + - cron: "0 6 * * 2,5" # Tue & Fri + workflow_dispatch: + +jobs: + update-flake-lock: + runs-on: nixos + + env: + BASE_BRANCH: main + BRANCH_PREFIX: flake-lock-update + FJ_URL: https://code.oliverdavies.uk + GIT_AUTHOR_EMAIL: flake-bot@local + GIT_AUTHOR_NAME: flake-bot + GIT_COMMITTER_EMAIL: ${{ env.GIT_AUTHOR_EMAIL }} + GIT_COMMITTER_NAME: ${{ env.GIT_AUTHOR_NAME }} + + steps: + - uses: actions/checkout@v3 + with: { fetch-depth: 0 } + + - name: Update inputs & commit + id: bump + run: | + set -o errexit + set -o nounset + set -o pipefail + + BRANCH="${BRANCH_PREFIX}-${GITHUB_RUN_ID}" + git switch -c "$BRANCH" + + BEFORE=$(git rev-parse HEAD) + + # Nix updates inputs and commits if needed + nix flake update --commit-lock-file + + AFTER=$(git rev-parse HEAD) + if [ "$BEFORE" = "$AFTER" ]; then + echo "changed=false" >> "$GITHUB_OUTPUT" + exit 0 + fi + + # ── Grab commit info ──────────────────────────────────────────────── + # Full message + COMMIT_RAW=$(git log -1 --pretty=%B) + + # First line is the short summary; we keep lines AFTER the first blank + COMMIT_BODY=$(printf '%s\n' "$COMMIT_RAW" \ + | sed '1,/^$/d' \ + | sed 's/^• */* /') # nicer Markdown bullet + + # Title becomes first line of the PR + COMMIT_TITLE=$(printf '%s\n' "$COMMIT_RAW" | head -n1) + + # JSON-escape the body so \n etc. are valid JSON + BODY_JSON=$(printf '%s' "$COMMIT_BODY" | jq -Rs .) + + echo "changed=true" >> "$GITHUB_OUTPUT" + echo "branch=$BRANCH" >> "$GITHUB_OUTPUT" + echo "title=$COMMIT_TITLE" >> "$GITHUB_OUTPUT" + echo "body_json=$BODY_JSON" >> "$GITHUB_OUTPUT" + + git push -u origin "$BRANCH" + + - name: Open pull-request + if: steps.bump.outputs.changed == 'true' + env: + TOKEN: ${{ secrets.FLAKE_UPDATE_PAT }} + BRANCH: ${{ steps.bump.outputs.branch }} + TITLE: ${{ steps.bump.outputs.title }} + BODY_JSON: ${{ steps.bump.outputs.body_json }} + run: | + set -o errexit + set -o nounset + + OWNER="${GITHUB_REPOSITORY%%/*}" + REPO="${GITHUB_REPOSITORY#*/}" + + curl -fSs -X POST "$FJ_URL/api/v1/repos/$OWNER/$REPO/pulls" \ + -H "Authorization: token $TOKEN" \ + --json '{ + "base": "'"$BASE_BRANCH"'", + "body": '"$BODY_JSON"', + "draft": false, + "head": "'"$BRANCH"'", + "title": "'"$TITLE"'" + }' diff --git a/.gitignore b/.gitignore index 953ba526..ee11d3e7 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,6 @@ -/nvim/.config/nvim/.netrwhist -/nvim/.config/nvim/plugged/ -/nvim/.config/nvim/plugin/packer_compiled.lua +# Nix. +/.direnv/ +/result + +# Syncthing. +/.stignore diff --git a/.ignore b/.ignore new file mode 100644 index 00000000..2d2ecd68 --- /dev/null +++ b/.ignore @@ -0,0 +1 @@ +.git/ diff --git a/.mailmap b/.mailmap new file mode 100644 index 00000000..6350744e --- /dev/null +++ b/.mailmap @@ -0,0 +1,7 @@ +Oliver Davies <339813+opdavies@users.noreply.github.com> +Oliver Davies +Oliver Davies +Oliver Davies +Oliver Davies +Oliver Davies +Oliver Davies diff --git a/.nvim.lua b/.nvim.lua new file mode 100644 index 00000000..2f839b98 --- /dev/null +++ b/.nvim.lua @@ -0,0 +1,67 @@ +vim.keymap.set("n", "fn", function() + require("telescope.builtin").find_files({ + cwd = "modules/home-manager/coding/neovim/config" + }) +end) + +require("conform").setup { + formatters_by_ft = { + lua = { "stylua" }, + nix = { "nixfmt" }, + }, +} + +require("lint").linters_by_ft = { + lua = { "luacheck" }, + nix = { "nix" }, +} + +local lspconfig = require "lspconfig" + +local capabilities = require("cmp_nvim_lsp").default_capabilities(vim.lsp.protocol.make_client_capabilities()) + +lspconfig.lua_ls.setup { + capabilities = capabilities, + + settings = { + Lua = { + completion = { + callSnippet = "Replace", + }, + + diagnostics = { + globals = { "vim" }, + }, + + runtime = { + version = "LuaJIT", + }, + + telemetry = { + enabled = false, + }, + + workspace = { + library = vim.api.nvim_get_runtime_file("", true), + }, + }, + }, +} + +lspconfig.nixd.setup { + capabilities = capabilities, + + cmd = { "nixd" }, + + settings = { + nixd = { + nixpkgs = { + expr = "import { }", + }, + + formatting = { + command = "nix fmt", + }, + }, + }, +} diff --git a/README.md b/README.md index 1088b583..7f398fb1 100644 --- a/README.md +++ b/README.md @@ -1,40 +1,3 @@ -# dotfiles +# nix-config -My personal dotfiles, originally for macOS only but currently being adapted for -use on Linux based systems (Ubuntu and Pop!_OS in particular) where needed. - -The repository is powered using Ansible, with each software package and its -associated configuration within separate roles within the `roles` directory. - -The `neovim` role, for example, has its own tasks in `roles/neovim/tasks/main.yaml` -and files in `roles/neovim/files`. - -Files within a role are typically symlinked into their required destination -so that they will be automatically updated without needing to run the playbook -again. - -For example, the files and directories within the neovim role are symlinked -into `~/.config/nvim`. - -## Requirements - -- [Ansible](https://www.ansible.com) -- [Git](https://git-scm.com) - -## Installation - -``` -$ ansible-playbook main.yaml --ask-become-pass -``` - -## Inspiration - -- [Chris Toomey](https://github.com/christoomey/dotfiles) -- [Gabe Berke-Williams](https://github.com/gabebw/dotfiles) -- [Jeff Geerling](https://github.com/geerlingguy/dotfiles) -- [Robin Malfait](https://github.com/RobinMalfait/dotfiles) -- [TJ DeVries](https://github.com/tjdevries/config_manager) -- [TheAltF4Stream](https://github.com/ALT-F4-LLC/dotfiles) -- [ThePrimeagen](https://github.com/ThePrimeagen/.dotfiles) -- [Thoughtbot](https://github.com/thoughtbot/dotfiles) -- [codico](https://github.com/codicocodes/dotfiles) +Originally my `dotfiles` repository, this repository contains my NixOS and Home Manager-based configurations for my personal laptop (`t480`) and home server/homelab (`nixedo`). diff --git a/ansible.cfg b/ansible.cfg deleted file mode 100644 index 5b1bf96a..00000000 --- a/ansible.cfg +++ /dev/null @@ -1,3 +0,0 @@ -[defaults] -become = true -inventory = ./hosts.ini diff --git a/bin/bin/drupalorg b/bin/bin/drupalorg deleted file mode 100755 index 8dd7f1c8..00000000 Binary files a/bin/bin/drupalorg and /dev/null differ diff --git a/bin/bin/git-abort b/bin/bin/git-abort deleted file mode 100755 index 078c3da2..00000000 --- a/bin/bin/git-abort +++ /dev/null @@ -1,20 +0,0 @@ -#!/bin/bash - -# Abort a rebase, merge, `am`, a cherry-pick or a revert, depending on the situation. - -if [[ -e .git/CHERRY_PICK_HEAD ]] ; then - exec git cherry-pick --abort "$@" -elif [[ -e .git/REVERT_HEAD ]] ; then - exec git revert --abort "$@" -elif [[ -e .git/rebase-apply/applying ]] ; then - exec git am --abort "$@" -elif [[ -e .git/rebase-apply ]] ; then - exec git rebase --abort "$@" -elif [[ -e .git/rebase-merge ]] ; then - exec git rebase --abort "$@" -elif [[ -e .git/MERGE_MODE ]] ; then - exec git merge --abort "$@" -else - echo git-abort: unknown state - exit -1 -fi diff --git a/bin/bin/git-close-pull-request b/bin/bin/git-close-pull-request deleted file mode 100755 index 67f3673d..00000000 --- a/bin/bin/git-close-pull-request +++ /dev/null @@ -1,271 +0,0 @@ -#!/usr/bin/env php - - * - * Run this from a branch which has an upstream remote branch, and an associated - * pull request. - * - * The script will merge the branch into master, push master (which will - * automatically close the pull request), and delete both the local and remote - * branches. - * - * Based on a script by @christoomey. Translated into PHP. - */ - -class ClosesPullRequests -{ - private $targetBranch; - private $localBranch; - private $remoteBranch; - - private const RUN_TYPE_COMMAND = 'command'; - private const RUN_TYPE_QUERY = 'query'; - - public function __construct() - { - $this->localBranch = $this->run( - 'git rev-parse --abbrev-ref HEAD', - self::RUN_TYPE_QUERY - ); - $this->targetBranch = $this->getTargetBranchFromArgs(); - - $this->remoteBranch = $this->run( - 'git rev-parse --abbrev-ref --symbolic-full-name @{u}', - self::RUN_TYPE_QUERY - ); - $this->remoteBranch = str_replace('origin/', '', $this->remoteBranch); - } - - public function __invoke(): void - { - $this->confirmCiStatusIsPassing(); - // TODO: Check that the current branch has a tracking branch. - $this->ensureWorkingDirectoryAndIndexAreClean(); - $this->fetchOrigin(); - $this->ensureFeatureBranchInSync(); - $this->ensureTargetBranchInSync(); - $this->checkoutTargetBranch(); - $this->mergeLocalBranch(); - $this->pushTargetBranch(); - $this->deleteRemoteBranch(); - $this->deleteLocalBranch(); - } - - private function ensureWorkingDirectoryAndIndexAreClean(): void - { - echo 'Ensuring that index and working directory are clean...' . PHP_EOL; - - $isIndexClean = $this->run('git diff --cached --exit-code', self::RUN_TYPE_COMMAND); - $isWorkingDirClean = $this->run('git diff --exit-code', self::RUN_TYPE_COMMAND); - - if (!$isIndexClean || !$isWorkingDirClean) { - $this->dieWithMessage('Index or working dir not clean. Aborting.'); - } - } - - private function getTargetBranchFromArgs(): string - { - if (!$targetBranchName = $this->getArg('t:', ['target:'])) { - $this->dieWithMessage('Invalid target branch specified. Aborting.'); - } - - return $targetBranchName; - } - - private function confirmCiStatusIsPassing(): void - { - if ($this->isForce()) { - echo 'Forced. Skipping ci-status check...' . PHP_EOL; - return; - } - - echo 'Confirming ci-status on PR is green...' . PHP_EOL; - - $passedCi = $this->run('gh pr checks', self::RUN_TYPE_COMMAND); - - // TODO: Check if there are no CI checks. Does this return `true` as well? - if (!$passedCi) { - $this->dieWithMessage('CI pending or failed.'); - } - } - - private function fetchOrigin(): void - { - print 'Fetching origin to confirm local and remote in sync...' - . PHP_EOL; - - $this->run('git fetch origin', self::RUN_TYPE_COMMAND); - } - - private function ensureTargetBranchInSync(): void - { - $this->ensureBranchInSyncWithUpstream( - $this->targetBranch, - $this->targetBranch - ); - } - - private function ensureFeatureBranchInSync(): void - { - $this->ensureBranchInSyncWithUpstream( - $this->localBranch, - $this->remoteBranch - ); - } - - private function ensureBranchInSyncWithUpstream( - string $localBranch, - string $remoteBranch - ): void { - echo sprintf( - 'Ensuring that %s is in sync with its upstream...', - $localBranch - ) . PHP_EOL; - - $localCommitTip = $this->tipCommitOfBranch($localBranch); - $remoteCommitTip = $this->tipCommitOfBranch(sprintf( - 'origin/%s', - $remoteBranch - )); - - if ($localCommitTip != $remoteCommitTip) { - $this->dieWithMessage(sprintf( - 'Branch %s was out of date, needs rebasing. Aborting.', - $localBranch - )); - } - } - - private function tipCommitOfBranch(string $branchName): string - { - return $this->run( - sprintf('git rev-parse %s', $branchName), - self::RUN_TYPE_QUERY - ); - } - - private function checkoutTargetBranch(): void - { - echo sprintf('Checking out %s...' . PHP_EOL, $this->targetBranch); - - $this->run( - sprintf('git checkout %s', $this->targetBranch), - self::RUN_TYPE_COMMAND - ); - } - - private function mergeLocalBranch(): void - { - echo sprintf( - 'Merging %s into %s...' . PHP_EOL, - $this->localBranch, - $this->targetBranch - ); - - $mergeCommand = sprintf('git merge --ff-only %s', $this->localBranch); - if (!$this->run($mergeCommand, self::RUN_TYPE_COMMAND)) { - // Switch back to the previous branch. - $this->run('git checkout -', self::RUN_TYPE_COMMAND); - - $this->dieWithMessage(sprintf( - 'Branch %s is not fast-forwardable.', - $this->localBranch - )); - } - } - - public function pushTargetBranch(): void - { - print(sprintf('Pushing updated %s branch...', $this->targetBranch)); - - $this->run( - sprintf('git push origin %s', $this->targetBranch), - self::RUN_TYPE_COMMAND - ); - } - - public function deleteRemoteBranch(): void - { - echo 'Deleting remote branch...' . PHP_EOL; - - $this->run( - sprintf('git push origin :%s', $this->remoteBranch), - self::RUN_TYPE_COMMAND - ); - } - - public function deleteLocalBranch(): void - { - echo 'Deleting local branch...' . PHP_EOL; - - $this->run( - sprintf('git branch -d %s', $this->localBranch), - self::RUN_TYPE_COMMAND - ); - } - - private function getArg(string $shortOpts, array $longOpts = []): ?string - { - if (!$values = getopt($shortOpts, $longOpts)) { - return NULL; - } - - return current($values); - } - - private function hasArg(string $shortOpts, array $longOpts = []): bool - { - return !empty(getopt($shortOpts, $longOpts)); - } - - private function isForce(): bool - { - return $this->hasArg('f::', ['force::']); - } - - /** - * Run the command. - * - * @return bool|string - * If the type is 'command', the method will return if there were any - * errors when running the command based on its return code. - * - * If the type is 'query', then the output of the command will be returned - * as a string. - */ - private function run(string $command, string $type) - { - switch ($type) { - case self::RUN_TYPE_COMMAND: - // Perform the command, hiding the original output and return - // whether or not there were errors. - @exec("$command", $output, $return); - - return $return == 0; - - case self::RUN_TYPE_QUERY: - // Perform the command and return the output. - return exec($command, $output); - } - } - - private function dieWithMessage(string $message): void - { - echo sprintf("\e[31m%s\e[0m", $message); - - exit(1); - } - - private function exitWithWarning(string $message): void - { - echo sprintf("\e[33m%s\e[0m", $message); - - exit(2); - } -} - -(new ClosesPullRequests())->__invoke(); diff --git a/bin/bin/git-cm b/bin/bin/git-cm deleted file mode 100755 index 0a243dae..00000000 --- a/bin/bin/git-cm +++ /dev/null @@ -1,7 +0,0 @@ -#!/usr/bin/env bash - -if [[ $# > 0 ]]; then - git commit -m "$@" -else - git commit -v -fi diff --git a/bin/bin/git-continue b/bin/bin/git-continue deleted file mode 100755 index 9bebe0d8..00000000 --- a/bin/bin/git-continue +++ /dev/null @@ -1,16 +0,0 @@ -#!/bin/bash - -# Continue a rebase or cherry-pick in the event of conflicts. - -if [[ -e .git/CHERRY_PICK_HEAD ]] ; then - exec git cherry-pick --continue "$@" -elif [[ -e .git/rebase-apply/applying ]] ; then - exec git rebase --continue "$@" -elif [[ -e .git/rebase-apply ]] ; then - exec git rebase --continue "$@" -elif [[ -e .git/rebase-merge ]] ; then - exec git rebase --continue "$@" -else - echo git-abort: unknown state - exit -1 -fi diff --git a/bin/bin/git-create-new-tracking-branch b/bin/bin/git-create-new-tracking-branch deleted file mode 100755 index 0a14fb4b..00000000 --- a/bin/bin/git-create-new-tracking-branch +++ /dev/null @@ -1,15 +0,0 @@ -#!/bin/sh - -set -e - -if [ "$#" -lt 1 ]; then - echo "Error: Not enough arguments." - exit l -fi - -# Create a new branch including any additional arguments. -git checkout -b "$@" - -# Push the branch to origin, bypassing any Git hooks. -new_branch_name=$1 -git push --no-verify -u origin "${new_branch_name}:opd-${new_branch_name}" diff --git a/bin/bin/git-delete-merged-branches b/bin/bin/git-delete-merged-branches deleted file mode 100755 index 77e7fc00..00000000 --- a/bin/bin/git-delete-merged-branches +++ /dev/null @@ -1,42 +0,0 @@ -#!/usr/bin/env php -/dev/null - - if [ $? -ne 0 ]; then - echo "Error: gh command not found." - exit 1 - fi - - # Load an existing PR, or create a new one. - gh pr view --web || gh pr create --assignee opdavies --web -} - -ensure_is_published -open_or_build_pull_request diff --git a/bin/bin/git-publish b/bin/bin/git-publish deleted file mode 100755 index ca196bf7..00000000 --- a/bin/bin/git-publish +++ /dev/null @@ -1,15 +0,0 @@ -#!/usr/bin/env php - /tmp/.git_ssh.$$ - chmod +x /tmp/.git_ssh.$$ - export GIT_SSH=/tmp/.git_ssh.$$ -fi - -# in case the git command is repeated -[ "$1" = "git" ] && shift - -# Run the git command -git "$@" diff --git a/bin/bin/main-or-master-branch b/bin/bin/main-or-master-branch deleted file mode 100755 index ed9ffbd3..00000000 --- a/bin/bin/main-or-master-branch +++ /dev/null @@ -1,10 +0,0 @@ -#!/bin/zsh - -# Check if we should use the `main` or `master` branch for this repo. -# Prefer `main` to `master`. - -if git show-ref --quiet origin/main || git rev-parse main &>/dev/null; then - echo main -else - echo master -fi \ No newline at end of file diff --git a/bin/bin/phpunit-or-pest b/bin/bin/phpunit-or-pest deleted file mode 100755 index 781b7124..00000000 --- a/bin/bin/phpunit-or-pest +++ /dev/null @@ -1,8 +0,0 @@ -#!/usr/bin/env bash - -if [[ -f "vendor/bin/pest" ]]; then - echo "pest" - exit 0 -fi - -echo "phpunit" diff --git a/bin/bin/tmux-sessioniser b/bin/bin/tmux-sessioniser deleted file mode 100755 index b42fe166..00000000 --- a/bin/bin/tmux-sessioniser +++ /dev/null @@ -1,39 +0,0 @@ -#!/bin/bash - -# Quickly navigate between different directories using fzf and tmux sessions -# (Thanks, ThePrimeagen!). -# -# https://github.com/ThePrimeagen/.dotfiles/blob/master/bin/.local/bin/tmux-sessionizer -# https://frontendmasters.com/workshops/dev-productivity - -if [[ $# -eq 1 ]]; then - selected=$1 -else - # Get the session name from fuzzy-finding list of directories and generating a - # tmux-safe version. - selected=$(find ~/ ~/Code ~/Code/clients ~/Code/os ~/Code/Personal ~/Documents/Books ~/Documents/Talks/ -mindepth 1 -maxdepth 1 -type d -not -name ".*" | sort | fzf) -fi - -if [[ -z $selected ]]; then - exit 0 -fi - -is_tmux_running=$(pgrep tmux) -selected_name=$(basename "$selected" | tr . -) - -if [[ -z $TMUX ]] && [[ -z $is_tmux_running ]]; then - tmux new-session -s $selected_name -c $selected - exit 0 -fi - -# Create a new session if tmux does not already have a session matching the -# selected session name. -if ! tmux has-session -t $selected_name 2> /dev/null; then - tmux new-session -s $selected_name -c $selected -d -fi - -if [[ -z $TMUX ]]; then - tmux attach-session -t $selected_name -else - tmux switch-client -t $selected_name -fi diff --git a/bin/dotfiles b/bin/dotfiles deleted file mode 100755 index 7983c79d..00000000 --- a/bin/dotfiles +++ /dev/null @@ -1,38 +0,0 @@ -#!/bin/bash - -set -e - -CONFIG_DIR="$HOME/.config/dotfiles" -DOTFILES_DIR="${DOTFILES_DIR:-$HOME/.dotfiles}" -PATH="${PATH}:${HOME}/.local/bin" - -clone_or_update_dotfiles() { - if ! [[ -d "$DOTFILES_DIR" ]]; then - git clone "https://github.com/opdavies/dotfiles.git" "$DOTFILES_DIR" - else - git -C "$DOTFILES_DIR" pull - fi -} - -create_config_dir() { - mkdir -p "${CONFIG_DIR}" -} - -install_dependencies() { - ansible-galaxy install -r "${DOTFILES_DIR}/requirements.yml" -} - -install_ansible() { - sudo apt-get -yqq update - sudo apt-get -yqq install python3-pip - pip install ansible --user -} - -run_playbook() { - ansible-playbook --diff --extra-vars "@${CONFIG_DIR}/values.yaml" --vault-password-file=${CONFIG_DIR}/vault-password.txt "${DOTFILES_DIR}/main.yaml" "${@}" -} - -clone_or_update_dotfiles -install_ansible -install_dependencies -run_playbook "${@}" diff --git a/bin/tmuxinator-fzf b/bin/tmuxinator-fzf deleted file mode 100755 index 595a9fa2..00000000 --- a/bin/tmuxinator-fzf +++ /dev/null @@ -1,7 +0,0 @@ -#!/usr/bin/env bash - -# Use fzf to select a project to open with tmuxinator. - -set -euo pipefail - -tmuxinator list -n | tail -n +2 | fzf | xargs tmuxinator start diff --git a/flake.lock b/flake.lock new file mode 100644 index 00000000..ce5e0080 --- /dev/null +++ b/flake.lock @@ -0,0 +1,627 @@ +{ + "nodes": { + "agenix": { + "inputs": { + "darwin": "darwin", + "home-manager": "home-manager", + "nixpkgs": [ + "nixpkgs" + ], + "systems": "systems" + }, + "locked": { + "lastModified": 1754433428, + "narHash": "sha256-NA/FT2hVhKDftbHSwVnoRTFhes62+7dxZbxj5Gxvghs=", + "owner": "ryantm", + "repo": "agenix", + "rev": "9edb1787864c4f59ae5074ad498b6272b3ec308d", + "type": "github" + }, + "original": { + "owner": "ryantm", + "repo": "agenix", + "type": "github" + } + }, + "bop-scripts": { + "flake": false, + "locked": { + "lastModified": 1756931648, + "narHash": "sha256-bfAmJ1IY0B6eNbJvoWkUMQ7Ya4ShrIoVSdQrnE/cn40=", + "owner": "breadonpenguins", + "repo": "scripts", + "rev": "d04bcbe63176e623e1ce8edc4c3840c506a28d96", + "type": "github" + }, + "original": { + "owner": "breadonpenguins", + "repo": "scripts", + "type": "github" + } + }, + "conf-vim": { + "flake": false, + "locked": { + "lastModified": 1507549264, + "narHash": "sha256-AjiTJsoim0BAnyfqk1IQzNsa6jhFM2+A66E7q9sJqz0=", + "owner": "tjdevries", + "repo": "conf.vim", + "rev": "a716df0fd5d7ba558c07dac2e07f05d5eba11afb", + "type": "github" + }, + "original": { + "owner": "tjdevries", + "repo": "conf.vim", + "type": "github" + } + }, + "darwin": { + "inputs": { + "nixpkgs": [ + "agenix", + "nixpkgs" + ] + }, + "locked": { + "lastModified": 1744478979, + "narHash": "sha256-dyN+teG9G82G+m+PX/aSAagkC+vUv0SgUw3XkPhQodQ=", + "owner": "lnl7", + "repo": "nix-darwin", + "rev": "43975d782b418ebf4969e9ccba82466728c2851b", + "type": "github" + }, + "original": { + "owner": "lnl7", + "ref": "master", + "repo": "nix-darwin", + "type": "github" + } + }, + "devshell": { + "inputs": { + "nixpkgs": [ + "git-repo-updater", + "nixpkgs" + ] + }, + "locked": { + "lastModified": 1741473158, + "narHash": "sha256-kWNaq6wQUbUMlPgw8Y+9/9wP0F8SHkjy24/mN3UAppg=", + "owner": "numtide", + "repo": "devshell", + "rev": "7c9e793ebe66bcba8292989a68c0419b737a22a0", + "type": "github" + }, + "original": { + "owner": "numtide", + "repo": "devshell", + "type": "github" + } + }, + "disko": { + "inputs": { + "nixpkgs": [ + "nixpkgs" + ] + }, + "locked": { + "lastModified": 1756733629, + "narHash": "sha256-dwWGlDhcO5SMIvMSTB4mjQ5Pvo2vtxvpIknhVnSz2I8=", + "owner": "nix-community", + "repo": "disko", + "rev": "a5c4f2ab72e3d1ab43e3e65aa421c6f2bd2e12a1", + "type": "github" + }, + "original": { + "owner": "nix-community", + "repo": "disko", + "type": "github" + } + }, + "edit-alternate-vim": { + "flake": false, + "locked": { + "lastModified": 1635180789, + "narHash": "sha256-mEKnqYAhgrdxPRoKf4S4yYecdFIHGg8bDxpqPuC1+S4=", + "owner": "tjdevries", + "repo": "edit_alternate.vim", + "rev": "ef3019115d9bb7ffd691d2859eda213dd99e0b0a", + "type": "github" + }, + "original": { + "owner": "tjdevries", + "repo": "edit_alternate.vim", + "type": "github" + } + }, + "flake-parts": { + "inputs": { + "nixpkgs-lib": "nixpkgs-lib" + }, + "locked": { + "lastModified": 1756770412, + "narHash": "sha256-+uWLQZccFHwqpGqr2Yt5VsW/PbeJVTn9Dk6SHWhNRPw=", + "owner": "hercules-ci", + "repo": "flake-parts", + "rev": "4524271976b625a4a605beefd893f270620fd751", + "type": "github" + }, + "original": { + "owner": "hercules-ci", + "repo": "flake-parts", + "type": "github" + } + }, + "flake-parts_2": { + "inputs": { + "nixpkgs-lib": [ + "nur", + "nixpkgs" + ] + }, + "locked": { + "lastModified": 1733312601, + "narHash": "sha256-4pDvzqnegAfRkPwO3wmwBhVi/Sye1mzps0zHWYnP88c=", + "owner": "hercules-ci", + "repo": "flake-parts", + "rev": "205b12d8b7cd4802fbcb8e8ef6a0f1408781a4f9", + "type": "github" + }, + "original": { + "owner": "hercules-ci", + "repo": "flake-parts", + "type": "github" + } + }, + "flake-utils": { + "inputs": { + "systems": "systems_2" + }, + "locked": { + "lastModified": 1731533236, + "narHash": "sha256-l0KFg5HjrsfsO/JpG+r7fRrqm12kzFHyUHqHCVpMMbI=", + "owner": "numtide", + "repo": "flake-utils", + "rev": "11707dc2f618dd54ca8739b309ec4fc024de578b", + "type": "github" + }, + "original": { + "owner": "numtide", + "repo": "flake-utils", + "type": "github" + } + }, + "git-repo-updater": { + "inputs": { + "devshell": "devshell", + "flake-parts": [ + "flake-parts" + ], + "import-tree": [ + "import-tree" + ], + "nixpkgs": [ + "nixpkgs" + ] + }, + "locked": { + "lastModified": 1757018109, + "narHash": "sha256-KfRzBPOOM5cf8mFVeWjV7TGa3p+ul/flxnUdwGW4Sds=", + "ref": "refs/heads/main", + "rev": "63235768261976efe0d9c825e69c44fff8c80e5d", + "revCount": 1, + "type": "git", + "url": "https://code.oliverdavies.uk/opdavies/git-repo-updater" + }, + "original": { + "type": "git", + "url": "https://code.oliverdavies.uk/opdavies/git-repo-updater" + } + }, + "home-manager": { + "inputs": { + "nixpkgs": [ + "agenix", + "nixpkgs" + ] + }, + "locked": { + "lastModified": 1745494811, + "narHash": "sha256-YZCh2o9Ua1n9uCvrvi5pRxtuVNml8X2a03qIFfRKpFs=", + "owner": "nix-community", + "repo": "home-manager", + "rev": "abfad3d2958c9e6300a883bd443512c55dfeb1be", + "type": "github" + }, + "original": { + "owner": "nix-community", + "repo": "home-manager", + "type": "github" + } + }, + "home-manager_2": { + "inputs": { + "nixpkgs": [ + "nixpkgs" + ] + }, + "locked": { + "lastModified": 1756991914, + "narHash": "sha256-4ve/3ah5H/SpL2m3qmZ9GU+VinQYp2MN1G7GamimTds=", + "owner": "nix-community", + "repo": "home-manager", + "rev": "b08f8737776f10920c330657bee8b95834b7a70f", + "type": "github" + }, + "original": { + "owner": "nix-community", + "ref": "master", + "repo": "home-manager", + "type": "github" + } + }, + "import-tree": { + "locked": { + "lastModified": 1752730890, + "narHash": "sha256-GES8fapSLGz36MMPRVNkSUWXUTtqvGQNXHjRmRLfJUY=", + "owner": "vic", + "repo": "import-tree", + "rev": "6ebb8cb87987b20264c09296166543fd3761d274", + "type": "github" + }, + "original": { + "owner": "vic", + "repo": "import-tree", + "type": "github" + } + }, + "ixx": { + "inputs": { + "flake-utils": [ + "nixvim", + "nuschtosSearch", + "flake-utils" + ], + "nixpkgs": [ + "nixvim", + "nuschtosSearch", + "nixpkgs" + ] + }, + "locked": { + "lastModified": 1754860581, + "narHash": "sha256-EM0IE63OHxXCOpDHXaTyHIOk2cNvMCGPqLt/IdtVxgk=", + "owner": "NuschtOS", + "repo": "ixx", + "rev": "babfe85a876162c4acc9ab6fb4483df88fa1f281", + "type": "github" + }, + "original": { + "owner": "NuschtOS", + "ref": "v0.1.1", + "repo": "ixx", + "type": "github" + } + }, + "nix-index-database": { + "inputs": { + "nixpkgs": [ + "nixpkgs" + ] + }, + "locked": { + "lastModified": 1756612744, + "narHash": "sha256-/glV6VAq8Va3ghIbmhET3S1dzkbZqicsk5h+FtvwiPE=", + "owner": "nix-community", + "repo": "nix-index-database", + "rev": "3fe768e1f058961095b4a0d7a2ba15dc9736bdc6", + "type": "github" + }, + "original": { + "owner": "nix-community", + "repo": "nix-index-database", + "type": "github" + } + }, + "nixos-hardware": { + "locked": { + "lastModified": 1756925795, + "narHash": "sha256-kUb5hehaikfUvoJDEc7ngiieX88TwWX/bBRX9Ar6Tac=", + "owner": "NixOS", + "repo": "nixos-hardware", + "rev": "ba6fab29768007e9f2657014a6e134637100c57d", + "type": "github" + }, + "original": { + "owner": "NixOS", + "ref": "master", + "repo": "nixos-hardware", + "type": "github" + } + }, + "nixpkgs": { + "locked": { + "lastModified": 1756787288, + "narHash": "sha256-rw/PHa1cqiePdBxhF66V7R+WAP8WekQ0mCDG4CFqT8Y=", + "owner": "nixos", + "repo": "nixpkgs", + "rev": "d0fc30899600b9b3466ddb260fd83deb486c32f1", + "type": "github" + }, + "original": { + "owner": "nixos", + "ref": "nixos-unstable", + "repo": "nixpkgs", + "type": "github" + } + }, + "nixpkgs-lib": { + "locked": { + "lastModified": 1754788789, + "narHash": "sha256-x2rJ+Ovzq0sCMpgfgGaaqgBSwY+LST+WbZ6TytnT9Rk=", + "owner": "nix-community", + "repo": "nixpkgs.lib", + "rev": "a73b9c743612e4244d865a2fdee11865283c04e6", + "type": "github" + }, + "original": { + "owner": "nix-community", + "repo": "nixpkgs.lib", + "type": "github" + } + }, + "nixpkgs-stable": { + "locked": { + "lastModified": 1751274312, + "narHash": "sha256-/bVBlRpECLVzjV19t5KMdMFWSwKLtb5RyXdjz3LJT+g=", + "owner": "nixos", + "repo": "nixpkgs", + "rev": "50ab793786d9de88ee30ec4e4c24fb4236fc2674", + "type": "github" + }, + "original": { + "owner": "nixos", + "ref": "nixos-24.11", + "repo": "nixpkgs", + "type": "github" + } + }, + "nixvim": { + "inputs": { + "flake-parts": [ + "flake-parts" + ], + "nixpkgs": [ + "nixpkgs" + ], + "nuschtosSearch": "nuschtosSearch", + "systems": "systems_3" + }, + "locked": { + "lastModified": 1756946299, + "narHash": "sha256-N4PjGA0rittpNZGscKPel+mr/dMcKF73j0yr4rbG3T0=", + "owner": "nix-community", + "repo": "nixvim", + "rev": "63496f00c681b3e200bd17878a43ec68b7139a66", + "type": "github" + }, + "original": { + "owner": "nix-community", + "repo": "nixvim", + "type": "github" + } + }, + "nur": { + "inputs": { + "flake-parts": "flake-parts_2", + "nixpkgs": [ + "nixpkgs" + ] + }, + "locked": { + "lastModified": 1757050467, + "narHash": "sha256-Rps0Ga0g/TdY49rR2ZRBsdBYybSzPccEsaI9IvwuE98=", + "owner": "nix-community", + "repo": "NUR", + "rev": "985abf0197c75dd64c24691a7e5e0acf308d7f20", + "type": "github" + }, + "original": { + "owner": "nix-community", + "repo": "NUR", + "type": "github" + } + }, + "nuschtosSearch": { + "inputs": { + "flake-utils": "flake-utils", + "ixx": "ixx", + "nixpkgs": [ + "nixvim", + "nixpkgs" + ] + }, + "locked": { + "lastModified": 1755555503, + "narHash": "sha256-WiOO7GUOsJ4/DoMy2IC5InnqRDSo2U11la48vCCIjjY=", + "owner": "NuschtOS", + "repo": "search", + "rev": "6f3efef888b92e6520f10eae15b86ff537e1d2ea", + "type": "github" + }, + "original": { + "owner": "NuschtOS", + "repo": "search", + "type": "github" + } + }, + "root": { + "inputs": { + "agenix": "agenix", + "bop-scripts": "bop-scripts", + "conf-vim": "conf-vim", + "disko": "disko", + "edit-alternate-vim": "edit-alternate-vim", + "flake-parts": "flake-parts", + "git-repo-updater": "git-repo-updater", + "home-manager": "home-manager_2", + "import-tree": "import-tree", + "nix-index-database": "nix-index-database", + "nixos-hardware": "nixos-hardware", + "nixpkgs": "nixpkgs", + "nixpkgs-stable": "nixpkgs-stable", + "nixvim": "nixvim", + "nur": "nur", + "rwxrob-dot": "rwxrob-dot", + "standard-vim": "standard-vim", + "vim-heritage": "vim-heritage", + "vim-textobj-xmlattr": "vim-textobj-xmlattr", + "voidrice": "voidrice", + "zet": "zet" + } + }, + "rwxrob-dot": { + "flake": false, + "locked": { + "lastModified": 1751898094, + "narHash": "sha256-kGpHL2l9p/yOtmG+AZvOb0Y5mH1d+Zoh2dd5N3Xjizc=", + "owner": "rwxrob", + "repo": "dot", + "rev": "90794c77061f270078e847af45c376610768c6e2", + "type": "github" + }, + "original": { + "owner": "rwxrob", + "repo": "dot", + "type": "github" + } + }, + "standard-vim": { + "flake": false, + "locked": { + "lastModified": 1539613748, + "narHash": "sha256-9VwkvV1Dv6cE4uDkPp36DozjWJOclDR883yDMYw000E=", + "owner": "tjdevries", + "repo": "standard.vim", + "rev": "b333ef9a9cf6cf66536deda017a542843613fa75", + "type": "github" + }, + "original": { + "owner": "tjdevries", + "repo": "standard.vim", + "type": "github" + } + }, + "systems": { + "locked": { + "lastModified": 1681028828, + "narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=", + "owner": "nix-systems", + "repo": "default", + "rev": "da67096a3b9bf56a91d16901293e51ba5b49a27e", + "type": "github" + }, + "original": { + "owner": "nix-systems", + "repo": "default", + "type": "github" + } + }, + "systems_2": { + "locked": { + "lastModified": 1681028828, + "narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=", + "owner": "nix-systems", + "repo": "default", + "rev": "da67096a3b9bf56a91d16901293e51ba5b49a27e", + "type": "github" + }, + "original": { + "owner": "nix-systems", + "repo": "default", + "type": "github" + } + }, + "systems_3": { + "locked": { + "lastModified": 1681028828, + "narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=", + "owner": "nix-systems", + "repo": "default", + "rev": "da67096a3b9bf56a91d16901293e51ba5b49a27e", + "type": "github" + }, + "original": { + "owner": "nix-systems", + "repo": "default", + "type": "github" + } + }, + "vim-heritage": { + "flake": false, + "locked": { + "lastModified": 1716350150, + "narHash": "sha256-YzqP2+Go8bW3heFyzzcS/91LrMkwjpZ89+ptrjjBKrM=", + "owner": "jessarcher", + "repo": "vim-heritage", + "rev": "574baeb0679681a710adce5110a0d8b2ae1c2637", + "type": "github" + }, + "original": { + "owner": "jessarcher", + "repo": "vim-heritage", + "type": "github" + } + }, + "vim-textobj-xmlattr": { + "flake": false, + "locked": { + "lastModified": 1464940962, + "narHash": "sha256-+91FVP95oh00flINdltqx6qJuijYo56tHIh3J098G2Q=", + "owner": "whatyouhide", + "repo": "vim-textobj-xmlattr", + "rev": "694a297f1d75fd527e87da9769f3c6519a87ebb1", + "type": "github" + }, + "original": { + "owner": "whatyouhide", + "repo": "vim-textobj-xmlattr", + "type": "github" + } + }, + "voidrice": { + "flake": false, + "locked": { + "lastModified": 1744355318, + "narHash": "sha256-9U1Do0w2oT5E6uZxSKoHAzbGbSLQRQlT65KcPGzwhW8=", + "owner": "lukesmithxyz", + "repo": "voidrice", + "rev": "f853f1884a8f0c244765192dc6f5a910a7e2b8e5", + "type": "github" + }, + "original": { + "owner": "lukesmithxyz", + "repo": "voidrice", + "type": "github" + } + }, + "zet": { + "flake": false, + "locked": { + "lastModified": 1758576585, + "narHash": "sha256-hWQE45nFaSN8agYMP8xt5kaUMfBXVj5k9zInZNs/xAI=", + "ref": "refs/heads/main", + "rev": "23505f6c31c7cc903e63621b52b5f92eea1facc5", + "revCount": 35, + "type": "git", + "url": "https://code.oliverdavies.uk/opdavies/zet" + }, + "original": { + "type": "git", + "url": "https://code.oliverdavies.uk/opdavies/zet" + } + } + }, + "root": "root", + "version": 7 +} diff --git a/flake.nix b/flake.nix new file mode 100644 index 00000000..25b1bf65 --- /dev/null +++ b/flake.nix @@ -0,0 +1,106 @@ +{ + inputs = { + agenix = { + inputs.nixpkgs.follows = "nixpkgs"; + url = "github:ryantm/agenix"; + }; + + bop-scripts = { + flake = false; + url = "github:breadonpenguins/scripts"; + }; + + conf-vim = { + flake = false; + url = "github:tjdevries/conf.vim"; + }; + + disko = { + inputs.nixpkgs.follows = "nixpkgs"; + url = "github:nix-community/disko"; + }; + + edit-alternate-vim = { + flake = false; + url = "github:tjdevries/edit_alternate.vim"; + }; + + flake-parts.url = "github:hercules-ci/flake-parts"; + + git-repo-updater = { + inputs.flake-parts.follows = "flake-parts"; + inputs.import-tree.follows = "import-tree"; + inputs.nixpkgs.follows = "nixpkgs"; + url = "git+https://code.oliverdavies.uk/opdavies/git-repo-updater"; + }; + + home-manager = { + inputs.nixpkgs.follows = "nixpkgs"; + url = "github:nix-community/home-manager/master"; + }; + + import-tree.url = "github:vic/import-tree"; + + nix-index-database = { + inputs.nixpkgs.follows = "nixpkgs"; + url = "github:nix-community/nix-index-database"; + }; + + nixos-hardware.url = "github:NixOS/nixos-hardware/master"; + + nixvim = { + inputs.flake-parts.follows = "flake-parts"; + inputs.nixpkgs.follows = "nixpkgs"; + url = "github:nix-community/nixvim"; + }; + + nixpkgs-stable.url = "github:nixos/nixpkgs/nixos-24.11"; + + nixpkgs.url = "github:nixos/nixpkgs/nixos-unstable"; + + nur = { + inputs.nixpkgs.follows = "nixpkgs"; + url = "github:nix-community/NUR"; + }; + + rwxrob-dot = { + flake = false; + url = "github:rwxrob/dot"; + }; + + standard-vim = { + flake = false; + url = "github:tjdevries/standard.vim"; + }; + + vim-heritage = { + flake = false; + url = "github:jessarcher/vim-heritage"; + }; + + vim-textobj-xmlattr = { + flake = false; + url = "github:whatyouhide/vim-textobj-xmlattr"; + }; + + voidrice = { + flake = false; + url = "github:lukesmithxyz/voidrice"; + }; + + zet = { + flake = false; + url = "git+https://code.oliverdavies.uk/opdavies/zet"; + }; + }; + + outputs = + inputs@{ flake-parts, ... }: + flake-parts.lib.mkFlake { inherit inputs; } { + flake = { + overlays = import ./overlays { inherit inputs; }; + }; + + imports = [ (inputs.import-tree ./modules) ]; + }; +} diff --git a/group_vars/all b/group_vars/all deleted file mode 100644 index 8fa0da3b..00000000 --- a/group_vars/all +++ /dev/null @@ -1,52 +0,0 @@ -default_roles: - - alacritty - - awesome-wm - - cargo - - copyq - - ctop - - dconf - - debugger - - delta - - discord - - docker - - filezilla - - flameshot - - fonts - - fzf - - git - - github-cli - - github-desktop - - gnome-tweak-tools - - google-chrome - - htop - - jq - - kdenlive - - mysql-client - - neovim - - neovim-lsp - - neovim-packer - - notion-app - - npm - - obs-studio - - pdf-arranger - - platformsh-cli - - pocketcasts - - postman - - projects - - pulumi - - pv - - ripgrep - - skype - - slack - - ssh - - stylua - - teams - - tldr - - tmux - - tmuxinator - - todoist - - tree - - vlc - - zoom - - zsh - - zsh-antigen diff --git a/home-manager/opdavies/nixedo.nix b/home-manager/opdavies/nixedo.nix new file mode 100644 index 00000000..902a9bfc --- /dev/null +++ b/home-manager/opdavies/nixedo.nix @@ -0,0 +1,13 @@ +{ pkgs, ... }: + +{ + imports = [ + ./nixedo/email-filters.nix + ]; + + home.packages = with pkgs; [ + import-to-jellyfin + vic + yt-dlp + ]; +} diff --git a/home-manager/opdavies/nixedo/email-filters.nix b/home-manager/opdavies/nixedo/email-filters.nix new file mode 100644 index 00000000..4cdcb162 --- /dev/null +++ b/home-manager/opdavies/nixedo/email-filters.nix @@ -0,0 +1,45 @@ +{ + config, + lib, + pkgs, + ... +}: + +let + cfg = config.nixedo.${name}; + name = "email-filters"; +in +{ + options.nixedo.${name} = { + configFile = lib.mkOption { + default = "${config.xdg.userDirs.extraConfig.XDG_REPOS_DIR}/${name}/config.lua"; + internal = true; + }; + }; + + config = { + systemd.user = { + services.${name} = { + Install.WantedBy = [ "default.target" ]; + + Service = { + ExecStart = "${lib.getExe pkgs.imapfilter} -c ${cfg.configFile}"; + Type = "oneshot"; + }; + + Unit.Description = name; + }; + + timers.${name} = { + Install.WantedBy = [ "timers.target" ]; + + Timer = { + OnCalendar = "*-*-* 06..23:00/5"; + Unit = "${name}.service"; + }; + + Unit.Description = "Automatically runs email filters with imapfilter."; + }; + }; + }; +} diff --git a/home-manager/opdavies/t480.nix b/home-manager/opdavies/t480.nix new file mode 100644 index 00000000..b4826a3c --- /dev/null +++ b/home-manager/opdavies/t480.nix @@ -0,0 +1,37 @@ +{ config, pkgs, ... }: + +{ + programs = { + zsh.shellAliases = + let + inherit (config.xdg.userDirs) documents; + in + { + "wiki-push" = + "rsync -avzP ${documents}/wiki nixedo.oliverdavies.uk:${documents} --delete --delete-after"; + }; + }; + + home.packages = with pkgs; [ + backup-websites + build-glove80 + count-tags + create-script + get-tags + qrencode + mounter + move-firefox-screenshots + set-background + tag-release + time-until + timer + unmounter + update-all-git-repos + vic + ]; + + xdg.configFile."pam-gnupg".text = '' + 098EE055DAD2B9CB68154C6759DD38292D2273B6 + 1E21B58D69FFEFAD077F152A50FEA938A3413F50 + ''; +} diff --git a/hosts.ini b/hosts.ini deleted file mode 100644 index 45b5d232..00000000 --- a/hosts.ini +++ /dev/null @@ -1,2 +0,0 @@ -[localhost] -127.0.0.1 ansible_connection=local diff --git a/hosts/common/default.nix b/hosts/common/default.nix new file mode 100644 index 00000000..0421aa39 --- /dev/null +++ b/hosts/common/default.nix @@ -0,0 +1,102 @@ +{ + hostname, + inputs, + outputs, + pkgs, + self, + stateVersion, + system, + username, + ... +}: + +{ + imports = [ + ./users + + inputs.home-manager.nixosModules.home-manager + ]; + + nix = { + settings = { + auto-optimise-store = true; + + download-buffer-size = "104857600"; + + experimental-features = [ + "nix-command" + "flakes" + ]; + + warn-dirty = false; + }; + }; + + programs.zsh.enable = true; + + users.defaultUserShell = pkgs.zsh; + + environment.systemPackages = with pkgs; [ + cryptsetup + fastfetch + mermaid-cli + mkcert + ]; + + home-manager = { + backupFileExtension = "backup"; + + extraSpecialArgs = { + inherit + hostname + inputs + outputs + self + system + username + ; + }; + useGlobalPkgs = true; + useUserPackages = true; + + users."${username}" = import ./home.nix; + }; + + nixpkgs.overlays = [ + inputs.nur.overlays.default + + outputs.overlays.additions + outputs.overlays.modifications + outputs.overlays.stable-packages + ]; + + nix.extraOptions = '' + trusted-users = root ${username} + ''; + + networking.hostName = hostname; + + time.timeZone = "Europe/London"; + + i18n = { + defaultLocale = "en_GB.UTF-8"; + + extraLocaleSettings = { + LC_ADDRESS = "en_GB.UTF-8"; + LC_IDENTIFICATION = "en_GB.UTF-8"; + LC_MEASUREMENT = "en_GB.UTF-8"; + LC_MONETARY = "en_GB.UTF-8"; + LC_NAME = "en_GB.UTF-8"; + LC_NUMERIC = "en_GB.UTF-8"; + LC_PAPER = "en_GB.UTF-8"; + LC_TELEPHONE = "en_GB.UTF-8"; + LC_TIME = "en_GB.UTF-8"; + }; + }; + + console.keyMap = "uk"; + + security.sudo.wheelNeedsPassword = false; + + system.stateVersion = stateVersion; +} diff --git a/hosts/common/home.nix b/hosts/common/home.nix new file mode 100644 index 00000000..1f67d1e1 --- /dev/null +++ b/hosts/common/home.nix @@ -0,0 +1,102 @@ +{ + config, + inputs, + outputs, + system, + ... +}: +let + pkgs = import inputs.nixpkgs { + inherit system; + + overlays = [ + outputs.overlays.additions + outputs.overlays.stable-packages + ]; + }; + + inherit (pkgs) lib; + + inherit (config.xdg) + cacheHome + configHome + dataHome + stateHome + ; +in +{ + home.username = "opdavies"; + home.homeDirectory = "/home/${config.home.username}"; + + home.packages = with pkgs; [ + cachix + delta + entr + gcc + git + git-crypt + gnupg + inotify-tools + jq + killall + lua + mob + pv + simple-http-server + sshs + tldr + tree + tree-sitter + unzip + w3m + watchexec + wget + xclip + xdg-utils + zbar + ]; + + programs.home-manager.enable = true; + + home.sessionVariables = { + EDITOR = "nvim"; + IMAPFILTER_HOME = "${configHome}/imapfilter"; + LANG = "en_GB.UTF-8"; + LC_ALL = "en_GB.UTF-8"; + LC_CTYPE = "en_GB.UTF-8"; + PASSWORD_STORE_DIR = "${dataHome}/pass"; + PATH = lib.concatStringsSep ":" [ + "$PATH" + "$HOME/go/bin" + "./vendor/bin" + "./node_modules/.bin" + ]; + PULUMI_SKIP_UPDATE_CHECK = "true"; + W3M_DIR = "${stateHome}/w3m"; + WGETRC = "${configHome}/wgetrc"; + XDG_CONFIG_HOME = config.xdg.configHome; + XDG_DATA_HOME = dataHome; + XDG_STATE_HOME = stateHome; + }; + + xdg = { + configFile = { + "${config.home.sessionVariables.WGETRC}".text = '' + hsts-file = "${cacheHome}/wget-hsts" + ''; + }; + + userDirs = { + enable = true; + + extraConfig = { + XDG_REPOS_DIR = "${config.home.homeDirectory}/Code"; + }; + }; + }; + + # Nicely reload system units when changing configs. + systemd.user.startServices = "sd-switch"; + + home.stateVersion = "22.05"; # Please read the comment before changing. +} diff --git a/hosts/common/users/default.nix b/hosts/common/users/default.nix new file mode 100644 index 00000000..65787561 --- /dev/null +++ b/hosts/common/users/default.nix @@ -0,0 +1,5 @@ +{ + imports = [ + ./opdavies.nix + ]; +} diff --git a/hosts/common/users/opdavies.nix b/hosts/common/users/opdavies.nix new file mode 100644 index 00000000..3842a813 --- /dev/null +++ b/hosts/common/users/opdavies.nix @@ -0,0 +1,7 @@ +{ config, self, ... }: + +{ + users.users.opdavies = { }; + + home-manager.users.opdavies = import "${self}/home-manager/opdavies/${config.networking.hostName}.nix"; +} diff --git a/hosts/nixedo/configuration.nix b/hosts/nixedo/configuration.nix new file mode 100644 index 00000000..88d3920c --- /dev/null +++ b/hosts/nixedo/configuration.nix @@ -0,0 +1,51 @@ +# Edit this configuration file to define what should be installed on +# your system. Help is available in the configuration.nix(5) man page +# and in the NixOS manual (accessible by running ‘nixos-help’). + +{ inputs, pkgs, ... }: + +{ + imports = [ + inputs.agenix.nixosModules.default + + ../common + ./hardware-configuration.nix + ./homelab.nix + ./modules + ./ports.nix + ./secrets.nix + ./services + + ../../users/opdavies.nix + ]; + + # TODO: why didn't it work when adding this to jitsi.nix? + nixpkgs.config.permittedInsecurePackages = [ + "jitsi-meet-1.0.8043" + ]; + + services.logind.lidSwitchExternalPower = "ignore"; + + boot.loader = { + efi.canTouchEfiVariables = true; + systemd-boot.enable = true; + }; + + networking.networkmanager.enable = true; + + users.users.opdavies.extraGroups = [ "media" ]; + + powerManagement.powertop.enable = true; + + users.groups.media = { }; + + networking.firewall.allowedTCPPorts = [ + 80 + 443 + ]; + + environment.systemPackages = with pkgs; [ + tree + vim + ]; +} diff --git a/hosts/nixedo/hardware-configuration.nix b/hosts/nixedo/hardware-configuration.nix new file mode 100644 index 00000000..c2508935 --- /dev/null +++ b/hosts/nixedo/hardware-configuration.nix @@ -0,0 +1,54 @@ +# Do not modify this file! It was generated by ‘nixos-generate-config’ +# and may be overwritten by future invocations. Please make changes +# to /etc/nixos/configuration.nix instead. +{ + config, + lib, + pkgs, + modulesPath, + ... +}: + +{ + imports = [ + (modulesPath + "/installer/scan/not-detected.nix") + ]; + + boot.initrd.availableKernelModules = [ + "xhci_pci" + "thunderbolt" + "nvme" + "usb_storage" + "sd_mod" + ]; + boot.initrd.kernelModules = [ ]; + boot.kernelModules = [ "kvm-intel" ]; + boot.extraModulePackages = [ ]; + + fileSystems."/" = { + device = "/dev/disk/by-uuid/40649879-4ee6-4668-8257-fe81a7773024"; + fsType = "ext4"; + }; + + fileSystems."/boot" = { + device = "/dev/disk/by-uuid/24B1-88CB"; + fsType = "vfat"; + options = [ + "fmask=0077" + "dmask=0077" + ]; + }; + + swapDevices = [ ]; + + # Enables DHCP on each ethernet and wireless interface. In case of scripted networking + # (the default) this is the recommended approach. When using systemd-networkd it's + # still possible to use this option, but it's recommended to use it in conjunction + # with explicit per-interface declarations with `networking.interfaces..useDHCP`. + networking.useDHCP = lib.mkDefault true; + # networking.interfaces.enp0s20f0u1.useDHCP = lib.mkDefault true; + # networking.interfaces.wlo1.useDHCP = lib.mkDefault true; + + nixpkgs.hostPlatform = lib.mkDefault "x86_64-linux"; + hardware.cpu.intel.updateMicrocode = lib.mkDefault config.hardware.enableRedistributableFirmware; +} diff --git a/hosts/nixedo/homelab.nix b/hosts/nixedo/homelab.nix new file mode 100644 index 00000000..5e747cc9 --- /dev/null +++ b/hosts/nixedo/homelab.nix @@ -0,0 +1,21 @@ +{ + homelab = { + enable = true; + + cloudflared.tunnelId = "e1514105-327f-4984-974e-e2fbaca76466"; + + domain = "oliverdavies.uk"; + + services = { + audiobookshelf.enable = true; + home-assistant.enable = true; + homepage-dashboard.enable = true; + jitsi.enable = true; + paperless.enable = true; + peertube.enable = true; + tubearchivist.enable = true; + uptime-kuma.enable = true; + vaultwarden.enable = false; + }; + }; +} diff --git a/hosts/nixedo/modules/acme.nix b/hosts/nixedo/modules/acme.nix new file mode 100644 index 00000000..33979e9c --- /dev/null +++ b/hosts/nixedo/modules/acme.nix @@ -0,0 +1,57 @@ +{ config, ... }: + +{ + security.acme = { + acceptTerms = true; + + certs = + let + domain = "oliverdavies.uk"; + in + { + ${domain} = { + inherit domain; + + dnsProvider = "cloudflare"; + email = "oliver@oliverdavies.uk"; + environmentFile = config.age.secrets.cloudflare.path; + webroot = null; + + extraDomainNames = + let + subdomains = [ + "2020" + "audiobookshelf" + "bootstrap-with-tailwind" + "code" + "eric" + "florida-drupalcamp-tailwind-css" + "home" + "jellyfin" + "luke" + "mealie" + "nixedo" + "paperless" + "photos" + "phpsw-sculpin-demo" + "rebuilding-acquia" + "rebuilding-bartik" + "rebuilding-bristol-js" + "rebuilding-symfony" + "tailwindcss-demo" + "talking-drupal-tailwindcss" + "tubearchivist" + "uptime" + "vaultwarden" + "wp-tailwind" + "www" + "zet" + ]; + + domains = map (subdomain: "${subdomain}.${domain}") subdomains; + in + domains; + }; + }; + }; +} diff --git a/hosts/nixedo/modules/audiobookshelf.nix b/hosts/nixedo/modules/audiobookshelf.nix new file mode 100644 index 00000000..8e30bdd4 --- /dev/null +++ b/hosts/nixedo/modules/audiobookshelf.nix @@ -0,0 +1,55 @@ +{ config, lib, ... }: + +with lib; + +let + cfg = homelab.services.${service}; + homelab = config.homelab; + service = "audiobookshelf"; +in +{ + options.homelab.services.${service} = { + enable = mkEnableOption "Enable ${service}"; + + url = mkOption { + default = "audiobookshelf.${homelab.domain}"; + type = types.str; + }; + + homepage.name = mkOption { + default = "Audiobookshelf"; + type = types.str; + }; + + homepage.description = mkOption { + default = "Self-hosted audiobook and podcast server"; + type = types.str; + }; + + homepage.icon = mkOption { + default = "audiobookshelf"; + type = types.str; + }; + + homepage.category = mkOption { + default = "Media"; + type = types.str; + }; + }; + + config = mkIf cfg.enable { + services = { + ${service}.enable = true; + + nginx.virtualHosts.${cfg.url} = { + forceSSL = true; + useACMEHost = homelab.domain; + + locations."/" = { + proxyPass = "http://localhost:${toString config.services.${service}.port}"; + recommendedProxySettings = true; + }; + }; + }; + }; +} diff --git a/hosts/nixedo/modules/cloudflared.nix b/hosts/nixedo/modules/cloudflared.nix new file mode 100644 index 00000000..4ec15b0f --- /dev/null +++ b/hosts/nixedo/modules/cloudflared.nix @@ -0,0 +1,12 @@ +{ config, ... }: + +{ + services.cloudflared = { + enable = true; + + tunnels."e1514105-327f-4984-974e-e2fbaca76466" = { + credentialsFile = config.age.secrets.cloudflared.path; + default = "http_status:404"; + }; + }; +} diff --git a/hosts/nixedo/modules/containers/default.nix b/hosts/nixedo/modules/containers/default.nix new file mode 100644 index 00000000..346ef242 --- /dev/null +++ b/hosts/nixedo/modules/containers/default.nix @@ -0,0 +1,6 @@ +{ + imports = [ + # ./pi-hole.nix + ./tubearchivist.nix + ]; +} diff --git a/hosts/nixedo/modules/containers/pi-hole.nix b/hosts/nixedo/modules/containers/pi-hole.nix new file mode 100644 index 00000000..7d523e89 --- /dev/null +++ b/hosts/nixedo/modules/containers/pi-hole.nix @@ -0,0 +1,40 @@ +{ config, lib, ... }: + +let + service = "pihole"; + port = config.homelab.ports.${service}; +in +{ + virtualisation.oci-containers.containers.${service} = { + image = "pihole/pihole:latest"; + + environment = { + PIHOLE_DNS_1 = "8.8.8.8"; + PIHOLE_DNS_2 = "8.8.4.4"; + TZ = "Europe/London"; + }; + + volumes = [ + "/home/opdavies/pihole/etc-dnsmasq.d:/etc/dnsmasq.d:rw" + "/home/opdavies/pihole/etc-pihole:/etc/pihole:rw" + ]; + + ports = [ + "53:53/tcp" + "53:53/udp" + "67:67/udp" + "${port}:80/tcp" + ]; + + log-driver = "journald"; + + extraOptions = [ + "--cap-add=NET_ADMIN" + ]; + }; + + systemd.services."podman-pihole".serviceConfig = { + Restart = lib.mkOverride 90 "always"; + RestartSec = lib.mkOverride 90 "1s"; + }; +} diff --git a/hosts/nixedo/modules/containers/tubearchivist.nix b/hosts/nixedo/modules/containers/tubearchivist.nix new file mode 100644 index 00000000..76212f0d --- /dev/null +++ b/hosts/nixedo/modules/containers/tubearchivist.nix @@ -0,0 +1,334 @@ +{ + config, + inputs, + lib, + pkgs, + ... +}: + +with lib; + +let + cfg = homelab.services.${service}; + service = "tubearchivist"; + homelab = config.homelab; + + port = homelab.ports.${service}; +in +{ + options.homelab.services.${service} = { + enable = mkEnableOption "Enable ${service}"; + + url = mkOption { + default = "${service}.${homelab.domain}"; + type = types.str; + }; + + homepage.name = mkOption { + default = "Tube Archivist"; + type = types.str; + }; + + homepage.description = mkOption { + default = "Your self hosted YouTube media server"; + type = types.str; + }; + + homepage.icon = mkOption { + default = "tube-archivist"; + type = types.str; + }; + + homepage.category = mkOption { + default = "Media"; + type = types.str; + }; + }; + + config = mkIf cfg.enable { + virtualisation = { + oci-containers.backend = "podman"; + podman.enable = true; + }; + + virtualisation.oci-containers.containers."archivist-es" = { + image = "bbilly1/tubearchivist-es"; + + environment = { + "ES_JAVA_OPTS" = "-Xms1g -Xmx1g"; + "discovery.type" = "single-node"; + "path.repo" = "/usr/share/elasticsearch/data/snapshot"; + "xpack.security.enabled" = "true"; + "cluster.routing.allocation.disk.watermark.flood_stage" = "98%"; + "cluster.routing.allocation.disk.watermark.high" = "97%"; + "cluster.routing.allocation.disk.watermark.low" = "95%"; + }; + + environmentFiles = [ + config.age.secrets.tubearchivist-env.path + ]; + + volumes = [ + "tubearchivist_es:/usr/share/elasticsearch/data:rw" + ]; + + log-driver = "journald"; + + extraOptions = [ + "--network-alias=archivist-es" + "--network=tubearchivist_default" + ]; + }; + + systemd.services."podman-archivist-es" = { + serviceConfig = { + Restart = mkOverride 90 "always"; + RestartMaxDelaySec = mkOverride 90 "1m"; + RestartSec = mkOverride 90 "100ms"; + RestartSteps = mkOverride 90 9; + }; + + after = [ + "podman-network-tubearchivist_default.service" + "podman-volume-tubearchivist_es.service" + ]; + + requires = [ + "podman-network-tubearchivist_default.service" + "podman-volume-tubearchivist_es.service" + ]; + + partOf = [ + "podman-compose-tubearchivist-root.target" + ]; + + wantedBy = [ + "podman-compose-tubearchivist-root.target" + ]; + }; + + virtualisation.oci-containers.containers."archivist-redis" = { + image = "redis"; + + volumes = [ + "tubearchivist_redis:/data:rw" + ]; + + dependsOn = [ + "archivist-es" + ]; + + log-driver = "journald"; + + extraOptions = [ + "--network-alias=archivist-redis" + "--network=tubearchivist_default" + ]; + }; + + systemd.services."podman-archivist-redis" = { + serviceConfig = { + Restart = mkOverride 90 "always"; + RestartMaxDelaySec = mkOverride 90 "1m"; + RestartSec = mkOverride 90 "100ms"; + RestartSteps = mkOverride 90 9; + }; + + after = [ + "podman-network-tubearchivist_default.service" + "podman-volume-tubearchivist_redis.service" + ]; + + requires = [ + "podman-network-tubearchivist_default.service" + "podman-volume-tubearchivist_redis.service" + ]; + + partOf = [ + "podman-compose-tubearchivist-root.target" + ]; + + wantedBy = [ + "podman-compose-tubearchivist-root.target" + ]; + }; + + virtualisation.oci-containers.containers."tubearchivist" = { + image = "bbilly1/tubearchivist"; + + environment = { + "ES_URL" = "http://archivist-es:9200"; + "HOST_GID" = "1000"; + "HOST_UID" = "1000"; + "REDIS_CON" = "redis://archivist-redis:6379"; + "TA_HOST" = "https://${cfg.url}"; + "TZ" = "Europe/London"; + }; + + environmentFiles = [ + config.age.secrets.tubearchivist-env.path + ]; + + volumes = [ + "/mnt/media/${service}/cache:/cache:rw" + "/mnt/media/${service}/media:/youtube:rw" + ]; + + ports = [ + "${toString port}:8000/tcp" + ]; + + dependsOn = [ + "archivist-es" + "archivist-redis" + ]; + + log-driver = "journald"; + + extraOptions = [ + "--health-cmd=[\"curl\", \"-f\", \"http://localhost:8000/health\"]" + "--health-interval=2m0s" + "--health-retries=3" + "--health-start-period=30s" + "--health-timeout=10s" + "--network-alias=tubearchivist" + "--network=tubearchivist_default" + ]; + }; + + systemd.services."podman-tubearchivist" = { + serviceConfig = { + Restart = mkOverride 90 "always"; + RestartMaxDelaySec = mkOverride 90 "1m"; + RestartSec = mkOverride 90 "100ms"; + RestartSteps = mkOverride 90 9; + }; + + after = [ + "podman-network-tubearchivist_default.service" + "podman-volume-tubearchivist_cache.service" + "podman-volume-tubearchivist_media.service" + ]; + + requires = [ + "podman-network-tubearchivist_default.service" + "podman-volume-tubearchivist_cache.service" + "podman-volume-tubearchivist_media.service" + ]; + + partOf = [ + "podman-compose-tubearchivist-root.target" + ]; + + wantedBy = [ + "podman-compose-tubearchivist-root.target" + ]; + }; + + systemd.services."podman-network-tubearchivist_default" = { + path = [ pkgs.podman ]; + + serviceConfig = { + Type = "oneshot"; + RemainAfterExit = true; + ExecStop = "podman network rm -f tubearchivist_default"; + }; + + script = '' + podman network inspect tubearchivist_default || podman network create tubearchivist_default + ''; + + partOf = [ "podman-compose-tubearchivist-root.target" ]; + wantedBy = [ "podman-compose-tubearchivist-root.target" ]; + }; + + systemd.services."podman-volume-tubearchivist_cache" = { + path = [ pkgs.podman ]; + + serviceConfig = { + Type = "oneshot"; + RemainAfterExit = true; + }; + + script = '' + podman volume inspect tubearchivist_cache || podman volume create tubearchivist_cache + ''; + + partOf = [ "podman-compose-tubearchivist-root.target" ]; + wantedBy = [ "podman-compose-tubearchivist-root.target" ]; + }; + + systemd.services."podman-volume-tubearchivist_es" = { + path = [ pkgs.podman ]; + + serviceConfig = { + Type = "oneshot"; + RemainAfterExit = true; + }; + + script = '' + podman volume inspect tubearchivist_es || podman volume create tubearchivist_es + ''; + + partOf = [ "podman-compose-tubearchivist-root.target" ]; + wantedBy = [ "podman-compose-tubearchivist-root.target" ]; + }; + + systemd.services."podman-volume-tubearchivist_media" = { + path = [ pkgs.podman ]; + + serviceConfig = { + Type = "oneshot"; + RemainAfterExit = true; + }; + + script = '' + podman volume inspect tubearchivist_media || podman volume create tubearchivist_media + ''; + + partOf = [ "podman-compose-tubearchivist-root.target" ]; + wantedBy = [ "podman-compose-tubearchivist-root.target" ]; + }; + + systemd.services."podman-volume-tubearchivist_redis" = { + path = [ pkgs.podman ]; + + serviceConfig = { + Type = "oneshot"; + RemainAfterExit = true; + }; + + script = '' + podman volume inspect tubearchivist_redis || podman volume create tubearchivist_redis + ''; + + partOf = [ "podman-compose-tubearchivist-root.target" ]; + wantedBy = [ "podman-compose-tubearchivist-root.target" ]; + }; + + systemd.targets."podman-compose-tubearchivist-root" = { + unitConfig = { + Description = "Root target generated by compose2nix."; + }; + + wantedBy = [ "multi-user.target" ]; + }; + + services.nginx.virtualHosts."${cfg.url}" = { + forceSSL = true; + useACMEHost = homelab.domain; + + locations."/" = { + proxyPass = "http://localhost:${toString port}"; + recommendedProxySettings = true; + proxyWebsockets = true; + + extraConfig = '' + proxy_buffering off; + ''; + }; + }; + + age.secrets.tubearchivist-env.file = "${inputs.self}/secrets/tubearchivist-env.age"; + }; +} diff --git a/hosts/nixedo/modules/default.nix b/hosts/nixedo/modules/default.nix new file mode 100644 index 00000000..20a9d6cf --- /dev/null +++ b/hosts/nixedo/modules/default.nix @@ -0,0 +1,34 @@ +{ lib, ... }: + +with lib; + +{ + options.homelab = { + enable = mkEnableOption "Enable homelab services and configuration"; + + cloudflared.tunnelId = mkOption { + example = "00000000-0000-0000-0000-000000000000"; + type = types.str; + }; + + domain = mkOption { + description = "The base domain to use for this homelab."; + type = types.str; + }; + }; + + imports = [ + ./acme.nix + ./audiobookshelf.nix + ./cloudflared.nix + ./containers + ./forgejo.nix + ./home-assistant.nix + ./immich.nix + ./jellyfin.nix + ./jitsi.nix + ./nginx + ./paperless.nix + ./peertube.nix + ]; +} diff --git a/hosts/nixedo/modules/forgejo.nix b/hosts/nixedo/modules/forgejo.nix new file mode 100644 index 00000000..91a228d6 --- /dev/null +++ b/hosts/nixedo/modules/forgejo.nix @@ -0,0 +1,26 @@ +{ config, ... }: + +{ + services.forgejo = { + enable = true; + stateDir = "/var/www/forgejo"; + + settings = { + server = { + DOMAIN = "code.oliverdavies.uk"; + LANDING_PAGE = "explore"; + ROOT_URL = "https://${config.services.forgejo.settings.server.DOMAIN}"; + SSH_DOMAIN = "ssh.oliverdavies.uk"; + }; + + service.DISABLE_REGISTRATION = true; + + ui.DEFAULT_THEME = "forgejo-auto"; + }; + }; + + services.cloudflared.tunnels.${config.homelab.cloudflared.tunnelId}.ingress = { + "${config.services.forgejo.settings.server.DOMAIN}" = + "http://localhost:${toString config.services.forgejo.settings.server.HTTP_PORT}"; + }; +} diff --git a/hosts/nixedo/modules/home-assistant.nix b/hosts/nixedo/modules/home-assistant.nix new file mode 100644 index 00000000..2995ade3 --- /dev/null +++ b/hosts/nixedo/modules/home-assistant.nix @@ -0,0 +1,97 @@ +{ config, lib, ... }: + +with lib; + +let + cfg = homelab.services.${service}; + homelab = config.homelab; + service = "home-assistant"; +in +{ + options.homelab.services.${service} = { + enable = mkEnableOption "Enable ${service}"; + + url = mkOption { + default = "home.${homelab.domain}"; + type = types.str; + }; + + homepage.name = mkOption { + default = "Home Assisant"; + type = types.str; + }; + + homepage.description = mkOption { + default = "Open source home automation that puts local control and privacy first."; + type = types.str; + }; + + homepage.icon = mkOption { + default = "home-assistant"; + type = types.str; + }; + + homepage.category = mkOption { + default = "Services"; + type = types.str; + }; + }; + + config = mkIf cfg.enable { + services = { + home-assistant = { + enable = true; + + config = { + external_url = "https://home.${homelab.domain}"; + name = "Home"; + time_zone = "Europe/London"; + unit_system = "metric"; + + http = { + trusted_proxies = [ + "127.0.0.1" + "::1" + ]; + use_x_forwarded_for = true; + }; + + mobile_app = { }; + # sia = { }; + }; + + extraComponents = [ + "default_config" + "elgato" + "hive" + "met" + "mobile_app" + # "sia" + "tplink" + "tplink_tapo" + "weather" + "webostv" + "wiz" + ]; + + extraPackages = + python3Packages: with python3Packages; [ + setuptools + ]; + + openFirewall = true; + }; + + nginx.virtualHosts."${cfg.url}" = { + forceSSL = true; + useACMEHost = homelab.domain; + + locations."/" = { + proxyPass = "http://localhost:${toString config.services.${service}.config.http.server_port}"; + proxyWebsockets = true; + recommendedProxySettings = true; + }; + }; + }; + }; +} diff --git a/hosts/nixedo/modules/immich.nix b/hosts/nixedo/modules/immich.nix new file mode 100644 index 00000000..24328d1b --- /dev/null +++ b/hosts/nixedo/modules/immich.nix @@ -0,0 +1,25 @@ +{ config, pkgs, ... }: + +{ + services.immich = { + enable = true; + group = "media"; + mediaLocation = "/mnt/media/immich"; + }; + + services.nginx.virtualHosts."photos.oliverdavies.uk" = { + forceSSL = true; + useACMEHost = "oliverdavies.uk"; + + locations."/" = { + proxyPass = "http://localhost:${toString config.services.immich.port}"; + proxyWebsockets = true; + recommendedProxySettings = true; + }; + }; + + environment.systemPackages = with pkgs; [ + immich-cli + immich-go + ]; +} diff --git a/hosts/nixedo/modules/jellyfin.nix b/hosts/nixedo/modules/jellyfin.nix new file mode 100644 index 00000000..430fac28 --- /dev/null +++ b/hosts/nixedo/modules/jellyfin.nix @@ -0,0 +1,23 @@ +{ + services.jellyfin = { + enable = true; + + configDir = "/mnt/media/jellyfin"; + group = "media"; + openFirewall = true; + }; + + services.nginx.virtualHosts."jellyfin.oliverdavies.uk" = { + forceSSL = true; + useACMEHost = "oliverdavies.uk"; + + locations."/" = { + proxyPass = "http://localhost:8096"; + recommendedProxySettings = true; + + extraConfig = '' + proxy_buffering off; + ''; + }; + }; +} diff --git a/hosts/nixedo/modules/jitsi.nix b/hosts/nixedo/modules/jitsi.nix new file mode 100644 index 00000000..fbe216e3 --- /dev/null +++ b/hosts/nixedo/modules/jitsi.nix @@ -0,0 +1,41 @@ +{ config, lib, ... }: + +let + cfg = config.homelab.services.${service}; + homelab = config.homelab; + service = "jitsi"; + + inherit (lib) mkEnableOption mkOption types; +in +{ + options.homelab.services.${service} = { + enable = mkEnableOption "Enable ${service}"; + + url = mkOption { + default = "meet.${homelab.domain}"; + type = types.str; + }; + }; + + config = lib.mkIf cfg.enable { + services = { + jitsi-meet = { + enable = false; + + hostName = cfg.url; + + secureDomain.enable = true; + }; + + nginx.virtualHosts.${cfg.url} = { + enableACME = false; + forceSSL = false; + }; + + cloudflared.tunnels.${homelab.cloudflared.tunnelId}.ingress = { + # TODO: is this the correct port? + ${cfg.url} = "http://localhost:5280"; + }; + }; + }; +} diff --git a/hosts/nixedo/modules/nginx/default.nix b/hosts/nixedo/modules/nginx/default.nix new file mode 100644 index 00000000..b28403e0 --- /dev/null +++ b/hosts/nixedo/modules/nginx/default.nix @@ -0,0 +1,55 @@ +{ config, ... }: + +let + sites = import ./sites.nix { ports = config.homelab.ports; }; +in +{ + services = { + nginx = { + enable = true; + + virtualHosts = builtins.listToAttrs ( + map (site: { + name = site.url; + + value = { + root = site.root; + + listen = [ + { + addr = "localhost"; + port = site.port; + } + ]; + + locations."/".tryFiles = "$uri $uri/index.html =404"; + + extraConfig = builtins.concatStringsSep "\n\n" [ + site.extraConfig or "" + + '' + port_in_redirect off; + + # Remove trailing slashes. + rewrite ^/(.*)/$ /$1 permanent; + '' + ]; + }; + }) sites + ); + }; + + cloudflared.tunnels."e1514105-327f-4984-974e-e2fbaca76466" = { + ingress = builtins.listToAttrs ( + map (site: { + name = site.url; + value = "http://localhost:${toString site.port}"; + }) sites + ); + }; + }; + + users.users.${config.services.nginx.user}.extraGroups = [ "acme" ]; + + imports = [ ./www.oliverdavies.uk ]; +} diff --git a/hosts/nixedo/modules/nginx/sites.nix b/hosts/nixedo/modules/nginx/sites.nix new file mode 100644 index 00000000..3d682ec7 --- /dev/null +++ b/hosts/nixedo/modules/nginx/sites.nix @@ -0,0 +1,51 @@ +{ ports }: + +let + mkSite = + name: overrides: + let + root = "/var/www/vhosts/${name}" + (overrides.rootSuffix or ""); + port = ports."nginx-${name}"; + url = "${name}.oliverdavies.uk"; + in + { inherit port root url; } // overrides; + + sites = [ + (mkSite "books" {}) + + (mkSite "eric" { + rootSuffix = "/public"; + + extraConfig = '' + add_header X-Robots-Tag "noindex, nofollow"; + ''; + }) + + (mkSite "examples" {}) + ] + ++ + map + ( + domain: + mkSite domain { + extraConfig = '' + add_header X-Robots-Tag "noindex, nofollow"; + ''; + } + ) + [ + "bootstrap-with-tailwind" + "florida-drupalcamp-tailwind-css" + "luke" + "phpsw-sculpin-demo" + "rebuilding-acquia" + "rebuilding-bartik" + "rebuilding-bristol-js" + "rebuilding-symfony" + "tailwindcss-demo" + "talking-drupal-tailwindcss" + "wp-tailwind" + "zet" + ]; +in +sites diff --git a/hosts/nixedo/modules/nginx/www.oliverdavies.uk/default.nix b/hosts/nixedo/modules/nginx/www.oliverdavies.uk/default.nix new file mode 100644 index 00000000..cfae1427 --- /dev/null +++ b/hosts/nixedo/modules/nginx/www.oliverdavies.uk/default.nix @@ -0,0 +1,89 @@ +{ config, ... }: + +let + ports = config.homelab.ports; + port = ports.nginx-website-sculpin; + + redirects = builtins.concatStringsSep "\n" ( + map (r: "rewrite ^${r.from}/?$ ${r.to} redirect;") (import ./redirects.nix) + ); + + tome = { + root = "/var/www/vhosts/website-tome"; + + paths = [ + "archive" + "automated-testing" + "core" + "daily/.+" + "examples" + "homelab" + "podcast" + "rss/bb.xml" + "rss/daily.xml" + "sites/default/files" + "testing" + "themes/custom/opdavies" + ]; + + port = ports.nginx-website-tome; + }; + + tomeLocations = builtins.listToAttrs ( + map (path: { + name = "~ ^/${path}"; + + value = { + root = tome.root; + tryFiles = "$uri $uri.html $uri/index.html =404"; + }; + }) tome.paths + ); +in +{ + services = { + nginx.virtualHosts = { + "www.oliverdavies.uk" = { + root = "/var/www/vhosts/website-sculpin"; + + listen = [ + { + inherit port; + + addr = "localhost"; + } + ]; + + locations = tomeLocations // { + "/".tryFiles = "$uri $uri.html $uri/index.html =404"; + }; + + extraConfig = '' + port_in_redirect off; + + # Remove trailing slashes. + rewrite ^/(.*)/$ /$1 permanent; + + error_page 404 /404; + + rewrite ^/talks/archive/?$ /talks permanent; + rewrite ^/talks/(.*)$ /presentations/$1 permanent; + rewrite ^/talks/?$ /presentations permanent; + + ${redirects} + ''; + }; + + "oliverdavies.uk" = { + forceSSL = true; + globalRedirect = "www.oliverdavies.uk"; + useACMEHost = "oliverdavies.uk"; + }; + }; + + cloudflared.tunnels."e1514105-327f-4984-974e-e2fbaca76466".ingress = { + "oliverdavies.uk" = "http://localhost:${toString port}"; + "www.oliverdavies.uk" = "http://localhost:${toString port}"; + }; + }; +} diff --git a/hosts/nixedo/modules/nginx/www.oliverdavies.uk/redirects.nix b/hosts/nixedo/modules/nginx/www.oliverdavies.uk/redirects.nix new file mode 100644 index 00000000..56bc82e9 --- /dev/null +++ b/hosts/nixedo/modules/nginx/www.oliverdavies.uk/redirects.nix @@ -0,0 +1,3074 @@ +[ + { + from = "/10-useful-drupal-6-modules-i-use-every-project"; + to = "/blog/10-useful-drupal-6-modules"; + } + { + from = "/2010/04/05/styling-drupal-6s-taxonomy-lists-with-php-css-and-jquery"; + to = "/blog/style-drupal-6s-taxonomy-lists-php-css-jquery"; + } + { + from = "/2010/04/28/using-imagecache-and-imagecrop-for-my-portfolio"; + to = "/blog/using-imagecache-imagecrop-my-portfolio"; + } + { + from = "/2010/05/29/importing-images-using-the-imagefieldimport-module"; + to = "/blog/quickly-import-multiples-images-using-imagefieldimport-module"; + } + { + from = "/2010/06/23/creating-a-block-of-social-media-icons-using-cck-views-and-nodequeue"; + to = "/blog/create-block-social-media-icons-using-cck-views-nodequeue"; + } + { + from = "/2010/07/05/thanks"; + to = "/blog/thanks"; + } + { + from = "/2010/08/17/create-a-better-photo-gallery-in-drupal-part-2"; + to = "/blog/create-better-photo-gallery-drupal-part-2"; + } + { + from = "/2014/05/21/git-format-patch"; + to = "/blog/git-format-patch-your-friend"; + } + { + from = "/2PxmyqP"; + to = "/articles/examples-of-laravel-collections-in-drupal"; + } + { + from = "/39CoG"; + to = "/articles/drupalcamp-london-testing-workshop"; + } + { + from = "/3eGQr"; + to = "https://github.com/howToCodeWell/howToCodeWellFM/blob/c927e0b3589f1d7375002f7fd70f0bfc9fc90449/composer.json#L17"; + } + { + from = "/6UhLN"; + to = "https://github.com/opdavies/sculpin-twig-markdown-bundle/pull/1"; + } + { + from = "/6i3YZ"; + to = "https://www.youtube.com/watch?v=vUK5sEbd-dk"; + } + { + from = "/9rv0Z"; + to = "https://www.drupal.org/project/override_node_options/issues/3109852"; + } + { + from = "/BhMZi"; + to = "https://git.drupalcode.org/search?utf8=%E2%9C%93&snippets=&scope=&repository_ref=8.x-1.x&search=baz&project_id=23203"; + } + { + from = "/NBi5h"; + to = "https://git.drupalcode.org/search?utf8=%E2%9C%93&search=bar&group_id=&project_id=23203&search_code=true&repository_ref=8.x-1.x&nav_source=navbar"; + } + { + from = "/P5KQ5"; + to = "https://www.npmjs.com/package/tailwindcss-skip-link"; + } + { + from = "/S8ZDA"; + to = "/articles/rebuilding-bartik-with-vuejs-tailwind-css-part-2"; + } + { + from = "/Wh48P"; + to = "https://github.com/opdavies/oliverdavies.uk/blob/master/source/_partials/talk/video.html.twig"; + } + { + from = "/XbzS2"; + to = "https://github.com/opdavies/gmail-filter-builder"; + } + { + from = "/YK1VH"; + to = "/articles/psr4-autoloading-test-cases-drupal-7"; + } + { + from = "/YilTZ$"; + to = "https://drupalcamp.london/tickets/training"; + } + { + from = "/about"; + to = "/"; + } + { + from = "/about/cv"; + to = "/cv"; + } + { + from = "/about/speaker"; + to = "/speaker"; + } + { + from = "/about/speaker-information"; + to = "/speaker-information"; + } + { + from = "/acquia-certifications"; + to = "https://certification.acquia.com/registry?fname=Oliver&lname=Davies&city=&state=&country=United+Kingdom&org=&exam=All"; + } + { + from = "/acquia-certified"; + to = "https://certification.acquia.com/?fname=Oliver&lname=Davies"; + } + { + from = "/ansible"; + to = "https://galaxy.ansible.com/opdavies"; + } + { + from = "/ansible-molecule"; + to = "/articles/test-driven-ansible-role-development-molecule"; + } + { + from = "/ansistrano-code"; + to = "https://github.com/opdavies/dransible"; + } + { + from = "/ansistrano-demo"; + to = "https://www.youtube.com/watch?v=PLS4ET7FAcU"; + } + { + from = "/ansistrano-slides"; + to = "/talks/deploying-php-ansible-ansistrano"; + } + { + from = "/archive"; + to = "/blog"; + } + { + from = "/archive/2022-08-28/how-started-programming"; + to = "/daily/2022-08-28/how-started-programming"; + } + { + from = "/archive/2022/08/20/return-to-offline-meetups-conferences"; + to = "/daily/2022/08/20/return-to-offline-meetups-conferences"; + } + { + from = "/archive/2022/08/23/git-gui-command-line"; + to = "/daily/2022/08/23/git-gui-command-line"; + } + { + from = "/archive/2022/08/25/why-i-work-in-neovim"; + to = "/daily/2022/08/25/why-i-work-in-neovim"; + } + { + from = "/archive/2022/08/26/always-be-learning"; + to = "/daily/2022/08/26/always-be-learning"; + } + { + from = "/archive/2022/08/27/giving-back"; + to = "/daily/2022/08/27/giving-back"; + } + { + from = "/archive/2022/08/29/why-like-drupal"; + to = "/daily/2022/08/29/why-like-drupal"; + } + { + from = "/archive/2022/08/30/why-dont-only-use-drupal"; + to = "/daily/2022/08/30/why-dont-only-use-drupal"; + } + { + from = "/archive/2022/08/31/monorepo-or-not"; + to = "/daily/2022/08/31/monorepo-or-not"; + } + { + from = "/archive/2022/09/01/conventional-commits-changelogs"; + to = "/daily/2022/09/01/conventional-commits-changelogs"; + } + { + from = "/archive/2022/09/02/automating-all-the-things-with-ansible"; + to = "/daily/2022/09/02/automating-all-the-things-with-ansible"; + } + { + from = "/archive/2022/09/04/using-ansible-for-server-configuration"; + to = "/daily/2022/09/04/using-ansible-for-server-configuration"; + } + { + from = "/archive/2022/09/05/using-ansible-for-local-configuration"; + to = "/daily/2022/09/05/using-ansible-for-local-configuration"; + } + { + from = "/archive/2022/09/06/deploying-applications-with-ansible"; + to = "/daily/2022/09/06/deploying-applications-with-ansible"; + } + { + from = "/archive/2022/09/07/my-tailwind-css-origin-story"; + to = "/daily/2022/09/07/my-tailwind-css-origin-story"; + } + { + from = "/archive/2022/09/08/keeping-secrets-with-ansible-vault"; + to = "/daily/2022/09/08/keeping-secrets-with-ansible-vault"; + } + { + from = "/archive/2022/09/09/refactoring-tailwind-component"; + to = "/daily/2022/09/09/refactoring-tailwind-component"; + } + { + from = "/archive/2022/09/10/automating-ansible-deployments-ci"; + to = "/daily/2022/09/10/automating-ansible-deployments-ci"; + } + { + from = "/archive/2022/09/11/custom-styles-tailwind-css-apply-theme-custom-plugins"; + to = "/daily/2022/09/11/custom-styles-tailwind-css-apply-theme-custom-plugins"; + } + { + from = "/archive/2022/09/12/month-/daily-emails"; + to = "daily/2022/09/12/month-daily-emails"; + } + { + from = "/archive/2022/09/14/simpletest-drupal-test"; + to = "/daily/2022/09/14/simpletest-drupal-test"; + } + { + from = "/archive/2022/09/16/why-mostly-write-functional-and-integration-tests"; + to = "/daily/2022/09/16/why-mostly-write-functional-and-integration-tests"; + } + { + from = "/archive/2022/09/17/thoughts-automated-code-formatting"; + to = "/daily/2022/09/17/thoughts-automated-code-formatting"; + } + { + from = "/archive/2022/09/19/useful-git-configuration"; + to = "/daily/2022/09/19/useful-git-configuration"; + } + { + from = "/archive/2022/09/20/why-like-trunk-based-development"; + to = "/daily/2022/09/20/why-like-trunk-based-development"; + } + { + from = "/archive/2022/09/21/being-drupal-contribution-mentor"; + to = "/daily/2022/09/21/being-drupal-contribution-mentor"; + } + { + from = "/archive/2022/09/22/releasing-drupal-module-template"; + to = "/daily/2022/09/22/releasing-drupal-module-template"; + } + { + from = "/archive/2022/09/23/adrs-technical-design-documents"; + to = "/daily/2022/09/23/adrs-technical-design-documents"; + } + { + from = "/archive/2022/09/25/using-component-library-for-front-end-development"; + to = "/daily/2022/09/25/using-component-library-for-front-end-development"; + } + { + from = "/archive/2022/09/26/experimenting-with-the-nix-package-manager"; + to = "/daily/2022/09/26/experimenting-with-the-nix-package-manager"; + } + { + from = "/archive/2022/09/27/mentoring-with-drupal-career-online"; + to = "/daily/2022/09/27/mentoring-with-drupal-career-online"; + } + { + from = "/archive/2022/09/28/mob-programming-php-south-wales"; + to = "/daily/2022/09/28/mob-programming-php-south-wales"; + } + { + from = "/archive/2022/09/30/store-wars-vuejs"; + to = "/daily/2022/09/30/store-wars-vuejs"; + } + { + from = "/archive/2022/10/12/overcoming-deployment-anxiety"; + to = "/daily/2022/10/12/overcoming-deployment-anxiety"; + } + { + from = "/archive/2022/10/17/14-years-drupalorg"; + to = "/daily/2022/10/17/14-years-drupalorg"; + } + { + from = "/archive/2022/10/18/pair-mob-programming"; + to = "/daily/2022/10/18/pair-mob-programming"; + } + { + from = "/archive/2022/10/20/cherry-picking-commits-is-an-anti-pattern"; + to = "/daily/2022/10/20/cherry-picking-commits-is-an-anti-pattern"; + } + { + from = "/archive/2022/10/20/run-vs-task-runners/?"; + to = "/archive/2022/10/19/run-vs-task-runners"; + } + { + from = "/archive/2022/10/21/automated-testing-and-test-driven-development-are-not-the-same"; + to = "/daily/2022/10/21/automated-testing-and-test-driven-development-are-not-the-same"; + } + { + from = "/archive/2022/10/24/looking-at-localgov-drupal"; + to = "/daily/2022/10/24/looking-at-localgov-drupal"; + } + { + from = "/archive/2022/10/25/what-are-drupal-distributions"; + to = "/daily/2022/10/25/what-are-drupal-distributions"; + } + { + from = "/archive/2022/10/26/neovim-as-a-personalised-development-environment"; + to = "/daily/2022/10/26/neovim-as-a-personalised-development-environment"; + } + { + from = "/archive/2022/10/27/getting-back-into-live-streaming"; + to = "/daily/2022/10/27/getting-back-into-live-streaming"; + } + { + from = "/archive/2022/10/28/why-write-framework-agnostic-packages"; + to = "/daily/2022/10/28/why-write-framework-agnostic-packages"; + } + { + from = "/archive/2022/10/29/the-open-source-first-development-workflow"; + to = "/daily/2022/10/29/the-open-source-first-development-workflow"; + } + { + from = "/archive/2022/10/30/refactoring-one-large-test-into-multiple-smaller-tests"; + to = "/daily/2022/10/30/refactoring-one-large-test-into-multiple-smaller-tests"; + } + { + from = "/archive/2022/11/08/are-sprints-incompatible-with-continuous-deployment"; + to = "/daily/2022/11/08/are-sprints-incompatible-with-continuous-deployment"; + } + { + from = "/archive/2022/11/09/your-conference-talk-has-been-accepted"; + to = "/daily/2022/11/09/your-conference-talk-has-been-accepted"; + } + { + from = "/archive/2022/11/12/building-a-minimum-viable-product-and-managing-technical-debt"; + to = "/daily/2022/11/12/building-a-minimum-viable-product-and-managing-technical-debt"; + } + { + from = "/archive/2022/11/12/creating-small-proof-of-concept-application-afternoon"; + to = "/daily/2022/11/12/creating-small-proof-of-concept-application-afternoon"; + } + { + from = "/archive/2022/11/13/how-i-manage-multiple-drupal-websites-using-the-same-codebase"; + to = "/daily/2022/11/13/how-i-manage-multiple-drupal-websites-using-the-same-codebase"; + } + { + from = "/archive/2022/11/14/camel-case-or-snake-case-for-test-methods"; + to = "/daily/2022/11/14/camel-case-or-snake-case-for-test-methods"; + } + { + from = "/archive/2022/11/15/writing-good-automated-test-names"; + to = "/daily/2022/11/15/writing-good-automated-test-names"; + } + { + from = "/archive/2022/11/16/why-don't-you-write-automated-tests"; + to = "/daily/2022/11/16/why-don't-you-write-automated-tests"; + } + { + from = "/archive/2022/11/17/agnostic-ci-pipelines-with-run-files"; + to = "/daily/2022/11/17/agnostic-ci-pipelines-with-run-files"; + } + { + from = "/archive/2022/11/18/one-test-a-day-keeps-bugs-away"; + to = "/daily/2022/11/18/one-test-a-day-keeps-bugs-away"; + } + { + from = "/archive/2022/11/19/are-missing-tests-a-blocker-to-refactoring"; + to = "/daily/2022/11/19/are-missing-tests-a-blocker-to-refactoring"; + } + { + from = "/archive/2022/11/20/version-controlled-commented-out-code"; + to = "/daily/2022/11/20/version-controlled-commented-out-code"; + } + { + from = "/archive/2022/11/21/git-tricks-to-avoid-committing-commented-out-and-other-unneeded-code"; + to = "/daily/2022/11/21/git-tricks-to-avoid-committing-commented-out-and-other-unneeded-code"; + } + { + from = "/archive/2022/11/22/tldr"; + to = "/daily/2022/11/22/tldr"; + } + { + from = "/archive/2022/11/23/do-you-need-to-branch"; + to = "/daily/2022/11/23/do-you-need-to-branch"; + } + { + from = "/archive/2022/11/24/doing-the-simplest-possible-thing"; + to = "/daily/2022/11/24/doing-the-simplest-possible-thing"; + } + { + from = "/archive/2022/11/25/plan-then-code"; + to = "/daily/2022/11/25/plan-then-code"; + } + { + from = "/archive/2022/11/30/ship-show-or-ask"; + to = "/daily/2022/11/30/ship-show-or-ask"; + } + { + from = "/archive/2022/12/01/writing-readable-code"; + to = "/daily/2022/12/01/writing-readable-code"; + } + { + from = "/archive/2022/12/02/commit-and-push-something-every-day"; + to = "/daily/2022/12/02/commit-and-push-something-every-day"; + } + { + from = "/archive/2022/12/03/what-to-do-with-todo-comments"; + to = "/daily/2022/12/03/what-to-do-with-todo-comments"; + } + { + from = "/archive/2022/12/04/writing-why-first-user-stories"; + to = "/daily/2022/12/04/writing-why-first-user-stories"; + } + { + from = "/archive/2022/12/05/outcomes-or-output"; + to = "/daily/2022/12/05/outcomes-or-output"; + } + { + from = "/archive/2022/12/06/should-you-comment-your-code"; + to = "/daily/2022/12/06/should-you-comment-your-code"; + } + { + from = "/archive/2022/12/07/separating-releases-from-deployments-with-feature-flags"; + to = "/daily/2022/12/07/separating-releases-from-deployments-with-feature-flags"; + } + { + from = "/archive/2022/12/08/the-decorator-design-pattern"; + to = "/daily/2022/12/08/the-decorator-design-pattern"; + } + { + from = "/archive/2022/12/09/how-and-why-i-started-using-postcss"; + to = "/daily/2022/12/09/how-and-why-i-started-using-postcss"; + } + { + from = "/archive/2022/12/10/managing-databases-with-neovim-and-docker"; + to = "/daily/2022/12/10/managing-databases-with-neovim-and-docker"; + } + { + from = "/archive/2022/12/15/happy-drupal-10-release-day"; + to = "/daily/2022/12/15/happy-drupal-10-release-day"; + } + { + from = "/archive/2022/12/20/automating-all-the-things,-including-infrastructure"; + to = "/daily/2022/12/20/automating-all-the-things,-including-infrastructure"; + } + { + from = "/archive/2022/12/21/duck-typing"; + to = "/daily/2022/12/21/duck-typing"; + } + { + from = "/archive/2022/12/22/the-boy-scout-rule"; + to = "/daily/2022/12/22/the-boy-scout-rule"; + } + { + from = "/archive/2022/12/23/speaking-at-php-stoke-and-nordevcon"; + to = "/daily/2022/12/23/speaking-at-php-stoke-and-nordevcon"; + } + { + from = "/archive/2022/12/28/debugging-gitignore-rules"; + to = "/daily/2022/12/28/debugging-gitignore-rules"; + } + { + from = "/archive/2022/12/29/what-is-the-cost-of-a-bug"; + to = "/daily/2022/12/29/what-is-the-cost-of-a-bug"; + } + { + from = "/archive/2022/12/30/tests-are-living-documentation"; + to = "/daily/2022/12/30/tests-are-living-documentation"; + } + { + from = "/archive/2022/12/31/just-start-writing"; + to = "/daily/2022/12/31/just-start-writing"; + } + { + from = "/archive/2023/01/01/types-and-static-analysis-saved-me-today"; + to = "/daily/2023/01/01/types-and-static-analysis-saved-me-today"; + } + { + from = "/archive/2023/01/02/dont-use-arbitrary-values-in-tailwind-css"; + to = "/daily/2023/01/02/dont-use-arbitrary-values-in-tailwind-css"; + } + { + from = "/archive/2023/01/03/tailwind-css-extensibility-is-one-of-its-best-features"; + to = "/daily/2023/01/03/tailwind-css-extensibility-is-one-of-its-best-features"; + } + { + from = "/archive/2023/01/04/testable-tailwind-css-plugins"; + to = "/daily/2023/01/04/testable-tailwind-css-plugins"; + } + { + from = "/archive/2023/01/05/adding-tailwind-to-an-existing-project"; + to = "/daily/2023/01/05/adding-tailwind-to-an-existing-project"; + } + { + from = "/archive/2023/01/06/utility-first-or-utility-last"; + to = "/daily/2023/01/06/utility-first-or-utility-last"; + } + { + from = "/archive/2023/01/07/reducing-utility-class-duplication"; + to = "/daily/2023/01/07/reducing-utility-class-duplication"; + } + { + from = "/archive/2023/01/16/back-after-php-stoke"; + to = "/daily/2023/01/16/back-after-php-stoke"; + } + { + from = "/archive/2023/01/17/things-to-know-about-php"; + to = "/daily/2023/01/17/things-to-know-about-php"; + } + { + from = "/archive/2023/01/18/drupal-turns-22"; + to = "/daily/2023/01/18/drupal-turns-22"; + } + { + from = "/archive/2023/01/19/long-term-maintainability-with-utility-classes-and-tailwind-css"; + to = "/daily/2023/01/19/long-term-maintainability-with-utility-classes-and-tailwind-css"; + } + { + from = "/archive/2023/01/20/tailwinds-classes-are-your-classes"; + to = "/daily/2023/01/20/tailwinds-classes-are-your-classes"; + } + { + from = "/archive/2023/01/21/tailwind-not-just-translating-css-to-utility-classes"; + to = "/daily/2023/01/21/tailwind-not-just-translating-css-to-utility-classes"; + } + { + from = "/archive/2023/01/22/building-bootstrap-css-examples-with-tailwind"; + to = "/daily/2023/01/22/building-bootstrap-css-examples-with-tailwind"; + } + { + from = "/archive/2023/01/23/debugging-with-git-bisect"; + to = "/daily/2023/01/23/debugging-with-git-bisect"; + } + { + from = "/archive/2023/01/24/small-commits-and-good-commit-messges"; + to = "/daily/2023/01/24/small-commits-and-good-commit-messges"; + } + { + from = "/archive/2023/01/25/to-squash-or-not-to-squash"; + to = "/daily/2023/01/25/to-squash-or-not-to-squash"; + } + { + from = "/archive/2023/02/07/astro-as-a-static-site-generator"; + to = "/daily/2023/02/07/astro-as-a-static-site-generator"; + } + { + from = "/archive/2023/02/08/fetching-api-data-with-astro"; + to = "/daily/2023/02/08/fetching-api-data-with-astro"; + } + { + from = "/archive/2023/02/09/creating-api-endpoints-with-astro"; + to = "/daily/2023/02/09/creating-api-endpoints-with-astro"; + } + { + from = "/archive/2023/02/16/tailwind-css-at-the-bristol-software-development-meetup"; + to = "/daily/2023/02/16/tailwind-css-at-the-bristol-software-development-meetup"; + } + { + from = "/archive/2023/02/17/upgrading-my-drupal-example-project-to-drupal-10"; + to = "/daily/2023/02/17/upgrading-my-drupal-example-project-to-drupal-10"; + } + { + from = "/archive/2023/02/18/drupal-10-version-of-override-node-options"; + to = "/daily/2023/02/18/drupal-10-version-of-override-node-options"; + } + { + from = "/archive/2023/02/19/clients-dont-care-which-design-pattern-you-use"; + to = "/daily/2023/02/19/clients-dont-care-which-design-pattern-you-use"; + } + { + from = "/archive/2023/02/20/tailwind-why-i-prefer-to-extract-html-components"; + to = "/daily/2023/02/20/tailwind-why-i-prefer-to-extract-html-components"; + } + { + from = "/archive/2023/03/01/tailwind-css-at-the-norfolk-developer-conference"; + to = "/daily/2023/03/01/tailwind-css-at-the-norfolk-developer-conference"; + } + { + from = "/archive/2023/03/02/busy-working-on-client-projects"; + to = "/daily/2023/03/02/busy-working-on-client-projects"; + } + { + from = "/archive/2023/03/03/adding-a-localgov-drupal-example"; + to = "/daily/2023/03/03/adding-a-localgov-drupal-example"; + } + { + from = "/archive/2023/03/04/why-i-built-a-tool-to-generate-configuration-files"; + to = "/daily/2023/03/04/why-i-built-a-tool-to-generate-configuration-files"; + } + { + from = "/archive/2023/03/05/mentoring-for-school-of-code"; + to = "/daily/2023/03/05/mentoring-for-school-of-code"; + } + { + from = "/archive/2023/03/08/automating-infrastructure-with-iac"; + to = "/daily/2023/03/08/automating-infrastructure-with-iac"; + } + { + from = "/archive/2023/03/09/in-what-language-should-i-write-my-automation"; + to = "/daily/2023/03/09/in-what-language-should-i-write-my-automation"; + } + { + from = "/archive/2023/03/13/what-problem-am-i-trying-to-solve"; + to = "/daily/2023/03/13/what-problem-am-i-trying-to-solve"; + } + { + from = "/archive/2023/03/14/automating-all-the-things"; + to = "/daily/2023/03/14/automating-all-the-things"; + } + { + from = "/archive/2023/03/15/the-benefits-of-automation"; + to = "/daily/2023/03/15/the-benefits-of-automation"; + } + { + from = "/archive/2023/03/21/there-isnt-a-tailwind-looking-site"; + to = "/daily/2023/03/21/there-isnt-a-tailwind-looking-site"; + } + { + from = "/archive/2023/03/22/with-utility-styles-your-css-stops-growing"; + to = "/daily/2023/03/22/with-utility-styles-your-css-stops-growing"; + } + { + from = "/archive/2023/03/27/software-development-solving-problems-and-adding-value"; + to = "/daily/2023/03/27/software-development-solving-problems-and-adding-value"; + } + { + from = "/archive/2023/04/07/speaking-at-php-london"; + to = "/daily/2023/04/07/speaking-at-php-london"; + } + { + from = "/archive/2023/04/08/why-i-use-tmux"; + to = "/daily/2023/04/08/why-i-use-tmux"; + } + { + from = "/archive/2023/04/09/nix-nixos-home-manager-and-wsl2"; + to = "/daily/2023/04/09/nix-nixos-home-manager-and-wsl2"; + } + { + from = "/archive/2023/04/10/how-i-use-neovim-for-writing-php"; + to = "/daily/2023/04/10/how-i-use-neovim-for-writing-php"; + } + { + from = "/archive/2023/04/11/just-vs-make"; + to = "/daily/2023/04/11/just-vs-make"; + } + { + from = "/archive/2023/04/12/cleaner-php-code-with-promoted-constructor-properties"; + to = "/daily/2023/04/12/cleaner-php-code-with-promoted-constructor-properties"; + } + { + from = "/archive/2023/04/13/immutable-read-only-properties-in-php-8-1"; + to = "/daily/2023/04/13/immutable-read-only-properties-in-php-8-1"; + } + { + from = "/archive/2023/04/14/data-transfer-objects-and-value-objects"; + to = "/daily/2023/04/14/data-transfer-objects-and-value-objects"; + } + { + from = "/archive/2023/04/15/automatically-running-commands-with-nodemon"; + to = "/daily/2023/04/15/automatically-running-commands-with-nodemon"; + } + { + from = "/archive/2023/04/16/refactoring-with-readonly-classes-in-php-8-2"; + to = "/daily/2023/04/16/refactoring-with-readonly-classes-in-php-8-2"; + } + { + from = "/archive/2023/04/17/introducing-feature-flags-to-build-configs"; + to = "/daily/2023/04/17/introducing-feature-flags-to-build-configs"; + } + { + from = "/archive/2023/04/18/consistency-is-key"; + to = "/daily/2023/04/18/consistency-is-key"; + } + { + from = "/archive/2023/04/19/camel-case-or-snake-case-for-drupal-code"; + to = "/daily/2023/04/19/camel-case-or-snake-case-for-drupal-code"; + } + { + from = "/archive/2023/04/20/micro-refactorings"; + to = "/daily/2023/04/20/micro-refactorings"; + } + { + from = "/archive/2023/04/21/making-my-drupal-module-template-drupal-10-compatible"; + to = "/daily/2023/04/21/making-my-drupal-module-template-drupal-10-compatible"; + } + { + from = "/archive/2023/04/22/build-configs-as-a-service"; + to = "/daily/2023/04/22/build-configs-as-a-service"; + } + { + from = "/archive/2023/04/23/laravel-pipelines"; + to = "/daily/2023/04/23/laravel-pipelines"; + } + { + from = "/archive/2023/04/24/ci-pipelines-should-start-locally"; + to = "/daily/2023/04/24/ci-pipelines-should-start-locally"; + } + { + from = "/archive/2023/04/25/shortening-the-feedback-loop-even-more"; + to = "/daily/2023/04/25/shortening-the-feedback-loop-even-more"; + } + { + from = "/archive/2023/04/26/tdd-structure-a-new-test-by-writing-comments-first"; + to = "/daily/2023/04/26/tdd-structure-a-new-test-by-writing-comments-first"; + } + { + from = "/archive/2023/04/27/tdd-write-the-test-backwards"; + to = "/daily/2023/04/27/tdd-write-the-test-backwards"; + } + { + from = "/archive/2023/04/30/will-we-see-drupal-7-100"; + to = "/daily/2023/04/30/will-we-see-drupal-7-100"; + } + { + from = "/archive/2023/05/01/should-drupal-7-support-be-extended-again"; + to = "/daily/2023/05/01/should-drupal-7-support-be-extended-again"; + } + { + from = "/archive/2023/05/02/does-it-depend-on-who-you-ask"; + to = "/daily/2023/05/02/does-it-depend-on-who-you-ask"; + } + { + from = "/archive/2023/05/03/just-because-core-is-supported"; + to = "/daily/2023/05/03/just-because-core-is-supported"; + } + { + from = "/archive/2023/05/04/speaking-at-the-symfony-uk-meetup-london"; + to = "/daily/2023/05/04/speaking-at-the-symfony-uk-meetup-london"; + } + { + from = "/archive/2023/05/05/getting-to-green"; + to = "/daily/2023/05/05/getting-to-green"; + } + { + from = "/archive/2023/05/06/why-its-important-to-see-the-test-fail"; + to = "/daily/2023/05/06/why-its-important-to-see-the-test-fail"; + } + { + from = "/archive/2023/05/07/you-dont-need-to-think-about-what-to-do-next"; + to = "/daily/2023/05/07/you-dont-need-to-think-about-what-to-do-next"; + } + { + from = "/archive/2023/05/08/only-write-enough-code-to-get-a-failing-test"; + to = "/daily/2023/05/08/only-write-enough-code-to-get-a-failing-test"; + } + { + from = "/archive/2023/05/09/the-single-responsibility-principle"; + to = "/daily/2023/05/09/the-single-responsibility-principle"; + } + { + from = "/archive/2023/05/10/tailwind-css-makes-change-easier"; + to = "/daily/2023/05/10/tailwind-css-makes-change-easier"; + } + { + from = "/archive/2023/05/11/why-i-like-pair-and-mob-programming"; + to = "/daily/2023/05/11/why-i-like-pair-and-mob-programming"; + } + { + from = "/archive/2023/05/12/always-listen-to-the-mob"; + to = "/daily/2023/05/12/always-listen-to-the-mob"; + } + { + from = "/archive/2023/05/13/when-you-do-things-right"; + to = "/daily/2023/05/13/when-you-do-things-right"; + } + { + from = "/archive/2023/05/14/releasing-small-changes-often-is-less-risky"; + to = "/daily/2023/05/14/releasing-small-changes-often-is-less-risky"; + } + { + from = "/archive/2023/05/15/is-the-drupal-release-cycle-too-fast"; + to = "/daily/2023/05/15/is-the-drupal-release-cycle-too-fast"; + } + { + from = "/archive/2023/05/16/mastering-your-tools-improves-productivity"; + to = "/daily/2023/05/16/mastering-your-tools-improves-productivity"; + } + { + from = "/archive/2023/05/17/what-is-deprecated-code"; + to = "/daily/2023/05/17/what-is-deprecated-code"; + } + { + from = "/archive/2023/05/18/why-is-backward-compatibility-important"; + to = "/daily/2023/05/18/why-is-backward-compatibility-important"; + } + { + from = "/archive/2023/05/19/semantic-versioning"; + to = "/daily/2023/05/19/semantic-versioning"; + } + { + from = "/archive/2023/05/20/a-minor-breaking-change"; + to = "/daily/2023/05/20/a-minor-breaking-change"; + } + { + from = "/archive/2023/05/21/drupal-9-almost-end-of-life-already"; + to = "/daily/2023/05/21/drupal-9-almost-end-of-life-already"; + } + { + from = "/archive/2023/06/05/how-long-should-a-feature-flag-live"; + to = "/daily/2023/06/05/how-long-should-a-feature-flag-live"; + } + { + from = "/archive/2023/06/06/drupal-7-end-of-life-extended"; + to = "/daily/2023/06/06/drupal-7-end-of-life-extended"; + } + { + from = "/archive/2023/06/07/what-does-the-drupal-7-eol-extension-mean-to-you"; + to = "/daily/2023/06/07/what-does-the-drupal-7-eol-extension-mean-to-you"; + } + { + from = "/archive/2023/06/08/write-less-drupal-code"; + to = "/daily/2023/06/08/write-less-drupal-code"; + } + { + from = "/archive/2023/06/09/drupal-is-built-by-people"; + to = "/daily/2023/06/09/drupal-is-built-by-people"; + } + { + from = "/archive/2023/06/10/how-do-you-know-when-to-remove-a-feature-flag"; + to = "/daily/2023/06/10/how-do-you-know-when-to-remove-a-feature-flag"; + } + { + from = "/archive/2023/06/11/failing-fast"; + to = "/daily/2023/06/11/failing-fast"; + } + { + from = "/archive/2023/06/12/feature-flags-in-a-multi-tenancy-application"; + to = "/daily/2023/06/12/feature-flags-in-a-multi-tenancy-application"; + } + { + from = "/archive/2023/06/13/should-you-feature-flag-everything"; + to = "/daily/2023/06/13/should-you-feature-flag-everything"; + } + { + from = "/archive/2023/06/14/what-if-there-was-no-open-source-software"; + to = "/daily/2023/06/14/what-if-there-was-no-open-source-software"; + } + { + from = "/archive/2023/06/15/done-is-better-than-perfect"; + to = "/daily/2023/06/15/done-is-better-than-perfect"; + } + { + from = "/archive/2023/06/16/make-the-easy-change"; + to = "/daily/2023/06/16/make-the-easy-change"; + } + { + from = "/archive/2023/06/17/avoid-git-merge-hell-with-trunk-based-development"; + to = "/daily/2023/06/17/avoid-git-merge-hell-with-trunk-based-development"; + } + { + from = "/archive/2023/06/18/are-you-doing-ci-cd"; + to = "/daily/2023/06/18/are-you-doing-ci-cd"; + } + { + from = "/archive/2023/06/19/should-you-upgrade-from-drupal-7-to-drupal-10"; + to = "/daily/2023/06/19/should-you-upgrade-from-drupal-7-to-drupal-10"; + } + { + from = "/archive/2023/06/20/should-you-deploy-on-a-friday"; + to = "/daily/2023/06/20/should-you-deploy-on-a-friday"; + } + { + from = "/archive/2023/06/21/deployments-or-releases"; + to = "/daily/2023/06/21/deployments-or-releases"; + } + { + from = "/archive/2023/06/22/fail-to-lear"; + to = "/daily/2023/06/22/fail-to-lear"; + } + { + from = "/archive/2023/06/23/why-keep-a-changelog"; + to = "/daily/2023/06/23/why-keep-a-changelog"; + } + { + from = "/archive/2023/06/24/credited-on-200-fixed-issues"; + to = "/daily/2023/06/24/credited-on-200-fixed-issues"; + } + { + from = "/archive/2023/06/25/do-you-need-permission-test-driven-development"; + to = "/daily/2023/06/25/do-you-need-permission-test-driven-development"; + } + { + from = "/archive/2023/06/26/is-any-code-without-tests-legacy"; + to = "/daily/2023/06/26/is-any-code-without-tests-legacy"; + } + { + from = "/archive/2023/06/27/ci-pipeline-additional-team-member"; + to = "/daily/2023/06/27/ci-pipeline-additional-team-member"; + } + { + from = "/archive/2023/06/28/theres-no-value-in-a-broken-ci-pipeline"; + to = "/daily/2023/06/28/theres-no-value-in-a-broken-ci-pipeline"; + } + { + from = "/archive/2023/06/29/tests-wont-tell-you-if-your-code-works"; + to = "/daily/2023/06/29/tests-wont-tell-you-if-your-code-works"; + } + { + from = "/archive/2023/06/30/how-did-you-learn-automated-testing"; + to = "/daily/2023/06/30/how-did-you-learn-automated-testing"; + } + { + from = "/archive/2023/07/01/once-you-start-writing-tests-you-cant-stop"; + to = "/daily/2023/07/01/once-you-start-writing-tests-you-cant-stop"; + } + { + from = "/archive/2023/07/02/docker-or-nix"; + to = "/daily/2023/07/02/docker-or-nix"; + } + { + from = "/archive/2023/07/03/why-write-custom-assertions-in-your-tests"; + to = "/daily/2023/07/03/why-write-custom-assertions-in-your-tests"; + } + { + from = "/archive/2023/07/04/think-smaller-with-tdd"; + to = "/daily/2023/07/04/think-smaller-with-tdd"; + } + { + from = "/archive/2023/07/05/services-vs-actions"; + to = "/daily/2023/07/05/services-vs-actions"; + } + { + from = "/archive/2023/07/06/automated-testing-is-more-than-just-unit-testing"; + to = "/daily/2023/07/06/automated-testing-is-more-than-just-unit-testing"; + } + { + from = "/archive/2023/07/15/test-driven-development-makes-you-more-productive"; + to = "/daily/2023/07/15/test-driven-development-makes-you-more-productive"; + } + { + from = "/archive/2023/07/16/when-writing-a-failing-test-youre-designing-your-code"; + to = "/daily/2023/07/16/when-writing-a-failing-test-youre-designing-your-code"; + } + { + from = "/archive/2023/07/17/too-many-choices"; + to = "/daily/2023/07/17/too-many-choices"; + } + { + from = "/archive/2023/07/18/tdd-as-a-concept-is-simple-but-tdd-is-difficult"; + to = "/daily/2023/07/18/tdd-as-a-concept-is-simple-but-tdd-is-difficult"; + } + { + from = "/archive/2023/07/19/tdd-is-like-clicker-training"; + to = "/daily/2023/07/19/tdd-is-like-clicker-training"; + } + { + from = "/archive/2023/07/20/tests-as-communication"; + to = "/daily/2023/07/20/tests-as-communication"; + } + { + from = "/archive/2023/07/21/comments-as-communication"; + to = "/daily/2023/07/21/comments-as-communication"; + } + { + from = "/archive/2023/07/22/more-code-more-problems"; + to = "/daily/2023/07/22/more-code-more-problems"; + } + { + from = "/archive/2023/07/23/tomorrow-is-easier-if-todays-code-is-simpler"; + to = "/daily/2023/07/23/tomorrow-is-easier-if-todays-code-is-simpler"; + } + { + from = "/archive/2023/07/24/testing-is-all-about-confidence"; + to = "/daily/2023/07/24/testing-is-all-about-confidence"; + } + { + from = "/archive/2023/07/25/working-backwards"; + to = "/daily/2023/07/25/working-backwards"; + } + { + from = "/archive/2023/07/26/prove-the-concept"; + to = "/daily/2023/07/26/prove-the-concept"; + } + { + from = "/archive/2023/07/27/stick-to-conventions"; + to = "/daily/2023/07/27/stick-to-conventions"; + } + { + from = "/archive/2023/07/28/generic-commit-messages"; + to = "/daily/2023/07/28/generic-commit-messages"; + } + { + from = "/archive/2023/07/29/should-i-wait-to-upgrade-from-drupal-7"; + to = "/daily/2023/07/29/should-i-wait-to-upgrade-from-drupal-7"; + } + { + from = "/archive/2023/07/30/commit-often-deploy-often"; + to = "/daily/2023/07/30/commit-often-deploy-often"; + } + { + from = "/archive/2023/07/31/upgrading-from-drupal-9-is-easier"; + to = "/daily/2023/07/31/upgrading-from-drupal-9-is-easier"; + } + { + from = "/archive/2023/08/01/maintaining-a-module-used-on-35000-drupal-websites"; + to = "/daily/2023/08/01/maintaining-a-module-used-on-35000-drupal-websites"; + } + { + from = "/archive/2023/08/02/a-crash-course-into-drupal-testing"; + to = "/daily/2023/08/02/a-crash-course-into-drupal-testing"; + } + { + from = "/archive/2023/08/03/what-problem-are-we-trying-to-solve"; + to = "/daily/2023/08/03/what-problem-are-we-trying-to-solve"; + } + { + from = "/archive/2023/08/04/laravel-prompts"; + to = "/daily/2023/08/04/laravel-prompts"; + } + { + from = "/archive/2023/08/05/use-drupal-to-own-your-content"; + to = "/daily/2023/08/05/use-drupal-to-own-your-content"; + } + { + from = "/archive/2023/08/06/yagni"; + to = "/daily/2023/08/06/yagni"; + } + { + from = "/archive/2023/08/07/tests-make-upgrades-less-risky"; + to = "/daily/2023/08/07/tests-make-upgrades-less-risky"; + } + { + from = "/archive/2023/08/08/8-years-of-dotfiles"; + to = "/daily/2023/08/08/8-years-of-dotfiles"; + } + { + from = "/archive/2023/08/09/vim-is-my-lightsaber"; + to = "/daily/2023/08/09/vim-is-my-lightsaber"; + } + { + from = "/archive/2023/08/10/testing-fixed-prices-and-bug-free-guarantees"; + to = "/daily/2023/08/10/testing-fixed-prices-and-bug-free-guarantees"; + } + { + from = "/archive/2023/08/11/everyone-tests-their-code"; + to = "/daily/2023/08/11/everyone-tests-their-code"; + } + { + from = "/archive/2023/08/12/does-not-writing-tests-actually-save-time"; + to = "/daily/2023/08/12/does-not-writing-tests-actually-save-time"; + } + { + from = "/archive/2023/08/13/dont-estimate-separately-for-testing"; + to = "/daily/2023/08/13/dont-estimate-separately-for-testing"; + } + { + from = "/archive/2023/08/14/why-keep-a-dotfiles-repository"; + to = "/daily/2023/08/14/why-keep-a-dotfiles-repository"; + } + { + from = "/archive/2023/08/15/writing-test-and-implementation-code-are-the-same-task"; + to = "/daily/2023/08/15/writing-test-and-implementation-code-are-the-same-task"; + } + { + from = "/archive/2023/08/16/writing-tests-in-your-own-time"; + to = "/daily/2023/08/16/writing-tests-in-your-own-time"; + } + { + from = "/archive/2023/08/17/writing-custom-assertions-in-your-tests"; + to = "/daily/2023/08/17/writing-custom-assertions-in-your-tests"; + } + { + from = "/archive/2023/08/18/types-vs-tests"; + to = "/daily/2023/08/18/types-vs-tests"; + } + { + from = "/archive/2023/08/19/asserting-all-the-things"; + to = "/daily/2023/08/19/asserting-all-the-things"; + } + { + from = "/archive/2023/08/20/php-types-and-assertions"; + to = "/daily/2023/08/20/php-types-and-assertions"; + } + { + from = "/archive/2023/08/21/which-part-of-the-ci-pipeline-has-the-most-value"; + to = "/daily/2023/08/21/which-part-of-the-ci-pipeline-has-the-most-value"; + } + { + from = "/archive/2023/08/22/deployments-with-your-ci-pipeline"; + to = "/daily/2023/08/22/deployments-with-your-ci-pipeline"; + } + { + from = "/archive/2023/08/23/dont-use-third-party-services-directly"; + to = "/daily/2023/08/23/dont-use-third-party-services-directly"; + } + { + from = "/archive/2023/08/24/testing-multiple-implementations-with-contract-tests"; + to = "/daily/2023/08/24/testing-multiple-implementations-with-contract-tests"; + } + { + from = "/archive/2023/08/25/start-with-a-vague-test"; + to = "/daily/2023/08/25/start-with-a-vague-test"; + } + { + from = "/archive/2023/08/26/work-in-small-chunks"; + to = "/daily/2023/08/26/work-in-small-chunks"; + } + { + from = "/archive/2023/08/27/pull-requests-are-great-for-open-source"; + to = "/daily/2023/08/27/pull-requests-are-great-for-open-source"; + } + { + from = "/archive/2023/08/28/pair-and-mob-programming-are-continuous-code-review"; + to = "/daily/2023/08/28/pair-and-mob-programming-are-continuous-code-review"; + } + { + from = "/archive/2023/08/29/ci-pipelines-are-an-automated-code-review"; + to = "/daily/2023/08/29/ci-pipelines-are-an-automated-code-review"; + } + { + from = "/archive/2023/08/30/tdd-and-unexpected-errors"; + to = "/daily/2023/08/30/tdd-and-unexpected-errors"; + } + { + from = "/archive/2023/08/31/code-review-discourages-small-refactorings"; + to = "/daily/2023/08/31/code-review-discourages-small-refactorings"; + } + { + from = "/archive/2023/09/01/non-blocking-code-reviews"; + to = "/daily/2023/09/01/non-blocking-code-reviews"; + } + { + from = "/archive/2023/09/02/planning-first-or-reviewing-last"; + to = "/daily/2023/09/02/planning-first-or-reviewing-last"; + } + { + from = "/archive/2023/09/03/including-time-for-tests-in-estimates"; + to = "/daily/2023/09/03/including-time-for-tests-in-estimates"; + } + { + from = "/archive/2023/09/04/charging-more-not-to-write-tests"; + to = "/daily/2023/09/04/charging-more-not-to-write-tests"; + } + { + from = "/archive/2023/09/05/spring-clean-before-upgrading"; + to = "/daily/2023/09/05/spring-clean-before-upgrading"; + } + { + from = "/archive/2023/09/06/verbosity-over-abstraction"; + to = "/daily/2023/09/06/verbosity-over-abstraction"; + } + { + from = "/archive/2023/09/07/what-s-the-simplest-test-to-begin-with"; + to = "/daily/2023/09/07/what-s-the-simplest-test-to-begin-with"; + } + { + from = "/archive/2023/09/08/do-you-proactively-refactor-your-code"; + to = "/daily/2023/09/08/do-you-proactively-refactor-your-code"; + } + { + from = "/archive/2023/09/09/a-lack-of-tests-discourages-refactoring"; + to = "/daily/2023/09/09/a-lack-of-tests-discourages-refactoring"; + } + { + from = "/archive/2023/09/10/code-is-read-more-than-it-s-written"; + to = "/daily/2023/09/10/code-is-read-more-than-it-s-written"; + } + { + from = "/archive/2023/09/11/dont-use-else"; + to = "/daily/2023/09/11/dont-use-else"; + } + { + from = "/archive/2023/09/12/dont-inject-too-many-dependencies"; + to = "/daily/2023/09/12/dont-inject-too-many-dependencies"; + } + { + from = "/archive/2023/09/13/which-type-of-test-should-i-use"; + to = "/daily/2023/09/13/which-type-of-test-should-i-use"; + } + { + from = "/archive/2023/09/14/outside-in-or-inside-out"; + to = "/daily/2023/09/14/outside-in-or-inside-out"; + } + { + from = "/archive/2023/09/15/types-or-no-types"; + to = "/daily/2023/09/15/types-or-no-types"; + } + { + from = "/archive/2023/09/16/how-not-to-break-36-000-websites"; + to = "/daily/2023/09/16/how-not-to-break-36-000-websites"; + } + { + from = "/archive/2023/09/17/how-much-refactoring-should-i-be-doing"; + to = "/daily/2023/09/17/how-much-refactoring-should-i-be-doing"; + } + { + from = "/archive/2023/09/18/increasing-test-coverage-with-regression-tests"; + to = "/daily/2023/09/18/increasing-test-coverage-with-regression-tests"; + } + { + from = "/archive/2023/09/19/stop-writing-tests"; + to = "/daily/2023/09/19/stop-writing-tests"; + } + { + from = "/archive/2023/09/20/why-i-prefer-types"; + to = "/daily/2023/09/20/why-i-prefer-types"; + } + { + from = "/archive/2023/09/21/buggy-software-causes-reputational-damage"; + to = "/daily/2023/09/21/buggy-software-causes-reputational-damage"; + } + { + from = "/archive/2023/09/22/documentation-and-comments-get-stale"; + to = "/daily/2023/09/22/documentation-and-comments-get-stale"; + } + { + from = "/archive/2023/09/23/not-everyone-writes-automated-tests"; + to = "/daily/2023/09/23/not-everyone-writes-automated-tests"; + } + { + from = "/archive/2023/09/24/test-to-save-your-job"; + to = "/daily/2023/09/24/test-to-save-your-job"; + } + { + from = "/archive/2023/09/25/should-you-use-a-staging-environment"; + to = "/daily/2023/09/25/should-you-use-a-staging-environment"; + } + { + from = "/archive/2023/09/26/which-branch-should-be-in-which-environment"; + to = "/daily/2023/09/26/which-branch-should-be-in-which-environment"; + } + { + from = "/archive/2023/09/27/separating-environments-with-feature-flags"; + to = "/daily/2023/09/27/separating-environments-with-feature-flags"; + } + { + from = "/archive/2023/09/28/feature-flags-enable-continuous-integration"; + to = "/daily/2023/09/28/feature-flags-enable-continuous-integration"; + } + { + from = "/archive/2023/09/29/92-changed-files-with-885-additions-and-156-deletions"; + to = "/daily/2023/09/29/92-changed-files-with-885-additions-and-156-deletions"; + } + { + from = "/archive/2023/09/30/automated-testing-offers-repeatability"; + to = "/daily/2023/09/30/automated-testing-offers-repeatability"; + } + { + from = "/archive/2023/10/01/tdd--repeat-and-refactor"; + to = "/daily/2023/10/01/tdd--repeat-and-refactor"; + } + { + from = "/archive/2023/10/02/only-comment-what-needs-to-be-commented"; + to = "/daily/2023/10/02/only-comment-what-needs-to-be-commented"; + } + { + from = "/archive/2023/10/03/there-is-no-perfect-solution"; + to = "/daily/2023/10/03/there-is-no-perfect-solution"; + } + { + from = "/archive/2023/10/04/the-best-solution-is-the-one-that-gets-the-tests-to-pass"; + to = "/daily/2023/10/04/the-best-solution-is-the-one-that-gets-the-tests-to-pass"; + } + { + from = "/archive/2023/10/05/some-solutions-are-good-enough"; + to = "/daily/2023/10/05/some-solutions-are-good-enough"; + } + { + from = "/archive/2023/10/06/software-development-is-like-going-to-the-dentist"; + to = "/daily/2023/10/06/software-development-is-like-going-to-the-dentist"; + } + { + from = "/archive/2023/10/07/a-breakdown-of-tests-from-a-current-project"; + to = "/daily/2023/10/07/a-breakdown-of-tests-from-a-current-project"; + } + { + from = "/archive/2023/10/08/is-test-driven-development-difficult"; + to = "/daily/2023/10/08/is-test-driven-development-difficult"; + } + { + from = "/archive/2023/10/09/spotting-new-things-in-drupal-10-1"; + to = "/daily/2023/10/09/spotting-new-things-in-drupal-10-1"; + } + { + from = "/archive/2023/10/10/why-use-composer-to-manage-drupal-dependencies"; + to = "/daily/2023/10/10/why-use-composer-to-manage-drupal-dependencies"; + } + { + from = "/archive/2023/10/11/do-you-need-that-module"; + to = "/daily/2023/10/11/do-you-need-that-module"; + } + { + from = "/archive/2023/10/12/business-logic-in-template-files"; + to = "/daily/2023/10/12/business-logic-in-template-files"; + } + { + from = "/archive/2023/10/13/writing-tests-is-an-investment"; + to = "/daily/2023/10/13/writing-tests-is-an-investment"; + } + { + from = "/archive/2023/10/14/do-you-need-to-write-tests-for-small-or-short-lived-projects"; + to = "/daily/2023/10/14/do-you-need-to-write-tests-for-small-or-short-lived-projects"; + } + { + from = "/archive/2023/10/15/off-to-drupalcon"; + to = "/daily/2023/10/15/off-to-drupalcon"; + } + { + from = "/archive/2023/10/23/when-should-run-your-tests"; + to = "/daily/2023/10/23/when-should-run-your-tests"; + } + { + from = "/archive/2023/10/24/how-to-test-code-you-didnt-write"; + to = "/daily/2023/10/24/how-to-test-code-you-didnt-write"; + } + { + from = "/archive/2023/10/25/automated-tests-prevent-regressions-when-upgrading"; + to = "/daily/2023/10/25/automated-tests-prevent-regressions-when-upgrading"; + } + { + from = "/archive/2023/10/26/is-decoupled-drupal-still-a-thing"; + to = "/daily/2023/10/26/is-decoupled-drupal-still-a-thing"; + } + { + from = "/archive/2023/10/27/work-with-me-and-support-the-drupal-association"; + to = "/daily/2023/10/27/work-with-me-and-support-the-drupal-association"; + } + { + from = "/archive/2023/10/28/can-you-move-faster-without-tests"; + to = "/daily/2023/10/28/can-you-move-faster-without-tests"; + } + { + from = "/archive/2023/10/29/i-can-drive-my-car-blindfolded-but-is-it-a-good-idea"; + to = "/daily/2023/10/29/i-can-drive-my-car-blindfolded-but-is-it-a-good-idea"; + } + { + from = "/archive/2023/10/30/is-drupal-a-cms-or-a-framework"; + to = "/daily/2023/10/30/is-drupal-a-cms-or-a-framework"; + } + { + from = "/archive/2023/10/31/one-official-drupal-development-environment"; + to = "/daily/2023/10/31/one-official-drupal-development-environment"; + } + { + from = "/archive/2023/11/01/drupal-9-is-now-end-of-life"; + to = "/daily/2023/11/01/drupal-9-is-now-end-of-life"; + } + { + from = "/archive/2023/11/02/is-code-coverage-an-objective-or-guideline"; + to = "/daily/2023/11/02/is-code-coverage-an-objective-or-guideline"; + } + { + from = "/archive/2023/11/03/why-your-company-should-contribute-to-open-source-software"; + to = "/daily/2023/11/03/why-your-company-should-contribute-to-open-source-software"; + } + { + from = "/archive/2023/11/04/why-you-should-contribute-to-open-source-software"; + to = "/daily/2023/11/04/why-you-should-contribute-to-open-source-software"; + } + { + from = "/archive/2023/11/05/i-m-starting-a-podcast"; + to = "/daily/2023/11/05/i-m-starting-a-podcast"; + } + { + from = "/archive/2023/11/06/the-first-beyond-blocks-podcast-episode-is-recorded"; + to = "/daily/2023/11/06/the-first-beyond-blocks-podcast-episode-is-recorded"; + } + { + from = "/archive/2023/11/07/it-depends"; + to = "/daily/2023/11/07/it-depends"; + } + { + from = "/archive/2023/11/08/building-build-configs"; + to = "/daily/2023/11/08/building-build-configs"; + } + { + from = "/archive/2023/11/09/readme-driven-development"; + to = "/daily/2023/11/09/readme-driven-development"; + } + { + from = "/archive/2023/11/10/retrofit-with-matt-glaman"; + to = "/daily/2023/11/10/retrofit-with-matt-glaman"; + } + { + from = "/archive/2023/11/11/work-in-small-batches"; + to = "/daily/2023/11/11/work-in-small-batches"; + } + { + from = "/archive/2023/11/12/drupal-gives-you-so-much-out-of-the-box"; + to = "/daily/2023/11/12/drupal-gives-you-so-much-out-of-the-box"; + } + { + from = "/archive/2023/11/13/phpunit-does-more-than-unit-testing"; + to = "/daily/2023/11/13/phpunit-does-more-than-unit-testing"; + } + { + from = "/archive/2023/11/14/why-i-prefer-integration-tests-to-unit-tests"; + to = "/daily/2023/11/14/why-i-prefer-integration-tests-to-unit-tests"; + } + { + from = "/archive/2023/11/15/dont-pre-optimise-and-over-customise"; + to = "/daily/2023/11/15/dont-pre-optimise-and-over-customise"; + } + { + from = "/archive/2023/11/16/avoiding-over-mocking"; + to = "/daily/2023/11/16/avoiding-over-mocking"; + } + { + from = "/archive/2023/11/17/drupal-s-alternate-realities"; + to = "/daily/2023/11/17/drupal-s-alternate-realities"; + } + { + from = "/archive/2023/11/18/writing-good-test-names"; + to = "/daily/2023/11/18/writing-good-test-names"; + } + { + from = "/archive/2023/11/19/why-ive-standardised-on-run-scripts"; + to = "/daily/2023/11/19/why-ive-standardised-on-run-scripts"; + } + { + from = "/archive/2023/11/20/whatll-be-in-drupal-11"; + to = "/daily/2023/11/20/whatll-be-in-drupal-11"; + } + { + from = "/archive/2023/11/21/why-i-built-build-configs"; + to = "/daily/2023/11/21/why-i-built-build-configs"; + } + { + from = "/archive/2023/11/22/frequency-reduces-difficulty"; + to = "/daily/2023/11/22/frequency-reduces-difficulty"; + } + { + from = "/archive/2023/11/23/partial-mocking"; + to = "/daily/2023/11/23/partial-mocking"; + } + { + from = "/archive/2023/11/24/are-conventional-commits-worth-it"; + to = "/daily/2023/11/24/are-conventional-commits-worth-it"; + } + { + from = "/archive/2023/11/25/community-engagement-for-non-technical-drupal-enthusiasts"; + to = "/daily/2023/11/25/community-engagement-for-non-technical-drupal-enthusiasts"; + } + { + from = "/archive/2023/11/26/to-docblock-or-not-to-docblock"; + to = "/daily/2023/11/26/to-docblock-or-not-to-docblock"; + } + { + from = "/archive/2023/11/27/finding-the-best-test-base"; + to = "/daily/2023/11/27/finding-the-best-test-base"; + } + { + from = "/archive/2023/11/28/which-phpstan-level-should-you-use"; + to = "/daily/2023/11/28/which-phpstan-level-should-you-use"; + } + { + from = "/archive/2023/11/29/the-lowest-level-is-better-than-no-level"; + to = "/daily/2023/11/29/the-lowest-level-is-better-than-no-level"; + } + { + from = "/archive/2023/11/30/are-bugs-good-for-users"; + to = "/daily/2023/11/30/are-bugs-good-for-users"; + } + { + from = "/archive/2023/12/01/the-contribution-first-workflow"; + to = "/daily/2023/12/01/the-contribution-first-workflow"; + } + { + from = "/archive/2023/12/04/writing-contrib-modules-as-glue-between-your-custom-code"; + to = "/daily/2023/12/04/writing-contrib-modules-as-glue-between-your-custom-code"; + } + { + from = "/archive/2023/12/05/open-source-encourages-open-source"; + to = "/daily/2023/12/05/open-source-encourages-open-source"; + } + { + from = "/archive/2023/12/06/open-source-first-doesnt-mean-you-need-to-cover-every-use-case"; + to = "/daily/2023/12/06/open-source-first-doesnt-mean-you-need-to-cover-every-use-case"; + } + { + from = "/archive/2023/12/07/a-drupal-case-study-from-oxfam"; + to = "/daily/2023/12/07/a-drupal-case-study-from-oxfam"; + } + { + from = "/archive/2023/12/08/dont-just-rewrite"; + to = "/daily/2023/12/08/dont-just-rewrite"; + } + { + from = "/archive/2023/12/09/rebuild-or-iterate"; + to = "/daily/2023/12/09/rebuild-or-iterate"; + } + { + from = "/archive/2023/12/10/suffixing-names"; + to = "/daily/2023/12/10/suffixing-names"; + } + { + from = "/archive/2023/12/11/custom-coding-standards-and-conventions"; + to = "/daily/2023/12/11/custom-coding-standards-and-conventions"; + } + { + from = "/archive/2023/12/12/drupalcon-session-survey-results"; + to = "/daily/2023/12/12/drupalcon-session-survey-results"; + } + { + from = "/archive/2023/12/13/reviving-an-old-php-project"; + to = "/daily/2023/12/13/reviving-an-old-php-project"; + } + { + from = "/archive/2023/12/14/save-time-and-effort-with-drupal-distributions"; + to = "/daily/2023/12/14/save-time-and-effort-with-drupal-distributions"; + } + { + from = "/archive/2023/12/15/building-your-own-in-house-drupal-distribution"; + to = "/daily/2023/12/15/building-your-own-in-house-drupal-distribution"; + } + { + from = "/archive/2023/12/16/adding-snapshot-tests-to-build-configs"; + to = "/daily/2023/12/16/adding-snapshot-tests-to-build-configs"; + } + { + from = "/archive/2023/12/17/fail-fast-fix-fast"; + to = "/daily/2023/12/17/fail-fast-fix-fast"; + } + { + from = "/archive/2023/12/18/static-analysis-on-tests"; + to = "/daily/2023/12/18/static-analysis-on-tests"; + } + { + from = "/archive/2023/12/19/php-tui-dan-leech"; + to = "/daily/2023/12/19/php-tui-dan-leech"; + } + { + from = "/archive/2023/12/20/hover-focus-hocus"; + to = "/daily/2023/12/20/hover-focus-hocus"; + } + { + from = "/archive/2023/12/21/new-year-coaching"; + to = "/daily/2023/12/21/new-year-coaching"; + } + { + from = "/archive/2023/12/22/best-language-cms-or-framework"; + to = "/daily/2023/12/22/best-language-cms-or-framework"; + } + { + from = "/archive/2023/12/23/using-a-whole-framework-or-part-of-it"; + to = "/daily/2023/12/23/using-a-whole-framework-or-part-of-it"; + } + { + from = "/archive/2023/12/24/this-should-never-happen"; + to = "/daily/2023/12/24/this-should-never-happen"; + } + { + from = "/archive/2023/12/25/zero-to-test"; + to = "/daily/2023/12/25/zero-to-test"; + } + { + from = "/archive/2023/12/26/good-code-is-not-about-being-easy-to-write"; + to = "/daily/2023/12/26/good-code-is-not-about-being-easy-to-write"; + } + { + from = "/archive/2023/12/27/writing-new-code-is-quick-to-begin-with"; + to = "/daily/2023/12/27/writing-new-code-is-quick-to-begin-with"; + } + { + from = "/archive/2023/12/28/pride-and-productivity"; + to = "/daily/2023/12/28/pride-and-productivity"; + } + { + from = "/archive/2023/12/29/decide-automate-document"; + to = "/daily/2023/12/29/decide-automate-document"; + } + { + from = "/archive/2023/12/30/weve-always-done-it-this-way"; + to = "/daily/2023/12/30/weve-always-done-it-this-way"; + } + { + from = "/archive/2023/12/31/just"; + to = "/daily/2023/12/31/just"; + } + { + from = "/archive/2024/03/03/centarro-and-drupal-commerce-with-ryan-szrama"; + to = "/daily/2024/03/03/centarro-and-drupal-commerce-with-ryan-szrama"; + } + { + from = "/atNOQ"; + to = "https://youtu.be/r41dkD2EOo8"; + } + { + from = "/automatically-updating-talk-created-date"; + to = "https://gist.github.com/opdavies/4e75e1753d8603113f07f8264bb783d6"; + } + { + from = "/blog.xml"; + to = "/rss.xml"; + } + { + from = "/blog/10-useful-drupal-6-modules"; + to = "/blog/useful-drupal-6-modules"; + } + { + from = "/blog/10-years-working-full-time-drupal"; + to = "/blog/10-years-working-full-time-drupal-php"; + } + { + from = "/blog/2010/04/05/style-drupal-6s-taxonomy-lists-php-css-and-jquery"; + to = "/blog/style-drupal-6s-taxonomy-lists-php-css-and-jquery"; + } + { + from = "/blog/2010/04/05/styling-drupal-6s-taxonomy-lists-with-php-css-and-jquery"; + to = "/blog/style-drupal-6s-taxonomy-lists-php-css-jquery"; + } + { + from = "/blog/2010/04/28/using-imagecache-and-imagecrop-my-portfolio"; + to = "/blog/using-imagecache-and-imagecrop-my-portfolio"; + } + { + from = "/blog/2010/05/06/conditional-email-addresses-webform"; + to = "/blog/conditional-email-addresses-webform"; + } + { + from = "/blog/2010/05/10/quickly-create-zen-subthemes-using-zenophile"; + to = "/blog/quickly-create-zen-subthemes-using-zenophile"; + } + { + from = "/blog/2010/05/25/create-slideshow-multiple-images-using-fancy-slide"; + to = "/blog/create-slideshow-multiple-images-using-fancy-slide"; + } + { + from = "/blog/2010/05/29/quickly-import-multiples-images-using-imagefieldimport-module"; + to = "/blog/quickly-import-multiples-images-using-imagefieldimport-module"; + } + { + from = "/blog/2010/06/02/improve-jpg-quality-imagecache-and-imageapi"; + to = "/blog/improve-jpg-quality-imagecache-and-imageapi"; + } + { + from = "/blog/2010/06/23/create-block-social-media-icons-using-cck-views-and-nodequeue"; + to = "/blog/create-block-social-media-icons-using-cck-views-and-nodequeue"; + } + { + from = "/blog/2010/06/25/10-useful-drupal-6-modules"; + to = "/blog/10-useful-drupal-6-modules"; + } + { + from = "/blog/2010/06/28/create-flickr-photo-gallery-using-feeds-cck-and-views"; + to = "/blog/create-flickr-photo-gallery-using-feeds-cck-and-views"; + } + { + from = "/blog/2010/07/01/change-content-type-multiple-nodes-using-sql"; + to = "/blog/change-content-type-multiple-nodes-using-sql"; + } + { + from = "/blog/2010/07/02/create-virtual-hosts-mac-os-x-using-virtualhostx"; + to = "/blog/create-virtual-hosts-mac-os-x-using-virtualhostx"; + } + { + from = "/blog/2010/07/07/add-taxonomy-term-multiple-nodes-using-sql"; + to = "/blog/add-taxonomy-term-multiple-nodes-using-sql"; + } + { + from = "/blog/2010/07/07/quickly-adding-taxonomy-term-multiple-nodes-using-sql"; + to = "/blog/add-taxonomy-term-multiple-nodes-using-sql"; + } + { + from = "/blog/2010/07/12/overview-teleport-module"; + to = "/blog/review-teleport-module"; + } + { + from = "/blog/2010/07/12/review-teleport-module"; + to = "/blog/review-teleport-module"; + } + { + from = "/blog/2010/08/10/review-adminhover-module"; + to = "/blog/review-adminhover-module"; + } + { + from = "/blog/2010/08/11/create-better-photo-gallery-drupal-part-1"; + to = "/blog/create-better-photo-gallery-drupal-part-1"; + } + { + from = "/blog/2010/08/11/how-create-better-photo-gallery-drupal-part-1"; + to = "/blog/create-better-photo-gallery-drupal-part-1"; + } + { + from = "/blog/2010/08/17/create-better-photo-gallery-drupal-part-2"; + to = "/blog/create-better-photo-gallery-drupal-part-2"; + } + { + from = "/blog/2010/08/20/review-image-caption-module"; + to = "/blog/review-image-caption-module"; + } + { + from = "/blog/2010/09/26/south-wales-drupal-user-group"; + to = "/blog/south-wales-drupal-user-group"; + } + { + from = "/blog/2010/10/10/create-and-apply-patches"; + to = "/blog/create-and-apply-patches"; + } + { + from = "/blog/2010/10/13/create-better-photo-gallery-drupal-part-3"; + to = "/blog/create-better-photo-gallery-drupal-part-3"; + } + { + from = "/blog/2010/10/22/create-better-photo-gallery-drupal-part-21"; + to = "/blog/create-better-photo-gallery-drupal-part-21"; + } + { + from = "/blog/2010/11/04/use-regular-expressions-search-and-replace-coda-or-textmate"; + to = "/blog/use-regular-expressions-search-and-replace-coda-or-textmate"; + } + { + from = "/blog/2011/02/14/easily-embed-typekit-fonts-your-drupal-website"; + to = "/blog/easily-embed-typekit-fonts-your-drupal-website"; + } + { + from = "/blog/2011/03/15/display-number-facebook-fans-php"; + to = "/blog/display-number-facebook-fans-php"; + } + { + from = "/blog/2011/03/31/proctor-stevenson"; + to = "/blog/proctor-stevenson"; + } + { + from = "/blog/2011/05/20/proctors-hosting-next-drupal-meetup"; + to = "/blog/proctors-hosting-next-drupal-meetup"; + } + { + from = "/blog/2011/05/23/imagefield-import-archive"; + to = "/blog/imagefield-import-archive"; + } + { + from = "/blog/2011/08/28/create-multigroups-drupal-7-using-field-collections"; + to = "/blog/create-multigroups-drupal-7-using-field-collections"; + } + { + from = "/blog/2011/10/19/install-and-configure-subversion-svn-server-ubuntu"; + to = "/blog/install-and-configure-subversion-svn-server-ubuntu"; + } + { + from = "/blog/2011/10/install-and-configure-subversion-svn-server-ubuntu"; + to = "/blog/how-install-configure-subversion-svn-server-ubuntu"; + } + { + from = "/blog/2012/01/04/site-upgraded-drupal-7"; + to = "/blog/site-upgraded-drupal-7"; + } + { + from = "/blog/2012/02/01/use-authorize-keys-create-passwordless-ssh-connection"; + to = "/blog/use-authorized-keys-create-passwordless-ssh-connection"; + } + { + from = "/blog/2012/04/16/create-omega-subtheme-less-css-preprocessor-using-omega-tools-and-drush"; + to = "/blog/create-omega-subtheme-less-css-preprocessor-using-omega-tools-and-drush"; + } + { + from = "/blog/2012/04/17/installing-nagios-centos"; + to = "/blog/installing-nagios-centos"; + } + { + from = "/blog/2012/04/19/adding-custom-theme-templates-drupal-7"; + to = "/blog/adding-custom-theme-templates-drupal-7"; + } + { + from = "/blog/2012/04/adding-custom-theme-templates-drupal-7"; + to = "/blog/adding-custom-theme-templates-drupal-7"; + } + { + from = "/blog/2012/05/23/add-date-popup-calendar-custom-form"; + to = "/blog/add-date-popup-calendar-custom-form"; + } + { + from = "/blog/2012/05/23/checkout-specific-revision-svn-command-line"; + to = "/blog/checkout-specific-revision-svn-command-line"; + } + { + from = "/blog/2012/05/23/forward-one-domain-another-using-mod-rewrite-and-htaccess"; + to = "/blog/forward-one-domain-another-using-mod-rewrite-and-htaccess"; + } + { + from = "/blog/2012/05/23/forward-one-domain-another-using-modrewrite-and-htaccess"; + to = "/blog/forward-one-domain-another-using-modrewrite-htaccess"; + } + { + from = "/blog/2012/05/23/prevent-apache-displaying-text-files-within-web-browser"; + to = "/blog/prevent-apache-displaying-text-files-within-web-browser"; + } + { + from = "/blog/2012/05/23/writing-info-file-drupal-7-theme"; + to = "/blog/writing-info-file-drupal-7-theme"; + } + { + from = "/blog/2012/05/24/dividing-drupals-process-and-preprocess-functions-separate-files"; + to = "/blog/dividing-drupals-process-and-preprocess-functions-separate-files"; + } + { + from = "/blog/2012/05/forward-one-domain-another-using-modrewrite-and-htaccess"; + to = "/blog/forward-one-domain-another-using-modrewrite-htaccess"; + } + { + from = "/blog/2012/07/12/my-new-drupal-modules"; + to = "/blog/my-new-drupal-modules"; + } + { + from = "/blog/2012/07/14/install-nomensa-media-player-drupal"; + to = "/blog/install-nomensa-media-player-drupal"; + } + { + from = "/blog/2012/07/27/writing-article-linux-journal"; + to = "/blog/writing-article-linux-journal"; + } + { + from = "/blog/2012/07/install-and-configure-nomensa-accessible-media-player-drupal"; + to = "/blog/install-configure-nomensa-accessible-media-player-drupal"; + } + { + from = "/blog/2012/07/nomensa-accessible-media-player-drupal"; + to = "/blog/install-configure-nomensa-accessible-media-player-drupal"; + } + { + from = "/blog/2012/08/18/display-custom-menu-drupal-7-theme-template-file"; + to = "/blog/display-custom-menu-drupal-7-theme-template-file"; + } + { + from = "/blog/2012/09/06/reflections-speaking-unifieddiff"; + to = "/blog/reflections-speaking-unifieddiff"; + } + { + from = "/blog/2012/10/25/my-sublime-text-2-settings"; + to = "/blog/my-sublime-text-2-settings"; + } + { + from = "/blog/2012/11/15/accessible-bristol-site-launched"; + to = "/blog/accessible-bristol-site-launched"; + } + { + from = "/blog/2012/11/17/open-sublime-text-2-mac-os-x-command-line"; + to = "/blog/open-sublime-text-2-mac-os-x-command-line"; + } + { + from = "/blog/2012/12/06/use-sass-and-compass-drupal-7-using-sassy"; + to = "/blog/use-sass-and-compass-drupal-7-using-sassy"; + } + { + from = "/blog/2012/12/use-sass-and-compass-drupal-7-using-sassy"; + to = "/blog/use-sass-and-compass-drupal-7-using-sassy"; + } + { + from = "/blog/2013/01/09/checking-if-user-logged-drupal-right-way"; + to = "/blog/checking-if-user-logged-drupal-right-way"; + } + { + from = "/blog/2013/02/16/creating-and-using-custom-tokens-drupal-7"; + to = "/blog/creating-and-using-custom-tokens-drupal-7"; + } + { + from = "/blog/2013/02/creating-and-using-custom-tokens-drupal-7"; + to = "/blog/creating-using-custom-tokens-drupal-7"; + } + { + from = "/blog/2013/03/02/quickest-way-install-sublime-text-2-ubuntu"; + to = "/blog/quickest-way-install-sublime-text-2-ubuntu"; + } + { + from = "/blog/2013/04/20/leaving-nomensa-joining-precedent"; + to = "/blog/leaving-nomensa-joining-precedent"; + } + { + from = "/blog/2013/04/27/display-git-branch-or-tag-names-your-bash-prompt"; + to = "/blog/display-git-branch-or-tag-names-your-bash-prompt"; + } + { + from = "/blog/2013/04/display-git-branch-or-tag-names-your-bash-prompt"; + to = "/blog/display-git-branch-or-tag-names-your-bash-prompt"; + } + { + from = "/blog/2013/06/13/some-useful-links-using-simpletest-drupal"; + to = "/blog/some-useful-links-using-simpletest-drupal"; + } + { + from = "/blog/2013/07/17/creating-local-and-staging-sites-drupals-domain-module-enabled"; + to = "/blog/creating-local-and-staging-sites-drupals-domain-module-enabled"; + } + { + from = "/blog/2013/07/26/going-drupalcon"; + to = "/blog/going-drupalcon"; + } + { + from = "/blog/2013/09/06/create-a-zen-sub-theme-using-drush"; + to = "/blog/create-a-zen-sub-theme-using-drush"; + } + { + from = "/blog/2013/09/create-zen-sub-theme-using-drush"; + to = "/blog/create-zen-sub-theme-using-drush"; + } + { + from = "/blog/2013/11/19/dont-bootstrap-drupal-use-drush"; + to = "/blog/dont-bootstrap-drupal-use-drush"; + } + { + from = "/blog/2013/11/27/useful-vagrant-commands"; + to = "/blog/useful-vagrant-commands"; + } + { + from = "/blog/2013/11/dont-bootstrap-drupal-use-drush"; + to = "/blog/dont-bootstrap-drupal-use-drush"; + } + { + from = "/blog/2013/12/24/quickly-apply-patches-using-git-and-curl-or-wget"; + to = "/blog/quickly-apply-patches-using-git-and-curl-or-wget"; + } + { + from = "/blog/2013/12/31/download-different-versions-drupal-drush"; + to = "/blog/download-different-versions-drupal-drush"; + } + { + from = "/blog/2013/12/quickly-apply-patches-using-git-and-curl-or-wget"; + to = "/blog/quickly-apply-patches-using-git-curl-or-wget"; + } + { + from = "/blog/2014/01/15/some-useful-git-aliases"; + to = "/blog/some-useful-git-aliases"; + } + { + from = "/blog/2014/02/09/drupalcamp-london-2014"; + to = "/blog/drupalcamp-london-2014"; + } + { + from = "/blog/2014/03/03/what-git-flow"; + to = "/blog/what-git-flow"; + } + { + from = "/blog/2014/05/03/drupal-association"; + to = "/blog/drupal-association"; + } + { + from = "/blog/2014/05/06/thanks"; + to = "/blog/thanks"; + } + { + from = "/blog/2014/05/21/git-format-patch"; + to = "/blog/git-format-patch"; + } + { + from = "/blog/2014/07/02/drush-make-drupalbristol"; + to = "/blog/drush-make-drupalbristol"; + } + { + from = "/blog/2014/10/06/fix-vagrant-loading-wrong-virtual-machine"; + to = "/blog/fix-vagrant-loading-wrong-virtual-machine"; + } + { + from = "/blog/2014/10/21/updating-features-and-adding-components-using-drush"; + to = "/blog/updating-features-and-adding-components-using-drush"; + } + { + from = "/blog/2014/11/18/include-css-fonts-using-sass-each-loop"; + to = "/blog/include-css-fonts-using-sass-each-loop"; + } + { + from = "/blog/2014/11/20/using-remote-files-when-developing-locally-with-stage-file-proxy-module"; + to = "/blog/using-remote-files-when-developing-locally-with-stage-file-proxy-module"; + } + { + from = "/blog/2014/11/27/pantheon-settings-files"; + to = "/blog/pantheon-settings-files"; + } + { + from = "/blog/2014/12/20/include-local-drupal-settings-file-environment-configuration-and-overrides"; + to = "/blog/include-local-drupal-settings-file-environment-configuration-and-overrides"; + } + { + from = "/blog/2015/04/03/how-to-define-a-minimum-drupal-core-version"; + to = "/blog/how-to-define-a-minimum-drupal-core-version"; + } + { + from = "/blog/2015/06/18/updating-forked-repositories-on-github"; + to = "/blog/updating-forked-repositories-on-github"; + } + { + from = "/blog/2015/07/19/sculpin-twig-resources"; + to = "/blog/sculpin-twig-resources"; + } + { + from = "/blog/2015/07/21/automating-sculpin-jenkins"; + to = "/blog/automating-sculpin-jenkins"; + } + { + from = "/blog/2015/12/22/programmatically-load-an-entityform-in-drupal-7"; + to = "/blog/programmatically-load-an-entityform-in-drupal-7"; + } + { + from = "/blog/2016/02/15/announcing-the-drupal-vm-generator"; + to = "/blog/announcing-the-drupal-vm-generator"; + } + { + from = "/blog/2016/05/03/simplifying-drupal-migrations-with-xautoload"; + to = "/blog/simplifying-drupal-migrations-with-xautoload"; + } + { + from = "/blog/2016/07/15/building-gmail-filters-with-php"; + to = "/blog/building-gmail-filters-with-php"; + } + { + from = "/blog/2016/12/30/drupal-vm-generator-291-released"; + to = "/blog/drupal-vm-generator-291-released"; + } + { + from = "/blog/2017/01/07/easier-sculpin-commands-with-composer-and-npm-scripts"; + to = "/blog/easier-sculpin-commands-with-composer-and-npm-scripts"; + } + { + from = "/blog/2017/01/31/nginx-redirects-with-query-string-arguments"; + to = "/blog/nginx-redirects-with-query-string-arguments"; + } + { + from = "/blog/2017/05/05/fixing-drupal-simpletest-docker"; + to = "/blog/2017/05/05/fixing-drupal-simpletest-issues-inside-docker-containers"; + } + { + from = "/blog/2017/05/05/fixing-drupal-simpletest-issues-inside-docker-containers"; + to = "/blog/fixing-drupal-simpletest-issues-inside-docker-containers"; + } + { + from = "/blog/2017/05/20/turning-drupal-module-into-feature"; + to = "/blog/turning-your-custom-drupal-module-feature"; + } + { + from = "/blog/2017/06/09/introducing-the-drupal-meetups-twitterbot"; + to = "/blog/introducing-the-drupal-meetups-twitterbot"; + } + { + from = "/blog/2017/07/13/publishing-sculpin-sites-with-github-pages"; + to = "/blog/publishing-sculpin-sites-github-pages"; + } + { + from = "/blog/2017/11/07/tdd-test-driven-drupal"; + to = "/blog/tdd-test-driven-drupal"; + } + { + from = "/blog/2017/11/07/writing-drupal-module-test-driven-development-tdd"; + to = "/blog/2017/11/07/tdd-test-driven-drupal"; + } + { + from = "/blog/2018/01/30/drupalcamp-bristol-2018"; + to = "/blog/drupalcamp-bristol-2018"; + } + { + from = "/blog/2018/02/05/using-tailwind-css-in-your-drupal-theme"; + to = "/blog/using-tailwind-css-in-your-drupal-theme"; + } + { + from = "/blog/2018/02/27/looking-forward-to-drupalcamp-london"; + to = "/blog/looking-forward-to-drupalcamp-london"; + } + { + from = "/blog/2018/02/27/queuing-private-messages-in-drupal-8"; + to = "/blog/queuing-private-messages-in-drupal-8"; + } + { + from = "/blog/2018/02/28/building-the-new-phpsw-website"; + to = "/blog/building-the-new-phpsw-website"; + } + { + from = "/blog/2018/03/02/yay-the-mediacurrent-contrib-half-hour-is-back"; + to = "/blog/yay-the-mediacurrent-contrib-half-hour-is-back"; + } + { + from = "/blog/2018/03/04/tweets-from-drupalcamp-london"; + to = "/blog/tweets-from-drupalcamp-london"; + } + { + from = "/blog/2018/04/23/back-to-the-future-git-diff-apply"; + to = "/blog/back-future-gits-diff-apply-commands"; + } + { + from = "/blog/2018/05/06/creating-a-custom-phpunit-command-for-docksal"; + to = "/blog/creating-a-custom-phpunit-command-for-docksal"; + } + { + from = "/blog/add-date-popup-calendar-custom-form"; + to = "/blog/how-add-date-popup-calendar-custom-form"; + } + { + from = "/blog/adding-methods-decorating-entity-metadata-wrapper"; + to = "/blog/decorating-entity-metadata-wrapper-add-refactor-methods"; + } + { + from = "/blog/announcing-drupal-vm-generator"; + to = "/blog/announcing-the-drupal-vm-generator"; + } + { + from = "/blog/announcing-the-drupal-vm-config-generator"; + to = "/blog/announcing-the-drupal-vm-generator"; + } + { + from = "/blog/back-to-the-future-git-diff-apply"; + to = "/blog/back-future-gits-diff-apply-commands"; + } + { + from = "/blog/building-gmail-filters-in-php"; + to = "/blog/building-gmail-filters-php"; + } + { + from = "/blog/building-new-phpsw-website"; + to = "/blog/building-the-new-phpsw-website"; + } + { + from = "/blog/building-presentation-slides-reveal-js-tailwind-css"; + to = "/blog/building-presentation-slides-rst2pdf"; + } + { + from = "/blog/building-speaker-leaderboard-php-south-wales-using-drupal-symfony"; + to = "/blog/building-speaker-leaderboard-php-south-wales-drupal-symfony"; + } + { + from = "/blog/create-and-apply-patches"; + to = "/blog/how-create-apply-patches"; + } + { + from = "/blog/create-flickr-photo-gallery-using-feeds-cck-and-views"; + to = "/blog/create-flickr-photo-gallery-using-feeds-cck-views"; + } + { + from = "/blog/creating-and-using-custom-tokens-drupal-7"; + to = "/blog/creating-using-custom-tokens-drupal-7"; + } + { + from = "/blog/creating-custom-docksal-commands"; + to = "/blog/creating-custom-phpunit-command-docksal"; + } + { + from = "/blog/debugging-drupal-commerce-promotions-illiminate-collections"; + to = "/blog/debugging-drupal-commerce-illuminate-collections"; + } + { + from = "/blog/decorating-entity-metadata-wrapper-add-add-refactor-methods"; + to = "/blog/decorating-entity-metadata-wrapper-add-refactor-methods"; + } + { + from = "/blog/dev-book-club-refactoring-chapter-1"; + to = "/blog/dev-book-club-notes-refactoring-chapter-1"; + } + { + from = "/blog/dividing-drupals-process-preprocess-functions-separate-files"; + to = "/blog/dividing-drupals-process-and-preprocess-functions-separate-files"; + } + { + from = "/blog/drupal-8-commerce-fixing-no-such-customer-error-(on-)?checkout"; + to = "/blog/drupal-8-commerce-fixing-no-such-customer-error-checkout"; + } + { + from = "/blog/drupal-vm-generator-291-released"; + to = "/blog/drupal-vm-generator-updates"; + } + { + from = "/blog/drupalcamp-london-2019-tickets"; + to = "/blog/drupalcamp-london-2019-tickets-available-call-sessions"; + } + { + from = "/blog/drush-make-drupalbristol"; + to = "/talks/drush-make-drupalbristol"; + } + { + from = "/blog/easier-git-repository-cloning-with-insteadof"; + to = "/blog/easier-git-repository-cloning-insteadof"; + } + { + from = "/blog/easier-sculpin-commands-with-composer-and-npm-scripts"; + to = "/blog/easier-sculpin-commands-composer-npm-scripts"; + } + { + from = "/blog/editing-meetup-videos-kdenlive"; + to = "/blog/editing-meetup-videos-linux-kdenlive"; + } + { + from = "/blog/examples-of-laravel-collections-in-drupal"; + to = "/blog/using-laravel-collections-drupal"; + } + { + from = "/blog/experimenting-with-events-in-drupal-8"; + to = "/blog/experimenting-events-drupal-8"; + } + { + from = "/blog/fix-vagrant-loading-wrong-virtual-machine"; + to = "/blog/how-fix-vagrant-loading-wrong-virtual-machine"; + } + { + from = "/blog/fixing-drupal-simpletest-docker"; + to = "/blog/fixing-drupal-simpletest-issues-inside-docker-containers"; + } + { + from = "/blog/forward-one-domain-another-using-modrewrite-and-htaccess"; + to = "/blog/forward-one-domain-another-using-modrewrite-htaccess"; + } + { + from = "/blog/forward-one-domain-another-using-modrewrite-and-htaccess"; + to = "/blog/forward-one-domain-another-using-modrewrite-htaccess"; + } + { + from = "/blog/git-format-patch"; + to = "/blog/git-format-patch-your-friend"; + } + { + from = "/blog/how-easily-embed-typekit-fonts-your-drupal-website"; + to = "/blog/easily-embed-typekit-fonts-your-drupal-website"; + } + { + from = "/blog/how-split-new-drupal-contrib-project-within-another-repository"; + to = "/blog/splitting-new-drupal-project-from-repo"; + } + { + from = "/blog/how-style-drupal-6s-taxonomy-lists-php-css-and-jquery"; + to = "/blog/style-drupal-6s-taxonomy-lists-php-css-jquery"; + } + { + from = "/blog/include-local-drupal-settings-file-environment-configuration-overrides"; + to = "/blog/include-local-drupal-settings-file-environment-configuration-and-overrides"; + } + { + from = "/blog/install-and-configure-subversion-svn-server-ubuntu"; + to = "/blog/how-install-configure-subversion-svn-server-ubuntu"; + } + { + from = "/blog/live-blogging-symfonylive-london"; + to = "/blog/live-blogging-symfonylive-london-2019"; + } + { + from = "/blog/minimum-core-version"; + to = "/blog/how-define-minimum-drupal-core-version"; + } + { + from = "/blog/nginx-redirects-with-query-string-arguments"; + to = "/blog/nginx-redirects-query-string-arguments"; + } + { + from = "/blog/null-users-and-system-users-in-drupal"; + to = "/blog/null-users-system-users-drupal"; + } + { + from = "/blog/overridding-phpcs-configuration-drupal-ci"; + to = "/blog/overriding-phpcs-configuration-drupal-ci"; + } + { + from = "/blog/pantheon-settings-files"; + to = "/blog/include-environment-specific-settings-files-pantheon"; + } + { + from = "/blog/pdfpc-pdf-presenter-console-notes"; + to = "/blog/presenting-pdf-slides-using-pdfpc-pdf-presenter-console"; + } + { + from = "/blog/php-apps-subdirectory-nginx"; + to = "/blog/how-put-your-php-application-subdirectory-another-site-nginx"; + } + { + from = "/blog/presenting-tailwind-css-ansible-cms-philly"; + to = "/blog/presenting-on-tailwind-css-and-ansible-at-cms-philly"; + } + { + from = "/blog/programmatically-load-(an-)?entityform-(in-)?drupal-7"; + to = "/blog/entityform"; + } + { + from = "/blog/published-my-first-docker-images-docker-hub"; + to = "/blog/published-my-first-docker-images-docker-hub-adr-tools-sculpin-rst2pdf"; + } + { + from = "/blog/publishing-sculpin-sites-(with-)?github-pages"; + to = "/blog/publishing-sculpin-sites-github-pages"; + } + { + from = "/blog/queuing-private-messages-in-drupal-8"; + to = "/blog/queuing-private-messages-drupal-8"; + } + { + from = "/blog/quick-project-switching-in-phpstorm"; + to = "/blog/quick-project-switching-phpstorm"; + } + { + from = "/blog/quickly-apply-patches-using-git-and-curl-or-wget"; + to = "/blog/quickly-apply-patches-using-git-curl-or-wget"; + } + { + from = "/blog/rebuilding-bartik-with-vuejs-tailwind-css"; + to = "/blog/rebuilding-bartik-drupals-default-theme-vuejs-tailwind-css"; + } + { + from = "/blog/rebuilding-bartik-with-vuejs-tailwind-css-part-2"; + to = "/blog/rebuilding-bartik-drupals-default-theme-vuejs-tailwind-css-part-2"; + } + { + from = "/blog/rebuilding-uis-tailwind-css"; + to = "/blog/uis-ive-rebuilt-tailwind-css"; + } + { + from = "/blog/restructuring-my-tailwindjs-config-files"; + to = "/blog/restructuring-my-tailwindjs-configuration-files"; + } + { + from = "/blog/retrieving-profile-data-user-using-entity-metadata-wrapper"; + to = "/blog/cleanly-retrieving-user-profile-data-using-entity-metadata-wrapper"; + } + { + from = "/blog/running-drupal-with-symfony-local-server"; + to = "/blog/running-drupal-88-symfony-local-server"; + } + { + from = "/blog/running-phpunit-tests-docksal-phpstorm"; + to = "/blog/how-run-drupal-8-phpunit-tests-within-docksal-phpstorm"; + } + { + from = "/blog/simplifying-drupal-migrations-with-xautoload"; + to = "/blog/simplifying-drupal-migrations-xautoload"; + } + { + from = "/blog/speaking-drupalcon-barcelona-2020"; + to = "/blog/speaking-drupalcon-europe-2020"; + } + { + from = "/blog/speaking-during-lockdown"; + to = "/blog/speaking-remotely-during-covid-19"; + } + { + from = "/blog/speaking-remotely-during-lockdown"; + to = "/blog/speaking-remotely-during-covid-19"; + } + { + from = "/blog/style-drupal-6s-taxonomy-lists-php-css-jquery"; + to = "/blog/style-drupal-6s-taxonomy-lists-php-css-and-jquery"; + } + { + from = "/blog/survey-results-my-drupalcon-europe-session"; + to = "/blog/survey-results-my-drupalcon-europe-session-test-driven-drupal"; + } + { + from = "/blog/system-users-null-users"; + to = "/blog/null-users-and-system-users-in-drupal"; + } + { + from = "/blog/test-driven-drupal-gitstore-leanpub"; + to = "/blog/test-driven-drupal-on-gitstore-leanpub"; + } + { + from = "/blog/test-driven-drupal-presentation-drupalcon-europe-0"; + to = "/blog/test-driven-drupal-presentation-drupalcon-europe"; + } + { + from = "/blog/test-driven-drupal-session-drupalcon-europe"; + to = "/blog/test-driven-drupal-presentation-drupalcon-europe"; + } + { + from = "/blog/test-driven-drupal-session-video-drupalcon-europe"; + to = "/blog/test-driven-drupal-presentation-drupalcon-europe"; + } + { + from = "/blog/testing-tailwind-css-plugins-with-jest"; + to = "/blog/testing-tailwind-css-plugins-jest"; + } + { + from = "/blog/testing-tailwindcss-plugins-with-jest"; + to = "/blog/testing-tailwind-css-plugins-jest"; + } + { + from = "/blog/tweets-from-drupalcamp-london"; + to = "/blog/tweets-drupalcamp-london"; + } + { + from = "/blog/updating-features-and-adding-components-using-drush"; + to = "/blog/updating-features-adding-components-using-drush"; + } + { + from = "/blog/updating-forked-repositories-github"; + to = "/blog/updating-forked-github-repos"; + } + { + from = "/blog/use-regular-expressions-search-and-replace-coda-or-textmate"; + to = "/blog/use-regular-expressions-search-replace-coda-or-textmate"; + } + { + from = "/blog/using-environment-variables-settings-docksal"; + to = "/blog/how-use-environment-variables-your-drupal-settings-docksal"; + } + { + from = "/blog/using-psr-4-autoloading-your-drupal-7-test-cases"; + to = "/blog/psr4-autoloading-test-cases-drupal-7"; + } + { + from = "/blog/using-tailwind-css-in-your-drupal-theme"; + to = "/blog/using-tailwind-css-your-drupal-theme"; + } + { + from = "/blog/using-the-pcss-extension-postcss-webpack-encore"; + to = "/blog/using-pcss-extension-postcss-webpack-encore"; + } + { + from = "/blog/weeknotes-june-5th"; + to = "/blog/weeknotes-2021-06-05"; + } + { + from = "/blog/writing-drupal-module-test-driven-development-tdd"; + to = "/blog/writing-new-drupal-8-module-using-test-driven-development-tdd"; + } + { + from = "/book"; + to = "/test-driven-drupal"; + } + { + from = "/calendars?"; + to = "https://savvycal.com/opdavies"; + } + { + from = "/cms-philly"; + to = "/articles/presenting-on-tailwind-css-and-ansible-at-cms-philly"; + } + { + from = "/code-enigma-interview"; + to = "https://blog.codeenigma.com/interview-with-a-drupal-expert-9fcd8e0fad28"; + } + { + from = "/consulting"; + to = "/"; + } + { + from = "/contrib-half-hour"; + to = "https://www.youtube.com/playlist?list=PLu-MxhbnjI9rHroPvZO5LEUhr58Yl0j_F"; + } + { + from = "/cv"; + to = "/cv.txt"; + } + { + from = "/d0P5z"; + to = "/talks/drupal-8-php-libraries-drupalorg-api"; + } + { + from = "/d7"; + to = "/drupal7"; + } + { + from = "/daily"; + to = "/blog"; + } + { + from = "/dcbristol-cfp"; + to = "https://www.papercall.io/drupalcamp-bristol-2019"; + } + { + from = "/dcbristol17-videos"; + to = "https://www.youtube.com/playlist?list=PLOwPvExSyLLngtd6R4PUD9MCXa6QL_obA"; + } + { + from = "/dcbristol19-announced"; + to = "/articles/drupalcamp-bristol-2019-speakers-sessions-announced"; + } + { + from = "/dclondon-sat"; + to = "https://drupalcamp.london/schedule/saturday"; + } + { + from = "/dclondon-sun"; + to = "https://drupalcamp.london/schedule/sunday"; + } + { + from = "/dclondon20"; + to = "/articles/drupalcamp-london-testing-workshop"; + } + { + from = "/ddev-phpunit-command"; + to = "/blog/creating-custom-phpunit-command-ddev"; + } + { + from = "/deploying-php-ansible"; + to = "/talks/deploying-php-ansible-ansistrano"; + } + { + from = "/dks7E"; + to = "https://www.youtube.com/watch?v=PLS4ET7FAcU"; + } + { + from = "/do-library"; + to = "https://github.com/opdavies/drupalorg-api-php"; + } + { + from = "/do-projects"; + to = "https://github.com/opdavies/drupal-module-drupalorg-projects"; + } + { + from = "/docksal-phpunit-phpstorm"; + to = "/articles/running-phpunit-tests-docksal-phpstorm"; + } + { + from = "/docksal-posts"; + to = "/articles/tags/docksal"; + } + { + from = "/dransible"; + to = "https://github.com/opdavies/dransible"; + } + { + from = "/dransible-drupal-9"; + to = "/blog/upgrading-dransible-project-drupal-9"; + } + { + from = "/drupal-bristol-march-19"; + to = "https://docs.google.com/presentation/d/1pk9LIN-hHX73kvDdo-lzgmKlAeH33_K_uvI0t7A-rvY/edit?usp=sharing"; + } + { + from = "/drupal-consultant"; + to = "/drupal-consulting"; + } + { + from = "/drupal-consulting"; + to = "/"; + } + { + from = "/drupal-core-live-stream"; + to = "https://www.youtube.com/watch?v=OK4FWwh1gQU"; + } + { + from = "/drupal-core-testing-gate"; + to = "https://www.drupal.org/core/gates#testing"; + } + { + from = "/drupal-first-time-issues"; + to = "https://www.drupal.org/project/issues/search?text=&projects=&assigned=&submitted=&project_issue_followers=&status%5B%5D=Open&issue_tags_op=%3D&issue_tags=Novice"; + } + { + from = "/drupal-forum-post"; + to = "http://www.webmaster-forums.net/webmasters-corner/developing-my-website-using-php-and-mysql#comment-1231537"; + } + { + from = "/drupal-marketplace-uk"; + to = "https://www.drupal.org/drupal-services?offices%5B%5D=24460"; + } + { + from = "/drupal-meetups-twitterbot"; + to = "/articles/introducing-the-drupal-meetups-twitterbot"; + } + { + from = "/drupal-novice-issues"; + to = "https://www.drupal.org/project/issues/search?text=&projects=&assigned=&submitted=&project_issue_followers=&status%5B%5D=Open&issue_tags_op=%3D&issue_tags=Novice"; + } + { + from = "/drupal-php-developer"; + to = "/drupal-consultant"; + } + { + from = "/drupal-php-developer-consultant-uk"; + to = "/drupal-php-developer"; + } + { + from = "/drupal-tailwind-demo"; + to = "https://www.youtube.com/watch?v=1eM-Gw6GI4g"; + } + { + from = "/drupal-tailwindcss"; + to = "https://www.drupal.org/project/tailwindcss"; + } + { + from = "/drupal-vuejs"; + to = "/talks/decoupling-drupal-vuejs/"; + } + { + from = "/drupal7"; + to = "/drupal-upgrade"; + } + { + from = "/drupalcamp-london-2019-tickets"; + to = "/articles/drupalcamp-london-2019-tickets"; + } + { + from = "/drupalcamp-nyc-training"; + to = "https://www.youtube.com/watch?v=3M9c4UUzKm0"; + } + { + from = "/drupalorg"; + to = "https://www.drupal.org/u/opdavies"; + } + { + from = "/drupalorg-project-issues"; + to = "https://www.drupal.org/project/issues/search?projects=Override+Node+Options%2C+Tailwind+CSS+Starter+Kit%2C+Block+ARIA+Landmark+Roles%2C+Copyright+Block+module%2C+System+User%2C+Null+User%2C+Collection+class%2C+Pathauto+Menu+Link%2C+Webform+ARIA&project_issue_followers=&status%5B%5D=1&status%5B%5D=13&status%5B%5D=8&status%5B%5D=14&status%5B%5D=15&issue_tags_op=%3D"; + } + { + from = "/drupalversary"; + to = "https://github.com/opdavies/drupal-module-drupalversary"; + } + { + from = "/elewant"; + to = "https://elewant.com/shepherd/admire/opdavies"; + } + { + from = "/feed"; + to = "/rss.xml"; + } + { + from = "/first-drupal-core-issue"; + to = "https://www.drupal.org/project/drupal/issues/753898"; + } + { + from = "/first-npm-package"; + to = "https://www.npmjs.com/package/tailwindcss-vuejs"; + } + { + from = "/freeagent"; + to = "https://opdavies.freeagent.com"; + } + { + from = "/git-flow"; + to = "/talks/git-flow"; + } + { + from = "/gitlab"; + to = "https://gitlab.com/opdavies"; + } + { + from = "/gitstore"; + to = "https://enjoy.gitstore.app/maintainers/opdavies"; + } + { + from = "/gmail-filters"; + to = "https://gitlab.com/opdavies/gmail-filters"; + } + { + from = "/images/me-precedent.jpg"; + to = "/sites/default/files/images/social-avatar.jpg"; + } + { + from = "/inviqa-tailwind-demo"; + to = "https://play.tailwindcss.com/Yfmw8O5UNN"; + } + { + from = "/inviqa-tailwind-notes"; + to = "https://gist.github.com/opdavies/e6f0f4938506a6859acf1aca8b4e1a74"; + } + { + from = "/join-php-south-wales-slack"; + to = "https://join.slack.com/t/phpsouthwales/shared_invite/zt-4vuetc43-AvtEK1WqNzp5k1w4yWKOJA"; + } + { + from = "/jy6rW"; + to = "https://www.meetup.com/PHP-South-Wales/events/264731393"; + } + { + from = "/kB6Jd"; + to = "/articles/running-drupal-with-symfony-local-server/"; + } + { + from = "/kmDRA"; + to = "https://www.bbc.co.uk/news/uk-46561779"; + } + { + from = "/leeds-php-drupal-9"; + to = "https://www.meetup.com/leedsphp/events/272504993"; + } + { + from = "/live"; + to = "https://www.youtube.com/channel/UCkeK0qF9HHUPQH_fvn4ghqQ"; + } + { + from = "/npm"; + to = "https://www.npmjs.com/~opdavies"; + } + { + from = "/oFlkS"; + to = "/articles/test-driven-drupal-on-gitstore-leanpub"; + } + { + from = "/oliver-davies-uk-based-drupal-symfony-developer"; + to = "/oliver-davies-uk-based-drupal-php-developer"; + } + { + from = "/pair-programming"; + to = "/pair"; + } + { + from = "/pair-with-me"; + to = "/pair"; + } + { + from = "/pairing"; + to = "/pair"; + } + { + from = "/php-ansible"; + to = "/talks/deploying-php-ansible-ansistrano"; + } + { + from = "/presentations/building-presenting-slide-decks-rst2pdf"; + to = "/presentations/rst2pdf"; + } + { + from = "/presentations/building-static-websites-sculpin"; + to = "/presentations/sculpin"; + } + { + from = "/qSHAl"; + to = "/articles/published-my-first-npm-package/"; + } + { + from = "/qT1Rb"; + to = "https://github.com/opdavies/drupal-meetups-twitterbot"; + } + { + from = "/rebuilding-acquia"; + to = "https://rebuilding-acquia.oliverdavies.uk"; + } + { + from = "/rebuilding-bartik"; + to = "/articles/rebuilding-bartik-with-vuejs-tailwind-css"; + } + { + from = "/rebuilding-bristol-js"; + to = "https://github.com/opdavies/rebuilding-bristol-js"; + } + { + from = "/rebuilding-pantheon"; + to = "https://play.tailwindcss.com/LND98XihGI?layout=horizontal"; + } + { + from = "/rebuilding-platformsh"; + to = "https://rebuilding-platformsh.oliverdavies.uk"; + } + { + from = "/rebuilding-symfony"; + to = "https://github.com/opdavies/rebuilding-symfony"; + } + { + from = "/rk29B"; + to = "https://www.meetup.com/PHP-South-Wales/events/268422525"; + } + { + from = "/roadmap"; + to = "/drupal-upgrade"; + } + { + from = "/rss"; + to = "/rss.xml"; + } + { + from = "/rst2pdf"; + to = "/talks/building-presenting-slide-decks-rst2pdf"; + } + { + from = "/s9MjJ"; + to = "https://symfonycasts.com/screencast/symfony"; + } + { + from = "/sculpin"; + to = "/talks/building-static-websites-sculpin"; + } + { + from = "/sculpin-encore-versioning"; + to = "https://github.com/opdavies/oliverdavies.uk/commit/d192b04aefa6e7a21bfc1f2e0fe0a16111e0e8a2"; + } + { + from = "/sites/default/files/images/social-avatar.jpg"; + to = "/images/social-avatar.jpg"; + } + { + from = "/skills"; + to = "https://opdavies-skills-tailwindcss.netlify.com/"; + } + { + from = "/slides-drupal-9"; + to = "https://slides-upgrading-to-drupal-9.oliverdavies.uk"; + } + { + from = "/slides-upgrading-to-drupal-9"; + to = "https://slides-upgrading-to-drupal-9.oliverdavies.uk"; + } + { + from = "/slides-upgrading-to-drupal-9/index.html"; + to = "https://slides-upgrading-to-drupal-9.oliverdavies.uk"; + } + { + from = "/slides-working-with-workspace"; + to = "https://slides-working-with-workspace.oliverdavies.uk"; + } + { + from = "/speaker"; + to = "/press"; + } + { + from = "/speaker-info"; + to = "/speaker"; + } + { + from = "/speaker-information"; + to = "/speaker"; + } + { + from = "/speaking-videos"; + to = "https://www.youtube.com/playlist?list=PLHn41Ay7w7kfAzczswrANch5oHAPZBlvu"; + } + { + from = "/stream"; + to = "https://www.youtube.com/channel/UCkeK0qF9HHUPQH_fvn4ghqQ/live"; + } + { + from = "/subscription"; + to = "/"; + } + { + from = "/swap-markdown-parser"; + to = "https://github.com/opdavies/sculpin-twig-markdown-bundle-example/tree/swap-markdown-parser"; + } + { + from = "/symfony"; + to = "https://connect.symfony.com/profile/opdavies"; + } + { + from = "/symfony-server"; + to = "/articles/running-drupal-with-symfony-local-server"; + } + { + from = "/symfonylive"; + to = "/articles/live-blogging-symfonylive-london"; + } + { + from = "/symposium"; + to = "https://symposiumapp.com/u/opdavies"; + } + { + from = "/tailwind-css-talk"; + to = "/talks/taking-flight-tailwind-css"; + } + { + from = "/tailwind-repos"; + to = "https://github.com/opdavies?utf8=%e2%9c%93&tab=repositories&q=tailwindcss"; + } + { + from = "/tailwind-talk"; + to = "/talks/taking-flight-with-tailwind-css"; + } + { + from = "/tailwindcss-demo"; + to = "http://tailwindcss-demo.oliverdavies.uk/"; + } + { + from = "/talks"; + to = "/presentations"; + } + { + from = "/talks-offer-tweet"; + to = "https://twitter.com/opdavies/status/1250870367712935938"; + } + { + from = "/talks/2012/09/05/what-is-this-drupal-thing-unified-diff"; + to = "/talks/what-is-this-drupal-thing"; + } + { + from = "/talks/2013/07/10/drupal-ldap-swdug"; + to = "/talks/drupal-ldap"; + } + { + from = "/talks/2014/03/01/git-flow-drupalcamp-london-2014"; + to = "/talks/git-flow"; + } + { + from = "/talks/2014/07/02/drush-make-drupalbristol-drupal-bristol"; + to = "/talks/drush-make-drupalbristol"; + } + { + from = "/talks/2014/08/19/drupal-association-swdug"; + to = "/talks/drupal-association"; + } + { + from = "/talks/2015/01/18/drupalorg-2015-drupalcamp-brighton-2015"; + to = "/talks/drupalorg-in-2015-whats-coming-next"; + } + { + from = "/talks/2015/02/28/drupalorg-2015-drupalcamp-london-2015"; + to = "/talks/drupalorg-in-2015-whats-coming-next"; + } + { + from = "/talks/2015/04/08/drupal-8-phpsw"; + to = "/talks/drupal-8"; + } + { + from = "/talks/2015/07/25/test-drive-twig-with-sculpin-drupalcamp-north-2015"; + to = "/talks/test-drive-twig-with-sculpin"; + } + { + from = "/talks/2015/08/25/dancing-for-drupal-umbristol"; + to = "/talks/dancing-for-drupal"; + } + { + from = "/talks/2015/10/14/sculpin-phpsw"; + to = "/talks/sculpin"; + } + { + from = "/talks/2016/03/05/drupal-8-module-development-drupalcamp-london-2016"; + to = "/talks/getting-started-with-drupal-8-module-development"; + } + { + from = "/talks/2016/03/09/drupal-vm-generator-nwdug"; + to = "/talks/drupal-vm-generator"; + } + { + from = "/talks/2016/04/02/drupal-vm-generator-drupal-bristol"; + to = "/talks/drupal-vm-generator"; + } + { + from = "/talks/2016/06/11/drupal-8-rejoining-the-herd-php-south-coast-2016"; + to = "/talks/drupal-8-rejoining-the-herd"; + } + { + from = "/talks/2016/07/23/drupal-vm-meet-symfony-console-drupalcamp-bristol-2016"; + to = "/talks/drupal-vm-meet-symfony-console"; + } + { + from = "/talks/2016/11/09/drupal-development-with-composer-phpsw"; + to = "/talks/drupal-development-with-composer"; + } + { + from = "/talks/2016/11/17/goodbye-drush-make-hello-composer-drupal-bristol"; + to = "/talks/goodbye-drush-make-hello-composer"; + } + { + from = "/talks/2017/01/18/getting-your-data-into-drupal-8-drupal-bristol"; + to = "/talks/getting-your-data-into-drupal-8"; + } + { + from = "/talks/2017/03/04/getting-your-data-into-drupal-8-drupalcamp-london-2017"; + to = "/talks/getting-your-data-into-drupal-8"; + } + { + from = "/talks/ansible-ansistrano"; + to = "https://www.oliverdavies.uk/talks/deploying-php-ansible-ansistrano"; + } + { + from = "/talks/deploying-php-applications-fabric"; + to = "/talks/deploying-php-fabric"; + } + { + from = "/talks/deploying-php-applications-with-fabric"; + to = "/talks/deploying-php-fabric"; + } + { + from = "/talks/drupal-vm-generator-2"; + to = "/talks/drupal-vm-generator"; + } + { + from = "/talks/drupalorg-2015-2"; + to = "/talks/drupalorg-2015"; + } + { + from = "/talks/drupalorg-in-2015-whats-coming-next"; + to = "/talks/drupalorg-2015"; + } + { + from = "/talks/getting-started-with-drupal-8-module-development"; + to = "/drupal-8-module-development"; + } + { + from = "/talks/having-fun-drupal-8-php-libraries-drupalorg-api"; + to = "/talks/drupal-8-php-libraries-drupalorg-api"; + } + { + from = "/talks/never-commit-master-introduction-git-flow"; + to = "/talks/git-flow"; + } + { + from = "/talks/sculpin"; + to = "/talks/building-static-websites-sculpin"; + } + { + from = "/talks/tailwind"; + to = "/talks/taking-flight-with-tailwind-css/"; + } + { + from = "/talks/taking-flight-tailwind-css"; + to = "/talks/taking-flight-with-tailwind-css"; + } + { + from = "/talks/using-laravel-collections-outside-laravel"; + to = "/talks/using-illuminate-collections-outside-laravel"; + } + { + from = "/talks/working-workspace"; + to = "/talks/working-with-workspace"; + } + { + from = "/tdd-blog"; + to = "https://github.com/opdavies/drupal-module-tdd-blog"; + } + { + from = "/tdd-test-driven-drupal"; + to = "/talks/tdd-test-driven-drupal/"; + } + { + from = "/team-coaching"; + to = "/"; + } + { + from = "/test-driven-drupal-book"; + to = "/test-driven-drupal"; + } + { + from = "/testing-drupal"; + to = "https://www.oliverdavies.uk/talks/tdd-test-driven-drupal"; + } + { + from = "/testing-drupal-intro"; + to = "https://inviqa.com/blog/drupal-automated-testing-introduction"; + } + { + from = "/testing-tailwind-plugins"; + to = "/articles/testing-tailwindcss-plugins-with-jest"; + } + { + from = "/testing-workshop"; + to = "https://github.com/opdavies/workshop-drupal-automated-testing"; + } + { + from = "/testing-workshop-code"; + to = "https://github.com/opdavies/workshop-drupal-automated-testing-code"; + } + { + from = "/todoist-filters"; + to = "https://gist.github.com/opdavies/6709fbdac5c3babbd94137bcc8b8e3c2"; + } + { + from = "/twitter-tweaks"; + to = "https://github.com/opdavies/chrome-extension-twitter-tweaks"; + } + { + from = "/upgrading-to-drupal-9"; + to = "/talks/upgrading-your-site-drupal-9"; + } + { + from = "/uxbjV"; + to = "https://www.drupal.org/project/copyright_block"; + } + { + from = "/vyTEF"; + to = "https://www.npmjs.com/package/tailwindcss-vuejs"; + } + { + from = "/webpack-encore-pcss-regex"; + to = "https://regexr.com/51iaf"; + } + { + from = "/wordcamp-bristol-tailwindcss"; + to = "https://2019.bristol.wordcamp.org/session/taking-flight-with-tailwind-css"; + } + { + from = "/wordpress-tailwind"; + to = "https://github.com/opdavies/wordcamp-bristol-2019"; + } + { + from = "/work"; + to = "/drupal-php-developer"; + } + { + from = "/working-with-workspace"; + to = "/talks/working-with-workspace"; + } + { + from = "/workshop-drupal-testing"; + to = "https://github.com/opdavies/workshop-drupal-automated-testing"; + } + { + from = "/workspace-demo"; + to = "https://github.com/opdavies/working-with-workspace-demo"; + } + { + from = "/wp-tailwind"; + to = "https://wp-tailwind.oliverdavies.uk"; + } + { + from = "/wp-tailwind-repo"; + to = "https://github.com/opdavies/wordcamp-bristol-2019"; + } + { + from = "/wp-tailwind-starter"; + to = "https://github.com/opdavies/wordpress-tailwindcss-startker-kit"; + } + { + from = "/wp-tailwind-static"; + to = "https://wp-tailwind.oliverdavies.uk"; + } + { + from = "/yXhoS"; + to = "/talks/things-you-should-know-about-php"; + } +] diff --git a/hosts/nixedo/modules/paperless.nix b/hosts/nixedo/modules/paperless.nix new file mode 100644 index 00000000..ca58fc15 --- /dev/null +++ b/hosts/nixedo/modules/paperless.nix @@ -0,0 +1,60 @@ +{ config, lib, ... }: + +with lib; + +let + cfg = homelab.services.paperless; + homelab = config.homelab; + service = "paperless"; +in +{ + options.homelab.services.${service} = { + enable = mkEnableOption "Enable ${service}"; + + url = mkOption { + default = "${service}.${homelab.domain}"; + type = types.str; + }; + + homepage.name = mkOption { + default = "Paperless-ngx"; + type = types.str; + }; + + homepage.description = mkOption { + default = "Document management system"; + type = types.str; + }; + + homepage.icon = mkOption { + default = "paperless"; + type = types.str; + }; + + homepage.category = mkOption { + default = "Services"; + type = types.str; + }; + }; + + config = mkIf cfg.enable { + services = { + ${service} = { + enable = true; + + dataDir = "/mnt/media/${service}"; + domain = "https://${cfg.url}"; + }; + + nginx.virtualHosts."${cfg.url}" = { + forceSSL = true; + useACMEHost = homelab.domain; + + locations."/" = { + proxyPass = "http://localhost:${toString config.services.${service}.port}"; + recommendedProxySettings = true; + }; + }; + }; + }; +} diff --git a/hosts/nixedo/modules/peertube.nix b/hosts/nixedo/modules/peertube.nix new file mode 100644 index 00000000..a35e3f01 --- /dev/null +++ b/hosts/nixedo/modules/peertube.nix @@ -0,0 +1,88 @@ +{ + config, + inputs, + lib, + ... +}: + +let + inherit (lib) + mkEnableOption + mkIf + mkOption + types + ; + + cfg = homelab.services.${service}; + homelab = config.homelab; + service = "peertube"; +in +{ + options.homelab.services.${service} = { + enable = mkEnableOption "Enable ${service}"; + + url = mkOption { + default = "videos.${homelab.domain}"; + type = types.str; + }; + + homepage.name = mkOption { + default = "Peertube"; + type = types.str; + }; + + homepage.description = mkOption { + default = "A free and open-source, decentralized, ActivityPub federated video platform"; + type = types.str; + }; + + homepage.icon = mkOption { + default = "peertube"; + type = types.str; + }; + + homepage.category = mkOption { + default = "Media"; + type = types.str; + }; + }; + + config = mkIf cfg.enable { + services = { + ${service} = { + enable = true; + + configureNginx = true; + enableWebHttps = false; + localDomain = cfg.url; + + database = { + createLocally = true; + }; + + redis = { + createLocally = true; + enableUnixSocket = true; + }; + + secrets.secretsFile = config.age.secrets.peertube-env.path; + + settings = { + webserver = { + hostname = config.services.${service}.localDomain; + port = lib.mkForce 443; + }; + }; + }; + + cloudflared.tunnels.${homelab.cloudflared.tunnelId}.ingress = { + ${cfg.url} = "http://localhost:${toString config.services.${service}.listenWeb}"; + }; + }; + + age.secrets."${service}-env" = { + file = "${inputs.self}/secrets/${service}-env.age"; + owner = config.services.${service}.user; + }; + }; +} diff --git a/hosts/nixedo/ports.nix b/hosts/nixedo/ports.nix new file mode 100644 index 00000000..e3ceba08 --- /dev/null +++ b/hosts/nixedo/ports.nix @@ -0,0 +1,38 @@ +{ lib, ... }: + +let + inherit (lib) mkOption types; +in +{ + options.homelab.ports = mkOption { + internal = true; + type = types.attrsOf types.port; + }; + + config.homelab.ports = { + homepage-dashboard = 8097; + mealie = 9001; + pihole = 8082; + tubearchivist = 8099; + vaultwarden = 8022; + + nginx-website-sculpin = 8095; + nginx-website-tome = 8098; + + nginx-books = 9002; + nginx-bootstrap-with-tailwind = 8081; + nginx-eric = 8084; + nginx-examples = 9003; + nginx-florida-drupalcamp-tailwind-css = 8083; + nginx-luke = 8094; + nginx-phpsw-sculpin-demo = 8085; + nginx-rebuilding-acquia = 8086; + nginx-rebuilding-bartik = 8087; + nginx-rebuilding-bristol-js = 8088; + nginx-rebuilding-symfony = 8089; + nginx-tailwindcss-demo = 8090; + nginx-talking-drupal-tailwindcss = 8093; + nginx-wp-tailwind = 8091; + nginx-zet = 8092; + }; +} diff --git a/hosts/nixedo/secrets.nix b/hosts/nixedo/secrets.nix new file mode 100644 index 00000000..6c55583f --- /dev/null +++ b/hosts/nixedo/secrets.nix @@ -0,0 +1,6 @@ +{ + age.secrets = { + cloudflare.file = ../../secrets/cloudflare.age; + cloudflared.file = ../../secrets/cloudflared-credentials.age; + }; +} diff --git a/hosts/nixedo/services/containers/default.nix b/hosts/nixedo/services/containers/default.nix new file mode 100644 index 00000000..10dea067 --- /dev/null +++ b/hosts/nixedo/services/containers/default.nix @@ -0,0 +1,5 @@ +{ + imports = [ + ./tubearchivist.nix + ]; +} diff --git a/hosts/nixedo/services/default.nix b/hosts/nixedo/services/default.nix new file mode 100644 index 00000000..b5a19f88 --- /dev/null +++ b/hosts/nixedo/services/default.nix @@ -0,0 +1,50 @@ +{ + config, + inputs, + pkgs, + ... +}: + +{ + imports = [ + ./homepage + ./mastodon.nix + ./mealie.nix + ./samba.nix + ./uptime-kuma.nix + ./vaultwarden.nix + ]; + + services = { + postgresqlBackup.enable = true; + }; + + services.gitea-actions-runner.instances.default = { + enable = true; + + hostPackages = with pkgs; [ + bash + coreutils + curl + gawk + gitMinimal + gnused + jq + nix + nodejs + wget + ]; + + labels = [ + "nixos:host" + ]; + + name = config.networking.hostName; + tokenFile = config.age.secrets.forgejo-runner-token.path; + url = config.services.forgejo.settings.server.ROOT_URL; + }; + + age.secrets = { + forgejo-runner-token.file = "${inputs.self}/secrets/forgejo-runner-token.age"; + }; +} diff --git a/hosts/nixedo/services/homepage/default.nix b/hosts/nixedo/services/homepage/default.nix new file mode 100644 index 00000000..df0b543b --- /dev/null +++ b/hosts/nixedo/services/homepage/default.nix @@ -0,0 +1,63 @@ +{ config, lib, ... }: + +with lib; + +let + cfg = homelab.services.${service}; + homelab = config.homelab; + service = "homepage-dashboard"; +in +{ + options.homelab.services.${service} = { + enable = mkEnableOption "Enable ${service}"; + + url = mkOption { + default = "${config.networking.hostName}.${homelab.domain}"; + type = types.str; + }; + }; + + config = mkIf cfg.enable { + services = { + ${service} = { + enable = true; + listenPort = homelab.ports.${service}; + openFirewall = true; + + customCSS = '' + #information-widgets { + padding-left: 1.5rem; + padding-right: 1.5rem; + } + + div#footer { + display: none; + } + + .services-group { + margin-bottom: 3rem; + } + ''; + + services = (import ./services.nix { inherit config lib; }); + + settings = { + headerStyle = "clean"; + hideVersion = "true"; + layout = (import ./layout.nix); + statusStyle = "dot"; + }; + }; + + glances.enable = true; + + nginx.virtualHosts.${cfg.url} = { + forceSSL = true; + useACMEHost = homelab.domain; + + locations."/".proxyPass = + "http://localhost:${toString config.services.homepage-dashboard.listenPort}"; + }; + }; + }; +} diff --git a/hosts/nixedo/services/homepage/glances.nix b/hosts/nixedo/services/homepage/glances.nix new file mode 100644 index 00000000..ebcd3622 --- /dev/null +++ b/hosts/nixedo/services/homepage/glances.nix @@ -0,0 +1,57 @@ +{ config }: + +{ + Glances = + let + port = toString config.services.glances.port; + in + [ + { + Info = { + widget = { + type = "glances"; + url = "http://localhost:${port}"; + metric = "info"; + chart = false; + version = 4; + }; + }; + } + + { + "CPU Temp" = { + widget = { + type = "glances"; + url = "http://localhost:${port}"; + metric = "sensor:Package id 0"; + chart = false; + version = 4; + }; + }; + } + + { + Processes = { + widget = { + type = "glances"; + url = "http://localhost:${port}"; + metric = "process"; + chart = false; + version = 4; + }; + }; + } + + { + Network = { + widget = { + type = "glances"; + url = "http://localhost:${port}"; + metric = "network:enp0s20f0u1"; + chart = false; + version = 4; + }; + }; + } + ]; +} diff --git a/hosts/nixedo/services/homepage/layout.nix b/hosts/nixedo/services/homepage/layout.nix new file mode 100644 index 00000000..b0b05b94 --- /dev/null +++ b/hosts/nixedo/services/homepage/layout.nix @@ -0,0 +1,23 @@ +[ + { + Glances = { + columns = 4; + header = false; + style = "row"; + }; + } + + { + Media = { + header = true; + style = "column"; + }; + } + + { + Services = { + header = true; + style = "column"; + }; + } +] diff --git a/hosts/nixedo/services/homepage/services.nix b/hosts/nixedo/services/homepage/services.nix new file mode 100644 index 00000000..52c8cec8 --- /dev/null +++ b/hosts/nixedo/services/homepage/services.nix @@ -0,0 +1,32 @@ +{ config, lib }: + +with lib; + +let + homelab = config.homelab.services; + + homepageCategories = [ + "Media" + "Services" + ]; + + homepageServices = + category: + (attrsets.filterAttrs ( + name: value: value ? homepage && value.homepage.category == category + ) homelab); + + services = lists.forEach homepageCategories (cat: { + "${cat}" = + lib.lists.forEach (lib.attrsets.mapAttrsToList (name: value: name) (homepageServices "${cat}")) + (x: { + "${homelab.${x}.homepage.name}" = { + icon = homelab.${x}.homepage.icon; + description = homelab.${x}.homepage.description; + href = "https://${homelab.${x}.url}"; + siteMonitor = "https://${homelab.${x}.url}"; + }; + }); + }); +in +services ++ [ (import ./glances.nix { inherit config; }) ] diff --git a/hosts/nixedo/services/mastodon.nix b/hosts/nixedo/services/mastodon.nix new file mode 100644 index 00000000..d020a223 --- /dev/null +++ b/hosts/nixedo/services/mastodon.nix @@ -0,0 +1,84 @@ +{ config, lib, ... }: + +with lib; + +let + cfg = config.homelab.services.${service}; + domain = "oliverdavies.uk"; + service = "mastodon"; +in +{ + options.homelab.services.${service} = { + url = mkOption { + default = "social.${domain}"; + internal = true; + type = types.str; + }; + }; + + config = { + services = { + ${service} = { + enable = false; + + configureNginx = false; + localDomain = domain; + streamingProcesses = 3; + + extraConfig = { + SINGLE_USER_MODE = "true"; + WEB_DOMAIN = cfg.url; + }; + + smtp = { + fromAddress = "social@${domain}"; + }; + }; + + cloudflared.tunnels.${config.homelab.cloudflared.tunnelId} = { + ingress = { + "${cfg.url}" = "http://localhost"; + }; + }; + + nginx = { + upstreams.mastodon-streaming = { + extraConfig = '' + least_conn; + ''; + + servers = builtins.listToAttrs ( + map (i: { + name = "unix:/run/mastodon-streaming/streaming-${toString i}.socket"; + value = { }; + }) (range 1 config.services.mastodon.streamingProcesses) + ); + }; + + virtualHosts."social.oliverdavies.uk" = { + root = "${config.services.mastodon.package}/public/"; + + locations = { + "/".tryFiles = "$uri @proxy"; + + "/api/v1/streaming/" = { + proxyPass = "http://mastodon-streaming"; + proxyWebsockets = true; + }; + + "/system/".alias = "/var/lib/mastodon/public-system/"; + + "@proxy" = { + proxyPass = "http://unix:/run/mastodon-web/web.socket"; + proxyWebsockets = true; + }; + }; + + extraConfig = '' + client_max_body_size 100m; + ''; + }; + }; + }; + }; +} diff --git a/hosts/nixedo/services/mealie.nix b/hosts/nixedo/services/mealie.nix new file mode 100644 index 00000000..ceb4516f --- /dev/null +++ b/hosts/nixedo/services/mealie.nix @@ -0,0 +1,27 @@ +{ config, pkgs, ... }: + +let + ports = config.homelab.ports; +in +{ + services.mealie = { + enable = true; + package = pkgs.stable.mealie; + + database.createLocally = true; + + port = ports.mealie; + + settings.ALLOW_SIGNUP = "false"; + }; + + services.nginx.virtualHosts."mealie.oliverdavies.uk" = { + forceSSL = true; + useACMEHost = "oliverdavies.uk"; + + locations."/" = { + proxyPass = "http://localhost:${toString config.services.mealie.port}"; + recommendedProxySettings = true; + }; + }; +} diff --git a/hosts/nixedo/services/samba.nix b/hosts/nixedo/services/samba.nix new file mode 100644 index 00000000..5f925121 --- /dev/null +++ b/hosts/nixedo/services/samba.nix @@ -0,0 +1,28 @@ +{ + services.samba = { + enable = true; + openFirewall = true; + + settings = { + home = { + path = "/home/opdavies"; + browseable = true; + writable = true; + "valid users" = [ "opdavies" ]; + "force group" = "media"; + "create mask" = "0660"; + "directory mask" = "0770"; + }; + + media = { + path = "/mnt/media"; + browseable = true; + writable = true; + "valid users" = [ "opdavies" ]; + "force group" = "media"; + "create mask" = "0660"; + "directory mask" = "0770"; + }; + }; + }; +} diff --git a/hosts/nixedo/services/uptime-kuma.nix b/hosts/nixedo/services/uptime-kuma.nix new file mode 100644 index 00000000..2bdb1487 --- /dev/null +++ b/hosts/nixedo/services/uptime-kuma.nix @@ -0,0 +1,55 @@ +{ config, lib, ... }: + +with lib; + +let + cfg = homelab.services.${service}; + homelab = config.homelab; + service = "uptime-kuma"; +in +{ + options.homelab.services.${service} = { + enable = mkEnableOption "Enable ${service}"; + + url = mkOption { + default = "uptime.${homelab.domain}"; + type = types.str; + }; + + homepage.name = mkOption { + default = "Uptime Kuma"; + type = types.str; + }; + + homepage.description = mkOption { + default = "A fancy self-hosted monitoring tool"; + type = types.str; + }; + + homepage.icon = mkOption { + default = "uptime-kuma"; + type = types.str; + }; + + homepage.category = mkOption { + default = "Services"; + type = types.str; + }; + }; + + config = mkIf cfg.enable { + services = { + ${service}.enable = true; + + nginx.virtualHosts.${cfg.url} = { + forceSSL = true; + useACMEHost = homelab.domain; + + locations."/" = { + proxyPass = "http://localhost:${toString config.services.${service}.settings.PORT}"; + recommendedProxySettings = true; + }; + }; + }; + }; +} diff --git a/hosts/nixedo/services/vaultwarden.nix b/hosts/nixedo/services/vaultwarden.nix new file mode 100644 index 00000000..b3f697a3 --- /dev/null +++ b/hosts/nixedo/services/vaultwarden.nix @@ -0,0 +1,53 @@ +{ + config, + inputs, + lib, + ... +}: + +with lib; + +let + cfg = homelab.services.${service}; + homelab = config.homelab; + service = "vaultwarden"; +in +{ + options.homelab.services.${service} = { + enable = mkEnableOption "Enable ${service}"; + + url = mkOption { + default = "${service}.${homelab.domain}"; + type = types.str; + }; + }; + + config = mkIf cfg.enable { + services = { + ${service} = { + enable = true; + + environmentFile = config.age.secrets.vaultwarden-env.path; + + config = { + DOMAIN = "https://${cfg.url}"; + ROCKET_ADDRESS = "127.0.0.1"; + ROCKET_PORT = homelab.ports.${service}; + SIGNUPS_ALLOWED = false; + }; + }; + + nginx.virtualHosts.${cfg.url} = { + forceSSL = true; + useACMEHost = homelab.domain; + + locations."/" = { + proxyPass = "http://localhost:${toString config.services.${service}.config.ROCKET_PORT}"; + recommendedProxySettings = true; + }; + }; + }; + + age.secrets.vaultwarden-env.file = "${inputs.self}/secrets/vaultwarden-env.age"; + }; +} diff --git a/hosts/t480/configuration.nix b/hosts/t480/configuration.nix new file mode 100644 index 00000000..6609ecc7 --- /dev/null +++ b/hosts/t480/configuration.nix @@ -0,0 +1,98 @@ +{ inputs, pkgs, ... }: + +{ + imports = [ + inputs.agenix.nixosModules.default + inputs.nixos-hardware.nixosModules.common-gpu-intel + inputs.nixos-hardware.nixosModules.lenovo-thinkpad-t480 + + ../common + + ./hardware-configuration.nix + ./cron.nix + ./neomutt.nix + ./newsboat + ./secrets.nix + ./xserver.nix + + ../../users/opdavies.nix + ]; + + services = { + auto-cpufreq.enable = true; + geoclue2.enable = true; + gvfs.enable = true; + power-profiles-daemon.enable = false; + printing.enable = true; + pulseaudio.enable = false; + thermald.enable = true; + throttled.enable = true; + upower.enable = true; + }; + + boot = { + loader = { + systemd-boot.enable = true; + systemd-boot.configurationLimit = 10; + + efi.canTouchEfiVariables = true; + }; + }; + + systemd.settings.Manager = { + DefaultTimeoutStopSec = "10s"; + }; + + networking.networkmanager.enable = true; + + networking.hosts = { + "192.168.1.116" = [ + "home.oliverdavies.uk" + "jellyfin.oliverdavies.uk" + "nixedo.oliverdavies.uk" + "paperless.oliverdavies.uk" + "photos.oliverdavies.uk" + "ssh.oliverdavies.uk" + "tubearchivist.oliverdavies.uk" + ]; + }; + + security = { + polkit.enable = true; + rtkit.enable = true; + }; + + environment.systemPackages = with pkgs; [ + abook + acpi + arandr + brightnessctl + cdrkit + cpufrequtils + dvdbackup + dvdplusrwtools + ffmpegthumbnailer + gimp3 + gtypist + hunspellDicts.en-gb-large + isync + kdePackages.kdenlive + kdePackages.okular + libnotify + libreoffice + meslo-lg + obs-studio + pam_gnupg + pamixer + pavucontrol + peek + pmutils + shotwell + stable.gscan2pdf + sxiv + ttyper + xcape + xsel + yt-dlp + ]; +} diff --git a/hosts/t480/cron.nix b/hosts/t480/cron.nix new file mode 100644 index 00000000..9d7b0e53 --- /dev/null +++ b/hosts/t480/cron.nix @@ -0,0 +1,12 @@ +{ pkgs, ... }: + +{ + services.cron = { + enable = true; + + systemCronJobs = [ + "*/15 * * * * opdavies ${pkgs.imapfilter}/bin/imapfilter -c ~/Code/personal/email-filters/config.lua" + "0 8,20 * * * opdavies ${pkgs.isync}/bin/mbsync -a" + ]; + }; +} diff --git a/hosts/t480/hardware-configuration.nix b/hosts/t480/hardware-configuration.nix new file mode 100644 index 00000000..49b636eb --- /dev/null +++ b/hosts/t480/hardware-configuration.nix @@ -0,0 +1,53 @@ +# Do not modify this file! It was generated by ‘nixos-generate-config’ +# and may be overwritten by future invocations. Please make changes +# to /etc/nixos/configuration.nix instead. +{ + config, + lib, + pkgs, + modulesPath, + ... +}: + +{ + imports = [ + (modulesPath + "/installer/scan/not-detected.nix") + ]; + + boot.initrd.availableKernelModules = [ + "xhci_pci" + "ahci" + "usb_storage" + "sd_mod" + ]; + boot.initrd.kernelModules = [ ]; + boot.kernelModules = [ "kvm-intel" ]; + boot.extraModulePackages = [ ]; + + fileSystems."/" = { + device = "/dev/disk/by-uuid/34bd5f2e-8ccf-4d5f-876c-9d7ea84c44f0"; + fsType = "ext4"; + }; + + fileSystems."/boot" = { + device = "/dev/disk/by-uuid/B8BC-688D"; + fsType = "vfat"; + options = [ + "fmask=0077" + "dmask=0077" + ]; + }; + + swapDevices = [ ]; + + # Enables DHCP on each ethernet and wireless interface. In case of scripted networking + # (the default) this is the recommended approach. When using systemd-networkd it's + # still possible to use this option, but it's recommended to use it in conjunction + # with explicit per-interface declarations with `networking.interfaces..useDHCP`. + networking.useDHCP = lib.mkDefault true; + # networking.interfaces.enp0s31f6.useDHCP = lib.mkDefault true; + # networking.interfaces.wlp3s0.useDHCP = lib.mkDefault true; + + nixpkgs.hostPlatform = lib.mkDefault "x86_64-linux"; + hardware.cpu.intel.updateMicrocode = lib.mkDefault config.hardware.enableRedistributableFirmware; +} diff --git a/hosts/t480/neomutt.nix b/hosts/t480/neomutt.nix new file mode 100644 index 00000000..dbc58332 --- /dev/null +++ b/hosts/t480/neomutt.nix @@ -0,0 +1,7 @@ +{ + home-manager.users.opdavies.programs.neomutt = { + enable = true; + + vimKeys = true; + }; +} diff --git a/hosts/t480/newsboat/default.nix b/hosts/t480/newsboat/default.nix new file mode 100644 index 00000000..e99f78e9 --- /dev/null +++ b/hosts/t480/newsboat/default.nix @@ -0,0 +1,30 @@ +{ + home-manager.users.opdavies.programs.newsboat = { + enable = true; + + extraConfig = '' + bind-key j down + bind-key k up + + bind-key j next articlelist + bind-key k prev articlelist + bind-key J next-feed articlelist + bind-key K prev-feed articlelist + + bind-key g home + bind-key G end + + bind-key d pagedown + bind-key u pageup + + bind-key a toggle-article-read + bind-key n next-unread + bind-key N prev-unread + bind-key x pb-delete + + color info white black bold + ''; + + urls = import ./urls.nix; + }; +} diff --git a/hosts/t480/newsboat/urls.nix b/hosts/t480/newsboat/urls.nix new file mode 100644 index 00000000..83f2a2df --- /dev/null +++ b/hosts/t480/newsboat/urls.nix @@ -0,0 +1,298 @@ +[ + { url = "https://www.reddit.com/r/nginx/new/.rss"; } + { url = "https://www.reddit.com/r/devops/.rss"; } + { url = "https://medium.com/feed/@bdfinst"; } + { url = "https://blog.system76.com/rss"; } + { url = "https://medium.com/feed/@codemonkeymike"; } + { url = "https://www.reddit.com/r/devops/new/.rss"; } + { url = "https://www.reddit.com/r/sysadmin/.rss"; } + { + url = "https://www.carlpullein.com/blog?format=RSS"; + title = "Carl Pullein"; + tags = [ "Productivity" ]; + } + { url = "https://feeds.feedburner.com/Faildesk"; } + { url = "https://syndication.thedailywtf.com/TheDailyWtf"; } + { url = "https://www.sherdog.com/rss/videos2.xml"; } + { + url = "https://www.reddit.com/r/MMA/.rss"; + tags = [ "MMA" ]; + } + { + url = "https://mmaweekly.com/feed/rss"; + tags = [ "MMA" ]; + } + { + url = "https://www.sherdog.com/rss/news2.xml"; + tags = [ "MMA" ]; + } + { + url = "https://www.sherdog.com/rss/articles2.xml"; + tags = [ "MMA" ]; + } + { + url = "https://www.ufc.com/rss/news"; + tags = [ "MMA" ]; + } + { url = "https://www.theregister.co.uk/headlines.atom"; } + { + url = "https://www.rbs6nations.com/en/RssLatestNews.xml"; + tags = [ "Rugby" ]; + } + { + url = "https://feeds.feedburner.com/rugbydump"; + tags = [ "Rugby" ]; + } + { + url = "https://www.telegraph.co.uk/sport/rugbyunion/rss"; + tags = [ "Rugby" ]; + } + { url = "https://code.facebook.com/posts/rss"; } + { url = "https://nginx.com/feed/rss"; } + { + url = "https://www.lornajane.net/feed"; + tags = [ "Software" ]; + } + { + url = "https://nginx.org/index.rss"; + tags = [ "Software" ]; + } + { url = "https://www.engadget.com/rss.xml"; } + { url = "https://rss.slashdot.org/Slashdot/slashdotIt"; } + { url = "https://lwn.net/headlines/newrss"; } + { url = "https://rss.slashdot.org/Slashdot/slashdotLinux"; } + { + url = "https://blog.sebastian-daschner.com/feeds/rss"; + title = "Sebastian Daschner"; + } + { url = "https://www.reddit.com/r/linux/.rss"; } + { url = "https://githubengineering.com/atom.xml"; } + { url = "https://rss.slashdot.org/Slashdot/slashdotDevelopers"; } + { url = "https://www.alistapart.com/rss.xml"; } + { url = "https://www.christitus.com/index.xml"; } + { url = "https://www.freeagentcentral.com/feed.rss"; } + { url = "https://akrabat.com/feed Software"; } + { url = "https://jasonmccreary.me/feed.atom"; } + { url = "https://martinfowler.com/bliki/bliki.atom"; } + { url = "https://lornajane.net/feed"; } + { url = "https://christoph-rumpel.com/feed.xml"; } + { url = "https://gdstechnology.blog.gov.uk/feed/atom"; } + { url = "https://weierophinney.net/matthew/feeds/index.rss2"; } + { url = "https://stitcher.io/rss"; } + { url = "https://www.reddit.com/r/css.rss"; } + { url = "https://www.reddit.com/r/PHP/.rss"; } + { url = "https://whateverthing.com/atom.xml"; } + { url = "https://mnapoli.fr/atom.xml"; } + { url = "https://www.epicweb.dev/rss.xml?ck_subscriber_id=2498091571"; } + { url = "https://dev.to/feed"; } + { url = "https://localheinz.com/feed.xml"; } + { url = "https://www.ben-morris.com/feed"; } + { url = "https://www.jbrains.ca/rss"; } + { url = "https://blog.thecodewhisperer.com/rss"; } + { url = "https://odan.github.io/feed.xml"; } + { url = "https://feeds.feedburner.com/symfony/blog"; } + { url = "https://www.alwaysagileconsulting.com/feed"; } + { url = "https://blog.sensiolabs.com/feed"; } + { url = "https://pascalbaljetmedia.com/rss"; } + { url = "https://tighten.co/blog/feed.atom"; } + { url = "https://ryangjchandler.co.uk/feed"; } + { url = "https://jnsgr.uk/posts/index.xml"; } + { url = "https://timacdonald.me/feed.xml"; } + { url = "https://phppot.com/feed"; } + { url = "https://howtocodewell.libsyn.com/rss"; } + { url = "https://ctankersley.com/atom.xml"; } + { url = "https://blog.wyrihaximus.net/atom.xml"; } + { url = "https://dotfyle.com/this-week-in-neovim/rss.xml"; } + { url = "https://paul-m-jones.com/feed"; } + { url = "https://www.tomasvotruba.cz/rss.xml"; } + { url = "https://www.reddit.com/r/git/.rss"; } + { url = "https://www.daveismyname.com/feed"; } + { + url = "https://murze.be/feed/php"; + title = "freek.dev"; + tags = [ + "PHP" + "Laravel" + "Software" + ]; + } + { url = "https://nikic.github.io/rss.xml"; } + { + url = "https://drupal.org/planet/rss.xml"; + tags = [ "Drupal" ]; + } + { url = "https://www.bram.us/feed"; } + { url = "https://feeds.feedburner.com/GiantRobotsSmashingIntoOtherGiantRobots"; } + { url = "https://murze.be/feed/originals"; } + { url = "https://www.patkua.com/feed"; } + { url = "https://www.benjystanton.co.uk/feed.xml"; } + { + url = "https://drupal.org/security/rss.xml"; + tags = [ "Drupal" ]; + } + { + url = "https://uk.indeed.com/rss?q=symfony&l=np18"; + tags = [ "Jobs" ]; + } + { + url = "https://uk.indeed.com/rss?q=php&l=np18"; + tags = [ "Jobs" ]; + } + { + url = "https://jobs.drupal.org/all-jobs/feed"; + tags = [ "Jobs" ]; + } + { + url = "https://www.reed.co.uk/jobs/rss/np18?source=rss&keywords=drupal&salaryfrom=50000&sortby=DisplayDate"; + tags = [ "Jobs" ]; + } + { + url = "https://www.reed.co.uk/jobs/rss/np18?source=rss&keywords=php&salaryfrom=50000&sortby=DisplayDate"; + tags = [ "Jobs" ]; + } + { + url = "https://uk.indeed.com/rss?q=drupal&l=np18"; + tags = [ "Jobs" ]; + } + { + url = "https://www.reed.co.uk/jobs/rss/np18?source=rss&keywords=symfony&salaryfrom=50000&sortby=DisplayDate"; + tags = [ "Jobs" ]; + } + { url = "https://emilywebber.co.uk/feed"; } + { url = "https://introvertdear.com/feed"; } + { url = "https://designli.co/blog/feed"; } + { url = "https://www.oliverdavies.uk/rss/daily.xml"; } + { + url = "https://www.drupal.org/project/issues/rss/override_node_options"; + tags = [ "Drupal" ]; + } + { + url = "https://www.drupal.org/project/issues/rss/tailwindcss"; + tags = [ "Drupal" ]; + } + { + url = "https://nixos.org/blog/announcements-rss.xml"; + tags = [ "Linux" ]; + } + { + url = "https://laracasts.com/feed"; + tags = [ + "PHP" + "Laravel" + ]; + } + { + url = "https://feeds.feedburner.com/knpuniversity"; + title = "SymfonyCasts"; + tags = [ + "PHP" + "Symfony" + ]; + } + { + url = "https://nickjanetakis.com/atom.xml"; + title = "Nick Janetakis"; + } + { + url = "https://www.learnlinux.tv/feed"; + tags = [ "Linux" ]; + } + { + url = "https://tailwindcss.com/feeds/feed.xml"; + tags = [ + "Software" + "CSS" + ]; + } + { + url = "https://monospacementor.com/feed"; + tags = [ + "Linux" + "Software" + ]; + } + { + url = "https://frontendmasters.com/blog/feed"; + tags = [ "Software" ]; + title = "Frontend Masters Boost"; + } + { + url = "https://www.youtube.com/feeds/videos.xml?channel_id=UC2aHRY064THg_t7JZoGSYGg"; + title = "YouTube - elysse"; + tags = [ + "Software" + "YouTube" + ]; + } + { + url = "https://www.youtube.com/feeds/videos.xml?channel_id=UCSUA5RARrNt4-Ik3qtbETLQ"; + title = "YouTube - Jason Swett"; + tags = [ + "Software" + "YouTube" + ]; + } + { + url = "https://www.youtube.com/feeds/videos.xml?channel_id=UCorzANoC3fX9VVefJHM5wtA"; + title = "~YouTube - Nick Janetakis"; + tags = [ + "Software" + "YouTube" + ]; + } + { url = "https://devenv.sh/feed_rss_created.xml"; } + { url = "https://sive.rs/en.atom"; } + { url = "https://kressle.in/feed.xml"; } + { + url = "https://github.com/sculpin/sculpin/releases.atom"; + tags = [ + "PHP" + "Sculpin" + "Open Source" + ]; + } + { url = "https://www.theminimalists.com/feed"; } + { url = "https://opensourcepledge.com/rss.xml"; } + { + url = "https://feeds.bbci.co.uk/sport/rugby-union/teams/ng-dragons/rss.xml"; + tags = [ "Rugby" ]; + title = "BBC Sport - Dragons RFC"; + } + { + url = "https://openrss.org/www.twitch.tv/thealtf4stream/videos?filter=all&sort=time"; + tags = [ "Twitch" ]; + } + { + url = "https://openrss.org/www.twitch.tv/theprimeagen/videos?filter=all&sort=time"; + tags = [ "Twitch" ]; + } + { + url = "https://openrss.org/www.twitch.tv/teej_dv/videos?filter=all&sort=time"; + tags = [ "Twitch" ]; + } + { + url = "https://openrss.org/www.twitch.tv/monospacementor/videos?filter=all&sort=time"; + tags = [ "Twitch" ]; + } + { url = "https://www.reddit.com/r/librewolf/new/.rss"; } + { + url = "https://www.youtube.com/feeds/videos.xml?channel_id=UCSJKQnpmPcdkysduL0mNktg"; + title = "YouTube - teej_daily"; + tags = [ + "Software" + "YouTube" + ]; + } + { + url = "https://feeds.bbci.co.uk/sport/rugby-union/rss.xml"; + tags = [ "Rugby" ]; + title = "BBC Sport - Rugby Union"; + } + { url = "https://tinkerbetter.tube/feeds/videos.xml?videoChannelId=2"; } + { url = "https://video.fosshq.org/feeds/videos.xml?videoChannelId=2"; } + { + url = "https://www.garfieldtech.com/blog/feed"; + tags = [ "PHP" ]; + } + { url = "https://world.hey.com/dhh/feed.atom"; } +] diff --git a/hosts/t480/secrets.nix b/hosts/t480/secrets.nix new file mode 100644 index 00000000..e2032222 --- /dev/null +++ b/hosts/t480/secrets.nix @@ -0,0 +1,5 @@ +{ + age.secrets = { + cloudflare.file = ../../secrets/cloudflare.age; + }; +} diff --git a/hosts/t480/xserver.nix b/hosts/t480/xserver.nix new file mode 100644 index 00000000..ab1cfb91 --- /dev/null +++ b/hosts/t480/xserver.nix @@ -0,0 +1,12 @@ +{ + services.xserver = { + enable = true; + + displayManager.startx.enable = true; + + xkb = { + layout = "gb"; + variant = ""; + }; + }; +} diff --git a/justfile b/justfile new file mode 100644 index 00000000..660bf9dc --- /dev/null +++ b/justfile @@ -0,0 +1,35 @@ +alias b := build +alias s := switch +alias t := test +alias u := update + +_default: + just --list + +build *args: + @just _nixos build {{ args }} + +check: + nix flake check + +clean: + nh clean all + +collect-garbage: + nix-collect-garbage -d + sudo nix-collect-garbage -d + +format: + nix fmt flake.nix hosts modules + +switch *args: + @just _nixos switch {{ args }} + +test *args: + @just _nixos test {{ args }} + +update: + nix flake update --commit-lock-file + +_nixos command *args: + nh os {{ command }} . {{ args }} diff --git a/main.yaml b/main.yaml deleted file mode 100644 index d8884bd7..00000000 --- a/main.yaml +++ /dev/null @@ -1,23 +0,0 @@ ---- -- hosts: localhost - tasks: - - name: Set roles - ansible.builtin.set_fact: - roles: "{{ ansible_run_tags != ['all'] and ansible_run_tags or default_roles | difference(exclude_roles | default([])) }}" - tags: - - always - - - name: Display roles - ansible.builtin.debug: "var=roles" - tags: - - always - - - name: Run roles - ansible.builtin.include_role: - name: "{{ item }}" - apply: - tags: - - "{{ item }}" - with_items: "{{ roles }}" - tags: - - always diff --git a/modules/.keep b/modules/.keep new file mode 100644 index 00000000..e69de29b diff --git a/modules/avahi.nix b/modules/avahi.nix new file mode 100644 index 00000000..1d5b631e --- /dev/null +++ b/modules/avahi.nix @@ -0,0 +1,12 @@ +{ + flake.modules.nixos.pc.services.avahi = { + enable = true; + nssmdns4 = true; + openFirewall = true; + + publish = { + enable = true; + addresses = true; + }; + }; +} diff --git a/modules/bluetooth.nix b/modules/bluetooth.nix new file mode 100644 index 00000000..7fff70cc --- /dev/null +++ b/modules/bluetooth.nix @@ -0,0 +1,7 @@ +{ + flake.modules.nixos.desktop = { + hardware.bluetooth.enable = true; + + services.blueman.enable = true; + }; +} diff --git a/modules/bluetuith.nix b/modules/bluetuith.nix new file mode 100644 index 00000000..a3ff23db --- /dev/null +++ b/modules/bluetuith.nix @@ -0,0 +1,29 @@ +{ + flake.modules.homeManager.base = + { pkgs, ... }: + { + home.packages = [ + pkgs.bluetuith + ]; + + xdg.configFile."bluetuith/bluetuith.conf" = { + text = '' + { + adapter: "" + adapter-states: "" + connect-bdaddr: "" + gsm-apn: "" + gsm-number: "" + + keybindings: { + NavigateDown: j + NavigateUp: k + } + + receive-dir: "" + theme: {} + } + ''; + }; + }; +} diff --git a/modules/bookmarkthis.nix b/modules/bookmarkthis.nix new file mode 100644 index 00000000..96c7a4eb --- /dev/null +++ b/modules/bookmarkthis.nix @@ -0,0 +1,57 @@ +{ lib, ... }: + +{ + flake.modules.homeManager.gui = + { config, pkgs, ... }: + { + options.programs.bookmarkthis.snippetsFile = lib.mkOption { + default = "${config.xdg.dataHome}/snippets.txt"; + type = lib.types.str; + }; + + config = { + home = { + packages = [ + (pkgs.writeShellApplication { + name = "bookmarkthis"; + + text = '' + message() { + if command -v ${lib.getExe pkgs.libnotify} > /dev/null; then + ${lib.getExe pkgs.libnotify} "$1" "$2" + else + echo "$2" + fi + } + + main() { + bookmark="$(xclip -o)" + file="$SNIPPETS_FILE" + + if grep -q "^$bookmark$" "$file"; then + message "Oops." "Already bookmarked." >&2 + + exit 2 + fi + + echo "$bookmark" >> "$file" + + message "Bookmark added!" "$bookmark is now saved to the file." + } + + main + ''; + }) + ]; + + sessionVariables = { + SNIPPETS_FILE = config.programs.bookmarkthis.snippetsFile; + }; + }; + + programs.zsh.zsh-abbr.abbreviations = lib.optionalAttrs (config.programs.zsh.enable) { + "sn" = "${config.home.sessionVariables.EDITOR} $SNIPPETS_FILE"; + }; + }; + }; +} diff --git a/modules/browsers/chromium.nix b/modules/browsers/chromium.nix new file mode 100644 index 00000000..3a8e7c87 --- /dev/null +++ b/modules/browsers/chromium.nix @@ -0,0 +1,3 @@ +{ + flake.modules.homeManager.gui.programs.chromium.enable = true; +} diff --git a/modules/browsers/librewolf/enable.nix b/modules/browsers/librewolf/enable.nix new file mode 100644 index 00000000..3a77d1f0 --- /dev/null +++ b/modules/browsers/librewolf/enable.nix @@ -0,0 +1,3 @@ +{ + flake.modules.homeManager.gui.programs.librewolf.enable = true; +} diff --git a/modules/browsers/librewolf/extensions.nix b/modules/browsers/librewolf/extensions.nix new file mode 100644 index 00000000..43e0fb83 --- /dev/null +++ b/modules/browsers/librewolf/extensions.nix @@ -0,0 +1,17 @@ +{ + flake.modules.homeManager.gui = + { pkgs, ... }: + { + programs.librewolf.profiles.default.extensions.packages = + with pkgs.nur.repos.rycee.firefox-addons; [ + awesome-rss + bitwarden + darkreader + tree-style-tab + ublock-origin + videospeed + vimium + web-developer + ]; + }; +} diff --git a/modules/browsers/librewolf/languages.nix b/modules/browsers/librewolf/languages.nix new file mode 100644 index 00000000..b84500e2 --- /dev/null +++ b/modules/browsers/librewolf/languages.nix @@ -0,0 +1,5 @@ +{ + flake.modules.homeManager.gui.programs.librewolf.languagePacks = [ + "en-GB" + ]; +} diff --git a/modules/browsers/librewolf/policies.nix b/modules/browsers/librewolf/policies.nix new file mode 100644 index 00000000..4b613855 --- /dev/null +++ b/modules/browsers/librewolf/policies.nix @@ -0,0 +1,70 @@ +{ + flake.modules.homeManager.gui.programs.librewolf.policies = { + CaptivePortal = false; + DisableFirefoxAccounts = true; + DisableFirefoxStudies = true; + DisablePocket = true; + DisableTelemetry = true; + + EnableTrackingProtection = { + Cryptomining = true; + Fingerprinting = true; + Value = true; + }; + + ExtensionSettings = { + "jid1-ZAdIEUB7XOzOJw@jetpack" = { + install_url = "https://addons.mozilla.org/firefox/downloads/latest/duckduckgo-for-firefox/latest.xpi"; + installation_mode = "force_installed"; + }; + + "uBlock0@raymondhill.net" = { + install_url = "https://addons.mozilla.org/firefox/downloads/latest/ublock-origin/latest.xpi"; + installation_mode = "force_installed"; + }; + }; + + FirefoxHome = { + Highlights = false; + Pocket = false; + Search = true; + Snippets = false; + SponsoredPocket = false; + SponsoredTopSites = false; + TopSites = true; + }; + + FirefoxSuggest = { + ImproveSuggest = false; + SponsoredSuggestions = false; + WebSuggestions = false; + }; + + NoDefaultBookmarks = true; + OfferToSaveLogins = false; + OfferToSaveLoginsDefault = false; + PasswordManagerEnabled = false; + + Preferences = { + "browser.newtabpage.enabled" = false; + "cookiebanners.service.mode" = 2; # Block cookie banners + "cookiebanners.service.mode.privateBrowsing" = 2; # Block cookie banners in private browsing + "privacy.donottrackheader.enabled" = true; + "privacy.fingerprintingProtection" = true; + "privacy.resistFingerprinting" = true; + "privacy.trackingprotection.emailtracking.enabled" = true; + "privacy.trackingprotection.enabled" = true; + "privacy.trackingprotection.fingerprinting.enabled" = true; + "privacy.trackingprotection.socialtracking.enabled" = true; + }; + + HardwareAcceleration = true; + TranslateEnabled = true; + + UserMessaging = { + ExtensionRecommendations = false; + UrlbarInterventions = false; + SkipOnboarding = true; + }; + }; +} diff --git a/modules/browsers/librewolf/search-engines.nix b/modules/browsers/librewolf/search-engines.nix new file mode 100644 index 00000000..e943506b --- /dev/null +++ b/modules/browsers/librewolf/search-engines.nix @@ -0,0 +1,19 @@ +{ + flake.modules.homeManager.gui.programs.librewolf.profiles.default.search.engines = { + # TODO: Drupal.org users. + # TODO: Mastodon. + # TODO: GitHub. + # TODO: Forgejo. + drupal_projects = { + name = "Drupal.org projects"; + urls = [ { template = "https://www.drupal.org/project/{searchTerms}"; } ]; + definedAliases = [ "@dp" ]; + }; + + nixvim = { + name = "Nixvim options search"; + urls = [ { template = "https://nix-community.github.io/nixvim/search/?query={searchTerms}"; } ]; + definedAliases = [ "@nxv" ]; + }; + }; +} diff --git a/modules/browsers/librewolf/search.nix b/modules/browsers/librewolf/search.nix new file mode 100644 index 00000000..35dbbba8 --- /dev/null +++ b/modules/browsers/librewolf/search.nix @@ -0,0 +1,7 @@ +{ + flake.modules.homeManager.gui.programs.librewolf.profiles.default.search = { + default = "ddg"; + force = true; + privateDefault = "ddg"; + }; +} diff --git a/modules/browsers/librewolf/settings.nix b/modules/browsers/librewolf/settings.nix new file mode 100644 index 00000000..a7c5f5dd --- /dev/null +++ b/modules/browsers/librewolf/settings.nix @@ -0,0 +1,10 @@ +{ + flake.modules.homeManager.gui.programs.librewolf.profiles.default.settings = { + "browser.search.isUS" = false; + "browser.search.region" = "GB"; + "distribution.searchplugins.defaultLocale" = "en-GB"; + "general.useragent.locale" = "en-GB"; + "intl.accept_languages" = "en-GB, en"; + "intl.regional_prefs.use_os_locales" = true; + }; +} diff --git a/modules/browsers/qutebrowser/enable.nix b/modules/browsers/qutebrowser/enable.nix new file mode 100644 index 00000000..a36898ab --- /dev/null +++ b/modules/browsers/qutebrowser/enable.nix @@ -0,0 +1,3 @@ +{ + flake.modules.homeManager.gui.programs.qutebrowser.enable = true; +} diff --git a/modules/browsers/qutebrowser/key-bindings.nix b/modules/browsers/qutebrowser/key-bindings.nix new file mode 100644 index 00000000..f825b833 --- /dev/null +++ b/modules/browsers/qutebrowser/key-bindings.nix @@ -0,0 +1,14 @@ +{ lib, ... }: + +{ + flake.modules.homeManager.gui.programs.qutebrowser.keyBindings.normal = { + "" = "config-cycle colors.webpage.darkmode.enabled true false"; + + "xb" = "config-cycle statusbar.show always never"; + "xt" = "config-cycle tabs.show always never"; + "xx" = lib.mkMerge [ + "config-cycle statusbar.show always never" + "config-cycle tabs.show always never" + ]; + }; +} diff --git a/modules/browsers/qutebrowser/package.nix b/modules/browsers/qutebrowser/package.nix new file mode 100644 index 00000000..c44f8487 --- /dev/null +++ b/modules/browsers/qutebrowser/package.nix @@ -0,0 +1,7 @@ +{ + flake.modules.homeManager.gui = + { pkgs, ... }: + { + programs.qutebrowser.package = pkgs.stable.qutebrowser; + }; +} diff --git a/modules/browsers/qutebrowser/search-engines.nix b/modules/browsers/qutebrowser/search-engines.nix new file mode 100644 index 00000000..5b15d91b --- /dev/null +++ b/modules/browsers/qutebrowser/search-engines.nix @@ -0,0 +1,10 @@ +{ + flake.modules.homeManager.gui.programs.qutebrowser.searchEngines = { + dp = "https://www.drupal.org/project/{}"; + du = "https://www.drupal.org/u/{}"; + gh = "https://github.com/search?q={}"; + mn = "https://mynixos.com/search?q={}"; + nx = "https://search.nixos.org/packages?query={}"; + yt = "https://www.youtube.com/results?search_query={}"; + }; +} diff --git a/modules/browsers/qutebrowser/settings.nix b/modules/browsers/qutebrowser/settings.nix new file mode 100644 index 00000000..f14cf732 --- /dev/null +++ b/modules/browsers/qutebrowser/settings.nix @@ -0,0 +1,5 @@ +{ + flake.modules.homeManager.gui.programs.qutebrowser.settings = { + colors.webpage.darkmode.enabled = true; + }; +} diff --git a/modules/calculator.nix b/modules/calculator.nix new file mode 100644 index 00000000..41ebe819 --- /dev/null +++ b/modules/calculator.nix @@ -0,0 +1,7 @@ +{ + flake.modules.nixos.pc = + { pkgs, ... }: + { + environment.systemPackages = [ pkgs.bc ]; + }; +} diff --git a/modules/dconf.nix b/modules/dconf.nix new file mode 100644 index 00000000..2c56e04c --- /dev/null +++ b/modules/dconf.nix @@ -0,0 +1,3 @@ +{ + flake.modules.nixos.pc.programs.dconf.enable = true; +} diff --git a/modules/desktop.nix b/modules/desktop.nix new file mode 100644 index 00000000..eaad4d8e --- /dev/null +++ b/modules/desktop.nix @@ -0,0 +1,7 @@ +{ config, ... }: + +{ + flake.modules.nixos.desktop.imports = with config.flake.modules.nixos; [ + pc + ]; +} diff --git a/modules/dev-commit.nix b/modules/dev-commit.nix new file mode 100644 index 00000000..352a01ad --- /dev/null +++ b/modules/dev-commit.nix @@ -0,0 +1,83 @@ +{ lib, ... }: + +{ + flake.modules.homeManager.base = + { config, pkgs, ... }: + { + options.programs.dev-commit = { + enable = lib.mkEnableOption "Enable dev-commit"; + + repoPaths = lib.mkOption { + default = [ ]; + description = "A list of repository paths that should have automated commits"; + type = lib.types.listOf lib.types.path; + }; + + schedule = lib.mkOption { + type = lib.types.submodule { + options = { + enable = lib.mkEnableOption "Enable automated dev commits with systemd"; + + time = lib.mkOption { + description = '' + Time expression for when to run the dev-commit job. + + This uses systemd's `OnCalendar` syntax. + + Examples: + - "hourly" (once every hour) + - "daily" (once per day at midnight) + - "Mon *-*-01 12:00:00" (every Monday at 12:00 PM) + + See `man systemd.time` for full syntax reference. + ''; + default = "hourly"; + type = lib.types.str; + }; + }; + }; + + default = { + enable = false; + time = "hourly"; + }; + }; + }; + + config = + let + cfg = config.programs.dev-commit; + repoPaths = lib.concatStringsSep ":" cfg.repoPaths; + in + { + home = lib.mkIf cfg.enable { + packages = [ pkgs.dev-commit ]; + + sessionVariables.DEV_COMMIT_PATHS = repoPaths; + }; + + systemd.user = lib.mkIf cfg.schedule.enable { + services.dev-commit = { + Service = { + Environment = [ "DEV_COMMIT_PATHS=${repoPaths}" ]; + ExecStart = "${lib.getExe pkgs.dev-commit}"; + Type = "oneshot"; + }; + + Unit.Description = "dev-commit"; + }; + + timers.dev-commit = { + Install.WantedBy = [ "timers.target" ]; + + Timer = { + OnCalendar = cfg.schedule.time; + Unit = "dev-commit.service"; + }; + + Unit.Description = "Runs automated development commits in select project repositories."; + }; + }; + }; + }; +} diff --git a/modules/direnv/enable.nix b/modules/direnv/enable.nix new file mode 100644 index 00000000..b758eec4 --- /dev/null +++ b/modules/direnv/enable.nix @@ -0,0 +1,3 @@ +{ + flake.modules.homeManager.base.programs.direnv.enable = true; +} diff --git a/modules/direnv/nix-direnv.nix b/modules/direnv/nix-direnv.nix new file mode 100644 index 00000000..f3848d08 --- /dev/null +++ b/modules/direnv/nix-direnv.nix @@ -0,0 +1,3 @@ +{ + flake.modules.homeManager.base.programs.direnv.nix-direnv.enable = true; +} diff --git a/modules/direnv/silent.nix b/modules/direnv/silent.nix new file mode 100644 index 00000000..302a19b1 --- /dev/null +++ b/modules/direnv/silent.nix @@ -0,0 +1,3 @@ +{ + flake.modules.homeManager.base.programs.direnv.silent = true; +} diff --git a/modules/direnv/zsh.nix b/modules/direnv/zsh.nix new file mode 100644 index 00000000..ca306692 --- /dev/null +++ b/modules/direnv/zsh.nix @@ -0,0 +1,3 @@ +{ + flake.modules.homeManager.base.programs.direnv.enableZshIntegration = true; +} diff --git a/modules/displayselect/default.nix b/modules/displayselect/default.nix new file mode 100644 index 00000000..b8b6ad92 --- /dev/null +++ b/modules/displayselect/default.nix @@ -0,0 +1,35 @@ +{ inputs, ... }: + +{ + flake.modules.homeManager.gui = + { pkgs, ... }: + { + home.packages = [ + (pkgs.stdenv.mkDerivation { + pname = "displayselect"; + version = "unstable"; + + src = inputs.voidrice; + + dontUnpack = true; + + buildInputs = with pkgs; [ + bash + xorg.xrandr + ]; + + prePatch = '' + cp "$src/.local/bin/displayselect" displayselect + ''; + + patches = [ ./scaling.patch ]; + + installPhase = '' + mkdir -p $out/bin + cp displayselect $out/bin + chmod +x $out/bin/displayselect + ''; + }) + ]; + }; +} diff --git a/modules/displayselect/scaling.patch b/modules/displayselect/scaling.patch new file mode 100644 index 00000000..248b7bee --- /dev/null +++ b/modules/displayselect/scaling.patch @@ -0,0 +1,26 @@ +diff --git a/.local/bin/displayselect b/.local/bin/displayselect +index 51dd468..c132b7a 100755 +--- a/displayselect ++++ b/displayselect +@@ -15,20 +15,13 @@ twoscreen() { # If multi-monitor is selected and there are two screens. + + res_external=$(xrandr --query | sed -n "/^$external/,/\+/p" | \ + tail -n 1 | awk '{print $1}') +- res_internal=$(xrandr --query | sed -n "/^$internal/,/\+/p" | \ +- tail -n 1 | awk '{print $1}') + + res_ext_x=$(echo "$res_external" | sed 's/x.*//') + res_ext_y=$(echo "$res_external" | sed 's/.*x//') +- res_int_x=$(echo "$res_internal" | sed 's/x.*//') +- res_int_y=$(echo "$res_internal" | sed 's/.*x//') +- +- scale_x=$(echo "$res_ext_x / $res_int_x" | bc -l) +- scale_y=$(echo "$res_ext_y / $res_int_y" | bc -l) + + xrandr --output "$external" --auto --scale 1.0x1.0 \ + --output "$internal" --auto --same-as "$external" \ +- --scale "$scale_x"x"$scale_y" ++ --scale-from "${res_ext_x}x${res_ext_y}" + else + + primary=$(echo "$screens" | dmenu -i -p "Select primary display:") diff --git a/modules/dmenu-sys.nix b/modules/dmenu-sys.nix new file mode 100644 index 00000000..2ccab6e7 --- /dev/null +++ b/modules/dmenu-sys.nix @@ -0,0 +1,26 @@ +{ inputs, ... }: + +{ + flake.modules.homeManager.gui = + { pkgs, ... }: + { + home.packages = [ + (pkgs.stdenv.mkDerivation rec { + pname = "dmenu_sys"; + version = "unstable"; + + src = inputs.bop-scripts; + + dontUnpack = true; + + buildInputs = with pkgs; [ dmenu ]; + + installPhase = '' + mkdir -p $out/bin + cp $src/${pname} $out/bin + chmod +x $out/bin/${pname} + ''; + }) + ]; + }; +} diff --git a/modules/dmenu-timer.nix b/modules/dmenu-timer.nix new file mode 100644 index 00000000..7a829d27 --- /dev/null +++ b/modules/dmenu-timer.nix @@ -0,0 +1,26 @@ +{ inputs, ... }: + +{ + flake.modules.homeManager.gui = + { pkgs, ... }: + { + home.packages = [ + (pkgs.stdenv.mkDerivation rec { + pname = "dmenu_timer"; + version = "unstable"; + + src = inputs.bop-scripts; + + dontUnpack = true; + + buildInputs = with pkgs; [ dmenu ]; + + installPhase = '' + mkdir -p $out/bin + cp $src/${pname} $out/bin + chmod +x $out/bin/${pname} + ''; + }) + ]; + }; +} diff --git a/modules/docker.nix b/modules/docker.nix new file mode 100644 index 00000000..e909e693 --- /dev/null +++ b/modules/docker.nix @@ -0,0 +1,24 @@ +{ config, lib, ... }: + +{ + flake.modules.nixos.pc = args: { + options.docker.enable = lib.mkEnableOption "Enable Docker"; + + config = lib.mkIf args.config.docker.enable { + virtualisation = { + oci-containers.backend = "docker"; + + docker = { + enable = true; + + autoPrune = { + enable = true; + dates = "weekly"; + }; + }; + }; + + users.users.${config.flake.meta.owner.username}.extraGroups = [ "docker" ]; + }; + }; +} diff --git a/modules/dwm/config.nix b/modules/dwm/config.nix new file mode 100644 index 00000000..99fd7d0e --- /dev/null +++ b/modules/dwm/config.nix @@ -0,0 +1,11 @@ +{ + flake.modules.homeManager.gui = + { config, ... }: + { + home = { + file."${config.home.sessionVariables.XINITRC}".source = ./xinitrc; + + sessionVariables.XINITRC = "${config.xdg.configHome}/X11/xinitrc"; + }; + }; +} diff --git a/modules/dwm/dmenu-center-noop.patch b/modules/dwm/dmenu-center-noop.patch new file mode 100644 index 00000000..9773ce73 --- /dev/null +++ b/modules/dwm/dmenu-center-noop.patch @@ -0,0 +1,14 @@ +diff --git a/dmenu.c b/dmenu.c + +index fd49549..e9e2648 100644 +--- a/dmenu.c ++++ b/dmenu.c +@@ -757,6 +757,8 @@ main(int argc, char *argv[]) + colors[SchemeSel][ColFg] = argv[++i]; + else if (!strcmp(argv[i], "-w")) /* embedding window id */ + embed = argv[++i]; ++ else if (!strcmp(argv[i], "-c")) ++ continue; + else + usage(); + diff --git a/modules/dwm/packages.nix b/modules/dwm/packages.nix new file mode 100644 index 00000000..0bc07182 --- /dev/null +++ b/modules/dwm/packages.nix @@ -0,0 +1,21 @@ +{ + flake.modules.nixos.pc = + { pkgs, ... }: + { + environment.systemPackages = with pkgs; [ + (dmenu.override { + patches = [ + ./dmenu-center-noop.patch + ]; + }) + + dmenu-bluetooth + dunst + networkmanager_dmenu + poweralertd + slock + xdotool + xwallpaper + ]; + }; +} diff --git a/modules/dwm/xinitrc b/modules/dwm/xinitrc new file mode 100644 index 00000000..ba020660 --- /dev/null +++ b/modules/dwm/xinitrc @@ -0,0 +1,13 @@ +systemctl --user import-environment DISPLAY +poweralertd -s & +set-background & +dwmblocks & +gammastep & + +sxhkd & + +export GPG_TTY=$(tty) +export SSH_AUTH_SOCK=$(gpgconf --list-dirs agent-ssh-socket) +gpg-connect-agent updatestartuptty /bye + +exec dwm diff --git a/modules/firmware.nix b/modules/firmware.nix new file mode 100644 index 00000000..cad66d99 --- /dev/null +++ b/modules/firmware.nix @@ -0,0 +1,3 @@ +{ + flake.modules.nixos.desktop.services.fwupd.enable = true; +} diff --git a/modules/flameshot/enable.nix b/modules/flameshot/enable.nix new file mode 100644 index 00000000..721b375e --- /dev/null +++ b/modules/flameshot/enable.nix @@ -0,0 +1,3 @@ +{ + flake.modules.homeManager.gui.services.flameshot.enable = true; +} diff --git a/modules/flameshot/settings.nix b/modules/flameshot/settings.nix new file mode 100644 index 00000000..86629d57 --- /dev/null +++ b/modules/flameshot/settings.nix @@ -0,0 +1,13 @@ +{ + flake.modules.homeManager.gui = + { config, ... }: + { + services.flameshot.settings.General = { + disabledTrayIcon = false; + saveAfterCopy = true; + savePath = "${config.xdg.userDirs.pictures}/Screenshots"; + showHelp = false; + uiColor = "#60a5fa"; + }; + }; +} diff --git a/modules/fonts.nix b/modules/fonts.nix new file mode 100644 index 00000000..728ba62f --- /dev/null +++ b/modules/fonts.nix @@ -0,0 +1,16 @@ +{ + flake.modules.nixos.desktop = + { pkgs, ... }: + { + fonts = { + fontconfig.enable = true; + + packages = with pkgs; [ + nerd-fonts.jetbrains-mono + nerd-fonts.meslo-lg + terminus_font + terminus_font_ttf + ]; + }; + }; +} diff --git a/modules/fzf/enable.nix b/modules/fzf/enable.nix new file mode 100644 index 00000000..512d9727 --- /dev/null +++ b/modules/fzf/enable.nix @@ -0,0 +1,6 @@ +{ + flake.modules.homeManager.base.programs.fzf = { + enable = true; + enableZshIntegration = true; + }; +} diff --git a/modules/fzf/session-variables.nix b/modules/fzf/session-variables.nix new file mode 100644 index 00000000..cb3e2433 --- /dev/null +++ b/modules/fzf/session-variables.nix @@ -0,0 +1,5 @@ +{ + flake.modules.homeManager.base.home.sessionVariables = { + FZF_DEFAULT_OPTS = "--reverse"; + }; +} diff --git a/modules/games/steam.nix b/modules/games/steam.nix new file mode 100644 index 00000000..faafa311 --- /dev/null +++ b/modules/games/steam.nix @@ -0,0 +1,8 @@ +{ + nixpkgs.allowedUnfreePackages = [ + "steam" + "steam-unwrapped" + ]; + + flake.modules.nixos.desktop.programs.steam.enable = true; +} diff --git a/modules/games/zeroad.nix b/modules/games/zeroad.nix new file mode 100644 index 00000000..c7d5cf6e --- /dev/null +++ b/modules/games/zeroad.nix @@ -0,0 +1,7 @@ +{ + flake.modules.homeManager.gui = + { pkgs, ... }: + { + home.packages = with pkgs; [ zeroad ]; + }; +} diff --git a/modules/gammastep/enable.nix b/modules/gammastep/enable.nix new file mode 100644 index 00000000..c8b70f14 --- /dev/null +++ b/modules/gammastep/enable.nix @@ -0,0 +1,3 @@ +{ + flake.modules.homManager.gui.services.gammastep.enable = true; +} diff --git a/modules/gammastep/provider.nix b/modules/gammastep/provider.nix new file mode 100644 index 00000000..e31c1826 --- /dev/null +++ b/modules/gammastep/provider.nix @@ -0,0 +1,3 @@ +{ + flake.modules.homManager.gui.services.gammastep.provider = "geoclue2"; +} diff --git a/modules/git-repo-updater.nix b/modules/git-repo-updater.nix new file mode 100644 index 00000000..e4857610 --- /dev/null +++ b/modules/git-repo-updater.nix @@ -0,0 +1,11 @@ +{ inputs, ... }: + +{ + flake.modules.nixos.pc = + { system, ... }: + { + environment.systemPackages = [ + inputs.git-repo-updater.packages.${system}.default + ]; + }; +} diff --git a/modules/git/aliases.nix b/modules/git/aliases.nix new file mode 100644 index 00000000..ad52e1b7 --- /dev/null +++ b/modules/git/aliases.nix @@ -0,0 +1,50 @@ +{ + flake.modules.homeManager.base.programs.git.aliases = { + aa = "add --all"; + assume = "update-index --assume-unchanged"; + assumed = "!git ls-files -v | grep '^[hsmrck?]' | cut -c 3-"; + b = "branch"; + blame = "blame -w -C -C -C"; + browse = "!gh repo view --web"; + ca = "commit --amend --verbose"; + car = "commit --amend --no-edit"; + cl = "!hub clone"; + co = "checkout"; + compare = "!hub compare"; + current-branch = "rev-parse --abbrev-ref HEAD"; + dc = "diff --color --word-diff --cached"; + df = "diff --color --word-diff"; + dup = "!git checkout develop && git fetch origin && echo && git sl develop..origin/develop && echo && git pull --quiet && git checkout -"; + fixup = "commit --fixup"; + issues = "!gh issue list --web"; + mup = "!git master-to-main-wrapper checkout %BRANCH% && git fetch origin && echo && git sl %BRANCH%..origin/%BRANCH% && echo && git pull --quiet && git checkout -"; + no-ff = "merge --no-ff"; + pl = "pull"; + prune = "remote prune origin"; + ps = "push"; + pulls = "!gh pr list --web"; + rbc = "rebase --continue"; + rdup = "!git dup && git rebase develop"; + remotes = "remote -v"; + repush = "!git pull --rebase && git push"; + ri = "rebase --interactive"; + rid = "!git rebase -i $(git merge-base develop HEAD)"; + rim = "!git rebase -i $(git master-to-main-wrapper merge-base %BRANCH% HEAD)"; + rip = "!git rebase -i $(git merge-base production HEAD)"; + ris = "!git rebase -i $(git merge-base staging HEAD)"; + riu = "!git rebase -i $(git rev-parse --abbrev-ref --symbolic-full-name @{u})"; + rmup = "!git mup && git master-to-main-wrapper rebase %BRANCH%"; + sl = "log --oneline --decorate -20"; + sla = "log --oneline --decorate --graph --all -20"; + slap = "log --oneline --decorate --graph --all"; + slp = "log --oneline --decorate"; + stash = "stash --included-untracked"; + unassume = "update-index --no-assume-unchanged"; + uncommit = "reset --soft HEAD^"; + unstage = "reset"; + update = "!git fetch --all --jobs=4 --prune --progress && git rebase --autostash --stat"; + upstream = "rev-parse --abbrev-ref --symbolic-full-name @{u}"; + ureset = "!git reset --hard $(git upstream)"; + worktrees = "worktree list"; + }; +} diff --git a/modules/git/default-commit-message.nix b/modules/git/default-commit-message.nix new file mode 100644 index 00000000..dfd1fe90 --- /dev/null +++ b/modules/git/default-commit-message.nix @@ -0,0 +1,25 @@ +{ + flake.modules.homeManager.base = + { config, ... }: + { + home.file."${config.xdg.configHome}/git/message".text = '' + + + # Description + # + # - Why is this change necessary? + # - How does it address the issue? + # - What side effects does this change have? + # + # For breaking changes, uncomment the following line and describe the change: + # + # BREAKING CHANGE: + # + # + # Add any issue IDs or commit SHAs that this commit references: + # + # Refs: + + ''; + }; +} diff --git a/modules/git/defaults.nix b/modules/git/defaults.nix new file mode 100644 index 00000000..02b8978c --- /dev/null +++ b/modules/git/defaults.nix @@ -0,0 +1,54 @@ +{ + flake.modules.homeManager.base = + { config, ... }: + { + programs.git.extraConfig = { + branch = { + autosetupmerge = true; + autosetuprebase = "always"; + sort = "-committerdate"; + }; + + checkout.defaultRemote = "origin"; + color.ui = true; + column.ui = "auto"; + commit.template = "${config.xdg.configHome}/git/message"; + + core = { + editor = "nvim"; + excludesFile = "${config.xdg.configHome}/git/ignore"; + }; + + diff.tool = "vimdiff"; + fetch.prune = true; + gpg.format = "ssh"; + grep.lineNumber = true; + help.autocorrect = "1"; + init.defaultBranch = "main"; + + maintenance = { + auto = false; + strategy = "incremental"; + }; + + merge.ff = "only"; + + push = { + autoSetupRemote = true; + default = "upstream"; + }; + + pull = { + ff = "only"; + rebase = true; + }; + + rebase = { + autosquash = true; + autostash = true; + }; + + user.signingkey = "~/.ssh/id_rsa.pub"; + }; + }; +} diff --git a/modules/git/enable.nix b/modules/git/enable.nix new file mode 100644 index 00000000..da8cc9f0 --- /dev/null +++ b/modules/git/enable.nix @@ -0,0 +1,3 @@ +{ + flake.modules.homeManager.base.programs.git.enable = true; +} diff --git a/modules/git/extra-packages.nix b/modules/git/extra-packages.nix new file mode 100644 index 00000000..6c610608 --- /dev/null +++ b/modules/git/extra-packages.nix @@ -0,0 +1,13 @@ +{ + flake.modules.homeManager.base = + { pkgs, ... }: + { + home.packages = with pkgs; [ + git-exclude + git-extras + git-graph + git-trim + stable.git-instafix + ]; + }; +} diff --git a/modules/git/ignores.nix b/modules/git/ignores.nix new file mode 100644 index 00000000..00b04ffc --- /dev/null +++ b/modules/git/ignores.nix @@ -0,0 +1,11 @@ +{ + flake.modules.homeManager.base.programs.git.ignores = [ + "/.ddev/providers/" + "/.direnv/" + "/.ignored/" + "/.issue-id" + "/.phpactor.json" + "/notes" + "/todo" + ]; +} diff --git a/modules/git/user.nix b/modules/git/user.nix new file mode 100644 index 00000000..bc3f214f --- /dev/null +++ b/modules/git/user.nix @@ -0,0 +1,8 @@ +{ config, ... }: + +{ + flake.modules.homeManager.base.programs.git = { + userName = config.flake.meta.owner.name; + userEmail = config.flake.meta.owner.email; + }; +} diff --git a/modules/git/variables.nix b/modules/git/variables.nix new file mode 100644 index 00000000..e47ccb5f --- /dev/null +++ b/modules/git/variables.nix @@ -0,0 +1,5 @@ +{ + flake.modules.homeManager.base.home.sessionVariables = { + GIT_INSTAFIX_UPSTREAM = "origin/main"; + }; +} diff --git a/modules/gnupg.nix b/modules/gnupg.nix new file mode 100644 index 00000000..da3edb80 --- /dev/null +++ b/modules/gnupg.nix @@ -0,0 +1,23 @@ +{ + flake.modules = { + nixos.pc = + { pkgs, ... }: + { + security.pam.services.login.gnupg.enable = true; + + programs.gnupg.agent = { + enable = true; + enableSSHSupport = true; + + pinentryPackage = pkgs.pinentry-qt; + }; + }; + + homeManager.base.home.file.".gnupg/gpg-agent.conf".text = '' + allow-preset-passphrase + default-cache-ttl 600 + max-cache-ttl 7200 + enable-ssh-support + ''; + }; +} diff --git a/modules/gtk/animations.nix b/modules/gtk/animations.nix new file mode 100644 index 00000000..45d5edac --- /dev/null +++ b/modules/gtk/animations.nix @@ -0,0 +1,6 @@ +{ + flake.modules.homeManager.gui.gtk = { + gtk3.extraConfig.gtk-enable-animations = false; + gtk4.extraConfig.gtk-enable-animations = false; + }; +} diff --git a/modules/gtk/enable.nix b/modules/gtk/enable.nix new file mode 100644 index 00000000..ceed16d3 --- /dev/null +++ b/modules/gtk/enable.nix @@ -0,0 +1,3 @@ +{ + flake.modules.homeManager.gui.gtk.enable = true; +} diff --git a/modules/gtk/icon-theme.nix b/modules/gtk/icon-theme.nix new file mode 100644 index 00000000..aed95ddf --- /dev/null +++ b/modules/gtk/icon-theme.nix @@ -0,0 +1,10 @@ +{ + flake.modules.homeManager.gui = + { pkgs, ... }: + { + gtk.iconTheme = { + name = "Arc"; + package = pkgs.arc-icon-theme; + }; + }; +} diff --git a/modules/gtk/theme.nix b/modules/gtk/theme.nix new file mode 100644 index 00000000..44e42980 --- /dev/null +++ b/modules/gtk/theme.nix @@ -0,0 +1,10 @@ +{ + flake.modules.homeManager.gui = + { pkgs, ... }: + { + gtk.theme = { + name = "Arc-Dark"; + package = pkgs.arc-theme; + }; + }; +} diff --git a/modules/handbrake.nix b/modules/handbrake.nix new file mode 100644 index 00000000..8a8532a9 --- /dev/null +++ b/modules/handbrake.nix @@ -0,0 +1,7 @@ +{ + flake.modules.homeManager.gui = + { pkgs, ... }: + { + home.packages = [ pkgs.handbrake ]; + }; +} diff --git a/modules/home-manager/base.nix b/modules/home-manager/base.nix new file mode 100644 index 00000000..bbd936b3 --- /dev/null +++ b/modules/home-manager/base.nix @@ -0,0 +1,14 @@ +{ config, ... }: + +{ + flake.modules.homeManager.base = args: { + home = { + homeDirectory = "/home/${config.flake.meta.owner.username}"; + username = config.flake.meta.owner.username; + }; + + programs.home-manager.enable = true; + + systemd.user.startServices = "sd-switch"; + }; +} diff --git a/modules/home-manager/nixos.nix b/modules/home-manager/nixos.nix new file mode 100644 index 00000000..f3a55dc4 --- /dev/null +++ b/modules/home-manager/nixos.nix @@ -0,0 +1,38 @@ +{ + config, + inputs, + lib, + ... +}: + +{ + flake.modules.nixos = { + base = { + imports = [ inputs.home-manager.nixosModules.home-manager ]; + + home-manager = { + extraSpecialArgs.hasGlobalPkgs = true; + useGlobalPkgs = true; + + # https://github.com/nix-community/home-manager/issues/6770 + # useUserPackages = true; + + users.${config.flake.meta.owner.username}.imports = [ + ( + { osConfig, ... }: + + { + home.stateVersion = lib.mkForce osConfig.system.stateVersion; + } + ) + + config.flake.modules.homeManager.base + ]; + }; + }; + + desktop.home-manager.users.${config.flake.meta.owner.username}.imports = [ + config.flake.modules.homeManager.gui + ]; + }; +} diff --git a/modules/hosts/nixedo/gitea-actions-runner.nix b/modules/hosts/nixedo/gitea-actions-runner.nix new file mode 100644 index 00000000..1c794ee4 --- /dev/null +++ b/modules/hosts/nixedo/gitea-actions-runner.nix @@ -0,0 +1,31 @@ +{ inputs, ... }: + +{ + flake.modules.nixos."nixosConfigurations/nixedo" = + { config, pkgs, ... }: + { + services.gitea-actions-runner.instances.default = { + enable = true; + + hostPackages = with pkgs; [ + bash + coreutils + curl + gawk + gitMinimal + gnused + nix + nodejs + wget + ]; + + labels = [ "nixos:host" ]; + + name = config.networking.hostName; + tokenFile = config.age.secrets.forgejo-runner-token.path; + url = config.services.forgejo.settings.server.ROOT_URL; + }; + + age.secrets.forgejo-runner-token.file = "${inputs.self}/secrets/forgejo-runner-token.age"; + }; +} diff --git a/modules/hosts/nixedo/imports.nix b/modules/hosts/nixedo/imports.nix new file mode 100644 index 00000000..e22a75c4 --- /dev/null +++ b/modules/hosts/nixedo/imports.nix @@ -0,0 +1,7 @@ +{ config, ... }: + +{ + flake.modules.nixos."nixosConfigurations/nixedo".imports = with config.flake.modules.nixos; [ + pc + ]; +} diff --git a/modules/hosts/t480/dev-commit.nix b/modules/hosts/t480/dev-commit.nix new file mode 100644 index 00000000..cb6114a4 --- /dev/null +++ b/modules/hosts/t480/dev-commit.nix @@ -0,0 +1,23 @@ +{ config, ... }: + +{ + flake.modules.nixos."nixosConfigurations/t480".home-manager.users.${config.flake.meta.owner.username} = + hmArgs: { + programs.dev-commit.enable = true; + + programs.dev-commit.schedule.enable = true; + programs.dev-commit.schedule.time = "daily"; + + programs.dev-commit.repoPaths = + let + repos = "${hmArgs.config.xdg.userDirs.extraConfig.XDG_REPOS_DIR}/forgejo/opdavies"; + in + map (name: "${repos}/${name}") [ + "email-filters" + "git-repo-updater" + "nix-config" + "oliverdavies.uk" + "opentofu-dns" + ]; + }; +} diff --git a/modules/hosts/t480/dwm/dwm.nix b/modules/hosts/t480/dwm/dwm.nix new file mode 100644 index 00000000..b6f219f6 --- /dev/null +++ b/modules/hosts/t480/dwm/dwm.nix @@ -0,0 +1,3 @@ +{ + flake.modules.nixos.pc.services.xserver.windowManager.dwm.enable = true; +} diff --git a/modules/hosts/t480/dwm/dwmblocks/audio.nix b/modules/hosts/t480/dwm/dwmblocks/audio.nix new file mode 100644 index 00000000..ddefba39 --- /dev/null +++ b/modules/hosts/t480/dwm/dwmblocks/audio.nix @@ -0,0 +1,21 @@ +{ + flake.modules.homeManager.gui = + { pkgs, ... }: + { + home.packages = [ + (pkgs.writeShellApplication { + name = "status-audio"; + + runtimeInputs = with pkgs; [ pulseaudio ]; + + text = '' + device="$(pactl list sinks | grep -A2 "$(pactl get-default-sink)" | grep "Description:" | awk '{print $2}')" + + test "$device" == "Dummy" && exit 0 + + echo "$device"; + ''; + }) + ]; + }; +} diff --git a/modules/hosts/t480/dwm/dwmblocks/battery.nix b/modules/hosts/t480/dwm/dwmblocks/battery.nix new file mode 100644 index 00000000..5abd5630 --- /dev/null +++ b/modules/hosts/t480/dwm/dwmblocks/battery.nix @@ -0,0 +1,23 @@ +{ + flake.modules.homeManager.gui = + { pkgs, ... }: + { + home.packages = [ + (pkgs.writeShellApplication { + name = "status-battery"; + + runtimeInputs = with pkgs; [ gawk ]; + + text = '' + percentage=$(battery | grep "percentage:" | awk '{print $2}') + + test "$percentage" == "100%" && exit 0 + + state=$(battery | grep "state:" | awk '{print $2}') + + echo "$percentage ($state)"; + ''; + }) + ]; + }; +} diff --git a/modules/hosts/t480/dwm/dwmblocks/cpu.nix b/modules/hosts/t480/dwm/dwmblocks/cpu.nix new file mode 100644 index 00000000..9e4f03fa --- /dev/null +++ b/modules/hosts/t480/dwm/dwmblocks/cpu.nix @@ -0,0 +1,17 @@ +{ + flake.modules.homeManager.gui = + { pkgs, ... }: + { + home.packages = [ + (pkgs.writeShellApplication { + name = "status-cpu"; + + runtimeInputs = with pkgs; [ sysstat ]; + + text = '' + mpstat | grep -A 5 "%idle" | tail -n 1 | awk -F " " '{printf "%s%% CPU", 100 - $ 12}' + ''; + }) + ]; + }; +} diff --git a/modules/hosts/t480/dwm/dwmblocks/default.nix b/modules/hosts/t480/dwm/dwmblocks/default.nix new file mode 100644 index 00000000..67827dd1 --- /dev/null +++ b/modules/hosts/t480/dwm/dwmblocks/default.nix @@ -0,0 +1,30 @@ +{ + flake.modules.homeManager.gui = + { pkgs, ... }: + { + home.packages = [ + (pkgs.dwmblocks.override { + conf = '' + static const Block blocks[] = { + {"", "status-audio", 10, 0}, + + {"", "status-network", 10, 0}, + + {"", "status-battery", 60, 0}, + + {"", "free -h | awk '/^Mem/ { printf \"%s/%s RAM\\n\", $3, $2 }' | sed 's/i//g'", 30, 0}, + + {"", "status-cpu", 10, 0}, + + {"", "status-weather", 600, 0}, + + {"", "date '+%a %d %b %Y %H:%M %Z'", 30, 0}, + }; + + static char delim[] = " | "; + static unsigned int delimLen = 5; + ''; + }) + ]; + }; +} diff --git a/modules/hosts/t480/dwm/dwmblocks/network.nix b/modules/hosts/t480/dwm/dwmblocks/network.nix new file mode 100644 index 00000000..bbe262bf --- /dev/null +++ b/modules/hosts/t480/dwm/dwmblocks/network.nix @@ -0,0 +1,24 @@ +{ + flake.modules.homeManager.gui = + { pkgs, ... }: + { + home.packages = [ + (pkgs.writeShellApplication { + name = "status-network"; + + runtimeInputs = with pkgs; [ networkmanager ]; + + text = '' + connected_to="$(nmcli | grep "connected to")" + + network_name="$(echo "$connected_to" | awk '{print $NF}')" + connected_device="$(echo "$connected_to" | cut -d ':' -f 1)" + + ip_address="$(ip a | grep "$connected_device" | grep inet | awk '{print $2}'| cut -d '/' -f 1)" + + echo "$network_name $ip_address" + ''; + }) + ]; + }; +} diff --git a/modules/hosts/t480/dwm/dwmblocks/weather.nix b/modules/hosts/t480/dwm/dwmblocks/weather.nix new file mode 100644 index 00000000..84d3aee3 --- /dev/null +++ b/modules/hosts/t480/dwm/dwmblocks/weather.nix @@ -0,0 +1,21 @@ +{ + flake.modules.homeManager.gui = + { pkgs, ... }: + { + home.packages = [ + (pkgs.writeShellApplication { + name = "status-weather"; + + runtimeInputs = with pkgs; [ curl ]; + + text = '' + out="$(curl -s https://wttr.in/Caerleon?format=%t)" + + [[ "$out" == *"Unknown location"* ]] && exit 1 + + echo "$out" + ''; + }) + ]; + }; +} diff --git a/modules/hosts/t480/fixapost.nix b/modules/hosts/t480/fixapost.nix new file mode 100644 index 00000000..23cb55fb --- /dev/null +++ b/modules/hosts/t480/fixapost.nix @@ -0,0 +1,17 @@ +{ inputs, ... }: + +{ + flake.modules.homeManager.base = + { pkgs, ... }: + { + home.packages = [ + (pkgs.writeShellApplication rec { + name = "fixapost"; + + runtimeInputs = [ pkgs.coreutils ]; + + text = builtins.readFile "${inputs.rwxrob-dot}/scripts/${name}"; + }) + ]; + }; +} diff --git a/modules/hosts/t480/heightwidth.nix b/modules/hosts/t480/heightwidth.nix new file mode 100644 index 00000000..9eb627e1 --- /dev/null +++ b/modules/hosts/t480/heightwidth.nix @@ -0,0 +1,17 @@ +{ inputs, ... }: + +{ + flake.modules.homeManager.base = + { pkgs, ... }: + { + home.packages = [ + (pkgs.writeShellApplication rec { + name = "heightwidth"; + + runtimeInputs = [ pkgs.ffmpeg ]; + + text = builtins.readFile "${inputs.rwxrob-dot}/scripts/${name}"; + }) + ]; + }; +} diff --git a/modules/hosts/t480/imports.nix b/modules/hosts/t480/imports.nix new file mode 100644 index 00000000..38ca7da8 --- /dev/null +++ b/modules/hosts/t480/imports.nix @@ -0,0 +1,7 @@ +{ config, ... }: + +{ + flake.modules.nixos."nixosConfigurations/t480".imports = with config.flake.modules.nixos; [ + desktop + ]; +} diff --git a/modules/hosts/t480/kanata/devices.nix b/modules/hosts/t480/kanata/devices.nix new file mode 100644 index 00000000..635656a2 --- /dev/null +++ b/modules/hosts/t480/kanata/devices.nix @@ -0,0 +1,5 @@ +{ + flake.modules.nixos.pc.services.kanata.devices = [ + "/dev/input/by-path/platform-i8042-serio-0-event-kbd" + ]; +} diff --git a/modules/hosts/t480/kanata/enable.nix b/modules/hosts/t480/kanata/enable.nix new file mode 100644 index 00000000..6bb8c1e5 --- /dev/null +++ b/modules/hosts/t480/kanata/enable.nix @@ -0,0 +1,3 @@ +{ + flake.modules.nixos.pc.services.kanata.enable = true; +} diff --git a/modules/hosts/t480/ollama.nix b/modules/hosts/t480/ollama.nix new file mode 100644 index 00000000..4ec6407a --- /dev/null +++ b/modules/hosts/t480/ollama.nix @@ -0,0 +1,3 @@ +{ + flake.modules.nixos.desktop.services.ollama.enable = false; +} diff --git a/modules/hosts/t480/open-webui.nix b/modules/hosts/t480/open-webui.nix new file mode 100644 index 00000000..ae6421f8 --- /dev/null +++ b/modules/hosts/t480/open-webui.nix @@ -0,0 +1,5 @@ +{ + nixpkgs.allowedUnfreePackages = [ "open-webui" ]; + + flake.modules.nixos.desktop.services.open-webui.enable = false; +} diff --git a/modules/hosts/t480/password-store.nix b/modules/hosts/t480/password-store.nix new file mode 100644 index 00000000..e40d892b --- /dev/null +++ b/modules/hosts/t480/password-store.nix @@ -0,0 +1,11 @@ +{ + flake.modules.homeManager.base = + { pkgs, ... }: + { + programs.password-store.extensions = with pkgs.passExtensions; [ + pass-audit + pass-otp + pass-update + ]; + }; +} diff --git a/modules/hosts/t480/slack.nix b/modules/hosts/t480/slack.nix new file mode 100644 index 00000000..97286f66 --- /dev/null +++ b/modules/hosts/t480/slack.nix @@ -0,0 +1,11 @@ +{ config, ... }: + +{ + nixpkgs.allowedUnfreePackages = [ "slack" ]; + + flake.modules.nixos."nixosConfigurations/t480" = + { pkgs, ... }: + { + users.users."${config.flake.meta.owner.username}".packages = [ pkgs.slack ]; + }; +} diff --git a/modules/hosts/t480/zoom.nix b/modules/hosts/t480/zoom.nix new file mode 100644 index 00000000..6e8251c2 --- /dev/null +++ b/modules/hosts/t480/zoom.nix @@ -0,0 +1,11 @@ +{ config, ... }: + +{ + nixpkgs.allowedUnfreePackages = [ "zoom" ]; + + flake.modules.nixos."nixosConfigurations/t480" = + { pkgs, ... }: + { + users.users."${config.flake.meta.owner.username}".packages = [ pkgs.zoom-us ]; + }; +} diff --git a/modules/kanata/config.nix b/modules/kanata/config.nix new file mode 100644 index 00000000..bc73ab3e --- /dev/null +++ b/modules/kanata/config.nix @@ -0,0 +1,29 @@ +{ + flake.modules.nixos.pc.services.kanata.keyboards.default.config = '' + (defsrc + caps a s d f j k l ; + ) + + (defvar + tap-time 150 + hold-time 200 + hold-time-slow 300 + ) + + (defalias + escctrl (tap-hold 100 100 esc lctl) + a (tap-hold $tap-time $hold-time-slow a lmet) + s (tap-hold $tap-time $hold-time-slow s lalt) + d (tap-hold $tap-time $hold-time d lsft) + f (tap-hold $tap-time $hold-time f lctl) + j (tap-hold $tap-time $hold-time j rctl) + k (tap-hold $tap-time $hold-time k rsft) + l (tap-hold $tap-time $hold-time-slow l ralt) + ; (tap-hold $tap-time $hold-time-slow ; rmet) + ) + + (deflayer base + @escctrl @a @s @d @f @j @k @l @; + ) + ''; +} diff --git a/modules/kanata/devices.nix b/modules/kanata/devices.nix new file mode 100644 index 00000000..42864248 --- /dev/null +++ b/modules/kanata/devices.nix @@ -0,0 +1,14 @@ +{ lib, ... }: + +{ + flake.modules.nixos.pc = + { config, ... }: + { + options.services.kanata.devices = lib.mkOption { + default = [ ]; + type = lib.types.listOf lib.types.str; + }; + + config.services.kanata.keyboards.default.devices = config.services.kanata.devices; + }; +} diff --git a/modules/kanata/extra-config.nix b/modules/kanata/extra-config.nix new file mode 100644 index 00000000..b41028a0 --- /dev/null +++ b/modules/kanata/extra-config.nix @@ -0,0 +1,3 @@ +{ + flake.modules.nixos.pc.services.kanata.keyboards.default.extraDefCfg = "process-unmapped-keys yes"; +} diff --git a/modules/lynx.nix b/modules/lynx.nix new file mode 100644 index 00000000..2187eb6c --- /dev/null +++ b/modules/lynx.nix @@ -0,0 +1,9 @@ +{ + flake.modules.nixos.base = + { pkgs, ... }: + { + environment.systemPackages = with pkgs; [ + lynx + ]; + }; +} diff --git a/modules/makemkv.nix b/modules/makemkv.nix new file mode 100644 index 00000000..a395220c --- /dev/null +++ b/modules/makemkv.nix @@ -0,0 +1,15 @@ +{ config, ... }: + +{ + nixpkgs.allowedUnfreePackages = [ "makemkv" ]; + + flake.modules.nixos.desktop = + { pkgs, ... }: + { + boot.kernelModules = [ "sg" ]; + + environment.systemPackages = with pkgs; [ makemkv ]; + + users.users.${config.flake.meta.owner.username}.extraGroups = [ "cdrom" ]; + }; +} diff --git a/modules/meta/dev-shell.nix b/modules/meta/dev-shell.nix new file mode 100644 index 00000000..89037018 --- /dev/null +++ b/modules/meta/dev-shell.nix @@ -0,0 +1,14 @@ +{ + perSystem = + { pkgs, ... }: + { + devShells.default = pkgs.mkShell { + packages = with pkgs; [ + just + lua-language-server + lua54Packages.luacheck + nixd + ]; + }; + }; +} diff --git a/modules/meta/flake-parts.nix b/modules/meta/flake-parts.nix new file mode 100644 index 00000000..1a92203d --- /dev/null +++ b/modules/meta/flake-parts.nix @@ -0,0 +1,7 @@ +{ inputs, ... }: + +{ + imports = [ + inputs.flake-parts.flakeModules.modules + ]; +} diff --git a/modules/meta/formatting.nix b/modules/meta/formatting.nix new file mode 100644 index 00000000..3c962b13 --- /dev/null +++ b/modules/meta/formatting.nix @@ -0,0 +1,7 @@ +{ + perSystem = + { pkgs, ... }: + { + formatter = pkgs.nixfmt-rfc-style; + }; +} diff --git a/modules/meta/meta-output.nix b/modules/meta/meta-output.nix new file mode 100644 index 00000000..dbf69e5d --- /dev/null +++ b/modules/meta/meta-output.nix @@ -0,0 +1,7 @@ +{ lib, ... }: + +{ + options.flake.meta = lib.mkOption { + type = lib.types.anything; + }; +} diff --git a/modules/meta/systems.nix b/modules/meta/systems.nix new file mode 100644 index 00000000..ce708c68 --- /dev/null +++ b/modules/meta/systems.nix @@ -0,0 +1,3 @@ +{ + systems = [ "x86_64-linux" ]; +} diff --git a/modules/mpv/bindings.nix b/modules/mpv/bindings.nix new file mode 100644 index 00000000..314514f4 --- /dev/null +++ b/modules/mpv/bindings.nix @@ -0,0 +1,7 @@ +{ + # https://github.com/mpv-player/mpv/blob/master/etc/input.conf + flake.modules.homeManager.gui.programs.mpv.bindings = { + "DOWN" = "add volume -5"; + "UP" = "add volume 5"; + }; +} diff --git a/modules/mpv/enable.nix b/modules/mpv/enable.nix new file mode 100644 index 00000000..6985bfee --- /dev/null +++ b/modules/mpv/enable.nix @@ -0,0 +1,3 @@ +{ + flake.modules.homeManager.gui.programs.mpv.enable = true; +} diff --git a/modules/nix-index.nix b/modules/nix-index.nix new file mode 100644 index 00000000..b1fcf010 --- /dev/null +++ b/modules/nix-index.nix @@ -0,0 +1,12 @@ +{ inputs, ... }: + +{ + flake.modules.homeManager.base = { + imports = [ inputs.nix-index-database.homeModules.nix-index ]; + + programs = { + nix-index.enable = true; + nix-index-database.comma.enable = true; + }; + }; +} diff --git a/modules/nix/utils.nix b/modules/nix/utils.nix new file mode 100644 index 00000000..9793b4b8 --- /dev/null +++ b/modules/nix/utils.nix @@ -0,0 +1,3 @@ +{ + flake.modules.homeManager.base.programs.nh.enable = true; +} diff --git a/modules/nixos-configurations.nix b/modules/nixos-configurations.nix new file mode 100644 index 00000000..7d091988 --- /dev/null +++ b/modules/nixos-configurations.nix @@ -0,0 +1,55 @@ +{ + config, + inputs, + self, + ... +}: + +{ + flake = + let + inherit (self) outputs; + + specialArgs = { + inherit inputs outputs self; + + system = "x86_64-linux"; + username = "opdavies"; + }; + + mkNixosConfiguration = + { + hostname, + modules ? [ ], + stateVersion ? "22.11", + system ? "x86_64-linux", + }: + inputs.nixpkgs.lib.nixosSystem { + inherit system; + + modules = modules ++ [ + "${self}/hosts/${hostname}/configuration.nix" + ]; + + specialArgs = specialArgs // { + inherit hostname stateVersion system; + }; + }; + in + { + nixosConfigurations = { + nixedo = mkNixosConfiguration rec { + hostname = "nixedo"; + stateVersion = "24.11"; + + modules = [ config.flake.modules.nixos."nixosConfigurations/${hostname}" ]; + }; + + t480 = mkNixosConfiguration rec { + hostname = "t480"; + + modules = [ config.flake.modules.nixos."nixosConfigurations/${hostname}" ]; + }; + }; + }; +} diff --git a/modules/nixvim/aliases.nix b/modules/nixvim/aliases.nix new file mode 100644 index 00000000..e8f6a389 --- /dev/null +++ b/modules/nixvim/aliases.nix @@ -0,0 +1,6 @@ +{ + flake.modules.nixvim.custom = { + viAlias = true; + vimAlias = true; + }; +} diff --git a/modules/nixvim/auto-save.nix b/modules/nixvim/auto-save.nix new file mode 100644 index 00000000..0844ec58 --- /dev/null +++ b/modules/nixvim/auto-save.nix @@ -0,0 +1,24 @@ +{ + flake.modules.nixvim.custom.plugins.auto-save = { + enable = true; + + settings.condition = '' + function(buf) + local excluded_filetypes = { + "harpoon", + "oil", + } + + local excluded_filenames = {} + + if vim.tbl_contains(excluded_filetypes, vim.fn.getbufvar(buf, "&filetype")) + or vim.tbl_contains(excluded_filenames, vim.fn.expand("%:t")) + then + return false + end + + return true + end + ''; + }; +} diff --git a/modules/nixvim/colorscheme.nix b/modules/nixvim/colorscheme.nix new file mode 100644 index 00000000..28e04bc8 --- /dev/null +++ b/modules/nixvim/colorscheme.nix @@ -0,0 +1,6 @@ +{ + flake.modules.nixvim.custom.colorschemes.catppuccin = { + enable = true; + settings.flavour = "mocha"; + }; +} diff --git a/modules/nixvim/completion/cmp.nix b/modules/nixvim/completion/cmp.nix new file mode 100644 index 00000000..c6d96b43 --- /dev/null +++ b/modules/nixvim/completion/cmp.nix @@ -0,0 +1,57 @@ +{ + flake.modules.nixvim.custom.plugins.cmp = { + enable = true; + + autoEnableSources = true; + + settings = { + mapping = { + "" = "cmp.mapping.close()"; + + "" = '' + cmp.mapping(function() + if ls.locally_jumpable(-1) then + ls.jump(-1) + end + end) + ''; + + "" = '' + cmp.mapping(function() + if ls.expand_or_locally_jumpable() then + ls.expand_or_jump() + end + end) + ''; + + "" = "cmp.mapping.select_next_item({ behavior = cmp.SelectBehavior.Select })"; + "" = "cmp.mapping.select_prev_item({ behavior = cmp.SelectBehavior.Select })"; + + "" = "cmp.mapping.confirm({ select = true })"; + + "" = "nil"; + "" = "nil"; + "" = "nil"; + }; + + snippet.expand = '' + function(args) + require('luasnip').lsp_expand(args.body) + end + ''; + + sources = [ + { name = "nvim_lsp"; } + { name = "nvim_lua"; } + { + name = "luasnip"; + keyword_length = 2; + } + { + name = "buffer"; + keyword_length = 3; + } + ]; + }; + }; +} diff --git a/modules/nixvim/completion/luasnip.nix b/modules/nixvim/completion/luasnip.nix new file mode 100644 index 00000000..5b91c029 --- /dev/null +++ b/modules/nixvim/completion/luasnip.nix @@ -0,0 +1,16 @@ +{ + flake.modules.nixvim.custom.plugins = { + cmp_luasnip.enable = true; + + luasnip = { + enable = true; + + fromLua = [ + { + lazyLoad = true; + paths = ./snippets; + } + ]; + }; + }; +} diff --git a/modules/nixvim/completion/snippets/asciidoc.lua b/modules/nixvim/completion/snippets/asciidoc.lua new file mode 100644 index 00000000..58b94986 --- /dev/null +++ b/modules/nixvim/completion/snippets/asciidoc.lua @@ -0,0 +1,10 @@ +return { + s("dev", t("__Under development...__")), + + s("source", fmta([[ + [source] + ---- + + ---- + ]], { finish = i(0), options = i(1) })), +} diff --git a/modules/nixvim/completion/snippets/javascript.lua b/modules/nixvim/completion/snippets/javascript.lua new file mode 100644 index 00000000..4cfb491e --- /dev/null +++ b/modules/nixvim/completion/snippets/javascript.lua @@ -0,0 +1,3 @@ +return { + s("log", fmta("console.log(<>);", { i(1, "value") })), +} diff --git a/modules/nixvim/completion/snippets/lua.lua b/modules/nixvim/completion/snippets/lua.lua new file mode 100644 index 00000000..31406fe7 --- /dev/null +++ b/modules/nixvim/completion/snippets/lua.lua @@ -0,0 +1,13 @@ +return { + s( + "req", + fmt([[local {} = require "{}"]], { + f(function(import_name) + local parts = vim.split(import_name[1][1], ".", true) + + return parts[#parts] or "" + end, { 1 }), + i(1), + }) + ) +} diff --git a/modules/nixvim/completion/snippets/nix.lua b/modules/nixvim/completion/snippets/nix.lua new file mode 100644 index 00000000..8e454963 --- /dev/null +++ b/modules/nixvim/completion/snippets/nix.lua @@ -0,0 +1,111 @@ +return { + s("home_packages", fmta("home.packages = with pkgs; [ <> ];", i(0))), + + s( + "homepage_options", + fmta( + [[ + homepage.name = mkOption { + default = ""; + type = types.str; + }; + + homepage.description = mkOption { + default = ""; + type = types.str; + }; + + homepage.icon = mkOption { + default = ""; + type = types.str; + }; + + homepage.category = mkOption { + default = ""; + type = types.str; + }; + ]], + { + description = i(2), + finish = i(0), + icon = i(3), + name = i(1), + } + ) + ), + + s( + "imports", + fmta( + [[ + { + imports = [ + <> + ]; + } + ]], + { i(0) } + ) + ), + + s( + "new_flake", + fmta( + [[ + { + inputs = { + nixpkgs.url = "github:nixos/nixpkgs/nixos-unstable"; + }; + + outputs = + { nixpkgs, ... }: + let + system = "x86_64-linux"; + pkgs = import nixpkgs { inherit system; }; + + inherit (pkgs) mkShell; + in + { + devShells.${system}.default = mkShell { + packages = with pkgs; [ ]; + }; + + formatter.${system} = pkgs.nixfmt-classic; + }; + } + ]], + { inputs = i(1), pkgs = i(2), finish = i(0) } + ) + ), + s( + "new_module", + fmta( + [[ + { config, lib, ... }: + + let + name = ""; + cfg = config..${name}; + in + { + options..${name} = { + enable = lib.mkEnableOption "Enable ${name}"; + }; + + config = lib.mkIf cfg.enable { + + }; + } + ]], + { + finish = i(0), + more_options = i(3), + name = i(1), + namespace = i(2), + }, + { repeat_duplicates = true } + ) + ), + + s("system_packages", fmta("environment.systemPackages = with pkgs; [<>];", i(0))), +} diff --git a/modules/nixvim/completion/snippets/php.lua b/modules/nixvim/completion/snippets/php.lua new file mode 100644 index 00000000..eeb9f5d9 --- /dev/null +++ b/modules/nixvim/completion/snippets/php.lua @@ -0,0 +1,55 @@ +return { + s("func", fmta("function <>(<>)<> {\n <>\n}<>", { i(1), i(2), i(3), i(4), i(0) })), + + s( + "met", + fmta( + [[ + <> function <>(<>)<> { + <> + }<> + ]], + { c(1, { t "public", t "protected", t "private" }), i(2), i(3), i(4), i(5), i(0) } + ) + ), + + s("pest", fmta("<>('<>', function() {\n <>\n});", { c(1, { t "it", t "test" }), i(2), i(0) })), + + s( + "test", + fmta( + [[ + public function test<>(): void { + <> + }<> + ]], + { i(1), i(2), i(0) } + ) + ), + + s( + "testan", + fmta( + [[ + /** @test */ + public function <>(): void { + <> + }<> + ]], + { i(1), i(2), i(0) } + ) + ), + + s( + "testat", + fmta( + [[ + [#Test] + public function <>(): void { + <> + }<> + ]], + { i(1), i(2), i(0) } + ) + ) +} diff --git a/modules/nixvim/completion/snippets/rst.lua b/modules/nixvim/completion/snippets/rst.lua new file mode 100644 index 00000000..7964a542 --- /dev/null +++ b/modules/nixvim/completion/snippets/rst.lua @@ -0,0 +1,54 @@ +local fmta = require("luasnip.extras.fmt").fmta + +local fill_line = function(char) + return function() + local row = vim.api.nvim_win_get_cursor(0)[1] + local lines = vim.api.nvim_buf_get_lines(0, row - 2, row, false) + return string.rep(char, #lines[1]) + end +end + +return { + s("class", t(".. class:: ", i(1))), + + s("footer", t(".. footer:: ", i(1))), + + s("link", t(".. _", i(1), ":")), + + s("raw", t(".. raw:: ", i(1))), + + -- TODO: add an optional new line and ":width" property. + s("image", t(".. image:: ", i(1))), + + s("head", f(fill_line "=", {})), + + s("sub", f(fill_line "-", {})), + + s("subsub", f(fill_line "^", {})), + + -- Add a page break with an optional page template. + s( + "pb", + fmta( + [[ + .. raw:: pdf + + PageBreak<> + ]], + { i(0) } + ) + ), + + -- Add a new speaker note. + s( + "ta", + fmta( + [[ + .. raw:: pdf + + TextAnnotation "<>" + ]], + { i(0) } + ) + ), +} diff --git a/modules/nixvim/completion/snippets/twig.lua b/modules/nixvim/completion/snippets/twig.lua new file mode 100644 index 00000000..a787a544 --- /dev/null +++ b/modules/nixvim/completion/snippets/twig.lua @@ -0,0 +1,19 @@ +return { + s("do", fmta("{% <> %}<>", { i(1), i(0) })), + s("dump", fmta("{{ dump(<>) }}<>", { i(1), i(0) })), + s("echo", fmta("{{ <> }}<>", { i(1), i(0) })), + + s( + "for", + fmta( + [[ + {% for <> in <> %} + <> + {% endfor %}<> + ]], + { i(1), i(2), i(3), i(0) } + ) + ), + + s("if", fmta("{% if <> %}<>{% endif %}<>", { i(1), i(2), i(0) })), +} diff --git a/modules/nixvim/conform.nix b/modules/nixvim/conform.nix new file mode 100644 index 00000000..8e7e5c8d --- /dev/null +++ b/modules/nixvim/conform.nix @@ -0,0 +1,3 @@ +{ + flake.modules.nixvim.custom.plugins.conform-nvim.enable = true; +} diff --git a/modules/nixvim/diagnostics.nix b/modules/nixvim/diagnostics.nix new file mode 100644 index 00000000..a3758ade --- /dev/null +++ b/modules/nixvim/diagnostics.nix @@ -0,0 +1,12 @@ +{ + flake.modules.nixvim.custom.diagnostic.settings = { + signs = true; + underline = false; + update_in_insert = false; + + virtual_text = { + enable = true; + spacing = 2; + }; + }; +} diff --git a/modules/nixvim/edit-alternate/config.nix b/modules/nixvim/edit-alternate/config.nix new file mode 100644 index 00000000..7adefaa0 --- /dev/null +++ b/modules/nixvim/edit-alternate/config.nix @@ -0,0 +1,71 @@ +{ + flake.modules.nixvim.custom.extraConfigLua = '' + local add_rule = function(ft, fn) + vim.fn["edit_alternate#rule#add"](ft, fn) + end + + add_rule("go", function(filename) + return filename:find "_test%.go$" + and filename:gsub("_test%.go$", ".go") + or filename:gsub("%.go$", "_test.go") + end) + + add_rule("php", function(filename) + if filename:find "Test.php$" then + filename = filename:gsub("Test.php$", ".php") + + return filename:find "tests/src/" + and filename:gsub("tests/src/(.-)/", "src/") + or filename:gsub("tests/", "src/") + else + local test_filename = filename:gsub("%.php$", "Test.php") + + if test_filename:find "modules/custom" then + local test_types = { "Functional", "FunctionalJavaScript", "Kernel", "Unit" } + + for _, test_type in ipairs(test_types) do + local candidate = test_filename:gsub("src/", string.format("tests/src/%s/", test_type)) + + if vim.fn.filereadable(candidate) == 1 then + return candidate + end + end + end + + return test_filename + end + end) + + add_rule("ts", function(filename) + return filename:gsub("%.stories.ts$", ".tsx") + end) + + add_rule("tsx", function(filename) + if filename:find("%.stories.tsx$") then + return filename:gsub("%.stories.tsx$", ".tsx") + end + + return filename:gsub("%.tsx$", ".stories.tsx") + end) + + if vim.fn.filereadable "composer.json" == 1 then + add_rule("json", function(filename) + return filename:find "composer.json" and filename:gsub("%.json$", ".lock") or nil + end) + + add_rule("lock", function(filename) + return filename:find "composer.lock" and filename:gsub("%.lock$", ".json") or nil + end) + end + + if vim.fn.filereadable "fractal.config.js" == 1 then + add_rule("twig", function(filename) + return filename:gsub("%.twig$", ".config.yml") + end) + + add_rule("yml", function(filename) + return filename:gsub("%.config.yml$", ".twig") + end) + end + ''; +} diff --git a/modules/nixvim/edit-alternate/extra-plugins.nix b/modules/nixvim/edit-alternate/extra-plugins.nix new file mode 100644 index 00000000..ca795f18 --- /dev/null +++ b/modules/nixvim/edit-alternate/extra-plugins.nix @@ -0,0 +1,31 @@ +{ inputs, ... }: + +{ + flake.modules.nixvim.custom = + { pkgs, ... }: + { + extraPlugins = + let + inherit (pkgs.vimUtils) buildVimPlugin; + in + [ + (buildVimPlugin { + pname = "conf-vim"; + src = inputs.conf-vim; + version = "unstable"; + }) + + (buildVimPlugin { + pname = "edit-alternate-vim"; + src = inputs.edit-alternate-vim; + version = "unstable"; + }) + + (buildVimPlugin { + pname = "standard-vim"; + src = inputs.standard-vim; + version = "unstable"; + }) + ]; + }; +} diff --git a/modules/nixvim/edit-alternate/keymaps.nix b/modules/nixvim/edit-alternate/keymaps.nix new file mode 100644 index 00000000..fa375bab --- /dev/null +++ b/modules/nixvim/edit-alternate/keymaps.nix @@ -0,0 +1,9 @@ +{ + flake.modules.nixvim.custom.keymaps = [ + { + action = "EditAlternate"; + key = "ea"; + mode = "n"; + } + ]; +} diff --git a/modules/nixvim/extra-packages.nix b/modules/nixvim/extra-packages.nix new file mode 100644 index 00000000..33f7d8f1 --- /dev/null +++ b/modules/nixvim/extra-packages.nix @@ -0,0 +1,10 @@ +{ + flake.modules.nixvim.custom = + { pkgs, ... }: + { + extraPackages = with pkgs; [ + nixfmt-rfc-style + stylua + ]; + }; +} diff --git a/modules/nixvim/fidget.nix b/modules/nixvim/fidget.nix new file mode 100644 index 00000000..05124ce7 --- /dev/null +++ b/modules/nixvim/fidget.nix @@ -0,0 +1,3 @@ +{ + flake.modules.nixvim.custom.plugins.fidget.enable = true; +} diff --git a/modules/nixvim/filetypes.nix b/modules/nixvim/filetypes.nix new file mode 100644 index 00000000..bfdc4ca9 --- /dev/null +++ b/modules/nixvim/filetypes.nix @@ -0,0 +1,17 @@ +{ + flake.modules.nixvim.custom.filetype = { + extension = { + "neon.dist" = "yaml"; + inc = "php"; + install = "php"; + module = "php"; + neon = "yaml"; + pcss = "scss"; + theme = "php"; + }; + + filename = { + "composer.lock" = "json"; + }; + }; +} diff --git a/modules/nixvim/flake-outputs.nix b/modules/nixvim/flake-outputs.nix new file mode 100644 index 00000000..2705d5c8 --- /dev/null +++ b/modules/nixvim/flake-outputs.nix @@ -0,0 +1,13 @@ +{ config, ... }: + +{ + perSystem = + { inputs', pkgs, ... }: + { + packages.neovim = inputs'.nixvim.legacyPackages.makeNixvimWithModule { + inherit pkgs; + + module = config.flake.modules.nixvim.custom; + }; + }; +} diff --git a/modules/nixvim/ftplugin/asciidoc.nix b/modules/nixvim/ftplugin/asciidoc.nix new file mode 100644 index 00000000..33a44bc6 --- /dev/null +++ b/modules/nixvim/ftplugin/asciidoc.nix @@ -0,0 +1,17 @@ +{ lib, ... }: + +{ + flake.modules.nixvim.custom = + { pkgs, ... }: + { + extraFiles."after/ftplugin/asciidoc.lua".text = '' + vim.opt_local.linebreak = true + vim.opt_local.makeprg = "${lib.getExe pkgs.asciidoctor} %" + vim.opt_local.spell = true + + -- Convert lines into a list. + vim.keymap.set("n", "l", "vip:norm I* ") + vim.keymap.set("v", "l", ":norm I* ") + ''; + }; +} diff --git a/modules/nixvim/ftplugin/gitcommit.nix b/modules/nixvim/ftplugin/gitcommit.nix new file mode 100644 index 00000000..9475a398 --- /dev/null +++ b/modules/nixvim/ftplugin/gitcommit.nix @@ -0,0 +1,9 @@ +{ + flake.modules.nixvim.custom.extraFiles."after/ftplugin/gitcommit.lua".text = + # lua + '' + vim.opt_local.colorcolumn = "50,72" + vim.opt_local.spell = true + vim.opt_local.textwidth = 72 + ''; +} diff --git a/modules/nixvim/ftplugin/go.nix b/modules/nixvim/ftplugin/go.nix new file mode 100644 index 00000000..21abe049 --- /dev/null +++ b/modules/nixvim/ftplugin/go.nix @@ -0,0 +1,9 @@ +{ + flake.modules.nixvim.custom = { + extraFiles."after/ftplugin/go.lua".text = + # lua + '' + vim.opt.makeprg = "go run %" + ''; + }; +} diff --git a/modules/nixvim/ftplugin/just.nix b/modules/nixvim/ftplugin/just.nix new file mode 100644 index 00000000..c9c4517c --- /dev/null +++ b/modules/nixvim/ftplugin/just.nix @@ -0,0 +1,11 @@ +{ + flake.modules.nixvim.custom = { + extraFiles."after/ftplugin/just.lua".text = + # lua + '' + local opt = vim.opt_local + + opt.shiftwidth = 4 + ''; + }; +} diff --git a/modules/nixvim/ftplugin/markdown.nix b/modules/nixvim/ftplugin/markdown.nix new file mode 100644 index 00000000..9cd1f1ed --- /dev/null +++ b/modules/nixvim/ftplugin/markdown.nix @@ -0,0 +1,22 @@ +{ + flake.modules.nixvim.custom = { + plugins.cmp-path.enable = true; + + extraFiles."after/ftplugin/markdown.lua".text = + # lua + '' + local opt = vim.opt_local + + opt.spell = true + opt.wrap = true + + local cmp = require "cmp" + local sources = cmp.get_config().sources + + -- TODO: confirm these aren't aleady in the list of sources to avoid duplicate suggestions. + table.insert(sources, { name = "path" }) + + cmp.setup.buffer { sources = sources } + ''; + }; +} diff --git a/modules/nixvim/ftplugin/php.nix b/modules/nixvim/ftplugin/php.nix new file mode 100644 index 00000000..e531157e --- /dev/null +++ b/modules/nixvim/ftplugin/php.nix @@ -0,0 +1,9 @@ +{ + flake.modules.nixvim.custom = { + extraFiles."after/ftplugin/php.lua".text = + # lua + '' + vim.opt_local.makeprg = "php %"; + ''; + }; +} diff --git a/modules/nixvim/fugitive.nix b/modules/nixvim/fugitive.nix new file mode 100644 index 00000000..ac800972 --- /dev/null +++ b/modules/nixvim/fugitive.nix @@ -0,0 +1,18 @@ +{ + flake.modules.nixvim.custom = { + plugins.fugitive.enable = true; + + keymaps = [ + { + key = "gc"; + action = "Git commitK"; + } + + { + # Open the ":Git" window in its own buffer, not a split. + key = "gs"; + action = "0Git"; + } + ]; + }; +} diff --git a/modules/nixvim/gitsigns.nix b/modules/nixvim/gitsigns.nix new file mode 100644 index 00000000..60609c35 --- /dev/null +++ b/modules/nixvim/gitsigns.nix @@ -0,0 +1,48 @@ +{ + flake.modules.nixvim.custom = { + plugins.gitsigns.enable = true; + + keymaps = [ + { + action = "Gitsigns prev_hunk"; + key = "[h"; + } + + { + action = "Gitsigns next_hunk"; + key = "]h"; + } + + { + action = "Gitsigns reset_hunk"; + key = "hr"; + } + + { + action = "Gitsigns reset_buffer"; + key = "hR"; + } + + { + action = "Gitsigns stage_hunk"; + key = "hs"; + mode = [ + "n" + "v" + ]; + } + + { + action = "Gitsigns stage_buffer"; + key = "hS"; + mode = "n"; + } + + { + action = "Gitsigns undo_stage_hunk"; + key = "hu"; + mode = "x"; + } + ]; + }; +} diff --git a/modules/nixvim/harpoon.nix b/modules/nixvim/harpoon.nix new file mode 100644 index 00000000..830b1f42 --- /dev/null +++ b/modules/nixvim/harpoon.nix @@ -0,0 +1,45 @@ +let + leaderBinding = key: command: { + key = "${key}"; + action = "${command}"; + options.silent = true; + }; +in +{ + flake.modules.nixvim.custom = { + plugins.harpoon = { + enable = true; + enableTelescope = true; + }; + + keymaps = [ + { + key = "a"; + action.__raw = "function() require'harpoon':list():add() end"; + } + + { + key = ""; + action.__raw = '' + function() + require 'harpoon'.ui:toggle_quick_menu(require'harpoon':list()) + end + ''; + } + ] + ++ (map + (num: leaderBinding "${toString num}" "lua require(\"harpoon\"):list():select(${toString num})") + [ + 1 + 2 + 3 + 4 + 5 + 6 + 7 + 8 + 9 + ] + ); + }; +} diff --git a/modules/nixvim/keymaps.nix b/modules/nixvim/keymaps.nix new file mode 100644 index 00000000..dc13def0 --- /dev/null +++ b/modules/nixvim/keymaps.nix @@ -0,0 +1,86 @@ +{ + flake.modules.nixvim.custom.keymaps = [ + { + action = "A,"; + key = ",,"; + mode = "i"; + } + + { + action = "A;"; + key = ";;"; + mode = "i"; + } + + { + action = "!drush cache-rebuild"; + key = "dcr"; + } + + { + action = ":edit todo.txt"; + key = "et"; + } + + { + action = "lua vim.lsp.buf.format()"; + key = "f"; + options.silent = true; + } + + { + action = "\"+y"; + key = "y"; + mode = [ + "n" + "x" + ]; + } + + { + action = "@q"; + key = "Q"; + } + + { + action = "silent !tmux new-window tmux-sessionizer"; + key = ""; + options.silent = true; + } + + { + action = ":w"; + key = ""; + mode = [ + "i" + "n" + ]; + } + + { + action = "tabnew"; + key = ""; + } + + { + action = "!composer install"; + key = "ci"; + } + + { + action = "edit composer.json"; + key = "ec"; + } + + { + action = "edit flake.nix"; + key = "ef"; + } + + { + action = ""; + key = "jk"; + mode = "i"; + } + ]; +} diff --git a/modules/nixvim/leader.nix b/modules/nixvim/leader.nix new file mode 100644 index 00000000..36b9eff9 --- /dev/null +++ b/modules/nixvim/leader.nix @@ -0,0 +1,6 @@ +{ + flake.modules.nixvim.custom.globals = { + mapleader = " "; + maplocalleader = " "; + }; +} diff --git a/modules/nixvim/lint.nix b/modules/nixvim/lint.nix new file mode 100644 index 00000000..60b766e6 --- /dev/null +++ b/modules/nixvim/lint.nix @@ -0,0 +1,3 @@ +{ + flake.modules.nixvim.custom.plugins.lint.enable = true; +} diff --git a/modules/nixvim/lsp.nix b/modules/nixvim/lsp.nix new file mode 100644 index 00000000..efd9d4d1 --- /dev/null +++ b/modules/nixvim/lsp.nix @@ -0,0 +1,23 @@ +{ + flake.modules.nixvim.custom.plugins.lsp = { + enable = true; + + keymaps = { + diagnostic = { + "dl" = "setqflist"; + }; + + lspBuf = { + "ca" = "code_action"; + "cr" = "rename"; + K = "hover"; + gD = "declaration"; + gT = "type_definition"; + gd = "definition"; + gr = "references"; + }; + }; + + servers.phpactor.enable = true; + }; +} diff --git a/modules/nixvim/lsp/bash.nix b/modules/nixvim/lsp/bash.nix new file mode 100644 index 00000000..5b4fe0d7 --- /dev/null +++ b/modules/nixvim/lsp/bash.nix @@ -0,0 +1,3 @@ +{ + flake.modules.nixvim.custom.lsp.servers.bashls.enable = true; +} diff --git a/modules/nixvim/lsp/css.nix b/modules/nixvim/lsp/css.nix new file mode 100644 index 00000000..df60f599 --- /dev/null +++ b/modules/nixvim/lsp/css.nix @@ -0,0 +1,6 @@ +{ + flake.modules.nixvim.custom.lsp.servers = { + cssls.enable = true; + tailwindcss.enable = true; + }; +} diff --git a/modules/nixvim/lsp/go.nix b/modules/nixvim/lsp/go.nix new file mode 100644 index 00000000..56dd395b --- /dev/null +++ b/modules/nixvim/lsp/go.nix @@ -0,0 +1,3 @@ +{ + flake.modules.nixvim.custom.lsp.servers.gopls.enable = true; +} diff --git a/modules/nixvim/lsp/html.nix b/modules/nixvim/lsp/html.nix new file mode 100644 index 00000000..6cc1f44e --- /dev/null +++ b/modules/nixvim/lsp/html.nix @@ -0,0 +1,3 @@ +{ + flake.modules.nixvim.custom.lsp.servers.html.enable = true; +} diff --git a/modules/nixvim/lsp/javascript.nix b/modules/nixvim/lsp/javascript.nix new file mode 100644 index 00000000..148adb94 --- /dev/null +++ b/modules/nixvim/lsp/javascript.nix @@ -0,0 +1,6 @@ +{ + flake.modules.nixvim.custom.plugins = { + lsp.servers.eslint.enable = true; + typescript-tools.enable = true; + }; +} diff --git a/modules/nixvim/lsp/lua.nix b/modules/nixvim/lsp/lua.nix new file mode 100644 index 00000000..7fb31f17 --- /dev/null +++ b/modules/nixvim/lsp/lua.nix @@ -0,0 +1,3 @@ +{ + flake.modules.nixvim.custom.lsp.servers.lua_ls.enable = true; +} diff --git a/modules/nixvim/lsp/nix.nix b/modules/nixvim/lsp/nix.nix new file mode 100644 index 00000000..a3e698cd --- /dev/null +++ b/modules/nixvim/lsp/nix.nix @@ -0,0 +1,3 @@ +{ + flake.modules.nixvim.custom.lsp.servers.nixd.enable = true; +} diff --git a/modules/nixvim/lsp/php.nix b/modules/nixvim/lsp/php.nix new file mode 100644 index 00000000..6a22484a --- /dev/null +++ b/modules/nixvim/lsp/php.nix @@ -0,0 +1,3 @@ +{ + flake.modules.nixvim.custom.lsp.servers.phpactor.enable = true; +} diff --git a/modules/nixvim/make.nix b/modules/nixvim/make.nix new file mode 100644 index 00000000..1a533b9a --- /dev/null +++ b/modules/nixvim/make.nix @@ -0,0 +1,14 @@ +{ + flake.modules.nixvim.custom = + { pkgs, ... }: + { + extraPackages = with pkgs; [ gnumake ]; + + keymaps = [ + { + action = "make"; + key = "r"; + } + ]; + }; +} diff --git a/modules/nixvim/mini.nix b/modules/nixvim/mini.nix new file mode 100644 index 00000000..e9b66a30 --- /dev/null +++ b/modules/nixvim/mini.nix @@ -0,0 +1,15 @@ +{ + flake.modules.nixvim.custom.plugins.mini = { + enable = true; + + modules = { + ai = { }; + align = { }; + bracketed = { }; + move = { }; + operators = { }; + splitjoin = { }; + surround = { }; + }; + }; +} diff --git a/modules/nixvim/oil.nix b/modules/nixvim/oil.nix new file mode 100644 index 00000000..2a022eea --- /dev/null +++ b/modules/nixvim/oil.nix @@ -0,0 +1,23 @@ +{ + flake.modules.nixvim.custom = { + plugins.oil = { + enable = true; + + settings = { + delete_to_trash = true; + + keymaps."-" = "actions.parent"; + + skip_confirm_for_simple_edits = true; + view_options.show_hidden = true; + }; + }; + + keymaps = [ + { + action = "Oil"; + key = "-"; + } + ]; + }; +} diff --git a/modules/nixvim/options.nix b/modules/nixvim/options.nix new file mode 100644 index 00000000..adfacce9 --- /dev/null +++ b/modules/nixvim/options.nix @@ -0,0 +1,28 @@ +{ + flake.modules.nixvim.custom.opts = { + cmdheight = 0; + expandtab = true; + exrc = true; + foldlevel = 1; + foldlevelstart = 99; + foldmethod = "indent"; + inccommand = "split"; + laststatus = 3; + list = true; + number = true; + relativenumber = true; + scrolloff = 5; + shiftwidth = 2; + signcolumn = "yes:1"; + smartindent = true; + softtabstop = 2; + splitbelow = true; + splitright = true; + swapfile = false; + syntax = "on"; + tabstop = 2; + termguicolors = true; + updatetime = 1000; + wrap = false; + }; +} diff --git a/modules/nixvim/phpactor.nix b/modules/nixvim/phpactor.nix new file mode 100644 index 00000000..d40f8a1f --- /dev/null +++ b/modules/nixvim/phpactor.nix @@ -0,0 +1,19 @@ +{ + flake.modules.nixvim.custom = + { pkgs, ... }: + { + extraPlugins = with pkgs.vimPlugins; [ phpactor ]; + + keymaps = [ + { + key = "pm"; + action = "PhpactorContextMenu"; + } + + { + key = "pn"; + action = "PhpactorClassNew"; + } + ]; + }; +} diff --git a/modules/nixvim/refactoring.nix b/modules/nixvim/refactoring.nix new file mode 100644 index 00000000..f59f9a9c --- /dev/null +++ b/modules/nixvim/refactoring.nix @@ -0,0 +1,54 @@ +{ config, lib, ... }: + +{ + flake.modules.nixvim.custom = { + plugins.refactoring = { + enable = true; + enableTelescope = true; + }; + + keymaps = [ + { + key = "ri"; + action = "Refactor inline_var"; + mode = "n"; + } + + { + key = "re"; + action = "Refactor extract"; + mode = "x"; + } + + { + key = "ri"; + action = "Refactor inline_var"; + mode = "x"; + } + + { + key = "rv"; + action = "Refactor extract_var"; + mode = "x"; + } + ]; + # ++ + # lib.optionals + # ( + # config.flake.modules.nixvim.custom.plugins.refactoring.enable + # && config.flake.modules.nixvim.custom.plugins.refactoring.enableTelescope + # ) + # [ + # { + # mode = "n"; + # key = "rR"; + # action.__raw = '' + # function() + # require('telescope').extensions.refactoring.refactors() + # end + # ''; + # options.silent = true; + # } + # ]; + }; +} diff --git a/modules/nixvim/spell/en.utf-8.add b/modules/nixvim/spell/en.utf-8.add new file mode 100644 index 00000000..6d36619c --- /dev/null +++ b/modules/nixvim/spell/en.utf-8.add @@ -0,0 +1,132 @@ +ANP +AWS +Acquia +Ansible +Appnovation +Architected +BAU +Behat +Bitbucket +Bluecheese +BrumPHP +CMSes +CTI +Cachix +Centarro +CiviCRM +Configs +D7 +DDEV +DevOps +DigitalOcean +Drupal +Drupal's +DrupalCamp +DrupalCon +DrupalEasy +Drupaler +Drush +FPM +FTSE +GitLab +Gitea +HDN +HashiCorp +Hetzner +Homelab +Immich +InvalidArgumentException +Inviqa +JSON +Jellyfin +Kickstart +Lando +Laravel +Linode +Magento +MariaDB +Microserve +Mischa +MySQL +NGINX +Neovim +Netlify +Nginx +NixOS +NodeInterface +Nomensa +OpenID +OpenTofu +PDOException +PHPDoc +PHPStan +PHPUnit +Packagist +PhpStorm +PostBuilder +PostNodeRepository +Pulumi +S3 +SHA +SQLSTATE +SQLite +SSO +Sculpin +Silex +SimpleTest +Sylius +Symfony +TODO +TermInterface +Themers +Traefik +TypeScript +Ubercart +VSCode +Vaultwarden +WCAG +WSL +Wellbeing +ZSH +Zellij +Zettelkasten +architected +assertContainsOnlyInstancesOf +assertSame +bootcamp +contrib +devenv +dotfiles +drupal +eCommerce +foreach +getPost +ghostty +hotfix +isNotPublished +isPublished +localhost +macOS +mentees +nixpkgs +nodeStorage +opdavies +osCommerce +param +reStructuredText +rebase +rebasing +roadmapping +rst2pdf +rwxrob +src +stylesheet +stylesheets +testbot +tmux +url +vhost +wildcard +worktree +worktrees +www diff --git a/modules/nixvim/telescope.nix b/modules/nixvim/telescope.nix new file mode 100644 index 00000000..ee59725e --- /dev/null +++ b/modules/nixvim/telescope.nix @@ -0,0 +1,31 @@ +{ + flake.modules.nixvim.custom.plugins.telescope = { + enable = true; + + extensions = { + live-grep-args.enable = true; + fzf-native.enable = true; + ui-select.enable = true; + }; + + keymaps = { + "/" = "current_buffer_fuzzy_find"; + "fb" = "buffers"; + "fd" = "find_files"; + "fg" = "live_grep"; + + "gw" = { + action = "grep_string"; + mode = [ + "n" + "v" + ]; + }; + }; + + settings.defaults.layout_config.prompt_position = "top"; + settings.defaults.sorting_strategy = "ascending"; + + settings.pickers.find_files.hidden = true; + }; +} diff --git a/modules/nixvim/templates/default.nix b/modules/nixvim/templates/default.nix new file mode 100644 index 00000000..753b600a --- /dev/null +++ b/modules/nixvim/templates/default.nix @@ -0,0 +1,9 @@ +{ + flake.modules.nixvim.custom.autoCmd = [ + { + event = "BufNewFile"; + pattern = [ "*.php" ]; + command = "0r ${./php}"; + } + ]; +} diff --git a/modules/nixvim/templates/php b/modules/nixvim/templates/php new file mode 100644 index 00000000..174d7fd7 --- /dev/null +++ b/modules/nixvim/templates/php @@ -0,0 +1,3 @@ +UndotreeToggle"; + key = "u"; + } + ]; + }; +} diff --git a/modules/nixvim/use-in-home.nix b/modules/nixvim/use-in-home.nix new file mode 100644 index 00000000..991fca81 --- /dev/null +++ b/modules/nixvim/use-in-home.nix @@ -0,0 +1,24 @@ +{ config, inputs, lib, ... }: + +{ + flake.modules.homeManager.base = + hmArgs@{ pkgs, ... }: + let + # Ideally: + # nixvim = self.packages.${pkgs.system}.nixvim; + # but https://github.com/danth/stylix/pull/415#issuecomment-2832398958 + neovim = inputs.nixvim.legacyPackages.${pkgs.system}.makeNixvimWithModule { + inherit pkgs; + + extraSpecialArgs.homeConfig = hmArgs.config; + + module = config.flake.modules.nixvim.custom; + }; + in + { + home = { + packages = [ neovim ]; + sessionVariables.EDITOR = lib.mkForce (lib.getExe neovim); + }; + }; +} diff --git a/modules/nixvim/vim-cool.nix b/modules/nixvim/vim-cool.nix new file mode 100644 index 00000000..1a02189e --- /dev/null +++ b/modules/nixvim/vim-cool.nix @@ -0,0 +1,7 @@ +{ + flake.modules.nixvim.custom = + { pkgs, ... }: + { + extraPlugins = [ pkgs.vimPlugins.vim-cool ]; + }; +} diff --git a/modules/nixvim/vim-dadbod.nix b/modules/nixvim/vim-dadbod.nix new file mode 100644 index 00000000..1ef2050d --- /dev/null +++ b/modules/nixvim/vim-dadbod.nix @@ -0,0 +1,7 @@ +{ + flake.modules.nixvim.custom.plugins = { + vim-dadbod.enable = true; + vim-dadbod-completion.enable = true; + vim-dadbod-ui.enable = true; + }; +} diff --git a/modules/nixvim/vim-heritage.nix b/modules/nixvim/vim-heritage.nix new file mode 100644 index 00000000..2ff64c26 --- /dev/null +++ b/modules/nixvim/vim-heritage.nix @@ -0,0 +1,25 @@ +{ inputs, ... }: + +{ + flake.modules.nixvim.custom = + { pkgs, ... }: + { + extraPlugins = [ + (pkgs.vimUtils.buildVimPlugin { + src = inputs.vim-heritage; + pname = "vim-heritage"; + version = "unstable"; + }) + ]; + + keymaps = [ + # https://github.com/jessarcher/vim-heritage/blob/574baeb0679681a710adce5110a0d8b2ae1c2637/README.md#L28-L33 + { + action = ":edit %:h/"; + key = "gf"; + mode = "n"; + options.silent = true; + } + ]; + }; +} diff --git a/modules/nixvim/vim-highlightedyank.nix b/modules/nixvim/vim-highlightedyank.nix new file mode 100644 index 00000000..ee937da9 --- /dev/null +++ b/modules/nixvim/vim-highlightedyank.nix @@ -0,0 +1,11 @@ +{ + flake.modules.nixvim.custom = + { pkgs, ... }: + { + extraPlugins = [ pkgs.vimPlugins.vim-highlightedyank ]; + + extraConfigVim = '' + let g:highlightedyank_highlight_duration = 100 + ''; + }; +} diff --git a/modules/nixvim/vim-test.nix b/modules/nixvim/vim-test.nix new file mode 100644 index 00000000..5ec7a29c --- /dev/null +++ b/modules/nixvim/vim-test.nix @@ -0,0 +1,20 @@ +{ + flake.modules.nixvim.custom = { + plugins.vim-test.enable = true; + + keymaps = [ + { + key = "tf"; + action = "TestFile"; + } + { + key = "tl"; + action = "TestLast"; + } + { + key = "tn"; + action = "TestNearest"; + } + ]; + }; +} diff --git a/modules/nixvim/vim-textobj-xmlattr.nix b/modules/nixvim/vim-textobj-xmlattr.nix new file mode 100644 index 00000000..6cdd4812 --- /dev/null +++ b/modules/nixvim/vim-textobj-xmlattr.nix @@ -0,0 +1,17 @@ +{ inputs, ... }: + +{ + flake.modules.nixvim.custom = + { pkgs, ... }: + { + extraPlugins = with pkgs.vimPlugins; [ + vim-textobj-user + + (pkgs.vimUtils.buildVimPlugin { + src = inputs.vim-textobj-xmlattr; + pname = "vim-textobj-xmlattr"; + version = "unstable"; + }) + ]; + }; +} diff --git a/modules/nixvim/web-devicons.nix b/modules/nixvim/web-devicons.nix new file mode 100644 index 00000000..56591499 --- /dev/null +++ b/modules/nixvim/web-devicons.nix @@ -0,0 +1,3 @@ +{ + flake.modules.nixvim.custom.plugins.web-devicons.enable = false; +} diff --git a/modules/node.nix b/modules/node.nix new file mode 100644 index 00000000..55ec9367 --- /dev/null +++ b/modules/node.nix @@ -0,0 +1,19 @@ +{ + flake.modules.homeManager.base = + { config, ... }: + let + inherit (config.xdg) configHome dataHome stateHome; + in + { + xdg.configFile."${config.home.sessionVariables.NPM_CONFIG_USERCONFIG}".text = '' + cache=${configHome}/npm + init-module=${configHome}/npm/config/npm-init.js + logs-dir=${stateHome}/npm/logs + prefix=${dataHome}/npm + ''; + + home.sessionVariables = { + NPM_CONFIG_USERCONFIG = "${configHome}/npm/npmrc"; + }; + }; +} diff --git a/modules/notes/xdg.nix b/modules/notes/xdg.nix new file mode 100644 index 00000000..f0daba22 --- /dev/null +++ b/modules/notes/xdg.nix @@ -0,0 +1,6 @@ +{ + flake.modules.homeManager.base.xdg = { + enable = true; + userDirs.enable = true; + }; +} diff --git a/modules/ollama/acceleration.nix b/modules/ollama/acceleration.nix new file mode 100644 index 00000000..f79fd202 --- /dev/null +++ b/modules/ollama/acceleration.nix @@ -0,0 +1,3 @@ +{ + flake.modules.nixos.desktop.services.ollama.acceleration = "rocm"; +} diff --git a/modules/ollama/models.nix b/modules/ollama/models.nix new file mode 100644 index 00000000..4df7a39a --- /dev/null +++ b/modules/ollama/models.nix @@ -0,0 +1,5 @@ +{ + flake.modules.nixos.desktop.services.ollama.loadModels = [ + "dimavz/whisper-tiny" + ]; +} diff --git a/modules/openssh/enable.nix b/modules/openssh/enable.nix new file mode 100644 index 00000000..278ab317 --- /dev/null +++ b/modules/openssh/enable.nix @@ -0,0 +1,3 @@ +{ + flake.modules.nixos.pc.services.openssh.enable = true; +} diff --git a/modules/openssh/firewall.nix b/modules/openssh/firewall.nix new file mode 100644 index 00000000..c8b4e8b5 --- /dev/null +++ b/modules/openssh/firewall.nix @@ -0,0 +1,5 @@ +{ lib, ... }: + +{ + flake.modules.nixos.pc.services.openssh.openFirewall = lib.mkForce true; +} diff --git a/modules/openssh/settings.nix b/modules/openssh/settings.nix new file mode 100644 index 00000000..d1a976f7 --- /dev/null +++ b/modules/openssh/settings.nix @@ -0,0 +1,8 @@ +{ lib, ... }: + +{ + flake.modules.nixos.pc.services.openssh.settings = { + PasswordAuthentication = false; + PermitRootLogin = lib.mkForce "no"; + }; +} diff --git a/modules/owner.nix b/modules/owner.nix new file mode 100644 index 00000000..5634a0c8 --- /dev/null +++ b/modules/owner.nix @@ -0,0 +1,23 @@ +{ config, lib, ... }: + +{ + flake = { + meta.owner = { + email = "oliver@oliverdavies.uk"; + name = "Oliver Davies"; + username = "opdavies"; + }; + + modules = { + nixos.base = { + users.users.${config.flake.meta.owner.username} = { + isNormalUser = true; + initialPassword = lib.mkForce ""; + extraGroups = [ "input" ]; + }; + + nix.settings.trusted-users = [ config.flake.meta.owner.username ]; + }; + }; + }; +} diff --git a/modules/password-store/enable.nix b/modules/password-store/enable.nix new file mode 100644 index 00000000..e5022dee --- /dev/null +++ b/modules/password-store/enable.nix @@ -0,0 +1,3 @@ +{ + flake.modules.homeManager.base.programs.password-store.enable = true; +} diff --git a/modules/password-store/package.nix b/modules/password-store/package.nix new file mode 100644 index 00000000..781a0e5d --- /dev/null +++ b/modules/password-store/package.nix @@ -0,0 +1,17 @@ +{ lib, ... }: + +{ + flake.modules.homeManager.base = + { config, pkgs, ... }: + { + options.programs.password-store.extensions = lib.mkOption { + default = [ ]; + type = lib.types.listOf lib.types.package; + description = "pass extensions to install."; + }; + + config.programs.password-store.package = pkgs.pass.withExtensions ( + e: with e; config.programs.password-store.extensions + ); + }; +} diff --git a/modules/password-store/settings.nix b/modules/password-store/settings.nix new file mode 100644 index 00000000..e4dd4374 --- /dev/null +++ b/modules/password-store/settings.nix @@ -0,0 +1,7 @@ +{ + flake.modules.homeManager.base = + { config, ... }: + { + programs.password-store.settings.PASSWORD_STORE_DIR = "${config.xdg.dataHome}/pass"; + }; +} diff --git a/modules/pc.nix b/modules/pc.nix new file mode 100644 index 00000000..6df7746c --- /dev/null +++ b/modules/pc.nix @@ -0,0 +1,5 @@ +{ config, ... }: + +{ + flake.modules.nixos.pc.imports = with config.flake.modules.nixos; [ base ]; +} diff --git a/modules/phpactor/config/phpactor.yml b/modules/phpactor/config/phpactor.yml new file mode 100644 index 00000000..1c755d12 --- /dev/null +++ b/modules/phpactor/config/phpactor.yml @@ -0,0 +1,6 @@ +code_transform.class_new.variants: + collection: collection + default: default + drupal-functional-test: drupal-functional-test + drupal-kernel-test: drupal-kernel-test + drupal-unit-test: drupal-unit-test diff --git a/modules/phpactor/config/templates/action/SourceCode.php.twig b/modules/phpactor/config/templates/action/SourceCode.php.twig new file mode 100644 index 00000000..eabd762e --- /dev/null +++ b/modules/phpactor/config/templates/action/SourceCode.php.twig @@ -0,0 +1,18 @@ +items); + } + + public function toArray(): array { + return $this->items; + } + +} +{% endfor %} diff --git a/modules/phpactor/config/templates/default/SourceCode.php.twig b/modules/phpactor/config/templates/default/SourceCode.php.twig new file mode 100644 index 00000000..86de1d9f --- /dev/null +++ b/modules/phpactor/config/templates/default/SourceCode.php.twig @@ -0,0 +1,10 @@ +> "$XDG_DOCUMENTS_DIR/wiki/2-areas/health-fitness/weight.csv" + + weight + ''; + }; + }; + + flake.modules.homeManager.base = + { pkgs, ... }: + { + home.packages = [ + (withSystem pkgs.system (psArgs: psArgs.config.packages.${name})) + ]; + }; +} diff --git a/modules/scripts/battery.nix b/modules/scripts/battery.nix new file mode 100644 index 00000000..ac1eae3c --- /dev/null +++ b/modules/scripts/battery.nix @@ -0,0 +1,17 @@ +{ + flake.modules.homeManager.gui = + { pkgs, ... }: + { + home.packages = [ + (pkgs.writeShellApplication { + name = "battery"; + + runtimeInputs = with pkgs; [ upower ]; + + text = '' + upower -i /org/freedesktop/UPower/devices/battery_BAT1 | grep -E 'state|to full|percentage' + ''; + }) + ]; + }; +} diff --git a/modules/scripts/build-adoc.nix b/modules/scripts/build-adoc.nix new file mode 100644 index 00000000..703adf51 --- /dev/null +++ b/modules/scripts/build-adoc.nix @@ -0,0 +1,62 @@ +{ + flake.modules.homeManager.base = + { pkgs, ... }: + { + home.packages = [ + (pkgs.writeShellApplication { + name = "build-adoc"; + + runtimeInputs = with pkgs; [ + asciidoctor-with-extensions + ]; + + excludeShellChecks = [ "SC2034" ]; + + text = '' + ls book + + echo "" + + date=$(date '+%Y-%m-%d %H:%M:%S') + + echo "The current date is $date." + + pwd=$(pwd) + parent=$(basename "$(dirname "$pwd")") + name=$(basename "$pwd") + + echo "The parent directory is $parent." + echo "The current directory is $name." + + echo "" + echo "Generating the HTML..." + asciidoctor \ + -D book \ + -a "date=$date" \ + -o index.html \ + ./book/index.adoc + + echo "" + echo "Generating the EPUB..." + asciidoctor-epub3 \ + -D book \ + -a "date=$date" \ + -o "$parent-$name.epub" \ + ./book/index.adoc + + echo "" + echo "Generating the PDF..." + asciidoctor-pdf \ + -D book \ + -a "date=$date" \ + -o "$parent-$name.pdf" \ + ./book/index.adoc + + echo "" + + ls book + ''; + }) + ]; + }; +} diff --git a/modules/scripts/build.nix b/modules/scripts/build.nix new file mode 100644 index 00000000..c04f4664 --- /dev/null +++ b/modules/scripts/build.nix @@ -0,0 +1,16 @@ +{ + flake.modules.homeManager.base = + { pkgs, ... }: + { + home.packages = [ + (pkgs.writeShellApplication { + name = "build"; + + text = '' + test -r book/index.adoc && exec build-adoc "$@" + test -x build && exec ./build "$@" + ''; + }) + ]; + }; +} diff --git a/modules/scripts/clone.nix b/modules/scripts/clone.nix new file mode 100644 index 00000000..36d1574d --- /dev/null +++ b/modules/scripts/clone.nix @@ -0,0 +1,53 @@ +{ withSystem, ... }: + +{ + perSystem = + psArgs@{ pkgs, ... }: + { + packages.clone = pkgs.writeShellApplication { + name = "clone"; + + runtimeInputs = with pkgs; [ + git + psArgs.config.packages.tmux-sessionizer + ]; + + text = '' + repo_url="$1" + repo_url="''${repo_url%.git}" + + if [[ "$repo_url" =~ ^(git@|https://|ssh://forgejo@)?([^:/]+)[:/](.*)/(.*)$ ]]; then + domain="''${BASH_REMATCH[2]}" + + if [[ "$domain" == "ssh.oliverdavies.uk" ]]; then + domain="code.oliverdavies.uk" + fi + + user="''${BASH_REMATCH[3]}" + name="''${BASH_REMATCH[4]}" + + user_path="$XDG_REPOS_DIR/$domain/$user" + repo_path="$user_path/$name" + + [[ -d "$repo_path" ]] && tmux-sessionizer "$repo_path" && exit 0 + + mkdir -pv "$repo_path" + + git clone "$repo_url" "$repo_path" + + tmux-sessionizer "$repo_path" + else + exit 1 + fi + ''; + }; + }; + + flake.modules.homeManager.base = + { pkgs, ... }: + { + home.packages = [ + (withSystem pkgs.system (psArgs: psArgs.config.packages.clone)) + ]; + }; +} diff --git a/modules/scripts/git-save.nix b/modules/scripts/git-save.nix new file mode 100644 index 00000000..423144b1 --- /dev/null +++ b/modules/scripts/git-save.nix @@ -0,0 +1,20 @@ +{ + flake.modules.homeManager.base = + { pkgs, ... }: + { + home.packages = [ + (pkgs.writeShellApplication { + name = "git-save"; + + runtimeInputs = with pkgs; [ git ]; + + text = '' + git status + git add . + git commit -s -m "Automated commit" + git push + ''; + }) + ]; + }; +} diff --git a/modules/scripts/hnow.nix b/modules/scripts/hnow.nix new file mode 100644 index 00000000..58650c03 --- /dev/null +++ b/modules/scripts/hnow.nix @@ -0,0 +1,35 @@ +{ lib, withSystem, ... }: + +let + name = "hnow"; +in +{ + perSystem = + psArgs@{ pkgs, ... }: + let + now = withSystem pkgs.system (psArgs: psArgs.config.packages.now); + in + { + packages.${name} = pkgs.writeShellApplication { + inherit name; + + runtimeInputs = [ + psArgs.config.packages.now + ]; + + text = '' + # Based on https://github.com/rwxrob/dot/blob/main/scripts/hnow. + + echo "== $(${lib.getExe now} "$*")" + ''; + }; + }; + + flake.modules.homeManager.base = + { pkgs, ... }: + { + home.packages = [ + (withSystem pkgs.system (psArgs: psArgs.config.packages.${name})) + ]; + }; +} diff --git a/modules/scripts/now.nix b/modules/scripts/now.nix new file mode 100644 index 00000000..94ad3d31 --- /dev/null +++ b/modules/scripts/now.nix @@ -0,0 +1,32 @@ +{ withSystem, ... }: + +let + name = "now"; +in +{ + perSystem = + { pkgs, ... }: + { + packages.${name} = pkgs.writeShellApplication { + inherit name; + + runtimeInputs = with pkgs; [ coreutils ]; + + text = '' + # Based on https://github.com/rwxrob/dot/blob/main/scripts/now. + + out=$(date "+%A, %B %e, %Y, %R %Z" "-d ''${*:-now}") + + echo "''${out// / }" + ''; + }; + }; + + flake.modules.homeManager.base = + { pkgs, ... }: + { + home.packages = [ + (withSystem pkgs.system (psArgs: psArgs.config.packages.${name})) + ]; + }; +} diff --git a/modules/scripts/open-repo-url.nix b/modules/scripts/open-repo-url.nix new file mode 100644 index 00000000..35e5b5f0 --- /dev/null +++ b/modules/scripts/open-repo-url.nix @@ -0,0 +1,32 @@ +{ withSystem, ... }: + +let + name = "open-repo-url"; +in +{ + perSystem = + { pkgs, ... }: + { + packages.${name} = pkgs.writeShellApplication { + inherit name; + + runtimeInputs = with pkgs; [ coreutils git ]; + + text = '' + repo_url=$(git remote get-url origin | sed -E 's#(git|forgejo)@([A-Za-z0-9.-]+):#https://\2/#;s#.git$##') + + repo_url="''${repo_url//ssh.oliverdavies.uk/code.oliverdavies.uk}" + + xdg-open "$repo_url" + ''; + }; + }; + + flake.modules.homeManager.base = + { pkgs, ... }: + { + home.packages = [ + (withSystem pkgs.system (psArgs: psArgs.config.packages.${name})) + ]; + }; +} diff --git a/modules/scripts/ppp.nix b/modules/scripts/ppp.nix new file mode 100644 index 00000000..17cba13a --- /dev/null +++ b/modules/scripts/ppp.nix @@ -0,0 +1,26 @@ +{ inputs, withSystem, ... }: + +let + name = "ppp"; +in +{ + perSystem = + { pkgs, ... }: + { + packages.${name} = pkgs.writeShellApplication { + inherit name; + + runtimeInputs = with pkgs; [ coreutils ]; + + text = builtins.readFile "${inputs.rwxrob-dot}/scripts/${name}"; + }; + }; + + flake.modules.homeManager.base = + { pkgs, ... }: + { + home.packages = [ + (withSystem pkgs.system (psArgs: psArgs.config.packages.${name})) + ]; + }; +} diff --git a/modules/scripts/preview.nix b/modules/scripts/preview.nix new file mode 100644 index 00000000..7a77187b --- /dev/null +++ b/modules/scripts/preview.nix @@ -0,0 +1,24 @@ +{ + flake.modules.homeManager.base = + { pkgs, ... }: + { + home.packages = [ + (pkgs.writeShellApplication { + name = "preview"; + + runtimeInputs = with pkgs.nodePackages; [ browser-sync ]; + + text = '' + # Based on https://github.com/rwxrob/dot/blob/main/scripts/preview. + + browser-sync start \ + --ignore '**/.*' \ + --no-notify \ + --no-open \ + --no-ui \ + -sw + ''; + }) + ]; + }; +} diff --git a/modules/scripts/tmux-sessionizer/default.nix b/modules/scripts/tmux-sessionizer/default.nix new file mode 100644 index 00000000..8f4513b5 --- /dev/null +++ b/modules/scripts/tmux-sessionizer/default.nix @@ -0,0 +1,30 @@ +{ + flake.modules.homeManager.base = + { config, pkgs, ... }: + { + home.file.".tmux-sessionizer".source = "${ + pkgs.writeShellApplication { + name = ".tmux-sessionizer"; + + runtimeInputs = with pkgs; [ + tmux + ]; + + text = '' + set +o errexit + set +o nounset + + if [[ "$PWD" == "${config.xdg.userDirs.extraConfig.XDG_REPOS_DIR}/os" || "$PWD" == "${config.xdg.userDirs.extraConfig.XDG_REPOS_DIR}/personal" || "$PWD" == "${config.xdg.userDirs.extraConfig.XDG_REPOS_DIR}/work" ]]; then + clear + + return + fi + + tmux new-window -d -n scratch + nvim . + clear + ''; + } + }/bin/.tmux-sessionizer"; + }; +} diff --git a/modules/scripts/tmux-sessionizer/package.nix b/modules/scripts/tmux-sessionizer/package.nix new file mode 100644 index 00000000..7c0cfb9c --- /dev/null +++ b/modules/scripts/tmux-sessionizer/package.nix @@ -0,0 +1,89 @@ +{ withSystem, ... }: + +{ + perSystem = + { pkgs, ... }: + { + packages.tmux-sessionizer = pkgs.writeShellApplication { + name = "tmux-sessionizer"; + + runtimeInputs = with pkgs; [ + coreutils + fzf + tmux + ]; + + text = '' + set -euo pipefail + + # Based on https://github.com/jessarcher/dotfiles/blob/master/scripts/t + # and https://github.com/ThePrimeagen/tmux-sessionizer. + + has_session() { + tmux list-sessions | grep -q "^$1:" + } + + hydrate() { + if [ -f "$2/.tmux-sessionizer" ]; then + tmux send-keys -t "$1" "source $2/.tmux-sessionizer" c-M + elif [ -f "$HOME/.tmux-sessionizer" ]; then + tmux send-keys -t "$1" "source $HOME/.tmux-sessionizer" c-M + fi + } + + is_tmux_running() { + tmux_running=$(pgrep tmux) + + if [[ -z ''${TMUX:-} ]] && [[ -z $tmux_running ]]; then + return 1 + fi + + return 0 + } + + switch_to() { + tmux attach-session -t "$1" || tmux switch-client -t "$1" + } + + if [[ $# -eq 1 ]]; then + selected=$1 + else + items=$( + find "$HOME/Code" -maxdepth 3 -mindepth 1 -type d + find "$HOME/Documents" -maxdepth 1 -mindepth 1 -type d + find "$HOME/tmp" -maxdepth 1 -type d + ) + + selected=$(echo "$items" | sed "s|^$HOME/||" | sort | fzf) + [[ $selected ]] && selected="$HOME/$selected" + fi + + if [[ -z $selected ]]; then + exit 0 + fi + + selected_name=$(basename "$selected" | tr . _) + + if ! is_tmux_running; then + tmux new-session -ds "$selected_name" -c "$selected" + hydrate "$selected_name" "$selected" + fi + + if ! has_session "$selected_name"; then + tmux new-session -ds "$selected_name" -c "$selected" + hydrate "$selected_name" "$selected" + fi + + switch_to "$selected_name" + ''; + }; + }; + + flake.modules.homeManager.base = + { pkgs, ... }: + { + home.packages = [ + (withSystem pkgs.system (psArgs: psArgs.config.packages.tmux-sessionizer)) + ]; + }; +} diff --git a/modules/scripts/today.nix b/modules/scripts/today.nix new file mode 100644 index 00000000..1abbee1f --- /dev/null +++ b/modules/scripts/today.nix @@ -0,0 +1,26 @@ +{ withSystem, ... }: + +let + name = "today"; +in +{ + perSystem = + { pkgs, ... }: + { + packages.${name} = pkgs.writeShellApplication { + inherit name; + + runtimeInputs = with pkgs; [ coreutils ]; + + text = ''date "+%x"''; + }; + }; + + flake.modules.homeManager.base = + { pkgs, ... }: + { + home.packages = [ + (withSystem pkgs.system (psArgs: psArgs.config.packages.${name})) + ]; + }; +} diff --git a/modules/scripts/today2.nix b/modules/scripts/today2.nix new file mode 100644 index 00000000..90a76c59 --- /dev/null +++ b/modules/scripts/today2.nix @@ -0,0 +1,26 @@ +{ withSystem, ... }: + +let + name = "today2"; +in +{ + perSystem = + { pkgs, ... }: + { + packages.${name} = pkgs.writeShellApplication { + inherit name; + + runtimeInputs = with pkgs; [ coreutils ]; + + text = ''date "+%F"''; + }; + }; + + flake.modules.homeManager.base = + { pkgs, ... }: + { + home.packages = [ + (withSystem pkgs.system (psArgs: psArgs.config.packages.${name})) + ]; + }; +} diff --git a/modules/scripts/todo.nix b/modules/scripts/todo.nix new file mode 100644 index 00000000..22c4c0c4 --- /dev/null +++ b/modules/scripts/todo.nix @@ -0,0 +1,28 @@ +{ withSystem, ... }: + +let + name = "todo"; +in +{ + perSystem = + { pkgs, ... }: + { + packages.${name} = pkgs.writeShellApplication { + inherit name; + + runtimeInputs = with pkgs; [ coreutils ]; + + text = ''"$EDITOR" +3 "$TODO_FILE"''; + }; + }; + + flake.modules.homeManager.base = + { config, pkgs, ... }: + { + home.packages = [ + (withSystem pkgs.system (psArgs: psArgs.config.packages.${name})) + ]; + + home.sessionVariables.TODO_FILE = "${config.home.sessionVariables.WIKI_DIRECTORY}/todo.adoc"; + }; +} diff --git a/modules/scripts/weight.nix b/modules/scripts/weight.nix new file mode 100644 index 00000000..4c63f47c --- /dev/null +++ b/modules/scripts/weight.nix @@ -0,0 +1,28 @@ +{ withSystem, ... }: + +let + name = "weight"; +in +{ + perSystem = + { pkgs, ... }: + { + packages.${name} = pkgs.writeShellApplication { + inherit name; + + runtimeInputs = with pkgs; [ + coreutils + ]; + + text = ''tail "$XDG_DOCUMENTS_DIR/wiki/2-areas/health-fitness/weight.csv"''; + }; + }; + + flake.modules.homeManager.base = + { pkgs, ... }: + { + home.packages = [ + (withSystem pkgs.system (psArgs: psArgs.config.packages.${name})) + ]; + }; +} diff --git a/modules/scripts/zet.nix b/modules/scripts/zet.nix new file mode 100644 index 00000000..4630d2fb --- /dev/null +++ b/modules/scripts/zet.nix @@ -0,0 +1,37 @@ +{ inputs, withSystem, ... }: + +let + name = "zet"; +in +{ + perSystem = + { pkgs, ... }: + { + packages.${name} = pkgs.writeShellApplication { + inherit name; + + bashOptions = [ "pipefail" ]; + + runtimeInputs = with pkgs; [ + bashInteractive + coreutils + fzf + git + ]; + + text = builtins.readFile "${inputs.zet}/${name}"; + }; + }; + + flake.modules.homeManager.base = + { config, pkgs, ... }: + { + home.packages = [ + (withSystem pkgs.system (psArgs: psArgs.config.packages.${name})) + ]; + + home.sessionVariables = { + ZET_DIR = "${config.xdg.userDirs.documents}/zet"; + }; + }; +} diff --git a/modules/sound/pipewire/alsa.nix b/modules/sound/pipewire/alsa.nix new file mode 100644 index 00000000..929b07c4 --- /dev/null +++ b/modules/sound/pipewire/alsa.nix @@ -0,0 +1,6 @@ +{ + flake.modules.nixos.desktop.services.pipewire.alsa = { + enable = true; + support32Bit = true; + }; +} diff --git a/modules/sound/pipewire/enable.nix b/modules/sound/pipewire/enable.nix new file mode 100644 index 00000000..3160292b --- /dev/null +++ b/modules/sound/pipewire/enable.nix @@ -0,0 +1,3 @@ +{ + flake.modules.nixos.pc.services.pipewire.enable = true; +} diff --git a/modules/sound/pipewire/pulse.nix b/modules/sound/pipewire/pulse.nix new file mode 100644 index 00000000..c3ee1c25 --- /dev/null +++ b/modules/sound/pipewire/pulse.nix @@ -0,0 +1,3 @@ +{ + flake.modules.nixos.pc.services.pipewire.pulse.enable = true; +} diff --git a/modules/st.nix b/modules/st.nix new file mode 100644 index 00000000..09d393dd --- /dev/null +++ b/modules/st.nix @@ -0,0 +1,365 @@ +{ + flake.modules.homeManager.gui = + { pkgs, ... }: + { + home.packages = with pkgs; [ + (st.override { + conf = '' + static char *font = "MesloLGSNerdFontMono:pixelsize=16:antialias=true:autohint=true"; + + int disablebold = 1; + int disableitalic = 1; + int disableroman = 1; + + static int borderpx = 2; + + static char *shell = "/bin/sh"; + char *utmp = NULL; + char *scroll = NULL; + char *stty_args = "stty raw pass8 nl -echo -iexten -cstopb 38400"; + + char *vtiden = "\033[?6c"; + + static float cwscale = 1.0; + static float chscale = 1.0; + + wchar_t *worddelimiters = L" "; + + static unsigned int doubleclicktimeout = 300; + static unsigned int tripleclicktimeout = 600; + + int allowaltscreen = 1; + + int allowwindowops = 0; + + static double minlatency = 2; + static double maxlatency = 33; + + static unsigned int blinktimeout = 800; + + static unsigned int cursorthickness = 2; + + static int bellvolume = 0; + + char *termname = "st-256color"; + + unsigned int tabspaces = 8; + + static const char *colorname[] = { + "black", + "red3", + "green3", + "yellow3", + "blue2", + "magenta3", + "cyan3", + "gray90", + + "gray50", + "red", + "green", + "yellow", + "#5c5cff", + "magenta", + "cyan", + "white", + + [255] = 0, + + "#cccccc", + "#555555", + "gray90", + "black", + }; + + unsigned int defaultfg = 258; + unsigned int defaultbg = 259; + unsigned int defaultcs = 256; + static unsigned int defaultrcs = 257; + + static unsigned int cursorshape = 2; + + static unsigned int cols = 80; + static unsigned int rows = 24; + + static unsigned int mouseshape = XC_xterm; + static unsigned int mousefg = 7; + static unsigned int mousebg = 0; + + static unsigned int defaultattr = 11; + + static uint forcemousemod = ShiftMask; + + static MouseShortcut mshortcuts[] = { + { XK_ANY_MOD, Button2, selpaste, {.i = 0}, 1 }, + { ShiftMask, Button4, ttysend, {.s = "\033[5;2~"} }, + { XK_ANY_MOD, Button4, ttysend, {.s = "\031"} }, + { ShiftMask, Button5, ttysend, {.s = "\033[6;2~"} }, + { XK_ANY_MOD, Button5, ttysend, {.s = "\005"} }, + }; + + #define MODKEY Mod1Mask + #define TERMMOD (ControlMask|ShiftMask) + + static Shortcut shortcuts[] = { + { XK_ANY_MOD, XK_Break, sendbreak, {.i = 0} }, + { ControlMask, XK_Print, toggleprinter, {.i = 0} }, + { ShiftMask, XK_Print, printscreen, {.i = 0} }, + { XK_ANY_MOD, XK_Print, printsel, {.i = 0} }, + { TERMMOD, XK_Prior, zoom, {.f = +1} }, + { TERMMOD, XK_Next, zoom, {.f = -1} }, + { TERMMOD, XK_Home, zoomreset, {.f = 0} }, + { TERMMOD, XK_C, clipcopy, {.i = 0} }, + { TERMMOD, XK_D, zoom, {.f = -2} }, + { TERMMOD, XK_J, zoom, {.f = -1} }, + { TERMMOD, XK_K, zoom, {.f = +1} }, + { TERMMOD, XK_U, zoom, {.f = +2} }, + { TERMMOD, XK_V, clippaste, {.i = 0} }, + { TERMMOD, XK_Y, selpaste, {.i = 0} }, + { ShiftMask, XK_Insert, selpaste, {.i = 0} }, + { TERMMOD, XK_Num_Lock, numlock, {.i = 0} }, + }; + + static KeySym mappedkeys[] = { -1 }; + + static uint ignoremod = Mod2Mask|XK_SWITCH_MOD; + + static Key key[] = { + { XK_KP_Home, ShiftMask, "\033[2J", 0, -1}, + { XK_KP_Home, ShiftMask, "\033[1;2H", 0, +1}, + { XK_KP_Home, XK_ANY_MOD, "\033[H", 0, -1}, + { XK_KP_Home, XK_ANY_MOD, "\033[1~", 0, +1}, + { XK_KP_Up, XK_ANY_MOD, "\033Ox", +1, 0}, + { XK_KP_Up, XK_ANY_MOD, "\033[A", 0, -1}, + { XK_KP_Up, XK_ANY_MOD, "\033OA", 0, +1}, + { XK_KP_Down, XK_ANY_MOD, "\033Or", +1, 0}, + { XK_KP_Down, XK_ANY_MOD, "\033[B", 0, -1}, + { XK_KP_Down, XK_ANY_MOD, "\033OB", 0, +1}, + { XK_KP_Left, XK_ANY_MOD, "\033Ot", +1, 0}, + { XK_KP_Left, XK_ANY_MOD, "\033[D", 0, -1}, + { XK_KP_Left, XK_ANY_MOD, "\033OD", 0, +1}, + { XK_KP_Right, XK_ANY_MOD, "\033Ov", +1, 0}, + { XK_KP_Right, XK_ANY_MOD, "\033[C", 0, -1}, + { XK_KP_Right, XK_ANY_MOD, "\033OC", 0, +1}, + { XK_KP_Prior, ShiftMask, "\033[5;2~", 0, 0}, + { XK_KP_Prior, XK_ANY_MOD, "\033[5~", 0, 0}, + { XK_KP_Begin, XK_ANY_MOD, "\033[E", 0, 0}, + { XK_KP_End, ControlMask, "\033[J", -1, 0}, + { XK_KP_End, ControlMask, "\033[1;5F", +1, 0}, + { XK_KP_End, ShiftMask, "\033[K", -1, 0}, + { XK_KP_End, ShiftMask, "\033[1;2F", +1, 0}, + { XK_KP_End, XK_ANY_MOD, "\033[4~", 0, 0}, + { XK_KP_Next, ShiftMask, "\033[6;2~", 0, 0}, + { XK_KP_Next, XK_ANY_MOD, "\033[6~", 0, 0}, + { XK_KP_Insert, ShiftMask, "\033[2;2~", +1, 0}, + { XK_KP_Insert, ShiftMask, "\033[4l", -1, 0}, + { XK_KP_Insert, ControlMask, "\033[L", -1, 0}, + { XK_KP_Insert, ControlMask, "\033[2;5~", +1, 0}, + { XK_KP_Insert, XK_ANY_MOD, "\033[4h", -1, 0}, + { XK_KP_Insert, XK_ANY_MOD, "\033[2~", +1, 0}, + { XK_KP_Delete, ControlMask, "\033[M", -1, 0}, + { XK_KP_Delete, ControlMask, "\033[3;5~", +1, 0}, + { XK_KP_Delete, ShiftMask, "\033[2K", -1, 0}, + { XK_KP_Delete, ShiftMask, "\033[3;2~", +1, 0}, + { XK_KP_Delete, XK_ANY_MOD, "\033[P", -1, 0}, + { XK_KP_Delete, XK_ANY_MOD, "\033[3~", +1, 0}, + { XK_KP_Multiply, XK_ANY_MOD, "\033Oj", +2, 0}, + { XK_KP_Add, XK_ANY_MOD, "\033Ok", +2, 0}, + { XK_KP_Enter, XK_ANY_MOD, "\033OM", +2, 0}, + { XK_KP_Enter, XK_ANY_MOD, "\r", -1, 0}, + { XK_KP_Subtract, XK_ANY_MOD, "\033Om", +2, 0}, + { XK_KP_Decimal, XK_ANY_MOD, "\033On", +2, 0}, + { XK_KP_Divide, XK_ANY_MOD, "\033Oo", +2, 0}, + { XK_KP_0, XK_ANY_MOD, "\033Op", +2, 0}, + { XK_KP_1, XK_ANY_MOD, "\033Oq", +2, 0}, + { XK_KP_2, XK_ANY_MOD, "\033Or", +2, 0}, + { XK_KP_3, XK_ANY_MOD, "\033Os", +2, 0}, + { XK_KP_4, XK_ANY_MOD, "\033Ot", +2, 0}, + { XK_KP_5, XK_ANY_MOD, "\033Ou", +2, 0}, + { XK_KP_6, XK_ANY_MOD, "\033Ov", +2, 0}, + { XK_KP_7, XK_ANY_MOD, "\033Ow", +2, 0}, + { XK_KP_8, XK_ANY_MOD, "\033Ox", +2, 0}, + { XK_KP_9, XK_ANY_MOD, "\033Oy", +2, 0}, + { XK_Up, ShiftMask, "\033[1;2A", 0, 0}, + { XK_Up, Mod1Mask, "\033[1;3A", 0, 0}, + { XK_Up, ShiftMask|Mod1Mask, "\033[1;4A", 0, 0}, + { XK_Up, ControlMask, "\033[1;5A", 0, 0}, + { XK_Up, ShiftMask|ControlMask, "\033[1;6A", 0, 0}, + { XK_Up, ControlMask|Mod1Mask, "\033[1;7A", 0, 0}, + { XK_Up, ShiftMask|ControlMask|Mod1Mask, "\033[1;8A", 0, 0}, + { XK_Up, XK_ANY_MOD, "\033[A", 0, -1}, + { XK_Up, XK_ANY_MOD, "\033OA", 0, +1}, + { XK_Down, ShiftMask, "\033[1;2B", 0, 0}, + { XK_Down, Mod1Mask, "\033[1;3B", 0, 0}, + { XK_Down, ShiftMask|Mod1Mask, "\033[1;4B", 0, 0}, + { XK_Down, ControlMask, "\033[1;5B", 0, 0}, + { XK_Down, ShiftMask|ControlMask, "\033[1;6B", 0, 0}, + { XK_Down, ControlMask|Mod1Mask, "\033[1;7B", 0, 0}, + { XK_Down, ShiftMask|ControlMask|Mod1Mask, "\033[1;8B", 0, 0}, + { XK_Down, XK_ANY_MOD, "\033[B", 0, -1}, + { XK_Down, XK_ANY_MOD, "\033OB", 0, +1}, + { XK_Left, ShiftMask, "\033[1;2D", 0, 0}, + { XK_Left, Mod1Mask, "\033[1;3D", 0, 0}, + { XK_Left, ShiftMask|Mod1Mask, "\033[1;4D", 0, 0}, + { XK_Left, ControlMask, "\033[1;5D", 0, 0}, + { XK_Left, ShiftMask|ControlMask, "\033[1;6D", 0, 0}, + { XK_Left, ControlMask|Mod1Mask, "\033[1;7D", 0, 0}, + { XK_Left, ShiftMask|ControlMask|Mod1Mask, "\033[1;8D", 0, 0}, + { XK_Left, XK_ANY_MOD, "\033[D", 0, -1}, + { XK_Left, XK_ANY_MOD, "\033OD", 0, +1}, + { XK_Right, ShiftMask, "\033[1;2C", 0, 0}, + { XK_Right, Mod1Mask, "\033[1;3C", 0, 0}, + { XK_Right, ShiftMask|Mod1Mask, "\033[1;4C", 0, 0}, + { XK_Right, ControlMask, "\033[1;5C", 0, 0}, + { XK_Right, ShiftMask|ControlMask, "\033[1;6C", 0, 0}, + { XK_Right, ControlMask|Mod1Mask, "\033[1;7C", 0, 0}, + { XK_Right, ShiftMask|ControlMask|Mod1Mask, "\033[1;8C", 0, 0}, + { XK_Right, XK_ANY_MOD, "\033[C", 0, -1}, + { XK_Right, XK_ANY_MOD, "\033OC", 0, +1}, + { XK_ISO_Left_Tab, ShiftMask, "\033[Z", 0, 0}, + { XK_Return, Mod1Mask, "\033\r", 0, 0}, + { XK_Return, XK_ANY_MOD, "\r", 0, 0}, + { XK_Insert, ShiftMask, "\033[4l", -1, 0}, + { XK_Insert, ShiftMask, "\033[2;2~", +1, 0}, + { XK_Insert, ControlMask, "\033[L", -1, 0}, + { XK_Insert, ControlMask, "\033[2;5~", +1, 0}, + { XK_Insert, XK_ANY_MOD, "\033[4h", -1, 0}, + { XK_Insert, XK_ANY_MOD, "\033[2~", +1, 0}, + { XK_Delete, ControlMask, "\033[M", -1, 0}, + { XK_Delete, ControlMask, "\033[3;5~", +1, 0}, + { XK_Delete, ShiftMask, "\033[2K", -1, 0}, + { XK_Delete, ShiftMask, "\033[3;2~", +1, 0}, + { XK_Delete, XK_ANY_MOD, "\033[P", -1, 0}, + { XK_Delete, XK_ANY_MOD, "\033[3~", +1, 0}, + { XK_BackSpace, XK_NO_MOD, "\177", 0, 0}, + { XK_BackSpace, Mod1Mask, "\033\177", 0, 0}, + { XK_Home, ShiftMask, "\033[2J", 0, -1}, + { XK_Home, ShiftMask, "\033[1;2H", 0, +1}, + { XK_Home, XK_ANY_MOD, "\033[H", 0, -1}, + { XK_Home, XK_ANY_MOD, "\033[1~", 0, +1}, + { XK_End, ControlMask, "\033[J", -1, 0}, + { XK_End, ControlMask, "\033[1;5F", +1, 0}, + { XK_End, ShiftMask, "\033[K", -1, 0}, + { XK_End, ShiftMask, "\033[1;2F", +1, 0}, + { XK_End, XK_ANY_MOD, "\033[4~", 0, 0}, + { XK_Prior, ControlMask, "\033[5;5~", 0, 0}, + { XK_Prior, ShiftMask, "\033[5;2~", 0, 0}, + { XK_Prior, XK_ANY_MOD, "\033[5~", 0, 0}, + { XK_Next, ControlMask, "\033[6;5~", 0, 0}, + { XK_Next, ShiftMask, "\033[6;2~", 0, 0}, + { XK_Next, XK_ANY_MOD, "\033[6~", 0, 0}, + { XK_F1, XK_NO_MOD, "\033OP" , 0, 0}, + { XK_F1, /* F13 */ ShiftMask, "\033[1;2P", 0, 0}, + { XK_F1, /* F25 */ ControlMask, "\033[1;5P", 0, 0}, + { XK_F1, /* F37 */ Mod4Mask, "\033[1;6P", 0, 0}, + { XK_F1, /* F49 */ Mod1Mask, "\033[1;3P", 0, 0}, + { XK_F1, /* F61 */ Mod3Mask, "\033[1;4P", 0, 0}, + { XK_F2, XK_NO_MOD, "\033OQ" , 0, 0}, + { XK_F2, /* F14 */ ShiftMask, "\033[1;2Q", 0, 0}, + { XK_F2, /* F26 */ ControlMask, "\033[1;5Q", 0, 0}, + { XK_F2, /* F38 */ Mod4Mask, "\033[1;6Q", 0, 0}, + { XK_F2, /* F50 */ Mod1Mask, "\033[1;3Q", 0, 0}, + { XK_F2, /* F62 */ Mod3Mask, "\033[1;4Q", 0, 0}, + { XK_F3, XK_NO_MOD, "\033OR" , 0, 0}, + { XK_F3, /* F15 */ ShiftMask, "\033[1;2R", 0, 0}, + { XK_F3, /* F27 */ ControlMask, "\033[1;5R", 0, 0}, + { XK_F3, /* F39 */ Mod4Mask, "\033[1;6R", 0, 0}, + { XK_F3, /* F51 */ Mod1Mask, "\033[1;3R", 0, 0}, + { XK_F3, /* F63 */ Mod3Mask, "\033[1;4R", 0, 0}, + { XK_F4, XK_NO_MOD, "\033OS" , 0, 0}, + { XK_F4, /* F16 */ ShiftMask, "\033[1;2S", 0, 0}, + { XK_F4, /* F28 */ ControlMask, "\033[1;5S", 0, 0}, + { XK_F4, /* F40 */ Mod4Mask, "\033[1;6S", 0, 0}, + { XK_F4, /* F52 */ Mod1Mask, "\033[1;3S", 0, 0}, + { XK_F5, XK_NO_MOD, "\033[15~", 0, 0}, + { XK_F5, /* F17 */ ShiftMask, "\033[15;2~", 0, 0}, + { XK_F5, /* F29 */ ControlMask, "\033[15;5~", 0, 0}, + { XK_F5, /* F41 */ Mod4Mask, "\033[15;6~", 0, 0}, + { XK_F5, /* F53 */ Mod1Mask, "\033[15;3~", 0, 0}, + { XK_F6, XK_NO_MOD, "\033[17~", 0, 0}, + { XK_F6, /* F18 */ ShiftMask, "\033[17;2~", 0, 0}, + { XK_F6, /* F30 */ ControlMask, "\033[17;5~", 0, 0}, + { XK_F6, /* F42 */ Mod4Mask, "\033[17;6~", 0, 0}, + { XK_F6, /* F54 */ Mod1Mask, "\033[17;3~", 0, 0}, + { XK_F7, XK_NO_MOD, "\033[18~", 0, 0}, + { XK_F7, /* F19 */ ShiftMask, "\033[18;2~", 0, 0}, + { XK_F7, /* F31 */ ControlMask, "\033[18;5~", 0, 0}, + { XK_F7, /* F43 */ Mod4Mask, "\033[18;6~", 0, 0}, + { XK_F7, /* F55 */ Mod1Mask, "\033[18;3~", 0, 0}, + { XK_F8, XK_NO_MOD, "\033[19~", 0, 0}, + { XK_F8, /* F20 */ ShiftMask, "\033[19;2~", 0, 0}, + { XK_F8, /* F32 */ ControlMask, "\033[19;5~", 0, 0}, + { XK_F8, /* F44 */ Mod4Mask, "\033[19;6~", 0, 0}, + { XK_F8, /* F56 */ Mod1Mask, "\033[19;3~", 0, 0}, + { XK_F9, XK_NO_MOD, "\033[20~", 0, 0}, + { XK_F9, /* F21 */ ShiftMask, "\033[20;2~", 0, 0}, + { XK_F9, /* F33 */ ControlMask, "\033[20;5~", 0, 0}, + { XK_F9, /* F45 */ Mod4Mask, "\033[20;6~", 0, 0}, + { XK_F9, /* F57 */ Mod1Mask, "\033[20;3~", 0, 0}, + { XK_F10, XK_NO_MOD, "\033[21~", 0, 0}, + { XK_F10, /* F22 */ ShiftMask, "\033[21;2~", 0, 0}, + { XK_F10, /* F34 */ ControlMask, "\033[21;5~", 0, 0}, + { XK_F10, /* F46 */ Mod4Mask, "\033[21;6~", 0, 0}, + { XK_F10, /* F58 */ Mod1Mask, "\033[21;3~", 0, 0}, + { XK_F11, XK_NO_MOD, "\033[23~", 0, 0}, + { XK_F11, /* F23 */ ShiftMask, "\033[23;2~", 0, 0}, + { XK_F11, /* F35 */ ControlMask, "\033[23;5~", 0, 0}, + { XK_F11, /* F47 */ Mod4Mask, "\033[23;6~", 0, 0}, + { XK_F11, /* F59 */ Mod1Mask, "\033[23;3~", 0, 0}, + { XK_F12, XK_NO_MOD, "\033[24~", 0, 0}, + { XK_F12, /* F24 */ ShiftMask, "\033[24;2~", 0, 0}, + { XK_F12, /* F36 */ ControlMask, "\033[24;5~", 0, 0}, + { XK_F12, /* F48 */ Mod4Mask, "\033[24;6~", 0, 0}, + { XK_F12, /* F60 */ Mod1Mask, "\033[24;3~", 0, 0}, + { XK_F13, XK_NO_MOD, "\033[1;2P", 0, 0}, + { XK_F14, XK_NO_MOD, "\033[1;2Q", 0, 0}, + { XK_F15, XK_NO_MOD, "\033[1;2R", 0, 0}, + { XK_F16, XK_NO_MOD, "\033[1;2S", 0, 0}, + { XK_F17, XK_NO_MOD, "\033[15;2~", 0, 0}, + { XK_F18, XK_NO_MOD, "\033[17;2~", 0, 0}, + { XK_F19, XK_NO_MOD, "\033[18;2~", 0, 0}, + { XK_F20, XK_NO_MOD, "\033[19;2~", 0, 0}, + { XK_F21, XK_NO_MOD, "\033[20;2~", 0, 0}, + { XK_F22, XK_NO_MOD, "\033[21;2~", 0, 0}, + { XK_F23, XK_NO_MOD, "\033[23;2~", 0, 0}, + { XK_F24, XK_NO_MOD, "\033[24;2~", 0, 0}, + { XK_F25, XK_NO_MOD, "\033[1;5P", 0, 0}, + { XK_F26, XK_NO_MOD, "\033[1;5Q", 0, 0}, + { XK_F27, XK_NO_MOD, "\033[1;5R", 0, 0}, + { XK_F28, XK_NO_MOD, "\033[1;5S", 0, 0}, + { XK_F29, XK_NO_MOD, "\033[15;5~", 0, 0}, + { XK_F30, XK_NO_MOD, "\033[17;5~", 0, 0}, + { XK_F31, XK_NO_MOD, "\033[18;5~", 0, 0}, + { XK_F32, XK_NO_MOD, "\033[19;5~", 0, 0}, + { XK_F33, XK_NO_MOD, "\033[20;5~", 0, 0}, + { XK_F34, XK_NO_MOD, "\033[21;5~", 0, 0}, + { XK_F35, XK_NO_MOD, "\033[23;5~", 0, 0}, + }; + + static uint selmasks[] = { + [SEL_RECTANGULAR] = Mod1Mask, + }; + + static char ascii_printable[] = + " !\"#$%&'()*+,-./0123456789:;<=>?" + "@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_" + "`abcdefghijklmnopqrstuvwxyz{|}~"; + ''; + + patches = [ + (fetchpatch { + name = "disable_bold_italic_fonts"; + url = "https://st.suckless.org/patches/disable_bold_italic_fonts/st-disable-bold-italic-fonts-0.8.2.diff"; + sha256 = "PG96QMqbX3Fr0EvDmF4lm/J3gj18eyBfm1bJ3M7plvQ="; + }) + + (fetchpatch { + name = "anysize"; + url = "https://st.suckless.org/patches/anysize/st-anysize-20220718-baa9357.diff"; + sha256 = "yx9VSwmPACx3EN3CAdQkxeoJKJxQ6ziC9tpBcoWuWHc="; + }) + ]; + }) + ]; + }; +} diff --git a/modules/starship/format.nix b/modules/starship/format.nix new file mode 100644 index 00000000..eeed3818 --- /dev/null +++ b/modules/starship/format.nix @@ -0,0 +1,27 @@ +{ lib, ... }: + +{ + # https://starship.rs/config/#prompt + flake.modules.homeManager.base.programs.starship.settings.format = lib.concatStringsSep "" [ + "\n" + "$username" + "$hostname" + "$directory" + "$vcsh" + "$git_branch" + "$git_status" + "$git_metrics" + "$docker_context" + "$nodejs" + "$php" + "$terraform" + "$nix_shell" + "$direnv" + "\${custom.mob}" + "$memory_usage" + "$cmd_duration" + "$lua" + "$status" + "$character" + ]; +} diff --git a/modules/starship/mob.nix b/modules/starship/mob.nix new file mode 100644 index 00000000..fd59ab88 --- /dev/null +++ b/modules/starship/mob.nix @@ -0,0 +1,7 @@ +{ + flake.modules.homeManager.base.programs.starship.settings.custom.mob = { + command = "echo $MOB_TIMER_ROOM"; + format = "[($output)]($style) "; + when = "[[ -v MOB_TIMER_ROOM ]]"; + }; +} diff --git a/modules/starship/newline.nix b/modules/starship/newline.nix new file mode 100644 index 00000000..80920b5a --- /dev/null +++ b/modules/starship/newline.nix @@ -0,0 +1,3 @@ +{ + flake.modules.homeManager.base.programs.starship.settings.add_newline = false; +} diff --git a/modules/starship/settings.nix b/modules/starship/settings.nix new file mode 100644 index 00000000..26b1efe7 --- /dev/null +++ b/modules/starship/settings.nix @@ -0,0 +1,133 @@ +{ + flake.modules.homeManager.base.programs.starship.settings = { + cmd_duration.disabled = true; + direnv.disabled = false; + directory.format = "[$path]($style) "; + git_status.disabled = true; + nix_shell.disabled = true; + nodejs.disabled = true; + php.disabled = true; + username.disabled = true; + + # https://starship.rs/presets/plain-text + aws.symbol = "aws "; + azure.symbol = "az "; + bun.symbol = "bun "; + c.symbol = "C "; + character = { + success_symbol = "[>](bold green)"; + error_symbol = "[x](bold red)"; + vimcmd_symbol = "[<](bold green)"; + }; + cobol.symbol = "cobol "; + conda.symbol = "conda "; + crystal.symbol = "cr "; + cmake.symbol = "cmake "; + daml.symbol = "daml "; + dart.symbol = "dart "; + deno.symbol = "deno "; + dotnet.symbol = ".NET "; + directory.read_only = " ro"; + docker_context.symbol = "docker "; + elixir.symbol = "exs "; + elm.symbol = "elm "; + fennel.symbol = "fnl "; + fossil_branch.symbol = "fossil "; + gcloud.symbol = "gcp "; + git_branch.symbol = "git "; + git_commit.tag_symbol = " tag "; + git_status = { + ahead = ">"; + behind = "<"; + diverged = "<>"; + renamed = "r"; + deleted = "x"; + }; + gleam.symbol = "gleam "; + golang.symbol = "go "; + gradle.symbol = "gradle "; + guix_shell.symbol = "guix "; + hg_branch.symbol = "hg "; + java.symbol = "java "; + julia.symbol = "jl "; + kotlin.symbol = "kt "; + lua.symbol = "lua "; + nodejs.symbol = "nodejs "; + memory_usage.symbol = "memory "; + meson.symbol = "meson "; + nats.symbol = "nats "; + nim.symbol = "nim "; + nix_shell.symbol = "nix "; + ocaml.symbol = "ml "; + opa.symbol = "opa "; + os.symbols = { + AIX = "aix "; + Alpaquita = "alq "; + AlmaLinux = "alma "; + Alpine = "alp "; + Amazon = "amz "; + Android = "andr "; + Arch = "rch "; + Artix = "atx "; + CentOS = "cent "; + Debian = "deb "; + DragonFly = "dfbsd "; + Emscripten = "emsc "; + EndeavourOS = "ndev "; + Fedora = "fed "; + FreeBSD = "fbsd "; + Garuda = "garu "; + Gentoo = "gent "; + HardenedBSD = "hbsd "; + Illumos = "lum "; + Kali = "kali "; + Linux = "lnx "; + Mabox = "mbox "; + Macos = "mac "; + Manjaro = "mjo "; + Mariner = "mrn "; + MidnightBSD = "mid "; + Mint = "mint "; + NetBSD = "nbsd "; + NixOS = "nix "; + OpenBSD = "obsd "; + OpenCloudOS = "ocos "; + openEuler = "oeul "; + openSUSE = "osuse "; + OracleLinux = "orac "; + Pop = "pop "; + Raspbian = "rasp "; + Redhat = "rhl "; + RedHatEnterprise = "rhel "; + RockyLinux = "rky "; + Redox = "redox "; + Solus = "sol "; + SUSE = "suse "; + Ubuntu = "ubnt "; + Ultramarine = "ultm "; + Unknown = "unk "; + Void = "void "; + Windows = "win "; + }; + package.symbol = "pkg "; + perl.symbol = "pl "; + php.symbol = "php "; + pijul_channel.symbol = "pijul "; + pulumi.symbol = "pulumi "; + purescript.symbol = "purs "; + python.symbol = "py "; + quarto.symbol = "quarto "; + raku.symbol = "raku "; + ruby.symbol = "rb "; + rust.symbol = "rs "; + scala.symbol = "scala "; + spack.symbol = "spack "; + solidity.symbol = "solidity "; + status.symbol = "[x](bold red) "; + sudo.symbol = "sudo "; + swift.symbol = "swift "; + typst.symbol = "typst "; + terraform.symbol = "terraform "; + zig.symbol = "zig "; + }; +} diff --git a/modules/starship/shlvl.nix b/modules/starship/shlvl.nix new file mode 100644 index 00000000..bceec83b --- /dev/null +++ b/modules/starship/shlvl.nix @@ -0,0 +1,8 @@ +{ + flake.modules.homeManager.base.programs.starship.settings.shlvl = { + disabled = false; + style = "bold red"; + symbol = ""; + threshold = 2; + }; +} diff --git a/modules/starship/starship.nix b/modules/starship/starship.nix new file mode 100644 index 00000000..5839e22c --- /dev/null +++ b/modules/starship/starship.nix @@ -0,0 +1,3 @@ +{ + flake.modules.homeManager.base.programs.starship.enable = true; +} diff --git a/modules/starship/zsh.nix b/modules/starship/zsh.nix new file mode 100644 index 00000000..f9114042 --- /dev/null +++ b/modules/starship/zsh.nix @@ -0,0 +1,3 @@ +{ + flake.modules.homeManager.base.programs.starship.enableZshIntegration = true; +} diff --git a/modules/sudo.nix b/modules/sudo.nix new file mode 100644 index 00000000..7f70c7c6 --- /dev/null +++ b/modules/sudo.nix @@ -0,0 +1,9 @@ +{ config, ... }: + +{ + flake.modules.nixos.pc = { + security.sudo-rs.enable = true; + + users.users.${config.flake.meta.owner.username}.extraGroups = [ "wheel" ]; + }; +} diff --git a/modules/sxhkd/enable.nix b/modules/sxhkd/enable.nix new file mode 100644 index 00000000..1712708b --- /dev/null +++ b/modules/sxhkd/enable.nix @@ -0,0 +1,3 @@ +{ + flake.modules.homeManager.gui.services.sxhkd.enable = true; +} diff --git a/modules/sxhkd/keybindings.nix b/modules/sxhkd/keybindings.nix new file mode 100644 index 00000000..67338e12 --- /dev/null +++ b/modules/sxhkd/keybindings.nix @@ -0,0 +1,21 @@ +{ lib, ... }: + +{ + flake.modules.homeManager.gui = + { pkgs, ... }: + { + services.sxhkd.keybindings = { + "@F10" = "/home/opdavies/.local/bin/unmounter"; + "@F3" = "displayselect"; + "@F9" = "/home/opdavies/.local/bin/mounter"; + "super + BackSpace" = "dmenu_sys"; + "super + shift + b" = "/etc/profiles/per-user/opdavies/bin/bookmarkthis"; + "super + shift + i" = + "${pkgs.xdotool}/bin/xdotool type $(cat ~/.local/share/snippets.txt | grep -v '^#' | grep -v '^$' | sort | dmenu -i -l 50 | cut -d' ' -f1)"; + "super + shift + p" = "${lib.getExe pkgs.passmenu-otp} -i"; + "super + x; {1, 2, 3, 4}" = "st {notes, newsboat, nmtui, bluetuith}"; + "{_, shift +, super +}XF86MonBrightness{Down,Up}" = + "${lib.getExe pkgs.brightnessctl} set {5%-,10%-,10%,+5%,+10%,100%} --quiet"; + }; + }; +} diff --git a/modules/tailscale.nix b/modules/tailscale.nix new file mode 100644 index 00000000..d239c83e --- /dev/null +++ b/modules/tailscale.nix @@ -0,0 +1,3 @@ +{ + flake.modules.nixos.pc.services.tailscale.enable = true; +} diff --git a/modules/thunar/enable.nix b/modules/thunar/enable.nix new file mode 100644 index 00000000..5ac63555 --- /dev/null +++ b/modules/thunar/enable.nix @@ -0,0 +1,3 @@ +{ + flake.modules.pc.nixos.programs.thunar.enable = true; +} diff --git a/modules/thunar/extra-packages.nix b/modules/thunar/extra-packages.nix new file mode 100644 index 00000000..036a7ff1 --- /dev/null +++ b/modules/thunar/extra-packages.nix @@ -0,0 +1,7 @@ +{ + flake.modules.pc.nixos = + { pkgs, ... }: + { + environment.systemPackages = with pkgs; [ xfce.tumbler ]; + }; +} diff --git a/modules/thunar/plugins.nix b/modules/thunar/plugins.nix new file mode 100644 index 00000000..5df3e2ab --- /dev/null +++ b/modules/thunar/plugins.nix @@ -0,0 +1,9 @@ +{ + flake.modules.pc.nixos = + { pkgs, ... }: + { + programs.thunar.plugins = with pkgs.xfce; [ + thunar-archive-plugin + ]; + }; +} diff --git a/modules/tmux/enable.nix b/modules/tmux/enable.nix new file mode 100644 index 00000000..a4a47b08 --- /dev/null +++ b/modules/tmux/enable.nix @@ -0,0 +1,3 @@ +{ + flake.modules.homeManager.base.programs.tmux.enable = true; +} diff --git a/modules/tmux/extra-config.nix b/modules/tmux/extra-config.nix new file mode 100644 index 00000000..78f0d208 --- /dev/null +++ b/modules/tmux/extra-config.nix @@ -0,0 +1,69 @@ +{ + flake.modules.homeManager.base.programs.tmux.extraConfig = '' + set-option -g status-keys "vi" + set-option -sa terminal-features "''${TERM}:RGB" + + bind -n S-Left resize-pane -L 2 + bind -n S-Right resize-pane -R 2 + bind -n S-Down resize-pane -D 1 + bind -n S-Up resize-pane -U 1 + + bind -n C-Left resize-pane -L 10 + bind -n C-Right resize-pane -R 10 + bind -n C-Down resize-pane -D 5 + bind -n C-Up resize-pane -U 5 + + # Status line customisation + set-option -g status-position top + set-option -g status-left "" + set-option -g status-right " #{session_name}" + set-option -g status-right-length 100 + set-option -g status-style "fg=#7C7D83 bg=default" + set-option -g window-status-activity-style none + + bind c new-window -c "#{pane_current_path}" + + set -g base-index 1 + set -g pane-base-index 1 + set -g renumber-windows on + + # Break a pane into a new window. + bind-key b break-pane -d + bind-key J command-prompt -p "join pane from: " "join-pane -h -s '%%'" + + bind-key C-j choose-tree + + set-window-option -g mode-keys vi + bind -T copy-mode-vi v send-keys -X begin-selection + bind -T copy-mode-vi y send-keys -X copy-pipe-and-cancel 'xclip -in -selection clipboard' + + bind C-j split-window -v "tmux list-sessions | sed -E 's/:.*$//' | grep -v \"^$(tmux display-message -p '#S')\$\" | fzf --reverse | xargs tmux switch-client -t" + + bind-key K run-shell 'tmux switch-client -n \; kill-session -t "$(tmux display-message -p "#S")" || tmux kill-session' + + # Allow clearing screen with ctrl-l by using C-l + bind C-l send-keys "C-l" + bind C-k send-keys "C-k" + + # Enable mouse support. + setw -g mouse on + + # Remove delay when switching Vim modes. + set -sg escape-time 0 + + set-option -g pane-active-border-style "fg=#1f2335" + set-option -g pane-border-style "fg=#1f2335" + + # Vim-like pane navigation. + bind ^ last-window + bind h select-pane -L + bind j select-pane -D + bind k select-pane -U + bind l select-pane -R + + bind-key -r f run-shell "tmux new-window tmux-sessionizer" + + bind-key -r D new-window -c "#{pane_current_path}" "[[ -e TODO.md ]] && nvim TODO.md || nvim ~/Documents/wiki/todo.txt" + bind-key -r W split-window -h -c ~/Documents/wiki "nvim '+Telescope find_files'" + ''; +} diff --git a/modules/tmux/plugins.nix b/modules/tmux/plugins.nix new file mode 100644 index 00000000..3e7d723d --- /dev/null +++ b/modules/tmux/plugins.nix @@ -0,0 +1,7 @@ +{ + flake.modules.homeManager.base = + { pkgs, ... }: + { + programs.tmux.plugins = with pkgs.tmuxPlugins; [ yank ]; + }; +} diff --git a/modules/tmux/terminal.nix b/modules/tmux/terminal.nix new file mode 100644 index 00000000..0edf3248 --- /dev/null +++ b/modules/tmux/terminal.nix @@ -0,0 +1,3 @@ +{ + flake.modules.homeManager.base.programs.tmux.terminal = "tmux-256color"; +} diff --git a/modules/unfree-packages.nix b/modules/unfree-packages.nix new file mode 100644 index 00000000..40f0f8a2 --- /dev/null +++ b/modules/unfree-packages.nix @@ -0,0 +1,26 @@ +{ config, lib, ... }: + +{ + options.nixpkgs.allowedUnfreePackages = lib.mkOption { + type = lib.types.listOf lib.types.str; + default = [ ]; + }; + + config.flake = { + modules = + let + predicate = pkg: builtins.elem (lib.getName pkg) config.nixpkgs.allowedUnfreePackages; + in + { + nixos.base.nixpkgs.config.allowUnfreePredicate = predicate; + + homeManager.base = args: { + nixpkgs.config = lib.mkIf (!(args.hasGlobalPkgs or false)) { + allowUnfreePredicate = predicate; + }; + }; + }; + + meta.nixpkgs.allowedUnfreePackages = config.nixpkgs.allowedUnfreePackages; + }; +} diff --git a/modules/wiki.nix b/modules/wiki.nix new file mode 100644 index 00000000..b5276c2e --- /dev/null +++ b/modules/wiki.nix @@ -0,0 +1,7 @@ +{ + flake.modules.homeManager.base = + { config, ...}: + { + home.sessionVariables.WIKI_DIRECTORY = "${config.xdg.userDirs.documents}/wiki"; + }; +} diff --git a/modules/xbanish.nix b/modules/xbanish.nix new file mode 100644 index 00000000..5ebb30b0 --- /dev/null +++ b/modules/xbanish.nix @@ -0,0 +1,3 @@ +{ + flake.modules.nixos.pc.services.xbanish.enable = true; +} diff --git a/modules/xsession.nix b/modules/xsession.nix new file mode 100644 index 00000000..5fdf17bf --- /dev/null +++ b/modules/xsession.nix @@ -0,0 +1,3 @@ +{ + flake.modules.homeManager.gui.xsession.enable = true; +} diff --git a/modules/zram.nix b/modules/zram.nix new file mode 100644 index 00000000..3ca702ff --- /dev/null +++ b/modules/zram.nix @@ -0,0 +1,7 @@ +{ + flake.modules.nixos.pc.zramSwap = { + enable = true; + algorithm = "zstd"; + memoryPercent = 90; + }; +} diff --git a/modules/zsh/abbreviations/abbreviations.nix b/modules/zsh/abbreviations/abbreviations.nix new file mode 100644 index 00000000..95022561 --- /dev/null +++ b/modules/zsh/abbreviations/abbreviations.nix @@ -0,0 +1,172 @@ +{ + nixpkgs.allowedUnfreePackages = [ + "zsh-abbr" + ]; + + flake.modules.homeManager.base.programs.zsh.zsh-abbr.abbreviations = { + cl = "clear"; + cs = "create-script"; + daily = "run create-daily next"; + gru = "git-repo-updater"; + rst = "rst2pdf"; + st = "source .tmux"; + sz = "source ~/.config/zsh/.zshrc"; + ti = "timer"; + uagr = "update-all-git-repos"; + v = "nvim"; + yt = "yt-dlp"; + + evl = "export-video-list"; + vv = "cat ~/Documents/videos.json"; + + f = "find ."; + fd = "find . -type d"; + fdn = "find . -type d -name"; + ff = "find . -type f"; + ffn = "find . -type f -name"; + + g = "git"; + ga = "git add"; + gan = "git add -N"; + gap = "git add -p"; + gb = "git branch"; + gba = "git branch --all"; + gbl = "git blame"; + gc = "git commit"; + gca = "git commit --amend"; + gcan = "git commit --amend --no-edit"; + gcl = "git clone"; + gcm = "git commit -m"; + gco = "git checkout"; + gcob = "git checkout -b"; + gd = "git diff"; + gds = "git diff --staged"; + gf = "git fetch"; + gfa = "git fetch --all"; + gl = "git log"; + glg = "git log --grep"; + glo = "git log --oneline"; + glog = "git log --oneline --grep"; + glos = "git log --oneline -S"; + gls = "git log -S"; + gm = "git merge"; + gmf = "git merge --ff"; + gmnf = "git merge --no-ff"; + gp = "git push"; + gpa = "git push acquia"; + gpam = "git push acquia main"; + gpap = "git push acquia HEAD:production"; + gpf = "git push --force-with-lease"; + gpfo = "git push --force-with-lease origin"; + gpl = "git pull"; + gplr = "git pull --rebase"; + gpo = "git push origin"; + gpom = "git push origin main"; + gpt = "git push --tags"; + gr = "git rebase"; + gra = "git rebase --abort"; + grc = "git rebase --continue"; + gri = "git rebase -i"; + gs = "git status"; + gsh = "git show"; + gst = "git stash"; + gstp = "git stash pop"; + gt = "git tag"; + + j = "just"; + jb = "just build"; + jt = "just test"; + js = "just switch"; + + # tmux + ta = "tmux attach"; + tl = "tmux list-sessions"; + tk = "tmux kill-session"; + + # Docker and Docker Compose. + dk = "docker"; + dkp = "docker ps"; + dkpa = "docker ps -a"; + dkpaq = "docker ps -a -q"; + dkb = "docker build -t"; + dks = "docker start"; + dkt = "docker stop"; + dkrm = "docker rm"; + dkri = "docker rmi"; + dke = "docker exec -ti"; + dkl = "docker logs -f"; + dki = "docker images"; + dkpu = "docker pull"; + dkph = "docker push"; + dkbnc = "docker build --no-cache -t"; + dkr = "docker run --rm"; + dkrti = "docker run --rm -ti"; + dkc = "docker compose"; + dkcb = "docker compose build"; + dkcu = "docker compose up"; + dkclean = "docker ps -q -a -f status=exited | xargs -r docker rm && docker images -q -f dangling=true | xargs -r docker rmi"; + + # Nix and direnv. + dea = "direnv allow"; + dee = "direnv edit"; + nxf = "nix flake"; + nxfc = "nix flake check"; + nxfs = "nix flake show"; + nxfu = "nix flake update"; + nxr = "nix run nixpkgs#%"; + nxs = "nix shell nixpkgs#%"; + + # run scripts. + r = "run"; + rc = "run composer"; + rcda = "run composer dump-autoload"; + rci = "run composer install"; + rcr = "run composer require"; + rcu = "run composer update"; + rd = "run drush"; + rdce = "run drush config:export -y"; + rdci = "run drush config:import -y"; + rdcr = "run drush cache:rebuild"; + rdscr = "run drush php:script"; + rduli = "run drush uli"; + rdup = "run drush updatedb -y"; + rpub = "run publish"; + rt = "run test"; + + nah = "git reset --hard; git clean -fd"; + wip = "git commit -m wip"; + + dv = "devenv"; + dvi = "devenv info"; + dvp = "devenv processes"; + dvs = "devenv shell"; + dvt = "devenv tasks"; + dvu = "devenv up"; + + c = "composer"; + ci = "composer install"; + cr = "composer require"; + crd = "composer require drupal/%"; + cu = "composer update"; + cul = "composer update --lock"; + cw = "composer why"; + cwn = "composer why-not"; + + d = "drush"; + dce = "drush config:export -y"; + dci = "drush config:import -y"; + dcr = "drush cache:rebuild"; + den = "drush pm:enable -y"; + deu = "drush pm:uninstall"; + dscr = "drush php:script"; + duli = "drush uli"; + dup = "drush updatedb -y"; + + sg = "vendor/bin/sculpin generate"; + sge = "vendor/bin/sculpin generate --env"; + sgs = "vendor/bin/sculpin generate --server"; + sgsp = "vendor/bin/sculpin generate --server --port"; + sgsw = "vendor/bin/sculpin generate --server --watch"; + sgswp = "vendor/bin/sculpin generate --server --watch --port"; + }; +} diff --git a/modules/zsh/abbreviations/enable.nix b/modules/zsh/abbreviations/enable.nix new file mode 100644 index 00000000..ae3da6f2 --- /dev/null +++ b/modules/zsh/abbreviations/enable.nix @@ -0,0 +1,3 @@ +{ + flake.modules.homeManager.base.programs.zsh.zsh-abbr.enable = true; +} diff --git a/modules/zsh/abbreviations/global-abbreviations.nix b/modules/zsh/abbreviations/global-abbreviations.nix new file mode 100644 index 00000000..b416083a --- /dev/null +++ b/modules/zsh/abbreviations/global-abbreviations.nix @@ -0,0 +1,16 @@ +{ + flake.modules.homeManager.base.programs.zsh.zsh-abbr.globalAbbreviations = { + A1 = "| awk '{print $1}'"; + C = "| xclip -sel clip"; + Fj = "| jq ."; + Fy = "| yq ."; + G = "| grep"; + GH = "| grep HTTP"; + Gi = "| grep -i"; + H2 = "| head -n 20"; + H = "| head"; + L = "| less"; + V = "| nvim -"; + X = "| xargs -I1"; + }; +} diff --git a/modules/zsh/aliases.nix b/modules/zsh/aliases.nix new file mode 100644 index 00000000..e89f1515 --- /dev/null +++ b/modules/zsh/aliases.nix @@ -0,0 +1,19 @@ +{ + flake.modules.homeManager.base = + { config, ... }: + { + programs.zsh.shellAliases = { + "$" = ""; + "-" = "cd -"; + ".." = "cd .."; + "..." = "cd ../.."; + "...." = "cd ../../.."; + "....." = "cd ../../../.."; + chmox = "chmod +x"; + run = "./run"; + tag = "tag-release"; + vss = "LC_ALL=C sort --unique ${config.xdg.userDirs.extraConfig.XDG_REPOS_DIR}/nixos-config/modules/home-manager/cli/neovim/config/spell/en.utf-8.adddotfiles/nvim/spell/en.utf-8.add --output ${config.xdg.userDirs.extraConfig.XDG_REPOS_DIR}/nixos-config/modules/home-manager/cli/neovim/config/spell/en.utf-8.add"; + wt = "git worktree"; + }; + }; +} diff --git a/modules/zsh/completion.nix b/modules/zsh/completion.nix new file mode 100644 index 00000000..f9859c29 --- /dev/null +++ b/modules/zsh/completion.nix @@ -0,0 +1,3 @@ +{ + flake.modules.homeManager.base.programs.zsh.enableCompletion = true; +} diff --git a/modules/zsh/dot-dir.nix b/modules/zsh/dot-dir.nix new file mode 100644 index 00000000..83e5f2e1 --- /dev/null +++ b/modules/zsh/dot-dir.nix @@ -0,0 +1,7 @@ +{ + flake.modules.homeManager.base = + { config, ... }: + { + programs.zsh.dotDir = "${config.xdg.configHome}/zsh"; + }; +} diff --git a/modules/zsh/enable.nix b/modules/zsh/enable.nix new file mode 100644 index 00000000..d9319f31 --- /dev/null +++ b/modules/zsh/enable.nix @@ -0,0 +1,3 @@ +{ + flake.modules.homeManager.base.programs.zsh.enable = true; +} diff --git a/modules/zsh/init.nix b/modules/zsh/init.nix new file mode 100644 index 00000000..e147ffad --- /dev/null +++ b/modules/zsh/init.nix @@ -0,0 +1,64 @@ +{ + flake.modules.homeManager.base = + { config, pkgs, ... }: + { + programs.zsh.initContent = '' + background() { + for ((i=2;i<=$#;i++)); do + ''${@[1]} ''${@[$i]} &> /dev/null & + done + } + + # suffix + alias -s gz="tar -tf" + alias -s {html,HTML}="background zsh" + alias -s {jpg,JPG,png,PNG}="background okular" + alias -s {pdf,PDF}="background okular" + alias -s {zip,ZIP}="unzip -l" + + git() { + case "$1" in + root) + shift + + local ROOT="$(${pkgs.git}/bin/git rev-parse --show-toplevel 2> /dev/null || echo -n .)" + + if [[ $# == 0 ]]; then + cd "''${ROOT}" + else + (cd "''${ROOT}" && eval "''${@}") + fi + ;; + + *) + ${pkgs.git}/bin/git "''${@}" + ;; + esac + } + + mbsync() { + ${pkgs.isync}/bin/mbsync --config "${config.xdg.configHome}/isync/mbsyncrc" "''${@}" + } + + ttyper() { + command ${pkgs.ttyper}/bin/ttyper --language english1000 --words 50 "''${@}" + } + + weather() { + curl "https://wttr.in/''$1" + } + + yt-dlp() { + command yt-dlp --paths ~/Videos "$@" + } + + bindkey -s ^f "tmux-sessionizer\n" + bindkey -s ^v "nvim\n" + + setopt auto_cd + setopt auto_pushd + setopt pushd_ignore_dups + setopt pushdminus + ''; + }; +} diff --git a/modules/zsh/profile.nix b/modules/zsh/profile.nix new file mode 100644 index 00000000..318d562c --- /dev/null +++ b/modules/zsh/profile.nix @@ -0,0 +1,7 @@ +{ + flake.modules.homeManager.base.programs.zsh.profileExtra = '' + if [[ -z "$DISPLAY" ]] && [[ "$(tty)" == "/dev/tty1" ]]; then + exec startx &>/dev/null + fi + ''; +} diff --git a/modules/zsh/syntax-highlighting.nix b/modules/zsh/syntax-highlighting.nix new file mode 100644 index 00000000..0fa884df --- /dev/null +++ b/modules/zsh/syntax-highlighting.nix @@ -0,0 +1,3 @@ +{ + flake.modules.homeManager.base.programs.zsh.syntaxHighlighting.enable = true; +} diff --git a/modules/zsh/variables.nix b/modules/zsh/variables.nix new file mode 100644 index 00000000..886b3ba2 --- /dev/null +++ b/modules/zsh/variables.nix @@ -0,0 +1,5 @@ +{ + flake.modules.homeManager.base.programs.zsh.localVariables = { + ABBR_SET_EXPANSION_CURSOR = 1; + }; +} diff --git a/modules/zsh/vi-mode.nix b/modules/zsh/vi-mode.nix new file mode 100644 index 00000000..79e609be --- /dev/null +++ b/modules/zsh/vi-mode.nix @@ -0,0 +1,3 @@ +{ + flake.modules.homeManager.base.programs.zsh.defaultKeymap = "viins"; +} diff --git a/notes.txt b/notes.txt new file mode 100644 index 00000000..e01d0f67 --- /dev/null +++ b/notes.txt @@ -0,0 +1,6 @@ +Running Neovim as a package: + +nix run .#neovim +nix run git+https://code.oliverdavies.uk/opdavies/nix-config#neovim + +nixos-rebuild --flake .#nixedo --target-host 192.168.1.116 --sudo test diff --git a/overlays/default.nix b/overlays/default.nix new file mode 100644 index 00000000..17308ce2 --- /dev/null +++ b/overlays/default.nix @@ -0,0 +1,21 @@ +{ inputs, ... }: + +{ + additions = + final: prev: + import ../packages { + inherit inputs prev; + + pkgs = final; + }; + + modifications = final: prev: { + dwm = import ./mods/dwm { inherit prev; }; + }; + + stable-packages = final: _prev: { + stable = import inputs.nixpkgs-stable { + system = final.system; + }; + }; +} diff --git a/overlays/mods/dwm/default.nix b/overlays/mods/dwm/default.nix new file mode 100644 index 00000000..67b3117c --- /dev/null +++ b/overlays/mods/dwm/default.nix @@ -0,0 +1,133 @@ +{ prev, ... }: + +let + inherit (prev) lib; +in +prev.dwm.override { + conf = '' + #define BROWSER "${lib.getExe prev.librewolf}" + #define TERMINAL "/etc/profiles/per-user/opdavies/bin/st" + + static const unsigned int borderpx = 1; + static const unsigned int snap = 32; + static const int showbar = 1; + static const int topbar = 1; + static const char *fonts[] = { "monospace:size=10" }; + static const char dmenufont[] = "monospace:size=10"; + static const char col_gray1[] = "#222222"; + static const char col_gray2[] = "#444444"; + static const char col_gray3[] = "#bbbbbb"; + static const char col_gray4[] = "#eeeeee"; + static const char col_cyan[] = "#005577"; + static const char *colors[][3] = { + [SchemeNorm] = { col_gray3, col_gray1, col_gray2 }, + [SchemeSel] = { col_gray4, col_cyan, col_cyan }, + }; + + static const char *tags[] = { "1", "2", "3", "4", "5", "6", "7", "8", "9" }; + + static const Rule rules[] = { + { "0ad", NULL, NULL, 1 << 7, 0, -1 }, + { "Slack", NULL, NULL, 1 << 8, 0, -1 }, + }; + + static const float mfact = 0.55; + static const int nmaster = 1; + static const int resizehints = 1; + static const int lockfullscreen = 1; + + static const Layout layouts[] = { + { "[]=", tile }, + { "><>", NULL }, + { "[M]", monocle }, + }; + + #define MODKEY Mod4Mask + + #define TAGKEYS(KEY,TAG) \ + { MODKEY, KEY, view, {.ui = 1 << TAG} }, \ + { MODKEY|ControlMask, KEY, toggleview, {.ui = 1 << TAG} }, \ + { MODKEY|ShiftMask, KEY, tag, {.ui = 1 << TAG} }, \ + { MODKEY|ControlMask|ShiftMask, KEY, toggletag, {.ui = 1 << TAG} }, + + #define SHCMD(cmd) { .v = (const char*[]){ "/bin/sh", "-c", cmd, NULL } } + + static char dmenumon[2] = "0"; /* component of dmenucmd, manipulated in spawn() */ + static const char *dmenucmd[] = { "dmenu_run", "-m", dmenumon, "-fn", dmenufont, "-nb", col_gray1, "-nf", col_gray3, "-sb", col_cyan, "-sf", col_gray4, NULL }; + static const char *termcmd[] = { TERMINAL, NULL }; + + static const Key keys[] = { + { MODKEY, XK_p, spawn, {.v = dmenucmd } }, + { MODKEY|ShiftMask, XK_Return, spawn, {.v = termcmd } }, + { MODKEY, XK_b, togglebar, {0} }, + { MODKEY, XK_j, focusstack, {.i = +1 } }, + { MODKEY, XK_k, focusstack, {.i = -1 } }, + { MODKEY, XK_i, incnmaster, {.i = +1 } }, + { MODKEY, XK_d, incnmaster, {.i = -1 } }, + { MODKEY, XK_h, setmfact, {.f = -0.05} }, + { MODKEY, XK_l, setmfact, {.f = +0.05} }, + { MODKEY, XK_Return, zoom, {0} }, + { MODKEY, XK_Tab, view, {0} }, + { MODKEY|ShiftMask, XK_c, killclient, {0} }, + { MODKEY, XK_t, setlayout, {.v = &layouts[0]} }, + { MODKEY, XK_f, setlayout, {.v = &layouts[1]} }, + { MODKEY, XK_m, setlayout, {.v = &layouts[2]} }, + { MODKEY, XK_space, setlayout, {0} }, + { MODKEY|ShiftMask, XK_space, togglefloating, {0} }, + { MODKEY, XK_0, view, {.ui = ~0 } }, + { MODKEY|ShiftMask, XK_0, tag, {.ui = ~0 } }, + { MODKEY, XK_comma, focusmon, {.i = -1 } }, + { MODKEY, XK_period, focusmon, {.i = +1 } }, + { MODKEY|ShiftMask, XK_comma, tagmon, {.i = -1 } }, + { MODKEY|ShiftMask, XK_period, tagmon, {.i = +1 } }, + TAGKEYS(XK_1, 0) + TAGKEYS(XK_2, 1) + TAGKEYS(XK_3, 2) + TAGKEYS(XK_4, 3) + TAGKEYS(XK_5, 4) + TAGKEYS(XK_6, 5) + TAGKEYS(XK_7, 6) + TAGKEYS(XK_8, 7) + TAGKEYS(XK_9, 8) + { MODKEY|ShiftMask, XK_f, spawn, SHCMD("${prev.xfce.thunar}/bin/thunar") }, + { MODKEY|ShiftMask, XK_q, quit, {0} }, + { MODKEY|ShiftMask, XK_r, quit, {1} }, + { MODKEY|ShiftMask, XK_s, spawn, SHCMD("${prev.flameshot}/bin/flameshot gui") }, + { MODKEY, XK_w, spawn, SHCMD(BROWSER) }, + }; + + static const Button buttons[] = { + { ClkLtSymbol, 0, Button1, setlayout, {0} }, + { ClkLtSymbol, 0, Button3, setlayout, {.v = &layouts[2]} }, + { ClkWinTitle, 0, Button2, zoom, {0} }, + { ClkStatusText, 0, Button2, spawn, {.v = termcmd } }, + { ClkClientWin, MODKEY, Button1, movemouse, {0} }, + { ClkClientWin, MODKEY, Button2, togglefloating, {0} }, + { ClkClientWin, MODKEY, Button3, resizemouse, {0} }, + { ClkTagBar, 0, Button1, view, {0} }, + { ClkTagBar, 0, Button3, toggleview, {0} }, + { ClkTagBar, MODKEY, Button1, tag, {0} }, + { ClkTagBar, MODKEY, Button3, toggletag, {0} }, + }; + ''; + + patches = with prev; [ + (fetchpatch { + name = "preserveonrestart"; + url = "https://dwm.suckless.org/patches/preserveonrestart/dwm-preserveonrestart-6.3.diff"; + sha256 = "zgwTCgD3YE+2K4BF6Em+qkM1Gax5vOZfeuWa6zXx8cE="; + }) + + (fetchpatch { + name = "hide_vacant_tags"; + url = "https://dwm.suckless.org/patches/hide_vacant_tags/dwm-hide_vacant_tags-6.4.diff"; + sha256 = "GIbRW0Inwbp99rsKLfIDGvPwZ3pqihROMBp5vFlHx5Q="; + }) + + (fetchpatch { + name = "pertag"; + url = "https://dwm.suckless.org/patches/pertag/dwm-pertag-20200914-61bb8b2.diff"; + sha256 = "wRZP/27V7xYOBnFAGxqeJFXdoDk4K1EQMA3bEoAXr/0="; + }) + ]; +} diff --git a/packages/_timer.nix b/packages/_timer.nix new file mode 100644 index 00000000..6dd00e3b --- /dev/null +++ b/packages/_timer.nix @@ -0,0 +1,19 @@ +{ pkgs }: + +pkgs.writeShellApplication { + name = "_timer"; + + runtimeInputs = with pkgs; [ + coreutils + libnotify + ]; + + text = '' + mins=$1 + message=''${2:-Time out!} + + sleep $((mins * 60)) + + notify-send -t 0 "''${message}" "Your timer of $mins min is over" -u normal + ''; +} diff --git a/packages/backup-websites.nix b/packages/backup-websites.nix new file mode 100644 index 00000000..fd7828df --- /dev/null +++ b/packages/backup-websites.nix @@ -0,0 +1,15 @@ +{ pkgs, ... }: + +pkgs.writeShellApplication { + name = "backup-websites"; + + runtimeInputs = with pkgs; [ rsync ]; + + text = '' + backup_path="''$HOME/server-backup" + + mkdir -p "''$backup_path" + + rsync -avzP nixedo.oliverdavies.uk:/var/www/vhosts/ "''$backup_path" --delete-after + ''; +} diff --git a/packages/build-glove80.nix b/packages/build-glove80.nix new file mode 100644 index 00000000..c6feba0d --- /dev/null +++ b/packages/build-glove80.nix @@ -0,0 +1,43 @@ +{ pkgs, ... }: + +with pkgs; + +writeShellApplication { + name = "build-glove80"; + + runtimeInputs = [ + cachix + git + nix + ]; + + text = '' + BRANCH="''${1:-main}" + SRC_DIR="''${PWD}/src" + CONFIG_DIR="''${PWD}/config" + NIX_FILE="''${CONFIG_DIR}/default.nix" + + # Ensure cachix is configured + echo "Using moergo-glove80-zmk-dev cache" + cachix use moergo-glove80-zmk-dev + + # Clone or update the ZMK repository + if [ ! -d "$SRC_DIR" ]; then + echo "Cloning ZMK repository into ./src..." + git clone https://github.com/moergo-sc/zmk "$SRC_DIR" + else + echo "Updating ZMK repository in ./src..." + git -C "$SRC_DIR" fetch --all + fi + + # Checkout the specified branch or tag + echo "Checking out branch/tag: $BRANCH in ./src" + git -C "$SRC_DIR" checkout -q --detach "$BRANCH" + + # Build firmware using Nix + echo "Building firmware from: $NIX_FILE" + nix-build "$NIX_FILE" --arg firmware "import ''${SRC_DIR}/default.nix {}" -j2 -o ./glove80.uf2 --show-trace + + echo "Firmware built successfully: $(realpath ./glove80.uf2)" + ''; +} diff --git a/packages/count-tags.nix b/packages/count-tags.nix new file mode 100755 index 00000000..c5e046fa --- /dev/null +++ b/packages/count-tags.nix @@ -0,0 +1,14 @@ +{ pkgs }: + +pkgs.writeShellApplication { + name = "count-tags"; + + runtimeInputs = with pkgs; [ + coreutils + get-tags + ]; + + text = '' + get-tags "''${1:-}" | wc -l + ''; +} diff --git a/packages/create-script.nix b/packages/create-script.nix new file mode 100755 index 00000000..840018fd --- /dev/null +++ b/packages/create-script.nix @@ -0,0 +1,19 @@ +{ pkgs }: + +pkgs.writeShellApplication { + name = "create-script"; + + text = '' + cat > "$1" << EOF + #!/usr/bin/env bash + + set -euo pipefail + + + EOF + + chmod +x "$1" + + $EDITOR "$1"; + ''; +} diff --git a/packages/default.nix b/packages/default.nix new file mode 100644 index 00000000..418c1638 --- /dev/null +++ b/packages/default.nix @@ -0,0 +1,37 @@ +{ + inputs, + pkgs, + prev, + ... +}: + +let + inherit (pkgs) callPackage; + + vimPlugins = callPackage ./vim-plugins { }; +in +{ + _timer = callPackage ./_timer.nix { }; + backup-websites = callPackage ./backup-websites.nix { }; + build-glove80 = callPackage ./build-glove80.nix { }; + count-tags = callPackage ./count-tags.nix { }; + create-script = callPackage ./create-script.nix { }; + dev-commit = callPackage ./dev-commit.nix { }; + get-tags = callPackage ./get-tags.nix { }; + git-exclude = callPackage ./git-exclude.nix { }; + git-graph = callPackage ./git-graph.nix { }; + import-to-jellyfin = callPackage ./import-to-jellyfin.nix { }; + mounter = callPackage ./mounter.nix { }; + move-firefox-screenshots = callPackage ./move-firefox-screenshots.nix { }; + passmenu-otp = callPackage ./passmenu-otp.nix { }; + set-background = callPackage ./set-background.nix { }; + tag-release = callPackage ./tag-release.nix { }; + time-until = callPackage ./time-until.nix { }; + timer = callPackage ./timer.nix { }; + tmux-sessionizer = callPackage ./tmux-sessionizer { }; + unmounter = callPackage ./unmounter.nix { }; + update-all-git-repos = callPackage ./update-all-git-repos.nix { }; + vic = callPackage ./vic.nix { inherit inputs; }; + + vimPlugins = prev.vimPlugins // vimPlugins; +} diff --git a/packages/dev-commit.nix b/packages/dev-commit.nix new file mode 100644 index 00000000..e71aa095 --- /dev/null +++ b/packages/dev-commit.nix @@ -0,0 +1,48 @@ +{ pkgs, ... }: + +pkgs.writeShellApplication { + name = "dev-commit"; + + runtimeInputs = with pkgs; [ + coreutils + git + logger + openssh + ]; + + text = '' + IFS=':' read -ra repos <<< "$DEV_COMMIT_PATHS" + + for repo in "''${repos[@]}"; do + logger "Processing repository: $repo" + + pushd "$repo" > /dev/null 2>&1 + + if [[ -n $(git status --porcelain) ]]; then + logger "Changes detected in $repo" + + git status --short | while read -r line; do + logger "Changed file: $line" + done + + git add . + + if git commit -m "Automated dev commit"; then + logger "Commit successful in $repo" + + if git push; then + logger "Push successful in $repo" + else + logger "Push failed in $repo" + fi + else + logger "No changes to commit in $repo" + fi + else + logger "No changes in $repo" + fi + + popd > /dev/null 2>&1 + done + ''; +} diff --git a/packages/get-tags.nix b/packages/get-tags.nix new file mode 100755 index 00000000..ac27898d --- /dev/null +++ b/packages/get-tags.nix @@ -0,0 +1,16 @@ +{ pkgs }: + +pkgs.writeShellApplication { + name = "get-tags"; + + runtimeInputs = with pkgs; [ git ]; + + text = '' + if [[ "$#" -gt 0 ]]; then + git tag | grep "$*" + exit 0 + fi + + git tag + ''; +} diff --git a/packages/git-exclude.nix b/packages/git-exclude.nix new file mode 100644 index 00000000..45e3cbdb --- /dev/null +++ b/packages/git-exclude.nix @@ -0,0 +1,24 @@ +{ pkgs }: + +pkgs.writeShellApplication { + name = "git-exclude"; + + runtimeInputs = with pkgs; [ git ]; + + text = '' + # Based on https://github.com/jfly/snow/blob/fb727b39736666f54908f4dc7c83dd6284607c5a/machines/pattern/homies/bin/git-exclude. + + root=$(git rev-parse --show-toplevel) + rel=$(realpath --relative-to "$root" .) + + # For some reason, ignore rules like "./.envrc" don't seem to work, but + # "/.envrc" does. :shrug: + if [ "$rel" = "." ]; then + rel="" + fi + + for item in "$@"; do + echo "''${rel}/$item" >> "$root/.git/info/exclude" + done + ''; +} diff --git a/packages/git-graph.nix b/packages/git-graph.nix new file mode 100644 index 00000000..4e719bc5 --- /dev/null +++ b/packages/git-graph.nix @@ -0,0 +1,17 @@ +{ pkgs }: + +pkgs.writeShellApplication { + name = "git-graph"; + + runtimeInputs = with pkgs; [ git ]; + + text = '' + # Based on https://github.com/sdaschner/dotfiles/blob/master/bin/git-graph. + + git log \ + --abbrev-commit \ + --all \ + --graph \ + --pretty=format:"%Cred%h%Creset -%C(yellow)%d%Creset %s %Cgreen(%cr) %C(bold blue)<%ae>%Creset" + ''; +} diff --git a/packages/import-to-jellyfin.nix b/packages/import-to-jellyfin.nix new file mode 100644 index 00000000..11bcb7c0 --- /dev/null +++ b/packages/import-to-jellyfin.nix @@ -0,0 +1,27 @@ +{ pkgs }: + +pkgs.writeShellApplication { + name = "import-to-jellyfin"; + + runtimeInputs = with pkgs; [ coreutils ]; + + text = '' + source_path="/home/opdavies/import" + + mapfile -t files < <(find "$source_path" -type f -name "*.mp4") + + for filepath in "''${files[@]}"; do + echo "Moving $filepath..." + + filename="$(basename "$filepath")" + filename_without_extension="''${filename%.mp4}" + + destination_path="/mnt/media/jellyfin/Movies/$filename_without_extension" + mkdir -p "$destination_path" + + mv "$source_path/$filename" "$destination_path" + done + + chown -R jellyfin:media /mnt/media/jellyfin + ''; +} diff --git a/packages/mounter.nix b/packages/mounter.nix new file mode 100755 index 00000000..df0e0982 --- /dev/null +++ b/packages/mounter.nix @@ -0,0 +1,45 @@ +{ pkgs }: + +pkgs.writeShellApplication { + name = "mounter"; + + runtimeInputs = with pkgs; [ + cryptsetup + dmenu + gawk + libnotify + util-linux + ]; + + text = '' + lsblk_output="$(lsblk -rpo "uuid,name,type,size,label,mountpoint,mountpoints,fstype" | grep "part" | grep -Ev "/(boot|nix/store)")" + partition_names="$(echo "$lsblk_output" | awk '{ printf "%s (%s)\n", $2, $4 }' )"; + + selected=$(echo "$partition_names" | dmenu -p "Select drive:" | awk '{ print $1 }') + test -n "$selected" + mount_device="$selected" + + if sudo cryptsetup isLuks "$selected"; then + luks_name="usb" + + ${"TERMINAL:-st"} -n floatterm -g 60x1 -e sudo cryptsetup open "$selected" "$luks_name" + + mount_device="/dev/mapper/$luks_name" + + test -b "/dev/mapper/$luks_name" + fi + + mount_point=$(echo -e "/mnt\n/media\n/run/media/$USER" | dmenu -p "Select mount point:") + test -n "$mount_point" + + sudo mkdir -p "$mount_point" + + if sudo mount "$mount_device" "$mount_point"; then + notify-send "Device mounted" "Mounted $selected at $mount_point." + else + notify-send "Mount failed" "Failed to mount $selected." + + exit 1 + fi + ''; +} diff --git a/packages/move-firefox-screenshots.nix b/packages/move-firefox-screenshots.nix new file mode 100755 index 00000000..8f544f30 --- /dev/null +++ b/packages/move-firefox-screenshots.nix @@ -0,0 +1,15 @@ +{ pkgs }: + +pkgs.writeShellApplication { + name = "move-firefox-screenshots"; + + runtimeInputs = with pkgs; [ findutils ]; + + text = '' + original_directory="''${HOME}/Downloads" + new_directory="''${HOME}/Pictures/Screenshots" + + find "''${original_directory}" -mindepth 1 -maxdepth 1 -type f -name "Screenshot *" \ + -exec mv {} "''${new_directory}" \; + ''; +} diff --git a/packages/passmenu-otp.nix b/packages/passmenu-otp.nix new file mode 100644 index 00000000..250cda7f --- /dev/null +++ b/packages/passmenu-otp.nix @@ -0,0 +1,30 @@ +{ pkgs, ... }: + +with pkgs; + +stdenv.mkDerivation { + pname = "passmenu-otp"; + version = "unstable-2019-04-21"; + + src = fetchFromGitHub { + owner = "petrmanek"; + repo = "passmenu-otp"; + rev = "2623a0845cc2bb68b636a743862693fce9ec8b02"; + sha256 = "sha256-2EGomeK/p3uVfgho5xGR11ovJQ2q3cPZoFG+z88DyxA="; + }; + + buildInputs = [ + pass + ]; + + installPhase = '' + mkdir -p $out/bin + cp passmenu-otp $out/bin/passmenu-otp + chmod +x $out/bin/passmenu-otp + ''; + + meta = { + homepage = "https://github.com/petrmanek/passmenu-otp"; + mainProgram = "passmenu-otp"; + }; +} diff --git a/packages/set-background.nix b/packages/set-background.nix new file mode 100644 index 00000000..8bd581f8 --- /dev/null +++ b/packages/set-background.nix @@ -0,0 +1,11 @@ +{ pkgs, writeShellApplication }: + +writeShellApplication { + name = "set-background"; + + runtimeInputs = with pkgs; [ xwallpaper ]; + + text = '' + xwallpaper --zoom "''${XDG_REPOS_DIR}/personal/nix-config/wallpaper/wallpaper.jpg" + ''; +} diff --git a/packages/tag-release.nix b/packages/tag-release.nix new file mode 100644 index 00000000..0bd612b6 --- /dev/null +++ b/packages/tag-release.nix @@ -0,0 +1,17 @@ +{ git, writeShellApplication }: + +writeShellApplication { + name = "tag-release"; + + runtimeInputs = [ git ]; + + text = '' + commit_sha="''${1:-HEAD}" + tag="$(date '+%Y-%m-%d-%H.%M.%S')" + + echo "Tagging commit $(git rev-parse "''${commit_sha}") as ''${tag}." + echo "" + + git tag "''${tag}" "''${commit_sha}" + ''; +} diff --git a/packages/time-until.nix b/packages/time-until.nix new file mode 100644 index 00000000..82e1c821 --- /dev/null +++ b/packages/time-until.nix @@ -0,0 +1,27 @@ +{ pkgs }: + +pkgs.writeShellApplication { + name = "time-until"; + + runtimeInputs = with pkgs; [ bc ]; + + text = '' + # Based on https://github.com/sdaschner/dotfiles/blob/master/bin/time-until. + set +o nounset + + if [[ "$1" == "" ]]; then + echo "Usage: ''${0##*/} " + echo " Example: ''${0##*/} 'tomorrow 06:00'" + exit 2 + fi + + set -o nounset + + secsUntil=$(( $(date +%s -d "$*") - $( date +%s ) )) + minutesUntil=$(bc <<< "scale=1; $secsUntil/60") + hoursUntil=$(bc <<< "scale=2; $secsUntil/3600") + date=$(date -d "$*") + + echo "$hoursUntil hours (or $minutesUntil mins) until $date" + ''; +} diff --git a/packages/timer.nix b/packages/timer.nix new file mode 100644 index 00000000..8580c10c --- /dev/null +++ b/packages/timer.nix @@ -0,0 +1,21 @@ +{ pkgs }: + +pkgs.writeShellApplication { + name = "timer"; + + runtimeInputs = with pkgs; [ + _timer + coreutils + systemdMinimal + ]; + + text = '' + mins=$1 + message="''${2:-}" + + nohup _timer "$mins" "$message" &> /dev/null & + + echo "timer started for $mins min" + echo "timer started for $mins min, message: '$message'" | systemd-cat -t timer + ''; +} diff --git a/packages/unmounter.nix b/packages/unmounter.nix new file mode 100755 index 00000000..51e5d967 --- /dev/null +++ b/packages/unmounter.nix @@ -0,0 +1,36 @@ +{ pkgs }: + +pkgs.writeShellApplication { + name = "unmounter"; + + runtimeInputs = with pkgs; [ + cryptsetup + dmenu + gawk + libnotify + util-linux + ]; + + text = '' + lsblk_output="$(lsblk -nrpo "name,type,size,mountpoint")" + mounted_drives="$(echo "$lsblk_output" | awk '($2=="part"||$2="crypt")&&$4!~/\/boot|\/home$|SWAP/&&length($4)>1{printf "%s (%s)\n",$4,$3}')" + + all_unmountable="$(echo "$mounted_drives" | sed "/^$/d;s/ *$//")" + test -n "$all_unmountable" + + selected="$(echo "$all_unmountable" | dmenu -i -p "Unmount which drive?")" + selected="''${selected%% *}" + test -n "$selected" + + sudo -A umount -l "/''${selected#*/}" + notify-send "Device unmounted" "$selected has been unmounted." + + # Close the selected drive if decrypted. + cryptid="$(echo "$lsblk_output" | grep "/''${selected#*/}$")" + cryptid="''${cryptid%% *}" + test -b /dev/mapper/"''${cryptid##*/}" + sudo -A cryptsetup close "$cryptid" + + notify-send "Device dencryption closed" "Drive is now securely locked again." + ''; +} diff --git a/packages/update-all-git-repos.nix b/packages/update-all-git-repos.nix new file mode 100755 index 00000000..1ef76bf2 --- /dev/null +++ b/packages/update-all-git-repos.nix @@ -0,0 +1,33 @@ +{ pkgs }: + +pkgs.writeShellApplication { + name = "update-all-git-repos"; + + runtimeInputs = with pkgs; [ + findutils + git + ]; + + text = '' + # Update all top-level Git repository clones within my Code directories to their + # latest version. + + dirs=$(find "$XDG_REPOS_DIR" -mindepth 2 -maxdepth 3 -type d -name .git -not -path '*/*.old/*') + + for dir in $dirs; do + repo_path="''${dir%/.git}" + + cd "''${repo_path}" + + # If the repo is a bare clone, the commands need to be run within the + # worktree directory. + [[ -f .bare/worktrees/main/gitdir && -d main && -f main/.git ]] && cd main + + echo "Updating $(pwd)" + + # Update the repository. + git fetch --all --jobs=4 --progress --prune + git pull --rebase + done + ''; +} diff --git a/packages/vic.nix b/packages/vic.nix new file mode 100755 index 00000000..312f8467 --- /dev/null +++ b/packages/vic.nix @@ -0,0 +1,9 @@ +{ inputs, pkgs }: + +pkgs.writeShellApplication rec { + name = "vic"; + + runtimeInputs = with pkgs; [ neovim tmux ]; + + text = builtins.readFile "${inputs.rwxrob-dot}/scripts/${name}"; +} diff --git a/packages/vim-plugins/default.nix b/packages/vim-plugins/default.nix new file mode 100644 index 00000000..f0fc4eb0 --- /dev/null +++ b/packages/vim-plugins/default.nix @@ -0,0 +1,23 @@ +{ pkgs, lib }: + +let + pluginsData = builtins.fromJSON (builtins.readFile ./vim-plugins.json); + + mkPlugin = + name: attrs: + with attrs; + with pkgs; + vimUtils.buildVimPlugin { + inherit name version; + + src = fetchFromGitHub { + inherit + hash + owner + repo + rev + ; + }; + }; +in +lib.mapAttrs mkPlugin pluginsData diff --git a/packages/vim-plugins/vim-plugins.json b/packages/vim-plugins/vim-plugins.json new file mode 100644 index 00000000..75a148c3 --- /dev/null +++ b/packages/vim-plugins/vim-plugins.json @@ -0,0 +1,10 @@ +{ + "vim-textobj-indent": { + "owner": "kana", + "repo": "vim-textobj-indent", + "rev": "deb76867c302f933c8f21753806cbf2d8461b548", + "version": "0.0.6", + "hash": "sha256-oFzUPG+IOkbKZ2gU/kduQ3G/LsLDlEjFhRP0BHBE+1Q=" + } +} + diff --git a/requirements.yml b/requirements.yml deleted file mode 100644 index 72fe72df..00000000 --- a/requirements.yml +++ /dev/null @@ -1,2 +0,0 @@ -collections: - - name: community.general diff --git a/roles/alacritty/files/alacritty.yml b/roles/alacritty/files/alacritty.yml deleted file mode 100644 index 95c3b91f..00000000 --- a/roles/alacritty/files/alacritty.yml +++ /dev/null @@ -1,13 +0,0 @@ -window: - decorations: full - dynamic_title: false - -font: - normal: - family: JetBrainsMono Nerd Font Mono - style: Regular - bold: - style: Regular - bold_italic: - style: Italic - size: 12 diff --git a/roles/alacritty/tasks/main.yaml b/roles/alacritty/tasks/main.yaml deleted file mode 100644 index ccf6fc8b..00000000 --- a/roles/alacritty/tasks/main.yaml +++ /dev/null @@ -1,19 +0,0 @@ ---- -- name: Install - ansible.builtin.package: - name: - - alacritty - state: latest - become: true - -- name: Config folder - ansible.builtin.file: - mode: "0755" - path: "{{ ansible_user_dir }}/.config/alacritty" - state: directory - -- name: Configure - ansible.builtin.file: - src: "{{ role_path }}/files/alacritty.yml" - dest: "{{ ansible_user_dir }}/.config/alacritty/alacritty.yml" - state: link diff --git a/roles/awesome-wm/tasks/main.yaml b/roles/awesome-wm/tasks/main.yaml deleted file mode 100644 index 98dcbcf7..00000000 --- a/roles/awesome-wm/tasks/main.yaml +++ /dev/null @@ -1,7 +0,0 @@ ---- -- name: Install - ansible.builtin.package: - name: - - awesome - state: latest - become: true diff --git a/roles/cargo/tasks/main.yaml b/roles/cargo/tasks/main.yaml deleted file mode 100644 index 793c7d57..00000000 --- a/roles/cargo/tasks/main.yaml +++ /dev/null @@ -1,7 +0,0 @@ ---- -- name: Install - ansible.builtin.package: - name: - - cargo - state: latest - become: true diff --git a/roles/copyq/tasks/main.yaml b/roles/copyq/tasks/main.yaml deleted file mode 100644 index 10f28fee..00000000 --- a/roles/copyq/tasks/main.yaml +++ /dev/null @@ -1,7 +0,0 @@ ---- -- name: Install - community.general.flatpak: - name: - - com.github.hluk.copyq - method: user - state: present diff --git a/roles/ctop/tasks/main.yaml b/roles/ctop/tasks/main.yaml deleted file mode 100644 index 76fc0dc5..00000000 --- a/roles/ctop/tasks/main.yaml +++ /dev/null @@ -1,7 +0,0 @@ ---- -- name: Install - ansible.builtin.package: - name: - - ctop - state: latest - become: true diff --git a/roles/dconf/files/dconf-settings.ini b/roles/dconf/files/dconf-settings.ini deleted file mode 100644 index fe38aeb9..00000000 --- a/roles/dconf/files/dconf-settings.ini +++ /dev/null @@ -1,23 +0,0 @@ -[org/gnome/desktop/wm/keybindings] -move-to-workspace-1=['Home', '1'] -move-to-workspace-2=['2'] -move-to-workspace-3=['3'] -move-to-workspace-3=['3'] -move-to-workspace-4=['4'] -move-to-workspace-4=['4'] -move-to-workspace-5=['5'] -move-to-workspace-6=['6'] -move-to-workspace-7=['7'] -move-to-workspace-8=['8'] -move-to-workspace-9=['9'] -move-to-workspace-10=['0'] -switch-to-workspace-1=['1'] -switch-to-workspace-2=['2'] -switch-to-workspace-3=['3'] -switch-to-workspace-4=['4'] -switch-to-workspace-5=['5'] -switch-to-workspace-6=['6'] -switch-to-workspace-7=['7'] -switch-to-workspace-8=['8'] -switch-to-workspace-9=['9'] -switch-to-workspace-10=['0'] diff --git a/roles/dconf/tasks/main.yaml b/roles/dconf/tasks/main.yaml deleted file mode 100644 index dad5c451..00000000 --- a/roles/dconf/tasks/main.yaml +++ /dev/null @@ -1,6 +0,0 @@ ---- -- name: Configure - ansible.builtin.file: - src: "{{ role_path }}/files/dconf-settings.ini" - dest: "{{ ansible_user_dir }}/.config/dconf-settings.ini" - state: link diff --git a/roles/debugger/tasks/main.yaml b/roles/debugger/tasks/main.yaml deleted file mode 100644 index 59cc5b72..00000000 --- a/roles/debugger/tasks/main.yaml +++ /dev/null @@ -1,4 +0,0 @@ ---- -- include_tasks: php.yaml - tags: - - debugger diff --git a/roles/debugger/tasks/php.yaml b/roles/debugger/tasks/php.yaml deleted file mode 100644 index 966b45de..00000000 --- a/roles/debugger/tasks/php.yaml +++ /dev/null @@ -1,22 +0,0 @@ ---- -- name: Clone - ansible.builtin.git: - depth: 1 - dest: "{{ ansible_user_dir }}/build/vscode-php-debug" - force: yes - repo: https://github.com/xdebug/vscode-php-debug.git - single_branch: yes - register: clone - tags: - - debugger - -- name: Install - ansible.builtin.command: | - npm install - npm run build - args: - chdir: "{{ ansible_user_dir }}/build/vscode-php-debug" - creates: "{{ ansible_user_dir }}/build/vscode-php-debug/out" - when: clone.changed - tags: - - debugger diff --git a/roles/delta/meta/main.yaml b/roles/delta/meta/main.yaml deleted file mode 100644 index fe55fc75..00000000 --- a/roles/delta/meta/main.yaml +++ /dev/null @@ -1,3 +0,0 @@ ---- -dependencies: - - role: cargo diff --git a/roles/delta/tasks/main.yaml b/roles/delta/tasks/main.yaml deleted file mode 100644 index 30e3bcfd..00000000 --- a/roles/delta/tasks/main.yaml +++ /dev/null @@ -1,8 +0,0 @@ ---- -- name: Install - community.general.cargo: - name: - - git-delta - path: /usr/local - state: latest - become: true diff --git a/roles/discord/tasks/main.yaml b/roles/discord/tasks/main.yaml deleted file mode 100644 index 1ff87385..00000000 --- a/roles/discord/tasks/main.yaml +++ /dev/null @@ -1,7 +0,0 @@ ---- -- name: Install - community.general.flatpak: - name: - - com.discordapp.Discord - method: user - state: present diff --git a/roles/docker/tasks/main.yaml b/roles/docker/tasks/main.yaml deleted file mode 100644 index a9e07478..00000000 --- a/roles/docker/tasks/main.yaml +++ /dev/null @@ -1,22 +0,0 @@ ---- -- name: Install - ansible.builtin.package: - name: - - docker - - docker-compose - state: latest - become: yes - -- name: Enable service - ansible.builtin.systemd: - enabled: yes - name: docker - state: started - become: yes - -- name: Add to group - ansible.builtin.user: - append: yes - groups: docker - name: "{{ ansible_env['USER'] }}" - become: yes diff --git a/roles/filezilla/tasks/main.yaml b/roles/filezilla/tasks/main.yaml deleted file mode 100644 index 96aee284..00000000 --- a/roles/filezilla/tasks/main.yaml +++ /dev/null @@ -1,7 +0,0 @@ ---- -- name: Install - community.general.flatpak: - name: - - org.filezillaproject.Filezilla - method: user - state: present diff --git a/roles/flameshot/tasks/main.yaml b/roles/flameshot/tasks/main.yaml deleted file mode 100644 index 195154f4..00000000 --- a/roles/flameshot/tasks/main.yaml +++ /dev/null @@ -1,7 +0,0 @@ ---- -- name: Install - community.general.flatpak: - name: - - org.flameshot.Flameshot - method: user - state: present diff --git a/roles/fonts/tasks/main.yaml b/roles/fonts/tasks/main.yaml deleted file mode 100644 index 50fc8f2f..00000000 --- a/roles/fonts/tasks/main.yaml +++ /dev/null @@ -1,14 +0,0 @@ ---- -- name: Download - ansible.builtin.get_url: - dest: "{{ font_item.dest }}" - url: "{{ font_item.url }}" - loop_control: - loop_var: font_item - loop: - - url: "https://github.com/ryanoasis/nerd-fonts/blob/master/patched-fonts/JetBrainsMono/Ligatures/Regular/complete/JetBrains%20Mono%20Regular%20Nerd%20Font%20Complete%20Mono.ttf?raw=true" - dest: /usr/share/fonts/truetype/JetBrainsMono Nerd Font Regular - - - url: "https://github.com/ryanoasis/nerd-fonts/blob/master/patched-fonts/JetBrainsMono/Ligatures/Italic/complete/JetBrains%20Mono%20Italic%20Nerd%20Font%20Complete%20Mono.ttf?raw=true" - dest: /usr/share/fonts/truetype/JetBrainsMono Nerd Font Italic - become: true diff --git a/roles/fzf/tasks/main.yaml b/roles/fzf/tasks/main.yaml deleted file mode 100644 index aa70668f..00000000 --- a/roles/fzf/tasks/main.yaml +++ /dev/null @@ -1,7 +0,0 @@ ---- -- name: Install - ansible.builtin.package: - name: - - fzf - state: latest - become: true diff --git a/roles/git/files/.gitconfig b/roles/git/files/.gitconfig deleted file mode 100644 index 4c566204..00000000 --- a/roles/git/files/.gitconfig +++ /dev/null @@ -1,138 +0,0 @@ -[alias] - aa = add --all - assume = update-index --assume-unchanged - assumed = !git ls-files -v | grep '^[hsmrck?]' | cut -c 3- - b = branch - browse = !gh repo view --web - ca = commit --amend --verbose - car = commit --amend --no-edit - cl = !hub clone - cl = !hub clone - co = checkout - compare = !hub compare - current-branch = rev-parse --abbrev-ref HEAD - dc = diff --color --word-diff --cached - df = diff --color --word-diff - dup = !git checkout develop && git fetch origin && echo && git sl develop..origin/develop && echo && git pull --quiet && git checkout - - fixup = commit --fixup - issues = !gh issue list --web - mup = !git master-to-main-wrapper checkout %BRANCH% && git fetch origin && echo && git sl %BRANCH%..origin/%BRANCH% && echo && git pull --quiet && git checkout - - nah = !git reset --hard && git clean -fd - no-ff = merge --no-ff - pl = pull - prune = remote prune origin - ps = push - pulls = !gh pr list --web - rbc = rebase --continue - rdup = !git dup && git rebase develop - remotes = remote -v - repush = !git pull --rebase && git push - ri = rebase --interactive - rid = !git rebase -i $(git merge-base develop HEAD) - rim = !git rebase -i $(git master-to-main-wrapper merge-base %BRANCH% HEAD) - rip = !git rebase -i $(git merge-base production HEAD) - ris = !git rebase -i $(git merge-base staging HEAD) - riu = !git rebase -i $(git rev-parse --abbrev-ref --symbolic-full-name @{u}) - rmup = !git mup && git master-to-main-wrapper rebase %BRANCH% - sl = log --oneline --decorate -20 - sla = log --oneline --decorate --graph --all -20 - slap = log --oneline --decorate --graph --all - slp = log --oneline --decorate - staged = diff --staged - unassume = update-index --no-assume-unchanged - uncommit = reset --soft HEAD^ - unstage = reset - upstream = rev-parse --abbrev-ref --symbolic-full-name @{u} - ureset = !git reset --hard $(git upstream) - wip = !git add . && git commit -m 'wip' - worktrees = "worktree list" - -[branch] - autosetupmerge = true - autosetuprebase = always - -[checkout] - defaultRemote = origin - -[color] - branch = auto - diff = auto - status = auto - ui = true - -[color "branch"] - current = red reverse - local = blue - remote = green - -[color "diff"] - meta = yellow - frag = magenta - old = red bold - new = green - plain = white - -[color "status"] - added = yellow - changed = green - untracked = cyan - -[commit] - template = ~/.gitmessage - verbose = true - -[core] - editor = nvim - excludesFile = ~/.gitignore-global - pager = delta - -[delta] - line-numbers = true - -[diff] - tool = vimdiff - -[fetch] - prune = true - -[gitsh] - nogreeting = true - -[grep] - lineNumber = true - -[help] - autocorrect = 1 - -[include] - path = ~/.gitconfig.local - -[init] - templatedir = ~/.git_template - -[merge] - ff = only - -[rebase] - autosquash = true - autostash = true - -[rerere] - enabled = true - -[push] - default = upstream - -[url "https://git.drupal.org/project/"] - insteadOf = do: - insteadOf = drupal: - -[pull] - ff = only - rebase = true - -[filter "lfs"] - process = git-lfs filter-process - required = true - clean = git-lfs clean -- %f - smudge = git-lfs smudge -- %f diff --git a/roles/git/files/.gitignore b/roles/git/files/.gitignore deleted file mode 100644 index b3817e5a..00000000 --- a/roles/git/files/.gitignore +++ /dev/null @@ -1,10 +0,0 @@ -* -!*/ -!/bin/** -!/tag-*/** -/tag-php/composer/.env -/tag-php/composer/auth.json -/tag-php/composer/bin/ -/tag-php/composer/config/ -/tag-php/composer/keys.*.pub -/**/*.zwc diff --git a/roles/git/files/.gitignore-global b/roles/git/files/.gitignore-global deleted file mode 100644 index 30ff8574..00000000 --- a/roles/git/files/.gitignore-global +++ /dev/null @@ -1,43 +0,0 @@ -# Ignore archive files. -*.7z -*.dmg -*.gz -*.iso -*.phar -*.phar.version -*.rar -*.tar -*.zip - -# Ignore database exports. -*.*sql - -# Ignore patch files and interdiffs. -*.patch -*.diff -*.rej -*.orig -interdiff*.txt - -# Ignore Vagrant directories. -.vagrant/ - -# Ignore logs. -*.log - -# Ignore IDE and text editor files. -.idea/ -*.sublime-* - -# Ignore temporary directories. -.php_cs.cache -tmp/ - -# Ignore Ansible Playbook retrys. -*.retry - -# Ignore notes within projects. -.notes/ - -# Ignore directory level aliases -.aliases diff --git a/roles/git/files/.gitmessage b/roles/git/files/.gitmessage deleted file mode 100644 index 91df68da..00000000 --- a/roles/git/files/.gitmessage +++ /dev/null @@ -1,16 +0,0 @@ - - -# 50-character subject line -# -# 72-character wrapped longer description. This should answer: -# -# * Why was this change necessary? -# * How does it address the problem? -# * Are there any side effects? -# -# Include a link to the ticket, if any. -# -# Add co-authors if you worked on this code with others: -# -# Co-authored-by: Full Name -# Co-authored-by: Full Name diff --git a/roles/git/tasks/main.yaml b/roles/git/tasks/main.yaml deleted file mode 100644 index d35e7c75..00000000 --- a/roles/git/tasks/main.yaml +++ /dev/null @@ -1,24 +0,0 @@ ---- -- name: Install - ansible.builtin.package: - name: - - git - state: latest - become: true - -- name: Configuration - ansible.builtin.file: - src: "{{ role_path }}/files/{{ git_config_item }}" - dest: "{{ ansible_user_dir }}/{{ git_config_item }}" - state: link - loop_control: - loop_var: git_config_item - with_items: - - .gitconfig - - .gitignore-global - - .gitmessage - -- name: Local configuration - ansible.builtin.template: - src: gitconfig.local.j2 - dest: "{{ ansible_user_dir }}/.gitconfig.local" diff --git a/roles/git/templates/gitconfig.local.j2 b/roles/git/templates/gitconfig.local.j2 deleted file mode 100644 index 9e0e4ddc..00000000 --- a/roles/git/templates/gitconfig.local.j2 +++ /dev/null @@ -1,3 +0,0 @@ -[user] -email = {{ git_user_email }} -name = {{ git_user_name }} diff --git a/roles/github-cli/tasks/main.yaml b/roles/github-cli/tasks/main.yaml deleted file mode 100644 index 07eccffd..00000000 --- a/roles/github-cli/tasks/main.yaml +++ /dev/null @@ -1,26 +0,0 @@ ---- -- name: Existing install - ansible.builtin.stat: - path: /usr/bin/gh - register: install - -- name: Keyring - ansible.builtin.get_url: - dest: /usr/share/keyrings/githubcli-archive-keyring.gpg - mode: 644 - url: https://cli.github.com/packages/githubcli-archive-keyring.gpg - when: not install.stat.exists - become: true - -- name: Repository - ansible.builtin.apt_repository: - repo: "deb [arch=amd64 signed-by=/usr/share/keyrings/githubcli-archive-keyring.gpg] https://cli.github.com/packages stable main" - when: not install.stat.exists - become: true - -- name: Install - ansible.builtin.package: - name: - - gh - state: latest - become: true diff --git a/roles/github-desktop/tasks/main.yaml b/roles/github-desktop/tasks/main.yaml deleted file mode 100644 index bfe6d117..00000000 --- a/roles/github-desktop/tasks/main.yaml +++ /dev/null @@ -1,7 +0,0 @@ ---- -- name: Install - community.general.flatpak: - name: - - io.github.shiftey.Desktop - method: user - state: present diff --git a/roles/gnome-tweak-tools/tasks/main.yaml b/roles/gnome-tweak-tools/tasks/main.yaml deleted file mode 100644 index 681ce503..00000000 --- a/roles/gnome-tweak-tools/tasks/main.yaml +++ /dev/null @@ -1,7 +0,0 @@ ---- -- name: Install - ansible.builtin.package: - name: - - gnome-tweaks - state: latest - become: true diff --git a/roles/google-chrome/tasks/main.yaml b/roles/google-chrome/tasks/main.yaml deleted file mode 100644 index 5f7b731a..00000000 --- a/roles/google-chrome/tasks/main.yaml +++ /dev/null @@ -1,7 +0,0 @@ ---- -- name: Install - community.general.flatpak: - name: - - com.google.Chrome - method: user - state: present diff --git a/roles/htop/tasks/main.yaml b/roles/htop/tasks/main.yaml deleted file mode 100644 index 67e45dd6..00000000 --- a/roles/htop/tasks/main.yaml +++ /dev/null @@ -1,7 +0,0 @@ ---- -- name: Install - ansible.builtin.package: - name: - - htop - state: latest - become: true diff --git a/roles/jq/tasks/main.yaml b/roles/jq/tasks/main.yaml deleted file mode 100644 index 14b5912b..00000000 --- a/roles/jq/tasks/main.yaml +++ /dev/null @@ -1,7 +0,0 @@ ---- -- name: Install - ansible.builtin.package: - name: - - jq - state: latest - become: true diff --git a/roles/kdenlive/tasks/main.yaml b/roles/kdenlive/tasks/main.yaml deleted file mode 100644 index fffa23da..00000000 --- a/roles/kdenlive/tasks/main.yaml +++ /dev/null @@ -1,7 +0,0 @@ ---- -- name: Install - community.general.flatpak: - name: - - org.kde.kdenlive - method: user - state: present diff --git a/roles/mysql-client/tasks/main.yaml b/roles/mysql-client/tasks/main.yaml deleted file mode 100644 index b1a53c80..00000000 --- a/roles/mysql-client/tasks/main.yaml +++ /dev/null @@ -1,7 +0,0 @@ ---- -- name: Install - ansible.builtin.package: - name: - - mysql-client - state: latest - become: true diff --git a/roles/neovim-lsp/tasks/main.yaml b/roles/neovim-lsp/tasks/main.yaml deleted file mode 100644 index 8946c86b..00000000 --- a/roles/neovim-lsp/tasks/main.yaml +++ /dev/null @@ -1,34 +0,0 @@ ---- -- name: Install - community.general.npm: - name: "{{ npm_install_item }}" - state: latest - global: true - loop_control: - loop_var: npm_install_item - with_items: - - "@ansible/ansible-language-server" - - "@tailwindcss/language-server" - - bash-language-server - - dockerfile-language-server-nodejs - - intelephense - - typescript - - typescript-language-server - - vls - - vscode-langservers-extracted - - yaml-language-server - become: true - -- name: Create intelephense directory - ansible.builtin.file: - path: "{{ ansible_user_dir }}/intelephense" - state: directory - when: intelephense_licence is defined - -- name: Add intelephense licence key - ansible.builtin.copy: - content: "{{ intelephense_licence }}" - dest: "{{ ansible_user_dir }}/intelephense/licence.txt" - mode: 0400 - no_log: true - when: intelephense_licence is defined diff --git a/roles/neovim-packer/tasks/main.yaml b/roles/neovim-packer/tasks/main.yaml deleted file mode 100644 index 68584cda..00000000 --- a/roles/neovim-packer/tasks/main.yaml +++ /dev/null @@ -1,7 +0,0 @@ ---- -- name: Install - ansible.builtin.git: - depth: 1 - dest: "{{ ansible_user_dir }}/.local/share/nvim/site/pack/packer/start/packer.nvim" - repo: https://github.com/wbthomason/packer.nvim - single_branch: true diff --git a/roles/neovim/files/after/plugin/colorscheme.lua b/roles/neovim/files/after/plugin/colorscheme.lua deleted file mode 100644 index 32c4d156..00000000 --- a/roles/neovim/files/after/plugin/colorscheme.lua +++ /dev/null @@ -1,58 +0,0 @@ -if not pcall(require, "colorbuddy") then - return -end - -vim.opt.termguicolors = true - -require "colorbuddy".colorscheme "gruvbuddy" -require "colorizer".setup {} - -local Group = require("colorbuddy.group").Group -local c = require("colorbuddy.color").colors -local g = require("colorbuddy.group").groups -local s = require("colorbuddy.style").styles - --- Global --- Group.new("TSComment", c.none) -Group.new("TSInclude", nil) -Group.new("TSOperator", nil) -Group.new("TSPunctBracket", nil) -Group.new("TSPunctDelimiter", nil) -Group.new("WinSeparator", nil) - --- Lua -Group.new("luaTSConstant", c.blue) -Group.new("luaTSField", nil, nil) -Group.new("luaTSFuncBuiltin", nil) -Group.new("luaTSFunction", nil) -Group.new("luaTSKeyword", nil) -Group.new("luaTSKeywordFunction", c.violet) -Group.new("luaTSKeywordOperator", c.orange) -Group.new("luaTSKeywordReturn", nil) -Group.new("luaTSParameter", nil) -Group.new("luaTSPunctBracket", nil) -Group.new("luaTSString", c.blue) -Group.new("luaTSVariable", nil) - --- PHP -Group.new("phpTSInclude", nil) -Group.new("phpTSKeyword", nil) -Group.new("phpTSKeywordFunction", nil) -Group.new("phpTSMethod", c.blue) -Group.new("phpTSOperator", nil) -Group.new("phpTSVariableBuiltin", nil) -Group.new("phpTSNamespace", c.blue) - --- JavaScript -Group.new("javascriptTSConstructor", c.blue) -Group.new("javascriptTSException", c.red) -Group.new("javascriptTSFunction", c.none) -Group.new("javascriptTSMethod", nil) -Group.new("javascriptTSProperty", nil) -Group.new("javascriptTSVariable", c.blue) - --- TypeScript -Group.new("typescriptTSConditional", c.none) -Group.new("typescriptTSKeyword", c.none) -Group.new("typescriptTSProperty", c.violet) -Group.new("typescriptTSType", c.blue) diff --git a/roles/neovim/files/after/plugin/comment.lua b/roles/neovim/files/after/plugin/comment.lua deleted file mode 100644 index eb350eb9..00000000 --- a/roles/neovim/files/after/plugin/comment.lua +++ /dev/null @@ -1,19 +0,0 @@ -local status_ok, comment = pcall(require, "Comment") -if not status_ok then - return -end - -comment.setup { - padding = true, - - opleader = { - line = "gc", - block = "gb", - }, - - mappings = { - basic = true, - extra = true, - extended = false, - }, -} diff --git a/roles/neovim/files/after/plugin/completion.lua b/roles/neovim/files/after/plugin/completion.lua deleted file mode 100644 index ec04244b..00000000 --- a/roles/neovim/files/after/plugin/completion.lua +++ /dev/null @@ -1,74 +0,0 @@ -local cmp_status_ok, cmp = pcall(require, "cmp") -if not cmp_status_ok then - return -end - -local snip_status_ok, luasnip = pcall(require, "luasnip") -if not snip_status_ok then - return -end - -vim.opt.shortmess:append "c" - -cmp.setup { - snippet = { - expand = function(args) - luasnip.lsp_expand(args.body) - end, - }, - - mapping = cmp.mapping.preset.insert { - [""] = cmp.mapping.scroll_docs(-4), - [""] = cmp.mapping.close(), - [""] = cmp.mapping.scroll_docs(4), - [""] = cmp.mapping.confirm { select = true }, - [""] = cmp.config.disable, - }, - - sources = { - { name = "nvim_lsp" }, - { name = "nvim_lua" }, - { name = "cmp_tabnine" }, - { name = "path" }, - { name = "luasnip" }, - { name = "buffer", keyword_length = 5, max_item_count = 5 }, - }, - - sorting = { - comparators = { - cmp.config.compare.offset, - cmp.config.compare.exact, - cmp.config.compare.score, - cmp.config.compare.kind, - cmp.config.compare.sort_text, - cmp.config.compare.length, - cmp.config.compare.order, - }, - }, - - formatting = { - format = require("lspkind").cmp_format { - with_text = true, - menu = { - buffer = "[buf]", - cmp_tabnine = "[tn]", - luasnip = "[snip]", - nvim_lsp = "[lsp]", - nvim_lua = "[lua]", - path = "[path]", - }, - }, - }, - - experimental = { - ghost_text = false, - native_menu = false, - }, -} - -vim.cmd [[ - augroup DadbodSql - au! - autocmd FileType sql,mysql,plsql lua require('cmp').setup.buffer { sources = { { name = 'vim-dadbod-completion' } } } - augroup END -]] diff --git a/roles/neovim/files/after/plugin/dap.lua b/roles/neovim/files/after/plugin/dap.lua deleted file mode 100644 index 269110c8..00000000 --- a/roles/neovim/files/after/plugin/dap.lua +++ /dev/null @@ -1,74 +0,0 @@ -local has_dap, dap = pcall(require, "dap") -if not has_dap then - return -end - -local has_dap_ui, dapui = pcall(require, "dapui") -if not has_dap_ui then - return -end - -dap.adapters.php = { - type = "executable", - command = "node", - args = { os.getenv("HOME") .. "/build/vscode-php-debug/out/phpDebug.js" } -} - -dap.configurations.php = { - { - type = "php", - request = "launch", - name = "Listen for Xdebug", - port = 9003, - pathMappings = { - ["/var/www/html"] = "${workspaceFolder}" - } - } -} - -dap.listeners.after.event_initialized["dapui_config"] = function() - dapui.open() -end - -dap.listeners.before.event_terminated["dapui_config"] = function() - dapui.close() -end - -dap.listeners.before.event_exited["dapui_config"] = function() - dapui.close() -end - -require "dapui".setup { - layouts = { - { - elements = { - { id = "scopes", size = 0.25 }, - "breakpoints", - "stacks", - "watches", - }, - size = 40, -- 40 columns - position = "right", - }, - { - elements = { - "repl", - "console", - }, - size = 0.25, -- 25% of total lines - position = "bottom", - }, - } -} - -require "nvim-dap-virtual-text".setup { - commented = true, -} - -local nmap = require "opdavies.keymap".nmap - -nmap { "", ":lua require'dap'.step_over()" } -nmap { "", ":lua require'dap'.step_into()" } -nmap { "", ":lua require'dap'.step_over()" } -nmap { "", ":lua require'dap'.continue()" } -nmap { "b", ":lua require'dap'.toggle_breakpoint()" } diff --git a/roles/neovim/files/after/plugin/dial.lua b/roles/neovim/files/after/plugin/dial.lua deleted file mode 100644 index 0b4d1098..00000000 --- a/roles/neovim/files/after/plugin/dial.lua +++ /dev/null @@ -1,52 +0,0 @@ -local status_ok, dial_config = pcall(require, "dial.config") -if not status_ok then - return -end - -local augend = require "dial.augend" - -dial_config.augends:register_group { - visual = { - augend.integer.alias.decimal, - augend.integer.alias.hex, - augend.date.alias["%Y/%m/%d"], - augend.constant.alias.alpha, - augend.constant.alias.Alpha, - }, - - mygroup = { - augend.constant.new { - elements = { "TRUE", "FALSE" }, - word = true, - cyclic = true, - }, - - augend.constant.new { - elements = { "public", "protected", "private" }, - word = true, - cyclic = true, - }, - - augend.constant.new { - elements = { "&&", "||" }, - word = false, - cyclic = true, - }, - - augend.date.alias["%d/%m/%Y"], - augend.constant.alias.bool, -- boolean value (true <-> false) - augend.integer.alias.decimal, - augend.integer.alias.hex, - augend.semver.alias.semver - }, -} - -local dial_map = require "dial.map" - -local nmap = require "opdavies.keymap".nmap -local vmap = require "opdavies.keymap".vmap - -nmap({ "", dial_map.inc_normal "mygroup" }) -nmap({ "", dial_map.dec_normal "mygroup" }) -vmap({ "", dial_map.inc_normal "visual" }) -vmap({ "", dial_map.dec_normal "visual" }) diff --git a/roles/neovim/files/after/plugin/fidget.lua b/roles/neovim/files/after/plugin/fidget.lua deleted file mode 100644 index 8f7deeec..00000000 --- a/roles/neovim/files/after/plugin/fidget.lua +++ /dev/null @@ -1,6 +0,0 @@ -local status_ok, fidget = pcall(require, "fidget") -if not status_ok then - return -end - -fidget.setup {} diff --git a/roles/neovim/files/after/plugin/git.lua b/roles/neovim/files/after/plugin/git.lua deleted file mode 100644 index b2572e59..00000000 --- a/roles/neovim/files/after/plugin/git.lua +++ /dev/null @@ -1,30 +0,0 @@ -local status_ok, neogit = pcall(require, "neogit") -if not status_ok then - return -end - -neogit.setup { - disable_commit_confirmation = true, -} - -local nmap = require("opdavies.keymap").nmap - -nmap { - "gc", - function() - neogit.open { "commit" } - end, -} -nmap { - "gl", - function() - neogit.open { "log" } - end, -} -nmap { - "gp", - function() - neogit.open { "push" } - end, -} -nmap { "gs", neogit.open } diff --git a/roles/neovim/files/after/plugin/gitsigns.lua b/roles/neovim/files/after/plugin/gitsigns.lua deleted file mode 100644 index 3cd84a21..00000000 --- a/roles/neovim/files/after/plugin/gitsigns.lua +++ /dev/null @@ -1,31 +0,0 @@ -local colorbuddy_status_ok, colorbuddy = pcall(require, "colorbuddy") -if not colorbuddy_status_ok then - return -end - -local gitsigns_status_ok, gitsigns = pcall(require, "gitsigns") -if not gitsigns_status_ok then - return -end - -local c = require("colorbuddy.color").colors -local Group = require("colorbuddy.group").Group - -Group.new("GitSignsAdd", c.green) -Group.new("GitSignsChange", c.yellow) -Group.new("GitSignsDelete", c.red) - -gitsigns.setup { - linehl = false, - numhl = true, - - signs = { - add = { hl = "GitSignsAdd", text = "│", numhl = "GitSignsAddNr" }, - change = { hl = "GitSignsChange", text = "│", numhl = "GitSignsChangeNr" }, - delete = { hl = "GitSignsDelete", text = "_", numhl = "GitSignsDeleteNr" }, - topdelete = { hl = "GitSignsDelete", text = "‾", numhl = "GitSignsDeleteNr" }, - changedelete = { hl = "GitSignsDelete", text = "~", numhl = "GitSignsChangeNr" }, - }, - - word_diff = false, -} diff --git a/roles/neovim/files/after/plugin/harpoon.lua b/roles/neovim/files/after/plugin/harpoon.lua deleted file mode 100644 index d56c3918..00000000 --- a/roles/neovim/files/after/plugin/harpoon.lua +++ /dev/null @@ -1,20 +0,0 @@ -local status_ok, harpoon = pcall(require, "harpoon") -if not status_ok then - return -end - -local nmap = require("opdavies.keymap").nmap - -harpoon.setup {} - -nmap { "", require("harpoon.ui").toggle_quick_menu } -nmap { "", require("harpoon.mark").add_file } - -for i = 1, 5 do - nmap { - string.format("%s", i), - function() - require("harpoon.ui").nav_file(i) - end, - } -end diff --git a/roles/neovim/files/after/plugin/indent-blankline.lua b/roles/neovim/files/after/plugin/indent-blankline.lua deleted file mode 100644 index d48f1153..00000000 --- a/roles/neovim/files/after/plugin/indent-blankline.lua +++ /dev/null @@ -1,18 +0,0 @@ -local status_ok, indent_blankline = pcall(require, "indent_blankline") -if not status_ok then - return -end - -vim.opt.list = true -vim.opt.listchars = { - eol = "↴", -} - -vim.cmd [[highlight IndentBlanklineIndent1 guifg=#555555 gui=nocombine]] - -indent_blankline.setup { - char_highlight_list = { - "IndentBlanklineIndent1", - }, - show_end_of_line = true, -} diff --git a/roles/neovim/files/after/plugin/lir.lua b/roles/neovim/files/after/plugin/lir.lua deleted file mode 100644 index f59bfc9a..00000000 --- a/roles/neovim/files/after/plugin/lir.lua +++ /dev/null @@ -1,67 +0,0 @@ -local has_lir, lir = pcall(require, "lir") -if not has_lir then - return -end - -local actions = require "lir.actions" -local clipboard_actions = require "lir.clipboard.actions" -local mark_actions = require "lir.mark.actions" - -lir.setup { - hide_cursor = true, - show_hidden_files = true, - devicons_enable = true, - - mappings = { - ["l"] = actions.edit, - [""] = actions.split, - [""] = actions.vsplit, - [""] = actions.tabedit, - - ["h"] = actions.up, - ["q"] = actions.quit, - - ["K"] = actions.mkdir, - ["N"] = actions.newfile, - ["R"] = actions.rename, - ["@"] = actions.cd, - ["Y"] = actions.yank_path, - ["."] = actions.toggle_show_hidden, - ["D"] = actions.delete, - - ["J"] = function() - mark_actions.toggle_mark() - vim.cmd "normal! j" - end, - - ["C"] = clipboard_actions.copy, - ["X"] = clipboard_actions.cut, - ["P"] = clipboard_actions.paste, - }, - - float = { - winblend = 0, - curdir_window = { - enable = false, - highlight_dirname = false, - }, - }, - - on_init = function() - -- use visual mode - vim.api.nvim_buf_set_keymap( - 0, - "x", - "J", - ':lua require"lir.mark.actions".toggle_mark("v")', - { noremap = true, silent = true } - ) - - -- echo cwd - vim.api.nvim_echo({ { vim.fn.expand "%:p", "Normal" } }, false, {}) - end, -} - -require("lir.git_status").setup { - show_ignored = false, -} diff --git a/roles/neovim/files/after/plugin/lualine.lua b/roles/neovim/files/after/plugin/lualine.lua deleted file mode 100644 index fdf27a14..00000000 --- a/roles/neovim/files/after/plugin/lualine.lua +++ /dev/null @@ -1,6 +0,0 @@ -local status_ok, lualine = pcall(require, "lualine") -if not status_ok then - return -end - -lualine.setup {} diff --git a/roles/neovim/files/after/plugin/luasnip.lua b/roles/neovim/files/after/plugin/luasnip.lua deleted file mode 100644 index cbb87891..00000000 --- a/roles/neovim/files/after/plugin/luasnip.lua +++ /dev/null @@ -1,95 +0,0 @@ -if not pcall(require, "luasnip") then - return -end - -local api = vim.api -local fn = vim.fn - -local ls = require "luasnip" - -local snippet = ls.snippet -local t = ls.text_node - -local shortcut = function(val) - if type(val) == "string" then - return { t { val }, i(0) } - end - - if type(val) == "table" then - for k, v in ipairs(val) do - if type(v) == "string" then - val[k] = t { v } - end - end - end - - return val -end - -local make = function(tbl) - local result = {} - for k, v in pairs(tbl) do - table.insert(result, (snippet({ trig = k, desc = v.desc }, shortcut(v)))) - end - - return result -end - -local snippets = {} - -for _, ft_path in ipairs(api.nvim_get_runtime_file("lua/opdavies/snippets/ft/*.lua", true)) do - local ft = fn.fnamemodify(ft_path, ":t:r") - snippets[ft] = make(loadfile(ft_path)()) - - ls.add_snippets(ft, snippets[ft]) -end - -ls.add_snippets("js", snippets.javascript) -ls.add_snippets("typescript", snippets.javascript) -ls.add_snippets("vue", snippets.javascript) - -ls.config.set_config { - enable_autosnippets = true, - history = true, - updateevents = "TextChanged,TextChangedI", -} - -local imap = require("opdavies.keymap").imap -local map = require("opdavies.keymap").map -local nmap = require("opdavies.keymap").nmap - --- Expand the current item or just to the next item within the snippet. -map { - { "i", "s" }, - "", - function() - if ls.expand_or_jumpable() then - ls.expand_or_jump() - end - end, - { silent = true }, -} - --- Jump backwards. -map { - { "i", "s" }, - "", - function() - if ls.jumpable(-1) then - ls.jump(-1) - end - end, - { silent = true }, -} - --- Select within a list of options. -imap { - "", - function() - if ls.choice_active() then - ls.change_choice(1) - end - end, -} - -nmap { "s", "source ~/.config/nvim/after/plugin/luasnip.lua" } diff --git a/roles/neovim/files/after/plugin/markdown-preview.lua b/roles/neovim/files/after/plugin/markdown-preview.lua deleted file mode 100644 index d895e4b8..00000000 --- a/roles/neovim/files/after/plugin/markdown-preview.lua +++ /dev/null @@ -1 +0,0 @@ -vim.g.mkdp_refresh_slow = 1 diff --git a/roles/neovim/files/after/plugin/nvim-rest.lua b/roles/neovim/files/after/plugin/nvim-rest.lua deleted file mode 100644 index 1bc5b33f..00000000 --- a/roles/neovim/files/after/plugin/nvim-rest.lua +++ /dev/null @@ -1,17 +0,0 @@ -local status_ok, rest_nvim = pcall(require, "rest-nvim") -if not status_ok then - return -end - -local nmap = require("opdavies.keymap").nmap - --- Run the request. -nmap { "rr", "require('rest-nvim').run()" } - --- Preview the request. -nmap { "rp", "require('rest-nvim').run(true)" } - --- Re-run the last request. -nmap { "rl", "require('rest-nvim').last()" } - -rest_nvim.setup() diff --git a/roles/neovim/files/after/plugin/refactoring.lua b/roles/neovim/files/after/plugin/refactoring.lua deleted file mode 100644 index 2eb06587..00000000 --- a/roles/neovim/files/after/plugin/refactoring.lua +++ /dev/null @@ -1,18 +0,0 @@ -local status_ok, refactoring = pcall(require, "refactoring") -if not status_ok then - return -end - -local nmap = require("opdavies.keymap").nmap -local vmap = require("opdavies.keymap").vmap - --- TODO: add keymaps - https://github.com/ThePrimeagen/refactoring.nvim#configuration-for-refactoring-operations -refactoring.setup {} - -local opts = { silent = true } - -nmap { "ri", "lua require 'refactoring'.refactor 'Inline Variable'", opts } - -vmap { "re", "lua require 'refactoring'.refactor 'Extract Function'", opts } -vmap { "ri", "lua require 'refactoring'.refactor 'Inline Variable'", opts } -vmap { "rv", "lua require 'refactoring'.refactor 'Extract Variable'", opts } diff --git a/roles/neovim/files/after/plugin/seiya.lua b/roles/neovim/files/after/plugin/seiya.lua deleted file mode 100644 index 91ee4ab0..00000000 --- a/roles/neovim/files/after/plugin/seiya.lua +++ /dev/null @@ -1,3 +0,0 @@ --- vim.g.seiya_auto_enable = 1 - --- vim.g.seiya_target_groups = { "guibg" } diff --git a/roles/neovim/files/after/plugin/statusline.lua b/roles/neovim/files/after/plugin/statusline.lua deleted file mode 100644 index 65f47555..00000000 --- a/roles/neovim/files/after/plugin/statusline.lua +++ /dev/null @@ -1,81 +0,0 @@ -local status_ok, el = pcall(require, "el") -if not status_ok then - return -end - -local builtin = require "el.builtin" -local diagnostic = require "el.diagnostic" -local extensions = require "el.extensions" -local lsp_statusline = require "el.plugins.lsp_status" -local sections = require "el.sections" -local subscribe = require "el.subscribe" - -local file_icon = subscribe.buf_autocmd("el_file_icon", "BufRead", function(_, buffer) - return extensions.file_icon(_, buffer) -end) - -local git_branch = subscribe.buf_autocmd("el_git_branch", "BufEnter", function(window, buffer) - local branch = extensions.git_branch(window, buffer) - if branch then - return " " .. extensions.git_icon() .. " " .. branch - end -end) - -local git_changes = subscribe.buf_autocmd("el_git_changes", "BufWritePost", function(window, buffer) - return extensions.git_changes(window, buffer) -end) - -local show_current_func = function(window, buffer) - if buffer.filetype == "lua" then - return "" - end - - return lsp_statusline.current_function(window, buffer) -end - -local diagnostic_display = diagnostic.make_buffer() - -el.setup { - generator = function(window, buffer) - local mode = extensions.gen_mode { format_string = " %s " } - - local items = { - { mode }, - { git_branch }, - { sections.split }, - { file_icon }, - { " " }, - { sections.maximum_width(builtin.make_responsive_file(140, 90), 0.40) }, - { sections.collapse_builtin { { " " }, { builtin.modified_flag } } }, - { sections.split }, - { diagnostic_display }, - { show_current_func }, - { git_changes }, - { "[" }, - { builtin.line_with_width(3) }, - { ":" }, - { builtin.column_with_width(2) }, - { "]" }, - { - sections.collapse_builtin { - "[", - builtin.help_list, - builtin.readonly_list, - "]", - }, - }, - { builtin.filetype }, - } - - local add_item = function(result, item) - table.insert(result, item) - end - - local result = {} - for _, item in ipairs(items) do - add_item(result, item) - end - - return result - end, -} diff --git a/roles/neovim/files/after/plugin/terminal.vim b/roles/neovim/files/after/plugin/terminal.vim deleted file mode 100644 index 557fc6b6..00000000 --- a/roles/neovim/files/after/plugin/terminal.vim +++ /dev/null @@ -1,9 +0,0 @@ -function! s:small_terminal() abort - new - wincmd J - call nvim_win_set_height(0, 12) - set winfixheight - term -endfunction - -nnoremap st :call small_terminal() diff --git a/roles/neovim/files/after/plugin/todo-comments.lua b/roles/neovim/files/after/plugin/todo-comments.lua deleted file mode 100644 index 3de9789c..00000000 --- a/roles/neovim/files/after/plugin/todo-comments.lua +++ /dev/null @@ -1,6 +0,0 @@ -local status_ok, todo_comments = pcall(require, "todo-comments") -if not status_ok then - return -end - -todo_comments.setup {} diff --git a/roles/neovim/files/after/plugin/treesitter.lua b/roles/neovim/files/after/plugin/treesitter.lua deleted file mode 100644 index 91a4fb1f..00000000 --- a/roles/neovim/files/after/plugin/treesitter.lua +++ /dev/null @@ -1,66 +0,0 @@ -local has_configs, configs = pcall(require, "nvim-treesitter.configs") -if not has_configs then - return -end - -configs.setup { - context_commenting = { - enable = true, - }, - ensure_installed = { - "bash", - "comment", - "css", - "dockerfile", - "go", - "html", - "javascript", - "json", - "lua", - "make", - "markdown", - "php", - "regex", - "rst", - "scss", - "typescript", - "vim", - "vue", - "yaml", - }, - highlight = { - enable = true, - }, - indent = { - disable = { "yaml" }, - enable = true, - }, - matchup = { - enable = true, - }, - textobjects = { - select = { - enable = true, - lookahead = true, - - keymaps = { - ["af"] = "@function.outer", - ["if"] = "@function.inner", - ["ac"] = "@class.outer", - ["ic"] = "@class.inner", - }, - }, - }, -} - -local nmap = require("opdavies.keymap").nmap - -nmap { "th", "TSHighlightCapturesUnderCursor" } -nmap { "tp", "TSPlaygroundToggle" } - -local has_context, context = pcall(require, "treesitter-context") -if not has_context then - return -end - -context.setup { enable = true } diff --git a/roles/neovim/files/after/plugin/twilight.lua b/roles/neovim/files/after/plugin/twilight.lua deleted file mode 100644 index 2cdb09cf..00000000 --- a/roles/neovim/files/after/plugin/twilight.lua +++ /dev/null @@ -1,8 +0,0 @@ -local status_ok, twilight = pcall(require, "twilight") -if not status_ok then - return -end - -twilight.setup { - context = 2, -} diff --git a/roles/neovim/files/after/plugin/vim-test.lua b/roles/neovim/files/after/plugin/vim-test.lua deleted file mode 100644 index 9d09379a..00000000 --- a/roles/neovim/files/after/plugin/vim-test.lua +++ /dev/null @@ -1,15 +0,0 @@ -local map = vim.api.nvim_set_keymap - -local options = { - silent = true, -} - -map("n", "t", ":TestFile", options) -map("n", "t", ":TestVisit", options) -map("n", "t", ":TestLast", options) -map("n", "t", ":TestNearest", options) -map("n", "t", ":TestSuite", options) - -vim.g["test#echo_command"] = 0 -vim.g["test#neovim#start_normal"] = 1 -vim.g["test#strategy"] = "vimux" diff --git a/roles/neovim/files/after/plugin/zen-mode.lua b/roles/neovim/files/after/plugin/zen-mode.lua deleted file mode 100644 index acd6d2ea..00000000 --- a/roles/neovim/files/after/plugin/zen-mode.lua +++ /dev/null @@ -1,25 +0,0 @@ -local status_ok, zen_mode = pcall(require, "zen-mode") -if not status_ok then - return -end - -zen_mode.setup { - window = { - backdrop = 0.95, - height = 1, - width = 80, - options = { - relativenumber = false, - number = false, - signcolumn = "no", - }, - }, - plugins = { - options = { - enabled = true, - ruler = false, - }, - gitsigns = { enabled = true }, - tmux = { enabled = true }, - }, -} diff --git a/roles/neovim/files/autoload/opdavies.vim b/roles/neovim/files/autoload/opdavies.vim deleted file mode 100644 index 449666bf..00000000 --- a/roles/neovim/files/autoload/opdavies.vim +++ /dev/null @@ -1,12 +0,0 @@ -if !exists('*opdavies#save_and_exec') - function! opdavies#save_and_exec() abort - if &filetype == 'vim' - :silent! write - :source % - elseif &filetype == 'lua' - :silent! write - :luafile % - endif - return - endfunction -endif diff --git a/roles/neovim/files/init.lua b/roles/neovim/files/init.lua deleted file mode 100644 index 2f8e49dc..00000000 --- a/roles/neovim/files/init.lua +++ /dev/null @@ -1,12 +0,0 @@ -pcall("require", impatient) - -require "opdavies.globals" - -require("opdavies.options").setup() - -require "opdavies.plugins" - -require "opdavies.lsp" - -require "opdavies.telescope.setup" -require "opdavies.telescope.mappings" diff --git a/roles/neovim/files/lua/opdavies/globals.lua b/roles/neovim/files/lua/opdavies/globals.lua deleted file mode 100644 index d6fd70c6..00000000 --- a/roles/neovim/files/lua/opdavies/globals.lua +++ /dev/null @@ -1,13 +0,0 @@ -P = function(v) - print(vim.inspect(v)) - return v -end - -RELOAD = function(...) - return require("plenary.reload").reload_module(...) -end - -R = function(name) - RELOAD(name) - return require(name) -end diff --git a/roles/neovim/files/lua/opdavies/keymap.lua b/roles/neovim/files/lua/opdavies/keymap.lua deleted file mode 100644 index df7d5f32..00000000 --- a/roles/neovim/files/lua/opdavies/keymap.lua +++ /dev/null @@ -1,23 +0,0 @@ -local M = {} - -M.imap = function(tbl) - vim.keymap.set("i", tbl[1], tbl[2], tbl[3]) -end - -M.map = function(tbl) - vim.keymap.set(tbl[1], tbl[2], tbl[3], tbl[4] or {}) -end - -M.nmap = function(tbl) - vim.keymap.set("n", tbl[1], tbl[2], tbl[3]) -end - -M.vmap = function(tbl) - vim.keymap.set("v", tbl[1], tbl[2], tbl[3]) -end - -M.xmap = function(tbl) - vim.keymap.set("x", tbl[1], tbl[2], tbl[3]) -end - -return M diff --git a/roles/neovim/files/lua/opdavies/lsp/init.lua b/roles/neovim/files/lua/opdavies/lsp/init.lua deleted file mode 100644 index 96d14084..00000000 --- a/roles/neovim/files/lua/opdavies/lsp/init.lua +++ /dev/null @@ -1,166 +0,0 @@ -local has_lsp, lspconfig = pcall(require, "lspconfig") -if not has_lsp then - return -end - -local nvim_status = require "lsp-status" - -local imap = require("opdavies.keymap").imap -local nmap = require("opdavies.keymap").nmap - -local telescope_mapper = require "opdavies.telescope.mappings" - -local buf_nnoremap = function(opts) - opts.buffer = 0 - nmap(opts) -end - -local buf_inoremap = function(opts) - opts.buffer = 0 - imap(opts) -end - -local updated_capabilities = vim.lsp.protocol.make_client_capabilities() -updated_capabilities = require("cmp_nvim_lsp").update_capabilities(updated_capabilities) - -local custom_init = function(client) - client.config.flags = client.config.flags or {} - client.config.flags.allow_incremental_sync = true -end - -local custom_attach = function(client) - local filetype = vim.api.nvim_buf_get_option(0, "filetype") - - nvim_status.on_attach(client) - - -- Keymaps - buf_inoremap { "", vim.lsp.buf.signature_help } - - buf_nnoremap { "ca", vim.lsp.buf.code_action } - buf_nnoremap { "dn", vim.diagnostic.goto_next } - buf_nnoremap { "dp", vim.diagnostic.goto_prev } - buf_nnoremap { "f", vim.lsp.buf.format } - buf_nnoremap { "rn", vim.lsp.buf.rename } - buf_nnoremap { "rr", "LspRestart" } - buf_nnoremap { "K", vim.lsp.buf.hover } - buf_nnoremap { "gD", vim.lsp.buf.declaration } - buf_nnoremap { "gT", vim.lsp.buf.type_definition } - buf_nnoremap { "gd", vim.lsp.buf.definition } - buf_nnoremap { "gi", vim.lsp.buf.implementation } - - if filetype ~= "lua" then - buf_nnoremap { "K", vim.lsp.buf.hover } - end - - telescope_mapper("dl", "diagnostics", nil, true) - - -- Set autocommands conditional on server_capabilities - if client.server_capabilities.document_highlight then - vim.cmd [[ - augroup lsp_document_highlight - autocmd! * - autocmd CursorHold lua vim.lsp.buf.document_highlight() - autocmd CursorMoved lua vim.lsp.buf.clear_references() - augroup END - ]] - end - - -- Attach any filetype specific options to the client - -- filetype_attach[filetype](client) -end - -local servers = { - ansiblels = true, - bashls = true, - cssls = true, - gopls = true, - html = true, - -- intelephense = true - tsserver = true, - vuels = true, - yamlls = true, - - intelephense = { - filetypes = { "php", "module", "test", "inc" }, - }, - - sumneko_lua = { - settings = { - Lua = { - diagnostics = { - globals = { "vim" }, - }, - }, - }, - }, - - tailwindcss = { - filetypes = { - -- html - "html", - "html.twig", - "php", - "twig", - - -- js - "javascript", - "typescript", - - -- mixed - "vue", - }, - - init_options = { - userLanguages = { - ["html.twig"] = "html", - }, - }, - }, - - -- tsserver = { - -- filetypes = { - -- "javascript", - -- "javascriptreact", - -- "javascript.jsx", - -- "typescript", - -- "typescriptreact", - -- "typescript.tsx", - -- "vue", - -- }, - -- }, -} - -local setup_server = function(server, config) - if not config then - return - end - - if type(config) ~= "table" then - config = {} - end - - config = vim.tbl_deep_extend("force", { - on_init = custom_init, - on_attach = custom_attach, - capabilities = updated_capabilities, - flags = { - debounce_text_changes = nil, - }, - }, config) - - lspconfig[server].setup(config) -end - -for server, config in pairs(servers) do - setup_server(server, config) -end - -vim.diagnostic.config { - signs = true, - underline = false, - update_in_insert = false, - virtual_text = { spacing = 2 }, -} - -require "opdavies.lsp.null-ls" -require "opdavies.lsp.signature" diff --git a/roles/neovim/files/lua/opdavies/lsp/null-ls.lua b/roles/neovim/files/lua/opdavies/lsp/null-ls.lua deleted file mode 100644 index 5fc1c0e4..00000000 --- a/roles/neovim/files/lua/opdavies/lsp/null-ls.lua +++ /dev/null @@ -1,36 +0,0 @@ -local status_ok, null_ls = pcall(require, "null-ls") -if not status_ok then - return -end - -local lsp_formatting = function(bufnr) - vim.lsp.buf.format { - filter = function(client) - return client.name == "null-ls" - end, - bufnr = bufnr, - } -end - -local augroup = vim.api.nvim_create_augroup("LspFormatting", {}) - -local completion = null_ls.builtins.completion -local diagnostics = null_ls.builtins.diagnostics -local formatting = null_ls.builtins.formatting - -null_ls.setup { - sources = { - formatting.phpcbf, - formatting.markdownlint, - formatting.prettier, - formatting.rustywind, - formatting.stylua, - - diagnostics.eslint, - diagnostics.markdownlint, - diagnostics.php, - diagnostics.phpcs, - diagnostics.phpstan, - diagnostics.shellcheck, - }, -} diff --git a/roles/neovim/files/lua/opdavies/lsp/signature.lua b/roles/neovim/files/lua/opdavies/lsp/signature.lua deleted file mode 100644 index 365c9739..00000000 --- a/roles/neovim/files/lua/opdavies/lsp/signature.lua +++ /dev/null @@ -1,6 +0,0 @@ -local status_ok, lsp_signature = pcall(require, "lsp_signature") -if not status_ok then - return -end - -lsp_signature.setup {} diff --git a/roles/neovim/files/lua/opdavies/options.lua b/roles/neovim/files/lua/opdavies/options.lua deleted file mode 100644 index 8073ced4..00000000 --- a/roles/neovim/files/lua/opdavies/options.lua +++ /dev/null @@ -1,172 +0,0 @@ -local M = {} - -local function set_autocmd() - vim.cmd [[ - autocmd BufRead,BufNewFile *.test set filetype=php - - autocmd BufWritePost plugins.lua luafile % - autocmd BufWritePost plugins.lua PackerSync - - autocmd FileType gitcommit highlight ColorColumn ctermbg=8 - autocmd FileType gitcommit setlocal colorcolumn=50,72 - autocmd FileType gitcommit setlocal spell - autocmd FileType gitcommit setlocal textwidth=72 - ]] - - -- Automatically resize buffers when Vim is resized. - vim.api.nvim_create_autocmd("VimResized *", { command = ":wincmd =" }) - - -- Cursorline highlighting control. - -- Only have it on in the current buffer. - local group = vim.api.nvim_create_augroup("CursorLineControl", { clear = true }) - local set_cursorline = function(event, value, pattern) - vim.api.nvim_create_autocmd(event, { - group = group, - pattern = pattern, - callback = function() - vim.opt_local.cursorline = value - end, - }) - end - set_cursorline("WinLeave", false) - set_cursorline("WinEnter", true) - set_cursorline("FileType", false, "TelescopePrompt") -end - -local function set_filetypes() - vim.cmd [[ - filetype indent on - filetype on - filetype plugin on - ]] -end - -local function set_key_mappings() - local map = vim.api.nvim_set_keymap - - local options = { noremap = true } - - map("n", "so", ":call opdavies#save_and_exec()", options) - - -- Format paragraphs to an 80 character line length. - map("n", "g", "gqap", options) - map("x", "g", "gqa", options) - - -- Make the current file executable - map("n", "x", ":!chmod +x %", options) - - -- Yank from the current column to the end of the line - map("n", "Y", "yg$", options) - - -- Keep things centred - map("n", "n", "nzzzv", options) - map("n", "N", "Nzzzv", options) - - -- Remove arrow keys - map("v", "", "", options) - map("v", "", "", options) - map("v", "", "", options) - map("v", "", "", options) - - -- Clears hlsearch after doing a search, otherwise just does normal stuff - vim.cmd [[ nnoremap {-> v:hlsearch ? ":nohl\" : "\"}() ]] - - map("n", "", ":silent !tmux neww tmux-sessioniser", { noremap = true, silent = true }) - - local keymap = require "opdavies.keymap" - local imap = keymap.imap - local nmap = keymap.nmap - local vmap = keymap.vmap - local xmap = keymap.xmap - - -- Easy insertion of a trailing ; or , from insert mode - imap { ",,", "A," } - imap { ";;", "A;" } - - nmap { "ga", "(EasyAlign)" } - xmap { "ga", "(EasyAlign)" } - - -- Focus on the current buffer. - nmap { "-", ":wincmd _:wincmd |", { noremap = true, silent = true } } - - -- Automatically resize buffers. - nmap { "=", ":wincmd =", { noremap = true, silent = true } } - - -- Move line(s) up and down. - local opts = { noremap = true, silent = true } - imap { "", ":m .+1==gi", opts } - imap { "", ":m .-2==gi", opts } - nmap { "", ":m .+1==", opts } - nmap { "", ":m .-2==", opts } - vmap { "", ":m '>+1gv=gv", opts } - vmap { "", ":m '<-2gv=gv", opts } - - -- Move half a screen up or down and re-center. - nmap { "", "zz" } - nmap { "", "zz" } -end - -local function set_highlights() - vim.cmd [[highlight Comment cterm=italic gui=italic]] -end - -local function set_vim_g() - vim.g.mapleader = " " -end - -local function set_vim_o() - local settings = { - autoindent = true, - breakindent = true, - conceallevel = 0, - cursorline = true, - expandtab = true, - foldlevel = 1, - foldlevelstart = 99, - foldmethod = "indent", - formatoptions = "lm", - hidden = false, - linebreak = true, - mouse = "n", - number = true, - pumblend = 10, - pumheight = 10, - relativenumber = true, - scrolloff = 10, - shiftwidth = 2, - showmode = false, - smartindent = true, - softtabstop = 2, - splitbelow = true, - splitright = true, - swapfile = false, - syntax = "on", - tabstop = 2, - termguicolors = true, - textwidth = 0, - updatetime = 1000, - winbar = "%=%m %f", - wrap = false, - } - - for key, value in pairs(settings) do - vim.o[key] = value - end - - vim.opt.clipboard:append "unnamedplus" - vim.opt.completeopt = { "menu", "menuone", "noselect" } - vim.opt.laststatus = 3 -end - -M.setup = function() - set_vim_g() - set_vim_o() - set_key_mappings() - set_autocmd() - set_filetypes() - set_highlights() - - vim.g.snippets = "luasnip" -end - -return M diff --git a/roles/neovim/files/lua/opdavies/plugins.lua b/roles/neovim/files/lua/opdavies/plugins.lua deleted file mode 100644 index 98915f80..00000000 --- a/roles/neovim/files/lua/opdavies/plugins.lua +++ /dev/null @@ -1,137 +0,0 @@ -local status_ok, packer = pcall(require, "packer") -if not status_ok then - return -end - -packer.init { - display = { - open_fn = function() - return require("packer.util").float {} - end, - }, -} - -return packer.startup(function() - local use = packer.use - - use "wbthomason/packer.nvim" - - -- Tmux - use "preservim/vimux" - - -- Utilities - use "aca/emmet-ls" - use "andymass/vim-matchup" - use "cakebaker/scss-syntax.vim" - use "christoomey/vim-sort-motion" - use "christoomey/vim-tmux-navigator" - use "editorconfig/editorconfig-vim" - use "folke/twilight.nvim" - use "folke/zen-mode.nvim" - use "icatalina/vim-case-change" - use "junegunn/vim-easy-align" - use "kazhala/close-buffers.nvim" - use "kyazdani42/nvim-web-devicons" - use "lewis6991/gitsigns.nvim" - use "lewis6991/impatient.nvim" - use "machakann/vim-highlightedyank" - use "miyakogi/seiya.vim" - use "mkitt/tabline.vim" - use "monaqa/dial.nvim" - use "norcalli/nvim-colorizer.lua" - use "numToStr/Comment.nvim" - use "nvim-lua/plenary.nvim" - use "nvim-lua/popup.nvim" - use "sheerun/vim-polyglot" - use "theprimeagen/git-worktree.nvim" - use "theprimeagen/refactoring.nvim" - use "tjdevries/express_line.nvim" - use "tpope/vim-abolish" - use "tpope/vim-repeat" - use "tpope/vim-surround" - use "vim-test/vim-test" - use { "mg979/vim-visual-multi", branch = "master" } - - -- Themes - use { - "tjdevries/gruvbuddy.nvim", - requires = { - "tjdevries/colorbuddy.vim", - }, - } - - -- Navigation - use "ThePrimeagen/harpoon" - use "tamago324/lir-git-status.nvim" - use "tamago324/lir.nvim" - - -- Treesitter - use "nvim-treesitter/playground" - use 'nvim-treesitter/nvim-treesitter-context' - use { - "nvim-treesitter/nvim-treesitter", - run = ":TSUpdate", - } - use "nvim-treesitter/nvim-treesitter-textobjects" - - -- Completion - use { - "hrsh7th/nvim-cmp", - requires = { - "L3MON4D3/LuaSnip", - "hrsh7th/cmp-buffer", - "hrsh7th/cmp-nvim-lsp", - "hrsh7th/cmp-path", - "onsails/lspkind-nvim", - "saadparwaiz1/cmp_luasnip", - }, - } - - -- Snippets - use "L3MON4D3/LuaSnip" - use "rafamadriz/friendly-snippets" - - -- LSP - use "jose-elias-alvarez/null-ls.nvim" - use "neovim/nvim-lspconfig" - use "nvim-lua/lsp-status.nvim" - - -- Debugging - use "mfussenegger/nvim-dap" - use "nvim-telescope/telescope-dap.nvim" - use "rcarriga/nvim-dap-ui" - use "theHamsta/nvim-dap-virtual-text" - - -- Telescope - use "nvim-telescope/telescope.nvim" - use "nvim-telescope/telescope-file-browser.nvim" - use { "nvim-telescope/telescope-fzf-native.nvim", run = "make" } - use { "nvim-telescope/telescope-ui-select.nvim" } - - -- Git - use "TimUntersberger/neogit" - - -- Databases - use "tpope/vim-dadbod" - use "kristijanhusak/vim-dadbod-completion" - use "kristijanhusak/vim-dadbod-ui" - - -- HTTP client - use "rest-nvim/rest.nvim" - - -- Text objects - use "kana/vim-textobj-indent" - use "kana/vim-textobj-user" - use "vim-scripts/argtextobj.vim" - use "wellle/targets.vim" - - -- Markdown - use { - "iamcco/markdown-preview.nvim", - run = "cd app && npm install", - setup = function() - vim.g.mkdp_filetypes = { "markdown" } - end, - ft = { "markdown" }, - } -end) diff --git a/roles/neovim/files/lua/opdavies/snippets/ft/javascript.lua b/roles/neovim/files/lua/opdavies/snippets/ft/javascript.lua deleted file mode 100644 index d3e795f8..00000000 --- a/roles/neovim/files/lua/opdavies/snippets/ft/javascript.lua +++ /dev/null @@ -1,10 +0,0 @@ -local fmta = require("luasnip.extras.fmt").fmta -local ls = require "luasnip" - -local i = ls.insert_node - -local M = { - log = fmta("console.log(<>);", { i(1, "value") }), -} - -return M diff --git a/roles/neovim/files/lua/opdavies/snippets/ft/lua.lua b/roles/neovim/files/lua/opdavies/snippets/ft/lua.lua deleted file mode 100644 index c2abfba8..00000000 --- a/roles/neovim/files/lua/opdavies/snippets/ft/lua.lua +++ /dev/null @@ -1,27 +0,0 @@ -local ls = require "luasnip" - -local fmt = require("luasnip.extras.fmt").fmt -local rep = require("luasnip.extras").rep - -local f, i = ls.function_node, ls.insert_node - -return { - pcall = fmt( - [[ - local status_ok, {} = pcall(require, "{}") - if not status_ok then - return - end - ]], - { i(1), rep(1) } - ), - - req = fmt([[local {} = require "{}"]], { - f(function(import_name) - local parts = vim.split(import_name[1][1], ".", true) - - return parts[#parts] or "" - end, { 1 }), - i(1), - }), -} diff --git a/roles/neovim/files/lua/opdavies/snippets/ft/markdown.lua b/roles/neovim/files/lua/opdavies/snippets/ft/markdown.lua deleted file mode 100644 index c194d2a0..00000000 --- a/roles/neovim/files/lua/opdavies/snippets/ft/markdown.lua +++ /dev/null @@ -1,18 +0,0 @@ -local fmt = require("luasnip.extras.fmt").fmt -local ls = require "luasnip" - -local i = ls.insert_node - -local M = { - frontmatter = fmt( - [[ - --- - title: {} - --- - {} - ]], - { i(1), i(0) } - ), -} - -return M diff --git a/roles/neovim/files/lua/opdavies/snippets/ft/php.lua b/roles/neovim/files/lua/opdavies/snippets/ft/php.lua deleted file mode 100644 index 61e53cb6..00000000 --- a/roles/neovim/files/lua/opdavies/snippets/ft/php.lua +++ /dev/null @@ -1,87 +0,0 @@ -local fmta = require("luasnip.extras.fmt").fmta -local ls = require "luasnip" - -local c = ls.choice_node -local f = ls.function_node -local i = ls.insert_node -local t = ls.text_node - -local M = { - - drupalclass = fmta( - [[ - <; - - final class <> { - - <> - - }]], - { - f(function() - local filepath = vim.fn.expand "%:h" - local filepath_parts = vim.fn.split(filepath, "/") - - if not vim.tbl_contains(filepath_parts, "src") then - return "" - end - - local namespace_parts = { "Drupal" } - - local is_test_file = vim.tbl_contains(filepath_parts, "tests") - if is_test_file then - table.insert(namespace_parts, "Tests") - end - - -- Find and add the module name. - for k, v in ipairs(filepath_parts) do - if v == "src" then - if is_test_file then - table.insert(namespace_parts, filepath_parts[k - 2]) - else - table.insert(namespace_parts, filepath_parts[k - 1]) - end - end - end - - -- Add the rest of the namespace. - local namespace = vim.split(filepath, "src/") - local final_part = (namespace[2] or ""):gsub("/", "\\") - table.insert(namespace_parts, final_part) - - return table.concat(namespace_parts, "\\") - end), - f(function() - return vim.fn.expand "%:t:r" - end), - i(0), - } - ), - - func = fmta("function <>(<>)<> {\n <>\n}<>", { i(1), i(2), i(3), i(4), i(0) }), - - met = fmta( - [[ - <> function <>(<>)<> { - <> - }<> - ]], - { c(1, { t "public", t "protected", t "private" }), i(2), i(3), i(4), i(5), i(0) } - ), - - test = fmta( - [[ - /** @test */ - public function <><>(): void { - <> - }<> - ]], - { c(1, { t "test", t "it", t "should" }), i(2), i(3), i(0) } - ), -} - -return M diff --git a/roles/neovim/files/lua/opdavies/snippets/ft/rst.lua b/roles/neovim/files/lua/opdavies/snippets/ft/rst.lua deleted file mode 100644 index 657dae18..00000000 --- a/roles/neovim/files/lua/opdavies/snippets/ft/rst.lua +++ /dev/null @@ -1,22 +0,0 @@ -local ls = require "luasnip" - -local i = ls.insert_node -local f = ls.function_node - -local fill_line = function(char) - return function() - local row = vim.api.nvim_win_get_cursor(0)[1] - local lines = vim.api.nvim_buf_get_lines(0, row - 2, row, false) - return string.rep(char, #lines[1]) - end -end - -local M = { - link = { ".. _", i(1), ":" }, - - head = f(fill_line "=", {}), - sub = f(fill_line "-", {}), - subsub = f(fill_line "^", {}), -} - -return M diff --git a/roles/neovim/files/lua/opdavies/telescope/init.lua b/roles/neovim/files/lua/opdavies/telescope/init.lua deleted file mode 100644 index a73c3d47..00000000 --- a/roles/neovim/files/lua/opdavies/telescope/init.lua +++ /dev/null @@ -1,139 +0,0 @@ -SHOULD_RELOAD_TELESCOPE = true - -local reloader = function() - if SHOULD_RELOAD_TELESCOPE then - RELOAD "plenary" - RELOAD "telescope" - RELOAD "opdavies.telescope.setup" - end -end - -local themes = require "telescope.themes" - -local M = {} - -function M.current_buf() - local opts = { - sorting_strategy = "ascending", - previewer = false, - } - - require("telescope.builtin").current_buffer_fuzzy_find(opts) -end - -M.diagnostics = function() - local theme = require("telescope.themes").get_dropdown { - previewer = false, - } - - require("telescope.builtin").diagnostics(theme) -end - -function M.lsp_document_symbols() - local theme = require("telescope.themes").get_dropdown { - previewer = false, - } - - require("telescope.builtin").lsp_document_symbols(theme) -end - -function M.edit_neovim() - local opts = { - cwd = "~/.config/nvim", - find_command = { "rg", "--no-ignore", "--files", "--follow" }, - path_display = { "shorten" }, - prompt_title = "~ dotfiles ~", - no_ignore = true, - - layout_strategy = "flex", - layout_config = { - height = 0.8, - prompt_position = "top", - width = 0.9, - - horizontal = { - width = { padding = 0.15 }, - }, - vertical = { - preview_height = 0.75, - }, - }, - } - - require("telescope.builtin").find_files(opts) -end - -function M.edit_zsh() - local opts = { - cwd = "~/.config/zsh", - path_display = { "shorten" }, - prompt_title = "~ zsh ~", - no_ignore = true, - - layout_strategy = "flex", - layout_config = { - height = 0.8, - prompt_position = "top", - width = 0.9, - - horizontal = { - width = { padding = 0.15 }, - }, - vertical = { - preview_height = 0.75, - }, - }, - } - - require("telescope.builtin").find_files(opts) -end - -function M.file_browser() - local opts = { - cwd = vim.fn.expand "%:p:h", - sorting_strategy = "ascending", - } - - require("telescope").extensions.file_browser.file_browser(opts) -end - -function M.fd() - local opts = themes.get_ivy { - file_ignore_patterns = { ".git/" }, - hidden = true, - no_ignore = true, - } - - require("telescope.builtin").find_files(opts) -end - -function M.git_files() - local opts = themes.get_ivy { - file_ignore_patterns = { ".git/", "vendor" }, - hidden = true, - no_ignore = true, - } - - require("telescope.builtin").git_files(opts) -end - -function M.live_grep() - require("telescope.builtin").live_grep { - file_ignore_patterns = { ".git/" }, - hidden = true, - no_ignore = true, - sorting_strategy = "ascending", - } -end - -return setmetatable({}, { - __index = function(_, k) - reloader() - - if M[k] then - return M[k] - else - return require("telescope.builtin")[k] - end - end, -}) diff --git a/roles/neovim/files/lua/opdavies/telescope/mappings.lua b/roles/neovim/files/lua/opdavies/telescope/mappings.lua deleted file mode 100644 index 44a5c7a0..00000000 --- a/roles/neovim/files/lua/opdavies/telescope/mappings.lua +++ /dev/null @@ -1,44 +0,0 @@ -TelescopeMapArgs = TelescopeMapArgs or {} - -local telescope = require "telescope" - -local telescope_mapper = function(key, f, options, buffer) - local map_key = vim.api.nvim_replace_termcodes(key .. f, true, true, true) - - TelescopeMapArgs[map_key] = options or {} - - local mode = "n" - local rhs = string.format("lua R('opdavies.telescope')['%s'](TelescopeMapArgs['%s'])", f, map_key) - - local map_options = { - noremap = true, - silent = true, - } - - if not buffer then - vim.api.nvim_set_keymap(mode, key, rhs, map_options) - else - vim.api.nvim_buf_set_keymap(0, mode, key, rhs, map_options) - end -end - -telescope_mapper("fb", "buffers") -telescope_mapper("fd", "fd") -telescope_mapper("fe", "file_browser") -telescope_mapper("ff", "current_buf") -telescope_mapper("fg", "git_files") -telescope_mapper("fh", "help_tags") -telescope_mapper("fl", "live_grep") - -telescope_mapper("ds", "lsp_document_symbols") -telescope_mapper("dl", "diagnostics") - -telescope_mapper("en", "edit_neovim") -telescope_mapper("ez", "edit_zsh") - -local nmap = require("opdavies.keymap").nmap - -nmap { "gm", telescope.extensions.git_worktree.create_git_worktree } -nmap { "gw", telescope.extensions.git_worktree.git_worktrees } - -return telescope_mapper diff --git a/roles/neovim/files/lua/opdavies/telescope/setup.lua b/roles/neovim/files/lua/opdavies/telescope/setup.lua deleted file mode 100644 index c0abbf07..00000000 --- a/roles/neovim/files/lua/opdavies/telescope/setup.lua +++ /dev/null @@ -1,63 +0,0 @@ -local status_ok, telescope = pcall(require, "telescope") -if not status_ok then - return -end - -local previewers = require "telescope.previewers" -local Job = require "plenary.job" - --- Create a new maker that won't preview binary files --- https://github.com/nvim-telescope/telescope.nvim/wiki/Configuration-Recipes#dont-preview-binaries -local new_maker = function(filepath, bufnr, opts) - filepath = vim.fn.expand(filepath) - Job:new({ - command = "file", - args = { "--mime-type", "-b", filepath }, - on_exit = function(j) - local mime_type = vim.split(j:result()[1], "/")[1] - if mime_type == "text" then - previewers.buffer_previewer_maker(filepath, bufnr, opts) - else - vim.schedule(function() - vim.api.nvim_buf_set_lines(bufnr, 0, -1, false, { "BINARY" }) - end) - end - end, - }):sync() -end - -local action_layout = require "telescope.actions.layout" -local actions = require "telescope.actions" - -telescope.setup { - defaults = { - buffer_previewer_maker = new_maker, - mappings = { - i = { - [""] = actions.which_key, - [""] = action_layout.toggle_preview, - }, - n = { - [""] = action_layout.toggle_preview, - }, - }, - no_ignore = true, - prompt_prefix = "$ ", - }, - - extensions = { - file_browser = { - theme = "ivy", - }, - - ["ui-select"] = { - require("telescope.themes").get_dropdown {}, - }, - }, -} - -telescope.load_extension "file_browser" -telescope.load_extension "fzf" -telescope.load_extension "git_worktree" -telescope.load_extension "refactoring" -telescope.load_extension "ui-select" diff --git a/roles/neovim/tasks/main.yaml b/roles/neovim/tasks/main.yaml deleted file mode 100644 index 552281fa..00000000 --- a/roles/neovim/tasks/main.yaml +++ /dev/null @@ -1,67 +0,0 @@ ---- -- name: Dependencies - ansible.builtin.package: - name: - - autoconf - - automake - - cmake - - curl - - doxygen - - g++ - - gettext - - libtool - - libtool-bin - - ninja-build - - pkg-config - - unzip - state: latest - become: yes - -- name: Clone - ansible.builtin.git: - clone: yes - depth: 1 - dest: "{{ ansible_user_dir }}/build/neovim" - repo: https://github.com/neovim/neovim.git - # single_branch: yes - update: yes - version: "{{ neovim_version | default('master') }}" - register: clone - -- name: Build - make: - chdir: "{{ ansible_user_dir }}/build/neovim" - params: - CMAKE_BUILD_TYPE: RelWithDebInfo - when: clone.changed - -- name: Install - make: - chdir: "{{ ansible_user_dir }}/build/neovim" - target: install - become: yes - when: clone.changed - -- name: Remove build folder - ansible.builtin.file: - path: "{{ ansible_user_dir }}/build/neovim/build" - state: absent - become: yes - -- name: Create .config/nvim directory - ansible.builtin.file: - path: "{{ ansible_user_dir }}/.config/nvim" - state: directory - -- name: Configuration files - ansible.builtin.file: - src: "{{ role_path }}/files/{{ neovim_config_item }}" - dest: "{{ ansible_user_dir }}/.config/nvim/{{ neovim_config_item }}" - state: link - loop_control: - loop_var: neovim_config_item - with_items: - - after - - autoload - - init.lua - - lua diff --git a/roles/notion-app/tasks/main.yaml b/roles/notion-app/tasks/main.yaml deleted file mode 100644 index 6264a478..00000000 --- a/roles/notion-app/tasks/main.yaml +++ /dev/null @@ -1,12 +0,0 @@ ---- -- name: Repository - ansible.builtin.apt_repository: - repo: "deb [trusted=yes] https://apt.fury.io/notion-repackaged/ /" - become: true - -- name: Install - ansible.builtin.package: - name: - - notion-app - state: latest - become: true diff --git a/roles/npm/tasks/main.yaml b/roles/npm/tasks/main.yaml deleted file mode 100644 index fb6eeb03..00000000 --- a/roles/npm/tasks/main.yaml +++ /dev/null @@ -1,7 +0,0 @@ ---- -- name: Install - ansible.builtin.package: - name: - - npm - state: latest - become: true diff --git a/roles/obs-studio/tasks/main.yaml b/roles/obs-studio/tasks/main.yaml deleted file mode 100644 index 29591516..00000000 --- a/roles/obs-studio/tasks/main.yaml +++ /dev/null @@ -1,7 +0,0 @@ ---- -- name: Install - community.general.flatpak: - name: - - com.obsproject.Studio - method: user - state: present diff --git a/roles/pdf-arranger/tasks/main.yaml b/roles/pdf-arranger/tasks/main.yaml deleted file mode 100644 index 9f81f636..00000000 --- a/roles/pdf-arranger/tasks/main.yaml +++ /dev/null @@ -1,7 +0,0 @@ ---- -- name: Install - community.general.flatpak: - name: - - com.github.jeromerobert.pdfarranger - method: user - state: present diff --git a/roles/platformsh-cli/tasks/main.yaml b/roles/platformsh-cli/tasks/main.yaml deleted file mode 100644 index 6973fda5..00000000 --- a/roles/platformsh-cli/tasks/main.yaml +++ /dev/null @@ -1,30 +0,0 @@ ---- -- name: Install dependencies - ansible.builtin.package: - name: - - php - state: latest - become: true - -- name: Existing install - stat: - path: "{{ ansible_user_dir }}/.platformsh/bin/platform" - register: install - -- name: Download installer - ansible.builtin.get_url: - dest: /tmp/platformsh-install.sh - mode: 0755 - url: https://platform.sh/cli/installer - become: true - when: not install.stat.exists - -- name: Execute installer - ansible.builtin.command: php /tmp/platformsh-install.sh - when: not install.stat.exists - -- name: Remove platformsh-install.sh - ansible.builtin.file: - path: /tmp/platformsh-install.sh - state: absent - become: true diff --git a/roles/pocketcasts/tasks/main.yaml b/roles/pocketcasts/tasks/main.yaml deleted file mode 100644 index 69a96028..00000000 --- a/roles/pocketcasts/tasks/main.yaml +++ /dev/null @@ -1,7 +0,0 @@ ---- -- name: Install - community.general.flatpak: - name: - - tech.feliciano.pocket-casts - method: user - state: present diff --git a/roles/postman/tasks/main.yaml b/roles/postman/tasks/main.yaml deleted file mode 100644 index 1128a0dd..00000000 --- a/roles/postman/tasks/main.yaml +++ /dev/null @@ -1,7 +0,0 @@ ---- -- name: Install - community.general.flatpak: - name: - - com.getpostman.Postman - method: user - state: present diff --git a/roles/projects/meta/main.yaml b/roles/projects/meta/main.yaml deleted file mode 100644 index 5b79f2a4..00000000 --- a/roles/projects/meta/main.yaml +++ /dev/null @@ -1,3 +0,0 @@ ---- -dependencies: - - role: ssh diff --git a/roles/projects/tasks/main.yaml b/roles/projects/tasks/main.yaml deleted file mode 100644 index cc417e42..00000000 --- a/roles/projects/tasks/main.yaml +++ /dev/null @@ -1,22 +0,0 @@ ---- -- name: Create project directories - ansible.builtin.file: - path: "{{ project_directory_item }}" - state: directory - recurse: yes - loop_control: - loop_var: project_directory_item - with_items: "{{ project_directories | default([]) }}" - -- name: Clone projects - ansible.builtin.git: - accept_hostkey: yes - bare: "{{ project_item.bare | default(true) }}" - clone: yes - dest: "{{ ansible_user_dir }}/Code/{{ project_item.dest }}" - repo: "{{ project_item.repo }}" - version: "{{ project_item.version | default('main') }}" - update: no - loop_control: - loop_var: project_item - with_items: "{{ project_projects | default([]) }}" diff --git a/roles/pulumi/tasks/main.yaml b/roles/pulumi/tasks/main.yaml deleted file mode 100644 index 0c1dc2f0..00000000 --- a/roles/pulumi/tasks/main.yaml +++ /dev/null @@ -1,23 +0,0 @@ ---- -- name: Existing install - stat: - path: "{{ ansible_user_dir }}/.pulumi/bin/pulumi" - register: install - -- name: Download installer - ansible.builtin.get_url: - dest: /tmp/pulumi-install.sh - mode: 0755 - url: https://get.pulumi.com - become: true - when: not install.stat.exists - -- name: Execute installer - ansible.builtin.command: sh /tmp/pulumi-install.sh - when: not install.stat.exists - -- name: Remove pulumi-install.sh - ansible.builtin.file: - path: /tmp/pulumi-install.sh - state: absent - become: true diff --git a/roles/pv/tasks/main.yaml b/roles/pv/tasks/main.yaml deleted file mode 100644 index 78c398ed..00000000 --- a/roles/pv/tasks/main.yaml +++ /dev/null @@ -1,7 +0,0 @@ ---- -- name: Install - ansible.builtin.package: - name: - - pv - state: latest - become: true diff --git a/roles/ripgrep/tasks/main.yaml b/roles/ripgrep/tasks/main.yaml deleted file mode 100644 index ee389d1d..00000000 --- a/roles/ripgrep/tasks/main.yaml +++ /dev/null @@ -1,7 +0,0 @@ ---- -- name: Install - ansible.builtin.package: - name: - - ripgrep - state: latest - become: true diff --git a/roles/skype/tasks/main.yaml b/roles/skype/tasks/main.yaml deleted file mode 100644 index c9850b90..00000000 --- a/roles/skype/tasks/main.yaml +++ /dev/null @@ -1,7 +0,0 @@ ---- -- name: Install - community.general.flatpak: - name: - - com.skype.Client - method: user - state: present diff --git a/roles/slack/tasks/main.yaml b/roles/slack/tasks/main.yaml deleted file mode 100644 index 9588720f..00000000 --- a/roles/slack/tasks/main.yaml +++ /dev/null @@ -1,7 +0,0 @@ ---- -- name: Install - community.general.flatpak: - name: - - com.slack.Slack - method: user - state: present diff --git a/roles/spotify/tasks/main.yaml b/roles/spotify/tasks/main.yaml deleted file mode 100644 index 6e53322c..00000000 --- a/roles/spotify/tasks/main.yaml +++ /dev/null @@ -1,7 +0,0 @@ ---- -- name: Install - community.general.flatpak: - name: - - com.spotify.Client - method: user - state: present diff --git a/roles/ssh/tasks/main.yaml b/roles/ssh/tasks/main.yaml deleted file mode 100644 index 44cc7d49..00000000 --- a/roles/ssh/tasks/main.yaml +++ /dev/null @@ -1,18 +0,0 @@ ---- -- name: Copy SSH keys - copy: - content: "{{ ssh_key_item.value }}" - dest: "{{ ansible_user_dir }}/.ssh/{{ ssh_key_item.key }}" - mode: 0400 - loop_control: - loop_var: ssh_key_item - no_log: true - with_items: "{{ ssh_key | default({}) | dict2items }}" - -- name: Create SSH configuration file - ansible.builtin.copy: - content: "{{ ssh_config }}" - dest: "{{ ansible_user_dir }}/.ssh/config" - mode: 0400 - no_log: true - when: ssh_config is defined diff --git a/roles/stylua/meta/main.yaml b/roles/stylua/meta/main.yaml deleted file mode 100644 index fe55fc75..00000000 --- a/roles/stylua/meta/main.yaml +++ /dev/null @@ -1,3 +0,0 @@ ---- -dependencies: - - role: cargo diff --git a/roles/stylua/tasks/main.yaml b/roles/stylua/tasks/main.yaml deleted file mode 100644 index 63a110a9..00000000 --- a/roles/stylua/tasks/main.yaml +++ /dev/null @@ -1,8 +0,0 @@ ---- -- name: Install - community.general.cargo: - name: - - stylua - path: /usr/local - state: latest - become: true diff --git a/roles/teams/tasks/main.yaml b/roles/teams/tasks/main.yaml deleted file mode 100644 index f1b31897..00000000 --- a/roles/teams/tasks/main.yaml +++ /dev/null @@ -1,7 +0,0 @@ ---- -- name: Install - community.general.flatpak: - name: - - com.github.IsmaelMartinez.teams_for_linux - method: user - state: present diff --git a/roles/tldr/tasks/main.yaml b/roles/tldr/tasks/main.yaml deleted file mode 100644 index 08ae98f6..00000000 --- a/roles/tldr/tasks/main.yaml +++ /dev/null @@ -1,7 +0,0 @@ ---- -- name: Install - ansible.builtin.package: - name: - - tldr - state: latest - become: true diff --git a/roles/tmux/files/tmux.conf b/roles/tmux/files/tmux.conf deleted file mode 100644 index 83c4d3ab..00000000 --- a/roles/tmux/files/tmux.conf +++ /dev/null @@ -1,95 +0,0 @@ -unbind C-b - -set -g prefix C-s -bind C-s send-prefix - -bind-key r source-file ~/.tmux.conf \; display-message "~/.tmux.conf reloaded" - -bind-key -n C-h select-pane -L -bind-key -n C-j select-pane -D -bind-key -n C-k select-pane -U -bind-key -n C-l select-pane -R - -set-option -g status-keys "emacs" -set-option -g default-terminal "xterm-256color" -set-option -ga terminal-overrides ",*256col*:Tc" - -bind-key h split-window -v -c '#{pane_current_path}' -bind-key v split-window -h -c '#{pane_current_path}' - -bind -n S-Left resize-pane -L 2 -bind -n S-Right resize-pane -R 2 -bind -n S-Down resize-pane -D 1 -bind -n S-Up resize-pane -U 1 - -bind -n C-Left resize-pane -L 10 -bind -n C-Right resize-pane -R 10 -bind -n C-Down resize-pane -D 5 -bind -n C-Up resize-pane -U 5 - -set-option -g status-left-length 50 -set-option -g status-right "" - -bind c new-window -c "#{pane_current_path}" - -set -g base-index 1 -set -g renumber-windows on - -# Break a pane into a new window. -bind-key b break-pane -d - -bind-key C-j choose-tree - -# Use vim keybindings in copy mode -setw -g mode-keys vi - -# Setup 'v' to begin selection as in Vim -bind-key -T copy-mode-vi 'v' send -X begin-selection -bind-key -T copy-mode-vi 'y' send -X copy-pipe "reattach-to-user-namespace pbcopy" - -# Update default binding of `Enter` to also use copy-pipe -unbind -T copy-mode-vi Enter -bind-key -T copy-mode-vi 'Enter' send -X copy-pipe "reattach-to-user-namespace pbcopy" - -bind C-j split-window -v "tmux list-sessions | sed -E 's/:.*$//' | grep -v \"^$(tmux display-message -p '#S')\$\" | fzf --reverse | xargs tmux switch-client -t" - -bind-key C-b send-keys 'tat && exit' 'C-m' -bind-key K run-shell 'tmux switch-client -n \; kill-session -t "$(tmux display-message -p "#S")" || tmux kill-session' - -# Smart pane switching with awareness of Vim splits. -# See: https://github.com/christoomey/vim-tmux-navigator -is_vim="ps -o state= -o comm= -t '#{pane_tty}' \ - | grep -iqE '^[^TXZ ]+ +(\\S+\\/)?g?(view|n?vim?x?)(diff)?$'" -bind-key -n 'C-h' if-shell "$is_vim" 'send-keys C-h' 'select-pane -L' -bind-key -n 'C-j' if-shell "$is_vim" 'send-keys C-j' 'select-pane -D' -bind-key -n 'C-k' if-shell "$is_vim" 'send-keys C-k' 'select-pane -U' -bind-key -n 'C-l' if-shell "$is_vim" 'send-keys C-l' 'select-pane -R' -tmux_version='$(tmux -V | sed -En "s/^tmux ([0-9]+(.[0-9]+)?).*/\1/p")' -if-shell -b '[ "$(echo "$tmux_version < 3.0" | bc)" = 1 ]' \ - "bind-key -n 'C-\\' if-shell \"$is_vim\" 'send-keys C-\\' 'select-pane -l'" -if-shell -b '[ "$(echo "$tmux_version >= 3.0" | bc)" = 1 ]' \ - "bind-key -n 'C-\\' if-shell \"$is_vim\" 'send-keys C-\\\\' 'select-pane -l'" - -bind-key -T copy-mode-vi 'C-h' select-pane -L -bind-key -T copy-mode-vi 'C-j' select-pane -D -bind-key -T copy-mode-vi 'C-k' select-pane -U -bind-key -T copy-mode-vi 'C-l' select-pane -R -bind-key -T copy-mode-vi 'C-\' select-pane -l - -# Allow clearing screen with ctrl-l by using C-l -bind C-l send-keys 'C-l' -bind C-k send-keys 'C-k' - -# Enable mouse support. -setw -g mouse on - -# Remove delay when switching Vim modes. -set -sg escape-time 0 - -# Plugins -set -g @plugin 'tmux-plugins/tmux-resurrect' -set -g @plugin 'tmux-plugins/tmux-yank' -set -g @plugin 'tmux-plugins/tpm' - -# Initialize TMUX plugin manager -run '~/.tmux/plugins/tpm/tpm' diff --git a/roles/tmux/tasks/main.yaml b/roles/tmux/tasks/main.yaml deleted file mode 100644 index 68ee8039..00000000 --- a/roles/tmux/tasks/main.yaml +++ /dev/null @@ -1,18 +0,0 @@ ---- -- name: Install - ansible.builtin.package: - name: - - tmux - state: latest - become: true - -- name: Directory - ansible.builtin.file: - path: "{{ ansible_user_dir }}/.config/tmux" - state: directory - -- name: Configuration - ansible.builtin.file: - src: "{{ role_path }}/files/tmux.conf" - dest: "{{ ansible_user_dir }}/.config/tmux/tmux.conf" - state: link diff --git a/roles/tmuxinator/tasks/main.yml b/roles/tmuxinator/tasks/main.yml deleted file mode 100644 index 1c7fd511..00000000 --- a/roles/tmuxinator/tasks/main.yml +++ /dev/null @@ -1,27 +0,0 @@ ---- -- name: Dependencies - ansible.builtin.package: - name: ruby - state: latest - become: true - -- name: Install - community.general.gem: - bindir: "{{ ansible_user_dir }}/.local/bin" - name: tmuxinator - state: latest - -- name: Configuration - ansible.builtin.file: - path: "{{ ansible_user_dir }}/.config/tmuxinator" - state: directory - -- name: Copy configuration files - copy: - content: "{{ tmuxinator_config_file.value }}" - dest: "{{ ansible_user_dir }}/.config/tmuxinator/{{ tmuxinator_config_file.key }}.yml" - mode: 0644 - loop_control: - loop_var: tmuxinator_config_file - no_log: true - with_items: "{{ tmuxinator_config | default({}) | dict2items }}" diff --git a/roles/todoist/tasks/main.yaml b/roles/todoist/tasks/main.yaml deleted file mode 100644 index 6c4a861f..00000000 --- a/roles/todoist/tasks/main.yaml +++ /dev/null @@ -1,7 +0,0 @@ ---- -- name: Install - community.general.flatpak: - name: - - com.todoist.Todoist - method: user - state: present diff --git a/roles/tree/tasks/main.yaml b/roles/tree/tasks/main.yaml deleted file mode 100644 index da6dd9fb..00000000 --- a/roles/tree/tasks/main.yaml +++ /dev/null @@ -1,7 +0,0 @@ ---- -- name: Install - ansible.builtin.package: - name: - - tree - state: latest - become: true diff --git a/roles/vlc/tasks/main.yaml b/roles/vlc/tasks/main.yaml deleted file mode 100644 index 1c766eec..00000000 --- a/roles/vlc/tasks/main.yaml +++ /dev/null @@ -1,7 +0,0 @@ ---- -- name: Install - community.general.flatpak: - name: - - org.videolan.VLC - method: user - state: present diff --git a/roles/zoom/tasks/main.yaml b/roles/zoom/tasks/main.yaml deleted file mode 100644 index 5b33b5d2..00000000 --- a/roles/zoom/tasks/main.yaml +++ /dev/null @@ -1,7 +0,0 @@ ---- -- name: Install - community.general.flatpak: - name: - - us.zoom.Zoom - method: user - state: present diff --git a/roles/zsh-antigen/tasks/main.yaml b/roles/zsh-antigen/tasks/main.yaml deleted file mode 100644 index 957e1d6e..00000000 --- a/roles/zsh-antigen/tasks/main.yaml +++ /dev/null @@ -1,5 +0,0 @@ ---- -- name: Download - get_url: - dest: ~/.antigen.zsh - url: https://raw.githubusercontent.com/zsh-users/antigen/master/bin/antigen.zsh diff --git a/roles/zsh/files/.zshenv b/roles/zsh/files/.zshenv deleted file mode 100644 index bf0a74c5..00000000 --- a/roles/zsh/files/.zshenv +++ /dev/null @@ -1,7 +0,0 @@ -export EDITOR=nvim -export ZDOTDIR="$HOME/.config/zsh" - -PROMPT_EOL_MARK='' -TERM=xterm-256color -WORDCHARS='*?_-.[]~=&;!#$%^(){}<>' -ZLE_REMOVE_SUFFIX_CHARS='' diff --git a/roles/zsh/files/config/.zshrc b/roles/zsh/files/config/.zshrc deleted file mode 100644 index 5f2bd58e..00000000 --- a/roles/zsh/files/config/.zshrc +++ /dev/null @@ -1,28 +0,0 @@ -for function in $ZDOTDIR/functions/*; do - source "${function}" -done - -sources=( - 'aliases' - 'colour' - 'functions' - 'fzf' - 'general' - 'history' - 'navigation' - 'nvm' - 'options' - 'path' - 'platformsh' - 'plugins' - 'prompt' - - 'post/completion' -) - -for s in "${sources[@]}"; do - source $ZDOTDIR/configs/${s}.zsh -done - -# Local config -[[ -f ~/.zshrc.local ]] && source ~/.zshrc.local diff --git a/roles/zsh/files/config/completion-scripts/_g b/roles/zsh/files/config/completion-scripts/_g deleted file mode 100644 index 4eca8f38..00000000 --- a/roles/zsh/files/config/completion-scripts/_g +++ /dev/null @@ -1,3 +0,0 @@ -#compdef g -compdef g=git - diff --git a/roles/zsh/files/config/completion-scripts/_m b/roles/zsh/files/config/completion-scripts/_m deleted file mode 100644 index 98a3250d..00000000 --- a/roles/zsh/files/config/completion-scripts/_m +++ /dev/null @@ -1,2 +0,0 @@ -#compdef m -compdef m=make diff --git a/roles/zsh/files/config/configs/aliases.zsh b/roles/zsh/files/config/configs/aliases.zsh deleted file mode 100644 index 728d4838..00000000 --- a/roles/zsh/files/config/configs/aliases.zsh +++ /dev/null @@ -1,11 +0,0 @@ -alias hosts='sudo vim /etc/hosts' -alias rebase='git fetch --all --prune --prune-tags && git rebase' -alias sshconfig='vim ~/.ssh/config' -alias vim='nvim' - -# Allow for pasting lines of code that start with a dollar sign. -alias \$='' - -# Re-implement pbcopy and pbpaste from macOS. -alias pbcopy="xclip -selection clipboard" -alias pbpaste="xclip -selection clipboard -o" diff --git a/roles/zsh/files/config/configs/colour.zsh b/roles/zsh/files/config/configs/colour.zsh deleted file mode 100644 index 534b774f..00000000 --- a/roles/zsh/files/config/configs/colour.zsh +++ /dev/null @@ -1,4 +0,0 @@ -autoload -U colors -colors - -export CLICOLOR=1 \ No newline at end of file diff --git a/roles/zsh/files/config/configs/functions.zsh b/roles/zsh/files/config/configs/functions.zsh deleted file mode 100644 index 0a3aecbd..00000000 --- a/roles/zsh/files/config/configs/functions.zsh +++ /dev/null @@ -1,38 +0,0 @@ -function m() { - if [[ -f .notes/Makefile ]]; - then - make -f .notes/Makefile "$@" - else - make "$@" - fi -} - -function mkd() { - mkdir -p "$@" && cd "$@" -} - -function composer() { - docker run -u $UID -it --rm \ - -v $(pwd):/app \ - -v ~/.composer:/root/.composer \ - -v ~/.ssh:/root/.ssh \ - composer \ - composer $* -} - -# Run 'phpunit' or 'pest' depending on the project. -function p () { - vendor/bin/$(phpunit-or-pest) $*; -} -function pf () { - vendor/bin/$(phpunit-or-pest) --filter $* -} - -nv() { - if [[ $# > 0 ]]; - then - nvim $@ - else - nvim . - fi -} diff --git a/roles/zsh/files/config/configs/fzf.zsh b/roles/zsh/files/config/configs/fzf.zsh deleted file mode 100644 index 6b5afa9b..00000000 --- a/roles/zsh/files/config/configs/fzf.zsh +++ /dev/null @@ -1,2 +0,0 @@ -# Include keybindings for fzf. -. /usr/share/doc/fzf/examples/key-bindings.zsh diff --git a/roles/zsh/files/config/configs/general.zsh b/roles/zsh/files/config/configs/general.zsh deleted file mode 100644 index 26510941..00000000 --- a/roles/zsh/files/config/configs/general.zsh +++ /dev/null @@ -1,5 +0,0 @@ -precmd() { - # Add a blank line before each command. - print '' -} - diff --git a/roles/zsh/files/config/configs/history.zsh b/roles/zsh/files/config/configs/history.zsh deleted file mode 100644 index d85faea5..00000000 --- a/roles/zsh/files/config/configs/history.zsh +++ /dev/null @@ -1,7 +0,0 @@ -setopt histignoredups - -setopt inc_append_history - -HISTSIZE=10000 -SAVEHIST=10000 -HISTFILE=~/.cache/zsh/history diff --git a/roles/zsh/files/config/configs/navigation.zsh b/roles/zsh/files/config/configs/navigation.zsh deleted file mode 100644 index 3bbef6d0..00000000 --- a/roles/zsh/files/config/configs/navigation.zsh +++ /dev/null @@ -1,9 +0,0 @@ -bindkey -s "^f" "tmux-sessioniser\n" - -# Search through history with the up and down arrows. -autoload -U up-line-or-beginning-search -autoload -U down-line-or-beginning-search -zle -N up-line-or-beginning-search -zle -N down-line-or-beginning-search -bindkey "${terminfo[kcuu1]}" up-line-or-beginning-search # Up -bindkey "${terminfo[kcud1]}" up-line-or-beginning-search # Down diff --git a/roles/zsh/files/config/configs/nvm.zsh b/roles/zsh/files/config/configs/nvm.zsh deleted file mode 100644 index 8deff7e7..00000000 --- a/roles/zsh/files/config/configs/nvm.zsh +++ /dev/null @@ -1,2 +0,0 @@ -export NVM_DIR="$([ -z "${XDG_CONFIG_HOME-}" ] && printf %s "${HOME}/.nvm" || printf %s "${XDG_CONFIG_HOME}/nvm")" -[ -s "$NVM_DIR/nvm.sh" ] && \. "$NVM_DIR/nvm.sh" diff --git a/roles/zsh/files/config/configs/options.zsh b/roles/zsh/files/config/configs/options.zsh deleted file mode 100644 index 095835ce..00000000 --- a/roles/zsh/files/config/configs/options.zsh +++ /dev/null @@ -1,3 +0,0 @@ -# Fix "zsh: no matches found: HEAD^" error. -# See https://github.com/opdavies/dotfiles/issues/14. -setopt NO_NOMATCH diff --git a/roles/zsh/files/config/configs/path.zsh b/roles/zsh/files/config/configs/path.zsh deleted file mode 100644 index 6eaa86ac..00000000 --- a/roles/zsh/files/config/configs/path.zsh +++ /dev/null @@ -1,25 +0,0 @@ -setopt auto_cd - -export PATH=\ -$PATH:\ -/usr/bin:\ -$HOME/.cargo/bin:\ -$HOME/.composer/vendor/bin:\ -$HOME/.dotfiles/bin:\ -$HOME/.dotfiles/bin/bin:\ -$HOME/.local/bin:\ -$HOME/.platformsh/bin:\ -$HOME/.pulumi/bin:\ -$HOME/bin:\ -$HOME/snap/bin:\ -bin:\ -node_modules/.bin:\ -tools/php-cs-fixer/vendor/bin:\ -vendor/bin - -export CDPATH=\ -./:\ -$HOME/Code:\ -$HOME/Code/clients:\ -$HOME/Code/open_source:\ -$HOME diff --git a/roles/zsh/files/config/configs/platformsh.zsh b/roles/zsh/files/config/configs/platformsh.zsh deleted file mode 100644 index 8e8c2b62..00000000 --- a/roles/zsh/files/config/configs/platformsh.zsh +++ /dev/null @@ -1,6 +0,0 @@ -# Platform.sh CLI configuration. -export PATH="$HOME/"'.platformsh/bin':"$PATH" - -if [ -f "$HOME/"'.platformsh/shell-config.rc' ]; then - . "$HOME/"'.platformsh/shell-config.rc'; -fi diff --git a/roles/zsh/files/config/configs/plugins.zsh b/roles/zsh/files/config/configs/plugins.zsh deleted file mode 100644 index 6a1243e0..00000000 --- a/roles/zsh/files/config/configs/plugins.zsh +++ /dev/null @@ -1,10 +0,0 @@ -# antigen.zsh has been downloaded manually for now, -# see https://github.com/zsh-users/antigen/issues/659. -source $HOME/.antigen.zsh - -antigen bundle mollifier/cd-gitroot -antigen bundle zsh-users/zsh-autosuggestions -antigen bundle zsh-users/zsh-completions -antigen bundle zsh-users/zsh-syntax-highlighting - -antigen apply diff --git a/roles/zsh/files/config/configs/plugins.zsh.zwc b/roles/zsh/files/config/configs/plugins.zsh.zwc deleted file mode 100644 index 7a6ac081..00000000 Binary files a/roles/zsh/files/config/configs/plugins.zsh.zwc and /dev/null differ diff --git a/roles/zsh/files/config/configs/post/completion.zsh b/roles/zsh/files/config/configs/post/completion.zsh deleted file mode 100644 index 4cc7bc31..00000000 --- a/roles/zsh/files/config/configs/post/completion.zsh +++ /dev/null @@ -1,8 +0,0 @@ -# load our own completion functions -fpath=(~/.config/zsh/completion-scripts $fpath) - -autoload -Uz compinit && compinit - -## case-insensitive (all), partial-word and then substring completion -zstyle ':completion:*' matcher-list '' 'm:{a-zA-Z}={A-Za-z}' \ - 'r:|[._-]=* r:|=*' 'l:|=* r:|=*' diff --git a/roles/zsh/files/config/configs/prompt.zsh b/roles/zsh/files/config/configs/prompt.zsh deleted file mode 100644 index 350368bc..00000000 --- a/roles/zsh/files/config/configs/prompt.zsh +++ /dev/null @@ -1,34 +0,0 @@ -autoload -Uz colors && colors - -prompt_color() { - [[ -n "$1" ]] && print "%{$fg_bold[$2]%}$1%{$reset_color%}" -} - -prompt_blue() { print "$(prompt_color "$1" blue)" } -prompt_green() { print "$(prompt_color "$1" green)" } -prompt_red() { print "$(prompt_color "$1" red)" } -prompt_yellow() { print "$(prompt_color "$1" yellow)" } - -prompt_full_path() { - print "$(prompt_blue %~)" -} - -prompt_shortened_path() { - print "$(prompt_blue %2~)" -} - -prompt_git_branch() { - local branch="$(git symbolic-ref HEAD 2> /dev/null | cut -d'/' -f3)" - - [ -n "${branch}" ] && print "$(prompt_green $branch)" -} - -prompt_git_commit() { - local commit_sha="$(git rev-parse --short HEAD 2> /dev/null)" - - [ -n "${commit_sha}" ] && echo [$(prompt_yellow $commit_sha)] -} - -setopt prompt_subst - -PROMPT='$(prompt_shortened_path) $(prompt_git_branch) $(prompt_git_commit) $ ' diff --git a/roles/zsh/files/config/functions/g b/roles/zsh/files/config/functions/g deleted file mode 100644 index 438db752..00000000 --- a/roles/zsh/files/config/functions/g +++ /dev/null @@ -1,9 +0,0 @@ -# No arguments: `git status` -# With arguments: acts like `git` -g() { - if [[ $# -gt 0 ]]; then - git "$@" - else - git status - fi -} diff --git a/roles/zsh/files/config/functions/run b/roles/zsh/files/config/functions/run deleted file mode 100644 index cabe3d1d..00000000 --- a/roles/zsh/files/config/functions/run +++ /dev/null @@ -1,8 +0,0 @@ -# Execute a "run" file either within ".notes" or the current directory. -function run { - if [[ -f .notes/run ]]; then - .notes/run "${@}" - elif [[ -f run ]]; then - ./run "${@}" - fi -} diff --git a/roles/zsh/files/config/oh-my-zsh/git.zsh b/roles/zsh/files/config/oh-my-zsh/git.zsh deleted file mode 100644 index be9fa7e6..00000000 --- a/roles/zsh/files/config/oh-my-zsh/git.zsh +++ /dev/null @@ -1,281 +0,0 @@ -# The git prompt's git commands are read-only and should not interfere with -# other processes. This environment variable is equivalent to running with `git -# --no-optional-locks`, but falls back gracefully for older versions of git. -# See git(1) for and git-status(1) for a description of that flag. -# -# We wrap in a local function instead of exporting the variable directly in -# order to avoid interfering with manually-run git commands by the user. -function __git_prompt_git() { - GIT_OPTIONAL_LOCKS=0 command git "$@" -} - -function git_prompt_info() { - # If we are on a folder not tracked by git, get out. - # Otherwise, check for hide-info at global and local repository level - if ! __git_prompt_git rev-parse --git-dir &> /dev/null \ - || [[ "$(__git_prompt_git config --get oh-my-zsh.hide-info 2>/dev/null)" == 1 ]]; then - return 0 - fi - - local ref - ref=$(__git_prompt_git symbolic-ref --short HEAD 2> /dev/null) \ - || ref=$(__git_prompt_git rev-parse --short HEAD 2> /dev/null) \ - || return 0 - - # Use global ZSH_THEME_GIT_SHOW_UPSTREAM=1 for including upstream remote info - local upstream - if (( ${+ZSH_THEME_GIT_SHOW_UPSTREAM} )); then - upstream=$(__git_prompt_git rev-parse --abbrev-ref --symbolic-full-name "@{upstream}" 2>/dev/null) \ - && upstream=" -> ${upstream}" - fi - - echo "${ZSH_THEME_GIT_PROMPT_PREFIX}${ref:gs/%/%%}${upstream:gs/%/%%}$(parse_git_dirty)${ZSH_THEME_GIT_PROMPT_SUFFIX}" -} - -# Checks if working tree is dirty -function parse_git_dirty() { - local STATUS - local -a FLAGS - FLAGS=('--porcelain') - if [[ "$(__git_prompt_git config --get oh-my-zsh.hide-dirty)" != "1" ]]; then - if [[ "${DISABLE_UNTRACKED_FILES_DIRTY:-}" == "true" ]]; then - FLAGS+='--untracked-files=no' - fi - case "${GIT_STATUS_IGNORE_SUBMODULES:-}" in - git) - # let git decide (this respects per-repo config in .gitmodules) - ;; - *) - # if unset: ignore dirty submodules - # other values are passed to --ignore-submodules - FLAGS+="--ignore-submodules=${GIT_STATUS_IGNORE_SUBMODULES:-dirty}" - ;; - esac - STATUS=$(__git_prompt_git status ${FLAGS} 2> /dev/null | tail -n 1) - fi - if [[ -n $STATUS ]]; then - echo "$ZSH_THEME_GIT_PROMPT_DIRTY" - else - echo "$ZSH_THEME_GIT_PROMPT_CLEAN" - fi -} - -# Gets the difference between the local and remote branches -function git_remote_status() { - local remote ahead behind git_remote_status git_remote_status_detailed - remote=${$(__git_prompt_git rev-parse --verify ${hook_com[branch]}@{upstream} --symbolic-full-name 2>/dev/null)/refs\/remotes\/} - if [[ -n ${remote} ]]; then - ahead=$(__git_prompt_git rev-list ${hook_com[branch]}@{upstream}..HEAD 2>/dev/null | wc -l) - behind=$(__git_prompt_git rev-list HEAD..${hook_com[branch]}@{upstream} 2>/dev/null | wc -l) - - if [[ $ahead -eq 0 ]] && [[ $behind -eq 0 ]]; then - git_remote_status="$ZSH_THEME_GIT_PROMPT_EQUAL_REMOTE" - elif [[ $ahead -gt 0 ]] && [[ $behind -eq 0 ]]; then - git_remote_status="$ZSH_THEME_GIT_PROMPT_AHEAD_REMOTE" - git_remote_status_detailed="$ZSH_THEME_GIT_PROMPT_AHEAD_REMOTE_COLOR$ZSH_THEME_GIT_PROMPT_AHEAD_REMOTE$((ahead))%{$reset_color%}" - elif [[ $behind -gt 0 ]] && [[ $ahead -eq 0 ]]; then - git_remote_status="$ZSH_THEME_GIT_PROMPT_BEHIND_REMOTE" - git_remote_status_detailed="$ZSH_THEME_GIT_PROMPT_BEHIND_REMOTE_COLOR$ZSH_THEME_GIT_PROMPT_BEHIND_REMOTE$((behind))%{$reset_color%}" - elif [[ $ahead -gt 0 ]] && [[ $behind -gt 0 ]]; then - git_remote_status="$ZSH_THEME_GIT_PROMPT_DIVERGED_REMOTE" - git_remote_status_detailed="$ZSH_THEME_GIT_PROMPT_AHEAD_REMOTE_COLOR$ZSH_THEME_GIT_PROMPT_AHEAD_REMOTE$((ahead))%{$reset_color%}$ZSH_THEME_GIT_PROMPT_BEHIND_REMOTE_COLOR$ZSH_THEME_GIT_PROMPT_BEHIND_REMOTE$((behind))%{$reset_color%}" - fi - - if [[ -n $ZSH_THEME_GIT_PROMPT_REMOTE_STATUS_DETAILED ]]; then - git_remote_status="$ZSH_THEME_GIT_PROMPT_REMOTE_STATUS_PREFIX${remote:gs/%/%%}$git_remote_status_detailed$ZSH_THEME_GIT_PROMPT_REMOTE_STATUS_SUFFIX" - fi - - echo $git_remote_status - fi -} - -# Outputs the name of the current branch -# Usage example: git pull origin $(git_current_branch) -# Using '--quiet' with 'symbolic-ref' will not cause a fatal error (128) if -# it's not a symbolic ref, but in a Git repo. -function git_current_branch() { - local ref - ref=$(__git_prompt_git symbolic-ref --quiet HEAD 2> /dev/null) - local ret=$? - if [[ $ret != 0 ]]; then - [[ $ret == 128 ]] && return # no git repo. - ref=$(__git_prompt_git rev-parse --short HEAD 2> /dev/null) || return - fi - echo ${ref#refs/heads/} -} - - -# Gets the number of commits ahead from remote -function git_commits_ahead() { - if __git_prompt_git rev-parse --git-dir &>/dev/null; then - local commits="$(__git_prompt_git rev-list --count @{upstream}..HEAD 2>/dev/null)" - if [[ -n "$commits" && "$commits" != 0 ]]; then - echo "$ZSH_THEME_GIT_COMMITS_AHEAD_PREFIX$commits$ZSH_THEME_GIT_COMMITS_AHEAD_SUFFIX" - fi - fi -} - -# Gets the number of commits behind remote -function git_commits_behind() { - if __git_prompt_git rev-parse --git-dir &>/dev/null; then - local commits="$(__git_prompt_git rev-list --count HEAD..@{upstream} 2>/dev/null)" - if [[ -n "$commits" && "$commits" != 0 ]]; then - echo "$ZSH_THEME_GIT_COMMITS_BEHIND_PREFIX$commits$ZSH_THEME_GIT_COMMITS_BEHIND_SUFFIX" - fi - fi -} - -# Outputs if current branch is ahead of remote -function git_prompt_ahead() { - if [[ -n "$(__git_prompt_git rev-list origin/$(git_current_branch)..HEAD 2> /dev/null)" ]]; then - echo "$ZSH_THEME_GIT_PROMPT_AHEAD" - fi -} - -# Outputs if current branch is behind remote -function git_prompt_behind() { - if [[ -n "$(__git_prompt_git rev-list HEAD..origin/$(git_current_branch) 2> /dev/null)" ]]; then - echo "$ZSH_THEME_GIT_PROMPT_BEHIND" - fi -} - -# Outputs if current branch exists on remote or not -function git_prompt_remote() { - if [[ -n "$(__git_prompt_git show-ref origin/$(git_current_branch) 2> /dev/null)" ]]; then - echo "$ZSH_THEME_GIT_PROMPT_REMOTE_EXISTS" - else - echo "$ZSH_THEME_GIT_PROMPT_REMOTE_MISSING" - fi -} - -# Formats prompt string for current git commit short SHA -function git_prompt_short_sha() { - local SHA - SHA=$(__git_prompt_git rev-parse --short HEAD 2> /dev/null) && echo "$ZSH_THEME_GIT_PROMPT_SHA_BEFORE$SHA$ZSH_THEME_GIT_PROMPT_SHA_AFTER" -} - -# Formats prompt string for current git commit long SHA -function git_prompt_long_sha() { - local SHA - SHA=$(__git_prompt_git rev-parse HEAD 2> /dev/null) && echo "$ZSH_THEME_GIT_PROMPT_SHA_BEFORE$SHA$ZSH_THEME_GIT_PROMPT_SHA_AFTER" -} - -function git_prompt_status() { - [[ "$(__git_prompt_git config --get oh-my-zsh.hide-status 2>/dev/null)" = 1 ]] && return - - # Maps a git status prefix to an internal constant - # This cannot use the prompt constants, as they may be empty - local -A prefix_constant_map - prefix_constant_map=( - '\?\? ' 'UNTRACKED' - 'A ' 'ADDED' - 'M ' 'ADDED' - 'MM ' 'MODIFIED' - ' M ' 'MODIFIED' - 'AM ' 'MODIFIED' - ' T ' 'MODIFIED' - 'R ' 'RENAMED' - ' D ' 'DELETED' - 'D ' 'DELETED' - 'UU ' 'UNMERGED' - 'ahead' 'AHEAD' - 'behind' 'BEHIND' - 'diverged' 'DIVERGED' - 'stashed' 'STASHED' - ) - - # Maps the internal constant to the prompt theme - local -A constant_prompt_map - constant_prompt_map=( - 'UNTRACKED' "$ZSH_THEME_GIT_PROMPT_UNTRACKED" - 'ADDED' "$ZSH_THEME_GIT_PROMPT_ADDED" - 'MODIFIED' "$ZSH_THEME_GIT_PROMPT_MODIFIED" - 'RENAMED' "$ZSH_THEME_GIT_PROMPT_RENAMED" - 'DELETED' "$ZSH_THEME_GIT_PROMPT_DELETED" - 'UNMERGED' "$ZSH_THEME_GIT_PROMPT_UNMERGED" - 'AHEAD' "$ZSH_THEME_GIT_PROMPT_AHEAD" - 'BEHIND' "$ZSH_THEME_GIT_PROMPT_BEHIND" - 'DIVERGED' "$ZSH_THEME_GIT_PROMPT_DIVERGED" - 'STASHED' "$ZSH_THEME_GIT_PROMPT_STASHED" - ) - - # The order that the prompt displays should be added to the prompt - local status_constants - status_constants=( - UNTRACKED ADDED MODIFIED RENAMED DELETED - STASHED UNMERGED AHEAD BEHIND DIVERGED - ) - - local status_text - status_text="$(__git_prompt_git status --porcelain -b 2> /dev/null)" - - # Don't continue on a catastrophic failure - if [[ $? -eq 128 ]]; then - return 1 - fi - - # A lookup table of each git status encountered - local -A statuses_seen - - if __git_prompt_git rev-parse --verify refs/stash &>/dev/null; then - statuses_seen[STASHED]=1 - fi - - local status_lines - status_lines=("${(@f)${status_text}}") - - # If the tracking line exists, get and parse it - if [[ "$status_lines[1]" =~ "^## [^ ]+ \[(.*)\]" ]]; then - local branch_statuses - branch_statuses=("${(@s/,/)match}") - for branch_status in $branch_statuses; do - if [[ ! $branch_status =~ "(behind|diverged|ahead) ([0-9]+)?" ]]; then - continue - fi - local last_parsed_status=$prefix_constant_map[$match[1]] - statuses_seen[$last_parsed_status]=$match[2] - done - fi - - # For each status prefix, do a regex comparison - for status_prefix in ${(k)prefix_constant_map}; do - local status_constant="${prefix_constant_map[$status_prefix]}" - local status_regex=$'(^|\n)'"$status_prefix" - - if [[ "$status_text" =~ $status_regex ]]; then - statuses_seen[$status_constant]=1 - fi - done - - # Display the seen statuses in the order specified - local status_prompt - for status_constant in $status_constants; do - if (( ${+statuses_seen[$status_constant]} )); then - local next_display=$constant_prompt_map[$status_constant] - status_prompt="$next_display$status_prompt" - fi - done - - echo $status_prompt -} - -# Outputs the name of the current user -# Usage example: $(git_current_user_name) -function git_current_user_name() { - __git_prompt_git config user.name 2>/dev/null -} - -# Outputs the email of the current user -# Usage example: $(git_current_user_email) -function git_current_user_email() { - __git_prompt_git config user.email 2>/dev/null -} - -# Output the name of the root directory of the git repository -# Usage example: $(git_repo_name) -function git_repo_name() { - local repo_path - if repo_path="$(__git_prompt_git rev-parse --show-toplevel 2>/dev/null)" && [[ -n "$repo_path" ]]; then - echo ${repo_path:t} - fi -} diff --git a/roles/zsh/tasks/main.yaml b/roles/zsh/tasks/main.yaml deleted file mode 100644 index 225e5989..00000000 --- a/roles/zsh/tasks/main.yaml +++ /dev/null @@ -1,34 +0,0 @@ ---- -- name: Install - ansible.builtin.package: - name: - - zsh - state: latest - become: true - -- name: Set default - user: - name: "{{ ansible_env['USER'] }}" - shell: /usr/bin/zsh - become: yes - -- name: Configuration - ansible.builtin.file: - src: "{{ role_path }}/files/{{ zsh_config_item.src }}" - path: "{{ zsh_config_item.path }}" - state: link - loop_control: - loop_var: zsh_config_item - with_items: - - { src: config, path: "{{ ansible_user_dir }}/.config/zsh" } - - { src: .zshenv, path: "{{ ansible_user_dir }}/.zshenv" } - -- name: Delete old files - ansible.builtin.file: - path: "{{ old_files_item }}" - state: absent - loop_control: - loop_var: old_files_item - with_items: - - "{{ ansible_user_dir }}/.zsh" - - "{{ ansible_user_dir }}/.zshrc" diff --git a/secrets.nix b/secrets.nix new file mode 100644 index 00000000..23e41540 --- /dev/null +++ b/secrets.nix @@ -0,0 +1,40 @@ +let + hosts = { + nixedo = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAILvtcGJnc94k6wCPfvK9oBvGey0WWVCR8IYSqg5vqage"; + t480 = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAILvtcGJnc94k6wCPfvK9oBvGey0WWVCR8IYSqg5vqage"; + }; + + users = { + opdavies = "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAACAQDkkbYaCD9NUIQT0NnsmlyfepwjxBYeiJSBCotOpdPTyc5inFAd29DiVw98j4skfaHdzjcqWmMFmDQWM6tGkK7eg8n0WuaABmsjdEbzTtfjHwM0tRDCIh5AtoT4IvoLhwLjEI2jKM05BGCQ2m5lS//AYJK1DjiV4UH+IjXHz6oy/3eFzQwANjxWS+mbR565p21yuAu1DKEyaGeVzT1xDhgzlnZG7Cys/rFgUYpIvYDHMOFxG6hsDB8vqyHiTXniniti5tdvGGYHgRGQcynRTU12aerrqHTIOefrElXJdf3/PA8FIY/Pd3MmZocY/vvQe0EVHXWrNtnHOF3MFQ1tFyfubKO51Dcp9KmzHnyBvO4CtvGVr/upSVWfo0I/EqkIqvCvBbdSIPeH9V5hAcyWENGF4Wf0/Yqtc0dBhfXJmPVBsC2ghZp9oERK+h5Xs7DpzkT0vtkN+wjgA5weIuG8e2UVNO29LWASzlychVqb7BVa6kNn5CyGwauyIGsYvAFnUjkyJpK8qleNM3VO5x9aw26IhSKlnSE9PAdX8p7PpdoWfxWRekKTc4h6iAe7pFOENvuokAvCNsE5LolR4VrYKXjA0m3nupDNWYexAWfR3lSeSlKd9nD3OENS0biJKayZHs11iDUTxm5u5gm/U60b4z0zDXjh1H/DI/pSCG6jjaXDpw=="; + }; +in +{ + "secrets/cloudflare.age".publicKeys = [ + hosts.nixedo + hosts.t480 + ] + ++ [ users.opdavies ]; + + "secrets/cloudflared-credentials.age".publicKeys = [ + hosts.nixedo + ] + ++ [ users.opdavies ]; + + "secrets/forgejo-runner-token.age".publicKeys = [ + hosts.nixedo + ] + ++ [ users.opdavies ]; + + "secrets/peertube-env.age".publicKeys = [ + hosts.nixedo + ] + ++ [ users.opdavies ]; + + "secrets/tubearchivist-env.age".publicKeys = [ + hosts.nixedo + hosts.t480 + ] + ++ [ users.opdavies ]; + + "secrets/vaultwarden-env.age".publicKeys = [ hosts.nixedo ] ++ [ users.opdavies ]; +} diff --git a/secrets/cloudflare.age b/secrets/cloudflare.age new file mode 100644 index 00000000..4c092f31 --- /dev/null +++ b/secrets/cloudflare.age @@ -0,0 +1,23 @@ +age-encryption.org/v1 +-> ssh-ed25519 M7i4ow JbGsQZjXyc/TOA5Bc2J1F4dUPImFkb2sJstGTiwS0lw +KhsNg7sOj7n2iOpKyKX8pfzFC16oYK+3GnE0PtwUres +-> ssh-ed25519 e6k47Q 5u6J38BGCrhgUo9+JrWNXLTbY6GwiSRc7EyrCnMqIBQ +rxCoxCxNcPIVhSXBItEnRyWi1lVRl0u7PH5EqydU4Bo +-> ssh-ed25519 IsVD3g xy60nMsxrMEVVHse7cfmvTtnzYZMr/8bHQ77dwBVmxo +wlJJVdek+bN6tzbxAl594FR9MBR93nQyvwqCLREp2Sw +-> ssh-ed25519 IsVD3g ATYSZBSFln40HNRBvAPd85D4ax8TA4vWc4JsgqvXpxU +YfUmlZLkQi9QFeuZ1kJdR3toWD/gkoTz+XAtBFx2qKY +-> ssh-rsa +vTWQw +cohbs+XV518CcQvwPPn5uAPsMVbn8MFx5FKOQVXyBcxXsK88fdQtBcp+BcgUfHeE ++HJLB5KDs3lfHiEVDX7Z2BBVx1y9y+j0f8vi8GKNvTLSAAdMwp7LFS/aNcjboayf +gn/+E+qtd4yiscSBBgsZvUBibkyRM+uVstXqACeX9S4j7TctsqpdEMvJKrbYJ0zQ +7KsZyyT6QeIp7H9zMLQg2Gv7W2co5+ny3S1saL/5F51gy68LaReAIvB+GAs2TzCY +AJVo1ANAG3JMRftGtUoNXgieyzXMKf/ucsC1OvwgUDlCDfqjHsiUlAaG64NWe1+K +3DB1nnE/RkbkPj4gEcHxgiPX6/zC/ZS/sVYOBpktZeyb+ofsVhwQ/Xb0MJAwvknY +WvETJ4DL4VQx4eC1v3yEYsgak1opnwOnRodeKbvR6pr+KeinFiKoF9dh9LQu9ByM +ocqCBEHRfzkL1ZM2BYS1hlYo6ECSoSKiNQ8J+BF6wNMLM7WwG9G+LHCw8DMeAo1n +DCpOMJXII2G1Mvgz/kUE63QB747uc7IImhYj5AQwTgYo/TUttVG6iEaJVGi5EFH0 +dwUPQU3wbYZiWTfKBYfBEX6+zyqSw20PpoQHbCouqOjKV37Ntwh3XhcyMOCBKB5L +ugK55xOpNwbVxSh6zjyis4YLk0ON5UI9cyxqx44Z8kY +--- ziQ837ro8cdUK22H13GWtnEVkq+QpSIwbwIYXU7t6H8 +LIːvMĘlYZ{CKLR߂Ĺ Bya`*p3miK=Ļj"LQ08ArKBE:XӜbWü*6NyhuF_Fohc0 \ No newline at end of file diff --git a/secrets/cloudflared-credentials.age b/secrets/cloudflared-credentials.age new file mode 100644 index 00000000..dc592620 --- /dev/null +++ b/secrets/cloudflared-credentials.age @@ -0,0 +1,17 @@ +age-encryption.org/v1 +-> ssh-ed25519 IsVD3g jeHVvTzxsEQOGls45oDKjDCWDSejIiPnSNZxnZRRPiQ +sapo+FofxdYGeidn49uEO+D+SDK9KKLRUAWJMoU5T10 +-> ssh-rsa +vTWQw +4SfYg8oc9eBd4zHYfDFYhUTmzHG4HGuz6wpcXMgmiemD5CIt+q2Q5ZzHnUhbfUsm +GIDlRFjN6JWbJSmzW3HpUt/t7WQVk44QyOD5azHM3d8ctcv7ana2npPukQKGqpWu +hWFX6amY5ng2yf1hfeeUgvhKIpDGxgnFKfAbNCheqdgWHWLaUpDSCuc0eugOziMD +RWEsLsHudpdWHtik0cB/Uwycpc/T09sOm2k36H2mMvtjeWdldSHezOcn0uO7Gs9H +OxpPdcuwTeisb6R3zI12ZAL/vEu/8h25OWNkfM64O4p/rkgPpbqhJBiIZL04vRcy +zLnq967b9RqqjmDZFPOkcZBtXm5ck1qo4UYDRck2wkQLfUNkHAYHnwO+29RxstA0 +ShQe1uUo68Hx17st/X2wwUZlnfhTcJ4IZwmuOiEZiNgmwbb9ZXBTi8myV1Tpgpkh +I0ooy/pU/tocS2/4XjYwcjRMmEcI0r7ESOgJmyzoakwM7Jbh3kaTDXd324vPYzhQ +SPvosb9VFNCQFuc02LOD1Psy74IEGp5xIMRKGxDE8VSnFFMiNpu3La6HRlrb6e4s +/G2OZ9lsrXSC8gyOF78olk1QMkuSvT6Lw56QhMbuC1XiVINd3+GKQNkE8T2BPAKS +P5PBYTbi0bZjqA4OwbBf+nSPxljUGed1R3IbpAvPM04 +--- 2VNOkmpXcK+ywl+DBli84MCED52jL/dPiIpzN82Xrqg +VByr=]]Q6>-3kP7Bi0sFԸϣn|f0ڡY$zU?""%%<ދ*yf^hVCNgm婪g=++v:u9#BS;Ji76h @7`$5$fV3V"; \ No newline at end of file diff --git a/secrets/forgejo-runner-token.age b/secrets/forgejo-runner-token.age new file mode 100644 index 00000000..78f0fe94 --- /dev/null +++ b/secrets/forgejo-runner-token.age @@ -0,0 +1,17 @@ +age-encryption.org/v1 +-> ssh-ed25519 IsVD3g VZRQKGdeV/lghsgN7xSWAuxOsThIU4cpBPEA5jRU/Ro +rlVrONsaGdSAW7jk04RbmxqBRr1nIpZi/QYJdhZNF8A +-> ssh-rsa +vTWQw +igGVvcUh30WG4jDQcXL906pmEk6NCDt0Fl0XC6q3ZuAeJHK1wZ70XKPTehb1JM4U +YSb5vsVW0J6Fv9kWbpfuSGo/eDoLwm45bP5OT+L3hThG8VRYlt4GuPt+BTdxBfcA +sLiQNBo/c+NeozLwsx39uwGZlBPXEiCWy2GR0tBpl97mpQgyLIvRleRMxzTtfN7Y +vreEbsOqo4kHMsAykGoOwMDVJpGArJBLNlm5cd9I0iHOvk9ugu919tNeiZ4vHyye +QKuoeAE24wqW/QXj98sFxz9SHi9UHJpqLMsgh2tCfvG6J65DItBzhWi7OKlgTUjy +7nhNOGMHtc4XBR/kjdt4z55ryb7t5DPdy6VIurJ3YAcZRm44o4LusHLw7llcNa20 +bXTiwZaICwK6Zi3deAASK4+DgbvThuKa6Ir0vaEK7Mik39ZanrIXDoFBv80ufBiq +tsFZex7Z/ZqqDR/WPnQKF92tz+Kqs7Jkka60ajYwkDdS6WnkOFPpKPJKayfutdF1 +9r6jzBUZEZ1E9avShow8ccw/FVhSnDzl9851TXZRyDrqFJ26s7484zHV9KpHPflh +qveux0fqB65vGl2ZvcsRawGVOw8G567s2HED6tuArdU98eEGC5Z/UdXPUYGpUSCK +zB9AQNtdS5IHY9CNKb7YqJFtvyaA7wlrd9Csp0UWVSY +--- i4UTmANM0HP3f9MKXDJZKyP2lod+E2dK8sNzHcm3y/o +ZpBl@Dp('u.X TO"Rrr=|ޮ:SQCDCb~V2 \ No newline at end of file diff --git a/secrets/peertube-env.age b/secrets/peertube-env.age new file mode 100644 index 00000000..0b03f08f --- /dev/null +++ b/secrets/peertube-env.age @@ -0,0 +1,18 @@ +age-encryption.org/v1 +-> ssh-ed25519 IsVD3g kyLYyMMYENXy2F1cnjVyptUhci5xfC8yrhvBtH8THUw +Q8sXfg7Wm4UMZ6jWGiBLgEKOqVvlCrHy8IthdpjRS/8 +-> ssh-rsa +vTWQw +i0sLs+iG1P7pvUAHCn1StChdaMlT+ze4qkI0beSzTbWm6+qoC7X9tBoJoBJbNGmQ +vIaJpYncYUn04r4WrYcjhBaYKYoECPGR0z/i9EtPT67DG6zuNEJLTclMStdudv4P +Y5uHDku3CoEF6l1nBabQmYtA6/7RT/wqQf+yYICp8pJX9fPtgkjbUtwx/EBOTz29 +t1Y6USjHI45IW9Od3G7XcZGuNkLkeV3clBEqWiFeck7+x3/SU8f8sv63M++Bitqb +F/ZXiLd/JDrlRhcgO0XsfKX+M6eodUg3ZQ7/0GFAjfYyiQp6uA5p/srIuTq40W1f +i7zzs0dewz75GjSKIWyivcYvQQzeobxDd6/1nhgtdjHCYyL5HV3QnE7Ew/ZoQPss +kIr25ftZ/sA87wg77J0c7koZneycSV1PioB2RyuW7cXP4ptMUOEaM0KjkLABBWNF ++WxIdGVd8d8E/zBbVnNNPNuKZYHEb6+eCo61Z8x7VAZhz61ziXOdOzeaN1Obgv+2 +Banoulrje4oF1L4KgO64NckVpYi6Od0Cl9W0hOxSt1BafokHYi4yxYiB2rmv/cdO +Q2IR10fKCd1BNYKvMPFia8j3Uv+OYJnilSNUi0bs+42UfFGcURZEgsSGluSIWP3W +ag1ENk3Y0tLR1WMj2mjbybk9JpEAWJ0oxT+oBOV2g9Q +--- iraOjJc4e+c1tH/YoiRIoEyyLVPgRx2xWaM5BUO1Fes +%Uck !XEw+1긑;+ +w& &m^us_nL<^,U \ No newline at end of file diff --git a/secrets/tubearchivist-env.age b/secrets/tubearchivist-env.age new file mode 100644 index 00000000..8e8fd5c1 --- /dev/null +++ b/secrets/tubearchivist-env.age @@ -0,0 +1,20 @@ +age-encryption.org/v1 +-> ssh-ed25519 IsVD3g JcpSuBgBp3nnPscb55121KL2XeCkBnwRwr57rFYE+nE +o0nLbL0tQWZIwOECYb+/zQsGo9/uoEpuaPqdxoZqY/Y +-> ssh-ed25519 IsVD3g fYyG89/0d3WO+aG9SaZ5+QMGrayd0y6EdnpjEx7mOTM +nbP/TlK5goWZe6ObIvqaRYTa7XPKprVoOeOZBPARON4 +-> ssh-rsa +vTWQw +mrS2MJwu/XgQd0y+bE9pa4iCZk8m1l6WQrnLb7tOaPXiVBObh03k6y9uWsfVSgmh +gnXHBQIAGXtdJ6qabt5jLDQrDxMZw1jxAr5QONR8Y+zmcw3BTvKYmVQRfsRlOM0O +qC4VG7CXcq7tcOEHKi3VliyUZW3R1SzXVhr72VXsug2IbWsNp/plusiA8MmLR3Mf +0N6z8ye1ZKRFHs4Q9ShyLad5JcJtkjrNmhbhQdZlNUQfOf+jrTEFrgKII96pCWqI +2eqpUbA1ameSUXgRknaZjIYQBmJd5ejvClGV5cojlD+DdX0W85mRW/Xj1CinUsGk +QZ+RFQ9GWGLLV8Uba707nbS1yMlnc2afJyG8dWGaH9m2E/9NnsFxCIbcQTrK28Yu +yabdui1sXG8stVWGK4FqCTuxNLv/bWC37IcFQQai9wgZhziyO07QR1jQ2xiMXLBZ +cw3KT8y8yYROzhZCuKoW/FAIrlsQv3ePBv+YEpnLF++2Pa25d1jmJXryAooDpBLd +5gi/hKvBeDPwtgStS0BjPYRM37tQ0UlHkcCqq8v2xeTX7VZpqWrzUcGX4DXCgxxX +Qrj5eDdomUfFH5NE8LWWNfpAlP1SOkM3ebCoa9e1sfEdJUzubIbSuRL/VFTm0SJe +WaUbIuTPOo7Sda6ZgM7lPFylqJNC8bHI5Ch6AH7UWX0 +--- GcN2m5Td0aMEWTrH6ZOyjplhvkHsHrCJfoyyfsbJHZo +xL}va1(t1$Cn߇;ftO@]ycvd +VQ XS;.Oס?HɊJD|'!w9gvRuNSú9 \ No newline at end of file diff --git a/secrets/vaultwarden-env.age b/secrets/vaultwarden-env.age new file mode 100644 index 00000000..522a87d7 Binary files /dev/null and b/secrets/vaultwarden-env.age differ diff --git a/stylua.toml b/stylua.toml deleted file mode 100644 index 348650b5..00000000 --- a/stylua.toml +++ /dev/null @@ -1,5 +0,0 @@ -indent_type = "Spaces" -indent_width = 2 -line_endings = "Unix" -no_call_parentheses = true -quote_style = "AutoPreferDouble" diff --git a/todo.txt b/todo.txt new file mode 100644 index 00000000..9fb12d75 --- /dev/null +++ b/todo.txt @@ -0,0 +1,18 @@ +Configure external hard drives on nixedo. + +server: +jellyfin +immich +tubearchivist +websites +forgejo + +Create a Home Manager module for bluetuith. +Enable tree-fmt + +Error detected while processing BufWritePost Autocommands for "*": +Error running vale: ENOENT: no such file or directory + +Re-add spellfile + +Re-add low battery notifications. diff --git a/users/opdavies.nix b/users/opdavies.nix new file mode 100644 index 00000000..613290c5 --- /dev/null +++ b/users/opdavies.nix @@ -0,0 +1,34 @@ +{ + config, + lib, + pkgs, + ... +}: + +with lib; + +{ + users.users.opdavies = { + description = "Oliver Davies"; + initialPassword = "opdavies"; + isNormalUser = true; + + extraGroups = [ + "networkmanager" + "wheel" + ]; + + packages = with pkgs; [ + magic-wormhole + ]; + + openssh.authorizedKeys.keys = [ + "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAACAQDkkbYaCD9NUIQT0NnsmlyfepwjxBYeiJSBCotOpdPTyc5inFAd29DiVw98j4skfaHdzjcqWmMFmDQWM6tGkK7eg8n0WuaABmsjdEbzTtfjHwM0tRDCIh5AtoT4IvoLhwLjEI2jKM05BGCQ2m5lS//AYJK1DjiV4UH+IjXHz6oy/3eFzQwANjxWS+mbR565p21yuAu1DKEyaGeVzT1xDhgzlnZG7Cys/rFgUYpIvYDHMOFxG6hsDB8vqyHiTXniniti5tdvGGYHgRGQcynRTU12aerrqHTIOefrElXJdf3/PA8FIY/Pd3MmZocY/vvQe0EVHXWrNtnHOF3MFQ1tFyfubKO51Dcp9KmzHnyBvO4CtvGVr/upSVWfo0I/EqkIqvCvBbdSIPeH9V5hAcyWENGF4Wf0/Yqtc0dBhfXJmPVBsC2ghZp9oERK+h5Xs7DpzkT0vtkN+wjgA5weIuG8e2UVNO29LWASzlychVqb7BVa6kNn5CyGwauyIGsYvAFnUjkyJpK8qleNM3VO5x9aw26IhSKlnSE9PAdX8p7PpdoWfxWRekKTc4h6iAe7pFOENvuokAvCNsE5LolR4VrYKXjA0m3nupDNWYexAWfR3lSeSlKd9nD3OENS0biJKayZHs11iDUTxm5u5gm/U60b4z0zDXjh1H/DI/pSCG6jjaXDpw==" + "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIHcR57U61CmPbV/QlaqeBZh3SNmWPGC7rhJpt1Ds3d3N" + ]; + }; + + age.identityPaths = [ + "/home/opdavies/.ssh/id_rsa" + ]; +} diff --git a/wallpaper/wallpaper.jpg b/wallpaper/wallpaper.jpg new file mode 100644 index 00000000..9c54212d Binary files /dev/null and b/wallpaper/wallpaper.jpg differ