mirror of
https://github.com/ivuorinen/dotfiles.git
synced 2026-01-27 21:45:41 +00:00
Compare commits
14 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| fb97f10f64 | |||
| 6dbbc439b3 | |||
| 368fbfc7c8 | |||
| d6d5a8ca36 | |||
|
|
d65c25819f | ||
|
|
62c620efad | ||
| 07fe18af75 | |||
|
|
29d3676b38 | ||
| 0b9e1803d4 | |||
|
|
c45ad9710d | ||
| cf7ca2109f | |||
| 1531647e01 | |||
|
|
15aff17f03 | ||
|
|
42a5b79048 |
5
.gitattributes
vendored
5
.gitattributes
vendored
@@ -85,6 +85,7 @@ LICENSE text
|
||||
NEWS text
|
||||
readme text
|
||||
*README* text
|
||||
# Files literally named "TODO", not a todo list item
|
||||
TODO text
|
||||
|
||||
# Templates
|
||||
@@ -122,7 +123,8 @@ package.json text eol=lf
|
||||
package-lock.json text eol=lf -diff
|
||||
pnpm-lock.yaml text eol=lf -diff
|
||||
.prettierrc text
|
||||
yarn.lock text -diff
|
||||
# Ensure yarn.lock shows textual diffs
|
||||
yarn.lock text eol=lf
|
||||
*.toml text
|
||||
*.yaml text
|
||||
*.yml text
|
||||
@@ -251,3 +253,4 @@ install text eol=lf diff=shell
|
||||
*.snippets text eol=lf
|
||||
*.theme text eol=lf
|
||||
*.yamlfmt text eol=lf
|
||||
*.bats text eol=lf diff=shell
|
||||
|
||||
30
.github/AGENTS.md
vendored
Normal file
30
.github/AGENTS.md
vendored
Normal file
@@ -0,0 +1,30 @@
|
||||
# Guidelines for AI contributors
|
||||
|
||||
These instructions help language models work with this repository.
|
||||
|
||||
## Setup
|
||||
|
||||
1. Run `yarn install` to get linting tools and the Bats test framework.
|
||||
|
||||
## Formatting
|
||||
|
||||
- Format code and docs with Prettier and markdownlint:
|
||||
|
||||
```bash
|
||||
yarn fix:prettier
|
||||
yarn fix:markdown
|
||||
```
|
||||
|
||||
- Shell scripts should pass `shellcheck`.
|
||||
|
||||
## Testing
|
||||
|
||||
- When code changes, run `yarn test` to execute Bats tests.
|
||||
- If only comments or documentation change, tests may be skipped.
|
||||
|
||||
## Commits and PRs
|
||||
|
||||
- Use Semantic Commit messages: `type(scope): summary`.
|
||||
- Keep PR titles in the same format.
|
||||
|
||||
<!-- vim: set ft=markdown spell spelllang=en_us cc=80 : -->
|
||||
8
.github/CODE_OF_CONDUCT.md
vendored
8
.github/CODE_OF_CONDUCT.md
vendored
@@ -60,7 +60,7 @@ representative at an online or offline event.
|
||||
|
||||
Instances of abusive, harassing, or otherwise unacceptable behavior may be
|
||||
reported to the community leaders responsible for enforcement at
|
||||
ismo@ivuorinen.net.
|
||||
<ismo@ivuorinen.net>.
|
||||
All complaints will be reviewed and investigated promptly and fairly.
|
||||
|
||||
All community leaders are obligated to respect the privacy and security of the
|
||||
@@ -116,7 +116,7 @@ the community.
|
||||
|
||||
This Code of Conduct is adapted from the [Contributor Covenant][homepage],
|
||||
version 2.0, available at
|
||||
https://www.contributor-covenant.org/version/2/0/code_of_conduct.html.
|
||||
<https://www.contributor-covenant.org/version/2/0/code_of_conduct.html>.
|
||||
|
||||
Community Impact Guidelines were inspired by [Mozilla's code of conduct
|
||||
enforcement ladder](https://github.com/mozilla/diversity).
|
||||
@@ -124,5 +124,5 @@ enforcement ladder](https://github.com/mozilla/diversity).
|
||||
[homepage]: https://www.contributor-covenant.org
|
||||
|
||||
For answers to common questions about this code of conduct, see the FAQ at
|
||||
https://www.contributor-covenant.org/faq. Translations are available at
|
||||
https://www.contributor-covenant.org/translations.
|
||||
<https://www.contributor-covenant.org/faq>. Translations are available at
|
||||
<https://www.contributor-covenant.org/translations>.
|
||||
|
||||
46
.github/README.md
vendored
46
.github/README.md
vendored
@@ -43,6 +43,12 @@ see what interesting stuff you've done with it. Sharing is caring.
|
||||
| `local/bin` | Helper scripts that I've collected or wrote. |
|
||||
| `scripts` | Setup scripts. |
|
||||
|
||||
### Host specific configuration
|
||||
|
||||
Configurations under `hosts/<hostname>` are applied only when running on the
|
||||
matching machine. Each host folder contains its own `install.conf.yaml` that
|
||||
is processed by Dotbot during installation.
|
||||
|
||||
### dotfile folders
|
||||
|
||||
| Repo | Destination | Description |
|
||||
@@ -58,6 +64,21 @@ see what interesting stuff you've done with it. Sharing is caring.
|
||||
|
||||
Running `dfm` gives you a list of available commands.
|
||||
|
||||
#### Documentation generation
|
||||
|
||||
`dfm docs` generates Markdown documentation under the `docs/` directory. The
|
||||
subcommands are:
|
||||
|
||||
```bash
|
||||
dfm docs alias # regenerate alias table
|
||||
dfm docs folders # document interesting folders
|
||||
dfm docs keybindings # update keybinding docs for tmux, nvim and others
|
||||
dfm docs all # run every docs task
|
||||
```
|
||||
|
||||
The `docs/` folder contains generated cheat sheets, keybindings and other
|
||||
reference files. New documentation can be added without modifying this README.
|
||||
|
||||
## Configuration
|
||||
|
||||
The folder structure follows [XDG Base Directory Specification][xdg] where possible.
|
||||
@@ -73,6 +94,31 @@ The folder structure follows [XDG Base Directory Specification][xdg] where possi
|
||||
|
||||
Please see [docs/folders.md][docs-folders] for more information.
|
||||
|
||||
## Managing submodules
|
||||
|
||||
This repository uses Git submodules for external dependencies. After cloning,
|
||||
run:
|
||||
|
||||
```bash
|
||||
git submodule update --init --recursive
|
||||
```
|
||||
|
||||
To pull submodule updates later use:
|
||||
|
||||
```bash
|
||||
git submodule update --remote --merge
|
||||
```
|
||||
|
||||
The helper script `add-submodules.sh` documents how each submodule is added and
|
||||
configured. Submodules are automatically updated by the
|
||||
[update-submodules.yml](.github/workflows/update-submodules.yml) workflow.
|
||||
|
||||
## Testing
|
||||
|
||||
Shell scripts under `local/bin` are validated with [Bats](https://github.com/bats-core/bats-core).
|
||||
Run `yarn test` to execute every test file. Bats is installed as a development
|
||||
dependency, so run `yarn install` first if needed.
|
||||
|
||||
[dfm]: https://github.com/ivuorinen/dotfiles/blob/main/local/bin/dfm
|
||||
[docs-folders]: https://github.com/ivuorinen/dotfiles/blob/main/docs/folders.md
|
||||
[xdg]: https://specifications.freedesktop.org/basedir-spec/basedir-spec-latest.html
|
||||
|
||||
2
.github/workflows/changelog.yml
vendored
2
.github/workflows/changelog.yml
vendored
@@ -1,5 +1,5 @@
|
||||
---
|
||||
# yaml-language-server: https://json.schemastore.org/github-workflow.json
|
||||
# $schema: "https://json.schemastore.org/github-workflow.json"
|
||||
name: Debug Changelog # Workflow name displayed on GitHub
|
||||
|
||||
on:
|
||||
|
||||
66
.github/workflows/linters.yml
vendored
66
.github/workflows/linters.yml
vendored
@@ -1,8 +1,10 @@
|
||||
---
|
||||
# yaml-language-server: https://json.schemastore.org/github-workflow.json
|
||||
name: Reviewdog
|
||||
# yaml-language-server: $schema=https://json.schemastore.org/github-workflow.json
|
||||
name: Lint Code Base
|
||||
|
||||
on: [push]
|
||||
on:
|
||||
pull_request:
|
||||
branches: [master, main]
|
||||
|
||||
concurrency:
|
||||
group: ${{ github.workflow }}-${{ github.ref }}
|
||||
@@ -11,50 +13,24 @@ concurrency:
|
||||
permissions: read-all
|
||||
|
||||
jobs:
|
||||
linters:
|
||||
name: Linters
|
||||
|
||||
runs-on: self-hosted
|
||||
|
||||
permissions: write-all
|
||||
Linter:
|
||||
name: PR Lint
|
||||
runs-on: ubuntu-latest
|
||||
timeout-minutes: 15
|
||||
permissions:
|
||||
statuses: write
|
||||
contents: read
|
||||
packages: read
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
|
||||
- name: Checkout
|
||||
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
|
||||
|
||||
- name: Setup Node.js environment
|
||||
uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4.4.0
|
||||
|
||||
- name: GitHub Actions
|
||||
uses: reviewdog/action-actionlint@a5524e1c19e62881d79c1f1b9b6f09f16356e281 # v1.65.2
|
||||
- name: Yarn Lock Changes
|
||||
uses: Simek/yarn-lock-changes@34017425198654c20162a4dfd4f238fbece9636f # v0.12.1
|
||||
with:
|
||||
github_token: ${{ secrets.GITHUB_TOKEN }}
|
||||
reporter: github-pr-review
|
||||
token: ${{ secrets.GITHUB_TOKEN }}
|
||||
|
||||
- name: detect-secrets
|
||||
uses: reviewdog/action-detect-secrets@master
|
||||
with:
|
||||
github_token: ${{ secrets.GITHUB_TOKEN }}
|
||||
reporter: github-pr-review
|
||||
|
||||
- name: markdownlint
|
||||
uses: reviewdog/action-markdownlint@3667398db9118d7e78f7a63d10e26ce454ba5f58 # v0.26.2
|
||||
with:
|
||||
github_token: ${{ secrets.GITHUB_TOKEN }}
|
||||
reporter: github-pr-review
|
||||
|
||||
- name: shfmt
|
||||
uses: reviewdog/action-shfmt@d8f080930b9be5847b4f97e9f4122b81a82aaeac # v1.0.4
|
||||
with:
|
||||
github_token: ${{ secrets.GITHUB_TOKEN }}
|
||||
shfmt_flags: |
|
||||
--find
|
||||
--list
|
||||
--write
|
||||
--diff
|
||||
--simplify
|
||||
--language-dialect bash
|
||||
--indent 2
|
||||
--binary-next-line
|
||||
--case-indent
|
||||
--space-redirects
|
||||
--func-next-line
|
||||
- name: Run PR Lint
|
||||
# https://github.com/ivuorinen/actions
|
||||
uses: ivuorinen/actions/pr-lint@c0f919957eb60743682a6e0cd6d454fd4b142ac9 # 25.6.30
|
||||
2
.github/workflows/new-release.yml
vendored
2
.github/workflows/new-release.yml
vendored
@@ -1,5 +1,5 @@
|
||||
---
|
||||
# yaml-language-server: https://json.schemastore.org/github-workflow.json
|
||||
# $schema: "https://json.schemastore.org/github-workflow.json"
|
||||
name: Release Daily State
|
||||
|
||||
on:
|
||||
|
||||
4
.github/workflows/pre-commit-autoupdate.yml
vendored
4
.github/workflows/pre-commit-autoupdate.yml
vendored
@@ -1,5 +1,5 @@
|
||||
---
|
||||
# yaml-language-server: https://json.schemastore.org/github-workflow.json
|
||||
# $schema: "https://json.schemastore.org/github-workflow.json"
|
||||
name: Pre-commit autoupdate
|
||||
|
||||
on:
|
||||
@@ -16,7 +16,7 @@ permissions: read-all
|
||||
|
||||
jobs:
|
||||
auto-update:
|
||||
runs-on: ubuntu-latest
|
||||
runs-on: self-hosted
|
||||
|
||||
permissions:
|
||||
contents: write
|
||||
|
||||
2
.github/workflows/semantic-pr.yml
vendored
2
.github/workflows/semantic-pr.yml
vendored
@@ -1,5 +1,5 @@
|
||||
---
|
||||
# yaml-language-server: https://json.schemastore.org/github-workflow.json
|
||||
# $schema: "https://json.schemastore.org/github-workflow.json"
|
||||
name: Semantic PR
|
||||
|
||||
on:
|
||||
|
||||
6
.github/workflows/sync-labels.yml
vendored
6
.github/workflows/sync-labels.yml
vendored
@@ -1,5 +1,5 @@
|
||||
---
|
||||
# yaml-language-server: https://json.schemastore.org/github-workflow.json
|
||||
# $schema: "https://json.schemastore.org/github-workflow.json"
|
||||
name: Sync labels
|
||||
|
||||
# yamllint disable-line rule:truthy
|
||||
@@ -23,10 +23,10 @@ permissions: read-all
|
||||
|
||||
jobs:
|
||||
SyncLabels:
|
||||
runs-on: ubuntu-latest
|
||||
runs-on: self-hosted
|
||||
|
||||
permissions:
|
||||
issues: write
|
||||
|
||||
steps:
|
||||
- uses: ivuorinen/actions/sync-labels@main
|
||||
- uses: ivuorinen/actions/sync-labels@c0f919957eb60743682a6e0cd6d454fd4b142ac9 # 25.6.30
|
||||
|
||||
2
.github/workflows/update-submodules.yml
vendored
2
.github/workflows/update-submodules.yml
vendored
@@ -1,5 +1,5 @@
|
||||
---
|
||||
# yaml-language-server: https://json.schemastore.org/github-workflow.json
|
||||
# $schema: "https://json.schemastore.org/github-workflow.json"
|
||||
name: Update submodules
|
||||
|
||||
on:
|
||||
|
||||
29
.mega-linter.yml
Normal file
29
.mega-linter.yml
Normal file
@@ -0,0 +1,29 @@
|
||||
---
|
||||
# Configuration file for MegaLinter
|
||||
# See all available variables at
|
||||
# https://megalinter.io/configuration/ and in linters documentation
|
||||
|
||||
APPLY_FIXES: all
|
||||
SHOW_ELAPSED_TIME: false # Show elapsed time at the end of MegaLinter run
|
||||
PARALLEL: true
|
||||
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
|
||||
|
||||
YAML_YAMLLINT_CONFIG_FILE: .yamllint.yml
|
||||
MARKDOWN_MARKDOWNLINT_CONFIG_FILE: .markdownlint.json
|
||||
JAVASCRIPT_ES_CONFIG_FILE: .eslintrc.json
|
||||
TYPESCRIPT_ES_CONFIG_FILE: .eslintrc.json
|
||||
|
||||
FILTER_REGEX_EXCLUDE: >
|
||||
(node_modules|tools|config/cheat/cheatsheets/community|config/cheat/cheatsheets/tldr|config/fzf|config/zsh|config/tmux/plugins)
|
||||
|
||||
@@ -49,7 +49,7 @@ repos:
|
||||
- id: actionlint
|
||||
|
||||
- repo: https://github.com/renovatebot/pre-commit-hooks
|
||||
rev: 41.1.4
|
||||
rev: 41.23.2
|
||||
hooks:
|
||||
- id: renovate-config-validator
|
||||
|
||||
|
||||
8
config/fish/completions/fzf_configure_bindings.fish
Normal file
8
config/fish/completions/fzf_configure_bindings.fish
Normal file
@@ -0,0 +1,8 @@
|
||||
complete fzf_configure_bindings --no-files
|
||||
complete fzf_configure_bindings --long help --short h --description "Print help" --condition "not __fish_seen_argument --help -h"
|
||||
complete fzf_configure_bindings --long directory --description "Change the key binding for Search Directory" --condition "not __fish_seen_argument --directory"
|
||||
complete fzf_configure_bindings --long git_log --description "Change the key binding for Search Git Log" --condition "not __fish_seen_argument --git_log"
|
||||
complete fzf_configure_bindings --long git_status --description "Change the key binding for Search Git Status" --condition "not __fish_seen_argument --git_status"
|
||||
complete fzf_configure_bindings --long history --description "Change the key binding for Search History" --condition "not __fish_seen_argument --history"
|
||||
complete fzf_configure_bindings --long processes --description "Change the key binding for Search Processes" --condition "not __fish_seen_argument --processes"
|
||||
complete fzf_configure_bindings --long variables --description "Change the key binding for Search Variables" --condition "not __fish_seen_argument --variables"
|
||||
28
config/fish/conf.d/fzf.fish
Normal file
28
config/fish/conf.d/fzf.fish
Normal file
@@ -0,0 +1,28 @@
|
||||
# fzf.fish is only meant to be used in interactive mode. If not in interactive mode and not in CI, skip the config to speed up shell startup
|
||||
if not status is-interactive && test "$CI" != true
|
||||
exit
|
||||
end
|
||||
|
||||
# Because of scoping rules, to capture the shell variables exactly as they are, we must read
|
||||
# them before even executing _fzf_search_variables. We use psub to store the
|
||||
# variables' info in temporary files and pass in the filenames as arguments.
|
||||
# This variable is global so that it can be referenced by fzf_configure_bindings and in tests
|
||||
set --global _fzf_search_vars_command '_fzf_search_variables (set --show | psub) (set --names | psub)'
|
||||
|
||||
|
||||
# Install the default bindings, which are mnemonic and minimally conflict with fish's preset bindings
|
||||
fzf_configure_bindings
|
||||
|
||||
# Doesn't erase autoloaded _fzf_* functions because they are not easily accessible once key bindings are erased
|
||||
function _fzf_uninstall --on-event fzf_uninstall
|
||||
_fzf_uninstall_bindings
|
||||
|
||||
set --erase _fzf_search_vars_command
|
||||
functions --erase _fzf_uninstall _fzf_migration_message _fzf_uninstall_bindings fzf_configure_bindings
|
||||
complete --erase fzf_configure_bindings
|
||||
|
||||
set_color cyan
|
||||
echo "fzf.fish uninstalled."
|
||||
echo "You may need to manually remove fzf_configure_bindings from your config.fish if you were using custom key bindings."
|
||||
set_color normal
|
||||
end
|
||||
@@ -8,3 +8,4 @@ edc/bass
|
||||
meaningful-ooo/sponge
|
||||
nickeb96/puffer-fish
|
||||
jgusta/paths
|
||||
patrickf1/fzf.fish
|
||||
|
||||
43
config/fish/functions/_fzf_configure_bindings_help.fish
Normal file
43
config/fish/functions/_fzf_configure_bindings_help.fish
Normal file
@@ -0,0 +1,43 @@
|
||||
function _fzf_configure_bindings_help --description "Prints the help message for fzf_configure_bindings."
|
||||
echo "\
|
||||
USAGE:
|
||||
fzf_configure_bindings [--COMMAND=[KEY_SEQUENCE]...]
|
||||
|
||||
DESCRIPTION
|
||||
fzf_configure_bindings installs key bindings for fzf.fish's commands and erases any bindings it
|
||||
previously installed. It installs bindings for both default and insert modes. fzf.fish executes
|
||||
it without options on fish startup to install the out-of-the-box key bindings.
|
||||
|
||||
By default, commands are bound to a mnemonic key sequence, shown below. Each command's binding
|
||||
can be configured using a namesake corresponding option:
|
||||
COMMAND | DEFAULT KEY SEQUENCE | CORRESPONDING OPTION
|
||||
Search Directory | Ctrl+Alt+F (F for file) | --directory
|
||||
Search Git Log | Ctrl+Alt+L (L for log) | --git_log
|
||||
Search Git Status | Ctrl+Alt+S (S for status) | --git_status
|
||||
Search History | Ctrl+R (R for reverse) | --history
|
||||
Search Processes | Ctrl+Alt+P (P for process) | --processes
|
||||
Search Variables | Ctrl+V (V for variable) | --variables
|
||||
Override a command's binding by specifying its corresponding option with the desired key
|
||||
sequence. Disable a command's binding by specifying its corresponding option with no value.
|
||||
|
||||
Because fzf_configure_bindings erases bindings it previously installed, it can be cleanly
|
||||
executed multiple times. Once the desired fzf_configure_bindings command has been found, add it
|
||||
to your config.fish in order to persist the customized bindings.
|
||||
|
||||
In terms of validation, fzf_configure_bindings fails if passed unknown options. It expects an
|
||||
equals sign between an option's name and value. However, it does not validate key sequences.
|
||||
|
||||
Pass -h or --help to print this help message and exit.
|
||||
|
||||
EXAMPLES
|
||||
Default bindings but bind Search Directory to Ctrl+F and Search Variables to Ctrl+Alt+V
|
||||
\$ fzf_configure_bindings --directory=\cf --variables=\e\cv
|
||||
Default bindings but disable Search History
|
||||
\$ fzf_configure_bindings --history=
|
||||
An agglomeration of different options
|
||||
\$ fzf_configure_bindings --git_status=\cg --history=\ch --variables= --processes=
|
||||
|
||||
SEE Also
|
||||
To learn more about fish key bindings, see bind(1) and fish_key_reader(1).
|
||||
"
|
||||
end
|
||||
15
config/fish/functions/_fzf_extract_var_info.fish
Normal file
15
config/fish/functions/_fzf_extract_var_info.fish
Normal file
@@ -0,0 +1,15 @@
|
||||
# helper function for _fzf_search_variables
|
||||
function _fzf_extract_var_info --argument-names variable_name set_show_output --description "Extract and reformat lines pertaining to \$variable_name from \$set_show_output."
|
||||
# Extract only the lines about the variable, all of which begin with either
|
||||
# $variable_name: ...or... $variable_name[
|
||||
string match --regex "^\\\$$variable_name(?::|\[).*" <$set_show_output |
|
||||
|
||||
# Strip the variable name prefix, including ": " for scope info lines
|
||||
string replace --regex "^\\\$$variable_name(?:: )?" '' |
|
||||
|
||||
# Distill the lines of values, replacing...
|
||||
# [1]: |value|
|
||||
# ...with...
|
||||
# [1] value
|
||||
string replace --regex ": \|(.*)\|" ' $1'
|
||||
end
|
||||
49
config/fish/functions/_fzf_preview_changed_file.fish
Normal file
49
config/fish/functions/_fzf_preview_changed_file.fish
Normal file
@@ -0,0 +1,49 @@
|
||||
# helper for _fzf_search_git_status
|
||||
# arg should be a line from git status --short, e.g.
|
||||
# MM functions/_fzf_preview_changed_file.fish
|
||||
# D README.md
|
||||
# R LICENSE -> "New License"
|
||||
function _fzf_preview_changed_file --argument-names path_status --description "Show the git diff of the given file."
|
||||
# remove quotes because they'll be interpreted literally by git diff
|
||||
# no need to requote when referencing $path because fish does not perform word splitting
|
||||
# https://fishshell.com/docs/current/fish_for_bash_users.html
|
||||
set -f path (string unescape (string sub --start 4 $path_status))
|
||||
# first letter of short format shows index, second letter shows working tree
|
||||
# https://git-scm.com/docs/git-status/2.35.0#_short_format
|
||||
set -f index_status (string sub --length 1 $path_status)
|
||||
set -f working_tree_status (string sub --start 2 --length 1 $path_status)
|
||||
|
||||
set -f diff_opts --color=always
|
||||
|
||||
if test $index_status = '?'
|
||||
_fzf_report_diff_type Untracked
|
||||
_fzf_preview_file $path
|
||||
else if contains {$index_status}$working_tree_status DD AU UD UA DU AA UU
|
||||
# Unmerged statuses taken directly from git status help's short format table
|
||||
# Unmerged statuses are mutually exclusive with other statuses, so if we see
|
||||
# these, then safe to assume the path is unmerged
|
||||
_fzf_report_diff_type Unmerged
|
||||
git diff $diff_opts -- $path
|
||||
else
|
||||
if test $index_status != ' '
|
||||
_fzf_report_diff_type Staged
|
||||
|
||||
# renames are only detected in the index, never working tree, so only need to test for it here
|
||||
# https://stackoverflow.com/questions/73954214
|
||||
if test $index_status = R
|
||||
# diff the post-rename path with the original path, otherwise the diff will show the entire file as being added
|
||||
set -f orig_and_new_path (string split --max 1 -- ' -> ' $path)
|
||||
git diff --staged $diff_opts -- $orig_and_new_path[1] $orig_and_new_path[2]
|
||||
# path currently has the form of "original -> current", so we need to correct it before it's used below
|
||||
set path $orig_and_new_path[2]
|
||||
else
|
||||
git diff --staged $diff_opts -- $path
|
||||
end
|
||||
end
|
||||
|
||||
if test $working_tree_status != ' '
|
||||
_fzf_report_diff_type Unstaged
|
||||
git diff $diff_opts -- $path
|
||||
end
|
||||
end
|
||||
end
|
||||
43
config/fish/functions/_fzf_preview_file.fish
Normal file
43
config/fish/functions/_fzf_preview_file.fish
Normal file
@@ -0,0 +1,43 @@
|
||||
# helper function for _fzf_search_directory and _fzf_search_git_status
|
||||
function _fzf_preview_file --description "Print a preview for the given file based on its file type."
|
||||
# because there's no way to guarantee that _fzf_search_directory passes the path to _fzf_preview_file
|
||||
# as one argument, we collect all the arguments into one single variable and treat that as the path
|
||||
set -f file_path $argv
|
||||
|
||||
if test -L "$file_path" # symlink
|
||||
# notify user and recurse on the target of the symlink, which can be any of these file types
|
||||
set -l target_path (realpath "$file_path")
|
||||
|
||||
set_color yellow
|
||||
echo "'$file_path' is a symlink to '$target_path'."
|
||||
set_color normal
|
||||
|
||||
_fzf_preview_file "$target_path"
|
||||
else if test -f "$file_path" # regular file
|
||||
if set --query fzf_preview_file_cmd
|
||||
# need to escape quotes to make sure eval receives file_path as a single arg
|
||||
eval "$fzf_preview_file_cmd '$file_path'"
|
||||
else
|
||||
bat --style=numbers --color=always "$file_path"
|
||||
end
|
||||
else if test -d "$file_path" # directory
|
||||
if set --query fzf_preview_dir_cmd
|
||||
# see above
|
||||
eval "$fzf_preview_dir_cmd '$file_path'"
|
||||
else
|
||||
# -A list hidden files as well, except for . and ..
|
||||
# -F helps classify files by appending symbols after the file name
|
||||
command ls -A -F "$file_path"
|
||||
end
|
||||
else if test -c "$file_path"
|
||||
_fzf_report_file_type "$file_path" "character device file"
|
||||
else if test -b "$file_path"
|
||||
_fzf_report_file_type "$file_path" "block device file"
|
||||
else if test -S "$file_path"
|
||||
_fzf_report_file_type "$file_path" socket
|
||||
else if test -p "$file_path"
|
||||
_fzf_report_file_type "$file_path" "named pipe"
|
||||
else
|
||||
echo "$file_path doesn't exist." >&2
|
||||
end
|
||||
end
|
||||
18
config/fish/functions/_fzf_report_diff_type.fish
Normal file
18
config/fish/functions/_fzf_report_diff_type.fish
Normal file
@@ -0,0 +1,18 @@
|
||||
# helper for _fzf_preview_changed_file
|
||||
# prints out something like
|
||||
# ╭────────╮
|
||||
# │ Staged │
|
||||
# ╰────────╯
|
||||
function _fzf_report_diff_type --argument-names diff_type --description "Print a distinct colored header meant to preface a git patch."
|
||||
# number of "-" to draw is the length of the string to box + 2 for padding
|
||||
set -f repeat_count (math 2 + (string length $diff_type))
|
||||
set -f line (string repeat --count $repeat_count ─)
|
||||
set -f top_border ╭$line╮
|
||||
set -f btm_border ╰$line╯
|
||||
|
||||
set_color yellow
|
||||
echo $top_border
|
||||
echo "│ $diff_type │"
|
||||
echo $btm_border
|
||||
set_color normal
|
||||
end
|
||||
6
config/fish/functions/_fzf_report_file_type.fish
Normal file
6
config/fish/functions/_fzf_report_file_type.fish
Normal file
@@ -0,0 +1,6 @@
|
||||
# helper function for _fzf_preview_file
|
||||
function _fzf_report_file_type --argument-names file_path file_type --description "Explain the file type for a file."
|
||||
set_color red
|
||||
echo "Cannot preview '$file_path': it is a $file_type."
|
||||
set_color normal
|
||||
end
|
||||
33
config/fish/functions/_fzf_search_directory.fish
Normal file
33
config/fish/functions/_fzf_search_directory.fish
Normal file
@@ -0,0 +1,33 @@
|
||||
function _fzf_search_directory --description "Search the current directory. Replace the current token with the selected file paths."
|
||||
# Directly use fd binary to avoid output buffering delay caused by a fd alias, if any.
|
||||
# Debian-based distros install fd as fdfind and the fd package is something else, so
|
||||
# check for fdfind first. Fall back to "fd" for a clear error message.
|
||||
set -f fd_cmd (command -v fdfind || command -v fd || echo "fd")
|
||||
set -f --append fd_cmd --color=always $fzf_fd_opts
|
||||
|
||||
set -f fzf_arguments --multi --ansi $fzf_directory_opts
|
||||
set -f token (commandline --current-token)
|
||||
# expand any variables or leading tilde (~) in the token
|
||||
set -f expanded_token (eval echo -- $token)
|
||||
# unescape token because it's already quoted so backslashes will mess up the path
|
||||
set -f unescaped_exp_token (string unescape -- $expanded_token)
|
||||
|
||||
# If the current token is a directory and has a trailing slash,
|
||||
# then use it as fd's base directory.
|
||||
if string match --quiet -- "*/" $unescaped_exp_token && test -d "$unescaped_exp_token"
|
||||
set --append fd_cmd --base-directory=$unescaped_exp_token
|
||||
# use the directory name as fzf's prompt to indicate the search is limited to that directory
|
||||
set --prepend fzf_arguments --prompt="Directory $unescaped_exp_token> " --preview="_fzf_preview_file $expanded_token{}"
|
||||
set -f file_paths_selected $unescaped_exp_token($fd_cmd 2>/dev/null | _fzf_wrapper $fzf_arguments)
|
||||
else
|
||||
set --prepend fzf_arguments --prompt="Directory> " --query="$unescaped_exp_token" --preview='_fzf_preview_file {}'
|
||||
set -f file_paths_selected ($fd_cmd 2>/dev/null | _fzf_wrapper $fzf_arguments)
|
||||
end
|
||||
|
||||
|
||||
if test $status -eq 0
|
||||
commandline --current-token --replace -- (string escape -- $file_paths_selected | string join ' ')
|
||||
end
|
||||
|
||||
commandline --function repaint
|
||||
end
|
||||
36
config/fish/functions/_fzf_search_git_log.fish
Normal file
36
config/fish/functions/_fzf_search_git_log.fish
Normal file
@@ -0,0 +1,36 @@
|
||||
function _fzf_search_git_log --description "Search the output of git log and preview commits. Replace the current token with the selected commit hash."
|
||||
if not git rev-parse --git-dir >/dev/null 2>&1
|
||||
echo '_fzf_search_git_log: Not in a git repository.' >&2
|
||||
else
|
||||
if not set --query fzf_git_log_format
|
||||
# %h gives you the abbreviated commit hash, which is useful for saving screen space, but we will have to expand it later below
|
||||
set -f fzf_git_log_format '%C(bold blue)%h%C(reset) - %C(cyan)%ad%C(reset) %C(yellow)%d%C(reset) %C(normal)%s%C(reset) %C(dim normal)[%an]%C(reset)'
|
||||
end
|
||||
|
||||
set -f preview_cmd 'git show --color=always --stat --patch {1}'
|
||||
if set --query fzf_diff_highlighter
|
||||
set preview_cmd "$preview_cmd | $fzf_diff_highlighter"
|
||||
end
|
||||
|
||||
set -f selected_log_lines (
|
||||
git log --no-show-signature --color=always --format=format:$fzf_git_log_format --date=short | \
|
||||
_fzf_wrapper --ansi \
|
||||
--multi \
|
||||
--scheme=history \
|
||||
--prompt="Git Log> " \
|
||||
--preview=$preview_cmd \
|
||||
--query=(commandline --current-token) \
|
||||
$fzf_git_log_opts
|
||||
)
|
||||
if test $status -eq 0
|
||||
for line in $selected_log_lines
|
||||
set -f abbreviated_commit_hash (string split --field 1 " " $line)
|
||||
set -f full_commit_hash (git rev-parse $abbreviated_commit_hash)
|
||||
set -f --append commit_hashes $full_commit_hash
|
||||
end
|
||||
commandline --current-token --replace (string join ' ' $commit_hashes)
|
||||
end
|
||||
end
|
||||
|
||||
commandline --function repaint
|
||||
end
|
||||
41
config/fish/functions/_fzf_search_git_status.fish
Normal file
41
config/fish/functions/_fzf_search_git_status.fish
Normal file
@@ -0,0 +1,41 @@
|
||||
function _fzf_search_git_status --description "Search the output of git status. Replace the current token with the selected file paths."
|
||||
if not git rev-parse --git-dir >/dev/null 2>&1
|
||||
echo '_fzf_search_git_status: Not in a git repository.' >&2
|
||||
else
|
||||
set -f preview_cmd '_fzf_preview_changed_file {}'
|
||||
if set --query fzf_diff_highlighter
|
||||
set preview_cmd "$preview_cmd | $fzf_diff_highlighter"
|
||||
end
|
||||
|
||||
set -f selected_paths (
|
||||
# Pass configuration color.status=always to force status to use colors even though output is sent to a pipe
|
||||
git -c color.status=always status --short |
|
||||
_fzf_wrapper --ansi \
|
||||
--multi \
|
||||
--prompt="Git Status> " \
|
||||
--query=(commandline --current-token) \
|
||||
--preview=$preview_cmd \
|
||||
--nth="2.." \
|
||||
$fzf_git_status_opts
|
||||
)
|
||||
if test $status -eq 0
|
||||
# git status --short automatically escapes the paths of most files for us so not going to bother trying to handle
|
||||
# the few edges cases of weird file names that should be extremely rare (e.g. "this;needs;escaping")
|
||||
set -f cleaned_paths
|
||||
|
||||
for path in $selected_paths
|
||||
if test (string sub --length 1 $path) = R
|
||||
# path has been renamed and looks like "R LICENSE -> LICENSE.md"
|
||||
# extract the path to use from after the arrow
|
||||
set --append cleaned_paths (string split -- "-> " $path)[-1]
|
||||
else
|
||||
set --append cleaned_paths (string sub --start=4 $path)
|
||||
end
|
||||
end
|
||||
|
||||
commandline --current-token --replace -- (string join ' ' $cleaned_paths)
|
||||
end
|
||||
end
|
||||
|
||||
commandline --function repaint
|
||||
end
|
||||
39
config/fish/functions/_fzf_search_history.fish
Normal file
39
config/fish/functions/_fzf_search_history.fish
Normal file
@@ -0,0 +1,39 @@
|
||||
function _fzf_search_history --description "Search command history. Replace the command line with the selected command."
|
||||
# history merge incorporates history changes from other fish sessions
|
||||
# it errors out if called in private mode
|
||||
if test -z "$fish_private_mode"
|
||||
builtin history merge
|
||||
end
|
||||
|
||||
if not set --query fzf_history_time_format
|
||||
# Reference https://devhints.io/strftime to understand strftime format symbols
|
||||
set -f fzf_history_time_format "%m-%d %H:%M:%S"
|
||||
end
|
||||
|
||||
# Delinate time from command in history entries using the vertical box drawing char (U+2502).
|
||||
# Then, to get raw command from history entries, delete everything up to it. The ? on regex is
|
||||
# necessary to make regex non-greedy so it won't match into commands containing the char.
|
||||
set -f time_prefix_regex '^.*? │ '
|
||||
# Delinate commands throughout pipeline using null rather than newlines because commands can be multi-line
|
||||
set -f commands_selected (
|
||||
builtin history --null --show-time="$fzf_history_time_format │ " |
|
||||
_fzf_wrapper --read0 \
|
||||
--print0 \
|
||||
--multi \
|
||||
--scheme=history \
|
||||
--prompt="History> " \
|
||||
--query=(commandline) \
|
||||
--preview="string replace --regex '$time_prefix_regex' '' -- {} | fish_indent --ansi" \
|
||||
--preview-window="bottom:3:wrap" \
|
||||
$fzf_history_opts |
|
||||
string split0 |
|
||||
# remove timestamps from commands selected
|
||||
string replace --regex $time_prefix_regex ''
|
||||
)
|
||||
|
||||
if test $status -eq 0
|
||||
commandline --replace -- $commands_selected
|
||||
end
|
||||
|
||||
commandline --function repaint
|
||||
end
|
||||
32
config/fish/functions/_fzf_search_processes.fish
Normal file
32
config/fish/functions/_fzf_search_processes.fish
Normal file
@@ -0,0 +1,32 @@
|
||||
function _fzf_search_processes --description "Search all running processes. Replace the current token with the pid of the selected process."
|
||||
# Directly use ps command because it is often aliased to a different command entirely
|
||||
# or with options that dirty the search results and preview output
|
||||
set -f ps_cmd (command -v ps || echo "ps")
|
||||
# use all caps to be consistent with ps default format
|
||||
# snake_case because ps doesn't seem to allow spaces in the field names
|
||||
set -f ps_preview_fmt (string join ',' 'pid' 'ppid=PARENT' 'user' '%cpu' 'rss=RSS_IN_KB' 'start=START_TIME' 'command')
|
||||
set -f processes_selected (
|
||||
$ps_cmd -A -opid,command | \
|
||||
_fzf_wrapper --multi \
|
||||
--prompt="Processes> " \
|
||||
--query (commandline --current-token) \
|
||||
--ansi \
|
||||
# first line outputted by ps is a header, so we need to mark it as so
|
||||
--header-lines=1 \
|
||||
# ps uses exit code 1 if the process was not found, in which case show an message explaining so
|
||||
--preview="$ps_cmd -o '$ps_preview_fmt' -p {1} || echo 'Cannot preview {1} because it exited.'" \
|
||||
--preview-window="bottom:4:wrap" \
|
||||
$fzf_processes_opts
|
||||
)
|
||||
|
||||
if test $status -eq 0
|
||||
for process in $processes_selected
|
||||
set -f --append pids_selected (string split --no-empty --field=1 -- " " $process)
|
||||
end
|
||||
|
||||
# string join to replace the newlines outputted by string split with spaces
|
||||
commandline --current-token --replace -- (string join ' ' $pids_selected)
|
||||
end
|
||||
|
||||
commandline --function repaint
|
||||
end
|
||||
47
config/fish/functions/_fzf_search_variables.fish
Normal file
47
config/fish/functions/_fzf_search_variables.fish
Normal file
@@ -0,0 +1,47 @@
|
||||
# This function expects the following two arguments:
|
||||
# argument 1 = output of (set --show | psub), i.e. a file with the scope info and values of all variables
|
||||
# argument 2 = output of (set --names | psub), i.e. a file with all variable names
|
||||
function _fzf_search_variables --argument-names set_show_output set_names_output --description "Search and preview shell variables. Replace the current token with the selected variable."
|
||||
if test -z "$set_names_output"
|
||||
printf '%s\n' '_fzf_search_variables requires 2 arguments.' >&2
|
||||
|
||||
commandline --function repaint
|
||||
return 22 # 22 means invalid argument in POSIX
|
||||
end
|
||||
|
||||
# Exclude the history variable from being piped into fzf because
|
||||
# 1. it's not included in $set_names_output
|
||||
# 2. it tends to be a very large value => increases computation time
|
||||
# 3._fzf_search_history is a much better way to examine history anyway
|
||||
set -f all_variable_names (string match --invert history <$set_names_output)
|
||||
|
||||
set -f current_token (commandline --current-token)
|
||||
# Use the current token to pre-populate fzf's query. If the current token begins
|
||||
# with a $, remove it from the query so that it will better match the variable names
|
||||
set -f cleaned_curr_token (string replace -- '$' '' $current_token)
|
||||
|
||||
set -f variable_names_selected (
|
||||
printf '%s\n' $all_variable_names |
|
||||
_fzf_wrapper --preview "_fzf_extract_var_info {} $set_show_output" \
|
||||
--prompt="Variables> " \
|
||||
--preview-window="wrap" \
|
||||
--multi \
|
||||
--query=$cleaned_curr_token \
|
||||
$fzf_variables_opts
|
||||
)
|
||||
|
||||
if test $status -eq 0
|
||||
# If the current token begins with a $, do not overwrite the $ when
|
||||
# replacing the current token with the selected variable.
|
||||
# Uses brace expansion to prepend $ to each variable name.
|
||||
commandline --current-token --replace (
|
||||
if string match --quiet -- '$*' $current_token
|
||||
string join " " \${$variable_names_selected}
|
||||
else
|
||||
string join " " $variable_names_selected
|
||||
end
|
||||
)
|
||||
end
|
||||
|
||||
commandline --function repaint
|
||||
end
|
||||
21
config/fish/functions/_fzf_wrapper.fish
Normal file
21
config/fish/functions/_fzf_wrapper.fish
Normal file
@@ -0,0 +1,21 @@
|
||||
function _fzf_wrapper --description "Prepares some environment variables before executing fzf."
|
||||
# Make sure fzf uses fish to execute preview commands, some of which
|
||||
# are autoloaded fish functions so don't exist in other shells.
|
||||
# Use --function so that it doesn't clobber SHELL outside this function.
|
||||
set -f --export SHELL (command --search fish)
|
||||
|
||||
# If neither FZF_DEFAULT_OPTS nor FZF_DEFAULT_OPTS_FILE are set, then set some sane defaults.
|
||||
# See https://github.com/junegunn/fzf#environment-variables
|
||||
set --query FZF_DEFAULT_OPTS FZF_DEFAULT_OPTS_FILE
|
||||
if test $status -eq 2
|
||||
# cycle allows jumping between the first and last results, making scrolling faster
|
||||
# layout=reverse lists results top to bottom, mimicking the familiar layouts of git log, history, and env
|
||||
# border shows where the fzf window begins and ends
|
||||
# height=90% leaves space to see the current command and some scrollback, maintaining context of work
|
||||
# preview-window=wrap wraps long lines in the preview window, making reading easier
|
||||
# marker=* makes the multi-select marker more distinguishable from the pointer (since both default to >)
|
||||
set --export FZF_DEFAULT_OPTS '--cycle --layout=reverse --border --height=90% --preview-window=wrap --marker="*"'
|
||||
end
|
||||
|
||||
fzf $argv
|
||||
end
|
||||
303
config/fish/functions/cr.fish
Normal file
303
config/fish/functions/cr.fish
Normal file
@@ -0,0 +1,303 @@
|
||||
# cr.fish — Create and manage code review worktrees for Fish shell
|
||||
#
|
||||
# Synopsis:
|
||||
# cr [OPTIONS] <source-branch>
|
||||
# cr cleanup [OPTIONS]
|
||||
#
|
||||
# Description:
|
||||
# Create a dedicated worktree for reviewing code based on a ticket ID
|
||||
# extracted from a branch name, or clean up existing cr- worktrees.
|
||||
#
|
||||
# Constants:
|
||||
# CR_DEFAULT_REMOTE Default Git remote used when none specified
|
||||
#
|
||||
# Fish Requirements:
|
||||
# Fish shell >= 3.1.0 for argparse builtin
|
||||
#
|
||||
# Based on work by ville6000 (https://github.com/ville6000)
|
||||
#
|
||||
# Examples:
|
||||
# cr feature/1234-add-login
|
||||
# cr -r upstream 5678
|
||||
# cr cleanup --dry-run
|
||||
|
||||
if not set -q CR_DEFAULT_REMOTE
|
||||
set -g CR_DEFAULT_REMOTE origin
|
||||
end
|
||||
|
||||
function __cr_show_help
|
||||
echo 'Usage: cr [OPTIONS] <source-branch>'
|
||||
echo ' cr cleanup [OPTIONS]'
|
||||
echo
|
||||
echo " -r, --remote <name> Git remote (default: $CR_DEFAULT_REMOTE)"
|
||||
echo ' -d, --dry-run Show actions without executing'
|
||||
echo ' -f, --force Skip confirmation prompts'
|
||||
echo ' -k, --keep-branch In cleanup, keep local branches'
|
||||
echo ' -b, --branch-only <ticket> Create only the review branch (no worktree)'
|
||||
echo ' --cleanup-branches-only In cleanup, delete branches only'
|
||||
echo ' -h, --help Show this help'
|
||||
end
|
||||
|
||||
function __cr_run_with_spinner --argument-names msg cmd
|
||||
set -l tmp (mktemp)
|
||||
eval $cmd >$tmp 2>&1 &
|
||||
set -l pid $last_pid
|
||||
set -l spin_chars '/-\|'
|
||||
set -l i 1
|
||||
while kill -0 $pid 2>/dev/null
|
||||
printf "\r[%c] %s" (string sub -s $i -l 1 $spin_chars) "$msg"
|
||||
set i (math (math $i % 4) + 1)
|
||||
sleep 0.1
|
||||
end
|
||||
printf "\r%s\r" (string repeat -n (math (string length "$msg") + 5) " ")
|
||||
wait $pid
|
||||
set -l output (cat $tmp)
|
||||
rm $tmp
|
||||
# Remove any leading empty or all-whitespace lines (from spinner clear)
|
||||
for line in $output
|
||||
if test -n (string trim -- $line)
|
||||
echo $line
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
function __cr_cleanup
|
||||
argparse dry_run force keep_branch cleanup_branches_only -- $argv
|
||||
or return
|
||||
|
||||
set -l dry_run (set -q _flag_dry_run; and echo 1; or echo 0)
|
||||
set -l force (set -q _flag_force; and echo 1; or echo 0)
|
||||
set -l keep_branch (set -q _flag_keep_branch; and echo 1; or echo 0)
|
||||
set -l branches_only (set -q _flag_cleanup_branches_only; and echo 1; or echo 0)
|
||||
|
||||
set -l target_branch
|
||||
if test (count $argv) -gt 0
|
||||
set target_branch $argv[1]
|
||||
end
|
||||
|
||||
git worktree prune
|
||||
|
||||
for wt in (git worktree list --porcelain | awk '/^worktree /{print $2}')
|
||||
set -l base (basename $wt)
|
||||
if string match -r '^cr-.*' $base
|
||||
if test -n "$target_branch" -a "$base" != "$target_branch"
|
||||
continue
|
||||
end
|
||||
if test "$branches_only" = 0
|
||||
if test "$dry_run" = 1
|
||||
echo "[DRY-RUN] remove worktree: $wt"
|
||||
else if test "$force" = 1
|
||||
git worktree remove --force $wt
|
||||
else
|
||||
echo "git worktree remove --force $wt"
|
||||
echo "(!) Use --force to actually remove worktree: $wt."
|
||||
end
|
||||
end
|
||||
if test "$keep_branch" = 0
|
||||
if test "$branches_only" = 0
|
||||
if test "$dry_run" = 1
|
||||
echo "[DRY-RUN] delete branch: $base"
|
||||
else if test "$force" = 1
|
||||
git branch -D $base
|
||||
else
|
||||
echo "git branch -D $base"
|
||||
echo "(!) Use --force to actually delete branch: $base."
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
# --- Main Entrypoint ---
|
||||
|
||||
function cr --description 'Create or cleanup code-review worktrees'
|
||||
if not git rev-parse --is-inside-work-tree >/dev/null 2>&1
|
||||
echo "Not inside a git repository." >&2
|
||||
return 1
|
||||
end
|
||||
|
||||
set -l remotes (git remote)
|
||||
if test (count $remotes) -eq 0
|
||||
echo "No git remotes found. Please add a remote before using cr." >&2
|
||||
return 1
|
||||
end
|
||||
|
||||
if not type -q argparse
|
||||
echo 'cr.fish requires the argparse builtin' >&2
|
||||
return 1
|
||||
end
|
||||
|
||||
argparse \
|
||||
r/remote= \
|
||||
h/help \
|
||||
d/dry-run \
|
||||
f/force \
|
||||
y/yes \
|
||||
k/keep-branch \
|
||||
b/branch-only= \
|
||||
cleanup-branches-only \
|
||||
-- $argv
|
||||
or return
|
||||
|
||||
if set -q _flag_h; or set -q _flag_help
|
||||
__cr_show_help
|
||||
return 0
|
||||
end
|
||||
|
||||
set -l remote (set -q _flag_remote; and echo $_flag_remote[-1]; or echo $CR_DEFAULT_REMOTE)
|
||||
if set -q _flag_yes
|
||||
set -g _flag_force 1
|
||||
end
|
||||
|
||||
if not contains $remote $remotes
|
||||
echo "Remote '$remote' does not exist. Available remotes: $remotes" >&2
|
||||
return 1
|
||||
end
|
||||
|
||||
if test (count $argv) -gt 0 -a "$argv[1]" = cleanup
|
||||
__cr_cleanup \
|
||||
(set -q _flag_dry_run; and echo --dry_run) \
|
||||
(set -q _flag_force; and echo --force) \
|
||||
(set -q _flag_keep_branch; and echo --keep_branch) \
|
||||
(set -q _flag_cleanup_branches_only; and echo --cleanup_branches_only)
|
||||
return 0
|
||||
end
|
||||
|
||||
set -l source_branch ""
|
||||
if test (count $argv) -gt 0
|
||||
set source_branch $argv[1]
|
||||
else if type -q fzf
|
||||
set -l branches (__cr_run_with_spinner "Fetching branches..." \
|
||||
"git ls-remote --heads $remote | sed 's|.*refs/heads/||'")
|
||||
printf "\n"
|
||||
if test (count $branches) -eq 0
|
||||
echo "No branches found on remote '$remote'." >&2
|
||||
return 1
|
||||
end
|
||||
set -l exclude_branches main master develop dev trunk
|
||||
set -l filtered_branches
|
||||
for b in $branches
|
||||
set b (string trim -- $b)
|
||||
if not contains -- $b $exclude_branches
|
||||
set filtered_branches $filtered_branches $b
|
||||
end
|
||||
end
|
||||
set source_branch (printf '%s\n' $filtered_branches | fzf --prompt='Select branch: ')
|
||||
echo "Selected branch: $source_branch"
|
||||
if test $status -ne 0
|
||||
echo 'Selection aborted' >&2
|
||||
return 1
|
||||
end
|
||||
if test -z "$source_branch"
|
||||
echo 'No branch selected' >&2
|
||||
return 1
|
||||
end
|
||||
else
|
||||
__cr_show_help >&2
|
||||
return 1
|
||||
end
|
||||
|
||||
# Extract ticket ID from branch name, or use slug if not found
|
||||
set -l branch_tail (string split "/" $source_branch)[-1]
|
||||
set -l ticket_id (printf '%s\n' $branch_tail | grep -o '[0-9]\+' | tail -n1)
|
||||
set -l review_suffix ""
|
||||
if test -z "$ticket_id"
|
||||
# No numeric ticket, use slug of branch name as suffix
|
||||
set review_suffix (string replace -ra '[^a-zA-Z0-9]+' '-' -- $source_branch)
|
||||
else
|
||||
set review_suffix $ticket_id
|
||||
end
|
||||
if set -q _flag_b; or set -q _flag_branch_only
|
||||
set review_suffix $_flag_branch_only[-1]
|
||||
end
|
||||
set -l review_branch cr-$review_suffix
|
||||
set -l folder ../$review_branch
|
||||
|
||||
# Branch-only mode
|
||||
if set -q _flag_b; or set -q _flag_branch_only
|
||||
if set -q _flag_dry_run
|
||||
echo "[DRY-RUN] Create branch $review_branch from $remote/$source_branch"
|
||||
return 0
|
||||
end
|
||||
__cr_run_with_spinner "Fetching from $remote..." \
|
||||
"git fetch $remote $source_branch"
|
||||
git branch $review_branch $remote/$source_branch
|
||||
echo "Created branch $review_branch"
|
||||
return 0
|
||||
end
|
||||
|
||||
__cr_run_with_spinner "Checking remote branch..." \
|
||||
"git ls-remote --exit-code --heads $remote $source_branch >/dev/null 2>&1"
|
||||
if test $status -ne 0
|
||||
echo "No remote branch $remote/$source_branch" >&2
|
||||
return 1
|
||||
end
|
||||
if git show-ref --quiet refs/heads/$review_branch
|
||||
echo "Local branch $review_branch exists" >&2
|
||||
return 1
|
||||
end
|
||||
if test -d $folder
|
||||
echo "Directory $folder exists" >&2
|
||||
return 1
|
||||
end
|
||||
|
||||
if set -q _flag_dry_run
|
||||
echo "[DRY-RUN] Add worktree $folder -b $review_branch $remote/$source_branch"
|
||||
return 0
|
||||
end
|
||||
|
||||
__cr_run_with_spinner "Fetching from $remote..." \
|
||||
"git fetch $remote $source_branch"
|
||||
git worktree add $folder -b $review_branch $remote/$source_branch
|
||||
end
|
||||
|
||||
# --- Completion Functions ---
|
||||
|
||||
complete -c cr -l help -s h -f -d 'Show help'
|
||||
complete -c cr -l remote -s r -f -d 'Git remote' -a '(git remote)'
|
||||
complete -c cr -l dry-run -s d -f -d 'Dry run'
|
||||
complete -c cr -l force -s f -f -d 'Skip confirmations'
|
||||
complete -c cr -l keep-branch -s k -f -d 'Keep branches in cleanup'
|
||||
complete -c cr -l branch-only -s b -f -d 'Branch-only mode' \
|
||||
-a '(__fish_cr_ticket_ids)'
|
||||
complete -c cr -l cleanup-branches-only -f -d 'Branches-only cleanup'
|
||||
complete -c cr -f -a cleanup -d 'Cleanup mode' \
|
||||
-n 'not __fish_seen_subcommand_from cleanup'
|
||||
complete -c cr -n '__fish_seen_subcommand_from cleanup' -f \
|
||||
-a '(__fish_cr_cleanup_branches)' -d 'cr-* branch'
|
||||
complete -c cr -n '__fish_seen_subcommand_from cleanup' -f
|
||||
complete -c cr -n 'not __fish_seen_subcommand_from cleanup' -f \
|
||||
-a '(__fish_cr_branches)' -d 'Source branch'
|
||||
|
||||
function __fish_cr_cleanup_branches
|
||||
git worktree list --porcelain | awk '/^worktree /{print $2}' | while read -l wt
|
||||
set base (basename $wt)
|
||||
if string match -r '^cr-.*' $base
|
||||
echo $base
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
function __fish_cr_branches --description 'List remote branches'
|
||||
set -l exclude_branches main master develop dev trunk
|
||||
set -l branches (git ls-remote --heads $CR_DEFAULT_REMOTE | \
|
||||
sed 's|.*refs/heads/||')
|
||||
for b in $branches
|
||||
set b (string trim -- $b)
|
||||
if not contains -- $b $exclude_branches
|
||||
echo $b
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
function __fish_cr_ticket_ids --description 'List ticket IDs from remote branches'
|
||||
for b in (git ls-remote --heads $CR_DEFAULT_REMOTE | \
|
||||
sed 's|.*refs/heads/||')
|
||||
set b (string trim -- $b)
|
||||
set -l id (string match -r '[0-9]+' -- $b)
|
||||
if test -n "$id"
|
||||
echo $id
|
||||
end
|
||||
end
|
||||
end
|
||||
46
config/fish/functions/fzf_configure_bindings.fish
Normal file
46
config/fish/functions/fzf_configure_bindings.fish
Normal file
@@ -0,0 +1,46 @@
|
||||
# Always installs bindings for insert and default mode for simplicity and b/c it has almost no side-effect
|
||||
# https://gitter.im/fish-shell/fish-shell?at=60a55915ee77a74d685fa6b1
|
||||
function fzf_configure_bindings --description "Installs the default key bindings for fzf.fish with user overrides passed as options."
|
||||
# no need to install bindings if not in interactive mode or running tests
|
||||
status is-interactive || test "$CI" = true; or return
|
||||
|
||||
set -f options_spec h/help 'directory=?' 'git_log=?' 'git_status=?' 'history=?' 'processes=?' 'variables=?'
|
||||
argparse --max-args=0 --ignore-unknown $options_spec -- $argv 2>/dev/null
|
||||
if test $status -ne 0
|
||||
echo "Invalid option or a positional argument was provided." >&2
|
||||
_fzf_configure_bindings_help
|
||||
return 22
|
||||
else if set --query _flag_help
|
||||
_fzf_configure_bindings_help
|
||||
return
|
||||
else
|
||||
# Initialize with default key sequences and then override or disable them based on flags
|
||||
# index 1 = directory, 2 = git_log, 3 = git_status, 4 = history, 5 = processes, 6 = variables
|
||||
set -f key_sequences \e\cf \e\cl \e\cs \cr \e\cp \cv # \c = control, \e = escape
|
||||
set --query _flag_directory && set key_sequences[1] "$_flag_directory"
|
||||
set --query _flag_git_log && set key_sequences[2] "$_flag_git_log"
|
||||
set --query _flag_git_status && set key_sequences[3] "$_flag_git_status"
|
||||
set --query _flag_history && set key_sequences[4] "$_flag_history"
|
||||
set --query _flag_processes && set key_sequences[5] "$_flag_processes"
|
||||
set --query _flag_variables && set key_sequences[6] "$_flag_variables"
|
||||
|
||||
# If fzf bindings already exists, uninstall it first for a clean slate
|
||||
if functions --query _fzf_uninstall_bindings
|
||||
_fzf_uninstall_bindings
|
||||
end
|
||||
|
||||
for mode in default insert
|
||||
test -n $key_sequences[1] && bind --mode $mode $key_sequences[1] _fzf_search_directory
|
||||
test -n $key_sequences[2] && bind --mode $mode $key_sequences[2] _fzf_search_git_log
|
||||
test -n $key_sequences[3] && bind --mode $mode $key_sequences[3] _fzf_search_git_status
|
||||
test -n $key_sequences[4] && bind --mode $mode $key_sequences[4] _fzf_search_history
|
||||
test -n $key_sequences[5] && bind --mode $mode $key_sequences[5] _fzf_search_processes
|
||||
test -n $key_sequences[6] && bind --mode $mode $key_sequences[6] "$_fzf_search_vars_command"
|
||||
end
|
||||
|
||||
function _fzf_uninstall_bindings --inherit-variable key_sequences
|
||||
bind --erase -- $key_sequences
|
||||
bind --erase --mode insert -- $key_sequences
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -1,7 +1,22 @@
|
||||
return {
|
||||
{
|
||||
'rmehri01/onenord.nvim',
|
||||
opts = {},
|
||||
'rose-pine/neovim',
|
||||
name = 'rose-pine',
|
||||
opts = {
|
||||
dim_inactive_windows = false,
|
||||
extend_background_behind_borders = true,
|
||||
styles = {
|
||||
bold = true,
|
||||
italic = true,
|
||||
transparency = true,
|
||||
},
|
||||
enable = {
|
||||
terminal = true,
|
||||
legacy_highlights = true, -- Improve compatibility for previous versions of Neovim
|
||||
migrations = true, -- Handle deprecated options automatically
|
||||
},
|
||||
},
|
||||
config = function() vim.cmd 'colorscheme rose-pine' end,
|
||||
},
|
||||
-- Automatic dark mode
|
||||
-- https://github.com/f-person/auto-dark-mode.nvim
|
||||
@@ -12,10 +27,12 @@ return {
|
||||
set_dark_mode = function()
|
||||
vim.api.nvim_set_option_value('background', 'dark', {})
|
||||
-- vim.cmd.colorscheme(vim.g.colors_variant_dark)
|
||||
vim.cmd 'colorscheme rose-pine'
|
||||
end,
|
||||
set_light_mode = function()
|
||||
vim.api.nvim_set_option_value('background', 'light', {})
|
||||
-- vim.cmd.colorscheme(vim.g.colors_variant_light)
|
||||
vim.cmd 'colorscheme rose-pine-dawn'
|
||||
end,
|
||||
},
|
||||
},
|
||||
@@ -68,6 +85,42 @@ return {
|
||||
'm4xshen/hardtime.nvim',
|
||||
lazy = false,
|
||||
dependencies = { 'MunifTanjim/nui.nvim' },
|
||||
opts = {},
|
||||
opts = {
|
||||
restriction_mode = 'hint',
|
||||
disabled_keys = {
|
||||
['<Up>'] = { '', 'n' },
|
||||
['<Down>'] = { '', 'n' },
|
||||
['<Left>'] = { '', 'n' },
|
||||
['<Right>'] = { '', 'n' },
|
||||
['<C-Up>'] = { '', 'n' },
|
||||
['<C-Down>'] = { '', 'n' },
|
||||
['<C-Left>'] = { '', 'n' },
|
||||
['<C-Right>'] = { '', 'n' },
|
||||
},
|
||||
disabled_filetypes = {
|
||||
'TelescopePrompt',
|
||||
'Trouble',
|
||||
'lazy',
|
||||
'mason',
|
||||
'help',
|
||||
'notify',
|
||||
'dashboard',
|
||||
'alpha',
|
||||
},
|
||||
hints = {
|
||||
['[dcyvV][ia][%(%)]'] = {
|
||||
message = function(keys)
|
||||
return 'Use ' .. keys:sub(1, 2) .. 'b instead of ' .. keys
|
||||
end,
|
||||
length = 3,
|
||||
},
|
||||
['[dcyvV][ia][%{%}]'] = {
|
||||
message = function(keys)
|
||||
return 'Use ' .. keys:sub(1, 2) .. 'B instead of ' .. keys
|
||||
end,
|
||||
length = 3,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
@@ -1 +1,7 @@
|
||||
[{"account_id":"S5Z2DMNFKJEZBPCWRHRWC4DCGI","vault_id":"injcin7obv3jdet3r2u3kfihfy","item_id":"f6vinbnc6l7ngdzvlw66ayewlq"}]
|
||||
[
|
||||
{
|
||||
"account_id": "S5Z2DMNFKJEZBPCWRHRWC4DCGI",
|
||||
"vault_id": "injcin7obv3jdet3r2u3kfihfy",
|
||||
"item_id": "f6vinbnc6l7ngdzvlw66ayewlq"
|
||||
}
|
||||
]
|
||||
|
||||
11
hosts/README.md
Normal file
11
hosts/README.md
Normal file
@@ -0,0 +1,11 @@
|
||||
# Host specific directories
|
||||
|
||||
Host folders contain machine specific overrides and an `install.conf.yaml` file that Dotbot processes during setup.
|
||||
|
||||
Current hosts:
|
||||
|
||||
- **air** – personal computer
|
||||
- **lakka** – remote server
|
||||
- **s** – work laptop
|
||||
- **tunkki** – local server
|
||||
- **v** – work desktop
|
||||
29
local/bin/a.md
Normal file
29
local/bin/a.md
Normal file
@@ -0,0 +1,29 @@
|
||||
# a
|
||||
|
||||
Encrypt or decrypt files and directories using `age` and your GitHub SSH keys.
|
||||
|
||||
## Usage
|
||||
|
||||
```bash
|
||||
a encrypt <file|dir>
|
||||
a decrypt <file.age|dir>
|
||||
```
|
||||
|
||||
Options:
|
||||
|
||||
- `-v`, `--verbose` – show log output
|
||||
|
||||
Environment variables:
|
||||
|
||||
- `AGE_KEYSFILE` – location of the keys file
|
||||
- `AGE_KEYSSOURCE` – URL to fetch keys if missing
|
||||
- `AGE_LOGFILE` – log file path
|
||||
|
||||
## Example
|
||||
|
||||
```bash
|
||||
a encrypt secret.txt
|
||||
a decrypt secret.txt.age
|
||||
```
|
||||
|
||||
<!-- vim: set ft=markdown spell spelllang=en_us cc=80 : -->
|
||||
19
local/bin/ad.md
Normal file
19
local/bin/ad.md
Normal file
@@ -0,0 +1,19 @@
|
||||
# ad
|
||||
|
||||
Decrypt a file encrypted with `age` using your GitHub SSH keys.
|
||||
|
||||
## Usage
|
||||
|
||||
```bash
|
||||
ad <file.age>
|
||||
```
|
||||
|
||||
Uses `AGE_KEYSFILE` and `AGE_KEYSSOURCE` if keys are missing.
|
||||
|
||||
## Example
|
||||
|
||||
```bash
|
||||
ad secret.txt.age
|
||||
```
|
||||
|
||||
<!-- vim: set ft=markdown spell spelllang=en_us cc=80 : -->
|
||||
19
local/bin/ae.md
Normal file
19
local/bin/ae.md
Normal file
@@ -0,0 +1,19 @@
|
||||
# ae
|
||||
|
||||
Encrypt a file with `age` using your GitHub SSH keys.
|
||||
|
||||
## Usage
|
||||
|
||||
```bash
|
||||
ae <file>
|
||||
```
|
||||
|
||||
Uses `AGE_KEYSFILE` and `AGE_KEYSSOURCE` if keys are missing.
|
||||
|
||||
## Example
|
||||
|
||||
```bash
|
||||
ae secret.txt
|
||||
```
|
||||
|
||||
<!-- vim: set ft=markdown spell spelllang=en_us cc=80 : -->
|
||||
26
local/bin/dfm.md
Normal file
26
local/bin/dfm.md
Normal file
@@ -0,0 +1,26 @@
|
||||
# dfm
|
||||
|
||||
Dotfiles manager and installation helper. Provides wrappers for many
|
||||
setup tasks defined in this repository.
|
||||
|
||||
## Usage
|
||||
|
||||
```bash
|
||||
dfm <command> [options]
|
||||
```
|
||||
|
||||
Common commands include:
|
||||
|
||||
- `install` – install tools or run platform specific setup
|
||||
- `brew` – manage Homebrew packages
|
||||
- `docs` – regenerate markdown documentation
|
||||
|
||||
Set `VERBOSE=1` to see debug output.
|
||||
|
||||
### Example
|
||||
|
||||
```bash
|
||||
dfm install all
|
||||
```
|
||||
|
||||
<!-- vim: set ft=markdown spell spelllang=en_us cc=80 : -->
|
||||
21
local/bin/fzf-tmux.md
Normal file
21
local/bin/fzf-tmux.md
Normal file
@@ -0,0 +1,21 @@
|
||||
# fzf-tmux
|
||||
|
||||
Wrapper around [`fzf`](https://github.com/junegunn/fzf) that opens the
|
||||
interface inside a tmux pane or popup.
|
||||
|
||||
## Usage
|
||||
|
||||
```bash
|
||||
fzf-tmux [layout options] [--] [fzf options]
|
||||
```
|
||||
|
||||
Layout flags like `-p` or `-d` control popup and split behaviour. Use
|
||||
`--` to pass arguments directly to `fzf`.
|
||||
|
||||
### Example
|
||||
|
||||
```bash
|
||||
fzf-tmux -p 80%,60% -- --reverse
|
||||
```
|
||||
|
||||
<!-- vim: set ft=markdown spell spelllang=en_us cc=80 : -->
|
||||
16
local/bin/fzf.md
Normal file
16
local/bin/fzf.md
Normal file
@@ -0,0 +1,16 @@
|
||||
# fzf
|
||||
|
||||
Binary of the fuzzy finder [fzf](https://github.com/junegunn/fzf).
|
||||
Use `fzf` as you would normally; this wrapper ships the prebuilt
|
||||
binary in the dotfiles.
|
||||
|
||||
## Usage
|
||||
|
||||
```bash
|
||||
fzf [options]
|
||||
```
|
||||
|
||||
Refer to the upstream `fzf` documentation for all available
|
||||
flags and features.
|
||||
|
||||
<!-- vim: set ft=markdown spell spelllang=en_us cc=80 : -->
|
||||
25
local/bin/git-attributes.md
Normal file
25
local/bin/git-attributes.md
Normal file
@@ -0,0 +1,25 @@
|
||||
# git-attributes
|
||||
|
||||
Checks that every tracked file has a matching pattern in `.gitattributes`.
|
||||
Can optionally suggest or write missing rules.
|
||||
|
||||
## Usage
|
||||
|
||||
```bash
|
||||
git-attributes [options]
|
||||
```
|
||||
|
||||
Options include:
|
||||
|
||||
- `-v, --verbose` – show progress information
|
||||
- `-e, --exit` – exit with non-zero status if missing rules
|
||||
- `-p, --pattern <glob>` – pattern to check (default: `text: auto`)
|
||||
- `-w, --write` – append suggestions to `.gitattributes`
|
||||
|
||||
### Example
|
||||
|
||||
```bash
|
||||
git-attributes -v --write
|
||||
```
|
||||
|
||||
<!-- vim: set ft=markdown spell spelllang=en_us cc=80 : -->
|
||||
15
local/bin/iterm2_shell_integration.zsh.md
Normal file
15
local/bin/iterm2_shell_integration.zsh.md
Normal file
@@ -0,0 +1,15 @@
|
||||
# iterm2_shell_integration.zsh
|
||||
|
||||
Official iTerm2 shell integration script for zsh. Source this file to
|
||||
enable prompt tracking and command notifications in iTerm2.
|
||||
|
||||
## Usage
|
||||
|
||||
```bash
|
||||
source iterm2_shell_integration.zsh
|
||||
```
|
||||
|
||||
No parameters are required. The script modifies your prompt to work
|
||||
with iTerm2 features such as badges and profile switching.
|
||||
|
||||
<!-- vim: set ft=markdown spell spelllang=en_us cc=80 : -->
|
||||
20
local/bin/msgr.md
Normal file
20
local/bin/msgr.md
Normal file
@@ -0,0 +1,20 @@
|
||||
# msgr
|
||||
|
||||
Helper library for printing colorized log messages from shell scripts.
|
||||
|
||||
## Usage
|
||||
|
||||
```bash
|
||||
msgr <type> "message" [extra]
|
||||
```
|
||||
|
||||
Message types include `ok`, `warn`, `err`, `run` and many more. The
|
||||
script is primarily sourced by other scripts.
|
||||
|
||||
### Example
|
||||
|
||||
```bash
|
||||
msgr ok "Installation complete"
|
||||
```
|
||||
|
||||
<!-- vim: set ft=markdown spell spelllang=en_us cc=80 : -->
|
||||
23
local/bin/php-switcher.md
Normal file
23
local/bin/php-switcher.md
Normal file
@@ -0,0 +1,23 @@
|
||||
# php-switcher
|
||||
|
||||
Switch between Homebrew-installed PHP versions or list installed versions.
|
||||
|
||||
## Usage
|
||||
|
||||
```bash
|
||||
php-switcher <version>|--auto [options]
|
||||
```
|
||||
|
||||
Options:
|
||||
|
||||
- `--installed` – list versions installed via Homebrew
|
||||
- `--current` – print currently active PHP version
|
||||
- `--auto` – read version from `.php-version` in current directory
|
||||
|
||||
### Example
|
||||
|
||||
```bash
|
||||
php-switcher 8.3
|
||||
```
|
||||
|
||||
<!-- vim: set ft=markdown spell spelllang=en_us cc=80 : -->
|
||||
@@ -56,22 +56,31 @@ __pushover_send_message()
|
||||
|
||||
response="$(eval "${curl_cmd}")"
|
||||
printf "%s\n" "$response"
|
||||
# TODO: Parse response
|
||||
r="${?}"
|
||||
if [ "${r}" -ne 0 ]; then
|
||||
printf "%s: Failed to send message\n" "${0}" >&2
|
||||
|
||||
# Parse response status. Expect JSON like: {"status":1,"request":"..."}
|
||||
if echo "$response" | grep -q '"status"[[:space:]]*:[[:space:]]*1'; then
|
||||
r=0
|
||||
else
|
||||
r=1
|
||||
fi
|
||||
|
||||
return "${r}"
|
||||
if [ "$r" -ne 0 ]; then
|
||||
# Extract possible error message from JSON
|
||||
err=$(echo "$response" | grep -o '"errors".*' | sed 's/"errors"[:,\[]//g' | tr -d '[]"')
|
||||
[ -n "$err" ] && printf "%s: %s\n" "$0" "$err" >&2
|
||||
printf "%s: Failed to send message\n" "$0" >&2
|
||||
fi
|
||||
|
||||
return "$r"
|
||||
}
|
||||
|
||||
CURL="$(which curl)"
|
||||
CURL="$(command -v curl)"
|
||||
PUSHOVER_URL="https://api.pushover.net/1/messages.json"
|
||||
TOKEN=$PUSHOVER_TOKEN
|
||||
USER=$PUSHOVER_USER
|
||||
CURL_OPTS=""
|
||||
devices="${devices} ${device}"
|
||||
optstring="c:d:D:e:f:p:r:t:T:s:u:U:a:h"
|
||||
devices=""
|
||||
optstring="c:d:D:e:p:r:t:T:s:u:U:a:h"
|
||||
|
||||
OPTIND=1
|
||||
while getopts ${optstring} c; do
|
||||
@@ -97,7 +106,7 @@ while getopts ${optstring} c; do
|
||||
t)
|
||||
title="${OPTARG}"
|
||||
;;
|
||||
k)
|
||||
T)
|
||||
TOKEN="${OPTARG}"
|
||||
;;
|
||||
s)
|
||||
|
||||
25
local/bin/pushover.md
Normal file
25
local/bin/pushover.md
Normal file
@@ -0,0 +1,25 @@
|
||||
# pushover
|
||||
|
||||
Send notifications via the Pushover API.
|
||||
|
||||
## Usage
|
||||
|
||||
```bash
|
||||
pushover -T <token> -U <user> [-t title] [-p priority] message
|
||||
```
|
||||
|
||||
Common options:
|
||||
|
||||
- `-c <callback>` – callback URL
|
||||
- `-d <device>` – target device
|
||||
- `-s <sound>` – notification sound name
|
||||
- `-T <token>` – application token (or `PUSHOVER_TOKEN` env)
|
||||
- `-U <user>` – user key (or `PUSHOVER_USER` env)
|
||||
|
||||
## Example
|
||||
|
||||
```bash
|
||||
pushover -T $TOKEN -U $USER -t "Build" "Finished successfully"
|
||||
```
|
||||
|
||||
<!-- vim: set ft=markdown spell spelllang=en_us cc=80 : -->
|
||||
23
local/bin/t.md
Normal file
23
local/bin/t.md
Normal file
@@ -0,0 +1,23 @@
|
||||
# t
|
||||
|
||||
Launch or switch to a tmux session based on a directory selected with
|
||||
`fzf`. Inspired by scripts from ThePrimeagen and Jess Archer.
|
||||
|
||||
## Usage
|
||||
|
||||
```bash
|
||||
t
|
||||
```
|
||||
|
||||
Environment variables:
|
||||
|
||||
- `T_ROOT` – base directory to search (default: `~/Code`)
|
||||
- `T_MAX_DEPTH` – recursion depth for directory search
|
||||
|
||||
### Example
|
||||
|
||||
```bash
|
||||
T_ROOT=~/projects t
|
||||
```
|
||||
|
||||
<!-- vim: set ft=markdown spell spelllang=en_us cc=80 : -->
|
||||
20
local/bin/x-backup-folder.md
Normal file
20
local/bin/x-backup-folder.md
Normal file
@@ -0,0 +1,20 @@
|
||||
# x-backup-folder
|
||||
|
||||
Create a compressed archive of a folder with a timestamped name.
|
||||
|
||||
## Usage
|
||||
|
||||
```bash
|
||||
x-backup-folder <folder> [archive-name]
|
||||
```
|
||||
|
||||
- `folder` – directory to back up
|
||||
- `archive-name` – optional prefix for the generated tar.gz
|
||||
|
||||
## Example
|
||||
|
||||
```bash
|
||||
x-backup-folder ~/Documents Notes
|
||||
```
|
||||
|
||||
<!-- vim: set ft=markdown spell spelllang=en_us cc=80 : -->
|
||||
21
local/bin/x-backup-mysql-with-prefix.md
Normal file
21
local/bin/x-backup-mysql-with-prefix.md
Normal file
@@ -0,0 +1,21 @@
|
||||
# x-backup-mysql-with-prefix
|
||||
|
||||
Dump MySQL tables matching a prefix to a timestamped file.
|
||||
|
||||
## Usage
|
||||
|
||||
```bash
|
||||
x-backup-mysql-with-prefix <prefix> <name> [database]
|
||||
```
|
||||
|
||||
- `prefix` – table prefix to match (e.g. `wp_`)
|
||||
- `name` – file name prefix
|
||||
- `database` – database name (default: `wordpress`)
|
||||
|
||||
## Example
|
||||
|
||||
```bash
|
||||
x-backup-mysql-with-prefix wp_ blog
|
||||
```
|
||||
|
||||
<!-- vim: set ft=markdown spell spelllang=en_us cc=80 : -->
|
||||
20
local/bin/x-change-alacritty-theme.md
Normal file
20
local/bin/x-change-alacritty-theme.md
Normal file
@@ -0,0 +1,20 @@
|
||||
# x-change-alacritty-theme
|
||||
|
||||
Adapted from <https://gist.github.com/xqm32/17777d035930d622d0ff7530bfab61fd>
|
||||
|
||||
## Usage
|
||||
|
||||
```bash
|
||||
x-change-alacritty-theme <day|night>
|
||||
```
|
||||
|
||||
Switches Alacritty's theme by copying a theme file under
|
||||
`~/.config/alacritty/`.
|
||||
|
||||
### Example
|
||||
|
||||
```bash
|
||||
x-change-alacritty-theme night
|
||||
```
|
||||
|
||||
<!-- vim: set ft=markdown spell spelllang=en_us cc=80 : -->
|
||||
19
local/bin/x-clean-vendordirs.md
Normal file
19
local/bin/x-clean-vendordirs.md
Normal file
@@ -0,0 +1,19 @@
|
||||
# x-clean-vendordirs
|
||||
|
||||
Remove `vendor` and `node_modules` directories recursively.
|
||||
|
||||
## Usage
|
||||
|
||||
```bash
|
||||
x-clean-vendordirs [directory]
|
||||
```
|
||||
|
||||
- `directory` – root directory to clean (default: current directory)
|
||||
|
||||
## Example
|
||||
|
||||
```bash
|
||||
x-clean-vendordirs ~/projects
|
||||
```
|
||||
|
||||
<!-- vim: set ft=markdown spell spelllang=en_us cc=80 : -->
|
||||
14
local/bin/x-compare-versions.py.md
Normal file
14
local/bin/x-compare-versions.py.md
Normal file
@@ -0,0 +1,14 @@
|
||||
# x-compare-versions.py
|
||||
|
||||
Compare version strings using Python's packaging library.
|
||||
|
||||
## Usage
|
||||
|
||||
```bash
|
||||
echo "1.2.3 >= 1.0.0" | x-compare-versions.py
|
||||
```
|
||||
|
||||
The script reads comparison expressions from standard input and exits
|
||||
with status 0 if all comparisons are true.
|
||||
|
||||
<!-- vim: set ft=markdown spell spelllang=en_us cc=80 : -->
|
||||
19
local/bin/x-dc.md
Normal file
19
local/bin/x-dc.md
Normal file
@@ -0,0 +1,19 @@
|
||||
# x-dc
|
||||
|
||||
Create a directory if it does not exist.
|
||||
|
||||
## Usage
|
||||
|
||||
```bash
|
||||
x-dc <directory>
|
||||
```
|
||||
|
||||
Set `VERBOSE=1` to see log messages.
|
||||
|
||||
## Example
|
||||
|
||||
```bash
|
||||
x-dc ~/tmp/mydir
|
||||
```
|
||||
|
||||
<!-- vim: set ft=markdown spell spelllang=en_us cc=80 : -->
|
||||
14
local/bin/x-dfm-docs-xterm-keybindings.md
Normal file
14
local/bin/x-dfm-docs-xterm-keybindings.md
Normal file
@@ -0,0 +1,14 @@
|
||||
# x-dfm-docs-xterm-keybindings
|
||||
|
||||
Generate `docs/tmux-keybindings.md` using tmux's key list.
|
||||
|
||||
## Usage
|
||||
|
||||
```bash
|
||||
x-dfm-docs-xterm-keybindings
|
||||
```
|
||||
|
||||
No parameters are needed. The script writes the file under `docs/` and
|
||||
overwrites any existing version.
|
||||
|
||||
<!-- vim: set ft=markdown spell spelllang=en_us cc=80 : -->
|
||||
21
local/bin/x-env-list.md
Normal file
21
local/bin/x-env-list.md
Normal file
@@ -0,0 +1,21 @@
|
||||
# x-env-list
|
||||
|
||||
Lists environment variables grouped by their prefix. Sensitive values
|
||||
are hidden by default.
|
||||
|
||||
## Usage
|
||||
|
||||
```bash
|
||||
x-env-list [options]
|
||||
```
|
||||
|
||||
Use `--json` for machine readable output or specify
|
||||
`X_ENV_GROUPING` with a YAML file to override the default groups.
|
||||
|
||||
### Example
|
||||
|
||||
```bash
|
||||
X_ENV_GROUPING=~/env-groups.yaml x-env-list --json
|
||||
```
|
||||
|
||||
<!-- vim: set ft=markdown spell spelllang=en_us cc=80 : -->
|
||||
20
local/bin/x-foreach.md
Normal file
20
local/bin/x-foreach.md
Normal file
@@ -0,0 +1,20 @@
|
||||
# x-foreach
|
||||
|
||||
Run a command in each directory produced by another command.
|
||||
|
||||
## Usage
|
||||
|
||||
```bash
|
||||
x-foreach "<list-cmd>" "<cmd>"
|
||||
```
|
||||
|
||||
- `list-cmd` – command that outputs directories
|
||||
- `cmd` – command to run inside each directory
|
||||
|
||||
## Example
|
||||
|
||||
```bash
|
||||
x-foreach "ls -d */" "git status"
|
||||
```
|
||||
|
||||
<!-- vim: set ft=markdown spell spelllang=en_us cc=80 : -->
|
||||
19
local/bin/x-gh-get-latest-release-targz.md
Normal file
19
local/bin/x-gh-get-latest-release-targz.md
Normal file
@@ -0,0 +1,19 @@
|
||||
# x-gh-get-latest-release-targz
|
||||
|
||||
Fetch the tarball URL of the latest GitHub release or download it directly.
|
||||
|
||||
## Usage
|
||||
|
||||
```bash
|
||||
x-gh-get-latest-release-targz <owner/repo> [--get]
|
||||
```
|
||||
|
||||
- `--get` – download and extract the tarball instead of printing the URL
|
||||
|
||||
## Example
|
||||
|
||||
```bash
|
||||
x-gh-get-latest-release-targz ivuorinen/dotfiles --get
|
||||
```
|
||||
|
||||
<!-- vim: set ft=markdown spell spelllang=en_us cc=80 : -->
|
||||
@@ -97,7 +97,7 @@ Examples:
|
||||
# Use GitHub Enterprise API
|
||||
GITHUB_API_URL="https://github.example.com/api/v3/repos" $BIN ivuorinen/dotfiles
|
||||
EOF
|
||||
exit 1
|
||||
exit 0
|
||||
}
|
||||
|
||||
# Check that required dependencies are installed
|
||||
|
||||
21
local/bin/x-git-largest-files.py.md
Normal file
21
local/bin/x-git-largest-files.py.md
Normal file
@@ -0,0 +1,21 @@
|
||||
# x-git-largest-files.py
|
||||
|
||||
Lists the largest files in a git repository.
|
||||
|
||||
```bash
|
||||
x-git-largest-files.py [options]
|
||||
```
|
||||
|
||||
Options:
|
||||
|
||||
- `-c NUM` – number of files to show (default: 10)
|
||||
- `--files-exceeding N` – list files larger than N KB
|
||||
- `-p` – sort by on-disk size instead of pack size
|
||||
|
||||
## Example
|
||||
|
||||
```bash
|
||||
x-git-largest-files.py -c 5
|
||||
```
|
||||
|
||||
<!-- vim: set ft=markdown spell spelllang=en_us cc=80 : -->
|
||||
18
local/bin/x-have.md
Normal file
18
local/bin/x-have.md
Normal file
@@ -0,0 +1,18 @@
|
||||
# x-have
|
||||
|
||||
Check if a command exists on the system. Exits with status 0 if found
|
||||
and 1 otherwise.
|
||||
|
||||
## Usage
|
||||
|
||||
```bash
|
||||
x-have <command>
|
||||
```
|
||||
|
||||
### Example
|
||||
|
||||
```bash
|
||||
x-have git && echo "git installed"
|
||||
```
|
||||
|
||||
<!-- vim: set ft=markdown spell spelllang=en_us cc=80 : -->
|
||||
19
local/bin/x-hr.md
Normal file
19
local/bin/x-hr.md
Normal file
@@ -0,0 +1,19 @@
|
||||
# x-hr
|
||||
|
||||
Print a horizontal rule. Useful for visually separating log output.
|
||||
|
||||
## Usage
|
||||
|
||||
```bash
|
||||
x-hr [character]
|
||||
```
|
||||
|
||||
If no character is given a red `-` is used.
|
||||
|
||||
### Example
|
||||
|
||||
```bash
|
||||
x-hr "="
|
||||
```
|
||||
|
||||
<!-- vim: set ft=markdown spell spelllang=en_us cc=80 : -->
|
||||
19
local/bin/x-ip.md
Normal file
19
local/bin/x-ip.md
Normal file
@@ -0,0 +1,19 @@
|
||||
# x-ip
|
||||
|
||||
Fetch your public IP address using `curl`.
|
||||
|
||||
## Usage
|
||||
|
||||
```bash
|
||||
x-ip [curl-options]
|
||||
```
|
||||
|
||||
Any arguments are passed directly to `curl`.
|
||||
|
||||
### Example
|
||||
|
||||
```bash
|
||||
x-ip -4
|
||||
```
|
||||
|
||||
<!-- vim: set ft=markdown spell spelllang=en_us cc=80 : -->
|
||||
21
local/bin/x-load-configs.md
Normal file
21
local/bin/x-load-configs.md
Normal file
@@ -0,0 +1,21 @@
|
||||
# x-load-configs
|
||||
|
||||
Source shell configuration files for aliases and exports. Intended to
|
||||
be run after `dfm install` or when switching hosts.
|
||||
|
||||
## Usage
|
||||
|
||||
```bash
|
||||
x-load-configs
|
||||
```
|
||||
|
||||
Set `VERBOSE=1` to print each file as it is sourced. Use `DEBUG=1` to
|
||||
enable tracing.
|
||||
|
||||
### Example
|
||||
|
||||
```bash
|
||||
VERBOSE=1 x-load-configs
|
||||
```
|
||||
|
||||
<!-- vim: set ft=markdown spell spelllang=en_us cc=80 : -->
|
||||
25
local/bin/x-localip.md
Normal file
25
local/bin/x-localip.md
Normal file
@@ -0,0 +1,25 @@
|
||||
# x-localip
|
||||
|
||||
Display local IPv4 and IPv6 addresses with optional interface filtering.
|
||||
|
||||
## Usage
|
||||
|
||||
```bash
|
||||
x-localip [--ipv4] [--ipv6] [interface]
|
||||
```
|
||||
|
||||
- `--ipv4` – show only IPv4 addresses
|
||||
- `--ipv6` – show only IPv6 addresses
|
||||
- `interface` – limit output to the named interface
|
||||
|
||||
## Example
|
||||
|
||||
```bash
|
||||
# Show all addresses
|
||||
x-localip
|
||||
|
||||
# IPv4 for wlan0
|
||||
x-localip --ipv4 wlan0
|
||||
```
|
||||
|
||||
<!-- vim: set ft=markdown spell spelllang=en_us cc=80 : -->
|
||||
@@ -1,7 +1,7 @@
|
||||
#!/usr/bin/env bash
|
||||
#
|
||||
# Create a directory and cd into it
|
||||
# Usage: mkcd <dir>
|
||||
# Usage: x-mkd <dir>
|
||||
|
||||
set -euo pipefail
|
||||
|
||||
|
||||
19
local/bin/x-mkd.md
Normal file
19
local/bin/x-mkd.md
Normal file
@@ -0,0 +1,19 @@
|
||||
# x-mkd
|
||||
|
||||
Create a directory and immediately `cd` into it.
|
||||
|
||||
## Usage
|
||||
|
||||
```bash
|
||||
x-mkd <dir>
|
||||
```
|
||||
|
||||
Set `VERBOSE=1` for status messages.
|
||||
|
||||
## Example
|
||||
|
||||
```bash
|
||||
x-mkd project && git init
|
||||
```
|
||||
|
||||
<!-- vim: set ft=markdown spell spelllang=en_us cc=80 : -->
|
||||
20
local/bin/x-multi-ping.md
Normal file
20
local/bin/x-multi-ping.md
Normal file
@@ -0,0 +1,20 @@
|
||||
# x-multi-ping
|
||||
|
||||
Multi-protocol ping helper supporting IPv4 and IPv6.
|
||||
|
||||
## Usage
|
||||
|
||||
```bash
|
||||
x-multi-ping [--loop] [--sleep=N] host1 host2...
|
||||
```
|
||||
|
||||
- `--loop` – ping continuously
|
||||
- `--sleep` – seconds to wait between iterations
|
||||
|
||||
## Example
|
||||
|
||||
```bash
|
||||
x-multi-ping --loop --sleep=5 example.com
|
||||
```
|
||||
|
||||
<!-- vim: set ft=markdown spell spelllang=en_us cc=80 : -->
|
||||
20
local/bin/x-multi-ping.pl.md
Normal file
20
local/bin/x-multi-ping.pl.md
Normal file
@@ -0,0 +1,20 @@
|
||||
# x-multi-ping.pl
|
||||
|
||||
Ping multiple hosts with IPv4/IPv6 support.
|
||||
|
||||
## Usage
|
||||
|
||||
```bash
|
||||
x-multi-ping.pl [--loop|--forever] [--sleep N] host1 host2 ...
|
||||
```
|
||||
|
||||
`--loop` keeps pinging each host until interrupted. `--sleep` controls
|
||||
the delay between attempts.
|
||||
|
||||
### Example
|
||||
|
||||
```bash
|
||||
x-multi-ping.pl --loop --sleep 2 example.com 1.1.1.1
|
||||
```
|
||||
|
||||
<!-- vim: set ft=markdown spell spelllang=en_us cc=80 : -->
|
||||
19
local/bin/x-open-ports.md
Normal file
19
local/bin/x-open-ports.md
Normal file
@@ -0,0 +1,19 @@
|
||||
# x-open-ports
|
||||
|
||||
List listening ports using `lsof` or `ss`.
|
||||
|
||||
## Usage
|
||||
|
||||
```bash
|
||||
x-open-ports [--json]
|
||||
```
|
||||
|
||||
- `--json` – output as JSON instead of Markdown
|
||||
|
||||
## Example
|
||||
|
||||
```bash
|
||||
x-open-ports --json
|
||||
```
|
||||
|
||||
<!-- vim: set ft=markdown spell spelllang=en_us cc=80 : -->
|
||||
19
local/bin/x-path-append.md
Normal file
19
local/bin/x-path-append.md
Normal file
@@ -0,0 +1,19 @@
|
||||
# x-path-append
|
||||
|
||||
Append directories to the `PATH` variable without duplicates.
|
||||
|
||||
## Usage
|
||||
|
||||
```bash
|
||||
x-path-append <dir1> [dir2 ...]
|
||||
```
|
||||
|
||||
Set `VERBOSE=1` for verbose logging.
|
||||
|
||||
## Example
|
||||
|
||||
```bash
|
||||
x-path-append /usr/local/sbin "$HOME/bin"
|
||||
```
|
||||
|
||||
<!-- vim: set ft=markdown spell spelllang=en_us cc=80 : -->
|
||||
19
local/bin/x-path-prepend.md
Normal file
19
local/bin/x-path-prepend.md
Normal file
@@ -0,0 +1,19 @@
|
||||
# x-path-prepend
|
||||
|
||||
Prepend directories to the `PATH` variable without duplicates.
|
||||
|
||||
## Usage
|
||||
|
||||
```bash
|
||||
x-path-prepend <dir1> [dir2 ...]
|
||||
```
|
||||
|
||||
Set `VERBOSE=1` for verbose logging.
|
||||
|
||||
## Example
|
||||
|
||||
```bash
|
||||
x-path-prepend "$HOME/bin" /opt/tools
|
||||
```
|
||||
|
||||
<!-- vim: set ft=markdown spell spelllang=en_us cc=80 : -->
|
||||
19
local/bin/x-path-remove.md
Normal file
19
local/bin/x-path-remove.md
Normal file
@@ -0,0 +1,19 @@
|
||||
# x-path-remove
|
||||
|
||||
Remove directories from the `PATH` variable.
|
||||
|
||||
## Usage
|
||||
|
||||
```bash
|
||||
x-path-remove <dir1> [dir2 ...]
|
||||
```
|
||||
|
||||
Set `VERBOSE=1` for verbose logging.
|
||||
|
||||
## Example
|
||||
|
||||
```bash
|
||||
x-path-remove /usr/local/bin
|
||||
```
|
||||
|
||||
<!-- vim: set ft=markdown spell spelllang=en_us cc=80 : -->
|
||||
30
local/bin/x-path.md
Normal file
30
local/bin/x-path.md
Normal file
@@ -0,0 +1,30 @@
|
||||
# x-path
|
||||
|
||||
Manage entries in the `PATH` variable through subcommands.
|
||||
|
||||
## Usage
|
||||
|
||||
```bash
|
||||
x-path <command> <directory1> [directory2 ...]
|
||||
```
|
||||
|
||||
### Commands
|
||||
|
||||
- `append` / `a` – Append directories to `PATH`
|
||||
- `prepend` / `p` – Prepend directories to `PATH`
|
||||
- `remove` – Remove directories from `PATH`
|
||||
- `check` – Validate directories (default: all in `PATH`)
|
||||
|
||||
Set `VERBOSE=1` for progress output.
|
||||
|
||||
## Examples
|
||||
|
||||
```bash
|
||||
# Prepend /opt/bin to PATH
|
||||
x-path prepend /opt/bin
|
||||
|
||||
# Remove /usr/local/bin from PATH
|
||||
x-path remove /usr/local/bin
|
||||
```
|
||||
|
||||
<!-- vim: set ft=markdown spell spelllang=en_us cc=80 : -->
|
||||
14
local/bin/x-quota-usage.php.md
Normal file
14
local/bin/x-quota-usage.php.md
Normal file
@@ -0,0 +1,14 @@
|
||||
# x-quota-usage.php
|
||||
|
||||
Display filesystem quota usage in a human readable table.
|
||||
|
||||
## Usage
|
||||
|
||||
```bash
|
||||
x-quota-usage.php
|
||||
```
|
||||
|
||||
Runs the `quota` command and formats the output. Requires PHP with the
|
||||
`shell_exec` function enabled.
|
||||
|
||||
<!-- vim: set ft=markdown spell spelllang=en_us cc=80 : -->
|
||||
19
local/bin/x-record.md
Normal file
19
local/bin/x-record.md
Normal file
@@ -0,0 +1,19 @@
|
||||
# x-record
|
||||
|
||||
Interactive screen recording wrapper around `giph`.
|
||||
|
||||
## Usage
|
||||
|
||||
```bash
|
||||
x-record <gif|mkv|webm|mp4> <fullscreen|set>
|
||||
```
|
||||
|
||||
The script asks for file type and area when omitted.
|
||||
|
||||
## Example
|
||||
|
||||
```bash
|
||||
x-record gif fullscreen
|
||||
```
|
||||
|
||||
<!-- vim: set ft=markdown spell spelllang=en_us cc=80 : -->
|
||||
14
local/bin/x-set-php-aliases.md
Normal file
14
local/bin/x-set-php-aliases.md
Normal file
@@ -0,0 +1,14 @@
|
||||
# x-set-php-aliases
|
||||
|
||||
---
|
||||
|
||||
## Usage
|
||||
|
||||
```bash
|
||||
source x-set-php-aliases
|
||||
```
|
||||
|
||||
Generates shell aliases (`php80`, `php81` ...) for each Homebrew PHP
|
||||
installation. Caches the list under `$XDG_CACHE_HOME/x-set-php-aliases`.
|
||||
|
||||
<!-- vim: set ft=markdown spell spelllang=en_us cc=80 : -->
|
||||
22
local/bin/x-sha256sum-matcher.md
Normal file
22
local/bin/x-sha256sum-matcher.md
Normal file
@@ -0,0 +1,22 @@
|
||||
# x-sha256sum-matcher
|
||||
|
||||
Compare two files by calculating their SHA256 checksums.
|
||||
|
||||
## Usage
|
||||
|
||||
```bash
|
||||
x-sha256sum-matcher [options] file1 file2
|
||||
```
|
||||
|
||||
Options:
|
||||
|
||||
- `-v` – verbose output
|
||||
- `-h, --help` – show help
|
||||
|
||||
### Example
|
||||
|
||||
```bash
|
||||
x-sha256sum-matcher original.iso download.iso
|
||||
```
|
||||
|
||||
<!-- vim: set ft=markdown spell spelllang=en_us cc=80 : -->
|
||||
22
local/bin/x-ssl-expiry-date.md
Normal file
22
local/bin/x-ssl-expiry-date.md
Normal file
@@ -0,0 +1,22 @@
|
||||
# x-ssl-expiry-date
|
||||
|
||||
Check the expiry date of an SSL certificate for one or more hosts.
|
||||
|
||||
## Usage
|
||||
|
||||
```bash
|
||||
x-ssl-expiry-date [-d] [-p PORT] host1 host2 ...
|
||||
```
|
||||
|
||||
Options:
|
||||
|
||||
- `-d` – show days left instead of the full date
|
||||
- `-p <port>` – use custom port (default: 443)
|
||||
|
||||
### Example
|
||||
|
||||
```bash
|
||||
x-ssl-expiry-date -d github.com
|
||||
```
|
||||
|
||||
<!-- vim: set ft=markdown spell spelllang=en_us cc=80 : -->
|
||||
14
local/bin/x-term-colors.md
Normal file
14
local/bin/x-term-colors.md
Normal file
@@ -0,0 +1,14 @@
|
||||
# x-term-colors
|
||||
|
||||
Display a table of 24‑bit color codes for testing terminal color
|
||||
support.
|
||||
|
||||
## Usage
|
||||
|
||||
```bash
|
||||
x-term-colors
|
||||
```
|
||||
|
||||
Pipe the output to `less -R` to view with color highlighting.
|
||||
|
||||
<!-- vim: set ft=markdown spell spelllang=en_us cc=80 : -->
|
||||
26
local/bin/x-thumbgen.md
Normal file
26
local/bin/x-thumbgen.md
Normal file
@@ -0,0 +1,26 @@
|
||||
# x-thumbgen
|
||||
|
||||
Generate thumbnails using ImageMagick (magick) with MIME type filtering.
|
||||
|
||||
## Usage
|
||||
|
||||
```bash
|
||||
x-thumbgen [options] source_directory
|
||||
```
|
||||
|
||||
Options:
|
||||
|
||||
- `-o DIR` – output directory (default: same as source)
|
||||
- `-s STR` – suffix for thumbnails
|
||||
- `-h` – show help
|
||||
|
||||
Environment variables like `THUMB_BACKGROUND` control the background
|
||||
color.
|
||||
|
||||
### Example
|
||||
|
||||
```bash
|
||||
THUMB_BACKGROUND=black x-thumbgen -o ~/thumbs ~/images
|
||||
```
|
||||
|
||||
<!-- vim: set ft=markdown spell spelllang=en_us cc=80 : -->
|
||||
20
local/bin/x-until-error.md
Normal file
20
local/bin/x-until-error.md
Normal file
@@ -0,0 +1,20 @@
|
||||
# x-until-error
|
||||
|
||||
Repeatedly execute a command until it returns a non-zero exit status.
|
||||
|
||||
## Usage
|
||||
|
||||
```bash
|
||||
x-until-error [--sleep SECONDS] command [args...]
|
||||
```
|
||||
|
||||
Use `--sleep` to wait between runs. The command is executed at least
|
||||
once.
|
||||
|
||||
### Example
|
||||
|
||||
```bash
|
||||
x-until-error --sleep 2 ping -c1 example.com
|
||||
```
|
||||
|
||||
<!-- vim: set ft=markdown spell spelllang=en_us cc=80 : -->
|
||||
20
local/bin/x-until-success.md
Normal file
20
local/bin/x-until-success.md
Normal file
@@ -0,0 +1,20 @@
|
||||
# x-until-success
|
||||
|
||||
Repeat a command until it succeeds (exit status 0). The command is
|
||||
always executed at least once.
|
||||
|
||||
## Usage
|
||||
|
||||
```bash
|
||||
x-until-success [--sleep SECONDS] command [args...]
|
||||
```
|
||||
|
||||
Use `--sleep` to control the delay between attempts.
|
||||
|
||||
### Example
|
||||
|
||||
```bash
|
||||
x-until-success --sleep 5 curl -I https://example.com
|
||||
```
|
||||
|
||||
<!-- vim: set ft=markdown spell spelllang=en_us cc=80 : -->
|
||||
14
local/bin/x-validate-sha256sum.sh.md
Normal file
14
local/bin/x-validate-sha256sum.sh.md
Normal file
@@ -0,0 +1,14 @@
|
||||
# x-validate-sha256sum.sh
|
||||
|
||||
This script contains a helper for sha256 validating your downloads
|
||||
|
||||
## Usage
|
||||
|
||||
```bash
|
||||
x-validate-sha256sum.sh file sha256sum
|
||||
```
|
||||
|
||||
The script computes the SHA256 hash of `file` and compares it to the
|
||||
expected value. It exits non-zero if the sums differ.
|
||||
|
||||
<!-- vim: set ft=markdown spell spelllang=en_us cc=80 : -->
|
||||
13
local/bin/x-welcome-banner.md
Normal file
13
local/bin/x-welcome-banner.md
Normal file
@@ -0,0 +1,13 @@
|
||||
# x-welcome-banner
|
||||
|
||||
Print a colorful MOTD with greeting, system info and today's weather.
|
||||
|
||||
## Usage
|
||||
|
||||
```bash
|
||||
x-welcome-banner
|
||||
```
|
||||
|
||||
Requires optional tools: `neofetch`, `figlet`, `lolcat` and `curl` for extra info.
|
||||
|
||||
<!-- vim: set ft=markdown spell spelllang=en_us cc=80 : -->
|
||||
17
local/bin/x-when-down.md
Normal file
17
local/bin/x-when-down.md
Normal file
@@ -0,0 +1,17 @@
|
||||
# x-when-down
|
||||
|
||||
Wait until a host stops responding to ping, then run a command.
|
||||
|
||||
## Usage
|
||||
|
||||
```bash
|
||||
x-when-down <host> <command...>
|
||||
```
|
||||
|
||||
## Example
|
||||
|
||||
```bash
|
||||
x-when-down 1.2.3.4 echo "server down"
|
||||
```
|
||||
|
||||
<!-- vim: set ft=markdown spell spelllang=en_us cc=80 : -->
|
||||
19
local/bin/x-when-up.md
Normal file
19
local/bin/x-when-up.md
Normal file
@@ -0,0 +1,19 @@
|
||||
# x-when-up
|
||||
|
||||
Wait for a host to respond to ping before running a command.
|
||||
|
||||
## Usage
|
||||
|
||||
```bash
|
||||
x-when-up <host> <command...>
|
||||
```
|
||||
|
||||
If the command is `ssh`, the host argument may be omitted.
|
||||
|
||||
## Example
|
||||
|
||||
```bash
|
||||
x-when-up 1.2.3.4 ssh 1.2.3.4
|
||||
```
|
||||
|
||||
<!-- vim: set ft=markdown spell spelllang=en_us cc=80 : -->
|
||||
@@ -10,7 +10,7 @@
|
||||
"fix:markdown": "npx markdownlint -df .",
|
||||
"lint:prettier": "npx prettier . --check",
|
||||
"fix:prettier": "npx prettier . --write",
|
||||
"test": "echo \"Error: no test specified\" && exit 0"
|
||||
"test": "bash test-all.sh"
|
||||
},
|
||||
"repository": {
|
||||
"type": "git",
|
||||
@@ -29,6 +29,7 @@
|
||||
"devDependencies": {
|
||||
"@ivuorinen/base-configs": "^2.0.0",
|
||||
"@types/node": "^24.0.1",
|
||||
"bats": "^1.12.0",
|
||||
"typescript": "^5.8.3"
|
||||
},
|
||||
"packageManager": "yarn@1.22.22"
|
||||
|
||||
11
scripts/create-aerospace-keymaps.md
Normal file
11
scripts/create-aerospace-keymaps.md
Normal file
@@ -0,0 +1,11 @@
|
||||
# create-aerospace-keymaps
|
||||
|
||||
Generates `docs/aerospace-keybindings.md` using `aerospace config --json`.
|
||||
|
||||
## Usage
|
||||
|
||||
```bash
|
||||
scripts/create-aerospace-keymaps.php
|
||||
```
|
||||
|
||||
Requires the `aerospace` CLI tool to be installed.
|
||||
11
scripts/create-nvim-keymaps.md
Normal file
11
scripts/create-nvim-keymaps.md
Normal file
@@ -0,0 +1,11 @@
|
||||
# create-nvim-keymaps
|
||||
|
||||
Outputs current Neovim key mappings to `docs/nvim-keybindings.md`.
|
||||
|
||||
## Usage
|
||||
|
||||
```bash
|
||||
scripts/create-nvim-keymaps.sh
|
||||
```
|
||||
|
||||
Requires Neovim to be installed.
|
||||
11
scripts/create-wezterm-keymaps.md
Normal file
11
scripts/create-wezterm-keymaps.md
Normal file
@@ -0,0 +1,11 @@
|
||||
# create-wezterm-keymaps
|
||||
|
||||
Generates `docs/wezterm-keybindings.md` by invoking `wezterm show-keys`.
|
||||
|
||||
## Usage
|
||||
|
||||
```bash
|
||||
scripts/create-wezterm-keymaps.sh
|
||||
```
|
||||
|
||||
Requires wezterm to be installed.
|
||||
12
scripts/install-cargo-packages.md
Normal file
12
scripts/install-cargo-packages.md
Normal file
@@ -0,0 +1,12 @@
|
||||
# install-cargo-packages
|
||||
|
||||
Install Rust packages listed in `config/asdf/cargo-packages`.
|
||||
|
||||
## Usage
|
||||
|
||||
```bash
|
||||
scripts/install-cargo-packages.sh
|
||||
```
|
||||
|
||||
The script installs each package with `cargo install` and runs
|
||||
`cargo-install-update` when available to update existing packages.
|
||||
12
scripts/install-cheat-purebashbible.md
Normal file
12
scripts/install-cheat-purebashbible.md
Normal file
@@ -0,0 +1,12 @@
|
||||
# install-cheat-purebashbible
|
||||
|
||||
Fetches the Pure Bash Bible repository and installs its cheatsheets for the
|
||||
`cheat` utility.
|
||||
|
||||
## Usage
|
||||
|
||||
```bash
|
||||
scripts/install-cheat-purebashbible.sh
|
||||
```
|
||||
|
||||
Requires `git` and `cheat` to be available in PATH.
|
||||
11
scripts/install-composer.md
Normal file
11
scripts/install-composer.md
Normal file
@@ -0,0 +1,11 @@
|
||||
# install-composer
|
||||
|
||||
Installs the PHP package manager [Composer](https://getcomposer.org/).
|
||||
|
||||
## Usage
|
||||
|
||||
```bash
|
||||
scripts/install-composer.sh
|
||||
```
|
||||
|
||||
The script downloads the latest Composer PHAR and places it in `$HOME/.local/bin`.
|
||||
11
scripts/install-fonts.md
Normal file
11
scripts/install-fonts.md
Normal file
@@ -0,0 +1,11 @@
|
||||
# install-fonts
|
||||
|
||||
Installs Nerd Fonts used by various terminal and editor setups.
|
||||
|
||||
## Usage
|
||||
|
||||
```bash
|
||||
scripts/install-fonts.sh
|
||||
```
|
||||
|
||||
Fonts are downloaded to `$HOME/.local/share/fonts` and refreshed automatically.
|
||||
12
scripts/install-gh-extensions.md
Normal file
12
scripts/install-gh-extensions.md
Normal file
@@ -0,0 +1,12 @@
|
||||
# install-gh-extensions
|
||||
|
||||
Installs a curated set of GitHub CLI extensions defined in
|
||||
`config/gh/extensions`.
|
||||
|
||||
## Usage
|
||||
|
||||
```bash
|
||||
scripts/install-gh-extensions.sh
|
||||
```
|
||||
|
||||
The script installs each extension using the `gh extension install` command.
|
||||
12
scripts/install-git-crypt.md
Normal file
12
scripts/install-git-crypt.md
Normal file
@@ -0,0 +1,12 @@
|
||||
# install-git-crypt
|
||||
|
||||
Installs `git-crypt` for transparent encryption of files in Git repositories.
|
||||
|
||||
## Usage
|
||||
|
||||
```bash
|
||||
scripts/install-git-crypt.sh
|
||||
```
|
||||
|
||||
After installation you can run `git-crypt init` inside a repository to begin
|
||||
encrypting files.
|
||||
12
scripts/install-go-packages.md
Normal file
12
scripts/install-go-packages.md
Normal file
@@ -0,0 +1,12 @@
|
||||
# install-go-packages
|
||||
|
||||
Installs Go binaries defined in `config/go/packages`.
|
||||
|
||||
## Usage
|
||||
|
||||
```bash
|
||||
scripts/install-go-packages.sh
|
||||
```
|
||||
|
||||
The script uses `go install` for each package path listed in the configuration
|
||||
file.
|
||||
11
scripts/install-macos-defaults.md
Normal file
11
scripts/install-macos-defaults.md
Normal file
@@ -0,0 +1,11 @@
|
||||
# install-macos-defaults
|
||||
|
||||
Applies a set of macOS defaults for a consistent developer environment.
|
||||
|
||||
## Usage
|
||||
|
||||
```bash
|
||||
scripts/install-macos-defaults.sh
|
||||
```
|
||||
|
||||
Requires macOS and the `defaults` command.
|
||||
11
scripts/install-npm-packages.md
Normal file
11
scripts/install-npm-packages.md
Normal file
@@ -0,0 +1,11 @@
|
||||
# install-npm-packages
|
||||
|
||||
Installs global npm packages listed in `config/npm/packages`.
|
||||
|
||||
## Usage
|
||||
|
||||
```bash
|
||||
scripts/install-npm-packages.sh
|
||||
```
|
||||
|
||||
Uses `npm install -g` for each package in the configuration file.
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user