Compare commits

..

1 Commits

Author SHA1 Message Date
renovate[bot]
3907502e75 chore(deps): update ivuorinen/actions action (v2026.01.21 → v2026.02.03)
Signed-off-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2026-02-04 01:24:17 +00:00
167 changed files with 21187 additions and 3385 deletions

View File

@@ -1,30 +0,0 @@
{
"hooks": {
"PreToolUse": [
{
"matcher": "Edit|Write",
"hooks": [
{
"type": "command",
"command": "fp=$(cat | jq -r '.tool_input.file_path // empty') && [ -n \"$fp\" ] && case \"$fp\" in */fzf-tmux|*/yarn.lock|*/.yarn/*) echo \"BLOCKED: $fp is a vendor/lock file — do not edit directly\" >&2; exit 2;; esac; exit 0"
}
]
}
],
"PostToolUse": [
{
"matcher": "Edit|Write",
"hooks": [
{
"type": "command",
"command": "fp=$(cat | jq -r '.tool_input.file_path // empty') && [ -n \"$fp\" ] && [ -f \"$fp\" ] && case \"$fp\" in *.sh|*/bin/*) head -1 \"$fp\" | grep -qE '^#!.*(ba)?sh' && command -v shfmt > /dev/null && shfmt -i 2 -bn -ci -sr -fn -w \"$fp\";; esac; exit 0"
},
{
"type": "command",
"command": "fp=$(cat | jq -r '.tool_input.file_path // empty') && [ -n \"$fp\" ] && [ -f \"$fp\" ] && case \"$fp\" in *.fish) command -v fish_indent > /dev/null && fish_indent -w \"$fp\";; esac; exit 0"
}
]
}
]
}
}

View File

@@ -1,38 +0,0 @@
---
name: fish-validate
description: >-
Validate fish scripts after editing.
Apply when writing or modifying any .fish file
in config/fish/.
user-invocable: false
allowed-tools: Bash, Read
---
After editing any `.fish` file in `config/fish/`, validate it:
## 1. Syntax check
```bash
fish --no-execute <file>
```
If syntax check fails, fix the issue before proceeding.
## 2. Format check
Run `fish_indent` to verify formatting:
```bash
fish_indent --check <file>
```
If formatting differs, apply it:
```bash
fish_indent -w <file>
```
## Key files to never validate
- Files inside `config/fish/functions/` prefixed with `_tide_`
(managed by the tide prompt plugin)

View File

@@ -1,22 +0,0 @@
---
name: lua-format
description: >-
Format Lua files after editing.
Apply when writing or modifying any .lua file.
user-invocable: false
allowed-tools: Bash
---
After editing any `.lua` file, format it with stylua:
```bash
stylua <file>
```
Project settings are in `stylua.toml` (90-char line length).
If stylua is not available, skip formatting silently.
## Files to never format
- Files inside `config/nvim/` managed by plugins (lazy.nvim lockfile)

View File

@@ -1,44 +0,0 @@
---
name: shell-validate
description: >-
Validate shell scripts after editing.
Apply when writing or modifying any shell script
in local/bin/ or scripts/.
user-invocable: false
allowed-tools: Bash, Read, Grep
---
After editing any shell script in `local/bin/`, `scripts/`, or `config/`
(files with a `#!` shebang or `# shellcheck shell=` directive),
validate it:
## 1. Determine the shell
- `/bin/sh` or `#!/usr/bin/env sh` shebang -> POSIX, use `sh -n`
- `/bin/bash` or `#!/usr/bin/env bash` shebang -> Bash, use `bash -n`
- `# shellcheck shell=bash` directive (no shebang) -> use `bash -n`
- `# shellcheck shell=sh` directive (no shebang) -> use `sh -n`
- No shebang and no directive -> default to `bash -n`
## 2. Syntax check
Run the appropriate syntax checker:
```bash
bash -n <file> # for bash scripts
sh -n <file> # for POSIX sh scripts
```
If syntax check fails, fix the issue before proceeding.
## 3. ShellCheck
Run `shellcheck <file>`. The project `.shellcheckrc` already
disables SC2039, SC2166, SC2154, SC1091, SC2174, SC2016.
Only report and fix warnings that are NOT in that exclude list.
## Key files to never validate (not shell scripts)
- `local/bin/fzf-tmux` (vendor file)
- `*.md` files
- `*.bats` test files (Bats, not plain shell)

View File

@@ -8,10 +8,6 @@ indent_style = space
insert_final_newline = true
trim_trailing_whitespace = true
[*.py]
indent_size = 4
max_line_length = 120
[*.fish]
max_line_length = 120

6
.github/README.md vendored
View File

@@ -37,7 +37,7 @@ see what interesting stuff you've done with it. Sharing is caring.
### Interesting folders
| Path | Description |
|---------------------|----------------------------------------------|
| ------------------- | -------------------------------------------- |
| `.github` | GitHub Repository configuration files, meta. |
| `hosts/{hostname}/` | Configs that should apply to that host only. |
| `local/bin` | Helper scripts that I've collected or wrote. |
@@ -52,7 +52,7 @@ is processed by Dotbot during installation.
### dotfile folders
| Repo | Destination | Description |
|-----------|-------------|---------------------------------------------|
| --------- | ----------- | ------------------------------------------- |
| `base/` | `.*` | `$HOME` level files. |
| `config/` | `.config/` | Configurations for applications. |
| `local/` | `.local/` | XDG Base folder: `bin`, `share` and `state` |
@@ -86,7 +86,7 @@ The folder structure follows [XDG Base Directory Specification][xdg] where possi
### XDG Variables
| Env | Default | Short description |
|--------------------|----------------------|------------------------------------------------|
| ------------------ | -------------------- | ---------------------------------------------- |
| `$XDG_BIN_HOME` | `$HOME/.local/bin` | Local binaries |
| `$XDG_CONFIG_HOME` | `$HOME/.config` | User-specific configs |
| `$XDG_DATA_HOME` | `$HOME/.local/share` | User-specific data files |

View File

@@ -9,27 +9,25 @@ concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true
permissions:
contents: read
permissions: read-all
jobs:
debug-changelog:
runs-on: ubuntu-latest
permissions:
contents: read
permissions: write-all
steps:
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
- name: Create changelog text
id: changelog
uses: loopwerk/tag-changelog@8dd150d55fbf1fe93e0ea00a29a6153aaeb81912 # v1.5.0
uses: loopwerk/tag-changelog@941366edb8920e2071eae0449031830984b9f26e # v1.3.0
with:
token: ${{ secrets.GITHUB_TOKEN }}
config_file: .github/tag-changelog-config.js
- name: "Echo results"
- name: 'Echo results'
id: output-changelog
run: |
echo "${{ steps.changelog.outputs.changes }}"

View File

@@ -11,8 +11,7 @@ concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true
permissions:
contents: read
permissions: read-all
jobs:
Linter:
@@ -31,9 +30,9 @@ jobs:
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
- name: Yarn Lock Changes
uses: Simek/yarn-lock-changes@59f47ee499424d2c2437c5aebf863b5c6d50a5bc # v0.14.1
uses: Simek/yarn-lock-changes@c7543145aaafdd8fc925cea5d85b2bd5a73091f8 # v0.14.0
with:
token: ${{ secrets.GITHUB_TOKEN }}
- name: Run PR Lint
uses: ivuorinen/actions/pr-lint@6e8f2aae9d0846d901d9eba15b8e94a2900573dc # v2026.03.02
uses: ivuorinen/actions/pr-lint@f371da218e9152e7d29ee39358454e41010c36dc # v2026.02.03

View File

@@ -5,21 +5,19 @@ name: Release Daily State
on:
workflow_dispatch:
schedule:
- cron: "0 21 * * *" # 00:00 at Europe/Helsinki
- cron: '0 21 * * *' # 00:00 at Europe/Helsinki
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true
permissions:
contents: read
permissions: read-all
jobs:
new-daily-release:
runs-on: ubuntu-latest
permissions:
contents: write
permissions: write-all
outputs:
created: ${{ steps.daily-version.outputs.created }}
@@ -35,7 +33,7 @@ jobs:
- name: Create changelog text
if: steps.daily-version.outputs.created
id: changelog
uses: loopwerk/tag-changelog@8dd150d55fbf1fe93e0ea00a29a6153aaeb81912 # v1.5.0
uses: loopwerk/tag-changelog@941366edb8920e2071eae0449031830984b9f26e # v1.3.0
with:
token: ${{ secrets.GITHUB_TOKEN }}
config_file: .github/tag-changelog-config.js

View File

@@ -5,15 +5,14 @@ name: Pre-commit autoupdate
on:
schedule:
# At 04:00 on Monday and Thursday.
- cron: "0 4 * * 1,4"
- cron: '0 4 * * 1,4'
workflow_dispatch:
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true
permissions:
contents: read
permissions: read-all
jobs:
auto-update:
@@ -34,6 +33,6 @@ jobs:
with:
token: ${{ secrets.GITHUB_TOKEN }}
branch: update/pre-commit-hooks
title: "chore: update pre-commit hooks"
commit-message: "chore: update pre-commit hooks"
title: 'chore: update pre-commit hooks'
commit-message: 'chore: update pre-commit hooks'
body: Update versions of pre-commit hooks to latest version.

View File

@@ -14,8 +14,7 @@ concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true
permissions:
pull-requests: read
permissions: read-all
jobs:
semantic-pr:

View File

@@ -11,7 +11,7 @@ on:
- .github/workflows/sync-labels.yml
- .github/labels.yml
schedule:
- cron: "34 5 * * *"
- cron: '34 5 * * *'
workflow_call:
workflow_dispatch:
@@ -19,8 +19,7 @@ concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true
permissions:
contents: read
permissions: read-all
jobs:
SyncLabels:
@@ -30,4 +29,4 @@ jobs:
issues: write
steps:
- uses: ivuorinen/actions/sync-labels@6e8f2aae9d0846d901d9eba15b8e94a2900573dc # v2026.03.02
- uses: ivuorinen/actions/sync-labels@f371da218e9152e7d29ee39358454e41010c36dc # v2026.02.03

View File

@@ -5,22 +5,20 @@ name: Update submodules
on:
schedule:
# At 04:00 on Monday and Thursday.
- cron: "0 4 * * 1"
- cron: '0 4 * * 1'
workflow_dispatch:
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true
permissions:
contents: read
permissions: read-all
jobs:
update-submodules:
runs-on: ubuntu-latest
permissions:
contents: write
permissions: write-all
steps:
- name: Checkout repository

1
.gitignore vendored
View File

@@ -56,6 +56,5 @@ local/man/yabai.1
local/share/fonts/*
lock
node_modules
__pycache__
ssh/local.d/*
config/fish/fish_variables*

12
.gitmodules vendored
View File

@@ -4,6 +4,11 @@
url = https://github.com/anishathalye/dotbot.git
ignore = dirty
[submodule "dotbot-brew"]
path = tools/dotbot-brew
url = https://github.com/wren/dotbot-brew.git
ignore = dirty
[submodule "dotbot-include"]
path = tools/dotbot-include
url = https://gitlab.com/gnfzdz/dotbot-include.git
@@ -24,6 +29,11 @@
url = https://github.com/tmux-plugins/tmux-sessionist.git
ignore = dirty
[submodule "dotbot-pip"]
path = tools/dotbot-pip
url = https://github.com/sobolevn/dotbot-pip.git
ignore = dirty
[submodule "tmux/tmux-suspend"]
path = config/tmux/plugins/tmux-suspend
url = https://github.com/MunifTanjim/tmux-suspend.git
@@ -53,8 +63,6 @@
[submodule "tmux/tmux-resurrect"]
path = config/tmux/plugins/tmux-resurrect
url = https://github.com/tmux-plugins/tmux-resurrect.git
ignore = dirty
[submodule "tmux/catppuccin"]
path = config/tmux/plugins/catppuccin
url = https://github.com/catppuccin/tmux.git
ignore = dirty

View File

@@ -6,5 +6,6 @@ config/tmux/plugins/**
config/vim/plugged/**
node_modules
tools/antidote/**
tools/dotbot-brew/**
tools/dotbot-include/**
tools/dotbot/**

View File

@@ -9,21 +9,16 @@ VALIDATE_ALL_CODEBASE: true
FILEIO_REPORTER: false # Generate file.io report
GITHUB_STATUS_REPORTER: true # Generate GitHub status report
IGNORE_GENERATED_FILES: true # Ignore generated files
JAVASCRIPT_DEFAULT_STYLE: prettier # Default style for JavaScript
PRINT_ALPACA: false # Print Alpaca logo in console
SARIF_REPORTER: true # Generate SARIF report
SHOW_SKIPPED_LINTERS: false # Show skipped linters in MegaLinter log
TYPESCRIPT_DEFAULT_STYLE: prettier # Default style for TypeScript
DISABLE_LINTERS:
- REPOSITORY_DEVSKIM
- JAVASCRIPT_ES # using biome
- JAVASCRIPT_PRETTIER # using biome
- TYPESCRIPT_PRETTIER # using biome
- JSON_PRETTIER # using biome
- PYTHON_BLACK # using ruff
- PYTHON_FLAKE8 # using ruff
- PYTHON_PYLINT # using ruff
- PYTHON_ISORT # using ruff (I rules)
YAML_YAMLLINT_CONFIG_FILE: .yamllint.yml
REPOSITORY_GIT_DIFF_DISABLE_ERRORS: true
BASH_SHFMT_ARGUMENTS: -i 2 -bn -ci -sr -fn
FILTER_REGEX_EXCLUDE: >
(node_modules|tools|config/cheat/cheatsheets/community|config/cheat/cheatsheets/tldr|config/fzf|config/zsh|config/tmux/plugins)

2
.nvmrc
View File

@@ -1 +1 @@
24.14.0
24.13.0

View File

@@ -28,25 +28,12 @@ repos:
entry: yarn biome check --write --files-ignore-unknown=true --no-errors-on-unmatched
language: system
files: \.(js|ts|jsx|tsx|json|md)$
- id: markdown-table-formatter
name: Markdown Table Formatter
entry: yarn markdown-table-formatter
language: system
types: [markdown]
- repo: https://github.com/adrienverge/yamllint
rev: v1.38.0
hooks:
- id: yamllint
- repo: https://github.com/pre-commit/mirrors-prettier
rev: v4.0.0-alpha.8
hooks:
- id: prettier
types_or: [yaml]
additional_dependencies:
- prettier@3.8.1
- repo: https://github.com/shellcheck-py/shellcheck-py
rev: v0.11.0.1
hooks:
@@ -56,10 +43,9 @@ repos:
rev: v3.12.0-2
hooks:
- id: shfmt
args: [-i, "2", -bn, -ci, -sr, -fn, -w]
- repo: https://github.com/rhysd/actionlint
rev: v1.7.11
rev: v1.7.10
hooks:
- id: actionlint
@@ -74,10 +60,3 @@ repos:
hooks:
- id: fish_syntax
- id: fish_indent
- repo: https://github.com/astral-sh/ruff-pre-commit
rev: v0.15.5
hooks:
- id: ruff-check
args: [--fix]
- id: ruff-format

View File

@@ -1,19 +0,0 @@
node_modules
.yarn
.pnp.*
.mypy_cache
Brewfile.lock.json
lazy-lock.json
config/cheat/cheatsheets/community
config/cheat/cheatsheets/tldr
config/fzf
config/nvim
config/op/plugins/used_plugins
config/tmux/plugins
config/vim/plugged
config/zsh
local/bin/antigen.zsh
local/bin/asdf
tools
docs/plans
config/gh/hosts.yml

View File

@@ -1,9 +0,0 @@
{
"$schema": "https://json.schemastore.org/prettierrc",
"printWidth": 200,
"tabWidth": 2,
"useTabs": false,
"endOfLine": "lf",
"singleQuote": false,
"proseWrap": "preserve"
}

View File

@@ -1 +1 @@
3.14.3
3.14.2

View File

@@ -13,11 +13,11 @@ ignore_all_files_in_gitignore: true
# Was previously called `ignored_dirs`, please update your config if you are using that.
# Added (renamed) on 2025-04-07
ignored_paths:
- "*.swp"
- "*.tmp"
- "*.tmp.*"
- ".DS_Store"
- ".git/**"
- '*.swp'
- '*.tmp'
- '*.tmp.*'
- '.DS_Store'
- '.git/**'
- /config/cheat/cheatsheets/community/**
- /config/cheat/cheatsheets/pure-bash-bible/**
- /config/cheat/cheatsheets/tldr/**
@@ -85,6 +85,6 @@ excluded_tools: []
# initial prompt for the project. It will always be given to the LLM upon activating the project
# (contrary to the memories, which are loaded on demand).
initial_prompt: ""
initial_prompt: ''
project_name: ".dotfiles"
project_name: '.dotfiles'

162
CLAUDE.md
View File

@@ -1,162 +0,0 @@
# CLAUDE.md
This file provides guidance to Claude Code (claude.ai/code)
when working with code in this repository.
## Repository Overview
Personal dotfiles repository for Ismo Vuorinen.
Uses **Dotbot** (not GNU Stow) to symlink configuration files into place.
The directory layout follows the XDG Base Directory Specification.
## Directory Layout and Linking
| Source | Destination | Notes |
|---------------------|-------------------|-------------------------------------------|
| `base/*` | `~/.*` | Home-level dotfiles (`.` added by Dotbot) |
| `config/*` | `~/.config/` | Application configurations |
| `local/bin/*` | `~/.local/bin/` | Helper scripts and utilities |
| `local/share/*` | `~/.local/share/` | Data files |
| `local/man/**` | `~/.local/man/` | Manual pages |
| `ssh/*` | `~/.ssh/` | SSH configuration (mode 0600) |
| `hosts/<hostname>/` | Overlays | Host-specific overrides |
Installation: `./install` runs Dotbot with `install.conf.yaml`,
then applies `hosts/<hostname>/install.conf.yaml` if it exists.
## Commands
```bash
# Install dependencies (required before lint/test)
yarn install
# Linting
yarn lint # Run biome + prettier + editorconfig-checker
yarn lint:biome # Biome only
yarn lint:ec # EditorConfig checker only
yarn lint:md-table # Markdown table formatting check
yarn fix:md-table # Auto-fix markdown tables
# Formatting
yarn fix:biome # Autofix with biome (JS/TS/JSON/MD)
yarn fix:prettier # Autofix with prettier (YAML)
yarn format # Format with biome
yarn format:yaml # Format YAML files with prettier
# Testing (Bats - Bash Automated Testing System)
yarn test # Run all tests in tests/
# Run a single test file:
./node_modules/.bin/bats tests/dfm.bats
# Shell linting
shellcheck <script> # Lint shell scripts
# Tooling maintenance
yarn biome migrate --write # Update biome schema version
```
## Pre-commit Hooks
Configured in `.pre-commit-config.yaml`: shellcheck, shfmt, biome,
yamllint, prettier, actionlint, stylua, fish_syntax/fish_indent.
Run `pre-commit run --all-files` to check everything.
## Commit Convention
Semantic Commit messages: `type(scope): summary`
(e.g., `fix(tmux): correct prefix binding`).
Enforced by commitlint extending `@ivuorinen/commitlint-config`.
## Architecture
### Shell Configuration Chain
Both `base/bashrc` and `base/zshrc` source `config/shared.sh`,
which loads:
- `config/exports` — environment variables, XDG dirs, PATH
- `config/alias` — shell aliases
Zsh additionally uses **antidote** (in `tools/antidote/`)
for plugin management and **oh-my-posh** for the prompt.
### msgr — Messaging Helper
`local/bin/msgr` provides colored output functions (`msgr msg`,
`msgr run`, `msgr yay`, `msgr err`, `msgr warn`). Sourced by `dfm`
and most scripts in `local/bin/`.
### dfm — Dotfiles Manager
`local/bin/dfm` is the main management script. Key commands:
- `dfm install all` — install everything in tiered stages
- `dfm brew install` / `dfm brew update` — Homebrew management
- `dfm apt upkeep` — APT package maintenance (Debian/Ubuntu)
- `dfm dotfiles fmt` / `dfm dotfiles shfmt` — format configs/scripts
- `dfm helpers <name>` — inspect aliases, colors, env, functions, path
- `dfm docs all` — regenerate documentation under `docs/`
- `dfm check arch` / `dfm check host` — system info
- `dfm scripts` — run scripts from `scripts/` (discovered via `@description` tags)
- `dfm tests` — test visualization helpers
### Submodules
External dependencies are git submodules (Dotbot, plugins,
tmux plugins, cheatsheets, antidote).
Managed by `add-submodules.sh`. All set to `ignore = dirty`.
Updated automatically via GitHub Actions on a schedule.
### Host-specific Configs
Machine-specific overrides live in `hosts/<hostname>/`
with their own `base/`, `config/`, and `install.conf.yaml`.
These are layered on top of the global config during installation.
## Code Style
- **EditorConfig**: 2-space indent, UTF-8, LF line endings.
See `.editorconfig` for per-filetype overrides
(4-space for PHP/fish, tabs for git config).
- **Shell scripts**: Must have a shebang or
`# shellcheck shell=bash` directive.
Follow shfmt settings in `.editorconfig`
(2-space indent, `binary_next_line`,
`switch_case_indent`, `space_redirects`, `function_next_line`).
- **Lua** (neovim config): Formatted with stylua (`stylua.toml`),
90-char line length.
- **JSON/JS/TS/Markdown**: Formatted with Biome (`biome.json`),
80-char width.
- **YAML**: Formatted with Prettier (`.prettierrc.json`),
validated with yamllint (`.yamllint.yml`).
## ShellCheck Disabled Rules
Defined in `.shellcheckrc`:
SC2039 (POSIX `local`), SC2166 (`-o` in test),
SC2154 (unassigned variables), SC1091 (source following),
SC2174 (mkdir -p -m), SC2016 (single-quote expressions).
## Gotchas
- **POSIX scripts**: `x-ssh-audit`, `x-codeql`, `x-until-error`,
`x-until-success`, `x-ssl-expiry-date` use `/bin/sh`.
Validate with `sh -n`, not `bash -n`.
- **Vendor file**: `local/bin/fzf-tmux` is vendored from
junegunn/fzf — do not modify.
- **Fish config**: `config/fish/` has its own config chain
(`config.fish`, `exports.fish`, `alias.fish`) plus 60+ functions.
- **gh CLI config**: `config/gh/hosts.yml` is managed by `gh` CLI
and excluded from prettier (see `.prettierignore`).
- **Python**: Two scripts (`x-compare-versions.py`,
`x-git-largest-files.py`) linted by Ruff (config in `pyproject.toml`).
## Claude Code Configuration
- **Hooks** (`.claude/settings.json`):
- *PreToolUse*: Blocks edits to `fzf-tmux`, `yarn.lock`, `.yarn/`
- *PostToolUse*: Auto-runs `shfmt` on shell scripts after Edit/Write
- **Skills** (`.claude/skills/`):
- `shell-validate`: Auto-validates shell scripts (syntax + shellcheck)
## Package Manager
Yarn (v4.12.0) is the package manager. Do not use npm.

View File

@@ -5,8 +5,12 @@ git submodule sync --recursive
# dotbot and plugins
git submodule add --name dotbot \
-f https://github.com/anishathalye/dotbot.git tools/dotbot
git submodule add --name dotbot-brew \
-f https://github.com/wren/dotbot-brew.git tools/dotbot-brew
git submodule add --name dotbot-include \
-f https://gitlab.com/gnfzdz/dotbot-include.git tools/dotbot-include
git submodule add --name dotbot-pip \
-f https://github.com/sobolevn/dotbot-pip.git tools/dotbot-pip
# other repos
git submodule add --name cheat-community \
@@ -42,70 +46,26 @@ done
# Mark certain repositories shallow
git config -f .gitmodules submodule.antidote.shallow true
# Log a message using msgr if available, else echo
_log()
{
local msg="$1"
if command -v msgr > /dev/null 2>&1; then
msgr run_done "$msg"
else
echo " [ok] $msg"
fi
return 0
}
# Remove a stale git submodule and clean up references
remove_old_submodule()
{
local name="$1" path="$2"
# Remove working tree
if [[ -d "$path" ]]; then
rm -rf "$path"
_log "Removed $path"
fi
# Remove stale git index entry
git rm --cached "$path" 2> /dev/null || true
# Remove .git/config section keyed by path
git config --remove-section "submodule.$path" 2> /dev/null || true
# Skip name-based cleanup if no submodule name provided
[[ -z "$name" ]] && return 0
# Remove .git/config section keyed by name
git config --remove-section "submodule.$name" 2> /dev/null || true
# Remove .git/modules/<name>/ cached repository
if [[ -d ".git/modules/$name" ]]; then
rm -rf ".git/modules/$name"
_log "Removed .git/modules/$name"
fi
}
# remove old submodules (name:path pairs)
old_submodules=(
"tmux/tpm:config/tmux/plugins/tpm"
":config/tmux/plugins/tmux"
"tmux/tmux-menus:config/tmux/plugins/tmux-menus"
"dotbot-crontab:tools/dotbot-crontab"
"dotbot-snap:tools/dotbot-snap"
"tmux/tmux-window-name:config/tmux/plugins/tmux-window-name"
"tmux/tmux-sensible:config/tmux/plugins/tmux-sensible"
"tmux/tmux-mode-indicator:config/tmux/plugins/tmux-mode-indicator"
"tmux/tmux-yank:config/tmux/plugins/tmux-yank"
":config/tmux/plugins/tmux-fzf-url"
"nvim-kickstart:config/nvim-kickstart"
"asdf:local/bin/asdf"
"asdf:local/asdf"
"dotbot-asdf:tools/dotbot-asdf"
"dotbot-pip:tools/dotbot-pip"
"dotbot-brew:tools/dotbot-brew"
# remove old submodules
folders=(
"config/tmux/plugins/tpm"
"config/tmux/plugins/tmux"
"config/tmux/plugins/tmux-menus"
"tools/dotbot-crontab"
"tools/dotbot-snap"
"config/tmux/plugins/tmux-window-name"
"config/tmux/plugins/tmux-sensible"
"config/tmux/plugins/tmux-mode-indicator"
"config/tmux/plugins/tmux-yank"
"config/tmux/plugins/tmux-fzf-url"
"config/nvim-kickstart"
"local/bin/asdf"
"local/asdf"
"tools/dotbot-asdf"
)
for entry in "${old_submodules[@]}"; do
name="${entry%%:*}"
path="${entry#*:}"
remove_old_submodule "$name" "$path"
for folder in "${folders[@]}"; do
[ -d "$folder" ] \
&& rm -rf "$folder" \
&& msgr run_done "Removed old submodule $folder"
done

View File

@@ -2,17 +2,20 @@
# shellcheck shell=bash
export DOTFILES="$HOME/.dotfiles"
# Minimal PATH for x-have and utilities; full PATH set in shared.sh/exports
export PATH="$HOME/.local/bin:$DOTFILES/local/bin:$PATH"
export SHARED_SCRIPTS_SOURCED=0
source "$DOTFILES/config/shared.sh"
if [ -n "${GHOSTTY_RESOURCES_DIR}" ]; then
builtin source "${GHOSTTY_RESOURCES_DIR}/shell-integration/bash/ghostty.bash"
fi
# shellcheck source=../config/fzf/fzf.bash
[ -f "${DOTFILES}/config/fzf/fzf.bash" ] &&
source "${DOTFILES}/config/fzf/fzf.bash"
# Import ssh keys in keychain (macOS-specific -A flag, silently fails on Linux)
# Import ssh keys in keychain
ssh-add -A 2>/dev/null
x-have antidot && {
@@ -22,3 +25,6 @@ x-have antidot && {
PROMPT_DIRTRIM=3
PROMPT_COMMAND='PS1_CMD1=$(git branch --show-current 2>/dev/null)'
PS1='\[\e[95m\]\u\[\e[0m\]@\[\e[38;5;22;2m\]\h\[\e[0m\] \[\e[38;5;33m\]\w\[\e[0m\] \[\e[92;2m\]${PS1_CMD1}\n\[\e[39m\]➜\[\e[0m\] '
# Added by LM Studio CLI (lms)
export PATH="$PATH:$HOME/.lmstudio/bin"

1
base/envrc Normal file
View File

@@ -0,0 +1 @@
use node

View File

@@ -2,14 +2,14 @@
-- These globals can be set and accessed:
--
globals = {
"rawrequire",
"rawrequire",
}
--
-- These globals can only be accessed:
--
read_globals = {
"hs",
"ls",
"spoon",
"hs",
"ls",
"spoon",
}

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -7,13 +7,18 @@
autoload -U promptinit; promptinit
export DOTFILES="$HOME/.dotfiles"
# Minimal PATH for x-have and utilities; full PATH set in shared.sh/exports
export PATH="$HOME/.local/bin:$DOTFILES/local/bin:$PATH"
LOCAL_SHARE="$HOME/.local/share"
export PATH="$HOME/.local/bin:$DOTFILES/local/bin:$LOCAL_SHARE/nvim/mason/bin:$LOCAL_SHARE/bob/nvim-bin:$LOCAL_SHARE/cargo/bin:/opt/homebrew/bin:/usr/local/bin:$PATH"
export SHARED_SCRIPTS_SOURCED=0
source "$DOTFILES/config/shared.sh"
# zsh completions directory (ZSH_CUSTOM_COMPLETION_PATH set in shared.sh)
# zsh completions directory
[ -z "$ZSH_COMPLETIONS" ] && export ZSH_COMPLETIONS="$XDG_CONFIG_HOME/zsh/completion"
# Add zsh completions to FPATH, compinit will be called later
FPATH="$ZSH_COMPLETIONS:$FPATH"
ZSH_COMPDUMP="$XDG_CACHE_HOME/zsh/zcompdump-${SHORT_HOST}-${ZSH_VERSION}"
source "$DOTFILES/config/zsh/antidote.zsh"
@@ -32,9 +37,12 @@ source_fzf_config
x-have antidot && eval "$(antidot init)"
autoload -Uz compinit bashcompinit
compinit -d "$ZSH_COMPDUMP"
compinit -d $ZSH_COMPDUMP
bashcompinit
# To customize prompt, run `p10k configure` or edit ~/.p10k.zsh.
export P10K_CONFIG="$DOTFILES/config/zsh/p10k.zsh"
[[ ! -f "$P10K_CONFIG" ]] || source "$P10K_CONFIG"
# Added by LM Studio CLI (lms)
export PATH="$PATH:$HOME/.lmstudio/bin"

View File

@@ -1,5 +1,5 @@
{
"$schema": "https://biomejs.dev/schemas/2.4.4/schema.json",
"$schema": "https://biomejs.dev/schemas/2.3.1/schema.json",
"vcs": {
"enabled": true,
"clientKind": "git",

View File

@@ -0,0 +1,251 @@
# Start AeroSpace at login
start-at-login = false
# Normalizations. See: https://nikitabobko.github.io/AeroSpace/guide#normalization
enable-normalization-flatten-containers = true
enable-normalization-opposite-orientation-for-nested-containers = true
# See: https://nikitabobko.github.io/AeroSpace/guide#layouts
# The 'accordion-padding' specifies the size of accordion padding
# You can set 0 to disable the padding feature
accordion-padding = 10
# Possible values: tiles|accordion
default-root-container-layout = 'tiles'
# Possible values: horizontal|vertical|auto
# 'auto' means: wide monitor (anything wider than high) gets horizontal orientation,
# tall monitor (anything higher than wide) gets vertical orientation
default-root-container-orientation = 'auto'
# Mouse follows focus when focused monitor changes
# Drop it from your config, if you don't like this behavior
# See https://nikitabobko.github.io/AeroSpace/guide#on-focus-changed-callbacks
# See https://nikitabobko.github.io/AeroSpace/commands#move-mouse
# Fallback value (if you omit the key): on-focused-monitor-changed = []
on-focused-monitor-changed = ['move-mouse monitor-lazy-center']
# You can effectively turn off macOS "Hide application" (cmd-h) feature by toggling this flag
# Useful if you don't use this macOS feature, but accidentally hit cmd-h or cmd-alt-h key
# Also see: https://nikitabobko.github.io/AeroSpace/goodness#disable-hide-app
automatically-unhide-macos-hidden-apps = true
# [[on-window-detected]]
# if.app-id = 'com.apple.systempreferences'
# if.app-name-regex-substring = 'settings'
# if.window-title-regex-substring = 'substring'
# if.workspace = 'workspace-name'
# if.during-aerospace-startup = true
# check-further-callbacks = true
# run = ['layout floating', 'move-node-to-workspace S'] # The callback itself
[[on-window-detected]]
if.app-name-regex-substring = 'settings' # All settings
run = ['layout floating']
[[on-window-detected]]
if.app-id = 'com.apple.systempreferences' # macOS System Preferences
run = ['layout floating']
[[on-window-detected]]
if.app-id = 'com.1password.1password' # 1Password
run = ['layout floating']
[[on-window-detected]]
if.app-id = 'org.ferdium.ferdium-app' # Ferdium, has WhatsApp etc.
run = ['layout floating']
[[on-window-detected]]
if.app-id = 'com.jetbrains.PhpStorm' # PhpStorm
run = ['layout floating']
[[on-window-detected]]
if.app-id = 'com.apple.finder' # Finder
run = ['layout floating']
[[on-window-detected]]
if.app-id = 'com.apple.Preview' # Preview
run = ['layout floating']
[[on-window-detected]]
if.app-id = 'com.apple.mail' # Mail
run = ['layout floating']
[[on-window-detected]]
if.app-id = 'com.DanPristupov.Fork' # Fork
run = ['layout floating']
[[on-window-detected]]
if.app-id = 'com.flexibits.fantastical2.mac' # Fantastical
run = ['layout floating']
[[on-window-detected]]
if.app-id = 'org.whispersystems.signal-desktop' # Signal
run = ['layout floating']
[[on-window-detected]]
if.app-id = 'com.tidal.desktop' # TIDAL
run = ['layout floating', 'move-node-to-workspace 2'] # Float and move to workspace 2
[[on-window-detected]]
if.app-id = 'com.apple.TV' # Apple TV app
run = ['layout floating']
[[on-window-detected]]
if.app-id = 'com.setapp.DesktopClient' # Setapp
run = ['layout floating']
[[on-window-detected]]
if.app-id = 'com.electron.dockerdesktop' # Docker Desktop
run = ['layout floating']
[[on-window-detected]]
if.app-id = 'com.tinyspeck.slackmacgap' # Slack
run = ['layout floating']
[[on-window-detected]]
if.app-id = 'md.obsidia' # Obsidian
run = ['layout floating']
[[on-window-detected]]
if.app-id = 'com.todoist.mac.Todoist' # Todoist
run = ['layout floating']
[[on-window-detected]]
if.app-id = 'com.apple.backup.launcher' # TimeMachine
run = ['layout floating']
[[on-window-detected]]
if.app-id = 'com.philipyoungg.session-setapp' # Session app (Setapp)
run = ['layout floating']
[[on-window-detected]]
if.app-id = 'com.microsoft.rdc.macos' # Remote Desktop
run = ['layout floating']
# Possible values: (qwerty|dvorak)
# See https://nikitabobko.github.io/AeroSpace/guide#key-mapping
[key-mapping]
preset = 'qwerty'
# Gaps between windows (inner-*) and between monitor edges (outer-*).
# Possible values:
# - Constant: gaps.outer.top = 8
# - Per monitor: gaps.outer.top = [{ monitor.main = 16 }, { monitor."some-pattern" = 32 }, 24]
# In this example, 24 is a default value when there is no match.
# Monitor pattern is the same as for 'workspace-to-monitor-force-assignment'.
# See: https://nikitabobko.github.io/AeroSpace/guide#assign-workspaces-to-monitors
[gaps]
inner.horizontal = 5
inner.vertical = 5
outer.top = [{ monitor.'^built-in retina display$' = 0 }, 0]
outer.right = 0
outer.bottom = 0
outer.left = 0
# 'main' binding mode declaration
# See: https://nikitabobko.github.io/AeroSpace/guide#binding-modes
# 'main' binding mode must be always presented
# Fallback value (if you omit the key): mode.main.binding = {}
[mode.main.binding]
cmd-h = [] # Disable "hide application"
cmd-alt-h = [] # Disable "hide others"
# All possible keys:
# - Letters. a, b, c, ..., z
# - Numbers. 0, 1, 2, ..., 9
# - Keypad numbers. keypad0, keypad1, keypad2, ..., keypad9
# - F-keys. f1, f2, ..., f20
# - Special keys. minus, equal, period, comma, slash, backslash, quote, semicolon, backtick,
# leftSquareBracket, rightSquareBracket, space, enter, esc, backspace, tab
# - Keypad special. keypadClear, keypadDecimalMark, keypadDivide, keypadEnter, keypadEqual,
# keypadMinus, keypadMultiply, keypadPlus
# - Arrows. left, down, up, right
# All possible modifiers: cmd, alt, ctrl, shift
# All possible commands: https://nikitabobko.github.io/AeroSpace/commands
# See: https://nikitabobko.github.io/AeroSpace/commands#exec-and-forget
# You can uncomment the following lines to open up terminal with alt + enter shortcut (like in i3)
# alt-enter = '''exec-and-forget osascript -e '
# tell application "Terminal"
# do script
# activate
# end tell'
# '''
# alt-cmd-shift-f = 'fullscreen'
# alt-shift-f = 'layout floating'
# alt-shift-tab = 'move-workspace-to-monitor --wrap-around next'
# See: https://nikitabobko.github.io/AeroSpace/commands#focus
alt-h = 'focus left'
alt-j = 'focus down'
alt-k = 'focus up'
alt-l = 'focus right'
# See: https://nikitabobko.github.io/AeroSpace/commands#workspace
alt-shift-1 = 'workspace 1' # Main
alt-shift-2 = 'workspace 2' # Media
ctrl-shift-1 = 'move-node-to-workspace 1' # Move node to Main
ctrl-shift-2 = 'move-node-to-workspace 2' # Move node to Media
alt-shift-tab = 'workspace-back-and-forth' # Switch between workspaces
ctrl-shift-tab = 'move-workspace-to-monitor --wrap-around prev'
# See: https://nikitabobko.github.io/AeroSpace/commands#mode
# See: https://nikitabobko.github.io/AeroSpace/guide#binding-modes
alt-a = 'mode apps'
alt-s = 'mode service'
alt-m = 'mode move'
# ╭──────────────────────────────────────────────────────────╮
# │ alt-m │
# ╰──────────────────────────────────────────────────────────╯
[mode.move.binding]
esc = ['reload-config', 'mode main']
# See: https://nikitabobko.github.io/AeroSpace/commands#move-node-to-workspace
1 = ['move-node-to-workspace 1 --focus-follows-window']
2 = ['move-node-to-workspace 2 --focus-follows-window']
# See: https://nikitabobko.github.io/AeroSpace/commands#move
h = 'move left'
j = 'move down'
k = 'move up'
l = 'move right'
# See: https://nikitabobko.github.io/AeroSpace/commands#join-with
shift-h = 'join-with left'
shift-j = 'join-with down'
shift-k = 'join-with up'
shift-l = 'join-with right'
# https://nikitabobko.github.io/AeroSpace/commands#resize
ctrl-h = 'resize smart -70'
ctrl-l = 'resize smart +70'
shift-left = 'resize smart +70'
shift-right = 'resize smart -70'
# https://nikitabobko.github.io/AeroSpace/commands#flatten-workspace-tree
r = ['flatten-workspace-tree', 'mode main'] # reset layout
# ╭──────────────────────────────────────────────────────────╮
# │ alt-a │
# ╰──────────────────────────────────────────────────────────╯
[mode.apps.binding]
esc = ['reload-config', 'mode main']
b = ['exec-and-forget open -a /Applications/Brave Browser.app', 'mode main'] # Browser
c = ['exec-and-forget open -a /Applications/Ferdium.app', 'mode main'] # Chat
g = ['exec-and-forget open -a /Applications/Ghostty.app', 'mode main'] # Ghostty
o = ['exec-and-forget open -a /Applications/Obsidian.app', 'mode main'] # Obsidian
s = ['exec-and-forget open -a /Applications/Slack.app', 'mode main'] # Slack
t = ['exec-and-forget open -a /Applications/TIDAL.app', 'mode main'] # Tidal
w = ['exec-and-forget open -a /Applications/WezTerm.app', 'mode main'] # WezTerm
# ╭──────────────────────────────────────────────────────────╮
# │ alt-s │
# ╰──────────────────────────────────────────────────────────╯
[mode.service.binding]
esc = ['reload-config', 'mode main'] # reload config
r = ['flatten-workspace-tree', 'mode main'] # reset layout
# See: https://nikitabobko.github.io/AeroSpace/commands#layout
f = ['layout floating tiling', 'mode main'] # Toggle between floating and tiling layout
backspace = ['close-all-windows-but-current', 'mode main']

View File

@@ -7,6 +7,8 @@ x-have eza && {
alias ls="eza -h -s=type --git --icons --group-directories-first"
}
alias vim='vim -u "$XDG_CONFIG_HOME/vim/vimrc"'
# Easier navigation: .., ..., ....
alias ..="cd .."
alias ...="cd ../.."

View File

@@ -93,13 +93,13 @@ expand-main:
# Note that not all layouts respond to this command.
increase-main:
mod: mod1
key: ","
key: ','
# Decrease the number of windows in the main pane.
# Note that not all layouts respond to this command.
decrease-main:
mod: mod1
key: "."
key: '.'
# General purpose command for custom layouts.
# Functionality is layout-dependent.

15
config/aqua/aqua.yaml Normal file
View File

@@ -0,0 +1,15 @@
---
# yaml-language-server: $schema=https://raw.githubusercontent.com/aquaproj/aqua/main/json-schema/aqua-yaml.json
# aqua - Declarative CLI Version Manager
# https://aquaproj.github.io/
# checksum:
# enabled: true
# require_checksum: true
# supported_envs:
# - all
registries:
- type: standard
ref: v4.346.0 # renovate: depName=aquaproj/aqua-registry
packages:
- name: cli/cli
version: 'v2.69.0'

5
config/asdf/asdfrc Normal file
View File

@@ -0,0 +1,5 @@
# See the docs for explanations: https://asdf-vm.com/manage/configuration.html
legacy_version_file=yes
use_release_candidates=no
concurrency=auto

1
config/asdf/gem-packages Normal file
View File

@@ -0,0 +1 @@
bundler

View File

@@ -0,0 +1,20 @@
1password-cli https://github.com/NeoHsu/asdf-1password-cli.git f5d5aab
age https://github.com/threkk/asdf-age.git 396bdf6
asdf-plugin-manager https://github.com/asdf-community/asdf-plugin-manager.git b5862c1
direnv https://github.com/asdf-community/asdf-direnv.git 6ff3dbe
dotenv-linter https://github.com/wesleimp/asdf-dotenv-linter.git 1369f53
editorconfig-checker https://github.com/gabitchov/asdf-editorconfig-checker.git 585c1d5
fd https://gitlab.com/wt0f/asdf-fd.git 17d56e0
github-cli https://github.com/bartlomiejdanek/asdf-github-cli.git e0605b7
golang https://github.com/asdf-community/asdf-golang.git e2527a3
hadolint https://github.com/devlincashman/asdf-hadolint.git c8eb88b
kubectl https://github.com/asdf-community/asdf-kubectl.git 2fb3b57
pre-commit https://github.com/jonathanmorley/asdf-pre-commit.git 26bfc42
ripgrep https://gitlab.com/wt0f/asdf-ripgrep.git e836665
rust https://github.com/code-lever/asdf-rust.git 95acf4f
shellcheck https://github.com/luizm/asdf-shellcheck.git 66200ff
shfmt https://github.com/luizm/asdf-shfmt.git a42c5ff
terragrunt https://github.com/ohmer/asdf-terragrunt.git 29f2935
tf-summarize https://github.com/adamcrews/asdf-tf-summarize.git 880ad26
yamllint https://github.com/ericcornelissen/asdf-yamllint.git e4cfb17
yq https://github.com/sudermanjr/asdf-yq.git 772992f

12
config/direnv/direnv.toml Normal file
View File

@@ -0,0 +1,12 @@
[global]
disable_stdin = false
load_dotenv = true
hide_env_diff = false
[whitelist]
prefix = [
"~/Code/"
]
exact = [
"~/.dotfiles/.envrc"
]

View File

@@ -0,0 +1,6 @@
### Do not edit. This was autogenerated by 'asdf direnv setup' ###
# shellcheck shell=bash
use_asdf()
{
source_env "$(asdf direnv envrc "$@")"
}

View File

@@ -4,15 +4,15 @@
# Set XDG directories if not already set
# https://specifications.freedesktop.org/basedir-spec/basedir-spec-latest.html
[ -z "${XDG_CONFIG_HOME:-}" ] && export XDG_CONFIG_HOME="$HOME/.config"
[ -z "${XDG_DATA_HOME:-}" ] && export XDG_DATA_HOME="$HOME/.local/share"
[ -z "${XDG_CACHE_HOME:-}" ] && export XDG_CACHE_HOME="$HOME/.cache"
[ -z "${XDG_STATE_HOME:-}" ] && export XDG_STATE_HOME="$HOME/.local/state"
[ -z "${XDG_BIN_HOME:-}" ] && export XDG_BIN_HOME="$HOME/.local/bin"
[ -z "${XDG_RUNTIME_DIR:-}" ] && export XDG_RUNTIME_DIR="$HOME/.local/run"
[ -z "$XDG_CONFIG_HOME" ] && export XDG_CONFIG_HOME="$HOME/.config"
[ -z "$XDG_DATA_HOME" ] && export XDG_DATA_HOME="$HOME/.local/share"
[ -z "$XDG_CACHE_HOME" ] && export XDG_CACHE_HOME="$HOME/.cache"
[ -z "$XDG_STATE_HOME" ] && export XDG_STATE_HOME="$HOME/.local/state"
[ -z "$XDG_BIN_HOME" ] && export XDG_BIN_HOME="$HOME/.local/bin"
[ -z "$XDG_RUNTIME_DIR" ] && export XDG_RUNTIME_DIR="$HOME/.local/run"
# if DOTFILES is not set, set it to the default location
[ -z "${DOTFILES:-}" ] && export DOTFILES="$HOME/.dotfiles"
[ -z "$DOTFILES" ] && export DOTFILES="$HOME/.dotfiles"
export PATH="$XDG_BIN_HOME:$DOTFILES/local/bin:$XDG_DATA_HOME/bob/nvim-bin:$XDG_DATA_HOME/cargo/bin:/opt/homebrew/bin:/usr/local/bin:$PATH"
@@ -150,7 +150,6 @@ commit()
git commit -a -m "$commitMessage"
}
# Run Laravel scheduler in a loop
scheduler()
{
while :; do
@@ -283,8 +282,7 @@ export LESSHISTFILE="$XDG_STATE_HOME"/less/history
export MANPAGER="less -X"
# Always enable colored `grep` output
# Note: GREP_OPTIONS is deprecated since GNU grep 2.21
# Color is handled via alias in config/alias
export GREP_OPTIONS="--color=auto"
# check the window size after each command and, if necessary,
# update the values of LINES and COLUMNS.
@@ -350,6 +348,12 @@ export COMPOSER_HOME="$XDG_STATE_HOME/composer"
export COMPOSER_BIN="$COMPOSER_HOME/vendor/bin"
export PATH="$COMPOSER_BIN:$PATH"
# direnv, https://direnv.net/
# https://direnv.net/docs/hook.html
# Set the hook to show the direnv message in a different color
# export DIRENV_LOG_FORMAT=$'\033[2mdirenv: %s\033[0m'
export DIRENV_LOG_FORMAT=
# docker, https://docs.docker.com/engine/reference/commandline/cli/
msg "Setting up Docker configuration"
export DOCKER_CONFIG="${XDG_CONFIG_HOME}/docker"
@@ -406,6 +410,11 @@ x-have pyenv && eval "$(pyenv init -)"
msg "Setting up Rust/Cargo configuration"
export RUST_WITHOUT=rust-docs
# screen
# https://www.gnu.org/software/screen/manual/screen.html
msg "Setting up screen configuration"
export SCREENRC="$XDG_CONFIG_HOME/misc/screenrc"
# sonarlint
# https://www.sonarlint.org/
msg "Setting up Sonarlint configuration"
@@ -433,24 +442,23 @@ export ZSH_TMUX_UNICODE=true
export ZSH_TMUX_AUTOQUIT=false
export ZSH_TMUX_DEFAULT_SESSION_NAME=main
# tms, https://github.com/jrmoulton/tmux-sessionizer
export TMS_CONFIG_FILE="${XDG_CONFIG_HOME}/tms/config.toml"
# wakatime, https://github.com/wakatime/wakatime-cli
msg "Setting up Wakatime configuration"
export WAKATIME_HOME="$XDG_STATE_HOME/wakatime"
x-dc "$WAKATIME_HOME"
# LM Studio CLI
msg "Setting up LM Studio configuration"
export PATH="$PATH:$HOME/.lmstudio/bin"
# Misc
msg "Setting up miscellaneous configuration"
export ZSHZ_DATA="$XDG_STATE_HOME/z"
export CHEAT_USE_FZF=true
export SQLITE_HISTORY="${XDG_CACHE_HOME}/sqlite_history"
if [ -f "$XDG_CONFIG_HOME/exports-secret" ]; then source "$XDG_CONFIG_HOME/exports-secret"; fi
if [ -f "$XDG_CONFIG_HOME/exports-local" ]; then source "$XDG_CONFIG_HOME/exports-local"; fi
[ -f "$XDG_CONFIG_HOME/exports-secret" ] && source "$XDG_CONFIG_HOME/exports-secret"
[ -f "$XDG_CONFIG_HOME/exports-local" ] && source "$XDG_CONFIG_HOME/exports-local"
# shellcheck source=./exports-lakka
if [ -f "$XDG_CONFIG_HOME/exports-$(hostname)" ]; then source "$XDG_CONFIG_HOME/exports-$(hostname)"; fi
[ -f "$XDG_CONFIG_HOME/exports-$(hostname)" ] && source "$XDG_CONFIG_HOME/exports-$(hostname)"
# shellcheck source=./exports-lakka-secret
if [ -f "$XDG_CONFIG_HOME/exports-$(hostname)-secret" ]; then source "$XDG_CONFIG_HOME/exports-$(hostname)-secret"; fi
[ -f "$XDG_CONFIG_HOME/exports-$(hostname)-secret" ] && source "$XDG_CONFIG_HOME/exports-$(hostname)-secret"

View File

@@ -8,6 +8,7 @@ fi
export PATH="$HOME/.local/go/bin:$PATH"
alias logrotate='/usr/sbin/logrotate -s "$HOME/logs/state"'
alias nano='nano -wS -$'
alias gpg=gpg2
ACME_PATH="$HOME/.acme.sh"

View File

@@ -0,0 +1 @@
/Applications/OrbStack.app/Contents/MacOS/../Resources/completions/fish/kubectl.fish

View File

@@ -0,0 +1 @@
/Applications/OrbStack.app/Contents/MacOS/../Resources/completions/fish/orbctl.fish

View File

@@ -2,21 +2,21 @@
# Place in ~/.config/fish/completions/phpenv.fish
# Complete main commands
complete -c phpenv -f -n __fish_use_subcommand -a install -d "Install a PHP version"
complete -c phpenv -f -n __fish_use_subcommand -a uninstall -d "Uninstall a PHP version"
complete -c phpenv -f -n __fish_use_subcommand -a use -d "Use PHP version for current shell"
complete -c phpenv -f -n __fish_use_subcommand -a local -d "Set PHP version for current project"
complete -c phpenv -f -n __fish_use_subcommand -a global -d "Set global PHP version"
complete -c phpenv -f -n __fish_use_subcommand -a list -d "List installed PHP versions"
complete -c phpenv -f -n __fish_use_subcommand -a ls -d "List installed PHP versions"
complete -c phpenv -f -n __fish_use_subcommand -a current -d "Show current PHP version"
complete -c phpenv -f -n __fish_use_subcommand -a which -d "Show path to PHP binary"
complete -c phpenv -f -n __fish_use_subcommand -a versions -d "Show all available versions"
complete -c phpenv -f -n __fish_use_subcommand -a doctor -d "Check phpenv installation"
complete -c phpenv -f -n __fish_use_subcommand -a config -d "Manage configuration"
complete -c phpenv -f -n __fish_use_subcommand -a extensions -d "Manage PHP extensions"
complete -c phpenv -f -n __fish_use_subcommand -a ext -d "Manage PHP extensions"
complete -c phpenv -f -n __fish_use_subcommand -a help -d "Show help"
complete -c phpenv -f -n "__fish_use_subcommand" -a "install" -d "Install a PHP version"
complete -c phpenv -f -n "__fish_use_subcommand" -a "uninstall" -d "Uninstall a PHP version"
complete -c phpenv -f -n "__fish_use_subcommand" -a "use" -d "Use PHP version for current shell"
complete -c phpenv -f -n "__fish_use_subcommand" -a "local" -d "Set PHP version for current project"
complete -c phpenv -f -n "__fish_use_subcommand" -a "global" -d "Set global PHP version"
complete -c phpenv -f -n "__fish_use_subcommand" -a "list" -d "List installed PHP versions"
complete -c phpenv -f -n "__fish_use_subcommand" -a "ls" -d "List installed PHP versions"
complete -c phpenv -f -n "__fish_use_subcommand" -a "current" -d "Show current PHP version"
complete -c phpenv -f -n "__fish_use_subcommand" -a "which" -d "Show path to PHP binary"
complete -c phpenv -f -n "__fish_use_subcommand" -a "versions" -d "Show all available versions"
complete -c phpenv -f -n "__fish_use_subcommand" -a "doctor" -d "Check phpenv installation"
complete -c phpenv -f -n "__fish_use_subcommand" -a "config" -d "Manage configuration"
complete -c phpenv -f -n "__fish_use_subcommand" -a "extensions" -d "Manage PHP extensions"
complete -c phpenv -f -n "__fish_use_subcommand" -a "ext" -d "Manage PHP extensions"
complete -c phpenv -f -n "__fish_use_subcommand" -a "help" -d "Show help"
# Helper functions for completions
function __phpenv_complete_installed_versions
@@ -26,13 +26,13 @@ end
function __phpenv_complete_available_versions
# Try to get dynamic versions first
if command -q curl -a command -q jq; and functions -q __phpenv_parse_version_field
echo latest
echo nightly
echo "latest"
echo "nightly"
echo "5.x"
echo "7.x"
echo "8.x"
__phpenv_parse_version_field latest "8.4"
__phpenv_parse_version_field nightly "8.5"
__phpenv_parse_version_field "latest" "8.4"
__phpenv_parse_version_field "nightly" "8.5"
__phpenv_parse_version_field "5.x" "5.6"
__phpenv_parse_version_field "7.x" "7.4"
__phpenv_parse_version_field "8.x" "8.4"
@@ -64,18 +64,18 @@ complete -c phpenv -f -n "__fish_seen_subcommand_from uninstall use local global
-a "(__phpenv_complete_installed_versions)" -d "Installed PHP version"
# Add system option for use command
complete -c phpenv -f -n "__fish_seen_subcommand_from use" -a system -d "Use system PHP"
complete -c phpenv -f -n "__fish_seen_subcommand_from use" -a "system" -d "Use system PHP"
# Complete binaries for which command
complete -c phpenv -f -n "__fish_seen_subcommand_from which" -a "(__phpenv_complete_binaries)" -d "PHP binary"
# Complete config subcommands
complete -c phpenv -f -n "__fish_seen_subcommand_from config; and not __fish_seen_subcommand_from get set list" \
-a get -d "Get configuration value"
-a "get" -d "Get configuration value"
complete -c phpenv -f -n "__fish_seen_subcommand_from config; and not __fish_seen_subcommand_from get set list" \
-a set -d "Set configuration value"
-a "set" -d "Set configuration value"
complete -c phpenv -f -n "__fish_seen_subcommand_from config; and not __fish_seen_subcommand_from get set list" \
-a list -d "List all configuration"
-a "list" -d "List all configuration"
# Complete config keys
complete -c phpenv -f -n "__fish_seen_subcommand_from config; and __fish_seen_subcommand_from get set" \
@@ -91,27 +91,27 @@ complete -c phpenv -f \
complete -c phpenv -f \
-n "__fish_seen_subcommand_from extensions ext" \
-n "not __fish_seen_subcommand_from install uninstall remove list ls available" \
-a install -d "Install PHP extension"
-a "install" -d "Install PHP extension"
complete -c phpenv -f \
-n "__fish_seen_subcommand_from extensions ext" \
-n "not __fish_seen_subcommand_from install uninstall remove list ls available" \
-a uninstall -d "Uninstall PHP extension"
-a "uninstall" -d "Uninstall PHP extension"
complete -c phpenv -f \
-n "__fish_seen_subcommand_from extensions ext" \
-n "not __fish_seen_subcommand_from install uninstall remove list ls available" \
-a remove -d "Remove PHP extension"
-a "remove" -d "Remove PHP extension"
complete -c phpenv -f \
-n "__fish_seen_subcommand_from extensions ext" \
-n "not __fish_seen_subcommand_from install uninstall remove list ls available" \
-a list -d "List installed extensions"
-a "list" -d "List installed extensions"
complete -c phpenv -f \
-n "__fish_seen_subcommand_from extensions ext" \
-n "not __fish_seen_subcommand_from install uninstall remove list ls available" \
-a ls -d "List installed extensions"
-a "ls" -d "List installed extensions"
complete -c phpenv -f \
-n "__fish_seen_subcommand_from extensions ext" \
-n "not __fish_seen_subcommand_from install uninstall remove list ls available" \
-a available -d "Show available extensions"
-a "available" -d "Show available extensions"
# Complete extension names
complete -c phpenv -f \

View File

@@ -23,7 +23,7 @@ if not set -q PHPENV_AUTO_SWITCH
end
if not set -q PHPENV_DEFAULT_EXTENSIONS
set -g PHPENV_DEFAULT_EXTENSIONS opcache
set -g PHPENV_DEFAULT_EXTENSIONS "opcache"
end
# Initialize PATH on shell startup if global version is set (less aggressive)

View File

@@ -1 +0,0 @@
source "/home/ivuorinen/.local/share/cargo/env.fish"

View File

@@ -21,7 +21,6 @@ if status is-interactive
source "$HOME/.config/op/plugins.sh"
# version manager initializers
type -q mise; and source (mise activate fish|psub)
type -q rbenv; and source (rbenv init -|psub)
type -q pyenv; and source (pyenv init -|psub)
type -q pyenv; and source (pyenv virtualenv-init -|psub)

View File

@@ -17,9 +17,6 @@ set -q HOSTNAME; or set -x HOSTNAME (hostname -s)
# Add local bin to path
fish_add_path "$XDG_BIN_HOME"
# Add mise shims to path
fish_add_path "$XDG_DATA_HOME/mise/shims"
# Add cargo bin to path
fish_add_path "$XDG_SHARE_HOME/cargo/bin"

View File

@@ -7,67 +7,65 @@ To be used with a companion fish function like this:
"""
from __future__ import print_function
import json
import os
import signal
import subprocess
import sys
import traceback
BASH = "bash"
BASH = 'bash'
FISH_READONLY = [
"PWD",
"SHLVL",
"history",
"pipestatus",
"status",
"version",
"FISH_VERSION",
"fish_pid",
"hostname",
"_",
"fish_private_mode",
'PWD', 'SHLVL', 'history', 'pipestatus', 'status', 'version',
'FISH_VERSION', 'fish_pid', 'hostname', '_', 'fish_private_mode'
]
IGNORED = ["PS1", "XPC_SERVICE_NAME"]
IGNORED = [
'PS1', 'XPC_SERVICE_NAME'
]
def ignored(name):
if name == "PWD": # this is read only, but has special handling
if name == 'PWD': # this is read only, but has special handling
return False
# ignore other read only variables
if name in FISH_READONLY:
return True
if name in IGNORED or name.startswith("BASH_FUNC"):
return True
return name.startswith("%")
if name.startswith('%'):
return True
return False
def escape(string):
# use json.dumps to reliably escape quotes and backslashes
return json.dumps(string).replace(r"$", r"\$")
return json.dumps(string).replace(r'$', r'\$')
def escape_identifier(word):
return escape(word.replace("?", "\\?"))
return escape(word.replace('?', '\\?'))
def comment(string):
return "\n".join(["# " + line for line in string.split("\n")])
return '\n'.join(['# ' + line for line in string.split('\n')])
def gen_script():
# Use the following instead of /usr/bin/env to read environment so we can
# deal with multi-line environment variables (and other odd cases).
env_reader = f"{sys.executable} -c 'import os,json; print(json.dumps({{k:v for k,v in os.environ.items()}}))'"
args = [BASH, "-c", env_reader]
env_reader = "%s -c 'import os,json; print(json.dumps({k:v for k,v in os.environ.items()}))'" % (sys.executable)
args = [BASH, '-c', env_reader]
output = subprocess.check_output(args, universal_newlines=True)
old_env = output.strip()
pipe_r, pipe_w = os.pipe()
os.set_inheritable(pipe_w, True)
command = f"eval $1 && ({env_reader}; alias) >&{pipe_w}"
args = [BASH, "-c", command, "bass", " ".join(sys.argv[1:])]
if sys.version_info >= (3, 4):
os.set_inheritable(pipe_w, True)
command = 'eval $1 && ({}; alias) >&{}'.format(
env_reader,
pipe_w
)
args = [BASH, '-c', command, 'bass', ' '.join(sys.argv[1:])]
p = subprocess.Popen(args, universal_newlines=True, close_fds=False)
os.close(pipe_w)
with os.fdopen(pipe_r) as f:
@@ -75,7 +73,9 @@ def gen_script():
alias_str = f.read()
if p.wait() != 0:
raise subprocess.CalledProcessError(
returncode=p.returncode, cmd=" ".join(sys.argv[1:]), output=new_env + alias_str
returncode=p.returncode,
cmd=' '.join(sys.argv[1:]),
output=new_env + alias_str
)
new_env = new_env.strip()
@@ -89,41 +89,41 @@ def gen_script():
continue
v1 = old_env.get(k)
if not v1:
script_lines.append(comment(f"adding {k}={v}"))
script_lines.append(comment('adding %s=%s' % (k, v)))
elif v1 != v:
script_lines.append(comment(f"updating {k}={v1} -> {v}"))
script_lines.append(comment('updating %s=%s -> %s' % (k, v1, v)))
# process special variables
if k == "PWD":
script_lines.append(f"cd {escape(v)}")
if k == 'PWD':
script_lines.append('cd %s' % escape(v))
continue
else:
continue
if k == "PATH": # noqa: SIM108
value = " ".join([escape(directory) for directory in v.split(":")])
if k == 'PATH':
value = ' '.join([escape(directory)
for directory in v.split(':')])
else:
value = escape(v)
script_lines.append(f"set -g -x {k} {value}")
script_lines.append('set -g -x %s %s' % (k, value))
for var in set(old_env.keys()) - set(new_env.keys()):
script_lines.append(comment(f"removing {var}"))
script_lines.append(f"set -e {var}")
script_lines.append(comment('removing %s' % var))
script_lines.append('set -e %s' % var)
script = "\n".join(script_lines)
script = '\n'.join(script_lines)
alias_lines = []
for line in alias_str.splitlines():
_, rest = line.split(None, 1)
k, v = rest.split("=", 1)
alias_lines.append("alias " + escape_identifier(k) + "=" + v)
alias = "\n".join(alias_lines)
alias = '\n'.join(alias_lines)
return script + "\n" + alias
return script + '\n' + alias
script_file = os.fdopen(3, "w")
script_file = os.fdopen(3, 'w')
if not sys.argv[1:]:
print("__bass_usage", file=script_file, end="")
print('__bass_usage', file=script_file, end='')
sys.exit(0)
try:
@@ -131,8 +131,8 @@ try:
except subprocess.CalledProcessError as e:
sys.exit(e.returncode)
except Exception:
print("Bass internal error!", file=sys.stderr)
raise # traceback will output to stderr
print('Bass internal error!', file=sys.stderr)
raise # traceback will output to stderr
except KeyboardInterrupt:
signal.signal(signal.SIGINT, signal.SIG_DFL)
os.kill(os.getpid(), signal.SIGINT)

View File

@@ -8,8 +8,8 @@ function fisher --argument-names cmd --description "A plugin manager for Fish"
echo "fisher, version $fisher_version"
case "" -h --help
echo "Usage: fisher install <plugins...> Install plugins"
echo " fisher remove <plugins...> Remove installed plugins"
echo " fisher uninstall <plugins...> Remove installed plugins (alias)"
echo " fisher remove <plugins...> Remove installed plugins"
echo " fisher uninstall <plugins...> Remove installed plugins (alias)"
echo " fisher update <plugins...> Update installed plugins"
echo " fisher update Update all installed plugins"
echo " fisher list [<regex>] List installed plugins matching regex"
@@ -41,7 +41,7 @@ function fisher --argument-names cmd --description "A plugin manager for Fish"
echo "fisher: \"$fish_plugins\" file not found: \"$cmd\"" >&2 && return 1
end
set arg_plugins $file_plugins
else if test "$cmd" = install && ! set --query old_plugins[1]
else if test "$cmd" = install && ! set --query old_plugins[1]
set --append arg_plugins $file_plugins
end

View File

@@ -103,7 +103,7 @@ end
function __phpenv_find_version_file -a phpenv_filename
set -l phpenv_dir (pwd)
while test "$phpenv_dir" != /
while test "$phpenv_dir" != "/"
if test -f "$phpenv_dir/$phpenv_filename"
echo "$phpenv_dir/$phpenv_filename"
return
@@ -130,13 +130,13 @@ function __phpenv_parse_composer_version
end
set -l phpenv_platform_php (jq -r '.config.platform.php // empty' composer.json 2>/dev/null)
if test $status -eq 0 -a -n "$phpenv_platform_php" -a "$phpenv_platform_php" != null
if test $status -eq 0 -a -n "$phpenv_platform_php" -a "$phpenv_platform_php" != "null"
echo $phpenv_platform_php
return
end
set -l phpenv_require_php (jq -r '.require.php // empty' composer.json 2>/dev/null)
if test $status -eq 0 -a -n "$phpenv_require_php" -a "$phpenv_require_php" != null
if test $status -eq 0 -a -n "$phpenv_require_php" -a "$phpenv_require_php" != "null"
__phpenv_parse_semver_constraint $phpenv_require_php
return
end
@@ -196,7 +196,7 @@ set -g __phpenv_version_cache_time 0
function __phpenv_get_version_info
set -l current_time (date +%s)
set -l cache_duration 300 # 5 minutes
set -l cache_duration 300 # 5 minutes
# Return cached version if still valid
if test -n "$__phpenv_version_cache"
@@ -236,12 +236,12 @@ end
# Check if Ondřej PPA is configured on the system
function __phpenv_has_ondrej_ppa
if test -d /etc/apt/sources.list.d
if grep -rq ondrej/php /etc/apt/sources.list.d/ 2>/dev/null
if grep -rq "ondrej/php" /etc/apt/sources.list.d/ 2>/dev/null
return 0
end
end
if test -f /etc/apt/sources.list
if grep -q ondrej/php /etc/apt/sources.list 2>/dev/null
if grep -q "ondrej/php" /etc/apt/sources.list 2>/dev/null
return 0
end
end
@@ -262,34 +262,34 @@ function __phpenv_get_provider
end
# macOS always uses Homebrew
if test (uname -s) = Darwin
echo homebrew
if test (uname -s) = "Darwin"
echo "homebrew"
return 0
end
# Linux: check for apt with Ondřej PPA first
if test (uname -s) = Linux
if test (uname -s) = "Linux"
if command -q apt-get; and __phpenv_has_ondrej_ppa
echo apt
echo "apt"
return 0
end
# Fall back to Homebrew (Linuxbrew) if available
if command -q brew
echo homebrew
echo "homebrew"
return 0
end
# If apt is available but no PPA yet, still use apt provider
# (it will prompt to add the PPA when needed)
if command -q apt-get
echo apt
echo "apt"
return 0
end
end
# Default fallback
echo homebrew
echo "homebrew"
return 0
end
@@ -319,7 +319,7 @@ function __phpenv_provider_homebrew_ensure_source
end
# Check and add required taps only if missing
set -l required_taps shivammathur/php shivammathur/extensions
set -l required_taps "shivammathur/php" "shivammathur/extensions"
for tap in $required_taps
if not brew tap | grep -qx $tap 2>/dev/null
if not brew tap $tap 2>/dev/null
@@ -343,7 +343,7 @@ function __phpenv_provider_homebrew_list_installed
continue
end
if test "$phpenv_basename" = php
if test "$phpenv_basename" = "php"
set -l phpenv_latest (__phpenv_parse_version_field "latest" "8.4")
set -a phpenv_versions $phpenv_latest
else if echo $phpenv_basename | grep -qE '^php@[0-9]+\.[0-9]+$'
@@ -375,7 +375,7 @@ function __phpenv_provider_homebrew_list_available
continue
end
if test "$phpenv_clean_name" = php
if test "$phpenv_clean_name" = "php"
set -a phpenv_versions "$phpenv_latest_version (latest)"
else if echo $phpenv_clean_name | grep -qE '^php@[0-9]+\.[0-9]+$'
set -l phpenv_version (echo $phpenv_clean_name | sed 's/php@//')
@@ -502,7 +502,7 @@ function __phpenv_provider_homebrew_ext_list -a phpenv_version
for phpenv_ext_dir in $phpenv_cellar_path/*@$phpenv_version
if test -d $phpenv_ext_dir
set -l phpenv_ext_name (basename $phpenv_ext_dir | sed "s/@$phpenv_version//")
if test "$phpenv_ext_name" != php
if test "$phpenv_ext_name" != "php"
echo $phpenv_ext_name
end
end
@@ -574,7 +574,7 @@ function __phpenv_provider_apt_ensure_source
echo ""
read -P "Add ppa:ondrej/php? [y/N] " -l confirm
if test "$confirm" = y -o "$confirm" = Y
if test "$confirm" = "y" -o "$confirm" = "Y"
echo "Adding ppa:ondrej/php..."
if command -q add-apt-repository
if sudo add-apt-repository -y ppa:ondrej/php
@@ -603,7 +603,8 @@ function __phpenv_provider_apt_list_installed
return 1
end
dpkg -l 'php[0-9]*-cli' 2>/dev/null | grep '^ii' | sed -E 's/^ii\s+php([0-9]+\.[0-9]+)-cli.*/\1/' | sort -V | uniq
dpkg -l 'php[0-9]*-cli' 2>/dev/null | grep '^ii' | \
sed -E 's/^ii\s+php([0-9]+\.[0-9]+)-cli.*/\1/' | sort -V | uniq
end
function __phpenv_provider_apt_list_available
@@ -612,7 +613,8 @@ function __phpenv_provider_apt_list_available
return
end
apt-cache search '^php[0-9]+\.[0-9]+-cli$' 2>/dev/null | sed -E 's/^php([0-9]+\.[0-9]+)-cli.*/\1/' | sort -V | uniq
apt-cache search '^php[0-9]+\.[0-9]+-cli$' 2>/dev/null | \
sed -E 's/^php([0-9]+\.[0-9]+)-cli.*/\1/' | sort -V | uniq
end
function __phpenv_provider_apt_get_php_path -a phpenv_version
@@ -642,7 +644,7 @@ function __phpenv_provider_apt_get_php_path -a phpenv_version
set -l temp_link "$target.$fish_pid"
ln -s "$source" "$temp_link" 2>/dev/null
and mv -f "$temp_link" "$target" 2>/dev/null
else if test "$binary" = phar; and test -x "/usr/bin/phar$phpenv_version"
else if test "$binary" = "phar"; and test -x "/usr/bin/phar$phpenv_version"
set -l temp_link "$target.$fish_pid"
ln -s "/usr/bin/phar$phpenv_version" "$temp_link" 2>/dev/null
and mv -f "$temp_link" "$target" 2>/dev/null
@@ -817,7 +819,8 @@ function __phpenv_provider_apt_ext_list -a phpenv_version
# Filter out core packages (cli, common, etc.)
set -l core_packages cli common opcache fpm cgi phpdbg
dpkg -l "php$phpenv_version-*" 2>/dev/null | grep '^ii' | awk '{print $2}' | sed "s/php$phpenv_version-//" | while read ext
dpkg -l "php$phpenv_version-*" 2>/dev/null | grep '^ii' | awk '{print $2}' | \
sed "s/php$phpenv_version-//" | while read ext
# Skip core packages
set -l is_core 0
for core in $core_packages
@@ -834,7 +837,9 @@ end
function __phpenv_provider_apt_ext_available -a phpenv_version
# List available extensions from apt cache
apt-cache search "^php$phpenv_version-" 2>/dev/null | sed "s/php$phpenv_version-//" | awk '{print $1}' | grep -v -E '^(cli|common|fpm|cgi|phpdbg|dev)$' | sort | uniq
apt-cache search "^php$phpenv_version-" 2>/dev/null | \
sed "s/php$phpenv_version-//" | awk '{print $1}' | \
grep -v -E '^(cli|common|fpm|cgi|phpdbg|dev)$' | sort | uniq
end
function __phpenv_provider_apt_get_path_pattern
@@ -974,9 +979,9 @@ end
function __phpenv_resolve_version_alias -a phpenv_version
switch $phpenv_version
case latest
__phpenv_parse_version_field latest "8.4"
__phpenv_parse_version_field "latest" "8.4"
case nightly
__phpenv_parse_version_field nightly "8.5"
__phpenv_parse_version_field "nightly" "8.5"
case '8.x'
__phpenv_parse_version_field "8.x" "8.4"
case '7.x'
@@ -992,7 +997,7 @@ function __phpenv_get_formula_name -a phpenv_version
set -l phpenv_latest_version (__phpenv_parse_version_field "latest" "8.4")
if test "$phpenv_version" = "$phpenv_latest_version"
echo shivammathur/php/php
echo "shivammathur/php/php"
else
echo "shivammathur/php/php@$phpenv_version"
end
@@ -1135,7 +1140,7 @@ function __phpenv_use
set -l phpenv_version $argv[1]
# Handle special case: restore system PHP
if test "$phpenv_version" = system
if test "$phpenv_version" = "system"
__phpenv_restore_system_path
echo "Restored system PHP"
return 0
@@ -1152,7 +1157,7 @@ function __phpenv_use
end
if not __phpenv_is_version_installed $phpenv_version
if test "$(__phpenv_config_get auto-install)" = true
if test "$(__phpenv_config_get auto-install)" = "true"
__phpenv_install $phpenv_version
else
echo "PHP $phpenv_version is not installed. Install with: phpenv install $phpenv_version"
@@ -1174,7 +1179,7 @@ function __phpenv_local -a phpenv_version
return 1
end
echo $phpenv_version >.php-version
echo $phpenv_version > .php-version
echo "Set local PHP version to $phpenv_version"
end
@@ -1267,7 +1272,7 @@ function __phpenv_get_tap_versions
continue
end
if test "$phpenv_clean_name" = php
if test "$phpenv_clean_name" = "php"
set -a phpenv_versions "$phpenv_latest_version (latest)"
else if echo $phpenv_clean_name | grep -qE '^php@[0-9]+\.[0-9]+$'
set -l phpenv_version (echo $phpenv_clean_name | sed 's/php@//')
@@ -1305,7 +1310,7 @@ function __phpenv_doctor
# Show provider information
set -l provider (__phpenv_get_provider)
set -l provider_source auto-detected
set -l provider_source "auto-detected"
if set -q PHPENV_PROVIDER; and test -n "$PHPENV_PROVIDER"
set provider_source "PHPENV_PROVIDER override"
end
@@ -1424,7 +1429,7 @@ function __phpenv_config_get -a phpenv_key
end
end
if test "$argv[2]" = --verbose
if test "$argv[2]" = "--verbose"
if test -n "$phpenv_value"
echo "$phpenv_key = $phpenv_value (from $phpenv_source)"
else
@@ -1576,18 +1581,19 @@ function __phpenv_get_tap_formulas -a tap_name
return 1
end
brew tap-info $tap_name --json 2>/dev/null | jq -r '.[]|(.formula_names[]?)' 2>/dev/null
brew tap-info $tap_name --json 2>/dev/null | \
jq -r '.[]|(.formula_names[]?)' 2>/dev/null
end
function __phpenv_get_available_extensions
__phpenv_get_tap_formulas shivammathur/extensions
__phpenv_get_tap_formulas "shivammathur/extensions"
end
function __phpenv_extension_available -a phpenv_extension phpenv_version
set -l phpenv_available_extensions (__phpenv_get_available_extensions)
if test -z "$phpenv_available_extensions"
return 0 # Assume available if can't check
return 0 # Assume available if can't check
end
for phpenv_ext_formula in $phpenv_available_extensions
@@ -1689,7 +1695,7 @@ function __phpenv_auto_switch --on-variable PWD
end
set -l phpenv_auto_switch (__phpenv_config_get auto-switch)
if test "$phpenv_auto_switch" = false
if test "$phpenv_auto_switch" = "false"
return 0
end
@@ -1712,7 +1718,7 @@ function __phpenv_auto_switch --on-variable PWD
set -g PHPENV_LAST_SWITCH_TIME $phpenv_current_time
else
set -l phpenv_auto_install (__phpenv_config_get auto-install)
if test "$phpenv_auto_install" = true
if test "$phpenv_auto_install" = "true"
echo "Auto-installing PHP $phpenv_new_version..."
if phpenv install "$phpenv_new_version"
set -g PHPENV_LAST_SWITCH_TIME $phpenv_current_time
@@ -1765,7 +1771,7 @@ function __phpenv_help
end
function __phpenv_validate_boolean -a phpenv_value
test "$phpenv_value" = true -o "$phpenv_value" = false
test "$phpenv_value" = "true" -o "$phpenv_value" = "false"
end
function __phpenv_validate_version -a phpenv_version

View File

@@ -58,3 +58,4 @@ fish_pager_color_progress 737994
fish_pager_color_prefix f4b8e4
fish_pager_color_completion c6d0f5
fish_pager_color_description 737994

View File

@@ -58,3 +58,4 @@ fish_pager_color_progress 6e738d
fish_pager_color_prefix f5bde6
fish_pager_color_completion cad3f5
fish_pager_color_description 6e738d

View File

@@ -58,3 +58,4 @@ fish_pager_color_progress 6c7086
fish_pager_color_prefix f5c2e7
fish_pager_color_completion cdd6f4
fish_pager_color_description 6c7086

View File

@@ -0,0 +1,6 @@
[General]
ApplicationUpdateChannel=release
CheckApplicatonUpdates=true
FirmwareUpdateChannel=release
LastFolderUrl=/Users/ivuorinen
ShowHiddenFiles=false

View File

@@ -13,37 +13,32 @@
if [[ $- =~ i ]]; then
# To use custom commands instead of find, override _fzf_compgen_{path,dir}
if ! declare -f _fzf_compgen_path > /dev/null; then
_fzf_compgen_path()
{
if ! declare -f _fzf_compgen_path >/dev/null; then
_fzf_compgen_path() {
echo "$1"
command find -L "$1" \
-name .git -prune -o -name .hg -prune -o -name .svn -prune -o \( -type d -o -type f -o -type l \) \
-a -not -path "$1" -print 2> /dev/null | sed 's@^\./@@'
-a -not -path "$1" -print 2>/dev/null | sed 's@^\./@@'
}
fi
if ! declare -f _fzf_compgen_dir > /dev/null; then
_fzf_compgen_dir()
{
if ! declare -f _fzf_compgen_dir >/dev/null; then
_fzf_compgen_dir() {
command find -L "$1" \
-name .git -prune -o -name .hg -prune -o -name .svn -prune -o -type d \
-a -not -path "$1" -print 2> /dev/null | sed 's@^\./@@'
-a -not -path "$1" -print 2>/dev/null | sed 's@^\./@@'
}
fi
###########################################################
# To redraw line after fzf closes (printf '\e[5n')
bind '"\e[0n": redraw-current-line' 2> /dev/null
bind '"\e[0n": redraw-current-line' 2>/dev/null
__fzf_comprun()
{
__fzf_comprun() {
if [[ "$(type -t _fzf_comprun 2>&1)" = function ]]; then
_fzf_comprun "$@"
elif [[ -n "${TMUX_PANE-}" ]] && {
[[ "${FZF_TMUX:-0}" != 0 ]] || [[ -n "${FZF_TMUX_OPTS-}" ]]
}; then
elif [[ -n "${TMUX_PANE-}" ]] && { [[ "${FZF_TMUX:-0}" != 0 ]] || [[ -n "${FZF_TMUX_OPTS-}" ]]; }; then
shift
fzf-tmux ${FZF_TMUX_OPTS:--d${FZF_TMUX_HEIGHT:-40%}} -- "$@"
else
@@ -52,8 +47,7 @@ if [[ $- =~ i ]]; then
fi
}
__fzf_orig_completion()
{
__fzf_orig_completion() {
local l comp f cmd
while read -r l; do
if [[ "$l" =~ ^(.*\ -F)\ *([^ ]*).*\ ([^ ]*)$ ]]; then
@@ -69,8 +63,7 @@ if [[ $- =~ i ]]; then
done
}
_fzf_opts_completion()
{
_fzf_opts_completion() {
local cur prev opts
COMPREPLY=()
cur="${COMP_WORDS[COMP_CWORD]}"
@@ -119,18 +112,18 @@ if [[ $- =~ i ]]; then
--sync"
case "${prev}" in
--tiebreak)
COMPREPLY=($(compgen -W "length begin end index" -- "$cur"))
return 0
;;
--color)
COMPREPLY=($(compgen -W "dark light 16 bw" -- "$cur"))
return 0
;;
--history)
COMPREPLY=()
return 0
;;
--tiebreak)
COMPREPLY=($(compgen -W "length begin end index" -- "$cur"))
return 0
;;
--color)
COMPREPLY=($(compgen -W "dark light 16 bw" -- "$cur"))
return 0
;;
--history)
COMPREPLY=()
return 0
;;
esac
if [[ "$cur" =~ ^-|\+ ]]; then
@@ -141,8 +134,7 @@ if [[ $- =~ i ]]; then
return 0
}
_fzf_handle_dynamic_completion()
{
_fzf_handle_dynamic_completion() {
local cmd orig_var orig ret orig_cmd orig_complete
cmd="$1"
shift
@@ -150,15 +142,15 @@ if [[ $- =~ i ]]; then
orig_var="_fzf_orig_completion_$cmd"
orig="${!orig_var-}"
orig="${orig##*#}"
if [[ -n "$orig" ]] && type "$orig" > /dev/null 2>&1; then
if [[ -n "$orig" ]] && type "$orig" >/dev/null 2>&1; then
$orig "$@"
elif [[ -n "${_fzf_completion_loader-}" ]]; then
orig_complete=$(complete -p "$orig_cmd" 2> /dev/null)
orig_complete=$(complete -p "$orig_cmd" 2>/dev/null)
_completion_loader "$@"
ret=$?
# _completion_loader may not have updated completion for the command
if [[ "$(complete -p "$orig_cmd" 2> /dev/null)" != "$orig_complete" ]]; then
__fzf_orig_completion < <(complete -p "$orig_cmd" 2> /dev/null)
if [[ "$(complete -p "$orig_cmd" 2>/dev/null)" != "$orig_complete" ]]; then
__fzf_orig_completion < <(complete -p "$orig_cmd" 2>/dev/null)
if [[ "${__fzf_nospace_commands-}" = *" $orig_cmd "* ]]; then
eval "${orig_complete/ -F / -o nospace -F }"
else
@@ -169,8 +161,7 @@ if [[ $- =~ i ]]; then
fi
}
__fzf_generic_path_completion()
{
__fzf_generic_path_completion() {
local cur base dir leftover matches trigger cmd
cmd="${COMP_WORDS[0]}"
if [[ $cmd == \\* ]]; then
@@ -216,8 +207,7 @@ if [[ $- =~ i ]]; then
fi
}
_fzf_complete()
{
_fzf_complete() {
# Split arguments around --
local args rest str_arg i sep
args=("$@")
@@ -241,7 +231,7 @@ if [[ $- =~ i ]]; then
local cur selected trigger cmd post
post="$(caller 0 | awk '{print $2}')_post"
type -t "$post" > /dev/null 2>&1 || post=cat
type -t "$post" >/dev/null 2>&1 || post=cat
cmd="${COMP_WORDS[0]//[^A-Za-z0-9_=]/_}"
trigger=${FZF_COMPLETION_TRIGGER-'**'}
@@ -263,59 +253,50 @@ if [[ $- =~ i ]]; then
fi
}
_fzf_path_completion()
{
_fzf_path_completion() {
__fzf_generic_path_completion _fzf_compgen_path "-m" "" "$@"
}
# Deprecated. No file only completion.
_fzf_file_completion()
{
_fzf_file_completion() {
_fzf_path_completion "$@"
}
_fzf_dir_completion()
{
_fzf_dir_completion() {
__fzf_generic_path_completion _fzf_compgen_dir "" "/" "$@"
}
_fzf_complete_kill()
{
_fzf_complete_kill() {
_fzf_proc_completion "$@"
}
_fzf_proc_completion()
{
_fzf_proc_completion() {
_fzf_complete -m --header-lines=1 --preview 'echo {}' --preview-window down:3:wrap --min-height 15 -- "$@" < <(
command ps -eo user,pid,ppid,start,time,command 2> /dev/null \
|| command ps -eo user,pid,ppid,time,args # For BusyBox
command ps -eo user,pid,ppid,start,time,command 2>/dev/null ||
command ps -eo user,pid,ppid,time,args # For BusyBox
)
}
_fzf_proc_completion_post()
{
_fzf_proc_completion_post() {
awk '{print $2}'
}
_fzf_host_completion()
{
_fzf_host_completion() {
_fzf_complete +m -- "$@" < <(
command cat <(command tail -n +1 ~/.ssh/config ~/.ssh/config.d/* /etc/ssh/ssh_config 2> /dev/null | command grep -i '^\s*host\(name\)\? ' | awk '{for (i = 2; i <= NF; i++) print $1 " " $i}' | command grep -v '[*?%]') \
command cat <(command tail -n +1 ~/.ssh/config ~/.ssh/config.d/* /etc/ssh/ssh_config 2>/dev/null | command grep -i '^\s*host\(name\)\? ' | awk '{for (i = 2; i <= NF; i++) print $1 " " $i}' | command grep -v '[*?%]') \
<(command grep -oE '^[[a-z0-9.,:-]+' ~/.ssh/known_hosts | tr ',' '\n' | tr -d '[' | awk '{ print $1 " " $1 }') \
<(command grep -v '^\s*\(#\|$\)' /etc/hosts | command grep -Fv '0.0.0.0') \
| awk '{if (length($2) > 0) {print $2}}' | sort -u
<(command grep -v '^\s*\(#\|$\)' /etc/hosts | command grep -Fv '0.0.0.0') |
awk '{if (length($2) > 0) {print $2}}' | sort -u
)
}
_fzf_var_completion()
{
_fzf_var_completion() {
_fzf_complete -m -- "$@" < <(
declare -xp | sed -En 's|^declare [^ ]+ ([^=]+).*|\1|p'
)
}
_fzf_alias_completion()
{
_fzf_alias_completion() {
_fzf_complete -m -- "$@" < <(
alias | sed -En 's|^alias ([^=]+).*|\1|p'
)
@@ -340,14 +321,13 @@ if [[ $- =~ i ]]; then
svn tar unzip zip"
# Preserve existing completion
__fzf_orig_completion < <(complete -p $d_cmds $a_cmds 2> /dev/null)
__fzf_orig_completion < <(complete -p $d_cmds $a_cmds 2>/dev/null)
if type _completion_loader > /dev/null 2>&1; then
if type _completion_loader >/dev/null 2>&1; then
_fzf_completion_loader=1
fi
__fzf_defc()
{
__fzf_defc() {
local cmd func opts orig_var orig def
cmd="$1"
func="$2"
@@ -374,23 +354,22 @@ if [[ $- =~ i ]]; then
unset cmd d_cmds a_cmds
_fzf_setup_completion()
{
_fzf_setup_completion() {
local kind fn cmd
kind=$1
fn=_fzf_${1}_completion
if [[ $# -lt 2 ]] || ! type -t "$fn" > /dev/null; then
if [[ $# -lt 2 ]] || ! type -t "$fn" >/dev/null; then
echo "usage: ${FUNCNAME[0]} path|dir|var|alias|host|proc COMMANDS..."
return 1
fi
shift
__fzf_orig_completion < <(complete -p "$@" 2> /dev/null)
__fzf_orig_completion < <(complete -p "$@" 2>/dev/null)
for cmd in "$@"; do
case "$kind" in
dir) __fzf_defc "$cmd" "$fn" "-o nospace -o dirnames" ;;
var) __fzf_defc "$cmd" "$fn" "-o default -o nospace -v" ;;
alias) __fzf_defc "$cmd" "$fn" "-a" ;;
*) __fzf_defc "$cmd" "$fn" "-o default -o bashdefault" ;;
dir) __fzf_defc "$cmd" "$fn" "-o nospace -o dirnames" ;;
var) __fzf_defc "$cmd" "$fn" "-o default -o nospace -v" ;;
alias) __fzf_defc "$cmd" "$fn" "-a" ;;
*) __fzf_defc "$cmd" "$fn" "-o default -o bashdefault" ;;
esac
done
}

View File

@@ -4,7 +4,7 @@
# Auto-completion
# ---------------
# shellcheck source=completion.bash
[[ $- == *i* ]] && source "$HOME/.dotfiles/config/fzf/completion.bash" 2> /dev/null
[[ $- == *i* ]] && source "$HOME/.dotfiles/config/fzf/completion.bash" 2>/dev/null
# Key bindings
# ------------

View File

@@ -13,8 +13,7 @@
# Key bindings
# ------------
__fzf_select__()
{
__fzf_select__() {
local cmd opts
cmd="${FZF_CTRL_T_COMMAND:-"command find -L . -mindepth 1 \\( -path '*/\\.*' -o -fstype 'sysfs' -o -fstype 'devfs' -o -fstype 'devtmpfs' -o -fstype 'proc' \\) -prune \
-o -type f -print \
@@ -22,32 +21,27 @@ __fzf_select__()
-o -type l -print 2> /dev/null | cut -b3-"}"
opts="--height ${FZF_TMUX_HEIGHT:-40%} --bind=ctrl-z:ignore --reverse ${FZF_DEFAULT_OPTS-} ${FZF_CTRL_T_OPTS-} -m"
# shellcheck disable=SC2091 # Intentionally execute output of __fzfcmd
eval "$cmd" | FZF_DEFAULT_OPTS="$opts" $(__fzfcmd) "$@" \
| while read -r item; do
eval "$cmd" | FZF_DEFAULT_OPTS="$opts" $(__fzfcmd) "$@" |
while read -r item; do
printf '%q ' "$item" # escape special chars
done
}
if [[ $- =~ i ]]; then
__fzfcmd()
{
[[ -n "${TMUX_PANE-}" ]] && {
[[ "${FZF_TMUX:-0}" != 0 ]] || [[ -n "${FZF_TMUX_OPTS-}" ]]
} \
&& echo "fzf-tmux ${FZF_TMUX_OPTS:--d${FZF_TMUX_HEIGHT:-40%}} -- " || echo "fzf"
__fzfcmd() {
[[ -n "${TMUX_PANE-}" ]] && { [[ "${FZF_TMUX:-0}" != 0 ]] || [[ -n "${FZF_TMUX_OPTS-}" ]]; } &&
echo "fzf-tmux ${FZF_TMUX_OPTS:--d${FZF_TMUX_HEIGHT:-40%}} -- " || echo "fzf"
}
fzf-file-widget()
{
fzf-file-widget() {
local selected
selected="$(__fzf_select__ "$@")"
READLINE_LINE="${READLINE_LINE:0:$READLINE_POINT}$selected${READLINE_LINE:$READLINE_POINT}"
READLINE_POINT=$((READLINE_POINT + ${#selected}))
}
__fzf_cd__()
{
__fzf_cd__() {
local cmd opts dir
cmd="${FZF_ALT_C_COMMAND:-"command find -L . -mindepth 1 \\( -path '*/\\.*' -o -fstype 'sysfs' -o -fstype 'devfs' -o -fstype 'devtmpfs' -o -fstype 'proc' \\) -prune \
-o -type d -print 2> /dev/null | cut -b3-"}"
@@ -59,17 +53,16 @@ if [[ $- =~ i ]]; then
) && printf 'builtin cd -- %q' "$dir"
}
__fzf_history__()
{
__fzf_history__() {
local output opts script
opts="--height ${FZF_TMUX_HEIGHT:-40%} --bind=ctrl-z:ignore ${FZF_DEFAULT_OPTS-} -n2..,.. --scheme=history --bind=ctrl-r:toggle-sort ${FZF_CTRL_R_OPTS-} +m --read0"
script='BEGIN { getc; $/ = "\n\t"; $HISTCOUNT = $ENV{last_hist} + 1 } s/^[ *]//; print $HISTCOUNT - $. . "\t$_" if !$seen{$_}++'
# shellcheck disable=SC2091 # Intentionally execute output of __fzfcmd
output=$(
set +o pipefail
builtin fc -lnr -2147483648 \
| last_hist=$(HISTTIMEFORMAT='' builtin history 1) perl -n -l0 -e "$script" \
| FZF_DEFAULT_OPTS="$opts" $(__fzfcmd) --query "$READLINE_LINE"
builtin fc -lnr -2147483648 |
last_hist=$(HISTTIMEFORMAT='' builtin history 1) perl -n -l0 -e "$script" |
FZF_DEFAULT_OPTS="$opts" $(__fzfcmd) --query "$READLINE_LINE"
) || return
READLINE_LINE=${output#*$'\t'}
if [[ -z "$READLINE_POINT" ]]; then

View File

@@ -52,4 +52,4 @@ keybindings:
prs: []
repoPaths: {}
pager:
diff: ""
diff: ''

View File

@@ -1,3 +1,3 @@
---
git_protocol: https
version: "1"
version: '1'

View File

@@ -1,5 +1,6 @@
---
github.com:
git_protocol: ssh
users:
ivuorinen:
user: ivuorinen
git_protocol: https
users:
ivuorinen:
user: ivuorinen

15
config/ghostty/config Normal file
View File

@@ -0,0 +1,15 @@
# vim: ft=ghostty
theme = "light:tokyonight-day,dark:tokyonight-storm"
font-family = "JetBrainsMono Nerd Font Mono"
background-blur-radius = 15
background-opacity = 0.95
clipboard-read = allow
clipboard-write = allow
cursor-style = bar
custom-shader-animation = true
gtk-single-instance = true
mouse-hide-while-typing = true
shell-integration-features = true
window-theme = system

View File

@@ -260,6 +260,8 @@ brew "php@8.2", link: true
brew "php@8.3"
# Pins GitHub Actions to full hashes and versions
brew "pinact"
# Execute binaries from Python packages in isolated environments
brew "pipx"
# Python version management
brew "pyenv"
# Migrate pip packages from one Python version to another

54
config/htop/htoprc Normal file
View File

@@ -0,0 +1,54 @@
# Beware! This file is rewritten by htop when settings are changed in the interface.
# The parser is also very primitive, and not human-friendly.
htop_version=3.4.1
config_reader_min_version=3
fields=0 48 17 18 38 39 2 46 47 49 1
hide_kernel_threads=1
hide_userland_threads=0
hide_running_in_container=0
shadow_other_users=0
show_thread_names=0
show_program_path=1
highlight_base_name=0
highlight_deleted_exe=1
shadow_distribution_path_prefix=0
highlight_megabytes=1
highlight_threads=1
highlight_changes=0
highlight_changes_delay_secs=5
find_comm_in_cmdline=1
strip_exe_from_cmdline=1
show_merged_command=0
header_margin=1
screen_tabs=1
detailed_cpu_time=0
cpu_count_from_one=0
show_cpu_usage=1
show_cpu_frequency=0
show_cached_memory=1
update_process_names=0
account_guest_in_cpu_meter=0
color_scheme=0
enable_mouse=1
delay=15
hide_function_bar=0
header_layout=two_50_50
column_meters_0=LeftCPUs2 Memory Swap
column_meter_modes_0=1 1 1
column_meters_1=RightCPUs2 Tasks LoadAverage Uptime
column_meter_modes_1=1 2 2 2
tree_view=0
sort_key=46
tree_sort_key=0
sort_direction=-1
tree_sort_direction=1
tree_view_always_by_pid=0
all_branches_collapsed=0
screen:Main=PID USER PRIORITY NICE M_VIRT M_RESIDENT STATE PERCENT_CPU PERCENT_MEM TIME Command
.sort_key=PERCENT_CPU
.tree_sort_key=PID
.tree_view_always_by_pid=0
.tree_view=0
.sort_direction=-1
.tree_sort_direction=1
.all_branches_collapsed=0

View File

@@ -1,4 +1,4 @@
#!/usr/bin/env bash
#!/bin/env bash
[[ -z "$NVM_DIR" ]] && export NVM_DIR="$HOME/.config/nvm"
[[ -s "$NVM_DIR/nvm.sh" ]] && \. "$NVM_DIR/nvm.sh" # This loads nvm
[ -z "$NVM_DIR" ] && export NVM_DIR="$HOME/.config/nvm"
[ -s "$NVM_DIR/nvm.sh" ] && \. "$NVM_DIR/nvm.sh" # This loads nvm

15
config/misc/screenrc Normal file
View File

@@ -0,0 +1,15 @@
# Disable the startup message
startup_message off
# Set a large scrollback buffer
defscrollback 32000
# Always start `screen` with UTF-8 enabled (`screen -U`)
defutf8 on
# Scroll with mouse wheel (http://stackoverflow.com/a/1125947)
termcapinfo xterm* ti@:te@
# Some settings for screen + vim
term xterm-256color
maptimeout 10

1
config/nano/nanorc Normal file
View File

@@ -0,0 +1 @@
set tabsize 2

18
config/nbrc Executable file
View File

@@ -0,0 +1,18 @@
#!/usr/bin/env bash
###############################################################################
# .nbrc
#
# Configuration file for `nb`, a command line note-taking, bookmarking,
# and knowledge base application with encryption, search, Git-backed syncing,
# and more in a single portable script.
#
# Edit this file manually or manage settings using the `nb settings`
# subcommand. Configuration options are set as environment variables, eg:
# export NB_ENCRYPTION_TOOL=gpg
#
# https://github.com/xwmx/nb
###############################################################################
export NB_DIR="${NB_DIR:-$HOME/.local/state/nb}" # Set by `nb` • Mon May 8 15:25:12 EEST 2023
export NB_COLOR_THEME="${NB_COLOR_THEME:-unicorn}" # Set by `nb` • Mon May 8 15:41:22 EEST 2023

View File

@@ -40,8 +40,7 @@ return {
operators = {},
-- miscs = {}, -- Uncomment to turn off hard-coded styles
},
-- Style of specific lsp hl groups (`:h lsp-highlight`)
lsp_styles = {
lsp_styles = { -- Handles the style of specific lsp hl groups (see `:h lsp-highlight`).
virtual_text = {
errors = { 'italic' },
hints = { 'italic' },
@@ -73,8 +72,7 @@ return {
enabled = true,
indentscope_color = '',
},
-- More integrations:
-- github.com/catppuccin/nvim#integrations
-- For more plugins integrations please scroll down (https://github.com/catppuccin/nvim#integrations)
},
}
@@ -117,8 +115,7 @@ return {
{
'dmtrKovalenko/fff.nvim',
build = function()
-- Downloads prebuild binary or uses rustup
-- toolchain to build from source
-- this will download prebuild binary or try to use existing rustup toolchain to build from source
-- (if you are using lazy you can use gb for rebuilding a plugin if needed)
require('fff.download').download_or_build_binary()
end,
@@ -127,8 +124,7 @@ return {
opts = { -- (optional)
debug = {
enabled = true, -- we expect your collaboration at least during the beta
-- Share scores to help optimize scoring
show_scores = true,
show_scores = true, -- to help us optimize the scoring system, feel free to share your scores!
},
},
-- No need to lazy-load with lazy.nvim.

View File

@@ -8,11 +8,8 @@
#
# Smart session manager for the terminal
# https://github.com/joshmedeski/sesh
#:schema https://github.com/joshmedeski/sesh/raw/main/sesh.schema.json
strict_mode = false
dir_length = 2 # Uses last 2 directories: "projects/sesh" instead of just "sesh"
cache = true
# [marker]
# inactivity_threshold = 10 # Seconds before alerts start
@@ -55,7 +52,3 @@ disable_startup_command = true
name = "Downloads"
path = "~/Downloads"
startup_command = "lsa"
[[session]]
name = "Code/ivuorinen"
path = "~/Code/ivuorinen/"

View File

@@ -5,7 +5,7 @@
# shellcheck shell=bash
# Defaults
[[ -z "${DOTFILES:-}" ]] && export DOTFILES="$HOME/.dotfiles"
[ -z "$DOTFILES" ] && export DOTFILES="$HOME/.dotfiles"
DOTFILES_CURRENT_SHELL=$(basename "$SHELL")
export DOTFILES_CURRENT_SHELL
@@ -15,7 +15,7 @@ VERBOSE="${VERBOSE:-0}"
DEBUG="${DEBUG:-0}"
# Enable debugging with DEBUG=1
[[ "${DEBUG:-0}" -eq 1 ]] && set -x
[ "${DEBUG:-0}" -eq 1 ] && set -x
# Detect the current shell
CURRENT_SHELL=$(ps -p $$ -ocomm= | awk -F/ '{print $NF}')
@@ -33,10 +33,9 @@ x-path-prepend()
;;
*)
echo "Unsupported shell: $CURRENT_SHELL"
return 1
exit 1
;;
esac
return 0
}
# Function to set environment variables based on the shell
@@ -53,10 +52,9 @@ x-set-env()
;;
*)
echo "Unsupported shell: $CURRENT_SHELL"
return 1
exit 1
;;
esac
return 0
}
# Explicitly set XDG folders, if not already set
@@ -76,17 +74,16 @@ x-path-prepend "$DOTFILES/local/bin"
x-path-prepend "$XDG_BIN_HOME"
# Custom completion paths
[[ -z "${ZSH_CUSTOM_COMPLETION_PATH:-}" ]] && export ZSH_CUSTOM_COMPLETION_PATH="$XDG_CONFIG_HOME/zsh/completion"
[ -z "$ZSH_CUSTOM_COMPLETION_PATH" ] && export ZSH_CUSTOM_COMPLETION_PATH="$XDG_CONFIG_HOME/zsh/completion"
x-dc "$ZSH_CUSTOM_COMPLETION_PATH"
export FPATH="$ZSH_CUSTOM_COMPLETION_PATH:${FPATH:-}"
export FPATH="$ZSH_CUSTOM_COMPLETION_PATH:$FPATH"
if ! declare -f msg > /dev/null; then
# Function to print messages if VERBOSE is enabled
# $1 - message (string)
msg()
{
local message="$1"
[[ "$VERBOSE" -eq 1 ]] && msgr msg "$message"
[ "$VERBOSE" -eq 1 ] && msgr msg "$1"
return 0
}
msg "msg was not defined, defined it now"
@@ -98,8 +95,7 @@ if ! declare -f msg_err > /dev/null; then
# $1 - error message (string)
msg_err()
{
local message="$1"
msgr err "$message" >&2
msgr err "$1" >&2
exit 1
}
fi
@@ -110,8 +106,7 @@ if ! declare -f msg_done > /dev/null; then
# $1 - message (string)
msg_done()
{
local message="$1"
msgr "done" "$message"
msgr "done" "$1"
return 0
}
fi
@@ -122,8 +117,7 @@ if ! declare -f msg_run > /dev/null; then
# $1 - message (string)
msg_run()
{
local message="$1"
msgr run "$message"
msgr run "$1"
return 0
}
fi
@@ -134,8 +128,7 @@ if ! declare -f msg_ok > /dev/null; then
# $1 - message (string)
msg_ok()
{
local message="$1"
msgr ok "$message"
msgr ok "$1"
return 0
}
fi
@@ -150,16 +143,12 @@ if ! declare -f array_diff > /dev/null; then
# Source: https://stackoverflow.com/a/42399479/594940
array_diff()
{
local result_var="$1"
local arr1_name="$2"
local arr2_name="$3"
# shellcheck disable=SC1083,SC2086
eval local ARR1=\(\"\${${arr1_name}[@]}\"\)
eval local ARR1=\(\"\${$2[@]}\"\)
# shellcheck disable=SC1083,SC2086
eval local ARR2=\(\"\${${arr2_name}[@]}\"\)
eval local ARR2=\(\"\${$3[@]}\"\)
local IFS=$'\n'
mapfile -t "$result_var" < <(comm -23 <(echo "${ARR1[*]}" | sort) <(echo "${ARR2[*]}" | sort))
return 0
mapfile -t "$1" < <(comm -23 <(echo "${ARR1[*]}" | sort) <(echo "${ARR2[*]}" | sort))
}
fi

154
config/starship.toml Normal file
View File

@@ -0,0 +1,154 @@
# Get editor completions based on the config schema
"$schema" = 'https://starship.rs/config-schema.json'
format = """
$os\
$directory\
$git_branch\
$git_state\
$git_status\
$fill \
$battery\
$username\
$hostname\
$aws\
$gcloud\
$conda\
$golang\
$nodejs\
$php\
$python\
$package\
$line_break\
$character"""
# Timeout for commands executed by starship (in milliseconds).
command_timeout = 1500
[character]
success_symbol = "[→](bold green)"
error_symbol = "[→](red)"
vimcmd_symbol = "[←](green)"
[aws]
symbol = " "
format = '[$symbol($profile )(\($region\) )(\[$duration\] )]($style)'
[cmd_duration]
disabled = true
[directory]
read_only = " 󰌾"
style = "blue"
before_repo_root_style = "white"
truncation_symbol = "…/"
[docker_context]
symbol = " "
format = '[$symbol$context]($style) '
[fill]
symbol = '·'
style = 'bold black'
[gcloud]
format = '[($symbol)$account(@$domain)(\($region\))]($style) '
[git_branch]
symbol = " "
format = '[$symbol$branch(:$remote_branch)]($style) '
truncation_length = 20
truncation_symbol = '…'
ignore_branches = ['master', 'main']
[git_status]
up_to_date = '✓'
staged = '[++\($count\)](green)'
[git_state]
format = '\([$state( $progress_current/$progress_total)]($style)\) '
style = "bright-black"
[git_metrics]
added_style = 'bold blue'
format = '[+$added]($added_style)/[-$deleted]($deleted_style) '
disabled = false
[golang]
symbol = " "
format = '[$symbol($version )]($style) '
[hostname]
ssh_symbol = " "
ssh_only = false
format = '[$ssh_symbol](bold blue)[$hostname](bold red) '
[lua]
format = '[$symbol($version )]($style)'
[nodejs]
symbol = " "
format = '[$symbol($version )]($style)'
version_format = '${major}.${minor}'
[os]
format = "[$symbol]($style) "
style = "bold blue"
disabled = false
[os.symbols]
Alpaquita = " "
Alpine = " "
Amazon = " "
Android = " "
Arch = " "
Artix = " "
CentOS = " "
Debian = " "
DragonFly = " "
Emscripten = " "
EndeavourOS = " "
Fedora = " "
FreeBSD = " "
Garuda = "󰛓 "
Gentoo = " "
HardenedBSD = "󰞌 "
Illumos = "󰈸 "
Linux = " "
Mabox = " "
Macos = " "
Manjaro = " "
Mariner = " "
MidnightBSD = " "
Mint = " "
NetBSD = " "
NixOS = " "
OpenBSD = "󰈺 "
openSUSE = " "
OracleLinux = "󰌷 "
Pop = " "
Raspbian = " "
Redhat = " "
RedHatEnterprise = " "
Redox = "󰀘 "
Solus = "󰠳 "
SUSE = " "
Ubuntu = " "
Unknown = " "
Windows = "󰍲 "
[package]
symbol = "󰏗 "
format = '[$symbol($version )]($style)'
version_format = '${major}.${minor}'
[php]
format = '[$symbol($version )]($style)'
version_format = '${major}.${minor}'
[python]
symbol = " "
format = "[$virtualenv]($style) "
[username]
format = "[$user]($style) "

81
config/task/taskrc Normal file
View File

@@ -0,0 +1,81 @@
# [Created by task 2.6.2 5/11/2023 09:33:14]
# Taskwarrior program configuration file.
# For more documentation, see https://taskwarrior.org or try 'man task', 'man task-color',
# 'man task-sync' or 'man taskrc'
# Here is an example of entries that use the default, override and blank values
# variable=foo -- By specifying a value, this overrides the default
# variable= -- By specifying no value, this means no default
# #variable=foo -- By commenting out the line, or deleting it, this uses the default
# You can also refence environment variables:
# variable=$HOME/task
# variable=$VALUE
# Use the command 'task show' to see all defaults and overrides
# Files
data.location=$XDG_DATA_HOME/task/
# To use the default location of the XDG directories,
# move this configuration file from ~/.taskrc to ~/.config/task/taskrc and uncomment below
#data.location=$XDG_DATA_HOME/task
#hooks.location=~/.config/task/hooks
# Color theme (uncomment one to use)
#include light-16.theme
#include light-256.theme
#include dark-16.theme
#include dark-256.theme
#include dark-red-256.theme
#include dark-green-256.theme
#include dark-blue-256.theme
#include dark-violets-256.theme
#include dark-yellow-green.theme
#include dark-gray-256.theme
#include dark-gray-blue-256.theme
#include solarized-dark-256.theme
#include solarized-light-256.theme
#include no-color.theme
weekstart=monday
news.version=2.6.0
default.project=Inbox
calendar.details=full
calendar.holidays=sparse
recurrence=on
uda.taskwarrior-tui.keyconfig.quit=q
uda.taskwarrior-tui.keyconfig.refresh=r
uda.taskwarrior-tui.keyconfig.go-to-bottom=G
uda.taskwarrior-tui.keyconfig.go-to-top=g
uda.taskwarrior-tui.keyconfig.down=j
uda.taskwarrior-tui.keyconfig.up=k
uda.taskwarrior-tui.keyconfig.page-down=J
uda.taskwarrior-tui.keyconfig.page-up=K
uda.taskwarrior-tui.keyconfig.delete=x
uda.taskwarrior-tui.keyconfig.done=d
uda.taskwarrior-tui.keyconfig.start-stop=s
uda.taskwarrior-tui.keyconfig.quick-tag=t
uda.taskwarrior-tui.keyconfig.undo=u
uda.taskwarrior-tui.keyconfig.edit=e
uda.taskwarrior-tui.keyconfig.modify=m
uda.taskwarrior-tui.keyconfig.shell=!
uda.taskwarrior-tui.keyconfig.log=l
uda.taskwarrior-tui.keyconfig.add=a
uda.taskwarrior-tui.keyconfig.annotate=A
uda.taskwarrior-tui.keyconfig.filter=/
uda.taskwarrior-tui.keyconfig.zoom=z
uda.taskwarrior-tui.keyconfig.context-menu=c
uda.taskwarrior-tui.keyconfig.next-tab=.
uda.taskwarrior-tui.keyconfig.previous-tab=,
taskd.certificate=$XDG_DATA_HOME/task/private.certificate.pem
taskd.key=$XDG_DATA_HOME/task/private.key.pem
taskd.ca=$XDG_DATA_HOME/task/ca.cert.pem
taskd.server=inthe.am:53589
taskd.credentials=inthe_am/ivuorinen/b99a4970-94fb-4fb8-b9fe-e1a8140dd44d
taskd.trust=strict

View File

@@ -0,0 +1,38 @@
[style.description]
underline = false
bold = false
italic = false
[style.command_name]
foreground = "cyan"
underline = false
bold = false
italic = false
[style.example_text]
foreground = "green"
underline = false
bold = false
italic = false
[style.example_code]
foreground = "cyan"
underline = false
bold = false
italic = false
[style.example_variable]
foreground = "cyan"
underline = true
bold = false
italic = false
[display]
compact = false
use_pager = false
[updates]
auto_update = false
auto_update_interval_hours = 720
[directories]

11
config/tms/config.toml Normal file
View File

@@ -0,0 +1,11 @@
default_session = "main"
display_full_path = true
[[search_dirs]]
path = "~/Code"
depth = 3
[picker_colors]
highlight_color = "#31748f"
highlight_text_color = "#e0def4"
border_color = "#524F67"

View File

@@ -7,13 +7,13 @@ DEFAULT_NAME="main"
CURRENT_SESSION=$(tmux display-message -p "#{session_name}")
# Check that the session has a name
if [[ "$CURRENT_SESSION" = "#{session_name}" ]] || [[ "$CURRENT_SESSION" = "0" ]]; then
if [ "$CURRENT_SESSION" = "#{session_name}" ] || [ "$CURRENT_SESSION" = "0" ]; then
# Check if the default name is already in use
if tmux has-session -t "$DEFAULT_NAME" 2> /dev/null; then
# Query the user for a new name
echo "Session name '$DEFAULT_NAME' is already in use. Enter a new name:"
read -r NEW_NAME
while tmux has-session -t "$NEW_NAME" 2> /dev/null || [[ -z "$NEW_NAME" ]]; do
while tmux has-session -t "$NEW_NAME" 2> /dev/null || [ -z "$NEW_NAME" ]; do
echo "Name '$NEW_NAME' is invalid or already in use. Enter a new name:"
read -r NEW_NAME
done

View File

@@ -8,14 +8,12 @@
set -euo pipefail
# Fall back to native tmux session picker if sesh is not installed
if ! command -v sesh &> /dev/null; then
if ! command -v sesh &>/dev/null; then
tmux choose-tree -Zs
exit 0
fi
# Pick a sesh session using gum filter
pick_with_gum()
{
pick_with_gum() {
sesh list -i \
| gum filter \
--limit 1 \
@@ -24,7 +22,6 @@ pick_with_gum()
--placeholder 'Pick a sesh' \
--height 50 \
--prompt='⚡'
return 0
}
FZF_COMMON_OPTS=(
@@ -43,23 +40,15 @@ FZF_COMMON_OPTS=(
--preview 'sesh preview {}'
)
# Pick a sesh session using fzf-tmux popup
pick_with_fzf_tmux()
{
pick_with_fzf_tmux() {
sesh list --icons | fzf-tmux -p 80%,70% "${FZF_COMMON_OPTS[@]}"
return 0
}
# Pick a sesh session using fzf inline
pick_with_fzf()
{
pick_with_fzf() {
sesh list --icons | fzf "${FZF_COMMON_OPTS[@]}"
return 0
}
# Pick a sesh session using bash select menu
pick_with_select()
{
pick_with_select() {
local sessions
mapfile -t sessions < <(sesh list)
if [[ ${#sessions[@]} -eq 0 ]]; then
@@ -75,11 +64,11 @@ pick_with_select()
}
# Cascading tool detection
if command -v gum &> /dev/null; then
if command -v gum &>/dev/null; then
selection=$(pick_with_gum)
elif command -v fzf-tmux &> /dev/null; then
elif command -v fzf-tmux &>/dev/null; then
selection=$(pick_with_fzf_tmux)
elif command -v fzf &> /dev/null; then
elif command -v fzf &>/dev/null; then
selection=$(pick_with_fzf)
else
selection=$(pick_with_select)

View File

@@ -10,7 +10,7 @@ config.color_scheme_dirs = {
}
-- Font and font size
config.font_size = 12
config.font_size = 16
config.font = wezterm.font_with_fallback {
{
family = 'Monaspace Argon NF',
@@ -48,9 +48,9 @@ config.window_background_opacity = 0.97
config.window_decorations = 'RESIZE'
config.macos_window_background_blur = 10
config.window_padding = {
left = 10,
right = 10,
top = 10,
left = 5,
right = 5,
top = 5,
bottom = 5,
}

181
config/wtf/config.yml Normal file
View File

@@ -0,0 +1,181 @@
---
wtf:
colors:
background: black
border:
focusable: darkslateblue
focused: orange
normal: gray
checked: yellow
highlight:
fore: black
back: gray
rows:
even: yellow
odd: white
grid:
# How _wide_ the columns are, in terminal characters. In this case we have
# four columns, each of which are 35 characters wide.
columns: [35, 35, 30, 20]
# How _high_ the rows are, in terminal lines. In this case we have four rows
# that support ten line of text and one of four.
rows: [10, 10, 10, 20, 10, 4]
refreshInterval: 1
openFileUtil: 'open'
mods:
# You can have multiple widgets of the same type.
# The "key" is the name of the widget and the type is the actual
# widget you want to implement.
europe_time:
title: 'Europe'
type: clocks
colors:
rows:
even: 'lightblue'
odd: 'white'
enabled: true
locations:
GMT: 'Etc/GMT'
Amsterdam: 'Europe/Amsterdam'
Berlin: 'Europe/Berlin'
Barcelona: 'Europe/Madrid'
Copenhagen: 'Europe/Copenhagen'
London: 'Europe/London'
Rome: 'Europe/Rome'
Stockholm: 'Europe/Stockholm'
position:
top: 0
left: 0
height: 1
width: 1
refreshInterval: 15
sort: 'alphabetical'
americas_time:
title: 'Americas'
type: clocks
colors:
rows:
even: 'lightblue'
odd: 'white'
enabled: true
locations:
UTC: 'Etc/UTC'
Vancouver: 'America/Vancouver'
New_York: 'America/New_York'
Sao_Paulo: 'America/Sao_Paulo'
Denver: 'America/Denver'
Iqaluit: 'America/Iqaluit'
Bahamas: 'America/Nassau'
Chicago: 'America/Chicago'
position:
top: 0
left: 1
height: 1
width: 1
refreshInterval: 15
sort: 'alphabetical'
battery:
type: power
title: '⚡️'
enabled: true
position:
top: 1
left: 2
height: 1
width: 2
refreshInterval: 15
todolist:
type: todo
checkedIcon: 'X'
colors:
checked: gray
highlight:
fore: 'black'
back: 'orange'
enabled: true
filename: 'todo.yml'
position:
top: 1
left: 0
height: 2
width: 1
refreshInterval: 3600
ip:
type: ipinfo
title: 'My IP'
colors:
name: 'lightblue'
value: 'white'
enabled: true
position:
top: 0
left: 2
height: 1
width: 2
refreshInterval: 150
security_info:
type: security
title: 'Staying safe'
enabled: true
position:
top: 1
left: 1
height: 1
width: 1
refreshInterval: 3600
readme:
type: textfile
enabled: true
filePaths:
- '~/.config/wtf/config.yml'
format: true
formatStyle: 'monokai'
position:
top: 3
left: 0
height: 1
width: 1
refreshInterval: 15
news:
type: hackernews
title: 'HackerNews'
enabled: true
numberOfStories: 10
position:
top: 3
left: 1
height: 1
width: 3
storyType: top
refreshInterval: 900
resources:
type: resourceusage
enabled: true
position:
top: 4
left: 0
height: 2
width: 1
refreshInterval: 1
uptime:
type: cmdrunner
args: []
cmd: 'uptime'
enabled: true
position:
top: 5
left: 1
height: 1
width: 3
refreshInterval: 30
disks:
type: cmdrunner
cmd: 'df'
args: ['-h']
enabled: true
position:
top: 4
left: 1
height: 1
width: 3
refreshInterval: 3600

View File

@@ -20,6 +20,7 @@ yabai -m config \
window_shadow float
# apps to not manage (ignore)
# TODO: add apps from aerospace config to here
# list active apps:
# > yabai -m query --windows | jq .[].app | sort | uniq
yabai -m rule --add app="1Password" manage=off

8
config/yamlfmt/.yamlfmt Normal file
View File

@@ -0,0 +1,8 @@
formatter:
type: basic
indent: 2
retain_line_breaks: false
disallow_anchors: false
max_line_length: 0
scan_folded_as_literal: false
indentless_arrays: false

31
config/yamllint/config Normal file
View File

@@ -0,0 +1,31 @@
---
extends: default
ignore-from-file: [.gitignore, .yamlignore]
rules:
braces:
level: warning
max-spaces-inside: 1
brackets:
level: warning
max-spaces-inside: 1
colons:
level: warning
commas:
level: warning
comments: disable
comments-indentation: disable
document-start: disable
empty-lines:
level: warning
hyphens:
level: warning
indentation:
level: warning
indent-sequences: consistent
line-length:
level: warning
allow-non-breakable-inline-mappings: true
max: 120
truthy: disable

View File

@@ -37,6 +37,7 @@ zdharma-continuum/fast-syntax-highlighting
# Add some plugins that are not in OMZ
jreese/zsh-titles
yuki-ycino/tms
# This needs to be last bundle
# zsh-users/zsh-syntax-highlighting

View File

@@ -28,6 +28,7 @@ _dfm()
sections=(
'install:Installation commands'
'asdf:ASDF version manager commands'
'brew:Homebrew package manager commands'
'check:System check commands'
'dotfiles:Dotfiles management commands'
@@ -68,6 +69,24 @@ _dfm()
_describe 'install commands' install_cmds
;;
asdf)
local -a asdf_cmds
asdf_cmds=(
'current:Show current versions'
'global:Show global versions'
'installed:Show installed versions'
'plugins-update:Update all plugins'
'plugins-install:Install plugins from configuration'
'plugins-remove:Remove installed plugins'
'reset:Reset plugins'
'fix-tool-versions:Remove uninstalled plugins from .tool-versions'
'versions:Show versions'
'where:Show where'
'which:Show which'
)
_describe 'asdf commands' asdf_cmds
;;
brew)
local -a brew_cmds
brew_cmds=(

View File

@@ -0,0 +1,66 @@
# aerospace keybindings
## main
| Key | Command(s) and actions |
| -------------- | -------------------------------------------- |
| alt-a | mode apps |
| alt-h | focus left |
| alt-j | focus down |
| alt-k | focus up |
| alt-l | focus right |
| alt-m | mode move |
| alt-s | mode service |
| alt-shift-1 | workspace 1 |
| alt-shift-2 | workspace 2 |
| alt-shift-tab | workspace-back-and-forth |
| ctrl-shift-1 | move-node-to-workspace 1 |
| ctrl-shift-2 | move-node-to-workspace 2 |
| ctrl-shift-tab | move-workspace-to-monitor --wrap-around prev |
## apps
| Key | Command(s) and actions |
| --- | ------------------------------------------------------------------ |
| b | exec-and-forget open -a /Applications/Brave Browser.app; mode main |
| c | exec-and-forget open -a /Applications/Ferdium.app; mode main |
| esc | reload-config; mode main |
| g | exec-and-forget open -a /Applications/Ghostty.app; mode main |
| o | exec-and-forget open -a /Applications/Obsidian.app; mode main |
| s | exec-and-forget open -a /Applications/Slack.app; mode main |
| t | exec-and-forget open -a /Applications/TIDAL.app; mode main |
| w | exec-and-forget open -a /Applications/WezTerm.app; mode main |
## move
| Key | Command(s) and actions |
| ----------- | ----------------------------------------------- |
| 1 | move-node-to-workspace 1 --focus-follows-window |
| 2 | move-node-to-workspace 2 --focus-follows-window |
| ctrl-h | resize smart -70 |
| ctrl-l | resize smart +70 |
| esc | reload-config; mode main |
| h | move left |
| j | move down |
| k | move up |
| l | move right |
| r | flatten-workspace-tree; mode main |
| shift-h | join-with left |
| shift-j | join-with down |
| shift-k | join-with up |
| shift-l | join-with right |
| shift-left | resize smart +70 |
| shift-right | resize smart -70 |
## service
| Key | Command(s) and actions |
| --------- | ---------------------------------------- |
| backspace | close-all-windows-but-current; mode main |
| esc | reload-config; mode main |
| f | layout floating tiling; mode main |
| r | flatten-workspace-tree; mode main |
File generated: 2025-01-15 13:32:41
Config file: [config/aerospace/aerospace.toml](./../config/aerospace/aerospace.toml)

View File

@@ -1,40 +0,0 @@
# Skip Already-Installed Cargo Packages
## Problem
`install-cargo-packages.sh` runs `cargo install-update -a` to update installed
packages, then runs `cargo install` for every package in the list — including
ones that are already installed and up-to-date. This wastes time rebuilding
packages that don't need it.
## Solution
Capture the `cargo install-update -a` output, parse installed package names,
and skip `cargo install` for any package that appeared in the update output.
## Changes
**File:** `scripts/install-cargo-packages.sh`
1. Declare an associative array `installed_packages` at the top.
2. In the `cargo-install-update` section, capture output with `tee /dev/stderr`
so it displays in real-time while also being stored in a variable.
3. Parse the captured output with `awk` — extract the first column from lines
matching a version pattern (`v[0-9]+\.[0-9]+`), skipping the header.
4. Populate `installed_packages` associative array from parsed names.
5. In `install_packages()`, check each package against the array. If found, log
a skip message via `msgr` and continue. If not found, install as before.
6. If `cargo-install-update` is not available, the array stays empty and all
packages install normally (preserves existing behavior).
## Output Parsing
The `cargo install-update -a` output format:
```text
Package Installed Latest Needs update
zoxide v0.9.8 v0.9.9 Yes
bkt v0.8.2 v0.8.2 No
```
Extraction: `awk '/v[0-9]+\.[0-9]+/ { print $1 }'` gets package names.

View File

@@ -1,55 +0,0 @@
# dfm Cleanup Design
## Summary
Clean up `local/bin/dfm` to fix bugs, remove dead code, improve
cross-platform portability, and make error handling consistent.
## Changes
### 1. Bash Version Bootstrap
Add a check at the top of the script (after variable declarations)
that requires bash 4.0+. On macOS, if bash is too old, install
Homebrew (if missing) and bash, then print instructions and exit.
The check itself uses only bash 3.2-compatible syntax.
### 2. Remove Fish Dead Code
Remove `CURRENT_SHELL` detection, `source_file()` function, and all
fish branches. Replace `source_file` calls with direct `source`.
The script has a bash shebang — fish handling was unreachable.
### 3. Bug Fixes
- Remove `ntfy` from install menu (no install script exists)
- Fix `msg)``msgr)` case label in `section_tests`
- Guard all `shift` calls against empty argument lists
- Quote `$width` in `menu_builder` seq calls
- Fix `$"..."` locale string → `"..."` in `usage()`
- Fix `exit 0` on apt.txt error → `return 1`
### 4. Replace `declare -A` in `section_scripts`
Replace associative array with indexed `"name:desc"` array,
matching the pattern used everywhere else in the script.
Move `get_script_description()` to top-level (out of the function).
### 5. Early-Return Guards & exit → return
- `section_brew()`: Early return with `msgr warn` if brew unavailable.
Remove duplicate `! x-have brew` check.
- `section_apt()`: Same pattern for apt.
- `section_check()`: Replace `exit` with `return`.
- `section_apt() install`: Replace `exit` with `return`.
- `section_brew() untracked`: Replace `exit` with `return`.
## Files Changed
- `local/bin/dfm` (all changes)
## Verification
- `yarn test` (existing bats test)
- `shellcheck local/bin/dfm`
- `bash -n local/bin/dfm` (syntax check)

View File

@@ -1,46 +0,0 @@
# x-* Scripts Cleanup Design
## Summary
Comprehensive cleanup of all 34 x-* utility scripts in `local/bin/`.
Fix critical bugs, consolidate duplicates, standardize patterns.
## Changes
### Removals
- `x-mkd`, `x-mkd.md`, `tests/x-mkd.bats` — unused, cd-in-subshell broken
- `x-validate-sha256sum.sh`, `x-validate-sha256sum.sh.md` — duplicates x-sha256sum-matcher
### Thin Wrappers (delegate to x-path)
- `x-path-append` → calls `x-path append "$@"`
- `x-path-prepend` → calls `x-path prepend "$@"`
- `x-path-remove` → calls `x-path remove "$@"`
### Critical Fixes
- `x-clean-vendordirs`: call msgr as command (it's in PATH)
- `x-foreach`: replace eval with direct "$@" execution
- `x-ip`: add error handling, curl check
### Consistency Fixes
- Fix `#!/bin/bash``#!/usr/bin/env bash` (x-env-list, x-localip)
- POSIX scripts keep `#!/bin/sh`
- Add `set -euo pipefail` where missing in bash scripts
- Use XDG variables instead of hardcoded paths (x-change-alacritty-theme)
- Quote unquoted variables
### Minor Fixes
- `x-multi-ping`: remove unused VERBOSE variable
- `x-when-down`, `x-when-up`: add error handling
- `x-term-colors`: add usage message
- `x-record`: fix undefined notify-call reference
## Verification
- `yarn test` — ensure remaining tests pass
- `shellcheck` on modified scripts
- `bash -n` syntax check on all modified bash scripts

View File

@@ -1,5 +1,5 @@
---
- include: "tools/dotbot-defaults.yaml"
- include: 'tools/dotbot-defaults.yaml'
- shell:
- echo "Configuring air"
- link:
@@ -7,7 +7,7 @@
force: true
glob: true
path: hosts/air/base/**
prefix: "."
prefix: '.'
~/.config/:
glob: true
force: true

View File

@@ -1,5 +1,5 @@
---
- include: "tools/dotbot-defaults.yaml"
- include: 'tools/dotbot-defaults.yaml'
- shell:
- echo "Configuring lakka"
- link:
@@ -7,7 +7,7 @@
force: true
glob: true
path: hosts/lakka/base/**
prefix: "."
prefix: '.'
~/.config/:
glob: true
force: true

View File

@@ -1,5 +1,5 @@
---
- include: "tools/dotbot-defaults.yaml"
- include: 'tools/dotbot-defaults.yaml'
- shell:
- echo "Configuring s"
- link:
@@ -7,7 +7,7 @@
force: true
glob: true
path: hosts/s/base/**
prefix: "."
prefix: '.'
~/.config/:
glob: true
force: true

View File

@@ -1,5 +1,5 @@
---
- include: "tools/dotbot-defaults.yaml"
- include: 'tools/dotbot-defaults.yaml'
- shell:
- echo "Configuring tunkki"
- link:
@@ -7,7 +7,7 @@
force: true
glob: true
path: hosts/tunkki/base/**
prefix: "."
prefix: '.'
~/.config/:
glob: true
force: true

12
install
View File

@@ -15,18 +15,24 @@ git submodule update --init --recursive "${DOTBOT_DIR}"
"${DOTBOT_BIN_PATH}" \
-d "${BASEDIR}" \
--plugin-dir=tools/dotbot-asdf \
--plugin-dir=tools/dotbot-brew \
--plugin-dir=tools/dotbot-include \
--plugin-dir=tools/dotbot-pip \
-c "${CONFIG}" \
"${@}"
if [ "${DOTBOT_HOST}" != "" ]; then
DOTBOT_HOST_CONFIG="${BASEDIR}/hosts/${DOTBOT_HOST}/${CONFIG}"
echo "-> Trying if host config can be found: ${DOTBOT_HOST_CONFIG}"
[ -r "$DOTBOT_HOST_CONFIG" ] && [ -f "$DOTBOT_HOST_CONFIG" ] \
&& echo "(!) Found $DOTBOT_HOST_CONFIG" \
&& "$DOTBOT_BIN_PATH" \
[ -r "$DOTBOT_HOST_CONFIG" ] && [ -f "$DOTBOT_HOST_CONFIG" ] &&
echo "(!) Found $DOTBOT_HOST_CONFIG" &&
"$DOTBOT_BIN_PATH" \
-d "$BASEDIR" \
--plugin-dir=tools/dotbot-asdf \
--plugin-dir=tools/dotbot-brew \
--plugin-dir=tools/dotbot-include \
--plugin-dir=tools/dotbot-pip \
-c "$DOTBOT_HOST_CONFIG" \
"${@}"
fi

View File

@@ -1,5 +1,5 @@
---
- include: "tools/dotbot-defaults.yaml"
- include: 'tools/dotbot-defaults.yaml'
- clean:
~/:
@@ -34,7 +34,7 @@
force: true
glob: true
path: base/*
prefix: "."
prefix: '.'
# Most of the configs
~/.config/:
glob: true
@@ -78,3 +78,8 @@
- shell:
# Use my dotfiles manager to install everything
- bash local/bin/dfm install all
- pipx:
file: tools/requirements-pipx.txt
stdout: true
stderr: true

View File

@@ -20,7 +20,7 @@ Some problematic code has been fixed per `shellcheck` suggestions.
## Sourced
| Script | Source |
|-------------------------|-------------------|
| ----------------------- | ----------------- |
| `x-dupes` | skx/sysadmin-util |
| `x-foreach` | mvdan/dotfiles |
| `x-multi-ping` | skx/sysadmin-util |

View File

@@ -1,9 +1,7 @@
#!/usr/bin/env bash
# A script for encrypting and decrypting files or directories with age and SSH keys
set -euo pipefail
VERSION="1.1.0"
VERSION="1.0.0"
# Default ENV values
KEYS_FILE="${AGE_KEYSFILE:-$HOME/.ssh/keys.txt}"
@@ -11,49 +9,14 @@ KEYS_SOURCE="${AGE_KEYSSOURCE:-https://github.com/ivuorinen.keys}"
LOG_FILE="${AGE_LOGFILE:-$HOME/.cache/a.log}"
VERBOSE=false
DELETE_ORIGINAL=false
FORCE=false
# Check for required dependencies
check_dependencies()
{
if ! command -v age &> /dev/null; then
echo "Error: 'age' is not installed. Please install it first." >&2
echo " brew install age # macOS" >&2
echo " apt install age # Debian/Ubuntu" >&2
echo " dnf install age # Fedora" >&2
exit 1
# Parse flags for verbosity
for arg in "$@"; do
if [[ "$arg" == "-v" || "$arg" == "--verbose" ]]; then
VERBOSE=true
break
fi
if ! command -v curl &> /dev/null; then
echo "Error: 'curl' is not installed." >&2
exit 1
fi
}
# Parse flags
parse_flags()
{
local args=()
for arg in "$@"; do
case "$arg" in
-v | --verbose)
VERBOSE=true
;;
--delete)
DELETE_ORIGINAL=true
;;
-f | --force)
FORCE=true
;;
*)
args+=("$arg")
;;
esac
done
# Return remaining arguments
printf '%s\n' "${args[@]}"
}
done
# Ensure log directory and file exist with correct permissions
prepare_log_file()
@@ -75,6 +38,8 @@ prepare_log_file()
chmod 0600 "$LOG_FILE"
}
prepare_log_file
# Logging function
log_message()
{
@@ -91,7 +56,7 @@ log_message()
print_help()
{
cat << EOF
Usage: a [options] [command] [file_or_directory]
Usage: a [command] [file_or_directory] [options]
Commands:
e, enc, encrypt Encrypt the specified file or directory
@@ -100,14 +65,12 @@ Commands:
version, --version Show version information
Options:
-v, --verbose Print log messages to console
--delete Delete original files after successful encryption
-f, --force Overwrite existing output files without prompting
-v, --verbose Print log messages to console in addition to writing to log file
Environment Variables:
AGE_KEYSFILE Path to the SSH keys file (default: \$HOME/.ssh/keys.txt)
AGE_KEYSFILE Path to the SSH keys file (default: $HOME/.ssh/keys.txt)
AGE_KEYSSOURCE URL to fetch SSH keys if keys file does not exist
AGE_LOGFILE Path to the log file (default: \$HOME/.cache/a.log)
AGE_LOGFILE Path to the log file (default: $HOME/.cache/a.log)
Examples:
Encrypt a file:
@@ -116,21 +79,14 @@ Examples:
Encrypt a directory:
a e /path/to/directory
Encrypt and delete originals:
a --delete e file.txt
Decrypt a file:
a d file.txt.age
Force overwrite existing files:
a -f e file.txt
Specify a custom keys file:
AGE_KEYSFILE=/path/to/keys.txt a e file.txt
Requirements:
- age (encryption tool): https://github.com/FiloSottile/age
- curl (for fetching keys)
Specify a custom keys source and log file:
AGE_KEYSSOURCE=https://example.com/keys.txt AGE_LOGFILE=/tmp/a.log a d file.txt.age
EOF
}
@@ -159,104 +115,26 @@ fetch_keys_if_missing()
fi
}
# Function to encrypt a single file
encrypt_single_file()
{
local file="$1"
# Skip already encrypted files
if [[ "$file" == *.age ]]; then
log_message "Skipping already encrypted file: $file"
return 0
fi
local output_file="${file}.age"
# Check if output file exists
if [[ -f "$output_file" && "$FORCE" != true ]]; then
log_message "Error: Output file '$output_file' already exists. Use --force to overwrite."
return 1
fi
fetch_keys_if_missing
local temp_file
temp_file="$(mktemp -p "$(dirname "$file")")"
if age -R "$KEYS_FILE" "$file" > "$temp_file" && mv "$temp_file" "$output_file"; then
log_message "File encrypted successfully: $output_file"
if [[ "$DELETE_ORIGINAL" == true ]]; then
rm -f "$file"
log_message "Original file deleted: $file"
fi
else
rm -f "$temp_file"
log_message "Error: Failed to encrypt file '$file'."
return 1
fi
}
# Function to encrypt files or directories
encrypt_file_or_directory()
{
local file="$1"
if [[ -d "$file" ]]; then
# Enable dotglob to include hidden files
shopt -s dotglob nullglob
local files=("$file"/*)
shopt -u dotglob nullglob
if [[ ${#files[@]} -eq 0 ]]; then
log_message "Warning: Directory '$file' is empty."
return 0
fi
for f in "${files[@]}"; do
for f in "$file"/*; do
encrypt_file_or_directory "$f"
done
elif [[ -f "$file" ]]; then
encrypt_single_file "$file"
else
log_message "Warning: '$file' is not a file or directory, skipping."
fi
}
# Function to decrypt a single file
decrypt_single_file()
{
local file="$1"
if [[ ! "$file" == *.age ]]; then
log_message "Skipping non-.age file: $file"
return 0
fi
local output_file="${file%.age}"
# Check if output file exists
if [[ -f "$output_file" && "$FORCE" != true ]]; then
log_message "Error: Output file '$output_file' already exists. Use --force to overwrite."
return 1
fi
fetch_keys_if_missing
local temp_file
temp_file="$(mktemp -p "$(dirname "$file")")"
if age -d -i "$KEYS_FILE" "$file" > "$temp_file" && mv "$temp_file" "$output_file"; then
log_message "File decrypted successfully: $output_file"
if [[ "$DELETE_ORIGINAL" == true ]]; then
rm -f "$file"
log_message "Encrypted file deleted: $file"
fetch_keys_if_missing
local output_file="${file}.age"
local temp_file
temp_file="$(mktemp -p "$(dirname "$file")")"
if age -R "$KEYS_FILE" "$file" > "$temp_file" && mv "$temp_file" "$output_file"; then
log_message "File encrypted successfully: $output_file"
else
rm -f "$temp_file"
log_message "Error: Failed to encrypt file '$file'."
exit 1
fi
else
rm -f "$temp_file"
log_message "Error: Failed to decrypt file '$file'."
return 1
fi
}
@@ -264,76 +142,54 @@ decrypt_single_file()
decrypt_file_or_directory()
{
local file="$1"
if [[ -d "$file" ]]; then
# Enable nullglob to handle no matches gracefully
shopt -s nullglob
local files=("$file"/*.age)
shopt -u nullglob
if [[ ${#files[@]} -eq 0 ]]; then
log_message "Warning: No .age files found in directory '$file'."
return 0
fi
for f in "${files[@]}"; do
decrypt_single_file "$f"
for f in "$file"/*.age; do
decrypt_file_or_directory "$f"
done
elif [[ -f "$file" ]]; then
decrypt_single_file "$file"
else
log_message "Warning: '$file' is not a file or directory, skipping."
fetch_keys_if_missing
local output_file="${file%.age}"
local temp_file
temp_file="$(mktemp -p "$(dirname "$file")")"
if age -d -i "$KEYS_FILE" "$file" > "$temp_file" && mv "$temp_file" "$output_file"; then
log_message "File decrypted successfully: $output_file"
else
rm -f "$temp_file"
log_message "Error: Failed to decrypt file '$file'."
exit 1
fi
fi
}
# Main entry point
main()
{
check_dependencies
# Parse flags and get remaining arguments
mapfile -t ARGS < <(parse_flags "$@")
prepare_log_file
local command="${ARGS[0]:-}"
local target="${ARGS[1]:-}"
case "$command" in
e | enc | encrypt)
if [[ -z "$target" ]]; then
log_message "Error: No file or directory specified for encryption."
print_help
exit 1
fi
encrypt_file_or_directory "$target"
;;
d | dec | decrypt)
if [[ -z "$target" ]]; then
log_message "Error: No file or directory specified for decryption."
print_help
exit 1
fi
decrypt_file_or_directory "$target"
;;
help | --help | -h)
print_help
;;
version | --version)
print_version
;;
"")
# Main logic
case "$1" in
e | enc | encrypt)
if [[ $# -lt 2 ]]; then
log_message "Error: No file or directory specified for encryption."
print_help
exit 1
;;
*)
log_message "Error: Unknown command '$command'"
fi
encrypt_file_or_directory "$2"
;;
d | dec | decrypt)
if [[ $# -lt 2 ]]; then
log_message "Error: No file or directory specified for decryption."
print_help
exit 1
;;
esac
}
main "$@"
fi
decrypt_file_or_directory "$2"
;;
help | --help)
print_help
;;
version | --version)
print_version
;;
*)
log_message "Error: Unknown command '$1'"
print_help
exit 1
;;
esac
# vim: ft=bash:syn=sh:ts=2:sw=2:et:ai:nowrap

View File

@@ -2,76 +2,28 @@
Encrypt or decrypt files and directories using `age` and your GitHub SSH keys.
## Requirements
- [age](https://github.com/FiloSottile/age) - encryption tool
- curl - for fetching SSH keys
Install age:
```bash
brew install age # macOS
apt install age # Debian/Ubuntu
dnf install age # Fedora
```
## Usage
```bash
a [options] <command> <file|directory>
a encrypt <file|dir>
a decrypt <file.age|dir>
```
Commands:
- `e`, `enc`, `encrypt` - encrypt files
- `d`, `dec`, `decrypt` - decrypt files
- `help`, `--help`, `-h` - show help
- `version`, `--version` - show version
Options:
- `-v`, `--verbose` - show log output
- `--delete` - delete original files after successful operation
- `-f`, `--force` - overwrite existing output files
- `-v`, `--verbose` show log output
Environment variables:
- `AGE_KEYSFILE` - location of the keys file (default: `~/.ssh/keys.txt`)
- `AGE_KEYSSOURCE` - URL to fetch keys if missing (default: GitHub keys)
- `AGE_LOGFILE` - log file path (default: `~/.cache/a.log`)
- `AGE_KEYSFILE` location of the keys file
- `AGE_KEYSSOURCE` URL to fetch keys if missing
- `AGE_LOGFILE` log file path
## Examples
## Example
```bash
# Encrypt a file
a encrypt secret.txt
# Encrypt with short command
a e secret.txt
# Decrypt a file
a decrypt secret.txt.age
a d secret.txt.age
# Encrypt a directory (includes hidden files)
a e /path/to/secrets/
# Encrypt and delete originals
a --delete e secret.txt
# Force overwrite existing .age file
a -f e secret.txt
# Verbose output
a -v e secret.txt
```
## Behavior
- Encrypting a directory processes all files recursively, including hidden files
- Already encrypted files (`.age`) are skipped during encryption
- Only `.age` files are processed during directory decryption
- Original files are preserved by default (use `--delete` to remove them)
- Output files are not overwritten by default (use `--force` to overwrite)
<!-- vim: set ft=markdown spell spelllang=en_us cc=80 : -->

View File

@@ -12,41 +12,41 @@
: "${DOTFILES:=$HOME/.dotfiles}"
: "${BREWFILE:=$DOTFILES/config/homebrew/Brewfile}"
: "${HOSTFILES:=$DOTFILES/hosts}"
export DOTFILES BREWFILE HOSTFILES
SCRIPT=$(basename "$0")
# Require bash 4.0+ for associative arrays and mapfile
if ((BASH_VERSINFO[0] < 4)); then
echo "dfm requires bash 4.0+, found ${BASH_VERSION}"
if [[ "$(uname)" == "Darwin" ]]; then
if ! command -v brew &> /dev/null; then
echo "Installing Homebrew..."
/bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"
fi
echo "Installing modern bash via Homebrew..."
brew install bash
echo "Done. Restart your shell and run dfm again."
else
echo "Install bash 4.0+ and try again."
fi
exit 1
fi
# Detect the current shell
CURRENT_SHELL=$(ps -p $$ -ocomm= | awk -F/ '{print $NF}')
# shellcheck disable=SC1091
source "$DOTFILES/config/shared.sh"
# shellcheck disable=SC1090
source "${DOTFILES}/local/bin/msgr"
# Get description from a script file's @description tag
get_script_description()
# Function to source files based on the shell
source_file()
{
local file="$1"
local desc
desc=$(sed -n '/@description/s/.*@description *\(.*\)/\1/p' "$file" | head -1)
echo "${desc:-No description available}"
local file=$1
case "$CURRENT_SHELL" in
fish)
if [[ -f "$file.fish" ]]; then
# shellcheck disable=SC1090
source "$file.fish"
else
echo "Fish shell file not found: $file.fish"
exit 1
fi
;;
sh | bash | zsh)
# shellcheck disable=SC1090
source "$file"
;;
*)
echo "Unsupported shell: $CURRENT_SHELL"
exit 1
;;
esac
}
# Modify the source commands to use the new function
source_file "$DOTFILES/config/shared.sh"
source_file "${DOTFILES}/local/bin/msgr"
# Menu builder
menu_builder()
{
@@ -54,9 +54,9 @@ menu_builder()
local commands=("${@:2}")
local width=60
printf "\n%s\n" "$(printf '%.s─' $(seq 1 "$width"))"
printf "\n%s\n" "$(printf '%.s─' $(seq 1 $width))"
printf "%-${width}s\n" " $title"
printf "%s\n" "$(printf '%.s─' $(seq 1 "$width"))"
printf "%s\n" "$(printf '%.s─' $(seq 1 $width))"
for cmd in "${commands[@]}"; do
local name=${cmd%%:*}
@@ -65,68 +65,41 @@ menu_builder()
done
}
# Handle install section commands
section_install()
{
USAGE_PREFIX="$SCRIPT install <command>"
MENU=(
"all:Installs everything in the correct order"
"apt-packages:Install apt packages (Debian/Ubuntu)"
"cargo:Install rust/cargo packages"
"cheat-databases:Install cheat external cheatsheet databases"
"composer:Install composer"
"dnf-packages:Install dnf packages (Fedora/RHEL)"
"fonts:Install programming fonts"
"gh:Install GitHub CLI Extensions"
"git-crypt:Install git-crypt from source"
"go:Install Go Packages"
"imagick:Install ImageMagick CLI"
"macos:Setup nice macOS defaults"
"npm-packages:Install NPM Packages"
"ntfy:Install ntfy notification tool"
"ntfy:Install ntfy"
"nvm-latest:Install latest lts node using nvm"
"nvm:Install Node Version Manager (nvm)"
"python-packages:Install Python packages via uv"
"shellspec:Install shellspec testing framework"
"xcode-cli-tools:Install Xcode CLI tools (macOS)"
"z:Install z"
)
case "$1" in
all)
msgr msg "Starting to install all and reloading configurations..."
# Tier 0: Platform foundations (OS packages, build tools)
[[ "$(uname)" == "Darwin" ]] && $0 install macos
[[ "$(uname)" == "Darwin" ]] && $0 install xcode-cli-tools
command -v apt &> /dev/null && $0 install apt-packages
command -v dnf &> /dev/null && $0 install dnf-packages
# Tier 1: Package managers & fonts
$0 brew install
$0 install macos
$0 install fonts
# Tier 2: Language packages (depend on runtimes from Tier 1)
$0 brew install
$0 install cargo
$0 install go
$0 install composer
$0 install cheat-databases
$0 install nvm
$0 install npm-packages
$0 install python-packages
# Tier 3: Tool-dependent installers
$0 install cheat-databases
$0 install gh
$0 install git-crypt
$0 install ntfy
# Tier 4: Independent utilities
$0 install shellspec
$0 install z
msgr msg "Reloading configurations again..."
# shellcheck disable=SC1091
source "$DOTFILES/config/shared.sh"
msgr yay "All done!"
;;
@@ -139,7 +112,7 @@ section_install()
cheat-databases)
msgr run "Installing cheat databases..."
for database in "$DOTFILES"/scripts/install-cheat-*.sh; do
for database in "$DOTFILES"/scripts/install-cheat-*; do
bash "$database" \
&& msgr run_done "Cheat: $database run"
done
@@ -211,48 +184,6 @@ section_install()
&& msgr yay "NPM Packages have been installed!"
;;
apt-packages)
msgr run "Installing apt packages..."
bash "$DOTFILES/scripts/install-apt-packages.sh" \
&& msgr yay "apt packages installed!"
;;
dnf-packages)
msgr run "Installing dnf packages..."
bash "$DOTFILES/scripts/install-dnf-packages.sh" \
&& msgr yay "dnf packages installed!"
;;
git-crypt)
msgr run "Installing git-crypt..."
bash "$DOTFILES/scripts/install-git-crypt.sh" \
&& msgr yay "git-crypt installed!"
;;
ntfy)
msgr run "Installing ntfy..."
bash "$DOTFILES/scripts/install-ntfy.sh" \
&& msgr yay "ntfy installed!"
;;
python-packages)
msgr run "Installing Python packages..."
bash "$DOTFILES/scripts/install-python-packages.sh" \
&& msgr yay "Python packages installed!"
;;
xcode-cli-tools)
msgr run "Installing Xcode CLI tools..."
bash "$DOTFILES/scripts/install-xcode-cli-tools.sh" \
&& msgr yay "Xcode CLI tools installed!"
;;
shellspec)
msgr run "Installing shellspec..."
bash "$DOTFILES/scripts/install-shellspec.sh" \
&& msgr yay "shellspec has been installed!"
;;
z)
msgr run "Installing z..."
bash "$DOTFILES/scripts/install-z.sh" \
@@ -263,7 +194,6 @@ section_install()
esac
}
# Handle Homebrew section commands
section_brew()
{
USAGE_PREFIX="$SCRIPT brew <command>"
@@ -278,91 +208,89 @@ section_brew()
"untracked:List untracked brew packages"
)
if ! x-have brew; then
msgr warn "brew not available, skipping"
return 0
fi
x-have brew && {
case "$1" in
install)
brew bundle install --file="$BREWFILE" --force --quiet && msgr yay "Done!"
;;
case "$1" in
install)
brew bundle install --file="$BREWFILE" --force --quiet && msgr yay "Done!"
;;
update)
brew update && brew outdated && brew upgrade && brew cleanup
msgr yay "Done!"
;;
update)
brew update && brew outdated && brew upgrade && brew cleanup
msgr yay "Done!"
;;
updatebundle)
# Updates .dotfiles/homebrew/Brewfile with descriptions
brew bundle dump \
--force \
--file="$BREWFILE" \
--cleanup \
--tap \
--formula \
--cask \
--describe && msgr yay "Done!"
;;
updatebundle)
# Updates .dotfiles/homebrew/Brewfile with descriptions
brew bundle dump \
--force \
--file="$BREWFILE" \
--cleanup \
--tap \
--formula \
--cask \
--describe && msgr yay "Done!"
;;
leaves)
brew leaves --installed-on-request
;;
leaves)
brew leaves --installed-on-request
;;
untracked)
declare -a BREW_LIST_ALL
while IFS= read -r line; do
BREW_LIST_ALL+=("$line")
done < <(brew list --formula --installed-on-request -1 --full-name)
while IFS= read -r c; do
BREW_LIST_ALL+=("$c")
done < <(brew list --cask -1 --full-name)
untracked)
declare -a BREW_LIST_ALL
while IFS= read -r line; do
BREW_LIST_ALL+=("$line")
done < <(brew list --formula --installed-on-request -1 --full-name)
while IFS= read -r c; do
BREW_LIST_ALL+=("$c")
done < <(brew list --cask -1 --full-name)
# Remove entries that are installed as dependencies
declare -a BREW_LIST_DEPENDENCIES
while IFS= read -r l; do
BREW_LIST_DEPENDENCIES+=("$l")
done < <(brew list -1 --installed-as-dependency)
# Remove entries that are installed as dependencies
declare -a BREW_LIST_DEPENDENCIES
while IFS= read -r l; do
BREW_LIST_DEPENDENCIES+=("$l")
done < <(brew list -1 --installed-as-dependency)
declare -a BREW_LIST_BUNDLED
while IFS= read -r b; do
BREW_LIST_BUNDLED+=("$b")
done < <(brew bundle list --all --file="$BREWFILE")
declare -a BREW_LIST_BUNDLED
while IFS= read -r b; do
BREW_LIST_BUNDLED+=("$b")
done < <(brew bundle list --all --file="$BREWFILE")
declare -a BREW_LIST_TRACKED_WITHOUT_DEPS
for f in "${BREW_LIST_ALL[@]}"; do
# shellcheck disable=SC2199
if [[ " ${BREW_LIST_DEPENDENCIES[@]} " != *" ${f} "* ]]; then
BREW_LIST_TRACKED_WITHOUT_DEPS+=("$f")
fi
done
declare -a BREW_LIST_TRACKED_WITHOUT_DEPS
for f in "${BREW_LIST_ALL[@]}"; do
# shellcheck disable=SC2199
if [[ " ${BREW_LIST_DEPENDENCIES[@]} " != *" ${f} "* ]]; then
BREW_LIST_TRACKED_WITHOUT_DEPS+=("$f")
array_diff BREW_LIST_UNTRACKED BREW_LIST_TRACKED_WITHOUT_DEPS BREW_LIST_BUNDLED
# If there are no untracked packages, exit
if [ ${#BREW_LIST_UNTRACKED[@]} -eq 0 ]; then
msgr yay "No untracked packages found!"
exit 0
fi
done
array_diff BREW_LIST_UNTRACKED BREW_LIST_TRACKED_WITHOUT_DEPS BREW_LIST_BUNDLED
echo "Untracked:"
for f in "${BREW_LIST_UNTRACKED[@]}"; do
echo " $f"
done
;;
# If there are no untracked packages, return
if [ ${#BREW_LIST_UNTRACKED[@]} -eq 0 ]; then
msgr yay "No untracked packages found!"
return 0
fi
autoupdate)
brew autoupdate delete
brew autoupdate start 43200 --upgrade --cleanup --immediate
;;
echo "Untracked:"
for f in "${BREW_LIST_UNTRACKED[@]}"; do
echo " $f"
done
;;
clean) brew bundle cleanup --file="$BREWFILE" && msgr yay "Done!" ;;
autoupdate)
brew autoupdate delete
brew autoupdate start 43200 --upgrade --cleanup --immediate
;;
*) menu_builder "$USAGE_PREFIX" "${MENU[@]}" ;;
esac
}
clean) brew bundle cleanup --file="$BREWFILE" && msgr yay "Done!" ;;
*) menu_builder "$USAGE_PREFIX" "${MENU[@]}" ;;
esac
! x-have brew && menu_builder "$USAGE_PREFIX" "brew not available on this system"
}
# Handle helper utility commands
section_helpers()
{
USAGE_PREFIX="$SCRIPT helpers <command>"
@@ -371,16 +299,17 @@ section_helpers()
"colors:Show colors"
"env:Show environment variables"
"functions:Show functions"
"aerospace:Show aerospace keybindings"
"nvim:Show nvim keybindings"
'path:Show $PATH dir by dir'
"tmux:Show tmux keybindings"
"wezterm:Show wezterm keybindings"
)
CMD="${1:-}"
[[ $# -gt 0 ]] && shift
SECTION="${1:-}"
[[ $# -gt 0 ]] && shift
CMD="$1"
shift
SECTION="$1"
shift
case "$CMD" in
path)
@@ -432,6 +361,7 @@ section_helpers()
"env") env | sort ;;
"functions") declare -F ;;
"aerospace") cat "$DOTFILES/docs/aerospace-keybindings.md" ;;
"nvim") cat "$DOTFILES/docs/nvim-keybindings.md" ;;
"tmux") cat "$DOTFILES/docs/tmux-keybindings.md" ;;
"wezterm") cat "$DOTFILES/docs/wezterm-keybindings.md" ;;
@@ -439,7 +369,6 @@ section_helpers()
esac
}
# Handle apt package manager commands
section_apt()
{
USAGE_PREFIX="$SCRIPT apt <command>"
@@ -452,69 +381,64 @@ section_apt()
"clean:Clean apt cache"
)
if ! x-have apt; then
msgr warn "apt not available, skipping"
return 0
fi
x-have apt && {
case "$1" in
upkeep)
sudo apt update \
&& sudo apt upgrade -y \
&& sudo apt autoremove -y \
&& sudo apt clean
;;
case "$1" in
upkeep)
sudo apt update \
&& sudo apt upgrade -y \
&& sudo apt autoremove -y \
&& sudo apt clean
;;
install)
# if apt.txt is not found, exit
[ ! -f "$DOTFILES/tools/apt.txt" ] && msgr err "apt.txt not found" && exit 0
install)
# if apt.txt is not found, return with error
if [ ! -f "$DOTFILES/tools/apt.txt" ]; then
msgr err "apt.txt not found"
return 1
fi
# Load apt.txt, remove comments (even if trailing comment) and empty lines.
#
# Ignoring "Quote this to prevent word splitting."
# shellcheck disable=SC2046
sudo apt install \
-y $(
grep -vE '^\s*#' "$DOTFILES/tools/apt.txt" \
| sed -e 's/#.*//' \
| tr '\n' ' '
)
# If there's a apt.txt file under hosts/$hostname/apt.txt,
# run install on those lines too.
HOSTNAME=$(hostname -s)
HOST_APT="$DOTFILES/hosts/$HOSTNAME/apt.txt"
[[ -f $HOST_APT ]] && {
# Load apt.txt, remove comments (even if trailing comment) and empty lines.
#
# Ignoring "Quote this to prevent word splitting."
# shellcheck disable=SC2046
sudo apt install -y $(
grep -vE '^\s*#' "$HOST_APT" \
| sed -e 's/#.*//' \
| tr '\n' ' '
)
}
sudo apt install \
-y $(
grep -vE '^\s*#' "$DOTFILES/tools/apt.txt" \
| sed -e 's/#.*//' \
| tr '\n' ' '
)
# Try this for an alternative way to install packages
# xargs -a <(awk '! /^ *(#|$)/' "$packagelist") -r -- sudo apt-get install -y
;;
# If there's a apt.txt file under hosts/$hostname/apt.txt,
# run install on those lines too.
HOSTNAME=$(hostname -s)
HOST_APT="$DOTFILES/hosts/$HOSTNAME/apt.txt"
[[ -f $HOST_APT ]] && {
# shellcheck disable=SC2046
sudo apt install -y $(
grep -vE '^\s*#' "$HOST_APT" \
| sed -e 's/#.*//' \
| tr '\n' ' '
)
}
update) sudo apt update ;;
upgrade) sudo apt upgrade -y ;;
autoremove) sudo apt autoremove -y ;;
clean) sudo apt clean ;;
*) menu_builder "$USAGE_PREFIX" "${MENU[@]}" ;;
esac
# Try this for an alternative way to install packages
# xargs -a <(awk '! /^ *(#|$)/' "$packagelist") -r -- sudo apt-get install -y
;;
update) sudo apt update ;;
upgrade) sudo apt upgrade -y ;;
autoremove) sudo apt autoremove -y ;;
clean) sudo apt clean ;;
*) menu_builder "$USAGE_PREFIX" "${MENU[@]}" ;;
esac
}
! x-have apt && menu_builder "$USAGE_PREFIX" "apt not available on this system"
}
# Handle documentation generation commands
section_docs()
{
USAGE_PREFIX="$SCRIPT docs <command>"
MENU=(
"all:Update all keybindings documentations"
"aerospace:Update aerospace keybindings documentation"
"tmux:Update tmux keybindings documentation"
"nvim:Update nvim keybindings documentation"
"wezterm:Update wezterm keybindings documentation"
@@ -522,10 +446,12 @@ section_docs()
case "$1" in
all)
$0 docs aerospace
$0 docs tmux
$0 docs nvim
$0 docs wezterm
;;
aerospace) bash "$DOTFILES/scripts/create-aerospace-keymaps.php" ;;
tmux) bash "$DOTFILES/local/bin/x-dfm-docs-xterm-keybindings" ;;
nvim) bash "$DOTFILES/scripts/create-nvim-keymaps.sh" ;;
wezterm) bash "$DOTFILES/scripts/create-wezterm-keymaps.sh" ;;
@@ -533,7 +459,6 @@ section_docs()
esac
}
# Handle dotfiles formatting and reset commands
section_dotfiles()
{
USAGE_PREFIX="$SCRIPT dotfiles <command>"
@@ -601,7 +526,6 @@ section_dotfiles()
esac
}
# Handle system check commands (arch, hostname)
section_check()
{
USAGE_PREFIX="$SCRIPT check <command>"
@@ -615,36 +539,50 @@ section_check()
case "$1" in
a | arch)
[[ $2 == "" ]] && echo "$X_ARCH" && return 0
[[ $X_ARCH == "$2" ]] && return 0 || return 1
[[ $2 == "" ]] && echo "$X_ARCH" && exit 0
[[ $X_ARCH == "$2" ]] && exit 0 || exit 1
;;
h | host | hostname)
[[ $2 == "" ]] && echo "$X_HOSTNAME" && return 0
[[ $X_HOSTNAME == "$2" ]] && return 0 || return 1
[[ $2 == "" ]] && echo "$X_HOSTNAME" && exit 0
[[ $X_HOSTNAME == "$2" ]] && exit 0 || exit 1
;;
*) menu_builder "$USAGE_PREFIX" "${MENU[@]}" ;;
esac
}
# Handle install script execution
section_scripts()
{
USAGE_PREFIX="$SCRIPT scripts <command>"
# Get description from a file
get_script_description()
{
local file
local desc
file="$1"
desc=$(sed -n '/@description/s/.*@description *\(.*\)/\1/p' "$file" | head -1)
echo "${desc:-No description available}"
}
# Collect scripts and their descriptions
local menu_items=()
declare -A SCRIPT_MENU
for script in "$DOTFILES/scripts/install-"*.sh; do
if [ -f "$script" ]; then
name=$(basename "$script" .sh | sed 's/install-//')
desc=$(get_script_description "$script")
menu_items+=("$name:$desc")
SCRIPT_MENU[$name]="$desc"
fi
done
case "$1" in
"")
# Show the menu
local menu_items=()
for name in "${!SCRIPT_MENU[@]}"; do
menu_items+=("$name:${SCRIPT_MENU[$name]}")
done
menu_builder "$USAGE_PREFIX" "${menu_items[@]}"
;;
*)
@@ -676,7 +614,7 @@ section_tests()
echo " $i"
done
;;
msgr)
msg)
# shellcheck disable=SC1010
msgr done "msgr done"
msgr done_suffix "msgr done_suffix"
@@ -696,12 +634,11 @@ section_tests()
esac
}
# Display main usage information for all sections
usage()
{
echo ""
msgr prompt "Usage: $SCRIPT <section> <command>"
echo " Empty <command> prints <section> help."
echo $" Empty <command> prints <section> help."
echo ""
section_install
echo ""
@@ -720,11 +657,10 @@ usage()
section_helpers
}
# Parse section argument and dispatch to handler
main()
{
SECTION="${1:-}"
[[ $# -gt 0 ]] && shift
SECTION="$1"
shift
# The main loop. The first keyword after $0 triggers section, or help.
case "$SECTION" in
install) section_install "$@" ;;
@@ -736,7 +672,7 @@ main()
docs) section_docs "$@" ;;
scripts) section_scripts "$@" ;;
tests) section_tests "$@" ;;
*) usage && return 0 ;;
*) usage && exit 0 ;;
esac
}

Some files were not shown because too many files have changed in this diff Show More