Compare commits

...

123 Commits

Author SHA1 Message Date
88efedf26b feat: updates, docs, license fixes, new helpers 2025-02-12 01:05:37 +02:00
renovate[bot]
cdd68748e0 chore(deps): update node.js to v22.14.0 (#77)
Signed-off-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-02-12 00:35:00 +02:00
github-actions[bot]
f8ff2699e6 chore: update pre-commit hooks (#76) 2025-02-10 14:19:32 +02:00
c5e06888b8 chore(config): update Brewfile, zed settings 2025-02-07 12:41:55 +02:00
renovate[bot]
4f138eee73 fix(container): update image python (3.13.1 → 3.13.2) (#75)
Signed-off-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-02-07 10:02:48 +02:00
github-actions[bot]
90258e5105 chore: update pre-commit hooks (#74) 2025-02-06 13:44:34 +02:00
efc53fc9bf feat(ci): sync-labels from ivuorinen/actions 2025-02-05 09:09:31 +02:00
github-actions[bot]
f62c17d940 chore: update pre-commit hooks (#73)
Co-authored-by: ivuorinen <11024+ivuorinen@users.noreply.github.com>
2025-02-03 14:36:14 +02:00
github-actions[bot]
fb15b93887 chore: update pre-commit hooks (#72)
Co-authored-by: ivuorinen <11024+ivuorinen@users.noreply.github.com>
2025-01-30 09:44:16 +02:00
renovate[bot]
222276486a feat(github-action): update actions/setup-python (v5.3.0 → v5.4.0)
Signed-off-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-01-28 22:37:48 +00:00
github-actions[bot]
4446d59e73 chore: update pre-commit hooks (#71) 2025-01-28 17:08:31 +02:00
a22709a0f0 chore(repo): add-submodules submodule ignore dirty 2025-01-28 14:54:58 +02:00
76598ad33b chore(config): tmux config tweaks, .ignore 2025-01-28 14:51:38 +02:00
56ccb7c136 chore(nvim): plugin tweaks, config tweaks 2025-01-24 01:33:58 +02:00
github-actions[bot]
b6d933d018 chore: update pre-commit hooks (#70) 2025-01-23 08:20:21 +02:00
f9856a27b9 chore(nvim): drop mini.jump, mini.move, update docs 2025-01-22 16:26:45 +02:00
b36b52ad57 chore(config): brew bundle update 2025-01-22 15:13:47 +02:00
1e60ccf49b chore(ssh): ignore submodule changes, tweak config 2025-01-22 15:12:59 +02:00
renovate[bot]
9ca9439b9a chore(deps): update node.js to v22.13.1 (#69)
Signed-off-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-01-22 09:34:00 +02:00
6d30ae7e84 chore(config): aerospace - add phpstorm 2025-01-21 14:08:06 +02:00
031e124663 chore(ssh): ft=sshconfig to turingpi config 2025-01-20 14:51:37 +02:00
bb50c9fe18 chore(scripts): macos default tweaks 2025-01-20 14:50:05 +02:00
8e608de501 chore(config): aerospace tweaks 2025-01-20 14:47:22 +02:00
github-actions[bot]
8917b7736b chore: update pre-commit hooks (#68)
Co-authored-by: ivuorinen <11024+ivuorinen@users.noreply.github.com>
2025-01-20 11:49:36 +02:00
18ff879f1d chore(config): tms colors, depth from 10 to 3 2025-01-17 13:25:32 +02:00
c5a258d7be feat(docs): alias docs and update script 2025-01-17 13:07:15 +02:00
7525f1f71d feat(dfm): dfm apt helper commands 2025-01-16 16:19:45 +02:00
3b665bdba0 chore(nvim): tweaks to lsp, autocommands, sessions 2025-01-16 16:18:50 +02:00
99477364bd chore(bin): t - filters, sorting, tweak checks 2025-01-16 16:17:42 +02:00
github-actions[bot]
629fdf6d4c chore: update pre-commit hooks (#67) 2025-01-16 07:10:21 +02:00
1288599b1f feat(docs): aerospace keybindings and update code 2025-01-15 15:33:01 +02:00
be3a68fecb fix(nvim): intelephense license loading 2025-01-14 07:23:51 +02:00
101e4da1d6 feat(bin): x-env-list, list ENV with protection 2025-01-14 07:01:22 +02:00
23430a609a chore(bin): dfm cleanup, tweaks 2025-01-14 06:59:36 +02:00
bb0d56e403 chore(config): wezterm config tweaks 2025-01-14 06:59:00 +02:00
d3b08bdf4f chore(config): add laravel shortcuts 2025-01-14 06:58:40 +02:00
e1ec501c55 chore(config): add local version of git-root cmd 2025-01-14 06:57:40 +02:00
f92c3407f0 feat(nvim): reintro noice.nvim 2025-01-14 06:56:56 +02:00
b5971439b6 feat(nvim): drop lspsaga.nvim 2025-01-14 06:56:29 +02:00
8ea8a2797a chore(nvim): keymap tweaks 2025-01-14 06:55:57 +02:00
b0f9222482 chore(nvim): move flash.nvim keymap defs 2025-01-14 06:52:34 +02:00
825ccc1031 chore(nvim): drop tokyonight customizations 2025-01-14 06:50:59 +02:00
dab7a8a38a chore(nvim): lsp sign definitions, icons, settings 2025-01-14 06:50:15 +02:00
1dbc7ae5cd chore(nvim): move mason tools to visible place 2025-01-14 06:47:24 +02:00
7038da568e chore(nvim): add support for intelephense license 2025-01-14 06:46:10 +02:00
bfcaa26070 chore(nvim): trouble.nvim related tweaks 2025-01-14 06:42:18 +02:00
f6488aecce chore(nvim): tweaks to options, cleanup 2025-01-14 06:39:36 +02:00
ad166e8012 feat(bin): t, add support for existing sessions 2025-01-14 05:56:19 +02:00
2a76a414a0 feat(config): split tmux config, add helpers 2025-01-14 05:50:19 +02:00
bb8ddf0bba chore(config): aerospace, add preview to floaters 2025-01-14 05:47:57 +02:00
bf3e746010 chore(base): add .ignore to limit searched files 2025-01-14 05:47:18 +02:00
github-actions[bot]
b9957e4f0e chore: update pre-commit hooks (#66)
Co-authored-by: ivuorinen <11024+ivuorinen@users.noreply.github.com>
2025-01-13 12:56:43 +02:00
e1deba4ccf chore(config): antidote, remove tmux plugin 2025-01-12 15:39:48 +02:00
36e4de3035 chore(nvim): add lazydev to blink.cmp completions 2025-01-10 22:13:00 +02:00
3eab1faeab chore(config): alias changes, remove .dx, add .o 2025-01-10 22:02:29 +02:00
1eb4098646 chore(shell): p10k aws, go and nvm section color 2025-01-10 22:01:05 +02:00
f7db8cae15 chore(shell): p10k config docs line width 2025-01-10 22:00:04 +02:00
97dd3dc21d chore(nvim): blink.cmp LuaSnip support, cleanup 2025-01-10 21:57:58 +02:00
6da6797f1b chore(config): tmux config tweaks
moved config around, did cleanup and moved TMUX_TMPDIR
under XDG_STATE_HOME. added the state/tmux folder creation
to the dotbot install config.
2025-01-10 21:56:39 +02:00
github-actions[bot]
88356f1392 chore: update pre-commit hooks (#65)
Co-authored-by: ivuorinen <11024+ivuorinen@users.noreply.github.com>
2025-01-10 01:26:03 +02:00
174bb842e9 chore(config): tmux config tweaks 2025-01-08 18:10:03 +02:00
f6e7590118 chore(hosts): remove ref to non-existent Brewfile 2025-01-08 03:35:15 +02:00
498996a6e2 chore(config): remove antigen config 2025-01-08 03:34:13 +02:00
0961985fb4 fix(nvim): vim-textobj-xmlattr init 2025-01-08 03:32:22 +02:00
293452604d feat(ci): add codeowners file 2025-01-08 03:31:53 +02:00
renovate[bot]
9582f18c7d chore(deps): update node.js to v22.13.0 (#64)
Signed-off-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-01-08 03:23:14 +02:00
051e3604ee feat(bin): x-localip - show active interfaces ips 2025-01-07 21:45:03 +02:00
09d62dd159 feat(nvim): plugins, fixes, helpers
Plugins:
- voldikss/vim-floaterm
- vim-test/vim-test
- tpope/vim-projectionist
- phpactor/phpactor
- catgoose/nvim-colorizer.lua

Fixes:
- lsp diagnostics config
- lsp diagnostics icons
- neo-tree configuration fixes
- tokyonight.nvim color scheme tweaks

Lots of tweaks to options.lua
2025-01-07 21:41:56 +02:00
8a3763e168 chore(config): zed config tweaks 2025-01-07 21:29:49 +02:00
c37793f649 chore(config): tmux config tweaks, new settings 2025-01-07 21:29:25 +02:00
7bc7230990 chore(config): cleanup aliases, shellcheck fixes 2025-01-07 21:23:26 +02:00
067df4e34b feat(bin): t, custom tmux session manager
- drops tms bindings from tmux config, wasn't using them
- drops t alias for tail -f, clashed with t script
2025-01-07 21:22:27 +02:00
4d28499423 chore(config): tmux config tweaks
- undercurl support
- underscore colors
- nvim split aware moving
- detach-on-destroy off
- session name display in status-right
- escape-time to zero
- default terminal to use $TERM
2025-01-07 15:58:16 +02:00
b685af82fb chore(brew): update brewfile 2025-01-07 15:05:05 +02:00
github-actions[bot]
b8a4b82431 chore: update pre-commit hooks (#63) 2025-01-06 13:44:20 +02:00
0b03acebd8 feat(config): tmux plugin tmux-fzf-url 2025-01-02 22:22:59 +02:00
d172b86cb8 chore(docs): update nvim, tmux, wezterm keymaps 2025-01-02 17:46:07 +02:00
f910dfb9ac chore(nvim): add lazy dev path, enable profiling 2025-01-02 17:36:53 +02:00
ee95d57ba0 chore(config): aerospace tweaks 2025-01-02 17:34:48 +02:00
f8a317f3c7 chore(dfm): install script cleanup 2025-01-02 15:18:48 +02:00
3762e10932 chore(config): aerospace docker desktop layout 2025-01-02 14:53:59 +02:00
afda96902b chore(config): ghostty tweaks 2025-01-02 14:53:20 +02:00
3060b6ad66 chore(nvim): mason tools, sessionopts 2025-01-02 14:15:06 +02:00
github-actions[bot]
4f154cf509 chore: update pre-commit hooks (#62)
Co-authored-by: ivuorinen <11024+ivuorinen@users.noreply.github.com>
2025-01-02 11:41:43 +02:00
863d803483 feat(config): zed config 2024-12-30 17:53:56 +02:00
07bb2b56d1 feat(config): glow config 2024-12-30 17:51:47 +02:00
84a753100e feat(config): ghostty config 2024-12-30 17:51:26 +02:00
c8b01f3fda chore(config): aerospace tweaks 2024-12-30 17:50:47 +02:00
8e6a110aac chore(ci): pre-commit - detect-aws-creds 2024-12-30 17:49:50 +02:00
a8baa1671f chore(config): fix terminfo, add ghostty inits 2024-12-30 17:27:45 +02:00
2ccdd042f6 chore: sort gitignore, echo submodule ignore status 2024-12-30 17:26:35 +02:00
github-actions[bot]
8cf43ed555 chore: update pre-commit hooks (#60)
Co-authored-by: ivuorinen <11024+ivuorinen@users.noreply.github.com>
2024-12-30 15:05:15 +02:00
e22094e0da fix(dfm): asdf plugin-install, docs translations 2024-12-30 11:26:54 +02:00
6186c5cba4 chore(config): tmux ignore md5 in window name 2024-12-28 19:02:55 +02:00
c453dcbf84 chore(nvim): statusline tweaks 2024-12-28 19:02:14 +02:00
4daaa62aed feat(dfm): scripts/install-* to autocomplete, docs 2024-12-28 19:01:45 +02:00
f56d5682d1 chore(nvim): shellscript formatting with shfmt 2024-12-28 18:59:59 +02:00
439638b686 chore(config): tweaks to aerospace config 2024-12-28 18:59:38 +02:00
a8a473a46d chore: shfmt, cleanup 2024-12-28 18:59:09 +02:00
eb91a43bbd feat(asdf): drop asdf-plugin-manager, use dotbot-asdf 2024-12-28 16:58:31 +02:00
github-actions[bot]
193fae662e chore: update pre-commit hooks (#58)
Co-authored-by: ivuorinen <11024+ivuorinen@users.noreply.github.com>
2024-12-27 05:18:32 +02:00
github-actions[bot]
117ca1a944 chore: update pre-commit hooks (#57)
Co-authored-by: ivuorinen <11024+ivuorinen@users.noreply.github.com>
2024-12-25 15:31:39 +02:00
1f1a6d42ad fix(ci): update-submodules cron syntax 2024-12-25 15:30:49 +02:00
cca265cd99 chore(ci): update update-submodules schedule 2024-12-25 15:15:53 +02:00
cc6abb53ba chore(ci): update pre-commit-autoupdate 2024-12-25 14:34:38 +02:00
ab34c148a6 feat(bin): age tools (#20)
* wip: ae for encryption, ad for decryption
* feat: finished ad and ae, created a for both uses
2024-12-24 09:31:25 +02:00
github-actions[bot]
910b29ed9f chore: update pre-commit hooks (#56) 2024-12-24 06:50:02 +02:00
3fb0a75a62 feat(asdf): update automation, versions, plugins 2024-12-24 00:59:50 +02:00
github-actions[bot]
f73abb508b chore: update pre-commit hooks (#55)
Co-authored-by: ivuorinen <11024+ivuorinen@users.noreply.github.com>
2024-12-23 13:00:01 +02:00
github-actions[bot]
1dd3d952cf chore: update pre-commit hooks (#54)
Co-authored-by: ivuorinen <11024+ivuorinen@users.noreply.github.com>
2024-12-22 02:07:59 +02:00
1ffd6e1569 feat(nvim): update blink config 2024-12-20 22:54:17 +02:00
a76033a48a chore(deps): update Brewfile 2024-12-20 18:55:14 +02:00
34dc18883e chore(config): aerospace tweaks 2024-12-20 18:14:57 +02:00
832d8b94f3 chore(nvim): add the awesome youtube video to mini 2024-12-20 12:37:00 +02:00
c40eb765f8 chore(config): tweak aerospace config 2024-12-20 12:06:37 +02:00
github-actions[bot]
1bb7e9076b chore: update pre-commit hooks (#53)
Co-authored-by: ivuorinen <11024+ivuorinen@users.noreply.github.com>
2024-12-20 10:11:10 +02:00
ivuorinen
17821dfefa chore(git): Update submodules (automated)
asdf 54d15e3
antidote
dotbot v1.20.4
2024-12-20 03:09:26 +00:00
19327947ed chore(config): tweak aerospace config 2024-12-19 12:48:41 +02:00
2356fc4c61 chore(deps): update asdf submodule 2024-12-19 12:48:26 +02:00
45219deccb fix(nvim): nvmdef - fix log levels for now 2024-12-19 12:46:53 +02:00
5471aba1a4 chore(nvim): autosession, configs, tweaks 2024-12-19 12:42:20 +02:00
github-actions[bot]
6f6ee3611c chore: update pre-commit hooks (#52)
Co-authored-by: ivuorinen <11024+ivuorinen@users.noreply.github.com>
2024-12-19 12:24:10 +02:00
ivuorinen
d8f9cdf265 chore(git): Update submodules (automated)
asdf 9c12b79
antidote
2024-12-19 03:14:30 +00:00
126 changed files with 4995 additions and 1791 deletions

View File

@@ -26,6 +26,8 @@ indent_size = 1
indent_style = tab
[{local/bin/*,**/*.sh,**/zshrc,config/*,scripts/*}]
indent_size = 2
tab_width = 2
shell_variant = bash # --language-variant
binary_next_line = true
switch_case_indent = true # --case-indent
@@ -37,5 +39,5 @@ function_next_line = true # --func-next-line
# such as "shfmt -l -w .". When formatting files directly,
# like "shfmt -w third_party/foo.sh" or "shfmt --filename=third_party/foo.sh",
# the ignore logic is applied only when the --apply-ignore flag is given.
[{tools/**,local/bin/asdf/**,config/cheat/cheatsheets/**}]
[{tools/**,local/bin/asdf/**,config/cheat/cheatsheets/**,config/tmux/plugins/**}]
ignore = true

1
.github/CODEOWNERS vendored Normal file
View File

@@ -0,0 +1 @@
* @ivuorinen

View File

@@ -2,7 +2,8 @@
name: Pre-commit autoupdate
on:
schedule:
- cron: "0 0 * * *"
# At 04:00 on Monday and Thursday.
- cron: "0 4 * * 1,4"
workflow_dispatch:
jobs:
auto-update:
@@ -12,7 +13,7 @@ jobs:
pull-requests: write
steps:
- uses: actions/checkout@v4
- uses: actions/setup-python@v5.3.0
- uses: actions/setup-python@v5.4.0
- run: pip install pre-commit && pre-commit autoupdate
- uses: peter-evans/create-pull-request@v7
with:

23
.github/workflows/sync-labels.yml vendored Normal file
View File

@@ -0,0 +1,23 @@
---
name: Sync labels
# yamllint disable-line rule:truthy
on:
push:
branches:
- main
paths:
- .github/workflows/sync-labels.yml
- .github/labels.yml
schedule:
- cron: "34 5 * * *"
workflow_call:
workflow_dispatch:
jobs:
SyncLabels:
permissions:
issues: write
runs-on: ubuntu-latest
steps:
- uses: ivuorinen/actions/sync-labels@main

View File

@@ -1,7 +1,9 @@
---
name: Update submodules
on:
schedule: [{ cron: 0 3 * * * }]
schedule:
# At 04:00 on Monday and Thursday.
- cron: "0 4 * * 1,4"
workflow_dispatch:
jobs:
update-submodules:

45
.gitignore vendored
View File

@@ -1,32 +1,35 @@
Brewfile.lock.json
lazy-lock.json
config/nvim/lazy-lock.json
*.log
!.gitkeep
*-secret
*.bak
*.log
*.socket
*cache
.env
.idea
.nfs*
.vscode
Brewfile.lock.json
antidote_plugins.zsh
config/alacritty/theme-active.toml
config/cheat/cheatsheets/pure-bash-bible/*
config/cheat/cheatsheets/tldr/*
config/git/credentials
config/npm/npmrc
config/zsh/.zcompdump
config/alacritty/theme-active.toml
ssh/local.d/*
!ssh/local.d/.gitkeep
!.gitkeep
.env
local/share/fonts/*
node_modules
.nfs*
*.socket
iTermServer-*
lock
config/iterm2/AppSupport
config/gnupg/S.*
config/gnupg/s
config/gnupg/private-keys-v1.d
config/gnupg/s
config/iterm2/AppSupport
config/npm/npmrc
config/nvim/lazy-lock.json
config/nvim/spell/*
!config/nvim/spell/.gitkeep
antidote_plugins.zsh
config/zed/*
!config/zed/settings.json
config/zsh/.zcompdump
iTermServer-*
lazy-lock.json
local/share/fonts/*
local/bin/asdf/plugins/*
lock
node_modules
ssh/local.d/*
!ssh/local.d/.gitkeep

27
.gitmodules vendored
View File

@@ -1,4 +1,4 @@
# vim: set expandtab:
# vim: noexpandtab filetype=gitconfig
[submodule "dotbot"]
path = tools/dotbot
url = https://github.com/anishathalye/dotbot.git
@@ -23,44 +23,69 @@
path = config/tmux/plugins/tmux-continuum
url = https://github.com/tmux-plugins/tmux-continuum
ignore = dirty
[submodule "tmux/tmux-sensible"]
path = config/tmux/plugins/tmux-sensible
url = https://github.com/tmux-plugins/tmux-sensible.git
ignore = dirty
[submodule "tmux/tmux-sessionist"]
path = config/tmux/plugins/tmux-sessionist
url = https://github.com/tmux-plugins/tmux-sessionist.git
ignore = dirty
[submodule "tmux/tmux-yank"]
path = config/tmux/plugins/tmux-yank
url = https://github.com/tmux-plugins/tmux-yank.git
ignore = dirty
[submodule "tmux/tmux-window-name"]
path = config/tmux/plugins/tmux-window-name
url = https://github.com/ivuorinen/tmux-window-name.git
ignore = dirty
[submodule "dotbot-pip"]
path = tools/dotbot-pip
url = https://github.com/sobolevn/dotbot-pip.git
ignore = dirty
[submodule "tmux/tmux-suspend"]
path = config/tmux/plugins/tmux-suspend
url = https://github.com/MunifTanjim/tmux-suspend.git
ignore = dirty
[submodule "tmux/tmux-mode-indicator"]
path = config/tmux/plugins/tmux-mode-indicator
url = https://github.com/MunifTanjim/tmux-mode-indicator.git
ignore = dirty
[submodule "tmux/tmux-current-pane-hostname"]
path = config/tmux/plugins/tmux-current-pane-hostname
url = https://github.com/soyuka/tmux-current-pane-hostname.git
ignore = dirty
[submodule "cheat-tldr"]
path = config/cheat/cheatsheets/tldr
url = https://github.com/ivuorinen/cheatsheet-tldr.git
ignore = dirty
[submodule "tmux/tmux-dark-notify"]
path = config/tmux/plugins/tmux-dark-notify
url = https://github.com/erikw/tmux-dark-notify.git
ignore = dirty
[submodule "asdf"]
path = local/bin/asdf
url = https://github.com/asdf-vm/asdf.git
ignore = dirty
[submodule "antidote"]
path = tools/antidote
url = https://github.com/mattmc3/antidote.git
shallow = true
ignore = dirty
[submodule "dotbot-asdf"]
path = tools/dotbot-asdf
url = https://github.com/sobolevn/dotbot-asdf
ignore = dirty

2
.nvmrc
View File

@@ -1 +1 @@
22.12.0
22.14.0

View File

@@ -3,6 +3,7 @@ repos:
rev: v5.0.0
hooks:
- id: requirements-txt-fixer
- id: detect-aws-credentials
- id: detect-private-key
- id: trailing-whitespace
args: [--markdown-linebreak-ext=md]
@@ -22,10 +23,10 @@ repos:
args: [--autofix, --no-sort-keys]
- repo: https://github.com/igorshubovych/markdownlint-cli
rev: v0.43.0
rev: v0.44.0
hooks:
- id: markdownlint
args: [-c, .markdownlint.yaml, --fix]
args: [-c, .markdownlint.json, --fix]
- repo: https://github.com/adrienverge/yamllint
rev: v1.35.1
@@ -43,12 +44,12 @@ repos:
- id: shfmt
- repo: https://github.com/rhysd/actionlint
rev: v1.7.4
rev: v1.7.7
hooks:
- id: actionlint
- repo: https://github.com/renovatebot/pre-commit-hooks
rev: 39.72.2
rev: 39.164.1
hooks:
- id: renovate-config-validator

View File

@@ -1 +1 @@
3.13.1
3.13.2

View File

@@ -24,3 +24,7 @@ disable=SC1091
# SC2174: When used with -p, -m only applies to the deepest directory.
# https://github.com/koalaman/shellcheck/wiki/SC2174
disable=SC2174
# SC2016: Expressions don't expand in single quotes, use double quotes for that.
# https://www.shellcheck.net/wiki/SC2016
disable=SC2016

View File

@@ -9,6 +9,8 @@ git submodule add --name dotbot-include \
-f https://gitlab.com/gnfzdz/dotbot-include.git tools/dotbot-include
git submodule add --name dotbot-pip \
-f https://github.com/sobolevn/dotbot-pip.git tools/dotbot-pip
git submodule add --name dotbot-asdf \
-f https://github.com/sobolevn/dotbot-asdf tools/dotbot-asdf
# other repos
git submodule add --name cheat-community \
@@ -19,8 +21,7 @@ git submodule add --name asdf \
-f https://github.com/asdf-vm/asdf.git local/bin/asdf
git submodule add --name antidote \
--depth 1 \
-f https://github.com/mattmc3/antidote.git tools/antidote \
-f https://github.com/mattmc3/antidote.git tools/antidote
# tmux plugin manager and plugins
git submodule add --name tmux/tmux-continuum \
@@ -44,7 +45,8 @@ git submodule add --name tmux/tmux-dark-notify \
# Takes submodules and sets them to ignore all changes
for MODULE in $(git config --file .gitmodules --get-regexp path | awk '{ print $2 }'); do
git config "submodule.${MODULE}.ignore" all
echo "Ignoring submodule changes for submodule.${MODULE}..."
git config "submodule.${MODULE}.ignore" "dirty"
done
# Mark certain repositories shallow

View File

@@ -7,6 +7,10 @@ export SHARED_SCRIPTS_SOURCED=0
source "$DOTFILES/config/shared.sh"
if [ -n "${GHOSTTY_RESOURCES_DIR}" ]; then
builtin source "${GHOSTTY_RESOURCES_DIR}/shell-integration/bash/ghostty.bash"
fi
# shellcheck source=../config/fzf/fzf.bash
[ -f "${DOTFILES}/config/fzf/fzf.bash" ] &&
source "${DOTFILES}/config/fzf/fzf.bash"

6
base/ignore Normal file
View File

@@ -0,0 +1,6 @@
Applications/
Library/
Movies/
Music/
Pictures/
Google Drive/

View File

@@ -1,27 +1,19 @@
asdf-plugin-manager 1.4.0
golang 1.23.3
ruby 3.3.4
rust 1.82.0
golang 1.23.4
rust 1.83.0
direnv 2.35.0
fd 10.2.0
1password-cli 2.30.3
age 1.2.0
bottom 0.10.2
age 1.2.1
dotenv-linter 3.3.0
editorconfig-checker 2.8.0
github-cli 2.61.0
github-cli 2.64.0
hadolint 2.12.0
kubectl 1.31.2
kubectl 1.32.0
pre-commit 4.0.1
ripgrep 14.1.1
shellcheck 0.10.0
shfmt 3.10.0
terragrunt 0.68.8
tf-summarize 0.3.13
terragrunt 0.71.1
tf-summarize 0.3.14
yamllint 1.35.1
yq 4.44.3
bats 1.11.0
gitleaks 8.18.4
delta 0.18.1
eza 0.20.8
sops 3.9.1
yq 4.44.6

View File

@@ -45,6 +45,10 @@ setup_tmux_window_name_plugin()
fi
}
if [[ -n $GHOSTTY_RESOURCES_DIR ]]; then
source "$GHOSTTY_RESOURCES_DIR"/shell-integration/zsh/ghostty-integration
fi
source_fzf_config
setup_tmux_window_name_plugin
x-have antidot && eval "$(antidot init)"

View File

@@ -8,7 +8,7 @@ enable-normalization-opposite-orientation-for-nested-containers = true
# See: https://nikitabobko.github.io/AeroSpace/guide#layouts
# The 'accordion-padding' specifies the size of accordion padding
# You can set 0 to disable the padding feature
accordion-padding = 40
accordion-padding = 10
# Possible values: tiles|accordion
default-root-container-layout = 'tiles'
@@ -40,12 +40,81 @@ automatically-unhide-macos-hidden-apps = true
# run = ['layout floating', 'move-node-to-workspace S'] # The callback itself
[[on-window-detected]]
if.app-name-regex-substring = 'ferdium'
run = 'layout floating'
if.app-name-regex-substring = 'settings' # All settings
run = ['layout floating']
[[on-window-detected]]
if.app-name-regex-substring = 'finder'
run = 'layout floating'
if.app-id = 'com.apple.systempreferences' # macOS System Preferences
run = ['layout floating']
[[on-window-detected]]
if.app-id = 'com.1password.1password' # 1Password
run = ['layout floating']
[[on-window-detected]]
if.app-id = 'org.ferdium.ferdium-app' # Ferdium, has WhatsApp etc.
run = ['layout floating']
[[on-window-detected]]
if.app-id = 'com.jetbrains.PhpStorm' # PhpStorm
run = ['layout floating']
[[on-window-detected]]
if.app-id = 'com.apple.finder' # Finder
run = ['layout floating']
[[on-window-detected]]
if.app-id = 'com.apple.Preview' # Preview
run = ['layout floating']
[[on-window-detected]]
if.app-id = 'com.apple.mail' # Mail
run = ['layout floating']
[[on-window-detected]]
if.app-id = 'com.DanPristupov.Fork' # Fork
run = ['layout floating']
[[on-window-detected]]
if.app-id = 'com.flexibits.fantastical2.mac' # Fantastical
run = ['layout floating']
[[on-window-detected]]
if.app-id = 'org.whispersystems.signal-desktop' # Signal
run = ['layout floating']
[[on-window-detected]]
if.app-id = 'com.tidal.desktop' # TIDAL
run = ['layout floating', 'move-node-to-workspace 2'] # Float and move to workspace 2
[[on-window-detected]]
if.app-id = 'com.apple.TV' # Apple TV app
run = ['layout floating']
[[on-window-detected]]
if.app-id = 'com.setapp.DesktopClient' # Setapp
run = ['layout floating']
[[on-window-detected]]
if.app-id = 'com.electron.dockerdesktop' # Docker Desktop
run = ['layout floating']
[[on-window-detected]]
if.app-id = 'com.tinyspeck.slackmacgap' # Slack
run = ['layout floating']
[[on-window-detected]]
if.app-id = 'md.obsidia' # Obsidian
run = ['layout floating']
[[on-window-detected]]
if.app-id = 'com.todoist.mac.Todoist' # Todoist
run = ['layout floating']
[[on-window-detected]]
if.app-id = 'com.apple.backup.launcher' # TimeMachine
run = ['layout floating']
# Possible values: (qwerty|dvorak)
# See https://nikitabobko.github.io/AeroSpace/guide#key-mapping
@@ -60,12 +129,12 @@ preset = 'qwerty'
# Monitor pattern is the same as for 'workspace-to-monitor-force-assignment'.
# See: https://nikitabobko.github.io/AeroSpace/guide#assign-workspaces-to-monitors
[gaps]
inner.horizontal = 10
inner.vertical = 10
outer.top = 5
outer.right = 10
outer.bottom = 5
outer.left = 10
inner.horizontal = 5
inner.vertical = 5
outer.top = [{ monitor.'^built-in retina display$' = 0 }, 0]
outer.right = 0
outer.bottom = 0
outer.left = 0
# 'main' binding mode declaration
# See: https://nikitabobko.github.io/AeroSpace/guide#binding-modes
@@ -73,6 +142,9 @@ outer.left = 10
# Fallback value (if you omit the key): mode.main.binding = {}
[mode.main.binding]
cmd-h = [] # Disable "hide application"
cmd-alt-h = [] # Disable "hide others"
# All possible keys:
# - Letters. a, b, c, ..., z
# - Numbers. 0, 1, 2, ..., 9
@@ -97,17 +169,9 @@ outer.left = 10
# end tell'
# '''
alt-ctrl-shift-f = 'fullscreen'
alt-ctrl-f = 'layout floating'
alt-shift-left = 'join-with left'
alt-shift-down = 'join-with down'
alt-shift-up = 'join-with up'
alt-shift-right = 'join-with right'
# See: https://nikitabobko.github.io/AeroSpace/commands#layout
alt-period = 'layout tiles horizontal vertical'
alt-comma = 'layout accordion horizontal vertical'
# alt-cmd-shift-f = 'fullscreen'
# alt-shift-f = 'layout floating'
# alt-shift-tab = 'move-workspace-to-monitor --wrap-around next'
# See: https://nikitabobko.github.io/AeroSpace/commands#focus
alt-h = 'focus left'
@@ -115,49 +179,66 @@ alt-j = 'focus down'
alt-k = 'focus up'
alt-l = 'focus right'
# See: https://nikitabobko.github.io/AeroSpace/commands#move
alt-shift-h = 'move left'
alt-shift-j = 'move down'
alt-shift-k = 'move up'
alt-shift-l = 'move right'
# See: https://nikitabobko.github.io/AeroSpace/commands#resize
alt-shift-minus = 'resize smart -50'
alt-shift-equal = 'resize smart +50'
# See: https://nikitabobko.github.io/AeroSpace/commands#workspace
alt-1 = 'workspace 1'
alt-2 = 'workspace 2'
alt-3 = 'workspace 3'
alt-4 = 'workspace 4'
alt-shift-1 = 'workspace 1' # Main
alt-shift-2 = 'workspace 2' # Media
ctrl-shift-1 = 'move-node-to-workspace 1' # Move node to Main
ctrl-shift-2 = 'move-node-to-workspace 2' # Move node to Media
# See: https://nikitabobko.github.io/AeroSpace/commands#move-node-to-workspace
alt-shift-1 = 'move-node-to-workspace 1 --focus-follows-window'
alt-shift-2 = 'move-node-to-workspace 2 --focus-follows-window'
alt-shift-3 = 'move-node-to-workspace 3 --focus-follows-window'
alt-shift-4 = 'move-node-to-workspace 4 --focus-follows-window'
alt-tab = 'workspace-back-and-forth'
alt-shift-tab = 'move-workspace-to-monitor --wrap-around next'
alt-shift-tab = 'workspace-back-and-forth' # Switch between workspaces
ctrl-shift-tab = 'move-workspace-to-monitor --wrap-around prev'
# See: https://nikitabobko.github.io/AeroSpace/commands#mode
alt-shift-semicolon = 'mode service'
alt-shift-enter = 'mode apps'
# Taken:
# - <alt> + hjkl 1234 ,.
# - <alt><shift> + hjkl 1234 -=; <cr> ↑↓←→
alt-t = 'exec-and-forget open -a /Applications/Ferdium.app'
alt-o = 'exec-and-forget open -a /Applications/Obsidian.app'
alt-b = 'exec-and-forget open -a /Applications/Brave Browser.app'
# 'service' binding mode declaration.
# See: https://nikitabobko.github.io/AeroSpace/guide#binding-modes
[mode.service.binding]
alt-a = 'mode apps'
alt-s = 'mode service'
alt-m = 'mode move'
# ╭──────────────────────────────────────────────────────────╮
# │ alt-m │
# ╰──────────────────────────────────────────────────────────╯
[mode.move.binding]
esc = ['reload-config', 'mode main']
# See: https://nikitabobko.github.io/AeroSpace/commands#move-node-to-workspace
1 = ['move-node-to-workspace 1 --focus-follows-window']
2 = ['move-node-to-workspace 2 --focus-follows-window']
# See: https://nikitabobko.github.io/AeroSpace/commands#move
h = 'move left'
j = 'move down'
k = 'move up'
l = 'move right'
# See: https://nikitabobko.github.io/AeroSpace/commands#join-with
shift-h = 'join-with left'
shift-j = 'join-with down'
shift-k = 'join-with up'
shift-l = 'join-with right'
# https://nikitabobko.github.io/AeroSpace/commands#resize
ctrl-h = 'resize smart -70'
ctrl-l = 'resize smart +70'
shift-left = 'resize smart +70'
shift-right = 'resize smart -70'
# https://nikitabobko.github.io/AeroSpace/commands#flatten-workspace-tree
r = ['flatten-workspace-tree', 'mode main'] # reset layout
# ╭──────────────────────────────────────────────────────────╮
# │ alt-a │
# ╰──────────────────────────────────────────────────────────╯
[mode.apps.binding]
esc = ['reload-config', 'mode main']
b = ['exec-and-forget open -a /Applications/Brave Browser.app', 'mode main'] # Browser
c = ['exec-and-forget open -a /Applications/Ferdium.app', 'mode main'] # Chat
g = ['exec-and-forget open -a /Applications/Ghostty.app', 'mode main'] # Ghostty
o = ['exec-and-forget open -a /Applications/Obsidian.app', 'mode main'] # Obsidian
s = ['exec-and-forget open -a /Applications/Slack.app', 'mode main'] # Slack
t = ['exec-and-forget open -a /Applications/TIDAL.app', 'mode main'] # Tidal
w = ['exec-and-forget open -a /Applications/WezTerm.app', 'mode main'] # WezTerm
# ╭──────────────────────────────────────────────────────────╮
# │ alt-s │
# ╰──────────────────────────────────────────────────────────╯
[mode.service.binding]
esc = ['reload-config', 'mode main'] # reload config
r = ['flatten-workspace-tree', 'mode main'] # reset layout
# See: https://nikitabobko.github.io/AeroSpace/commands#layout
f = ['layout floating tiling', 'mode main'] # Toggle between floating and tiling layout
backspace = ['close-all-windows-but-current', 'mode main']
[mode.apps.binding]
alt-w = ['exec-and-forget open -a /Applications/WezTerm.app', 'mode main']

View File

@@ -12,16 +12,27 @@ alias ..="cd .."
alias ...="cd ../.."
alias ....="cd ../../.."
# Get git repository root path
get_git_root()
{
# check that we are in a git repository
if git rev-parse --is-inside-work-tree &> /dev/null; then
git rev-parse --show-toplevel
else
>&2 msgr err "Not in a git repository"
fi
}
# cd to git root directory
alias cdgr='cd "$(git root)"'
alias cdgr='cd "$(get_git_root)"'
# interesting folders, and shortcuts
alias .="cd $HOME"
alias .b="cd $XDG_BIN_HOME"
alias .c="cd $HOME/Code"
alias .d="cd $DOTFILES"
alias .dx="cd $DOTFILES;ks"
alias .l="cd $HOME/.local"
alias .='cd $HOME'
alias .b='cd $XDG_BIN_HOME'
alias .c='cd $HOME/Code'
alias .d='cd $DOTFILES'
alias .l='cd $HOME/.local'
alias .o='cd $HOME/Code/ivuorinen/obsidian/'
# Shortcuts for listing
alias ll="ls -la"
@@ -31,13 +42,10 @@ alias l="ls -a"
alias cd..="cd .."
alias sl="ls"
# List only directories
alias lsd="ls -lF | grep '^d'"
# IP addresses
alias x-ip="dig +short myip.opendns.com @resolver1.opendns.com"
alias localip="ipconfig getifaddr en1"
alias ips="ifconfig -a | grep -o 'inet6\? \(\([0-9]\+\.[0-9]\+\.[0-9]\+\.[0-9]\+\)\|[a-fA-F0-9:]\+\)' | sed -e 's/inet6* //'"
alias ips="ifconfig -a | grep -o 'inet6\? \(\([0-9]\+\.[0-9]\+\.[0-9]\+\.[0-9]\+\)\|[a-fA-F0-9:]\+\)' | sed -e 's/inet6* //' | sort"
# Show/hide hidden files in Finder
alias show="defaults write com.apple.finder AppleShowAllFiles -bool true; killall Finder"
@@ -57,14 +65,7 @@ alias isodate="date +'%Y-%m-%d'"
alias x-datetime="date +'%Y-%m-%d %H:%M:%S'"
alias x-timestamp="date +'%s'"
# tmux: automatically attach or create session with name 'main'
alias tm='command tmux new-session -A -s main'
# tmux: attach or create new session
alias ta='command tmux attach || command tmux'
# nvim
alias c='nvim'
alias ks='nvim'
# nvim aliases
alias vi='nvim'
alias vim='nvim'
@@ -79,8 +80,6 @@ alias zapds='find . -name ".DS_Store" -print -delete'
alias zappyc="find . -type f -name '*.pyc' -ls -delete"
# Run all zaps
alias zapall="zapds && zappyc"
# tail with follow flag on
alias t='tail -f'
# directory usage, return only the total
alias dn='du -chd1'
# Mirror site with wget
@@ -88,6 +87,7 @@ alias mirror_site='wget -m -k -K -E -e robots=off'
# Mirror stdout to stderr, useful for seeing data going through a pipe
alias peek='tee >(cat 1>&2)'
# Runs Gitlab code quality scanner
alias code_scanner='docker run
--env SOURCE_CODE="$PWD"
--volume "${PWD}":/code
@@ -95,20 +95,25 @@ alias code_scanner='docker run
registry.gitlab.com/gitlab-org/ci-cd/codequality:"${CODEQUALITY_VERSION:-latest}"
/code'
# Runs trivy container image scanner
alias trivy_scan='docker run -v /var/run/docker.sock:/var/run/docker.sock -v $HOME/Library/Caches:/root/.cache/ aquasec/trivy'
# Opens dotfiles with $EDITOR
alias zedit='$EDITOR ~/.dotfiles'
# Open irssi with my configurations
alias irssi='irssi --config=$XDG_CONFIG_HOME/irssi/config --home=$XDG_CONFIG_HOME/irssi'
# Configures wget to use correct wget-hsts file
alias wget='wget --hsts-file=$XDG_DATA_HOME/wget-hsts'
# Configures svn to use correct config directory
alias svn='svn --config-dir $XDG_CONFIG_HOME/subversion'
alias irssi="irssi --config=$XDG_CONFIG_HOME/irssi/config --home=$XDG_CONFIG_HOME/irssi"
# Laravel artisan shortcut
alias art='[ -f artisan ] && php artisan || php vendor/bin/artisan'
alias wget="wget --hsts-file=$XDG_DATA_HOME/wget-hsts"
alias svn="svn --config-dir $XDG_CONFIG_HOME/subversion"
# Laravel Sail shortcut
alias sail='[ -f sail ] && bash sail || bash vendor/bin/sail'
if [[ $(uname) == 'Darwin' ]]; then
# Laravel Sail shortcut
alias sail='[ -f sail ] && bash sail || bash vendor/bin/sail'
# Flush Directory Service cache
alias flushdns="sudo dscacheutil -flushcache; sudo killall -HUP mDNSResponder"
@@ -130,6 +135,6 @@ X_ALIAS_FILES=(
)
for aliasFile in "${X_ALIAS_FILES[@]}"; do
# shellcheck source=$HOME/.config/alias-secret
[ -f "$aliasFile" ] && source "$aliasFile" && msg "Sourced $aliasFile"
[ -f "$aliasFile" ] && source "$aliasFile" && msgr ok "Sourced $aliasFile"
done
unset X_ALIAS_FILES

View File

@@ -1,27 +1,20 @@
1password-cli https://github.com/NeoHsu/asdf-1password-cli.git f5d5aab
age https://github.com/threkk/asdf-age.git 396bdf6
asdf-plugin-manager https://github.com/asdf-community/asdf-plugin-manager.git b5862c1
bats https://github.com/timgluz/asdf-bats.git 299551f
bottom https://github.com/carbonteq/asdf-btm.git fd8a55a
delta https://github.com/andweeb/asdf-delta.git 501318b
direnv https://github.com/asdf-community/asdf-direnv.git 6ff3dbe
dotenv-linter https://github.com/wesleimp/asdf-dotenv-linter.git 1369f53
editorconfig-checker https://github.com/gabitchov/asdf-editorconfig-checker.git 585c1d5
eza https://github.com/lwiechec/asdf-eza.git 11f578d
fd https://gitlab.com/wt0f/asdf-fd.git 17d56e0
github-cli https://github.com/bartlomiejdanek/asdf-github-cli.git e0605b7
gitleaks https://github.com/jmcvetta/asdf-gitleaks.git 0cc0d7e
golang https://github.com/asdf-community/asdf-golang.git e2527a3
hadolint https://github.com/devlincashman/asdf-hadolint.git 335e230
hadolint https://github.com/devlincashman/asdf-hadolint.git c8eb88b
kubectl https://github.com/asdf-community/asdf-kubectl.git 2fb3b57
pre-commit https://github.com/jonathanmorley/asdf-pre-commit.git 26bfc42
ripgrep https://gitlab.com/wt0f/asdf-ripgrep.git e836665
ruby https://github.com/asdf-vm/asdf-ruby.git 194fe45
rust https://github.com/code-lever/asdf-rust.git 95acf4f
shellcheck https://github.com/luizm/asdf-shellcheck.git 66200ff
shfmt https://github.com/luizm/asdf-shfmt.git a42c5ff
sops https://github.com/feniix/asdf-sops.git 5c7a2fb
terragrunt https://github.com/ohmer/asdf-terragrunt.git 4a6651a
terragrunt https://github.com/ohmer/asdf-terragrunt.git 29f2935
tf-summarize https://github.com/adamcrews/asdf-tf-summarize.git 880ad26
yamllint https://github.com/ericcornelissen/asdf-yamllint.git bc2813e
yamllint https://github.com/ericcornelissen/asdf-yamllint.git e4cfb17
yq https://github.com/sudermanjr/asdf-yq.git 772992f

View File

@@ -281,8 +281,8 @@ export LESSHISTFILE="$XDG_STATE_HOME"/less/history
# export LESS_TERMCAP_md="$ORANGE"
# zsh autoloaded terminfo
export TERMINFO="${XDG_DATA_HOME}/terminfo"
export TERMINFO_DIRS="${XDG_DATA_HOME}/terminfo":/usr/share/terminfo
# export TERMINFO="${XDG_DATA_HOME}/terminfo"
# export TERMINFO_DIRS="${XDG_DATA_HOME}/terminfo":/usr/share/terminfo
# Don't clear the screen after quitting a manual page
export MANPAGER="less -X"
@@ -333,14 +333,6 @@ export ANTIDOTE_DIR="$DOTFILES/tools/antidote"
export ANTIDOTE_HOME="$XDG_CACHE_HOME/antidote"
export ANTIDOTE_PLUGINS="$XDG_CONFIG_HOME/zsh/antidote_plugins"
# Antigen configuration
# https://github.com/zsh-users/antigen/wiki/Configuration
msg "Setting up Antigen configuration"
export ADOTDIR="$XDG_DATA_HOME/antigen"
export ANTIGEN_CACHE="$XDG_CACHE_HOME/antigen"
export ANTIGEN_SYSTEM_RECEIPT_F=".local/share/antigen/antigen_system_lastupdate"
export ANTIGEN_PLUGIN_RECEIPT_F=".local/share/antigen/antigen_plugin_lastupdate"
# Ansible configuration
# https://docs.ansible.com/ansible/latest/reference_appendices/config.html
msg "Setting up Ansible configuration"
@@ -476,11 +468,13 @@ export TF_PLUGIN_CACHE_DIR="$XDG_CACHE_HOME/terraform/plugin-cache"
# tmux
# https://tmux.github.io/
msg "Setting up tmux configuration"
export TMUX_PLUGINS="$XDG_CONFIG_HOME/tmux/plugins"
export TMUX_CONF="$XDG_CONFIG_HOME/tmux/tmux.conf"
export TMUX_TMPDIR="$XDG_STATE_HOME/tmux"
export TMUX_CONF_DIR="$XDG_CONFIG_HOME/tmux"
export TMUX_PLUGINS="$TMUX_CONF_DIR/plugins"
export TMUX_CONF="$TMUX_CONF_DIR/tmux.conf"
## These settings are for zsh-tmux
export ZSH_TMUX_AUTOSTART=false
export ZSH_TMUX_CONFIG="$DOTFILES/config/tmux/tmux.conf"
export ZSH_TMUX_CONFIG="$TMUX_CONF"
export ZSH_TMUX_UNICODE=true
export ZSH_TMUX_AUTOQUIT=false
export ZSH_TMUX_DEFAULT_SESSION_NAME=main

15
config/ghostty/config Normal file
View File

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

View File

@@ -11,3 +11,5 @@
[include]
path = ~/.config/git/overrides/config
[advice]
detachedHead = false

6
config/glow/glow.yml Normal file
View File

@@ -0,0 +1,6 @@
# mouse support (TUI-mode only)
mouse: false
# use pager to display markdown
pager: true
# word-wrap at width
width: 80

View File

@@ -13,6 +13,8 @@ tap "jesseduffield/lazygit"
tap "k8sgpt-ai/k8sgpt"
tap "keith/formulae"
tap "mongodb/brew"
tap "nikitabobko/tap"
tap "pantheon-systems/external"
tap "reviewdog/tap"
tap "shivammathur/extensions"
tap "shivammathur/php"
@@ -21,6 +23,22 @@ tap "teamookla/speedtest"
tap "xwmx/taps"
# Run your GitHub Actions locally
brew "act"
# Simple, modern, secure file encryption
brew "age"
# Mozilla CA certificate store
brew "ca-certificates"
# Mozilla CA bundle for Python
brew "certifi"
# Cryptography and SSL/TLS Toolkit
brew "openssl@3"
# Cryptographic recipes and primitives for Python
brew "cryptography"
# YAML Parser
brew "libyaml"
# Automate deployment, configuration, and upgrading
brew "ansible"
# Checks ansible playbooks for practices and behaviour
brew "ansible-lint"
# Generic-purpose lossless compression algorithm by Google
brew "brotli"
# Library and utilities for processing GIFs
@@ -39,10 +57,6 @@ brew "jpeg-xl"
brew "aom"
# Apache Portable Runtime library
brew "apr"
# Mozilla CA certificate store
brew "ca-certificates"
# Cryptography and SSL/TLS Toolkit
brew "openssl@3"
# Companion library to apr, the Apache Portable Runtime library
brew "apr-util"
# Password hashing library and CLI utility
@@ -53,18 +67,26 @@ brew "aspell"
brew "autoconf"
# Collection of over 500 reusable autoconf macros
brew "autoconf-archive"
# Cryptographic recipes and primitives for Python
brew "cryptography"
# GNU multiple precision arithmetic library
brew "gmp"
# Package compiler and linker metadata toolkit
brew "pkgconf"
# Automated text file generator
brew "autogen"
# Tool for generating GNU Standards-compliant Makefiles
brew "automake"
# Official Amazon AWS command-line interface
brew "awscli"
# Bourne-Again SHell, a UNIX command interpreter
brew "bash"
# GNU multiple precision arithmetic library
brew "gmp"
# Clone of cat(1) with syntax highlighting and Git integration
brew "bat"
# GNU File, Shell, and Text utilities
brew "coreutils"
# Bash Automated Testing System
brew "bats-core"
# Parser generator
brew "bison"
# Software library to render fonts
brew "freetype"
# XML-based font configuration API for X Windows
@@ -73,18 +95,34 @@ brew "fontconfig"
brew "gettext"
# Core application library for C
brew "glib"
# Mozilla CA bundle for Python
brew "certifi"
# Prevent cloud misconfigurations during build-time for IaC tools
brew "checkov"
# Human-friendly and fast alternative to cut and (sometimes) awk
brew "choose-rust"
# Cross-platform make
brew "cmake"
# Get a file from an HTTP, HTTPS or FTP server
brew "curl"
# Lightweight DNS forwarder and DHCP server
brew "dnsmasq"
# Spellchecker wrapping library
brew "enchant"
# Perl lib for reading and writing EXIF metadata
brew "exiftool"
# Banner-like program prints strings as ASCII art
brew "figlet"
# Lock file during command
brew "flock"
# Libraries to talk to Microsoft SQL Server and Sybase databases
brew "freetds"
# Monitor a directory for changes and run a shell command
brew "fswatch"
# Command-line fuzzy finder written in Go
brew "fzf"
# Graphics library to dynamically manipulate images
brew "gd"
# Disk usage analyzer with console interface written in Go
brew "gdu"
# GitHub command-line tool
brew "gh"
# OpenType text shaping engine
@@ -95,22 +133,38 @@ brew "libb2"
brew "pango"
# Distributed revision control system
brew "git"
# Enable transparent encryption/decryption of files in a git repo
brew "git-crypt"
# Small git utilities
brew "git-extras"
# See your latest local git branches, formatted real fancy
brew "git-recent"
# Render markdown on the CLI
brew "glow"
# GNU implementation of the famous stream editor
brew "gnu-sed"
# Validating, recursive, caching DNS resolver
brew "unbound"
# GNU Transport Layer Security (TLS) Library
brew "gnutls"
# GNU Pretty Good Privacy (PGP) package
brew "gnupg"
# Library access to GnuPG
brew "gpgme"
# Manage your GnuPG keys with ease!
brew "gpg-tui"
# Image manipulation
brew "netpbm"
# Library to render SVG files using Cairo
brew "librsvg"
# Graph visualization software from AT&T and Bell Labs
brew "graphviz"
# GNU grep, egrep and fgrep
brew "grep"
# Popular GNU data compression program
brew "gzip"
# Text-based UI library
brew "ncurses"
# Improved top (interactive process viewer)
brew "htop"
# Portable abstraction of the hierarchical topology of modern architectures
@@ -121,6 +175,8 @@ brew "libheif"
brew "imagemagick"
# Modular IRC client
brew "irssi"
# Image manipulation library
brew "jpeg"
# Lightweight and flexible command-line JSON processor
brew "jq"
# JSON parser for C
@@ -129,16 +185,28 @@ brew "json-c"
brew "krb5"
# Tool to detect/remediate misconfig and security risks of GitHub/GitLab assets
brew "legitify"
# BSD-style licensed readline alternative
brew "libedit"
# Conversion library
brew "libiconv"
# Postgres C API library
brew "libpq"
# Version of the SSL/TLS protocol forked from OpenSSL
brew "libressl"
# Multi-platform support library with a focus on asynchronous I/O
brew "libuv"
# YAML Parser
brew "libyaml"
# GNOME XML library
brew "libxml2"
# Package manager for the Lua programming language
brew "luarocks"
# LZMA-based compression program similar to gzip or bzip2
brew "lzip"
# Swiss Army Knife for macOS
brew "m-cli"
# Collection of tools that nobody wrote when UNIX was young
brew "moreutils"
# NCurses Disk Usage
brew "ncdu"
# HTTP(S) server and reverse proxy, and IMAP/POP3 proxy server
brew "nginx"
# Port scanning utility for large networks
@@ -147,22 +215,48 @@ brew "nmap"
brew "nss"
# Open source suite of directory software
brew "openldap"
# Cryptography and SSL/TLS Toolkit
brew "openssl@1.1"
# ISO-C API and CLI for generating UUIDs
brew "ossp-uuid"
# General-purpose scripting language
brew "php"
# General-purpose scripting language
brew "php@8.2"
# Manage compile and link flags for libraries
brew "pkg-config"
# General-purpose scripting language
brew "php@8.3"
# Python version management
brew "pyenv"
# Migrate pip packages from one Python version to another
brew "pyenv-pip-migrate"
# Pyenv plugin to manage virtualenv
brew "pyenv-virtualenv"
# Interpreted, interactive, object-oriented programming language
brew "python@3.11"
# Install various Ruby versions and implementations
brew "ruby-build"
# Ruby version manager
brew "rbenv"
# Generate C-based recognizers from regular expressions
brew "re2c"
# Static analysis and lint tool, for (ba)sh scripts
brew "shellcheck"
# Send macOS User Notifications from the command-line
brew "terminal-notifier"
# Tool which checks for the support of TLS/SSL ciphers and flaws
brew "testssl"
# Terraform version manager inspired by rbenv
brew "tfenv"
# Linter for Terraform files
brew "tflint"
# Static analysis security scanner for your terraform code
brew "tfsec"
# Terminal multiplexer
brew "tmux"
# Display directories as trees (with optional color/HTML output)
brew "tree"
# Tool for creating isolated virtual python environments
brew "virtualenv"
# Command-line interface to the WakaTime api
brew "wakatime-cli"
# Executes a program periodically, showing output fullscreen
@@ -171,8 +265,18 @@ brew "watch"
brew "wget"
# Check your $HOME for unwanted files and directories
brew "xdg-ninja", args: ["HEAD"]
# General-purpose lossless data-compression library
brew "zlib"
# Watcher for macOS 10.14+ light/dark mode changes
brew "cormacrelf/tap/dark-notify"
# Cleans up your $HOME from those pesky dotfiles
brew "doron-cohen/tap/antidot"
# lets you quickly switch between multiple git user profiles
brew "gesquive/tap/git-user"
# Terminus is Pantheon's Command-line Interface (CLI)
brew "pantheon-systems/external/terminus"
# Automated code review tool integrated with any code analysis tools regardless of programming language.
brew "reviewdog/tap/reviewdog"
# Igbinary PHP extension
brew "shivammathur/extensions/igbinary@8.3"
# Imagick PHP extension
@@ -191,8 +295,14 @@ brew "shivammathur/extensions/uuid@8.3"
brew "shivammathur/extensions/yaml@8.3"
# General-purpose scripting language
brew "shivammathur/php/php-debug"
# General-purpose scripting language
brew "shivammathur/php/php@7.4"
# General-purpose scripting language
brew "shivammathur/php/php@8.0", link: true
# Find & fix known vulnerabilities in open-source dependencies
brew "snyk/tap/snyk"
# AeroSpace is an i3-like tiling window manager for macOS
cask "aerospace"
# Text editor
cask "coda"
# Universal database tool and SQL client
@@ -203,13 +313,7 @@ cask "dbngin"
cask "docker"
cask "font-jetbrains-mono"
cask "font-jetbrains-mono-nerd-font"
cask "font-lato"
cask "font-open-sans"
cask "font-roboto"
cask "font-source-code-pro"
cask "font-source-code-pro-for-powerline"
cask "font-source-sans-pro"
cask "font-source-serif-pro"
# GIT client
cask "fork"
# HTTP and GraphQL Client

View File

@@ -5,7 +5,7 @@
-- ── Install lazylazy ────────────────────────────────────────────────
-- https://github.com/folke/lazy.nvim
local lazypath = vim.fn.stdpath 'data' .. '/lazy/lazy.nvim'
if not vim.loop.fs_stat(lazypath) then
if not vim.uv.fs_stat(lazypath) then
local lazyrepo = 'https://github.com/folke/lazy.nvim.git'
local out = vim.fn.system {
'git',
@@ -52,9 +52,15 @@ require('lazy').setup(
-- No need to notify about changes
notify = false,
},
dev = {
path = '~/Code/nvim', -- Load wip plugins from this path
},
install = {
colorscheme = { vim.g.colors_theme },
},
profiling = {
loader = true,
},
}
)

View File

@@ -93,11 +93,12 @@ autocmd({ 'FileType' }, {
-- Set filetype for SSH config directory
-- Pattern handles directories with files like:
-- .dotfiles/ssh/config.d/*, .ssh/config.local, .ssh/config.work
-- .dotfiles/ssh/config.d/*, .ssh/config.local, .ssh/config.work,
-- .ssh/shared.d/*, .ssh/local.d/*
autocmd({ 'BufRead', 'BufNewFile' }, {
desc = 'Set filetype for SSH config directory',
pattern = {
'*/?.ssh/{config|shared}.d/*',
'*/?.ssh/{config|shared|local}.d/*',
'*/?.ssh/config.local',
'*/?.ssh/config.work',
},

View File

@@ -1,4 +1,4 @@
-- vim: set ft=lua ts=2 sw=2 tw=0 et cc=120 :
-- vim: set ft=lua ts=2 sw=2 tw=0 et cc=130 :
require 'utils'
@@ -42,6 +42,24 @@ K.nl('o', function() require('snacks').gitbrowse() end, 'Open repo in browser')
K.n('<C-s>', ':w!<cr>', { desc = 'Save', noremap = true })
K.n('<esc><esc>', ':nohlsearch<cr>', { desc = 'Clear Search Highlighting' })
-- ── ToggleTerm ──────────────────────────────────────────────────────
K.d('<F1>', 'n', ':FloatermToggle<CR>', 'Toggle Floaterm')
K.d('<F1>', 'i', '<Esc>:FloatermToggle<CR>', 'Toggle Floaterm')
K.d('<F1>', 't', '<C-\\><C-n>:FloatermToggle<CR>', 'Toggle Floaterm')
-- ── Test operations ─────────────────────────────────────────────────
K.nl('an', ':silent TestNearest<CR>', 'Test Nearest')
K.nl('af', ':silent TestFile<CR>', 'Test File')
K.nl('as', ':silent TestSuite<CR>', 'Test Suite')
K.nl('al', ':silent TestLast<CR>', 'Test Last')
K.nl('av', ':silent TestVisit<CR>', 'Test Visit')
-- ── PHPActor Operations ─────────────────────────────────────────────
K.nl('apm', ':PhpactorContextMenu<cr>', 'PHPactor: Context Menu')
K.nl('apn', ':PhpactorClassNew<cr>', 'PHPactor: Class New')
K.nl('aps', ':PhpactorClassSearch<cr>', 'PHPactor: Class Search')
K.nl('apt', ':PhpactorTransform<cr>', 'PHPactor: Transform')
-- ── Buffer operations ───────────────────────────────────────────────
-- Mappings for buffer management operations like switching, deleting, etc.
-- Convention: All mappings start with 'b' followed by the operation
@@ -57,25 +75,26 @@ K.nl('bw', ':lua MiniBufremove.wipeout()<CR>', 'Wipeout')
-- Mappings for code and LSP operations like code actions, formatting, etc.
-- Convention: All mappings start with 'c' followed by the operation
-- unless it's a generic operation like signature help or hover
local b = function() return require 'telescope.builtin' end
local lws = function() return b().lsp_workspace_symbols() end
local ldws = function() return b().lsp_dynamic_workspace_symbols() end
K.n('<C-l>', ':lua vim.lsp.buf.signature_help()<CR>', { desc = 'Signature' })
K.n('K', ':Lspsaga hover_doc<cr>', { desc = 'Hover Documentation' })
K.ld('ca', 'n', ':Lspsaga code_action<cr>', 'Code Action')
K.ld('cci', 'n', ':Lspsaga incoming_calls<cr>', 'Incoming Calls')
K.ld('cco', 'n', ':Lspsaga outgoing_calls<cr>', 'Outgoing Calls')
K.ld('cd', 'n', ':Lspsaga show_line_diagnostics<cr>', 'Line Diagnostics')
-- K.ld('cf', { 'n', 'x' }, ':lua vim.lsp.buf.format()<CR>', 'Format')
K.n('K', ':lua vim.lsp.buf.hover()<CR>', { desc = 'Hover Documentation' })
K.ld('ca', 'n', ':lua vim.lsp.buf.code_action()<CR>', 'Code Action')
K.ld('cci', 'n', function() b().lsp_incoming_calls() end, 'Incoming calls')
K.ld('cco', 'n', function() b().lsp_outgoing_calls() end, 'Outgoing calls')
K.ld('cd', 'n', function() b().lsp_definitions() end, 'Definitions')
K.ld('cf', { 'n', 'x' }, ':lua vim.lsp.buf.format()<CR>', 'Format')
K.ld('cg', 'n', ':lua require("neogen").generate()<CR>', 'Generate annotations')
K.ld('ci', 'n', ':Lspsaga implement<cr>', 'Implementations')
K.ld('cl', 'n', ':Lspsaga show_cursor_diagnostics<cr>', 'Cursor Diagnostics')
K.ld('cp', 'n', ':Lspsaga peek_definition<cr>', 'Peek Definition')
K.ld('cr', 'n', ':Lspsaga rename<cr>', 'Rename')
K.ld('cR', 'n', ':Lspsaga rename ++project<cr>', 'Rename Project wide')
K.ld('ci', 'n', function() b().lsp_implementations() end, 'Implementations')
K.ld('cp', 'n', function() b().lsp_type_definitions() end, 'Type Definition')
K.ld('cr', 'n', vim.lsp.buf.rename, 'Rename')
K.ld('cs', 'n', ':Telescope lsp_document_symbols<CR>', 'LSP Document Symbols')
K.ld('ct', 'n', ':Lspsaga peek_type_definition<cr>', 'Peek Type Definition')
K.ld('cT', 'n', ':Telescope lsp_type_definitions<CR>', 'LSP Type Definitions')
K.ld('cu', 'n', ':Lspsaga preview_definition<cr>', 'Preview Definition')
K.ld('cv', 'n', ':Lspsaga diagnostic_jump_prev<cr>', 'Diagnostic Jump Prev')
K.ld('cw', 'n', ':Lspsaga diagnostic_jump_next<cr>', 'Diagnostic Jump Next')
K.ld('ct', 'n', function() b().treesitter() end, 'treesitter')
K.ld('cws', 'n', function() lws() end, 'Workspace Symbols')
K.ld('cwd', 'n', function() ldws() end, 'Dynamic Workspace Symbols')
-- ── CommentBox operations ───────────────────────────────────────────
-- Mappings for creating and managing comment boxes
@@ -90,20 +109,23 @@ K.nl('cbt', '<Cmd>CBllline<CR>', 'CB: Titled Line')
-- Mappings for Telescope operations like finding files, buffers, etc.
-- Convention: All mappings start with 's' followed by the operation
-- unless it's a generic operation like searching or finding buffers
K.nl('f', ':Telescope find_files<cr>', 'Find Files')
local fuzzy_search = function()
require('telescope.builtin').find_files(
require('telescope.themes').get_dropdown {
winblend = 20,
previewer = true,
}
)
end
local lazy_plugins = function()
return require('telescope').extensions.lazy_plugins.lazy_plugins()
end
K.nl('f', ':Telescope fd --hidden=true<cr>', 'Find Files')
K.nl(',', ':Telescope buffers<cr>', 'Find existing buffers')
K.nl(
'/',
function()
require('telescope.builtin').current_buffer_fuzzy_find(
require('telescope.themes').get_dropdown {
winblend = 20,
previewer = true,
}
)
end,
'Fuzzily search in current buffer'
)
K.nl('/', function() fuzzy_search() end, 'Fuzzily search in current buffer')
K.nl('sc', ':Telescope commands<cr>', 'Commands')
K.nl('sd', ':Telescope diagnostics<cr>', 'Search Diagnostics')
@@ -112,20 +134,15 @@ K.nl('sh', ':Telescope help_tags<cr>', 'Help tags')
K.nl('sk', ':Telescope keymaps<cr>', 'Search Keymaps')
K.nl('sl', ':Telescope luasnip<CR>', 'Search LuaSnip')
K.nl('so', ':Telescope oldfiles<CR>', 'Old Files')
K.nl(
'sp',
':lua require("telescope").extensions.lazy_plugins.lazy_plugins()<cr>',
'Lazy Plugins'
)
K.nl('sp', function() lazy_plugins() end, 'Lazy Plugins')
K.nl('sq', ':Telescope quickfix<cr>', 'Quickfix')
K.nl('ss', ':Telescope treesitter<cr>', 'Treesitter')
K.nl('st', ':TodoTelescope<cr>', 'Search Todos')
K.nl('sw', ':Telescope grep_string<cr>', 'Grep String')
K.nl('sx', ':Telescope import<cr>', 'Telescope: Import')
-- ── Trouble operations ──────────────────────────────────────────────
-- Convention is 'x' followed by the operation
K.nl('xd', ':Trouble document_diagnostics<cr>', 'Document Diagnostics')
K.nl('xd', ':Trouble diagnostics<cr>', 'Document Diagnostics')
K.nl('xl', ':Trouble loclist<cr>', 'Location List')
K.nl('xq', ':Trouble quickfix<cr>', 'Quickfix')
K.nl('xw', ':Trouble workspace_diagnostics<cr>', 'Workspace Diagnostics')
@@ -153,4 +170,13 @@ K.nl('qQ', function()
end
end, 'Force quit without saving')
-- ── Flash.nvim keymaps ──────────────────────────────────────────────
local nxo = { 'n', 'x', 'o' }
local fj = function() return require('flash').jump() end
local ft = function() return require('flash').treesitter() end
local fx = function() return require('flash').toggle() end
K.d('zk', nxo, fj, { desc = 'Flash' })
K.d('Zk', nxo, ft, { desc = 'Flash Treesitter' })
K.d('<m-s>', 'c', fx, { desc = 'Toggle Flash Search' })
-- That concludes the keymaps section of the config.

View File

@@ -30,12 +30,24 @@ end
-- Helper function to show a notification
---@param msg string Show a message
---@param level number|"info"|"warn"|"error"|"trace" Notification level
---@param level "info"|"warn"|"error"|"trace" Notification level
local function n(msg, level)
if msg == nil then msg = M.name .. ': No message provided' end
if level == nil then level = 'trace' end
vim.notify(M.name .. ': ' .. msg, level)
local log_level = vim.log.levels.INFO
if level == 'info' then
log_level = vim.log.levels.INFO
elseif level == 'warn' then
log_level = vim.log.levels.WARN
elseif level == 'error' then
log_level = vim.log.levels.ERROR
elseif level == 'trace' then
log_level = vim.log.levels.TRACE
end
vim.notify(M.name .. ': ' .. msg, log_level)
end
---@class NvmDefaultOptions

View File

@@ -7,6 +7,7 @@
local g = vim.g -- A table to store global variables
local o = vim.opt -- A table to store global options
local a = vim.api -- A table to store API functions
-- vim.global
g.mapleader = ' ' -- Space as the leader key
@@ -24,13 +25,17 @@ g.loaded_java_provider = 0 -- Disable java provider
-- vim.options
-- Most of the good defaults are provided by `mini.basics`
-- See: lua/plugins/mini.lua
o.confirm = true -- Confirm before closing unsaved buffers
o.ignorecase = true -- Ignore case in search patterns
o.inccommand = 'split' -- Preview substitutions live, as you type!
o.list = true -- Show invisible characters
o.listchars = { tab = '» ', trail = '·', nbsp = '' }
o.number = true -- Show line numbers
o.numberwidth = 3 -- Set the width of the number column
o.relativenumber = true -- Show relative line numbers
o.scrolloff = 15 -- Show context around cursor
o.signcolumn = 'yes:3' -- Keep signcolumn on by default
o.scrolloff = 8 -- Show context around cursor
o.sidescrolloff = 8 -- Show context around cursor
o.signcolumn = 'yes' -- Keep signcolumn on by default
o.spell = true -- Enable spell checking
o.spelllang = 'en_us' -- Set the spell checking language
o.splitbelow = true -- split to the bottom
@@ -39,15 +44,23 @@ o.termguicolors = true -- Enable GUI colors
o.timeoutlen = 250 -- Decrease mapped sequence wait time
o.updatetime = 250 -- 250 ms = 2,5 seconds
-- Session options
-- This is a comma separated list of options that will be
-- saved when a session ends.
local so = 'buffers,curdir,folds,tabpages,winsize,winpos,terminal,localoptions'
o.sessionoptions = so
o.wildmode = 'longest:full,full' -- Command-line completion mode
-- Enable the colorcolumn
vim.api.nvim_set_option_value('colorcolumn', '+1', { scope = 'global' })
a.nvim_set_option_value('colorcolumn', '+1', { scope = 'global' })
-- Sync clipboard between OS and Neovim.
-- Schedule the setting after `UiEnter` because it can increase startup-time.
-- See `:help 'clipboard'`
vim.schedule(function()
local c = vim.env.SSH_TTY and '' or 'unnamedplus'
vim.opt.clipboard = c
o.clipboard = c
end)
-- vim: ts=2 sts=2 sw=2 et

View File

@@ -18,9 +18,14 @@ return {
},
},
{ 'L3MON4D3/LuaSnip', version = 'v2.*', build = 'make install_jsregexp' },
-- Set of preconfigured snippets for different languages.
-- https://github.com/rafamadriz/friendly-snippets
{ 'rafamadriz/friendly-snippets' },
{
'rafamadriz/friendly-snippets',
config = function() require('luasnip.loaders.from_vscode').lazy_load() end,
},
-- Lua plugin to turn github copilot into a cmp source
-- https://github.com/giuxtaposition/blink-cmp-copilot
@@ -48,8 +53,8 @@ return {
},
},
---@module 'blink.cmp'
---@type blink.cmp.Config
opts = {
snippets = { preset = 'luasnip' },
-- 'default' for mappings similar to built-in completion
-- 'super-tab' for mappings similar to vscode (tab to accept, arrow keys to navigate)
-- 'enter' for mappings similar to 'super-tab' but with 'enter' to accept
@@ -91,26 +96,28 @@ return {
-- default list of enabled providers defined so that you can extend it
-- elsewhere in your config, without redefining it, via `opts_extend`
sources = {
default = {
'lazydev',
'lsp',
'snippets',
'copilot',
'path',
'buffer',
},
providers = {
copilot = {
name = 'copilot',
module = 'blink-cmp-copilot',
},
},
completion = {
enabled_providers = {
'lsp',
'copilot',
'path',
'snippets',
'buffer',
lazydev = {
name = 'LazyDev',
module = 'lazydev.integrations.blink',
-- make lazydev completions top priority (see `:h blink.cmp`)
score_offset = 100,
},
},
},
-- experimental auto-brackets support
-- completion = { accept = { auto_brackets = { enabled = true } } }
-- experimental signature help support
signature = { enabled = true },
},

View File

@@ -8,6 +8,47 @@ return {
opts = { enabled = true, snippet_engine = 'luasnip' },
},
-- Terminal manager for (neo)vim
-- https://github.com/voldikss/vim-floaterm
{
'voldikss/vim-floaterm',
cmd = { 'FloatermToggle' },
init = function()
vim.g.floaterm_width = 0.8
vim.g.floaterm_height = 0.8
end,
},
-- Run your tests at the speed of thought
-- https://github.com/vim-test/vim-test
{
'vim-test/vim-test',
dependencies = { 'voldikss/vim-floaterm' },
config = function()
vim.cmd [[
function! PhpUnitTransform(cmd) abort
return join(map(split(a:cmd), 'v:val == "--colors" ? "--colors=always" : v:val'))
endfunction
let g:test#custom_transformations = {'phpunit': function('PhpUnitTransform')}
let g:test#transformation = 'phpunit'
" let test#php#phpunit#options = '--colors=always'
let test#php#pest#options = '-v'
let test#javascript#jest#options = '--color'
function! FloatermStrategy(cmd)
execute 'silent FloatermSend q'
execute 'silent FloatermKill'
execute 'FloatermNew! '.a:cmd.' | less -X'
endfunction
let g:test#custom_strategies = {'floaterm': function('FloatermStrategy')}
let g:test#strategy = 'floaterm'
]]
end,
},
-- Cloak allows you to overlay *'s over defined patterns in defined files.
-- https://github.com/laytan/cloak.nvim
{
@@ -36,6 +77,81 @@ return {
},
},
-- projectionist.vim: Granular project configuration
-- https://github.com/tpope/vim-projectionist
{
'tpope/vim-projectionist',
dependencies = 'tpope/vim-dispatch',
config = function()
vim.g.projectionist_heuristics = {
artisan = {
['*'] = {
start = 'php artisan serve',
console = 'php artisan tinker',
},
['app/*.php'] = {
type = 'source',
alternate = {
'tests/Unit/{}Test.php',
'tests/Feature/{}Test.php',
},
},
['tests/Feature/*Test.php'] = {
type = 'test',
alternate = 'app/{}.php',
},
['tests/Unit/*Test.php'] = {
type = 'test',
alternate = 'app/{}.php',
},
['app/Models/*.php'] = {
type = 'model',
},
['app/Http/Controllers/*.php'] = {
type = 'controller',
},
['routes/*.php'] = {
type = 'route',
},
['database/migrations/*.php'] = {
type = 'migration',
},
},
['src/&composer.json'] = {
['src/*.php'] = {
type = 'source',
alternate = {
'tests/{}Test.php',
},
},
['tests/*Test.php'] = {
type = 'test',
alternate = 'src/{}.php',
},
},
['app/&composer.json'] = {
['app/*.php'] = {
type = 'source',
alternate = {
'tests/{}Test.php',
},
},
['tests/*Test.php'] = {
type = 'test',
alternate = 'app/{}.php',
},
},
}
end,
},
-- A vim text object for XML/HTML attributes.
-- https://github.com/whatyouhide/vim-textobj-xmlattr
{
'whatyouhide/vim-textobj-xmlattr',
dependencies = { 'kana/vim-textobj-user' },
},
-- Describe the regexp under the cursor
-- https://github.com/bennypowers/nvim-regexplainer
{
@@ -84,4 +200,12 @@ return {
ft = { 'go', 'gomod' },
build = ':lua require("go.install").update_all_sync()', -- if you need to install/update all binaries
},
-- Mainly a PHP Language Server with more features than you can shake a stick at
-- https://github.com/phpactor/phpactor
{
'phpactor/phpactor',
build = 'composer install --no-dev --optimize-autoloader',
ft = 'php',
},
}

View File

@@ -5,15 +5,9 @@ return {
'folke/snacks.nvim',
priority = 1000,
lazy = false,
---@type snacks.Config
opts = {
bigfile = { enabled = true },
gitbrowse = { enabled = true },
notifier = {
enabled = true,
timeout = 3000,
},
notify = { enabled = true },
quickfile = { enabled = true },
statuscolumn = {
enabled = true,
@@ -37,6 +31,86 @@ return {
},
},
},
-- Highly experimental plugin that completely
-- replaces the UI for messages, cmdline and the popupmenu.
-- https://github.com/folke/noice.nvim
{
'folke/noice.nvim',
event = 'VeryLazy',
opts = {
lsp = {
-- override markdown rendering so that **cmp** and other plugins use **Treesitter**
override = {
['vim.lsp.util.convert_input_to_markdown_lines'] = true,
['vim.lsp.util.stylize_markdown'] = true,
['cmp.entry.get_documentation'] = true, -- requires hrsh7th/nvim-cmp
},
},
-- you can enable a preset for easier configuration
presets = {
bottom_search = true, -- use a classic bottom cmdline for search
command_palette = true, -- position the cmdline and popupmenu together
long_message_to_split = true, -- long messages will be sent to a split
inc_rename = false, -- enables an input dialog for inc-rename.nvim
lsp_doc_border = false, -- add a border to hover docs and signature help
},
routes = {
{
filter = {
event = 'msg_show',
kind = '',
find = 'written',
},
opts = { skip = true },
},
{
filter = {
event = 'msg_show',
any = {
{ find = '%d+L, %d+B' },
{ find = '; after #%d+' },
{ find = '; before #%d+' },
{ find = "' added to" },
},
},
view = 'mini',
},
{
filter = {
event = 'lsp',
kind = 'progress',
cond = function(message)
local client = vim.tbl_get(message.opts, 'progress', 'client')
return client == 'lua_ls'
end,
},
opts = { skip = true },
},
},
views = {
cmdline_popup = {
border = {
style = 'none',
padding = { 1, 2 },
},
filter_options = {},
win_options = {
winhighlight = 'NormalFloat:NormalFloat,FloatBorder:FloatBorder',
},
},
},
},
dependencies = {
-- if you lazy-load any plugin below, make sure to add proper `module="..."` entries
'MunifTanjim/nui.nvim',
-- OPTIONAL:
-- `nvim-notify` is only needed, if you want to use the notification view.
-- If not available, we use `mini` as the fallback
'rcarriga/nvim-notify',
},
},
-- A pretty diagnostics, references, telescope results,
-- quickfix and location list to help you solve all the
-- trouble your code is causing.
@@ -44,42 +118,53 @@ return {
{
'folke/trouble.nvim',
lazy = false,
cmd = 'Trouble',
dependencies = { 'nvim-tree/nvim-web-devicons' },
---@type trouble.Config
opts = {
auto_preview = true,
auto_fold = true,
auto_close = true,
use_lsp_diagnostic_signs = true,
keys = {
j = 'next',
k = 'prev',
},
modes = {
diagnostics = {
auto_open = true,
},
test = {
mode = 'diagnostics',
preview = {
type = 'split',
relative = 'win',
position = 'right',
size = 0.3,
},
},
cascade = {
mode = 'diagnostics', -- inherit from diagnostics mode
filter = function(items)
local severity = vim.diagnostic.severity.HINT
for _, item in ipairs(items) do
severity = math.min(severity, item.severity)
end
return vim.tbl_filter(
function(item) return item.severity == severity end,
items
)
end,
},
},
},
},
-- Navigate your code with search labels, enhanced
-- character motions and Treesitter integration
-- https://github.com/folke/flash.nvim
{
'folke/flash.nvim',
event = 'VeryLazy',
---@type Flash.Config
opts = {},
keys = {
{
'zk',
mode = { 'n', 'x', 'o' },
function() require('flash').jump() end,
desc = 'Flash',
},
{
'Zk',
mode = { 'n', 'x', 'o' },
function() require('flash').treesitter() end,
desc = 'Flash Treesitter',
},
{
'<m-s>',
mode = { 'c' },
function() require('flash').toggle() end,
desc = 'Toggle Flash Search',
},
},
},
}

View File

@@ -2,10 +2,11 @@
-- │ LSP Setup and configuration │
-- ╰─────────────────────────────────────────────────────────╯
require 'utils'
-- LSP Servers are installed and configured by lsp-setup.nvim
-- Mason formatters Conform uses to format files
-- These are automatically configured by zapling/mason-conform.nvim
local lsp_servers = {
bashls = {},
-- csharp_ls = {},
@@ -26,7 +27,11 @@ local lsp_servers = {
},
},
html = {},
intelephense = {},
intelephense = {
init_options = {
licenceKey = GetIntelephenseLicense(),
},
},
jsonls = {},
lua_ls = {
settings = {
@@ -37,12 +42,6 @@ local lsp_servers = {
diagnostics = {
globals = {
'vim',
-- busted
'describe',
'it',
'before_each',
'after_each',
'assert',
},
disable = {
-- Ignore lua_ls noisy `missing-fields` warnings
@@ -50,7 +49,7 @@ local lsp_servers = {
},
},
hint = {
enable = false,
enable = true,
arrayIndex = 'Auto',
await = true,
paramName = 'All',
@@ -105,6 +104,28 @@ local lsp_servers = {
},
}
-- Mason tools to automatically install and configure.
-- These are automatically configured by WhoIsSethDaniel/mason-tool-installer.nvim
local mason_tools = {
'actionlint',
'editorconfig-checker',
'goimports',
'gotests',
'phpcbf',
'phpmd',
'phpstan',
'pint',
'prettierd',
'semgrep',
'shellcheck',
'shfmt',
'staticcheck',
'stylua',
'trivy',
'vint',
'yamlfmt',
}
return {
-- `lazydev` configures Lua LSP for your Neovim config, runtime and plugins
-- used for completion, annotations and signatures of Neovim apis
@@ -116,6 +137,9 @@ return {
library = {
-- Load luvit types when the `vim.uv` word is found
{ path = 'luvit-meta/library', words = { 'vim%.uv' } },
-- load assert and describe paths
{ path = 'luassert/library', words = { 'assert' } },
{ path = 'busted/library', words = { 'describe' } },
},
},
},
@@ -124,120 +148,72 @@ return {
-- https://github.com/Bilal2453/luvit-meta
{ 'Bilal2453/luvit-meta', lazy = true },
-- improve neovim lsp experience
-- https://github.com/nvimdev/lspsaga.nvim
-- https://nvimdev.github.io/lspsaga/
-- Quickstart configs for Nvim LSP
-- https://github.com/neovim/nvim-lspconfig
{ 'neovim/nvim-lspconfig' },
-- Portable package manager for Neovim that runs everywhere Neovim runs.
-- Easily install and manage LSP servers, DAP servers, linters, and formatters.
-- https://github.com/williamboman/mason.nvim
{
'nvimdev/lspsaga.nvim',
event = 'LspAttach',
dependencies = {
'nvim-treesitter/nvim-treesitter',
'nvim-tree/nvim-web-devicons',
},
---@type LspsagaConfig
'williamboman/mason.nvim',
version = '*',
cmd = 'Mason',
run = ':MasonUpdate',
opts = {},
},
-- Extensible UI for Neovim notifications and LSP progress messages.
-- https://github.com/j-hui/fidget.nvim
{
'j-hui/fidget.nvim',
version = '*',
opts = {},
},
-- Extension to mason.nvim that makes it easier to use lspconfig with mason.nvim.
-- https://github.com/williamboman/mason-lspconfig.nvim
{ 'williamboman/mason-lspconfig.nvim' },
-- Install and upgrade third party tools automatically
-- https://github.com/WhoIsSethDaniel/mason-tool-installer.nvim
{
'WhoIsSethDaniel/mason-tool-installer.nvim',
version = '*',
opts = {
code_action = {
show_server_name = true,
keys = {
quit = { 'q', '<ESC>' },
},
},
diagnostic = {
keys = {
quit = { 'q', '<ESC>' },
},
},
auto_install = true,
auto_update = true,
ensure_installed = mason_tools,
},
},
-- JSON schemas for Neovim
-- https://github.com/b0o/SchemaStore.nvim
{ 'b0o/schemastore.nvim' },
-- Performant, batteries-included completion plugin for Neovim
-- https://github.com/saghen/blink.cmp
-- See lua/plugins/blink.lua for configs
{ 'saghen/blink.cmp' },
-- A simple wrapper for nvim-lspconfig and mason-lspconfig
-- to easily setup LSP servers.
-- https://github.com/junnplus/lsp-setup.nvim
{
'junnplus/lsp-setup.nvim',
dependencies = {
-- Quickstart configs for Nvim LSP
-- https://github.com/neovim/nvim-lspconfig
{ 'neovim/nvim-lspconfig' },
-- Portable package manager for Neovim that runs everywhere Neovim runs.
-- Easily install and manage LSP servers, DAP servers, linters, and formatters.
-- https://github.com/williamboman/mason.nvim
{
'williamboman/mason.nvim',
version = '*',
cmd = 'Mason',
run = ':MasonUpdate',
opts = {},
},
-- Extensible UI for Neovim notifications and LSP progress messages.
-- https://github.com/j-hui/fidget.nvim
{
'j-hui/fidget.nvim',
version = '*',
opts = {},
},
-- Extension to mason.nvim that makes it easier to use lspconfig with mason.nvim.
-- https://github.com/williamboman/mason-lspconfig.nvim
{ 'williamboman/mason-lspconfig.nvim' },
-- Install and upgrade third party tools automatically
-- https://github.com/WhoIsSethDaniel/mason-tool-installer.nvim
{
'WhoIsSethDaniel/mason-tool-installer.nvim',
version = '*',
opts = {
auto_install = true,
auto_update = true,
ensure_installed = {
'editorconfig-checker',
'goimports',
'gotests',
'phpcbf',
'pint',
'prettierd',
'shellcheck',
'shfmt',
'staticcheck',
'stylua',
'vint',
'yamlfmt',
},
},
},
-- JSON schemas for Neovim
-- https://github.com/b0o/SchemaStore.nvim
{ 'b0o/schemastore.nvim' },
-- Performant, batteries-included completion plugin for Neovim
-- https://github.com/saghen/blink.cmp
-- See lua/plugins/blink.lua for configs
{ 'saghen/blink.cmp' },
},
opts = {
default_mappings = false,
mappings = {
gd = 'lua require"telescope.builtin".lsp_definitions()',
gi = 'lua require"telescope.builtin".lsp_implementations()',
gr = 'lua require"telescope.builtin".lsp_references()',
},
inlay_hints = {
enabled = true,
},
servers = lsp_servers,
},
config = function(_, opts)
require('lazydev').setup()
require('lsp-setup').setup(opts)
local cmp = require 'blink.cmp'
local lspconfig = require 'lspconfig'
for server, config in pairs(opts.servers) do
-- passing config.capabilities to blink.cmp merges with the capabilities in your
-- `opts[server].capabilities, if you've defined it
config.capabilities =
require('blink.cmp').get_lsp_capabilities(config.capabilities)
config.capabilities = cmp.get_lsp_capabilities(config.capabilities)
lspconfig[server].setup(config)
end
@@ -284,6 +260,43 @@ return {
validate = { enable = true },
},
}
-- Diagnostic configuration
local signs = {
{ name = 'DiagnosticSignError', text = '' }, -- Error icon
{ name = 'DiagnosticSignWarn', text = '' }, -- Warning icon
{ name = 'DiagnosticSignHint', text = '' }, -- Hint icon
{ name = 'DiagnosticSignInfo', text = '' }, -- Information icon
}
local function ensure_sign_defined(name, sign_opts)
if vim.tbl_isempty(vim.fn.sign_getdefined(name)) then
vim.fn.sign_define(name, sign_opts)
end
end
for _, sign in ipairs(signs) do
ensure_sign_defined(sign.name, {
text = sign.text,
texthl = sign.texthl or sign.name,
numhl = sign.numhl or sign.name,
})
end
---@type vim.diagnostic.Opts
local diagnostics_config = {
signs = {
active = signs, -- show signs
},
update_in_insert = false,
underline = true,
severity_sort = true,
virtual_text = true,
}
vim.diagnostic.config(diagnostics_config)
-- end of junnplus/lsp-setup config
end,
},
@@ -293,16 +306,6 @@ return {
'stevearc/conform.nvim',
event = { 'BufWritePre' },
cmd = { 'ConformInfo' },
keys = {
{
'<leader>cf',
function()
require('conform').format { async = true, lsp_format = 'fallback' }
end,
mode = '',
desc = 'Format buffer',
},
},
opts = {
notify_on_error = false,
---@type nil|conform.FormatOpts|fun(bufnr: integer): nil|conform.FormatOpts
@@ -317,6 +320,11 @@ return {
else
lsp_format_opt = 'fallback'
end
-- Disable autoformat for files in a certain paths
local bufname = vim.api.nvim_buf_get_name(bufnr)
if bufname:match '/node_modules|vendor/' then return end
return {
timeout_ms = 500,
lsp_format = lsp_format_opt,
@@ -324,6 +332,9 @@ return {
end,
formatters_by_ft = {
lua = { 'stylua' },
sh = { 'shfmt' },
bash = { 'shfmt' },
php = { 'phpcbf' },
-- Conform can also run multiple formatters sequentially
-- python = { "isort", "black" },
--
@@ -331,6 +342,10 @@ return {
-- javascript = { "prettierd", "prettier", stop_after_first = true },
},
},
init = function()
-- If you want the formatexpr, here is the place to set it
vim.o.formatexpr = "v:lua.require'conform'.formatexpr()"
end,
},
-- Automatically install formatters registered with conform.nvim via mason.nvim
-- https://github.com/zapling/mason-conform.nvim

View File

@@ -1,8 +1,12 @@
return {
-- Library of 40+ independent Lua modules improving overall Neovim
-- (version 0.8 and higher) experience with minimal effort
--
-- https://github.com/echasnovski/mini.nvim
-- https://github.com/echasnovski/mini.nvim/tree/main?tab=readme-ov-file#modules
--
-- YouTube: Text editing with 'mini.nvim' - Neovimconf 2024 - Evgeni Chasnovski
-- https://www.youtube.com/watch?v=cNK5kYJ7mrs
{
'echasnovski/mini.nvim',
version = '*',
@@ -78,6 +82,7 @@ return {
miniclue.gen_clues.registers(),
miniclue.gen_clues.windows(),
miniclue.gen_clues.z(),
{ mode = 'n', keys = '<Leader>a', desc = '+Automation' },
{ mode = 'n', keys = '<Leader>b', desc = '+Buffers' },
{ mode = 'n', keys = '<Leader>c', desc = '+Code' },
{ mode = 'n', keys = '<Leader>cb', desc = '+CommentBox' },
@@ -160,20 +165,6 @@ return {
-- Replaced lukas-reineke/indent-blankline.nvim
require('mini.indentscope').setup()
-- Jump to next/previous single character
require('mini.jump').setup {
mappings = {
forward = 'f',
backward = 'F',
forward_till = 't',
backward_till = 'T',
repeat_jump = ';',
},
}
-- Move lines and blocks of text
require('mini.move').setup()
-- Text edit operators
-- g= - Evaluate text and replace with output
-- gx - Exchange text regions
@@ -218,18 +209,18 @@ return {
content = {
active = function()
local mode, mode_hl = sl.section_mode { trunc_width = 120 }
local git = sl.section_git { trunc_width = 75 }
local diagnostics = sl.section_diagnostics { trunc_width = 75 }
local filename = sl.section_filename { trunc_width = 999 }
-- local fileinfo = statusline.section_fileinfo({ trunc_width = 120 })
local location = sl.section_location { trunc_width = 75 }
local git = sl.section_git { trunc_width = 9999 }
local diagnostics = sl.section_diagnostics { trunc_width = 9999 }
local filename = sl.section_filename { trunc_width = 9999 }
local fileinfo = sl.section_fileinfo { trunc_width = 9999 }
local location = sl.section_location { trunc_width = 9999 }
return sl.combine_groups {
{ hl = mode_hl, strings = { mode } },
{ hl = 'statuslineDevinfo', strings = { git, diagnostics } },
'%<', -- Mark general truncate point
{ hl = 'statuslineFilename', strings = { filename } },
'%=', -- End left alignment
-- { hl = 'statuslineFileinfo', strings = { fileinfo } },
{ hl = 'statuslineFileinfo', strings = { fileinfo } },
{ hl = mode_hl, strings = { location } },
}
end,

View File

@@ -31,9 +31,43 @@ return {
cmd = 'Neotree',
opts = {
close_if_last_window = true,
hide_root_node = true,
popup_border_style = 'rounded',
enable_git_status = true,
enable_diagnostics = true,
sources = {
'filesystem',
'buffers',
'document_symbols',
},
source_selector = {
winbar = true,
statusline = false,
separator = { left = '', right = '' },
show_separator_on_edge = true,
highlight_tab = 'SidebarTabInactive',
highlight_tab_active = 'SidebarTabActive',
highlight_background = 'StatusLine',
highlight_separator = 'SidebarTabInactiveSeparator',
highlight_separator_active = 'SidebarTabActiveSeparator',
},
event_handlers = {
{
event = 'file_opened',
handler = function(file_path)
require('neo-tree.command').execute { action = 'close' }
end,
},
},
default_component_configs = {
indent = {
padding = 0,
},
name = {
use_git_status_colors = true,
highlight_opened_files = true,
},
},
git_status = {
symbols = {
-- Change type
@@ -54,59 +88,18 @@ return {
mappings = {
['<Esc>'] = 'close_window',
['q'] = 'close_window',
['<cr>'] = 'open_with_window_picker',
},
},
filtered_items = {
hide_dotfiles = true,
hide_gitignored = true,
hide_dotfiles = false,
hide_hidden = true, -- only works on Windows for hidden files/directories
never_show = {
'.DS_Store',
},
hide_by_name = {
'node_modules',
},
always_show = {
'.actrc',
'.browserslistrc',
'.commitlintrc.json',
'.editorconfig',
'.env',
'.env.example',
'.envrc',
'.eslintrc.json',
'.github',
'.gitignore',
'.gitkeep',
'.ignore',
'.markdownlint.json',
'.markdownlint.yaml',
'.markdownlintignore',
'.nvmrc',
'.prettierignore',
'.prettierrc.js',
'.prettierrc.json',
'.prettierrc.yaml',
'.python-version',
'.releaserc.json',
'.shellcheckrc',
'.simple-git-hooks.json',
'.stylelintrc.json',
'.stylua.toml',
'.yamlignore',
'.yamllint.yaml',
},
always_show_by_pattern = {
'.*.json',
'.*.toml',
'.*.yaml',
'.*.yml',
'.*rc',
'.*rc.*',
'.env*',
'.prettierrc*',
'.markdownlint*',
'.stylua.*',
'.git',
},
},
},

View File

@@ -1,4 +1,41 @@
return {
{
'rmagatti/auto-session',
lazy = false,
version = '*',
opts = {
suppressed_dirs = {
'/',
'~/',
'~/Downloads',
'~/Library',
},
bypass_save_filetypes = {
'PlenaryTestPopup',
'alpha',
'checkhealth',
'dashboard',
'dbout',
'gitsigns.blame',
'grug-far',
'help',
'lspinfo',
'man',
'neo-tree',
'neotest-output',
'neotest-output-panel',
'neotest-summary',
'notify',
'qf',
'spectre_panel',
'startuptime',
'trouble',
'tsplayground',
},
-- log_level = 'debug',
},
},
{
'nvim-lua/plenary.nvim',
version = '*',

View File

@@ -36,6 +36,9 @@ return {
local t = require 'telescope'
local a = require 'telescope.actions'
local open_with_trouble = require('trouble.sources.telescope').open
local add_to_trouble = require('trouble.sources.telescope').add
-- [[ Configure Telescope ]]
-- See `:help telescope` and `:help telescope.setup()`
t.setup {
@@ -52,6 +55,12 @@ return {
['<C-j>'] = a.move_selection_next,
['<C-k>'] = a.move_selection_previous,
['<C-d>'] = a.move_selection_previous,
['<C-t>'] = open_with_trouble,
['<C-q>'] = add_to_trouble,
},
n = {
['<C-t>'] = open_with_trouble,
['<C-q>'] = add_to_trouble,
},
},
},

View File

@@ -12,7 +12,6 @@ return {
'nvim-treesitter/nvim-treesitter-context',
'JoosepAlviste/nvim-ts-context-commentstring',
},
---@type TSConfig
opts = {
auto_install = true, -- Auto install the parser generators
sync_install = false, -- Sync install the parser generators, install async

View File

@@ -27,6 +27,17 @@ return {
},
},
-- The fastest Neovim colorizer
-- https://github.com/catgoose/nvim-colorizer.lua
{
'catgoose/nvim-colorizer.lua',
opts = {
user_default_options = {
names = false,
},
},
},
-- A neovim plugin that shows colorcolumn dynamically
-- https://github.com/Bekaboo/deadcolumn.nvim
{ 'Bekaboo/deadcolumn.nvim' },

View File

@@ -1,6 +1,11 @@
-- These are my utility functions
-- I use to make my life bit easier
local function file_exists(name)
if type(name) ~= 'string' then return false end
return os.rename(name, name) and true or false
end
-- ╭─────────────────────────────────────────────────────────╮
-- │ Function shortcuts for keymap set │
-- ╰─────────────────────────────────────────────────────────╯
@@ -80,3 +85,20 @@ end
-- Toggle background between light and dark
function ToggleBackground() vim.o.bg = vim.o.bg == 'light' and 'dark' or 'light' end
-- ╭─────────────────────────────────────────────────────────╮
-- │ LSP Related helper functions │
-- ╰─────────────────────────────────────────────────────────╯
-- Get the license key for intelephense
---@return string|nil -- The license key for intelephense
function GetIntelephenseLicense()
local p = os.getenv 'HOME' .. '/intelephense/license.txt'
if not file_exists(p) then return nil end
local f = assert(io.open(p, 'rb'))
local content = f:read '*a'
f:close()
return string.gsub(content, '%s+', '')[1] or nil
end

View File

@@ -42,7 +42,7 @@ if ! declare -f msg > /dev/null; then
# $1 - message (string)
msg()
{
[ "$VERBOSE" -eq 1 ] && echo "$1"
[ "$VERBOSE" -eq 1 ] && msgr msg "$1"
return 0
}
msg "msg was not defined, defined it now"
@@ -54,7 +54,7 @@ if ! declare -f msg_err > /dev/null; then
# $1 - error message (string)
msg_err()
{
echo "(!) ERROR: $1" >&2
msgr err "$1" >&2
exit 1
}
fi
@@ -65,7 +65,7 @@ if ! declare -f msg_done > /dev/null; then
# $1 - message (string)
msg_done()
{
echo "$1"
msgr done "$1"
return 0
}
fi
@@ -76,7 +76,7 @@ if ! declare -f msg_run > /dev/null; then
# $1 - message (string)
msg_run()
{
echo "$1"
msgr run "$1"
return 0
}
fi
@@ -87,10 +87,29 @@ if ! declare -f msg_ok > /dev/null; then
# $1 - message (string)
msg_ok()
{
echo "$1"
msgr ok "$1"
return 0
}
fi
if ! declare -f array_diff > /dev/null; then
# Function to compare two arrays and return the difference
# Example: array_diff DIFFERENCE ARRAY1 ARRAY2
# $1 - variable to store the difference
# $2 - first array
# $3 - second array
# Output to $1 the difference between $2 and $3
# Source: https://stackoverflow.com/a/42399479/594940
array_diff()
{
# shellcheck disable=SC1083,SC2086
eval local ARR1=\(\"\${$2[@]}\"\)
# shellcheck disable=SC1083,SC2086
eval local ARR2=\(\"\${$3[@]}\"\)
local IFS=$'\n'
mapfile -t "$1" < <(comm -23 <(echo "${ARR1[*]}" | sort) <(echo "${ARR2[*]}" | sort))
}
fi
source "$DOTFILES/config/exports"
source "$DOTFILES/config/alias"

View File

@@ -2,4 +2,9 @@ default_session = "main"
[[search_dirs]]
path = "~/Code"
depth = 10
depth = 3
[picker_colors]
highlight_color = "#21202e"
highlight_text_color = "#86e1fc"
border_color = "#524f67"

1
config/tmux/.ignore Normal file
View File

@@ -0,0 +1 @@
plugins/*

View File

@@ -0,0 +1,37 @@
# ╭──────────────────────────────────────────────────────────╮
# │ Bindings │
# ╰──────────────────────────────────────────────────────────╯
# bind flags
# -r = repeatable, only needs prefix once
# -n = doesn't need prefix
# -t = binds to a certain key-table (root, copy-mode, prefix, etc.)
# Set <prefix> to Control + Space, keeping the default of C-b intact.
# C-Space send-prefix line doubles the prefix when in nested tmux session.
set -g prefix C-Space
bind C-Space send-prefix
# Use Alt-arrow keys without prefix key to switch panes
bind -n M-Left select-pane -L
bind -n M-Right select-pane -R
bind -n M-Up select-pane -U
bind -n M-Down select-pane -D
# Easier switching between window
bind C-n next-window
bind C-p previous-window
bind C-a last-window
# Reload tmux config with <prefix> + r
unbind r
bind r "source-file ~/.dotfiles/config/tmux/tmux.conf; display 'tmux cfg reloaded!'"
# copy mode using 'Esc'
unbind [
bind Escape copy-mode
# paste using 'p'
unbind p
bind p paste-buffer
# vim: ft=tmux ts=2 sw=2 et

View File

@@ -0,0 +1,50 @@
# ╭──────────────────────────────────────────────────────────╮
# │ Plugins │
# ╰──────────────────────────────────────────────────────────╯
# ── Plugins related configurations ────────────────────────────────────
# Plugin that lets you suspend local tmux session,
# so that you can work with nested remote tmux session painlessly.
# https://github.com/MunifTanjim/tmux-suspend
set -g @suspend_key 'F12'
## A plugin to name your tmux windows smartly.
## https://github.com/ofirgall/tmux-window-name
### Maximum name length of a window
set -g @tmux_window_name_max_name_len "20"
### Replace $HOME with ~ in window names
set -g @tmux_window_dir_programs "['nvim', 'vim', 'vi', 'git']"
set -g @tmux_window_name_ignored_programs "['sqlite3', 'antidote', 'direnv', 'md5']" # Default is []
set -g @tmux_window_name_shells "['bash', 'fish', 'sh', 'zsh']"
set -g @tmux_window_name_substitute_sets "[('.+ipython2', 'ipython2'), ('.+ipython3', 'ipython3'), ('.+\.local', '.local'), ('.+asdf', 'asdf')]"
set -g @tmux_window_name_use_tilde "True"
# https://github.com/erikw/tmux-dark-notify
set -g @dark-notify-theme-path-light "$TMUX_CONF_DIR/theme-light.conf"
set -g @dark-notify-theme-path-dark "$TMUX_CONF_DIR/theme-dark.conf"
## https://github.com/MunifTanjim/tmux-mode-indicator
set -g @mode_indicator_copy_mode_style 'bg=default,fg=yellow'
set -g @mode_indicator_empty_mode_style 'bg=default,fg=#7aa2f7'
set -g @mode_indicator_prefix_mode_style 'bg=default,fg=#7aa2f7'
set -g @mode_indicator_sync_mode_style 'bg=default,fg=red'
# https://github.com/wfxr/tmux-fzf-url
set -g @fzf-url-bind 'u'
set -g @fzf-url-history-limit '2000'
# ── Sourcing the plugins ──────────────────────────────────────────────
run-shell "$TMUX_PLUGINS/tmux-sensible/sensible.tmux"
run-shell "$TMUX_PLUGINS/tmux-window-name/tmux_window_name.tmux"
run-shell "$TMUX_PLUGINS/tmux-mode-indicator/mode_indicator.tmux"
run-shell "$TMUX_PLUGINS/tmux-suspend/suspend.tmux"
run-shell "$TMUX_PLUGINS/tmux-continuum/continuum.tmux"
run-shell "$TMUX_PLUGINS/tmux-sessionist/sessionist.tmux"
run-shell "$TMUX_PLUGINS/tmux-yank/yank.tmux"
run-shell "$TMUX_PLUGINS/tmux-current-pane-hostname/current_pane_hostname.tmux"
run-shell "$TMUX_PLUGINS/tmux-dark-notify/main.tmux"
run-shell "$TMUX_PLUGINS/tmux-fzf-url/fzf-url.tmux"
# vim: ft=tmux ts=2 sw=2 et

View File

@@ -0,0 +1,40 @@
# ╭──────────────────────────────────────────────────────────╮
# │ Settings │
# ╰──────────────────────────────────────────────────────────╯
# set [flags] [command] [value]
# Flags can be combined, e.g. -as
# -a : Append the value to the existing setting.
# -s : Apply the setting to the current session.
# -g : Apply the setting globally to all sessions.
# -o : Set the option only if it is not already set.
# -u : Unset the specified option.
set -g default-terminal "tmux-256color" # Set default terminal to 256 colors
set -g detach-on-destroy off # don't detach tmux when killing a session
set -g display-time 0 # Hide clock
set -g focus-events on # Focus events enabled for terminals that support them
set -g mouse on # Mouse support
set -g set-titles on # Allow tmux to set the terminal title
set -g status on # Setting status on
set -g status-keys vi # vi keys to move between panes
# Activity Monitoring (for when something happens in another pain)
set -g monitor-activity on
set -g visual-activity off
set -g visual-bell off
# A bell in another window should cause a bell in the current window
set -g bell-action any
# Keep Tmux alive when the initial command is finished
set -g remain-on-exit off
# Start windows and panes at 1, not 0
set -g base-index 1
set -g pane-base-index 1
set -g renumber-windows on
# Activate with `DEBUG=1 tmux -vv`
if-shell '[ "$DEBUG" = "1" ]' 'set -g debug-file ~/.cache/tmux-debug.log'
# vim: ft=tmux ts=2 sw=2 et

View File

@@ -0,0 +1,16 @@
# ╭──────────────────────────────────────────────────────────╮
# │ Theme │
# ╰──────────────────────────────────────────────────────────╯
set -g pane-active-border-style "fg=#7aa2f7"
set -g pane-border-style "fg=#3b4261"
set -g status-justify "left"
set -g status-left ''
set -g status-left-length "0"
set -g status-position "bottom"
set -g status-right "#S@#{hostname_short} #{tmux_mode_indicator}"
set -g status-right-length "30"
set -g window-status-current-format ' #I:#W#{?window_zoomed_flag, ◈ ,} '
set -g window-status-format ' #I:#W '
# vim: ft=tmux ts=2 sw=2 et

View File

@@ -0,0 +1 @@
https://wfxr.mit-license.org/2018

View File

@@ -0,0 +1,64 @@
#!/usr/bin/env bash
#===============================================================================
# Author: Wenxuan
# Email: wenxuangm@gmail.com
# Created: 2018-04-06 12:12
#===============================================================================
get_fzf_options()
{
local fzf_options
local fzf_default_options='-w 100% -h 50% --multi -0 --no-preview'
fzf_options="$(tmux show -gqv '@fzf-url-fzf-options')"
[ -n "$fzf_options" ] && echo "$fzf_options" || echo "$fzf_default_options"
}
fzf_filter()
{
eval "fzf-tmux $(get_fzf_options)"
}
custom_open=$3
open_url()
{
if [[ -n $custom_open ]]; then
$custom_open "$@"
elif hash xdg-open &> /dev/null; then
nohup xdg-open "$@"
elif hash open &> /dev/null; then
nohup open "$@"
elif [[ -n $BROWSER ]]; then
nohup "$BROWSER" "$@"
fi
}
limit='screen'
[[ $# -ge 2 ]] && limit=$2
if [[ $limit == 'screen' ]]; then
content="$(tmux capture-pane -J -p -e | sed -r 's/\x1B\[[0-9;]*[mK]//g'))"
else
content="$(tmux capture-pane -J -p -e -S -"$limit" | sed -r 's/\x1B\[[0-9;]*[mK]//g'))"
fi
urls=$(echo "$content" | grep -oE '(https?|ftp|file):/?//[-A-Za-z0-9+&@#/%?=~_|!:,.;]*[-A-Za-z0-9+&@#/%=~_|]')
wwws=$(echo "$content" | grep -oE '(http?s://)?www\.[a-zA-Z](-?[a-zA-Z0-9])+\.[a-zA-Z]{2,}(/\S+)*' | grep -vE '^https?://' | sed 's/^\(.*\)$/http:\/\/\1/')
ips=$(echo "$content" | grep -oE '[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}(:[0-9]{1,5})?(/\S+)*' | sed 's/^\(.*\)$/http:\/\/\1/')
gits=$(echo "$content" | grep -oE '(ssh://)?git@\S*' | sed 's/:/\//g' | sed 's/^\(ssh\/\/\/\)\{0,1\}git@\(.*\)$/https:\/\/\2/')
gh=$(echo "$content" | grep -oE "['\"]([_A-Za-z0-9-]*/[_.A-Za-z0-9-]*)['\"]" | sed "s/['\"]//g" | sed 's#.#https://github.com/&#')
if [[ $# -ge 1 && $1 != '' ]]; then
extras=$(echo "$content" | eval "$1")
fi
items=$(
printf '%s\n' "${urls[@]}" "${wwws[@]}" "${gh[@]}" "${ips[@]}" "${gits[@]}" "${extras[@]}" \
| grep -v '^$' \
| sort -u \
| nl -w3 -s ' '
)
[ -z "$items" ] && tmux display 'tmux-fzf-url: no URLs found' && exit
fzf_filter <<< "$items" | awk '{print $2}' \
| while read -r chosen; do
open_url "$chosen" &> "/tmp/tmux-$(id -u)-fzf-url.log"
done

View File

@@ -0,0 +1,23 @@
#!/usr/bin/env bash
#===============================================================================
# Author: Wenxuan
# Email: wenxuangm@gmail.com
# Created: 2018-04-06 09:30
#===============================================================================
SCRIPT_DIR=$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)
# $1: option
# $2: default value
tmux_get() {
local value
value="$(tmux show -gqv "$1")"
[ -n "$value" ] && echo "$value" || echo "$2"
}
key="$(tmux_get '@fzf-url-bind' 'u')"
history_limit="$(tmux_get '@fzf-url-history-limit' 'screen')"
extra_filter="$(tmux_get '@fzf-url-extra-filter' '')"
custom_open="$(tmux_get '@fzf-url-open' '')"
echo "$extra_filter" >/tmp/filter
tmux bind-key "$key" run -b "$SCRIPT_DIR/fzf-url.sh '$extra_filter' $history_limit '$custom_open'"

28
config/tmux/rename-session.sh Executable file
View File

@@ -0,0 +1,28 @@
#!/usr/bin/env bash
# Default session name
DEFAULT_NAME="main"
# Current session
CURRENT_SESSION=$(tmux display-message -p "#{session_name}")
# Check that the session has a name
if [ "$CURRENT_SESSION" = "#{session_name}" ] || [ "$CURRENT_SESSION" = "0" ]; then
# Check if the default name is already in use
if tmux has-session -t "$DEFAULT_NAME" 2> /dev/null; then
# Query the user for a new name
echo "Session name '$DEFAULT_NAME' is already in use. Enter a new name:"
read -r NEW_NAME
while tmux has-session -t "$NEW_NAME" 2> /dev/null || [ -z "$NEW_NAME" ]; do
echo "Name '$NEW_NAME' is invalid or already in use. Enter a new name:"
read -r NEW_NAME
done
# Rename the session with the new name
tmux rename-session -t "$(tmux display-message -p "#{session_id}")" "$NEW_NAME"
exit 0
else
# Rename the session with the default name
tmux rename-session -t "$(tmux display-message -p "#{session_id}")" "$DEFAULT_NAME"
exit 0
fi
fi

16
config/tmux/theme-activate.sh Executable file
View File

@@ -0,0 +1,16 @@
#!/usr/bin/env bash
#
# If our dark/light theme switching theme file can be found,
# source it in tmux. This is a separate file to keep the
# current theme settings separate from the main tmux configuration.
#
# This script requires the following in your tmux.conf:
# `run-shell "./theme-activate.sh"`
# and having the tmux-dark-notify plugin installed.
#
# Author: Ismo Vuorinen <https://github.com/ivuorinen> 2025
# License: MIT
THEME_FILE="$HOME/.local/state/tmux/tmux-dark-notify-theme.conf"
[[ -e $THEME_FILE ]] && tmux source-file "$THEME_FILE"

View File

@@ -4,175 +4,22 @@
# - https://tmuxguide.readthedocs.io/en/latest/tmux/tmux.html
# - https://github.com/dreamsofcode-io/tmux/blob/main/tmux.conf
# ╭──────────────────────────────────────────────────────────╮
# │ Bindings │
# ╰──────────────────────────────────────────────────────────╯
# Load the configuration settings
source-file "$TMUX_CONF_DIR/config-settings.conf"
# Set <prefix> to Control + Space, keeping the default of C-b intact.
# unbind C-b
set -g prefix C-Space
bind C-Space send-prefix
# Load the theme settings
source-file "$TMUX_CONF_DIR/config-themes.conf"
# Vim style pane selection
bind h select-pane -L
bind j select-pane -D
bind k select-pane -U
bind l select-pane -R
# Load the keybindings
source-file "$TMUX_CONF_DIR/config-keybinds.conf"
# Use Alt-arrow keys without prefix key to switch panes
bind -n M-Left select-pane -L
bind -n M-Right select-pane -R
bind -n M-Up select-pane -U
bind -n M-Down select-pane -D
# Load the plugins and plugin settings
source-file "$TMUX_CONF_DIR/config-plugins.conf"
# Reload tmux config with <prefix> + r
bind r source-file ~/.dotfiles/config/tmux/tmux.conf \; display "tmux cfg reloaded!"
# Switch to next client with <prefix>( and previous with <prefix>)
bind -r '(' switch-client -p\; refresh-client -S
bind -r ')' switch-client -n\; refresh-client -S
# tms, https://github.com/jrmoulton/tmux-sessionizer
bind C-h display-popup -E "tms"
bind C-j display-popup -E "tms switch"
bind C-k display-popup -E "tms windows"
# Open a new window with <prefix> + N
bind N new-window
# Set default directory for new windows in this session to current directory:
bind M-c attach-session -c "#{pane_current_path}"
# Open a new window in the current directory
bind C new-window -c "#{pane_current_path}"
# keybindings
bind-key -T copy-mode-vi v send-keys -X begin-selection
bind-key -T copy-mode-vi C-v send-keys -X rectangle-toggle
bind-key -T copy-mode-vi y send-keys -X copy-selection-and-cancel
bind '"' split-window -v -c "#{pane_current_path}"
bind '!' split-window -h -c "#{pane_current_path}"
bind '^' switch-client -t'{marked}'
# synchronize all panes in a window
bind y setw synchronize-panes
#### copy mode : vim ####
# copy mode using 'Esc'
unbind [
bind Escape copy-mode
# paste using 'p'
unbind p
bind p paste-buffer
# ╭──────────────────────────────────────────────────────────╮
# │ Settings │
# ╰──────────────────────────────────────────────────────────╯
set -g default-terminal "tmux-256color"
set -ag terminal-overrides ",xterm-256color:RGB"
# Setting status on
set -g status "on"
# Hide clock
set -g display-time 0
# Activity Monitoring (for when something happens in another pain)
set -g monitor-activity on
set -g visual-activity off
set -g visual-bell off
# Expose window title
set-option -g set-titles on
# Set bigger history limit
set -g history-limit 20000
# Keep Tmux alive when the initial command is finished
set -g remain-on-exit off
# Mouse support
set -g mouse on
# Make delay shorter
set -sg escape-time 0
# Start windows and panes at 1, not 0
set -g base-index 1
set -g pane-base-index 1
set-window-option -g pane-base-index 1
set-option -g renumber-windows on
# set vi-mode
set-window-option -g mode-keys vi
# ╭──────────────────────────────────────────────────────────╮
# │ Theme │
# ╰──────────────────────────────────────────────────────────╯
set -g status-left-length "0"
set -g status-right-length "30"
set-option -g status-position "bottom"
set-option -g status-justify left
set-option -g status-left ''
set-option -g window-status-format ' #I:#W '
set-option -g window-status-current-format ' #I:#W#{?window_zoomed_flag, ◈ ,} '
set-option -g status-right "#{hostname_short}/#(tms sessions) #{tmux_mode_indicator}"
set -g pane-border-style "fg=#3b4261"
set -g pane-active-border-style "fg=#7aa2f7"
# https://github.com/erikw/tmux-dark-notify
set -g @dark-notify-theme-path-light '~/.dotfiles/config/tmux/theme-light.conf'
set -g @dark-notify-theme-path-dark '~/.dotfiles/config/tmux/theme-dark.conf'
# ╭──────────────────────────────────────────────────────────╮
# │ Plugins related configurations │
# ╰──────────────────────────────────────────────────────────╯
# Plugin that lets you suspend local tmux session,
# so that you can work with nested remote tmux session painlessly.
# https://github.com/MunifTanjim/tmux-suspend
set -g @suspend_key 'F12'
## A plugin to name your tmux windows smartly.
## https://github.com/ofirgall/tmux-window-name
### Maximum name length of a window
set -g @tmux_window_name_max_name_len "20"
### Replace $HOME with ~ in window names
set -g @tmux_window_name_use_tilde "True"
set -g @tmux_window_name_shells "['bash', 'fish', 'sh', 'zsh', 'oh-my-posh']"
set -g @tmux_window_dir_programs "['nvim', 'vim', 'vi', 'git']"
set -g @tmux_window_name_ignored_programs "['sqlite3', 'oh-my-posh', 'antidot', 'antidote', 'direnv']" # Default is []
set -g @tmux_window_name_substitute_sets "[('.+ipython2', 'ipython2'), ('.+ipython3', 'ipython3'), ('.+\.local', '.local'), ('.+asdf', 'asdf')]"
## https://github.com/tmux-plugins/tmux-continuum
# set -g @continuum-restore 'on'
## https://github.com/MunifTanjim/tmux-mode-indicator
set -g @mode_indicator_prefix_mode_style 'bg=default,fg=#7aa2f7'
set -g @mode_indicator_copy_mode_style 'bg=default,fg=yellow'
set -g @mode_indicator_empty_mode_style 'bg=default,fg=#7aa2f7'
set -g @mode_indicator_sync_mode_style 'bg=default,fg=red'
# ╭──────────────────────────────────────────────────────────╮
# │ Plugins │
# ╰──────────────────────────────────────────────────────────╯
run-shell ~/.dotfiles/config/tmux/plugins/tmux-sensible/sensible.tmux
run-shell ~/.dotfiles/config/tmux/plugins/tmux-window-name/tmux_window_name.tmux
# run-shell ~/.dotfiles/config/tmux/plugins/tmux-continuum/continuum.tmux
# run-shell ~/.dotfiles/config/tmux/plugins/tmux-sessionist/sessionist.tmux
run-shell ~/.dotfiles/config/tmux/plugins/tmux-mode-indicator/mode_indicator.tmux
run-shell ~/.dotfiles/config/tmux/plugins/tmux-suspend/suspend.tmux
run-shell ~/.dotfiles/config/tmux/plugins/tmux-yank/yank.tmux
run-shell ~/.dotfiles/config/tmux/plugins/tmux-current-pane-hostname/current_pane_hostname.tmux
run-shell ~/.dotfiles/config/tmux/plugins/tmux-dark-notify/main.tmux
if-shell "test -e $HOME/.local/state/tmux/tmux-dark-notify-theme.conf" \
"source-file $HOME/.local/state/tmux/tmux-dark-notify-theme.conf"
# Load theme based on tmux-dark-notify state.
# This script helps states where dark-notify is not available,
# and we want to have light or dark state constantly available.
run-shell "$TMUX_CONF_DIR/theme-activate.sh"
# If we started tmux with a session name, rename it.
run-shell "$TMUX_CONF_DIR/rename-session.sh"

View File

@@ -4,18 +4,19 @@ local config = wezterm.config_builder()
-- Font and font size
config.font_size = 14.0
config.font = wezterm.font_with_fallback {
'JetBrainsMonoNL Nerd Font Mono',
'JetBrainsMonoNL NFM Light',
'JetBrains Mono',
'Noto Color Emoji',
'Symbols Nerd Font Mono',
}
config.harfbuzz_features = { 'zero', 'ss01', 'cv05' }
-- Make the window a bit transparent
config.window_background_opacity = 0.97
config.window_background_opacity = 0.98
-- Don't show tab bar
config.enable_tab_bar = false
-- Fix alt on macOS
config.send_composed_key_when_left_alt_is_pressed = true
-- Function to detect the theme based on appearance

78
config/zed/settings.json Normal file
View File

@@ -0,0 +1,78 @@
{
"telemetry": {
"metrics": false
},
"assistant": {
"default_model": {
"provider": "copilot_chat",
"model": "claude-3-5-sonnet"
},
"version": "2"
},
"formatter": {
"external": {
"command": "node_modules/.bin/prettier",
"arguments": [
"--stdin-filepath",
"{buffer_path}"
]
}
},
"languages": {
"JavaScript": {
"enable_language_server": true,
"code_actions_on_format": {
"source.fixAll.eslint": true
}
},
"Lua": {
"enable_language_server": true,
"tab_size": 2
}
},
"lsp": {
"eslint": {
"settings": {
"nodePath": "./node_modules/.bin"
}
},
"gopls": {
"initialization_options": {
"hints": {
"assignVariableTypes": true,
"compositeLiteralFields": true,
"compositeLiteralTypes": true,
"constantValues": true,
"functionTypeParameters": true,
"parameterNames": true,
"rangeVariableTypes": true
}
}
}
},
"preferred_line_length": 100,
"format_on_save": "on",
"vim_mode": true,
"theme": {
"mode": "system",
"light": "Tokyo Night Light",
"dark": "Tokyo Night Storm"
},
"inlay_hints": {
"enabled": true,
"show_type_hints": true,
"show_parameter_hints": true,
"show_other_hints": true
},
"ui_font_size": 16,
"buffer_font_size": 16,
"buffer_font_fallbacks": [
"JetBrainsMono Nerd Font"
],
"inline_completions": {
"disabled_globs": [
".env"
]
},
"hour_format": "hour24"
}

View File

@@ -26,7 +26,7 @@ ohmyzsh/ohmyzsh path:plugins/golang
ohmyzsh/ohmyzsh path:plugins/gpg-agent
ohmyzsh/ohmyzsh path:plugins/nvm
ohmyzsh/ohmyzsh path:plugins/python
ohmyzsh/ohmyzsh path:plugins/tmux
# ohmyzsh/ohmyzsh path:plugins/tmux
ohmyzsh/ohmyzsh path:plugins/z
# Automatically activate nvm if .nvmrc file is present

170
config/zsh/completion/_dfm Normal file
View File

@@ -0,0 +1,170 @@
#compdef dfm
# Completion for dfm, the dotfiles manager
_dfm_get_script_description() {
local file="$1"
sed -n '/@description/s/.*@description *\(.*\)/\1/p' "$file" | head -1
}
_dfm_get_available_scripts() {
local scripts=()
local dotfiles="${HOME}/.dotfiles"
for script in "${dotfiles}/scripts/install-"*.sh; do
if [ -f "$script" ]; then
local name=$(basename "$script" .sh | sed 's/install-//')
local desc=$(_dfm_get_script_description "$script")
[ -z "$desc" ] && desc="No description available"
scripts+=("${name}:${desc}")
fi
done
echo ${(F)scripts}
}
_dfm()
{
local -a commands sections
sections=(
'install:Installation commands'
'asdf:ASDF version manager commands'
'brew:Homebrew package manager commands'
'check:System check commands'
'dotfiles:Dotfiles management commands'
'docs:Documentation commands'
'helpers:Helper utilities'
'scripts:Installation scripts'
'tests:Test commands'
)
_arguments -C \
"1: :->sections" \
"*::arg:->args"
case "$state" in
sections)
_describe 'sections' sections
;;
args)
case $line[1] in
install)
local -a install_cmds
install_cmds=(
'all:Install everything in correct order'
'cargo:Install rust/cargo packages'
'cheat-databases:Install cheat external cheatsheet databases'
'composer:Install composer'
'fonts:Install programming fonts'
'gh:Install GitHub CLI Extensions'
'go:Install Go Packages'
'imagick:Install ImageMagick CLI'
'macos:Setup nice macOS defaults'
'nvm:Install Node Version Manager'
'nvm-latest:Install latest LTS node'
'npm-packages:Install NPM Packages'
'ntfy:Install ntfy'
'z:Install z'
)
_describe 'install commands' install_cmds
;;
asdf)
local -a asdf_cmds
asdf_cmds=(
'current:Show current versions'
'global:Show global versions'
'installed:Show installed versions'
'plugins-update:Update all plugins'
'plugins-install:Install plugins from configuration'
'plugins-remove:Remove installed plugins'
'reset:Reset plugins'
'fix-tool-versions:Remove uninstalled plugins from .tool-versions'
'versions:Show versions'
'where:Show where'
'which:Show which'
)
_describe 'asdf commands' asdf_cmds
;;
brew)
local -a brew_cmds
brew_cmds=(
'install:Install items from Brewfile'
'update:Update and upgrade packages'
'updatebundle:Update Brewfile with descriptions'
'autoupdate:Setup brew auto-update'
'leaves:List brew leaves'
'clean:Clean up packages'
'untracked:List untracked packages'
)
_describe 'brew commands' brew_cmds
;;
check)
local -a check_cmds
check_cmds=(
'arch:Check architecture'
'host:Check hostname'
)
_describe 'check commands' check_cmds
;;
dotfiles)
local -a dotfiles_cmds
dotfiles_cmds=(
'fmt:Run all formatters'
'yamlfmt:Run yamlfmt'
'shfmt:Run shfmt'
'reset_all:Reset everything'
'reset_nvim:Reset neovim'
)
_describe 'dotfiles commands' dotfiles_cmds
;;
docs)
local -a docs_cmds
docs_cmds=(
'all:Update all documentation'
'tmux:Update tmux documentation'
'nvim:Update nvim documentation'
'wezterm:Update wezterm documentation'
)
_describe 'docs commands' docs_cmds
;;
helpers)
local -a helpers_cmds
helpers_cmds=(
'aliases:Show aliases'
'colors:Show colors'
'env:Show environment variables'
'functions:Show functions'
'nvim:Show nvim keybindings'
'path:Show PATH'
'tmux:Show tmux keybindings'
'wezterm:Show wezterm keybindings'
)
_describe 'helper commands' helpers_cmds
;;
scripts)
local -a script_cmds
script_cmds=("${(@f)$(_dfm_get_available_scripts)}")
_describe 'available scripts' script_cmds
;;
tests)
local -a test_cmds
test_cmds=(
'msg:List log functions'
'params:List parameters'
)
_describe 'test commands' test_cmds
;;
esac
;;
esac
}
_dfm "$@"

View File

@@ -6,7 +6,8 @@
# transient_prompt, instant_prompt=verbose.
# Type `p10k configure` to generate another config.
#
# Config file for Powerlevel10k with the style of Pure (https://github.com/sindresorhus/pure).
# Config file for Powerlevel10k with the style of Pure
# (https://github.com/sindresorhus/pure).
#
# Differences from Pure:
#
@@ -14,13 +15,16 @@
# - `@c4d3ec2c` instead of something like `v1.4.0~11` when in detached HEAD state.
# - No automatic `git fetch` (the same as in Pure with `PURE_GIT_PULL=0`).
#
# Apart from the differences listed above, the replication of Pure prompt is exact. This includes
# even the questionable parts. For example, just like in Pure, there is no indication of Git status
# being stale; prompt symbol is the same in command, visual and overwrite vi modes; when prompt
# doesn't fit on one line, it wraps around with no attempt to shorten it.
# Apart from the differences listed above, the replication of Pure
# prompt is exact. This includes even the questionable parts.
# For example, just like in Pure, there is no indication of Git status
# being stale; prompt symbol is the same in command, visual and overwrite
# vi modes; when prompt doesn't fit on one line, it wraps around with
# no attempt to shorten it.
#
# If you like the general style of Pure but not particularly attached to all its quirks, type
# `p10k configure` and pick "Lean" style. This will give you slick minimalist prompt while taking
# If you like the general style of Pure but not particularly attached
# to all its quirks, type `p10k configure` and pick "Lean" style.
# This will give you slick minimalist prompt while taking
# advantage of Powerlevel10k features that aren't present in Pure.
# Temporarily change options.
@@ -83,8 +87,9 @@
typeset -g POWERLEVEL9K_{LEFT,RIGHT}_SEGMENT_SEPARATOR= # no end-of-line symbol
typeset -g POWERLEVEL9K_VISUAL_IDENTIFIER_EXPANSION= # no segment icons
# Add an empty line before each prompt except the first. This doesn't emulate the bug
# in Pure that makes prompt drift down whenever you use the Alt-C binding from fzf or similar.
# Add an empty line before each prompt except the first. This doesn't
# emulate the bug in Pure that makes prompt drift down whenever you use
# the Alt-C binding from fzf or similar.
typeset -g POWERLEVEL9K_PROMPT_ADD_NEWLINE=true
# Magenta prompt symbol if the last command succeeded.
@@ -116,6 +121,9 @@
# Don't show context unless root or in SSH.
# typeset -g POWERLEVEL9K_CONTEXT_{DEFAULT,SUDO}_CONTENT_EXPANSION=
# aws, go and nvm versions colors.
typeset -g POWERLEVEL9K_{AWS,GO,NVM}_FOREGROUND=$grey
# Show previous command duration only if it's >= 86400s = 24h.
typeset -g POWERLEVEL9K_COMMAND_EXECUTION_TIME_THRESHOLD=86400
# Don't show fractional seconds. Thus, 7s rather than 7.3s.
@@ -125,15 +133,17 @@
# Yellow previous command duration.
typeset -g POWERLEVEL9K_COMMAND_EXECUTION_TIME_FOREGROUND=$yellow
# Grey Git prompt. This makes stale prompts indistinguishable from up-to-date ones.
# Grey Git prompt. This makes stale prompts indistinguishable
# from up-to-date ones.
typeset -g POWERLEVEL9K_VCS_FOREGROUND=$grey
# Disable async loading indicator to make directories that aren't Git repositories
# indistinguishable from large Git repositories without known state.
# Disable async loading indicator to make directories that aren't
# Git repositories indistinguishable from large Git repositories
# without known state.
typeset -g POWERLEVEL9K_VCS_LOADING_TEXT=
# Don't wait for Git status even for a millisecond, so that prompt always updates
# asynchronously when Git state changes.
# Don't wait for Git status even for a millisecond, so that
# prompt always updates asynchronously when Git state changes.
typeset -g POWERLEVEL9K_VCS_MAX_SYNC_LATENCY_SECONDS=0
# Cyan ahead/behind arrows.
@@ -161,36 +171,42 @@
typeset -g POWERLEVEL9K_TIME_FOREGROUND=$grey
# Format for the current time: 09:51:02. See `man 3 strftime`.
typeset -g POWERLEVEL9K_TIME_FORMAT='%D{%H:%M:%S}'
# If set to true, time will update when you hit enter. This way prompts for the past
# commands will contain the start times of their commands rather than the end times of
# their preceding commands.
# If set to true, time will update when you hit enter. This way prompts
# for the past commands will contain the start times of their commands
# rather than the end times of their preceding commands.
typeset -g POWERLEVEL9K_TIME_UPDATE_ON_COMMAND=false
# Transient prompt works similarly to the builtin transient_rprompt option. It trims down prompt
# when accepting a command line. Supported values:
# Transient prompt works similarly to the builtin transient_rprompt option.
# It trims down prompt when accepting a command line. Supported values:
#
# - off: Don't change prompt when accepting a command line.
# - always: Trim down prompt when accepting a command line.
# - same-dir: Trim down prompt when accepting a command line unless this is the first command
# typed after changing current working directory.
# - same-dir: Trim down prompt when accepting a command line
# unless this is the first command typed after
# changing current working directory.
typeset -g POWERLEVEL9K_TRANSIENT_PROMPT=always
# Instant prompt mode.
#
# - off: Disable instant prompt. Choose this if you've tried instant prompt and found
# it incompatible with your zsh configuration files.
# - quiet: Enable instant prompt and don't print warnings when detecting console output
# during zsh initialization. Choose this if you've read and understood
# - off: Disable instant prompt. Choose this if you've tried
# instant prompt and found it incompatible with your
# zsh configuration files.
# - quiet: Enable instant prompt and don't print warnings when
# detecting console output during zsh initialization.
# Choose this if you've read and understood
# https://github.com/romkatv/powerlevel10k#instant-prompt.
# - verbose: Enable instant prompt and print a warning when detecting console output during
# zsh initialization. Choose this if you've never tried instant prompt, haven't
# seen the warning, or if you are unsure what this all means.
# - verbose: Enable instant prompt and print a warning when detecting
# console output during zsh initialization. Choose this
# if you've never tried instant prompt, haven't seen the
# warning, or if you are unsure what this all means.
typeset -g POWERLEVEL9K_INSTANT_PROMPT=off
# Hot reload allows you to change POWERLEVEL9K options after Powerlevel10k has been initialized.
# For example, you can type POWERLEVEL9K_BACKGROUND=red and see your prompt turn red. Hot reload
# can slow down prompt by 1-2 milliseconds, so it's better to keep it turned off unless you
# really need it.
# Hot reload allows you to change POWERLEVEL9K options after
# Powerlevel10k has been initialized. For example, you can type
# POWERLEVEL9K_BACKGROUND=red and see your prompt turn red.
# Hot reload can slow down prompt by 1-2 milliseconds, so it's
# better to keep it turned off unless you really need it.
typeset -g POWERLEVEL9K_DISABLE_HOT_RELOAD=true
# If p10k is already loaded, reload configuration.

View File

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

52
docs/alias.md Normal file
View File

@@ -0,0 +1,52 @@
# Alias Commands
This file lists all aliases defined in `config/alias`.
| Alias | Command |
| ------------- | ------------------------------------------------------------------------------------------------------------------------------ |
| `....` | `cd ../../..` |
| `...` | `cd ../..` |
| `..` | `cd ..` |
| `.` | `cd $HOME` |
| `.b` | `cd $XDG_BIN_HOME` |
| `.c` | `cd $HOME/Code` |
| `.d` | `cd $DOTFILES` |
| `.l` | `cd $HOME/.local` |
| `.o` | `cd $HOME/Code/ivuorinen/obsidian/` |
| `art` | `[ -f artisan ] && php artisan \|\| php vendor/bin/artisan` |
| `cd..` | `cd ..` |
| `cdgr` | `cd "$(get_git_root)"` |
| `dn` | `du -chd1` |
| `flush` | `dscacheutil -flushcache` |
| `grep` | `grep --color` |
| `hide` | `defaults write com.apple.finder AppleShowAllFiles -bool false; killall Finder` |
| `ips` | `ifconfig -a \| grep -o 'inet6\? \(\([0-9]\+\.[0-9]\+\.[0-9]\+\.[0-9]\+\)\\|[a-fA-F0-9:]\+\)' \| sed -e 's/inet6* //' \| sort` |
| `irssi` | `irssi --config=$XDG_CONFIG_HOME/irssi/config --home=$XDG_CONFIG_HOME/irssi` |
| `isodate` | `date +'%Y-%m-%d'` |
| `l` | `ls -a` |
| `ll` | `ls -la` |
| `localip` | `ipconfig getifaddr en1` |
| `mirror_site` | `wget -m -k -K -E -e robots=off` |
| `peek` | `tee >(cat 1>&2)` |
| `pubkey` | `more ~/.ssh/id_rsa.pub \| pbcopy \| echo '=> Public key copied to pasteboard.'` |
| `sail` | `[ -f sail ] && bash sail \|\| bash vendor/bin/sail` |
| `show` | `defaults write com.apple.finder AppleShowAllFiles -bool true; killall Finder` |
| `sl` | `ls` |
| `svn` | `svn --config-dir $XDG_CONFIG_HOME/subversion` |
| `trivy_scan` | `docker run -v /var/run/docker.sock:/var/run/docker.sock -v $HOME/Library/Caches:/root/.cache/ aquasec/trivy` |
| `updatedb` | `sudo /usr/libexec/locate.updatedb` |
| `vi` | `nvim` |
| `vim` | `nvim` |
| `watchx` | `watch -dpbc` |
| `wget` | `wget --hsts-file=$XDG_DATA_HOME/wget-hsts` |
| `x-datetime` | `date +'%Y-%m-%d %H:%M:%S'` |
| `x-ip` | `dig +short myip.opendns.com @resolver1.opendns.com` |
| `x-timestamp` | `date +'%s'` |
| `xdg` | `xdg-ninja --skip-ok --skip-unsupported` |
| `zapall` | `zapds && zappyc` |
| `zapds` | `find . -name ".DS_Store" -print -delete` |
| `zappyc` | `find . -type f -name '*.pyc' -ls -delete` |
| `zedit` | `$EDITOR ~/.dotfiles` |
Total aliases: 43
Last updated: Fri 17 Jan 2025 13:06:59 EET

View File

@@ -2,73 +2,69 @@
```txt
x <Space> *@~/.local/share/nvim/lazy/mini.clue/lua/mini/clue.lua
x <Space> *@~/.local/share/nvim/lazy/mini.nvim/lua/mini/clue.lua
Query keys after "<Space>"
n <Space> *@~/.local/share/nvim/lazy/mini.clue/lua/mini/clue.lua
n <Space> *@~/.local/share/nvim/lazy/mini.nvim/lua/mini/clue.lua
Query keys after "<Space>"
x " *@~/.local/share/nvim/lazy/mini.clue/lua/mini/clue.lua
x " *@~/.local/share/nvim/lazy/mini.nvim/lua/mini/clue.lua
Query keys after """
n " *@~/.local/share/nvim/lazy/mini.clue/lua/mini/clue.lua
n " *@~/.local/share/nvim/lazy/mini.nvim/lua/mini/clue.lua
Query keys after """
x ' *@~/.local/share/nvim/lazy/mini.clue/lua/mini/clue.lua
x ' *@~/.local/share/nvim/lazy/mini.nvim/lua/mini/clue.lua
Query keys after "'"
n ' *@~/.local/share/nvim/lazy/mini.clue/lua/mini/clue.lua
n ' *@~/.local/share/nvim/lazy/mini.nvim/lua/mini/clue.lua
Query keys after "'"
x ` *@~/.local/share/nvim/lazy/mini.clue/lua/mini/clue.lua
x ` *@~/.local/share/nvim/lazy/mini.nvim/lua/mini/clue.lua
Query keys after "`"
n ` *@~/.local/share/nvim/lazy/mini.clue/lua/mini/clue.lua
n ` *@~/.local/share/nvim/lazy/mini.nvim/lua/mini/clue.lua
Query keys after "`"
x g *@~/.local/share/nvim/lazy/mini.clue/lua/mini/clue.lua
x g *@~/.local/share/nvim/lazy/mini.nvim/lua/mini/clue.lua
Query keys after "g"
n g *@~/.local/share/nvim/lazy/mini.clue/lua/mini/clue.lua
n g *@~/.local/share/nvim/lazy/mini.nvim/lua/mini/clue.lua
Query keys after "g"
x z *@~/.local/share/nvim/lazy/mini.clue/lua/mini/clue.lua
x z *@~/.local/share/nvim/lazy/mini.nvim/lua/mini/clue.lua
Query keys after "z"
n z *@~/.local/share/nvim/lazy/mini.clue/lua/mini/clue.lua
n z *@~/.local/share/nvim/lazy/mini.nvim/lua/mini/clue.lua
Query keys after "z"
n <C-W> *@~/.local/share/nvim/lazy/mini.clue/lua/mini/clue.lua
n <C-W> *@~/.local/share/nvim/lazy/mini.nvim/lua/mini/clue.lua
Query keys after "<C-W>"
n <Esc><Esc> * :nohlsearch<CR>
Clear Search Highlighting
n <Space>qQ * :q!<CR>
n <Space>qQ * ~/.config/nvim/lua/keymaps.lua
Force quit without saving
n <Space>qw * :wq<CR>
Write and quit
n <Space>qq * :wq!<CR>
n <Space>qq * ~/.config/nvim/lua/keymaps.lua
Quit with force saving
n <Space>qf * :q<CR>
Quicker close split
n <Space>tn * :Noice dismiss<CR>
Noice: Dismiss Notification
n <Space>tl * :lua vim.o.bg = vim.o.bg:get() == "light" and "dark" or "light"<CR>
n <Space>tl * ~/.config/nvim/lua/utils.lua
Toggle Light/Dark Mode
n <Space>te * :Neotree toggle<CR>
Toggle Neotree
n <Space>tc * :CloakToggle<CR>
Cloak: Toggle
n <Space>o * ~/.config/nvim/lua/keymaps.lua
Open repo in browser
n <Space>xx * :Trouble diagnostics<CR>
Trouble: Diagnostic
Diagnostic
n <Space>xw * :Trouble workspace_diagnostics<CR>
Trouble: Workspace Diagnostics
Workspace Diagnostics
n <Space>xq * :Trouble quickfix<CR>
Trouble: Quickfix
Quickfix
n <Space>xl * :Trouble loclist<CR>
Trouble: Location List
n <Space>xd * :Trouble document_diagnostics<CR>
Trouble: Document Diagnostics
Location List
n <Space>xd * :Trouble diagnostics<CR>
Document Diagnostics
n <Space>sx * :Telescope import<CR>
Telescope: Import
n <Space>sw * :Telescope grep_string<CR>
Grep String
n <Space>st * :TodoTelescope<CR>
Search Todos
n <Space>ss * :Telescope treesitter<CR>
Treesitter
n <Space>sq * :Telescope quickfix<CR>
Quickfix
n <Space>sp * :lua require("telescope").extensions.lazy_plugins.lazy_plugins()<CR>
n <Space>sp * ~/.config/nvim/lua/keymaps.lua
Lazy Plugins
n <Space>so * :Telescope oldfiles<CR>
Old Files
@@ -76,8 +72,8 @@ n <Space>sl * :Telescope luasnip<CR>
Search LuaSnip
n <Space>sk * :Telescope keymaps<CR>
Search Keymaps
n <Space>sh * :Telescope highlights<CR>
List Highlights
n <Space>sh * :Telescope help_tags<CR>
Help tags
n <Space>sg * :Telescope live_grep<CR>
Search by Grep
n <Space>sd * :Telescope diagnostics<CR>
@@ -88,7 +84,7 @@ n <Space>/ * ~/.config/nvim/lua/keymaps.lua
Fuzzily search in current buffer
n <Space>, * :Telescope buffers<CR>
Find existing buffers
n <Space>f * :Telescope find_files<CR>
n <Space>f * :Telescope fd --hidden=true<CR>
Find Files
n <Space>cbt * <Cmd>CBllline<CR>
CB: Titled Line
@@ -100,42 +96,34 @@ n <Space>cbd * <Cmd>CBd<CR>
CB: Remove a box
n <Space>cbb * <Cmd>CBccbox<CR>
CB: Box Title
n <Space>cw * :Lspsaga diagnostic_jump_next<CR>
Diagnostic Jump Next
n <Space>cv * :Lspsaga diagnostic_jump_prev<CR>
Diagnostic Jump Prev
n <Space>cu * :Lspsaga preview_definition<CR>
Preview Definition
n <Space>cT * :Telescope lsp_type_definitions<CR>
LSP Type Definitions
n <Space>ct * :Lspsaga peek_type_definition<CR>
Peek Type Definition
n <Space>cwd * ~/.config/nvim/lua/keymaps.lua
Dynamic Workspace Symbols
n <Space>cws * ~/.config/nvim/lua/keymaps.lua
Workspace Symbols
n <Space>ct * ~/.config/nvim/lua/keymaps.lua
treesitter
n <Space>cs * :Telescope lsp_document_symbols<CR>
LSP Document Symbols
n <Space>cR * :Lspsaga rename ++project<CR>
Rename Project wide
n <Space>cr * :Lspsaga rename<CR>
n <Space>cr * ~/.local/share/bob/v0.10.2/nvim-macos-arm64/share/nvim/runtime/lua/vim/lsp/buf.lua
Rename
n <Space>cp * :Lspsaga peek_definition<CR>
Peek Definition
n <Space>cl * :Lspsaga show_cursor_diagnostics<CR>
Cursor Diagnostics
n <Space>ci * :Lspsaga implement<CR>
n <Space>cp * ~/.config/nvim/lua/keymaps.lua
Type Definition
n <Space>ci * ~/.config/nvim/lua/keymaps.lua
Implementations
n <Space>cg * :lua require("neogen").generate()<CR>
Generate annotations
x <Space>cf * :lua vim.lsp.buf.format()<CR>
Format
n <Space>cf * :lua vim.lsp.buf.format()<CR>
Format
n <Space>cd * :Lspsaga show_line_diagnostics<CR>
Line Diagnostics
n <Space>cco * :Lspsaga outgoing_calls<CR>
Outgoing Calls
n <Space>cci * :Lspsaga incoming_calls<CR>
Incoming Calls
n <Space>ca * :Lspsaga code_action<CR>
n <Space>cd * ~/.config/nvim/lua/keymaps.lua
Definitions
n <Space>cco * ~/.config/nvim/lua/keymaps.lua
Outgoing calls
n <Space>cci * ~/.config/nvim/lua/keymaps.lua
Incoming calls
n <Space>ca * :lua vim.lsp.buf.code_action()<CR>
Code Action
n <Space>cg * :lua require("neogen").generate()<CR>
Generate annotations
n <Space>bw * :lua MiniBufremove.wipeout()<CR>
Wipeout
n <Space>bl * :bnext<CR>
@@ -148,6 +136,50 @@ n <Space>bh * :bprev<CR>
Prev
n <Space>bd * :lua MiniBufremove.delete()<CR>
Delete
n <Space>ba * :%bd|e#|bd#<CR>
Close all except current
n <Space>apt * :PhpactorTransform<CR>
PHPactor: Transform
n <Space>aps * :PhpactorClassSearch<CR>
PHPactor: Class Search
n <Space>apn * :PhpactorClassNew<CR>
PHPactor: Class New
n <Space>apm * :PhpactorContextMenu<CR>
PHPactor: Context Menu
n <Space>av * :silent TestVisit<CR>
Test Visit
n <Space>al * :silent TestLast<CR>
Test Last
n <Space>as * :silent TestSuite<CR>
Test Suite
n <Space>af * :silent TestFile<CR>
Test File
n <Space>an * :silent TestNearest<CR>
Test Nearest
n <Space>o * ~/.config/nvim/lua/keymaps.lua
Open repo in browser
n <Space>tmw * <Cmd>setlocal wrap! wrap?<CR>
Toggle 'wrap'
n <Space>tms * <Cmd>setlocal spell! spell?<CR>
Toggle 'spell'
n <Space>tmr * <Cmd>setlocal relativenumber! relativenumber?<CR>
Toggle 'relativenumber'
n <Space>tmn * <Cmd>setlocal number! number?<CR>
Toggle 'number'
n <Space>tml * <Cmd>setlocal list! list?<CR>
Toggle 'list'
n <Space>tmi * <Cmd>setlocal ignorecase! ignorecase?<CR>
Toggle 'ignorecase'
n <Space>tmh * <Cmd>let v:hlsearch = 1 - v:hlsearch | echo (v:hlsearch ? " " : "no") . "hlsearch"<CR>
Toggle search highlight
n <Space>tmd * <Cmd>lua print(MiniBasics.toggle_diagnostic())<CR>
Toggle diagnostic
n <Space>tmC * <Cmd>setlocal cursorcolumn! cursorcolumn?<CR>
Toggle 'cursorcolumn'
n <Space>tmc * <Cmd>setlocal cursorline! cursorline?<CR>
Toggle 'cursorline'
n <Space>tmb * <Cmd>lua vim.o.bg = vim.o.bg == "dark" and "light" or "dark"; print(vim.o.bg)<CR>
Toggle 'background'
x # * vim/_defaults.lua
:help v_#-default
o % <Plug>(MatchitOperationForward)
@@ -155,14 +187,12 @@ x % <Plug>(MatchitVisualForward)
n % <Plug>(MatchitNormalForward)
n & * :&&<CR>
:help &-default
n '? & :<C-U>echo ":Start" dispatch#start_focus(v:count > 1 ? 0 : v:count ? line(".") : -1)<CR>
n '! & <SNR>28_:.Start!
n '<Space> & <SNR>28_:.Start<Space>
n '<CR> & <SNR>28_:.Start<CR>
x * * vim/_defaults.lua
:help v_star-default
o ; * ~/.local/share/nvim/lazy/mini.jump/lua/mini/jump.lua
Repeat jump
x ; * <Cmd>lua MiniJump.jump()<CR>
Repeat jump
n ; * <Cmd>lua MiniJump.jump()<CR>
Repeat jump
v < * <gv
Indent Left
n < * <gv
@@ -171,35 +201,23 @@ v > * >gv
Indent Right
n > * >gv
Indent Right
n @ * ~/.local/share/nvim/lazy/mini.clue/lua/mini/clue.lua
n @ * ~/.local/share/nvim/lazy/mini.nvim/lua/mini/clue.lua
Execute macro without 'mini.clue' triggers
x @ * mode() == 'V' ? ':normal! @'.getcharstr().'<CR>' : '@'
x @ * mode() ==# 'V' ? ':normal! @'.getcharstr().'<CR>' : '@'
:help v_@-default
o F * ~/.local/share/nvim/lazy/mini.jump/lua/mini/jump.lua
Jump backward
x F * <Cmd>lua MiniJump.smart_jump(true, false)<CR>
Jump backward
n F * <Cmd>lua MiniJump.smart_jump(true, false)<CR>
Jump backward
n K * :Lspsaga hover_doc<CR>
n K * :lua vim.lsp.buf.hover()<CR>
Hover Documentation
n Q * ~/.local/share/nvim/lazy/mini.clue/lua/mini/clue.lua
n Q * ~/.local/share/nvim/lazy/mini.nvim/lua/mini/clue.lua
Execute macro without 'mini.clue' triggers
x Q * mode() == 'V' ? ':normal! @<C-R>=reg_recorded()<CR><CR>' : 'Q'
x Q * mode() ==# 'V' ? ':normal! @<C-R>=reg_recorded()<CR><CR>' : 'Q'
:help v_Q-default
o T * ~/.local/share/nvim/lazy/mini.jump/lua/mini/jump.lua
Jump backward till
x T * <Cmd>lua MiniJump.smart_jump(true, true)<CR>
Jump backward till
n T * <Cmd>lua MiniJump.smart_jump(true, true)<CR>
Jump backward till
n Y * y$
:help Y-default
n Zk * ~/.local/share/nvim/lazy/lazy.nvim/lua/lazy/core/handler/keys.lua
o Zk * ~/.config/nvim/lua/keymaps.lua
Flash Treesitter
x Zk * ~/.local/share/nvim/lazy/lazy.nvim/lua/lazy/core/handler/keys.lua
x Zk * ~/.config/nvim/lua/keymaps.lua
Flash Treesitter
o Zk * ~/.local/share/nvim/lazy/lazy.nvim/lua/lazy/core/handler/keys.lua
n Zk * ~/.config/nvim/lua/keymaps.lua
Flash Treesitter
o [% <Plug>(MatchitOperationMultiBackward)
x [% <Plug>(MatchitVisualMultiBackward)
@@ -247,32 +265,34 @@ n ]h * <Cmd>lua MiniDiff.goto_hunk('next')<CR>
Next hunk
n ]d * vim/_defaults.lua
Jump to the next diagnostic
n `? & <SNR>28_:.FocusDispatch<CR>
n `! & <SNR>28_:.Dispatch!
n `<Space> & <SNR>28_:.Dispatch<Space>
n `<CR> & <SNR>28_:.Dispatch<CR>
x a% <Plug>(MatchitVisualTextObject)
o ax <Plug>(textobj-xmlattr-attr-a)
x ax <Plug>(textobj-xmlattr-attr-a)
o ai * <Cmd>lua MiniIndentscope.textobject(true)<CR>
Object scope with border
x ai * <Cmd>lua MiniIndentscope.textobject(true)<CR>
Object scope with border
o f * ~/.local/share/nvim/lazy/mini.jump/lua/mini/jump.lua
Jump forward
x f * <Cmd>lua MiniJump.smart_jump(false, false)<CR>
Jump forward
n f * <Cmd>lua MiniJump.smart_jump(false, false)<CR>
Jump forward
n gR * :RegexplainerToggle<CR>
Toggle Regexplainer
o g% <Plug>(MatchitOperationBackward)
x g% <Plug>(MatchitVisualBackward)
n g% <Plug>(MatchitNormalBackward)
o gh * <Cmd>lua MiniDiff.textobject()<CR>
Hunk range textobject
x gH * ~/.local/share/nvim/lazy/mini.diff/lua/mini/diff.lua
Reset hunks
n gH * ~/.local/share/nvim/lazy/mini.diff/lua/mini/diff.lua
Reset hunks
x gh * ~/.local/share/nvim/lazy/mini.diff/lua/mini/diff.lua
Apply hunks
n gh * ~/.local/share/nvim/lazy/mini.diff/lua/mini/diff.lua
Apply hunks
n g`? & :<C-U>echo ":Spawn" dispatch#spawn_focus(v:count > 1 ? 0 : v:count ? line(".") : -1)<CR>
n g`! & <SNR>28_:.Spawn!
n g`<Space> & <SNR>28_:.Spawn<Space>
n g`<CR> & <SNR>28_:.Spawn<CR>
n g'? & :<C-U>echo ":Spawn" dispatch#spawn_focus(v:count > 1 ? 0 : v:count ? line(".") : -1)<CR>
n g'! & <SNR>28_:.Spawn!
n g'<Space> & <SNR>28_:.Spawn<Space>
n g'<CR> & <SNR>28_:.Spawn<CR>
x gS * :<C-U>lua MiniSplitjoin.toggle({ region = MiniSplitjoin.get_visual_region() })<CR>
Toggle arguments
n gS * v:lua.MiniSplitjoin.operator("toggle") . " "
Toggle arguments
x gs * <Cmd>lua MiniOperators.sort('visual')<CR>
Sort selection
n gss ^gsg_
@@ -299,88 +319,104 @@ n g== g=_
Evaluate line
n g= * v:lua.MiniOperators.evaluate()
Evaluate operator
x gS * :<C-U>lua MiniSplitjoin.toggle({ region = MiniSplitjoin.get_visual_region() })<CR>
Toggle arguments
n gS * v:lua.MiniSplitjoin.operator("toggle") . " "
Toggle arguments
o gh * <Cmd>lua MiniDiff.textobject()<CR>
Hunk range textobject
x gH * ~/.local/share/nvim/lazy/mini.nvim/lua/mini/diff.lua
Reset hunks
n gH * ~/.local/share/nvim/lazy/mini.nvim/lua/mini/diff.lua
Reset hunks
x gh * ~/.local/share/nvim/lazy/mini.nvim/lua/mini/diff.lua
Apply hunks
n gh * ~/.local/share/nvim/lazy/mini.nvim/lua/mini/diff.lua
Apply hunks
x g/ * <Esc>/\%V
Search inside visual selection
n gV * "`[" . strpart(getregtype(), 0, 1) . "`]"
Visually select changed text
x gp * "+P
Paste from system clipboard
n gp * "+p
Paste from system clipboard
x gy * "+y
Copy to system clipboard
n gy * "+y
Copy to system clipboard
n go * v:lua.MiniBasics.put_empty_line(v:false)
Put empty line below
n gO * v:lua.MiniBasics.put_empty_line(v:true)
Put empty line above
o gc * <Cmd>lua MiniComment.textobject()<CR>
Comment textobject
n gcc * ~/.local/share/nvim/lazy/mini.comment/lua/mini/comment.lua
n gcc * ~/.local/share/nvim/lazy/mini.nvim/lua/mini/comment.lua
Comment line
x gc * ~/.local/share/nvim/lazy/mini.comment/lua/mini/comment.lua
x gc * ~/.local/share/nvim/lazy/mini.nvim/lua/mini/comment.lua
Comment selection
n gc * ~/.local/share/nvim/lazy/mini.comment/lua/mini/comment.lua
n gc * ~/.local/share/nvim/lazy/mini.nvim/lua/mini/comment.lua
Comment
x gx * <Cmd>lua MiniOperators.exchange('visual')<CR>
Exchange selection
n gx * v:lua.MiniOperators.exchange()
Exchange operator
o ix <Plug>(textobj-xmlattr-attr-i)
x ix <Plug>(textobj-xmlattr-attr-i)
o ii * <Cmd>lua MiniIndentscope.textobject(false)<CR>
Object scope
x ii * <Cmd>lua MiniIndentscope.textobject(false)<CR>
Object scope
x j * v:count == 0 ? 'gj' : 'j'
n j * v:count == 0 ? 'gj' : 'j'
Move down
x k * v:count == 0 ? 'gk' : 'k'
n k * v:count == 0 ? 'gk' : 'k'
Move up
n shn * ~/.local/share/nvim/lazy/mini.surround/lua/mini/surround.lua
n m? & :<C-U>echo ":Dispatch" dispatch#make_focus(v:count > 1 ? 0 : v:count ? line(".") : -1)<CR>
n m! & <SNR>28_:.Make!
n m<Space> & <SNR>28_:.Make<Space>
n m<CR> & <SNR>28_:.Make<CR>
n shn * ~/.local/share/nvim/lazy/mini.nvim/lua/mini/surround.lua
Highlight next surrounding
n sFn * ~/.local/share/nvim/lazy/mini.surround/lua/mini/surround.lua
n sFn * ~/.local/share/nvim/lazy/mini.nvim/lua/mini/surround.lua
Find next left surrounding
n sfn * ~/.local/share/nvim/lazy/mini.surround/lua/mini/surround.lua
n sfn * ~/.local/share/nvim/lazy/mini.nvim/lua/mini/surround.lua
Find next right surrounding
n srn * ~/.local/share/nvim/lazy/mini.surround/lua/mini/surround.lua
n srn * ~/.local/share/nvim/lazy/mini.nvim/lua/mini/surround.lua
Replace next surrounding
n sdn * ~/.local/share/nvim/lazy/mini.surround/lua/mini/surround.lua
n sdn * ~/.local/share/nvim/lazy/mini.nvim/lua/mini/surround.lua
Delete next surrounding
n shl * ~/.local/share/nvim/lazy/mini.surround/lua/mini/surround.lua
n shl * ~/.local/share/nvim/lazy/mini.nvim/lua/mini/surround.lua
Highlight previous surrounding
n sFl * ~/.local/share/nvim/lazy/mini.surround/lua/mini/surround.lua
n sFl * ~/.local/share/nvim/lazy/mini.nvim/lua/mini/surround.lua
Find previous left surrounding
n sfl * ~/.local/share/nvim/lazy/mini.surround/lua/mini/surround.lua
n sfl * ~/.local/share/nvim/lazy/mini.nvim/lua/mini/surround.lua
Find previous right surrounding
n srl * ~/.local/share/nvim/lazy/mini.surround/lua/mini/surround.lua
n srl * ~/.local/share/nvim/lazy/mini.nvim/lua/mini/surround.lua
Replace previous surrounding
n sdl * ~/.local/share/nvim/lazy/mini.surround/lua/mini/surround.lua
n sdl * ~/.local/share/nvim/lazy/mini.nvim/lua/mini/surround.lua
Delete previous surrounding
x sa * :<C-U>lua MiniSurround.add('visual')<CR>
Add surrounding to selection
n sn * ~/.local/share/nvim/lazy/mini.surround/lua/mini/surround.lua
n sn * ~/.local/share/nvim/lazy/mini.nvim/lua/mini/surround.lua
Update `MiniSurround.config.n_lines`
n sh * ~/.local/share/nvim/lazy/mini.surround/lua/mini/surround.lua
n sh * ~/.local/share/nvim/lazy/mini.nvim/lua/mini/surround.lua
Highlight surrounding
n sF * ~/.local/share/nvim/lazy/mini.surround/lua/mini/surround.lua
n sF * ~/.local/share/nvim/lazy/mini.nvim/lua/mini/surround.lua
Find left surrounding
n sf * ~/.local/share/nvim/lazy/mini.surround/lua/mini/surround.lua
n sf * ~/.local/share/nvim/lazy/mini.nvim/lua/mini/surround.lua
Find right surrounding
n sr * ~/.local/share/nvim/lazy/mini.surround/lua/mini/surround.lua
n sr * ~/.local/share/nvim/lazy/mini.nvim/lua/mini/surround.lua
Replace surrounding
n sd * ~/.local/share/nvim/lazy/mini.surround/lua/mini/surround.lua
n sd * ~/.local/share/nvim/lazy/mini.nvim/lua/mini/surround.lua
Delete surrounding
n sa * ~/.local/share/nvim/lazy/mini.surround/lua/mini/surround.lua
n sa * ~/.local/share/nvim/lazy/mini.nvim/lua/mini/surround.lua
Add surrounding
o t * ~/.local/share/nvim/lazy/mini.jump/lua/mini/jump.lua
Jump forward till
x t * <Cmd>lua MiniJump.smart_jump(false, true)<CR>
Jump forward till
n t * <Cmd>lua MiniJump.smart_jump(false, true)<CR>
Jump forward till
x zk * ~/.local/share/nvim/lazy/lazy.nvim/lua/lazy/core/handler/keys.lua
o zk * ~/.config/nvim/lua/keymaps.lua
Flash
n zk * ~/.local/share/nvim/lazy/lazy.nvim/lua/lazy/core/handler/keys.lua
x zk * ~/.config/nvim/lua/keymaps.lua
Flash
o zk * ~/.local/share/nvim/lazy/lazy.nvim/lua/lazy/core/handler/keys.lua
n zk * ~/.config/nvim/lua/keymaps.lua
Flash
n <C-W>= * <C-W>=
Equal Size Splits
n <C-W>+ * :resize +5<CR>
H Resize +
n <C-W>- * :resize -5<CR>
H Resize -
n <C-W>. * :vertical resize +10<CR>
V Resize +
n <C-W>, * :vertical resize -10<CR>
V Resize -
n <F1> * :FloatermToggle<CR>
Toggle Floaterm
v <C-J> * :m '>+1<CR>gv=gv
Move Block Down
n <C-J> * :m '>+1<CR>gv=gv
@@ -389,12 +425,24 @@ v <C-K> * :m '<-2<CR>gv=gv
Move Block Up
n <C-K> * :m '<-2<CR>gv=gv
Move Block Up
n <C-S> * :w!<CR>
Save
n <C-W>= * <C-W>=
Equal Size Splits
n <C-W>+ * :resize +10<CR>
H Resize +
n <C-W>- * :resize -10<CR>
H Resize -
n <C-W>. * :vertical resize +10<CR>
V Resize +
n <C-W>, * :vertical resize -10<CR>
V Resize -
n <Down> * :echo "Use j to move!!"<CR>
?
n <Up> * :echo "Use k to move!!"<CR>
?
n <Right> * :echo "Use l to move!!"<CR>
?
n <Left> * :echo "Use h to move!!"<CR>
?
x <Plug>(MatchitVisualTextObject) <Plug>(MatchitVisualMultiBackward)o<Plug>(MatchitVisualMultiForward)
o <Plug>(MatchitOperationMultiForward) * :<C-U>call matchit#MultiMatch("W", "o")<CR>
o <Plug>(MatchitOperationMultiBackward) * :<C-U>call matchit#MultiMatch("bW", "o")<CR>
@@ -408,23 +456,34 @@ x <Plug>(MatchitVisualBackward) * :<C-U>call matchit#Match_wrapper('',0,'v')<CR
x <Plug>(MatchitVisualForward) * :<C-U>call matchit#Match_wrapper('',1,'v')<CR>:if col("''") != col("$") | exe ":normal! m'" | endif<CR>gv``
n <Plug>(MatchitNormalBackward) * :<C-U>call matchit#Match_wrapper('',0,'n')<CR>
n <Plug>(MatchitNormalForward) * :<C-U>call matchit#Match_wrapper('',1,'n')<CR>
n <M-k> * <Cmd>lua MiniMove.move_line('up')<CR>
Move line up
n <M-j> * <Cmd>lua MiniMove.move_line('down')<CR>
Move line down
n <M-l> * <Cmd>lua MiniMove.move_line('right')<CR>
Move line right
n <M-h> * <Cmd>lua MiniMove.move_line('left')<CR>
Move line left
x <M-k> * <Cmd>lua MiniMove.move_selection('up')<CR>
Move up
x <M-j> * <Cmd>lua MiniMove.move_selection('down')<CR>
Move down
x <M-l> * <Cmd>lua MiniMove.move_selection('right')<CR>
Move right
x <M-h> * <Cmd>lua MiniMove.move_selection('left')<CR>
Move left
o <Plug>(textobj-xmlattr-attr-i) & <SNR>34_(save-cursor-pos):<C-U>call g:__textobj_xmlattr.do_by_pattern("select","attr-i","o")<CR>
v <Plug>(textobj-xmlattr-attr-i) & <SNR>34_(save-cursor-pos):<C-U>call g:__textobj_xmlattr.do_by_pattern("select","attr-i","v")<CR>
o <Plug>(textobj-xmlattr-attr-a) & <SNR>34_(save-cursor-pos):<C-U>call g:__textobj_xmlattr.do_by_pattern("select","attr-a","o")<CR>
v <Plug>(textobj-xmlattr-attr-a) & <SNR>34_(save-cursor-pos):<C-U>call g:__textobj_xmlattr.do_by_pattern("select","attr-a","v")<CR>
n <SNR>34_ * <SNR>34_
<SNR>34_(save-cursor-pos) * <SNR>34_save_cursor_pos()
n <SNR>28_:. & :<C-R>=getcmdline() =~ ',' ? "\0250" : ""<CR>
n <Plug>PlenaryTestFile * :lua require('plenary.test_harness').test_file(vim.fn.expand("%:p"))<CR>
s <Plug>luasnip-jump-prev * ~/.local/share/nvim/lazy/LuaSnip/plugin/luasnip.lua
LuaSnip: Jump to the previous node
s <Plug>luasnip-jump-next * ~/.local/share/nvim/lazy/LuaSnip/plugin/luasnip.lua
LuaSnip: Jump to the next node
s <Plug>luasnip-prev-choice * ~/.local/share/nvim/lazy/LuaSnip/plugin/luasnip.lua
LuaSnip: Change to the previous choice from the choiceNode
s <Plug>luasnip-next-choice * ~/.local/share/nvim/lazy/LuaSnip/plugin/luasnip.lua
LuaSnip: Change to the next choice from the choiceNode
s <Plug>luasnip-expand-snippet * ~/.local/share/nvim/lazy/LuaSnip/plugin/luasnip.lua
LuaSnip: Expand the current snippet
s <Plug>luasnip-expand-or-jump * ~/.local/share/nvim/lazy/LuaSnip/plugin/luasnip.lua
LuaSnip: Expand or jump in the current snippet
<Plug>luasnip-expand-repeat * ~/.local/share/nvim/lazy/LuaSnip/plugin/luasnip.lua
LuaSnip: Repeat last node expansion
n <Plug>luasnip-delete-check * ~/.local/share/nvim/lazy/LuaSnip/plugin/luasnip.lua
LuaSnip: Removes current snippet from jumplist
x <C-S> * <Esc><Cmd>silent! update | redraw<CR>
Save and go to Normal mode
n <C-S> * :w!<CR>
Save
n <C-W><C-D> <C-W>d
Show diagnostics under the cursor
n <C-W>d * vim/_defaults.lua
@@ -433,4 +492,4 @@ n <C-L> * :lua vim.lsp.buf.signature_help()<CR>
Signature
```
- Generated on Mon 9 Dec 2024 10:05:25 EET
- Generated on Tue 21 Jan 2025 15:24:13 EET

View File

@@ -2,17 +2,11 @@
Leader: `<ctrl><space>`
```
C-o Rotate through the panes
C-z Suspend the current client
Space Select next layout
# List all paste buffers
```txt
$ Rename current session
% Split window horizontally
& Kill current window
' Prompt for window index to select
( Switch to previous client
) Switch to next client
, Rename current window
- Delete the most recent paste buffer
. Move the current window
@@ -31,7 +25,6 @@ Leader: `<ctrl><space>`
; Move to the previously active pane
= Choose a paste buffer from a list
? List key bindings
D Choose and detach a client from a list
E Spread panes out evenly
L Switch to the last client
M Clear the marked pane
@@ -41,7 +34,6 @@ Leader: `<ctrl><space>`
f Search for a pane
i Display window information
m Toggle the marked pane
n Select the next window
o Select the next pane
q Display pane numbers
s Choose a session from a list
@@ -63,6 +55,8 @@ Leader: `<ctrl><space>`
M-3 Set the main-horizontal layout
M-4 Set the main-vertical layout
M-5 Select the tiled layout
M-6 Set the main-horizontal-mirrored layout
M-7 Set the main-vertical-mirrored layout
M-n Select the next window with an alert
M-o Rotate through the panes in reverse
M-p Select the previous window with an alert
@@ -70,6 +64,8 @@ Leader: `<ctrl><space>`
M-Down Resize the pane down by 5
M-Left Resize the pane left by 5
M-Right Resize the pane right by 5
C-o Rotate through the panes
C-z Suspend the current client
C-Up Resize the pane up
C-Down Resize the pane down
C-Left Resize the pane left

View File

@@ -277,4 +277,4 @@ Mouse: alt_screen
```
- Generated on Sat 10 Aug 2024 13:01:59 EEST
- Generated on Thu 2 Jan 2025 17:41:13 EET

View File

@@ -2,8 +2,6 @@
- include: 'tools/dotbot-defaults.yaml'
- shell:
- echo "Configuring air"
- brewfile:
- Brewfile
- link:
~/:
force: true

View File

@@ -1,5 +1,4 @@
#!/usr/bin/env bash
set -e
CONFIG="install.conf.yaml"
@@ -16,6 +15,7 @@ git submodule update --init --recursive "${DOTBOT_DIR}"
"${DOTBOT_BIN_PATH}" \
-d "${BASEDIR}" \
--plugin-dir=tools/dotbot-asdf \
--plugin-dir=tools/dotbot-brew \
--plugin-dir=tools/dotbot-include \
--plugin-dir=tools/dotbot-pip \
@@ -25,10 +25,11 @@ git submodule update --init --recursive "${DOTBOT_DIR}"
if [ "${DOTBOT_HOST}" != "" ]; then
DOTBOT_HOST_CONFIG="${BASEDIR}/hosts/${DOTBOT_HOST}/${CONFIG}"
echo "-> Trying if host config can be found: ${DOTBOT_HOST_CONFIG}"
[ -r "$DOTBOT_HOST_CONFIG" ] && [ -f "$DOTBOT_HOST_CONFIG" ] &&
echo "(!) Found $DOTBOT_HOST_CONFIG" &&
"$DOTBOT_BIN_PATH" \
[ -r "$DOTBOT_HOST_CONFIG" ] && [ -f "$DOTBOT_HOST_CONFIG" ] \
&& echo "(!) Found $DOTBOT_HOST_CONFIG" \
&& "$DOTBOT_BIN_PATH" \
-d "$BASEDIR" \
--plugin-dir=tools/dotbot-asdf \
--plugin-dir=tools/dotbot-brew \
--plugin-dir=tools/dotbot-include \
--plugin-dir=tools/dotbot-pip \

View File

@@ -1,5 +1,6 @@
---
- include: 'tools/dotbot-defaults.yaml'
- clean:
~/:
~/.config:
@@ -8,6 +9,7 @@
recursive: true
~/.ssh:
recursive: true
- create:
~/.cache:
~/.cache/git:
@@ -19,12 +21,14 @@
~/.local/share/gnupg:
mode: 0700
~/.local/state:
~/.local/state/tmux:
~/.local/state/zsh:
~/.ssh:
mode: 0700
~/.ssh/local.d:
mode: 0700
~/Code:
- link:
~/:
force: true
@@ -53,10 +57,54 @@
glob: true
mode: 0600
path: ssh/*
- shell:
- bash add-submodules.sh || true
- git submodule update --init --recursive --force
- asdf:
- plugin: 1password-cli
url: https://github.com/NeoHsu/asdf-1password-cli.git
- plugin: age
url: https://github.com/threkk/asdf-age.git
- plugin: direnv
url: https://github.com/asdf-community/asdf-direnv.git
- plugin: dotenv-linter
url: https://github.com/wesleimp/asdf-dotenv-linter.git
- plugin: editorconfig-checker
url: https://github.com/gabitchov/asdf-editorconfig-checker.git
- plugin: fd
url: https://gitlab.com/wt0f/asdf-fd.git
- plugin: github-cli
url: https://github.com/bartlomiejdanek/asdf-github-cli.git
- plugin: golang
url: https://github.com/asdf-community/asdf-golang.git
- plugin: hadolint
url: https://github.com/devlincashman/asdf-hadolint.git
- plugin: kubectl
url: https://github.com/asdf-community/asdf-kubectl.git
- plugin: pre-commit
url: https://github.com/jonathanmorley/asdf-pre-commit.git
- plugin: ripgrep
url: https://gitlab.com/wt0f/asdf-ripgrep.git
- plugin: rust
url: https://github.com/code-lever/asdf-rust.git
- plugin: shellcheck
url: https://github.com/luizm/asdf-shellcheck.git
- plugin: shfmt
url: https://github.com/luizm/asdf-shfmt.git
- plugin: terragrunt
url: https://github.com/ohmer/asdf-terragrunt.git
- plugin: tf-summarize
url: https://github.com/adamcrews/asdf-tf-summarize.git
- plugin: yamllint
url: https://github.com/ericcornelissen/asdf-yamllint.git
- plugin: yq
url: https://github.com/sudermanjr/asdf-yq.git
- shell:
- bash local/bin/dfm install all
- pipx:
file: tools/requirements-pipx.txt
stdout: true

View File

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

191
local/bin/a Executable file
View File

@@ -0,0 +1,191 @@
#!/usr/bin/env bash
# A script for encrypting and decrypting files or directories with age and SSH keys
VERSION="1.0.0"
# Default ENV values
KEYS_FILE="${AGE_KEYSFILE:-$HOME/.ssh/keys.txt}"
KEYS_SOURCE="${AGE_KEYSSOURCE:-https://github.com/ivuorinen.keys}"
LOG_FILE="${AGE_LOGFILE:-$HOME/.cache/a.log}"
VERBOSE=false
# Parse flags for verbosity
for arg in "$@"; do
if [[ "$arg" == "-v" || "$arg" == "--verbose" ]]; then
VERBOSE=true
break
fi
done
# Ensure log directory and file exist with correct permissions
prepare_log_file()
{
local log_dir
log_dir=$(dirname "$LOG_FILE")
# Create log directory if it does not exist
if [[ ! -d "$log_dir" ]]; then
mkdir -p "$log_dir"
fi
# Create log file if it does not exist
if [[ ! -f "$LOG_FILE" ]]; then
touch "$LOG_FILE"
fi
# Set permissions to 0600
chmod 0600 "$LOG_FILE"
}
prepare_log_file
# Logging function
log_message()
{
local message="$1"
echo "$(date +'%Y-%m-%d %H:%M:%S') - $message" >> "$LOG_FILE"
# Print to user if verbose flag is set
if [[ "$VERBOSE" == true ]]; then
echo "$message"
fi
}
# Function to print usage
print_help()
{
cat << EOF
Usage: a [command] [file_or_directory] [options]
Commands:
e, enc, encrypt Encrypt the specified file or directory
d, dec, decrypt Decrypt the specified file or directory
help, --help Show this help message
version, --version Show version information
Options:
-v, --verbose Print log messages to console in addition to writing to log file
Environment Variables:
AGE_KEYSFILE Path to the SSH keys file (default: $HOME/.ssh/keys.txt)
AGE_KEYSSOURCE URL to fetch SSH keys if keys file does not exist
AGE_LOGFILE Path to the log file (default: $HOME/.cache/a.log)
Examples:
Encrypt a file:
a e file.txt
Encrypt a directory:
a e /path/to/directory
Decrypt a file:
a d file.txt.age
Specify a custom keys file:
AGE_KEYSFILE=/path/to/keys.txt a e file.txt
Specify a custom keys source and log file:
AGE_KEYSSOURCE=https://example.com/keys.txt AGE_LOGFILE=/tmp/a.log a d file.txt.age
EOF
}
# Function to print version
print_version()
{
echo "a version $VERSION"
echo "Created by Ismo Vuorinen <https://github.com/ivuorinen>"
}
# Function to fetch keys if missing
fetch_keys_if_missing()
{
if [[ ! -f "$KEYS_FILE" ]]; then
log_message "Keys file '$KEYS_FILE' not found. Attempting to fetch from $KEYS_SOURCE..."
mkdir -p "$(dirname "$KEYS_FILE")"
curl -s "$KEYS_SOURCE" -o "$KEYS_FILE"
if [[ $? -ne 0 || ! -s "$KEYS_FILE" ]]; then
log_message "Error: Failed to fetch keys from $KEYS_SOURCE"
exit 1
fi
chmod 0400 "$KEYS_FILE"
log_message "Keys file fetched and permissions set to 0400."
fi
}
# Function to encrypt files or directories
encrypt_file_or_directory()
{
local file="$1"
if [[ -d "$file" ]]; then
for f in "$file"/*; do
encrypt_file_or_directory "$f"
done
elif [[ -f "$file" ]]; then
fetch_keys_if_missing
local output_file="${file}.age"
age -R "$KEYS_FILE" "$file" > "$output_file"
if [[ $? -eq 0 ]]; then
log_message "File encrypted successfully: $output_file"
else
log_message "Error: Failed to encrypt file '$file'."
exit 1
fi
fi
}
# Function to decrypt files or directories
decrypt_file_or_directory()
{
local file="$1"
if [[ -d "$file" ]]; then
for f in "$file"/*.age; do
decrypt_file_or_directory "$f"
done
elif [[ -f "$file" ]]; then
fetch_keys_if_missing
local output_file="${file%.age}"
age -d -i "$KEYS_FILE" "$file" > "$output_file"
if [[ $? -eq 0 ]]; then
log_message "File decrypted successfully: $output_file"
else
log_message "Error: Failed to decrypt file '$file'."
exit 1
fi
fi
}
# Main logic
case "$1" in
e | enc | encrypt)
if [[ $# -lt 2 ]]; then
log_message "Error: No file or directory specified for encryption."
print_help
exit 1
fi
encrypt_file_or_directory "$2"
;;
d | dec | decrypt)
if [[ $# -lt 2 ]]; then
log_message "Error: No file or directory specified for decryption."
print_help
exit 1
fi
decrypt_file_or_directory "$2"
;;
help | --help)
print_help
;;
version | --version)
print_version
;;
*)
log_message "Error: Unknown command '$1'"
print_help
exit 1
;;
esac
# vim: ft=bash:syn=sh:ts=2:sw=2:et:ai:nowrap

60
local/bin/ad Executable file
View File

@@ -0,0 +1,60 @@
#!/usr/bin/env bash
# age decrypt file with github keys
# Use ENV or default values for keys file and source
KEYS_FILE="${AGE_KEYSFILE:-$HOME/.ssh/keys.txt}"
KEYS_SOURCE="${AGE_KEYSSOURCE:-https://github.com/ivuorinen.keys}"
# Check for required commands
if ! command -v age &> /dev/null; then
echo "Error: age is not installed. Please install it to continue."
exit 1
fi
if ! command -v curl &> /dev/null; then
echo "Error: curl is not installed. Please install it to continue."
exit 1
fi
# Ensure a file is provided
if [[ $# -lt 1 ]]; then
echo "Usage: $0 <file-to-decrypt>"
exit 1
fi
FILE="$1"
if [[ ! -f "$FILE" ]]; then
echo "Error: File '$FILE' does not exist."
exit 1
fi
# Check if keys file exists, otherwise fetch it
if [[ ! -f "$KEYS_FILE" ]]; then
echo "Keys file '$KEYS_FILE' not found. Attempting to fetch from $KEYS_SOURCE..."
# Create the directory if it doesn't exist
mkdir -p "$(dirname "$KEYS_FILE")"
# Fetch the keys and save to the file
curl -s "$KEYS_SOURCE" -o "$KEYS_FILE"
if [[ $? -ne 0 || ! -s "$KEYS_FILE" ]]; then
echo "Error: Failed to fetch keys from $KEYS_SOURCE"
exit 1
fi
# Set permissions to 0400
chmod 0400 "$KEYS_FILE"
echo "Keys file fetched and permissions set to 0400."
fi
# Decrypt the file
OUTPUT_FILE="${FILE%.age}"
age -d -i "$KEYS_FILE" "$FILE" > "$OUTPUT_FILE"
if [[ $? -eq 0 ]]; then
echo "File decrypted successfully: $OUTPUT_FILE"
else
echo "Error: Failed to decrypt file."
exit 1
fi

61
local/bin/ae Executable file
View File

@@ -0,0 +1,61 @@
#!/usr/bin/env bash
# age encrypt file with github keys
# Use ENV or default values for keys file and source
KEYS_FILE="${AGE_KEYSFILE:-$HOME/.ssh/keys.txt}"
KEYS_SOURCE="${AGE_KEYSSOURCE:-https://github.com/ivuorinen.keys}"
# Check for required commands
if ! command -v age &> /dev/null; then
echo "Error: age is not installed. Please install it to continue."
exit 1
fi
if ! command -v curl &> /dev/null; then
echo "Error: curl is not installed. Please install it to continue."
exit 1
fi
# Ensure a file is provided
# shellcheck disable=SC2181
if [[ $# -lt 1 ]]; then
echo "Usage: $0 <file-to-encrypt>"
exit 1
fi
FILE="$1"
if [[ ! -f "$FILE" ]]; then
echo "Error: File '$FILE' does not exist."
exit 1
fi
# Check if keys file exists, otherwise fetch it
if [[ ! -f "$KEYS_FILE" ]]; then
echo "Keys file '$KEYS_FILE' not found. Attempting to fetch from $KEYS_SOURCE..."
# Create the directory if it doesn't exist
mkdir -p "$(dirname "$KEYS_FILE")"
# Fetch the keys and save to the file
curl -s "$KEYS_SOURCE" -o "$KEYS_FILE"
if [[ $? -ne 0 || ! -s "$KEYS_FILE" ]]; then
echo "Error: Failed to fetch keys from $KEYS_SOURCE"
exit 1
fi
# Set permissions to 0400
chmod 0400 "$KEYS_FILE"
echo "Keys file fetched and permissions set to 0400."
fi
# Encrypt the file
OUTPUT_FILE="${FILE}.age"
age -R "$KEYS_FILE" "$FILE" > "$OUTPUT_FILE"
if [[ $? -eq 0 ]]; then
echo "File encrypted successfully: $OUTPUT_FILE"
else
echo "Error: Failed to encrypt file."
exit 1
fi

View File

@@ -4,6 +4,7 @@
# (c) Ismo Vuorinen <https://github.com/ivuorinen> 2022
# Licensed under MIT, see LICENSE
#
# vim: ft=bash ts=2 sw=2 et
# shellcheck source-path=$HOME/.dotfiles/local/bin
#
# Helper variables, override with ENVs like `VERBOSE=1 dfm help`
@@ -14,109 +15,25 @@
SCRIPT=$(basename "$0")
if ! declare -f msg > /dev/null; then
# Function to print messages if VERBOSE is enabled
# $1 - message (string)
msg()
{
[ "$VERBOSE" -eq 1 ] && echo "$1"
return 0
}
fi
if ! declare -f msg_err > /dev/null; then
# Function to print error messages and exit
# $1 - error message (string)
msg_err()
{
# shellcheck disable=SC2317
echo "(!) ERROR: $1" >&2
# shellcheck disable=SC2317
exit 1
}
fi
if ! declare -f msg_done > /dev/null; then
# Function to print done message
# $1 - message (string)
msg_done()
{
# shellcheck disable=SC2317
echo "✓ $1"
# shellcheck disable=SC2317
return 0
}
fi
if ! declare -f array_diff > /dev/null; then
# Function to compare two arrays and return the difference
# Example: array_diff DIFFERENCE ARRAY1 ARRAY2
# $1 - variable to store the difference
# $2 - first array
# $3 - second array
# Output to $1 the difference between $2 and $3
# Source: https://stackoverflow.com/a/42399479/594940
array_diff()
{
# shellcheck disable=SC1083,SC2086
eval local ARR1=\(\"\${$2[@]}\"\)
# shellcheck disable=SC1083,SC2086
eval local ARR2=\(\"\${$3[@]}\"\)
local IFS=$'\n'
mapfile -t "$1" < <(comm -23 <(echo "${ARR1[*]}" | sort) <(echo "${ARR2[*]}" | sort))
}
fi
# Loads configs for better installation experience
source "$DOTFILES/config/shared.sh"
source "${DOTFILES}/local/bin/msgr"
# -- Menu builder -- #
menu_section()
# Menu builder
menu_builder()
{
LINE=$(printf '%-18s [ %-15s ]\n' "$1" "$2")
echo -e " $(__log_marker) $LINE"
}
menu_item()
{
LINE=$(printf '%-15s %-30s\n' "$1" "$2")
echo -e "$(__log_indent)$(__log_marker) $LINE"
}
local title=$1
local commands=("${@:2}")
local width=60
# Takes a bash array ("cow:moo", "dinosaur:roar") and loops
# through the keys to build menu section listing.
menu_usage_header()
{
MENU_CMD="$1"
shift
MENU_ARRAY=("$@")
printf "\n%s\n" "$(printf '%.s─' $(seq 1 $width))"
printf "%-${width}s\n" " $title"
printf "%s\n" "$(printf '%.s─' $(seq 1 $width))"
KEYS=""
for item in "${MENU_ARRAY[@]}"; do
CMD=$(echo "${item}" | awk -F ":" '{print $1}')
KEYS+="${CMD} | "
done
# "???" removes 3 last characters, being " | " from the end
menu_section "$MENU_CMD" "${KEYS%???}"
}
# Takes the usage command "$0 dotfiles" and a
# bash array ("cow:moo" "dinosaur:roar") and loops
# through in building a menu for dfm command usage listing.
menu_usage()
{
MENU_CMD="$1"
shift
MENU_ARRAY=("$@")
msg "$MENU_CMD"
for item in "${MENU_ARRAY[@]}"; do
CMD=$(echo "${item}" | awk -F ":" '{print $1}')
DESC=$(echo "${item}" | awk -F ":" '{print $2}')
menu_item "$CMD" "$DESC"
for cmd in "${commands[@]}"; do
local name=${cmd%%:*}
local desc=${cmd#*:}
printf " %-20s %s\n" "$name" "$desc"
done
}
@@ -126,23 +43,19 @@ section_install()
MENU=(
"all:Installs everything in the correct order"
"asdf:Install asdf plugins"
"cargo:Install rust/cargo packages"
"cheat-databases:Install cheat external cheatsheet databases"
"composer:Install composer"
"dotenv:Install dotenv-linter"
"fonts:Install programming fonts"
"gh:Install GitHub CLI Extensions"
"go:Install Go Packages"
"imagick:Install ImageMagick CLI"
"starship:Install starship.rs"
"macos:Setup nice macOS defaults"
"neofetch:Install neofetch"
"nvm:Install Node Version Manager (nvm)"
"nvm-latest:Install latest lts node using nvm"
"npm:Install NPM Packages"
"npm-packages:Install NPM Packages"
"ntfy:Install ntfy"
"ohmybash:Install oh-my-bash"
"pip:Install pip/python packages"
"nvm-latest:Install latest lts node using nvm"
"nvm:Install Node Version Manager (nvm)"
"z:Install z"
)
@@ -152,124 +65,111 @@ section_install()
$0 install macos
$0 install fonts
$0 brew install
#$0 install ohmyposh
$0 install asdf
$0 install composer
$0 install fzf
#$0 install go
$0 install cheat-databases
#$0 install imagick
$0 install nvm
$0 install npm
# $0 install ntfy
$0 install npm-packages
$0 install z
msgr msg "Reloading configurations again..."
source "$DOTFILES/config/shared.sh"
msgr yay "All done!"
;;
asdf)
msg "Installing asdf..."
bash "$DOTFILES/scripts/install-asdf.sh both" \
&& msg_yay "asdf installed!"
msgr run "Installing asdf..."
$0 asdf plugins-install \
&& msgr yay "asdf plugins installed!"
;;
cargo)
msg "Installing cargo packages..."
msgr run "Installing cargo packages..."
bash "$DOTFILES/scripts/install-cargo-packages.sh" \
&& msg_yay "cargo packages installed!"
&& msgr yay "cargo packages installed!"
;;
cheat-databases)
msg "Installing cheat databases..."
msgr run "Installing cheat databases..."
for database in "$DOTFILES"/scripts/install-cheat-*; do
bash "$database" \
&& msg_yay "Cheat: $database run"
&& msgr run_done "Cheat: $database run"
done
;;
composer)
msg "Installing composer..."
msgr run "Installing composer..."
bash "$DOTFILES/scripts/install-composer.sh" \
&& msg_yay "composer installed!"
&& msgr run_done "composer installed!"
;;
fonts)
msg "Installing fonts..."
msgr run "Installing fonts..."
bash "$DOTFILES/scripts/install-fonts.sh" \
&& msg_yay "Installed fonts!"
;;
fzf)
msg "Installing fzf..."
bash "$DOTFILES/scripts/install-fzf.sh" \
&& msg_yay "fzf installed!"
&& msgr yay "Installed fonts!"
;;
gh)
msg "Installing GitHub CLI Extensions..."
msgr run "Installing GitHub CLI Extensions..."
bash "$DOTFILES/scripts/install-gh-extensions.sh" \
&& msg_yay "github cli extensions installed!"
&& msgr yay "github cli extensions installed!"
;;
go)
msg "Installing Go Packages..."
msgr run "Installing Go Packages..."
bash "$DOTFILES/scripts/install-go-packages.sh" \
&& msg_yay "go packages installed!"
&& msgr yay "go packages installed!"
;;
imagick)
msg "Installing ImageMagick CLI..."
msgr run "Downloading and installing ImageMagick CLI..."
curl -L https://imagemagick.org/archive/binaries/magick > "$XDG_BIN_HOME/magick" \
&& chmod +x "$XDG_BIN_HOME/magick" \
&& msg_yay "imagick installed!"
&& msgr yay "imagick downloaded and installed!"
;;
macos)
msg "Setting up macOS defaults..."
bash "$DOTFILES/scripts/set-macos-defaults.sh" \
&& msg_yay "Brewfile defined apps has been installed!"
;;
neofetch)
msg "Installing neofetch..."
bash "$DOTFILES/scripts/install-neofetch.sh" \
&& msg_yay "neofetch installed!"
msgr run "Setting up macOS defaults..."
bash "$DOTFILES/scripts/install-macos-defaults.sh" \
&& msgr yay "macOS defaults set!"
;;
nvm)
msg "Installing nvm..."
msgr run "Installing nvm..."
local NVM_VERSION
NVM_VERSION=$(x-gh-get-latest-version nvm-sh/nvm)
msg "Latest nvm version: $NVM_VERSION"
NVM_INSTALL="https://raw.githubusercontent.com/nvm-sh/nvm/${NVM_VERSION}/install.sh"
NVM_CURL="curl -o- \"$NVM_INSTALL\" | bash"
msgr ok "Latest nvm version: $NVM_VERSION"
local NVM_INSTALL="https://raw.githubusercontent.com/nvm-sh/nvm/${NVM_VERSION}/install.sh"
local NVM_CURL="curl -o- \"$NVM_INSTALL\" | bash"
PROFILE=/dev/null bash -c "$NVM_CURL"
$0 install nvm-latest
msg_yay "nvm installed!"
msgr yay "nvm installed!"
;;
nvm-latest)
msg "Installing latest lts node..."
msgr run "Installing latest lts node..."
if [ -n "$NVM_DIR" ]; then
[ -s "$NVM_DIR/nvm.sh" ] && \. "$NVM_DIR/nvm.sh"
fi
nvm install --lts --latest-npm --default
git checkout "$DOTFILES/base/zshrc"
git checkout "$DOTFILES/base/bashrc"
msg_yay "latest lts node installed!"
msgr yay "latest lts node installed!"
;;
npm)
msg "NPM Packages install started..."
npm-packages)
msgr run "NPM Packages install started..."
bash "$DOTFILES/scripts/install-npm-packages.sh" \
&& msg_yay "NPM Packages have been installed!"
;;
ntfy)
msg "ntfy install started..."
bash "$DOTFILES/scripts/install-ntfy.sh" \
&& msg_yay "ntfy installed!"
;;
ohmyposh)
msg "oh-my-posh install started..."
bash "$DOTFILES/scripts/install-ohmyposh.sh" \
&& msg_yay "oh-my-posh installed!"
;;
pip)
msg "pip install started..."
bash "$DOTFILES/scripts/install-pip-packages.sh"
&& msgr yay "NPM Packages have been installed!"
;;
z)
msg "Installing z..."
msgr run "Installing z..."
bash "$DOTFILES/scripts/install-z.sh" \
&& msg_yay "z has been installed!"
&& msgr yay "z has been installed!"
;;
*) menu_usage "$USAGE_PREFIX" "${MENU[@]}" ;;
*) menu_builder "$USAGE_PREFIX" "${MENU[@]}" ;;
esac
}
@@ -290,12 +190,14 @@ section_brew()
x-have brew && {
case "$1" in
install)
brew bundle install --file="$BREWFILE" --force --quiet && msg_yay "Done!"
brew bundle install --file="$BREWFILE" --force --quiet && msgr yay "Done!"
;;
update)
brew update && brew outdated && brew upgrade && brew cleanup
msg_yay "Done!"
msgr yay "Done!"
;;
updatebundle)
# Updates .dotfiles/homebrew/Brewfile with descriptions
brew bundle dump \
@@ -305,11 +207,13 @@ section_brew()
--tap \
--formula \
--cask \
--describe && msg_yay "Done!"
--describe && msgr yay "Done!"
;;
leaves)
brew leaves --installed-on-request
;;
untracked)
declare -a BREW_LIST_ALL
while IFS= read -r line; do
@@ -342,7 +246,7 @@ section_brew()
# If there are no untracked packages, exit
if [ ${#BREW_LIST_UNTRACKED[@]} -eq 0 ]; then
msg_yay "No untracked packages found!"
msgr yay "No untracked packages found!"
exit 0
fi
@@ -351,64 +255,176 @@ section_brew()
echo " $f"
done
;;
clean)
brew bundle cleanup --file="$BREWFILE" && msg_yay "Done!"
;;
autoupdate)
brew autoupdate delete
brew autoupdate start 43200 --upgrade --cleanup --immediate
;;
*)
menu_usage "$USAGE_PREFIX" "${MENU[@]}"
;;
clean) brew bundle cleanup --file="$BREWFILE" && msgr yay "Done!" ;;
*) menu_builder "$USAGE_PREFIX" "${MENU[@]}" ;;
esac
}
! x-have brew && menu_section "$USAGE_PREFIX" "brew not available on this system"
! x-have brew && menu_builder "$USAGE_PREFIX" "brew not available on this system"
}
section_asdf()
{
USAGE_PREFIX="$SCRIPT asdf <command>"
MENU=(
"install:Install asdf"
"current:Show asdf current versions"
"global:Show asdf global versions"
"installed:Show asdf installed versions"
"local:Show asdf local versions"
"plugins-update:Update all asdf plugins"
"plugins-install:Install plugins from configuration"
"plugins-remove:Remove installed plugins"
"reset:Reset asdf plugins"
"fix-tool-versions:Remove uninstalled plugins from .tool-versions"
"versions:Show asdf versions"
"where:Show asdf where"
"which:Show asdf which"
)
case "$1" in
install)
msg "Installing asdf..."
bash "$DOTFILES/scripts/install-asdf.sh both" \
&& msg_yay "asdf installed!"
plugins-update)
msgr run "Updating all asdf plugins"
asdf plugin update --all
msgr run_done "Updated all plugins"
;;
current)
asdf current
plugins-install)
msgr run "Installing plugins from configuration"
# First install direnv if it's not installed
if ! asdf plugin list | grep -q "^direnv$"; then
msgr nested "Installing direnv plugin"
asdf plugin add direnv https://github.com/asdf-community/asdf-direnv.git
# Install latest direnv
local latest_direnv
latest_direnv=$(asdf latest direnv)
asdf install direnv "$latest_direnv"
asdf global direnv "$latest_direnv"
fi
# Check that all plugins are installed
local installed_plugins
installed_plugins=$(asdf plugin list)
while IFS= read -r line; do
# Skip empty lines and comments
[[ -z $line || $line =~ ^# ]] && continue
local plugin
plugin=$(echo "$line" | awk '{print $1}')
# Skip direnv, it's already installed
[[ $plugin == "direnv" ]] && continue
if ! echo "$installed_plugins" | grep -q "^${plugin}$"; then
msgr nested "Installing $plugin plugin"
asdf plugin add "$plugin"
fi
done < "$DOTFILES/base/tool-versions"
msgr run_done "All plugins installed"
;;
global)
asdf global
plugins-remove)
msgr run "Remove installed plugins"
local installed_plugins
installed_plugins=$(asdf plugin list | grep -v "^direnv$")
for plugin in $installed_plugins; do
msgr nested "Removing $plugin"
asdf plugin remove "$plugin"
done
msgr run_done "Remove plugins done!"
;;
installed)
asdf list
reset)
msgr run "Resetting asdf environment"
$0 asdf plugins-remove
$0 asdf plugins-install
asdf reshim
msgr yay "Reset asdf plugins done!"
;;
local)
asdf local
fix-tool-versions)
local tool_versions_file="$DOTFILES/base/tool-versions"
local temp_file
temp_file=$(mktemp)
msgr run "Fixing tool-versions file"
# Check that .tool-versions file exists
if [[ ! -f $tool_versions_file ]]; then
msgr error "tool-versions file not found: $tool_versions_file"
rm -f "$temp_file"
return 1
fi
# Check that asdf can be found in the path
if ! command -v asdf > /dev/null; then
msgr error "asdf not found"
rm -f "$temp_file"
return 1
fi
# Read installed plugins
msgr nested "Reading installed plugins"
local installed_plugins
installed_plugins=$(asdf plugin list | sort)
# Compare .tool-versions and installed plugins,
# remove unknown plugins from .tool-versions
msgr nested "Updating tool-versions file"
while IFS= read -r line; do
# Keep comments and empty lines
if [[ -z $line || $line =~ ^[[:space:]]*# ]]; then
echo "$line" >> "$temp_file"
continue
fi
local plugin
plugin=$(echo "$line" | awk '{print $1}')
if echo "$installed_plugins" | grep -q "^${plugin}$"; then
echo "$line" >> "$temp_file"
else
msgr nested "Removing $plugin - not installed"
fi
done < "$tool_versions_file"
# Check that the temp file is valid
if [[ ! -s $temp_file ]] || ! grep -v '^[[:space:]]*#' "$temp_file" | grep -q .; then
msgr error "Generated file is empty or contains only comments, keeping original"
rm -f "$temp_file"
return 1
fi
# Backup the original .tool-versions
cp "$tool_versions_file" "${tool_versions_file}.bak"
# Overwrite .tool-versions with the generated file
mv "$temp_file" "$tool_versions_file"
msgr run_done "Updated $tool_versions_file"
msgr nested "Backup saved as ${tool_versions_file}.bak"
return 0
;;
versions)
asdf list all
;;
where)
asdf where
;;
which)
asdf which
;;
*) menu_usage "$USAGE_PREFIX" "${MENU[@]}" ;;
current) asdf current ;;
global) asdf global ;;
installed) asdf list ;;
versions) asdf list all ;;
where) asdf where ;;
which) asdf which ;;
*) menu_builder "$USAGE_PREFIX" "${MENU[@]}" ;;
esac
}
@@ -416,12 +432,12 @@ section_helpers()
{
USAGE_PREFIX="$SCRIPT helpers <command>"
MENU=(
"aliases:<shell> (bash, zsh) Show aliases for bash or zsh"
"aliases:<shell> (bash, zsh) Show aliases"
"colors:Show colors"
"env:Show environment variables"
"functions:Show functions"
"aerospace:Show aerospace keybindings"
"nvim:Show nvim keybindings"
# shellcheck disable=SC2016
'path:Show $PATH dir by dir'
"tmux:Show tmux keybindings"
"wezterm:Show wezterm keybindings"
@@ -437,6 +453,7 @@ section_helpers()
# shellcheck disable=2001
for i in $(echo "$PATH" | sed 's/:/ /g'); do echo "$i"; done
;;
aliases)
case "$SECTION" in
"zsh")
@@ -450,6 +467,7 @@ section_helpers()
;;
esac
;;
"colors")
max=255
start=0
@@ -473,33 +491,88 @@ section_helpers()
printf "\n"
start=$((start + 10))
done
;;
;;
"env")
env | sort
;;
"functions")
declare -F
;;
"nvim")
cat "$DOTFILES/docs/nvim-keybindings.md"
;;
"tmux")
cat "$DOTFILES/docs/tmux-keybindings.md"
;;
"wezterm")
cat "$DOTFILES/docs/wezterm-keybindings.md"
;;
*) menu_usage "$USAGE_PREFIX" "${MENU[@]}" ;;
"env") env | sort ;;
"functions") declare -F ;;
"aerospace") cat "$DOTFILES/docs/aerospace-keybindings.md" ;;
"nvim") cat "$DOTFILES/docs/nvim-keybindings.md" ;;
"tmux") cat "$DOTFILES/docs/tmux-keybindings.md" ;;
"wezterm") cat "$DOTFILES/docs/wezterm-keybindings.md" ;;
*) menu_builder "$USAGE_PREFIX" "${MENU[@]}" ;;
esac
}
section_apt()
{
USAGE_PREFIX="$SCRIPT apt <command>"
MENU=(
"upkeep:Run update, upgrade, autoremove and clean"
'install:Install packages from $DOTFILES/tools/apt.txt'
"update:Update apt packages"
"upgrade:Upgrade apt packages"
"autoremove:Remove unused apt packages"
"clean:Clean apt cache"
)
x-have apt && {
case "$1" in
upkeep)
sudo apt update \
&& sudo apt upgrade -y \
&& sudo apt autoremove -y \
&& sudo apt clean
;;
install)
# if apt.txt is not found, exit
[ ! -f "$DOTFILES/tools/apt.txt" ] && msgr err "apt.txt not found" && exit 0
# Load apt.txt, remove comments (even if trailing comment) and empty lines.
#
# Ignoring "Quote this to prevent word splitting."
# shellcheck disable=SC2046
sudo apt install \
-y $(
grep -vE '^\s*#' "$DOTFILES/tools/apt.txt" \
| sed -e 's/#.*//' \
| tr '\n' ' '
)
# If there's a apt.txt file under hosts/$hostname/apt.txt,
# run install on those lines too.
HOSTNAME=$(hostname -s)
HOST_APT="$DOTFILES/hosts/$HOSTNAME/apt.txt"
[[ -f $HOST_APT ]] && {
# shellcheck disable=SC2046
sudo apt install -y $(
grep -vE '^\s*#' "$HOST_APT" \
| sed -e 's/#.*//' \
| tr '\n' ' '
)
}
# Try this for an alternative way to install packages
# xargs -a <(awk '! /^ *(#|$)/' "$packagelist") -r -- sudo apt-get install -y
;;
update) sudo apt update ;;
upgrade) sudo apt upgrade -y ;;
autoremove) sudo apt autoremove -y ;;
clean) sudo apt clean ;;
*) menu_builder "$USAGE_PREFIX" "${MENU[@]}" ;;
esac
}
! x-have apt && menu_builder "$USAGE_PREFIX" "apt not available on this system"
}
section_docs()
{
USAGE_PREFIX="$SCRIPT docs <command>"
MENU=(
"all:Update all keybindings documentations"
"aerospace:Update aerospace keybindings documentation"
"tmux:Update tmux keybindings documentation"
"nvim:Update nvim keybindings documentation"
"wezterm:Update wezterm keybindings documentation"
@@ -507,14 +580,16 @@ section_docs()
case "$1" in
all)
$0 docs aerospace
$0 docs tmux
$0 docs nvim
$0 docs wezterm
;;
aerospace) bash "$DOTFILES/scripts/create-aerospace-keymaps.php" ;;
tmux) bash "$DOTFILES/local/bin/x-dfm-docs-xterm-keybindings" ;;
nvim) bash "$DOTFILES/scripts/create-nvim-keymaps.sh" ;;
wezterm) bash "$DOTFILES/scripts/create-wezterm-keymaps.sh" ;;
*) menu_usage "$USAGE_PREFIX" "${MENU[@]}" ;;
*) menu_builder "$USAGE_PREFIX" "${MENU[@]}" ;;
esac
}
@@ -532,37 +607,42 @@ section_dotfiles()
case "$1" in
fmt)
msg_ok "Running all formatters"
msgr run "Running all formatters"
$0 dotfiles yamlfmt
$0 dotfiles shfmt
msg_done "...done!"
msgr run_done "...done!"
;;
reset_all)
msg_ok "Running all reset commands"
msgr ok "Running all reset commands"
$0 dotfiles reset_nvim
;;
reset_nvim)
msgr run "Cleaning nvim state, cache and config"
rm -rf \
~/.local/share/nvim \
~/.local/state/nvim \
~/.cache/nvim \
~/.config/nvim
msg_ok "Deleted old nvim files (share, state and cache + config)"
msgr ok "Deleted old nvim files (share, state and cache + config)"
ln -s "$DOTFILES/config/nvim" ~/.config/nvim
msg_ok "Linked nvim and astronvim"
msgr ok "Linked nvim and astronvim"
x-have npm && $0 install npm
msg_ok "Installed packages"
msg_done "nvim reset!"
msgr ok "Installed packages"
msgr run_done "nvim reset!"
;;
yamlfmt)
# format yaml files
x-have yamlfmt && yamlfmt -conf "$DOTFILES/.yamlfmt"
! x-have yamlfmt && msg_err "yamlfmt not found"
! x-have yamlfmt && msgr err "yamlfmt not found"
;;
shfmt)
# If system doesn't have fd or shfmt installed, exit
! x-have fd && msg_err "fd not found, install with asdf"
! x-have shfmt && msg_err "shfmt not found, install with asdf"
! x-have fd && msgr err "fd not found, install it to continue"
! x-have shfmt && msgr err "shfmt not found, install it to continue"
# Format shell scripts according to following rules.
fd --full-path "$DOTFILES" -tx \
--hidden \
@@ -573,9 +653,10 @@ section_dotfiles()
--func-next-line --list --write \
--indent 2 --case-indent --space-redirects \
--binary-next-line {} \;
msg_yay "dotfiles have been shfmt formatted!"
msgr yay "dotfiles have been shfmt formatted!"
;;
*) menu_usage "$USAGE_PREFIX" "${MENU[@]}" ;;
*) menu_builder "$USAGE_PREFIX" "${MENU[@]}" ;;
esac
}
@@ -595,11 +676,58 @@ section_check()
[[ $2 == "" ]] && echo "$X_ARCH" && exit 0
[[ $X_ARCH == "$2" ]] && exit 0 || exit 1
;;
h | host | hostname)
[[ $2 == "" ]] && echo "$X_HOSTNAME" && exit 0
[[ $X_HOSTNAME == "$2" ]] && exit 0 || exit 1
;;
*) menu_usage "$USAGE_PREFIX" "${MENU[@]}" ;;
*) menu_builder "$USAGE_PREFIX" "${MENU[@]}" ;;
esac
}
section_scripts()
{
USAGE_PREFIX="$SCRIPT scripts <command>"
# Get description from a file
get_script_description()
{
local file
local desc
file="$1"
desc=$(sed -n '/@description/s/.*@description *\(.*\)/\1/p' "$file" | head -1)
echo "${desc:-No description available}"
}
# Collect scripts and their descriptions
declare -A SCRIPT_MENU
for script in "$DOTFILES/scripts/install-"*.sh; do
if [ -f "$script" ]; then
name=$(basename "$script" .sh | sed 's/install-//')
desc=$(get_script_description "$script")
SCRIPT_MENU[$name]="$desc"
fi
done
case "$1" in
"")
# Show the menu
local menu_items=()
for name in "${!SCRIPT_MENU[@]}"; do
menu_items+=("$name:${SCRIPT_MENU[$name]}")
done
menu_builder "$USAGE_PREFIX" "${menu_items[@]}"
;;
*)
# Run the chosen script
script_path="$DOTFILES/scripts/install-$1.sh"
if [ -f "$script_path" ]; then
bash "$script_path"
else
msgr err "Script not found: $1"
fi
;;
esac
}
@@ -609,7 +737,7 @@ section_tests()
USAGE_PREFIX="$SCRIPT tests <command>"
MENU=(
"msg:List all log functions from shared.sh"
"msgr:List all available msgr message types"
"params:List all parameters"
)
@@ -621,33 +749,35 @@ section_tests()
done
;;
msg)
msg "msg"
msg_done "msg_done"
msg_done_suffix "msg_done_suffix"
msg_err "msg_err"
msg_nested "msg_nested"
msg_nested_done "msg_nested_done"
msg_ok "msg_ok"
msg_prompt "msg_prompt"
msg_prompt_done "msg_prompt_done"
msg_run "msg_run" "second_param"
msg_run_done "msg_run_done" "second_param"
msg_warn "msg_warn"
msg_yay "msg_yay"
msg_yay_done "msg_yay_done"
# shellcheck disable=SC1010
msgr done "msgr done"
msgr done_suffix "msgr done_suffix"
msgr err "msgr err"
msgr nested "msgr nested"
msgr nested_done "msgr nested_done"
msgr ok "msgr ok"
msgr prompt "msgr prompt"
msgr prompt_done "msgr prompt_done"
msgr run "msgr run" "second_param"
msgr run_done "msgr run_done" "second_param"
msgr warn "msgr warn"
msgr yay "msgr yay"
msgr yay_done "msgr yay_done"
;;
*) menu_usage "$USAGE_PREFIX" "${MENU[@]}" ;;
*) menu_builder "$USAGE_PREFIX" "${MENU[@]}" ;;
esac
}
usage()
{
echo ""
msg_prompt "Usage: $SCRIPT <section> <command>"
msgr prompt "Usage: $SCRIPT <section> <command>"
echo $" Empty <command> prints <section> help."
echo ""
section_install
echo ""
section_apt
echo ""
section_asdf
echo ""
section_brew
@@ -658,6 +788,8 @@ usage()
echo ""
section_docs
echo ""
section_scripts
echo ""
section_helpers
}
@@ -668,12 +800,14 @@ main()
# The main loop. The first keyword after $0 triggers section, or help.
case "$SECTION" in
install) section_install "$@" ;;
apt) section_apt "$@" ;;
asdf) section_asdf "$@" ;;
brew) section_brew "$@" ;;
check) section_check "$@" ;;
dotfiles) section_dotfiles "$@" ;;
helpers) section_helpers "$@" ;;
docs) section_docs "$@" ;;
scripts) section_scripts "$@" ;;
tests) section_tests "$@" ;;
*) usage && exit 0 ;;
esac

View File

@@ -23,8 +23,8 @@
VERBOSE="${VERBOSE:-0}"
# UTF-8 ftw
GITDIRTY="❌ "
GITCLEAN="✅ "
GIT_DIRTY="❌ "
GIT_CLEAN="✅ "
# Function to print messages if VERBOSE is enabled
# $1 - message (string)
@@ -41,7 +41,7 @@ catch()
# Function to check the git status of a directory
# $1 - directory (string)
gitdirty()
git_dirty()
{
local d="$1"
trap 'catch $? $LINENO' ERR
@@ -58,15 +58,15 @@ gitdirty()
# If we have `.git` folder, check it.
if [[ -d ".git" ]]; then
ISDIRTY=$(git diff --shortstat 2> /dev/null | tail -n1)
ICON="$GITCLEAN"
GIT_IS_DIRTY=$(git diff --shortstat 2> /dev/null | tail -n1)
ICON="$GIT_CLEAN"
[[ $ISDIRTY != "" ]] && ICON="$GITDIRTY"
[[ $GIT_IS_DIRTY != "" ]] && ICON="$GIT_DIRTY"
printf " %s %s\n" "$ICON" "$(pwd)"
else
# If it wasn't git repository, check subdirectories.
gitdirtyrepos ./*
git_dirty_repos ./*
fi
cd - > /dev/null || exit
fi
@@ -76,10 +76,10 @@ gitdirty()
# Function to check git status for multiple directories
# $@ - directories
gitdirtyrepos()
git_dirty_repos()
{
for x in "$@"; do
gitdirty "$x"
git_dirty "$x"
done
}
@@ -96,7 +96,7 @@ main()
11) echo "segfault occurred";;
esac' EXIT
gitdirtyrepos "$GIT_DIRTY_DIR"
git_dirty_repos "$GIT_DIRTY_DIR"
}
main "$@"

143
local/bin/t Executable file
View File

@@ -0,0 +1,143 @@
#!/usr/bin/env bash
#
# Credit to ThePrimeagen, Jess Archer
# See https://github.com/jessarcher/dotfiles/blob/master/scripts/t
#
# Tweaks by Ismo Vuorinen <https://github.com/ivuorinen> 2025
# vim: ft=bash ts=2 sw=2 et
# Set environment variables for configuration with defaults
T_ROOT="${T_ROOT:-$HOME/Code}"
DOTFILES="${DOTFILES:-$HOME/.dotfiles}"
T_MAX_DEPTH="${T_MAX_DEPTH:-3}"
# Function to print an error message and exit
error_exit() {
echo "Error: $1" >&2
exit 1
}
# Validate that T_ROOT exists
if [[ ! -d "$T_ROOT" ]]; then
error_exit "T_ROOT directory '$T_ROOT' does not exist."
fi
# Check for required dependencies
check_dependencies() {
local T_DEPS=(tmux fzf find)
for cmd in "${T_DEPS[@]}"; do
if ! command -v "$cmd" &> /dev/null; then
error_exit "$cmd is not installed."
fi
done
}
check_dependencies
# Generate an array of '-not -path' rules for each exclusion pattern
# without using namerefs.
generate_exclude_rules() {
local result_var="$1"
shift
local arr=()
for pattern in "$@"; do
# Exclude both the directory and any subdirectories under it.
arr+=( -not -path "*/${pattern}" -not -path "*/${pattern}/*" )
done
# Use eval to assign the array to the variable whose name was passed.
eval "$result_var=(\"\${arr[@]}\")"
}
get_directories() {
local exclude_patterns=(
".bzr" ".git" ".hg" ".idea" ".obsidian" ".run" ".svn" ".vscode"
"build" "dist" "node_modules" "out" "target" "vendor"
)
local exclude_rules=()
generate_exclude_rules exclude_rules "${exclude_patterns[@]}"
local dirs
# Use $'string' to correctly process escape sequences.
dirs=$'# Directories\n'
dirs+=$(find "$T_ROOT" \
-maxdepth "$T_MAX_DEPTH" \
-mindepth 1 \
-type d \
"${exclude_rules[@]}"
)
echo -e "$dirs"
}
check_tmux() {
if ! command -v tmux &> /dev/null; then
error_exit "tmux is not installed."
fi
# Ensure tmux server is running
if ! tmux info &> /dev/null; then
tmux start-server
fi
}
get_sessions() {
check_tmux
T_TMUX_SESSIONS=$(tmux list-sessions -F "#{session_name}" 2> /dev/null)
if [[ -z "$T_TMUX_SESSIONS" ]]; then
echo ""
return
fi
echo -e "# Sessions\n$T_TMUX_SESSIONS"
}
# Determine selection from command-line argument or interactive fzf menu
if [[ $# -eq 1 ]]; then
selected="$1"
else
# Combine sessions and directories for selection
T_ITEMS="$(get_sessions | sort)
$(get_directories | sort)"
# Use sort to order the entries and fzf for interactive selection
selected=$(echo "$T_ITEMS" | fzf) || exit 0
fi
# Reject selection if it is a header line
[[ ${selected:0:1} == "#" ]] && error_exit "Header selected. Please choose a valid session or directory."
[[ -z "$selected" ]] && error_exit "No directory or session selected."
# Sanitize the session name
session_name=$(basename "$selected")
if [[ -z "$session_name" ]]; then
session_name="$selected"
fi
# Remove dots since tmux dislikes them
session_name="${session_name//./}"
# Attempt to switch to an existing session
tmux switch-client -t "=$session_name" 2>/dev/null
active_session=$(tmux display-message -p -F '#{session_name}' 2>/dev/null)
if [[ "$active_session" == "$session_name" ]]; then
exit 0
fi
# Create a new session (or attach to an existing one) based on the selection
if [ -z "$TMUX" ]; then
# Not inside tmux: create (or attach to) the session and attach.
tmux new-session -A -s "$session_name" -c "$selected"
else
# Inside tmux: check if the target session exists.
if tmux has-session -t "$session_name" 2>/dev/null; then
# Session exists; switch to it.
tmux switch-client -t "$session_name"
else
# Session does not exist; create it in detached mode and then switch.
tmux new-session -d -s "$session_name" -c "$selected"
tmux switch-client -t "$session_name"
fi
fi

54
local/bin/x-clean-vendordirs Executable file
View File

@@ -0,0 +1,54 @@
#!/usr/bin/env bash
# vim: ft=bash sw=2 ts=2 et
#
# Removes vendor and node_modules directories from the
# current directory and all subdirectories.
#
# Author: Ismo Vuorinen 2025
# License: MIT
# Check if the user has provided a directory as an argument
if [ "$1" ]; then
# Check if the directory exists
if [ -d "$1" ]; then
CLEANDIR="$1"
else
msgr err "Directory $1 does not exist."
exit 1
fi
else
CLEANDIR="."
fi
# Function to remove node_modules and vendor folders
remove_node_modules_vendor() {
local dir=$1
# If the directory is a symlink, skip it
if [ -L "$dir" ]; then
msgr msg "Skipping symlink $dir"
return
fi
# Check if the directory exists
if [ -d "$dir" ]; then
# If node_modules or vendor folder exists, remove it and all its contents
if [ -d "$dir/node_modules" ]; then
msgr run "Removing $dir/node_modules"
rm -rf "$dir/node_modules"
fi
if [ -d "$dir/vendor" ]; then
msgr run "Removing $dir/vendor"
rm -rf "$dir/vendor"
fi
# Recursively check subdirectories
for item in "$dir"/*; do
remove_node_modules_vendor "$item"
done
fi
}
# Start removing node_modules and vendor folders from the current working directory
remove_node_modules_vendor "$CLEANDIR"

View File

@@ -23,7 +23,8 @@ generate_tmux_keybindings()
{
local tmux_keybindings_docs="$1"
local cb="\n\`\`\`\n"
local cb="\n\`\`\`txt\n"
local cbe="\n\`\`\`\n"
local kb
kb=$(tmux lsk -Tprefix -N | sed -e 's/^/ /;')
local h="# tmux keybindings\n"
@@ -33,7 +34,7 @@ generate_tmux_keybindings()
kb="${kb//$HOME/\$HOME}"
msg "Outputting tmux keybindings to $tmux_keybindings_docs"
echo -e "${h}${l}${cb}${kb}${cb}" > "$tmux_keybindings_docs"
echo -e "${h}${l}${cb}${kb}${cbe}" > "$tmux_keybindings_docs"
msg "Done!"
}

226
local/bin/x-env-list Executable file
View File

@@ -0,0 +1,226 @@
#!/bin/bash
#
# List environment variables grouped by the first part before underscore
# protecting environment variables that possibly contain sensitive information.
#
# Author: Ismo Vuorinen <https://github.com/ivuorinen> 2025
# License: MIT
#
# vim: ft=bash fileencoding=utf-8 sw=2 ts=2 sts=2 et tw=100
# X_ENV_GROUPING is a file that contains custom groupings for environment variables.
# The file should contain lines in the format "KEY:GROUP". One line per key.
: "${X_ENV_GROUPING:=${XDG_CONFIG_HOME:-$HOME/.config}/zsh/env_list_grouping.yaml}"
# Define protected keywords. Values of these keys are displayed as [protected value].
# The keys are case-insensitive and are matched as substrings.
PROTECTED_KEYS=("*TOKEN*" "*SECRET*" "DIRENV_DIFF" "DIRENV_WATCHES" "PATH" "FPATH")
# Default grouping is based on the first part before underscore, but can be overridden
# either by custom grouping file or by the get_custom_group function.
# The following grouping is used by default and for example groups Golang environment variables
# under the "GO" group. The keys BASH, COMMAND, FPATH, etc. are grouped under the "SHELL" group.
DEFINED_GROUPS=(
"AUTOSWITCH_VIRTUAL_ENV_DIR=PYTHON"
"BASH=SHELL"
"COMMAND=SHELL"
"COMPLETION=SHELL"
"DISABLE_LS_COLORS=SHELL"
"FPATH=SHELL"
"GOBIN=GO"
"GOPATH=GO"
"GOROOT=GO"
"GREP=SHELL"
"HIST=SHELL"
"HISTCONTROL=SHELL"
"HISTFILE=SHELL"
"HISTIGNORE=SHELL"
"HISTORY=SHELL"
"HISTSIZE=SHELL"
"HOME=SHELL"
"INFOPATH=SHELL"
"LESS=SHELL"
"LESSHISTFILE=SHELL"
"LOGNAME=SHELL"
"MANPAGER=SHELL"
"PAGER=SHELL"
"PATH=SHELL"
"PWD=SHELL"
"PYENV_ROOT=PYTHON"
"PYENV_SHELL=PYTHON"
"PYTHONPATH=PYTHON"
"RUSTUP_HOME=RUST"
"RUST_WITHOUT=RUST"
"SHELL=SHELL"
"TMPDIR=SHELL"
"USER=SHELL"
"WORKON_HOME=PYTHON"
"ZSH=ZSH"
"_=SHELL"
"npm_config_cache=NPM"
)
CONFIG_FILE="$X_ENV_GROUPING"
# If we have configuration file, run extra checks so we can process it.
if [[ -f "$CONFIG_FILE" ]]; then
# Check if yq is installed
if ! command -v yq &> /dev/null; then
echo "Error: yq is not installed. Please install it to proceed." >&2
exit 1
fi
# Validate the YAML file
if ! yq '.' "$CONFIG_FILE" &> /dev/null; then
echo "Error: Invalid YAML structure in '$CONFIG_FILE'." >&2
exit 1
fi
# Check if required keys exist in the YAML structure
if ! yq '.custom_grouping, .protected_keys' "$CONFIG_FILE" &> /dev/null; then
echo "Error: Missing required keys ('custom_grouping' or 'protected_keys') in '$CONFIG_FILE'." >&2
exit 1
fi
# If X_ENV_GROUPING is set, it will be used as the file path for custom grouping, and
# protected keys will be read from the file. The values in the file will be appended to the
# processing algorithm.
CUSTOM_KEYS=$(yq '.protected_keys[]' "$CONFIG_FILE")
while IFS= read -r key; do
# Add to default_protected_keys
PROTECTED_KEYS+=("$key")
done <<< "$CUSTOM_KEYS"
CUSTOM_GROUPS=$(yq '.custom_grouping[]' "$CONFIG_FILE")
while IFS= read -r group; do
group_name=$(echo "$group" | yq 'keys[0]')
GROUP_KEYS=$(yq ".custom_grouping[] | .[\"$group_name\"][]" "$CONFIG_FILE")
while IFS= read -r key; do
# Add to default_custom_grouping in "GROUP=KEY" format
DEFINED_GROUPS+=("$group_name=$key")
done <<< "$GROUP_KEYS"
done <<< "$CUSTOM_GROUPS"
fi
if [[ -f "$X_ENV_GROUPING" ]]; then
while IFS=':' read -r key group; do
DEFINED_GROUPS+=("$key=$group")
done < "$X_ENV_GROUPING"
fi
# Check if the key is in the protected keywords list
is_protected()
{
local key=$1
for protected_key in "${PROTECTED_KEYS[@]}"; do
# Direct match
if [[ "$key" == "$protected_key" ]]; then
return 0
fi
# Wildcard match (protected_key contains '*')
if [[ "$protected_key" == *"*"* ]] && [[ "$key" == $protected_key ]]; then
return 0
fi
done
return 1
}
# Custom function to determine a custom group.
#
# If custom grouping file was found and was read,
# the default grouping was already overridden.
get_custom_group()
{
local key=$1
for entry in "${DEFINED_GROUPS[@]}"; do
local mapping_key=${entry%%=*}
local mapping_group=${entry#*=}
if [[ $key == "$mapping_key" ]]; then
echo "$mapping_group"
return 0
fi
done
# Automatically create TOKENS group if the key contains "TOKEN".
if [[ $key == *TOKEN* ]]; then
echo "TOKENS"
return 0
fi
return 1
}
# Create arrays to store all groups, group data and max lengths for each group
all_groups=()
group_data=()
group_max_lengths=()
# Get environment variables and group them
while IFS='=' read -r key value; do
# Check for custom group
group=$(get_custom_group "$key")
# If there is no custom group, use the default algorithm:
# 1) First part before underscore is used as the group name.
# 2) If the key starts with an underscore, the group is determined by the second part.
# 3) If the key does not contain an underscore, the group is the key itself.
if [[ -z $group ]]; then
if [[ $key == _* ]]; then
group="${key#_}"
group="${group%%_*}"
[[ -z $group ]] && group="Ungrouped"
else
group="${key%%_*}"
[[ -z $group ]] && group="Ungrouped"
fi
fi
# Hide values of protected keys
if is_protected "$key"; then
value="[protected value]"
fi
# Update group data
if [[ ! " ${all_groups[*]} " =~ " $group " ]]; then
all_groups+=("$group")
fi
group_data+=("$group|$key|$value")
key_length=${#key}
for i in "${!all_groups[@]}"; do
if [[ ${all_groups[$i]} == "$group" ]]; then
if [[ ${group_max_lengths[$i]:-0} -lt $key_length ]]; then
group_max_lengths[i]=$key_length
fi
break
fi
done
done < <(env | sort | awk -F'=' '{print $1"="$2}')
# Print groups in order, "Ungrouped" last
sorted_groups=()
while IFS= read -r line; do
sorted_groups+=("$line")
done < <(printf "%s\n" "${all_groups[@]}" | grep -v "^Ungrouped$" | sort)
sorted_groups+=("Ungrouped")
for group in "${sorted_groups[@]}"; do
echo -e "\n# $group"
for i in "${!all_groups[@]}"; do
if [[ ${all_groups[$i]} == "$group" ]]; then
max_length=${group_max_lengths[$i]}
break
fi
done
for entry in "${group_data[@]}"; do
IFS='|' read -r g k v <<< "$entry"
if [[ $g == "$group" ]]; then
printf "%-*s = %s\n" "$max_length" "$k" "$v"
fi
done
done

View File

@@ -1,6 +1,7 @@
#!/usr/bin/env bash
#
# foreach <folder> <commands that should be run to each file>
# foreach "ls -d */" "git status" # run git status in each folder
#
# Source: https://github.com/mvdan/dotfiles/blob/master/.bin/foreach
@@ -11,6 +12,7 @@ for dir in $($cmd); do
(
echo "$dir"
cd "$dir" || exit 1
# shellcheck disable=SC2294,SC2034
eval "$@" # allow multiple commands like "foo && bar"
)
done

View File

@@ -1,7 +1,7 @@
#!/usr/bin/env bash
#
# Fetch the latest release version of a GitHub repository in tar.gz format (e.g. v1.0.0.tar.gz)
# Usage: x-gh-get-latest-release-targ <repo> [--get]
# Usage: x-gh-get-latest-release-targz <repo> [--get]
# Author: Ismo Vuorinen <https://github.com/ivuorinen> 2024
set -euo pipefail

View File

@@ -1,66 +1,190 @@
#!/usr/bin/env bash
#
# Get latest release version from GitHub
# Get latest release version, branch tag, or latest commit from GitHub
# Usage: x-gh-get-latest-version <repo>
# Author: Ismo Vuorinen <https://github.com/ivuorinen> 2024
set -euo pipefail
# Enable verbosity with VERBOSE=1
# Environment variables, more under get_release_version() and get_latest_branch_tag()
# functions. These can be overridden by the user.
GITHUB_API_URL="${GITHUB_API_URL:-https://api.github.com/repos}"
VERBOSE="${VERBOSE:-0}"
# Function to print usage information
usage()
{
echo "Usage: $0 <repo> (e.g. ivuorinen/dotfiles)"
# Prints a message if VERBOSE=1
msg() {
[[ "$VERBOSE" -eq 1 ]] && echo "$1"
}
# Show usage information
usage() {
cat <<EOF
Usage: $0 <repo> (e.g. ivuorinen/dotfiles)
Fetches the latest release version, latest branch tag, or latest commit SHA from GitHub.
Options:
- INCLUDE_PRERELEASES=1 Include prerelease versions (default: only stable releases).
- OLDEST_RELEASE=1 Fetch the oldest release instead of the latest.
- BRANCH=<branch> Fetch the latest tag from a specific branch (default: main).
- LATEST_COMMIT=1 Fetch the latest commit SHA from the specified branch.
- OUTPUT=json Return output as JSON (default: plain text).
- GITHUB_API_URL=<url> Override GitHub API URL (useful for GitHub Enterprise).
- GITHUB_TOKEN=<token> Use GitHub API token to increase rate limits (default: unauthenticated).
Requirements:
- curl
- jq (for JSON processing)
Examples:
# Fetch the latest stable release
$0 ivuorinen/dotfiles
# Fetch the latest release including prereleases
INCLUDE_PRERELEASES=1 $0 ivuorinen/dotfiles
# Fetch the oldest release
OLDEST_RELEASE=1 $0 ivuorinen/dotfiles
# Fetch the latest tag from the 'develop' branch
BRANCH=develop $0 ivuorinen/dotfiles
# Fetch the latest commit SHA from 'main' branch
LATEST_COMMIT=1 $0 ivuorinen/dotfiles
# Output result in JSON format
OUTPUT=json $0 ivuorinen/dotfiles
# Use GitHub API token for higher rate limits
GITHUB_TOKEN="your_personal_access_token" $0 ivuorinen/dotfiles
# Use GitHub Enterprise API
GITHUB_API_URL="https://github.example.com/api/v3/repos" $0 ivuorinen/dotfiles
EOF
exit 1
}
# Function to print messages if VERBOSE is enabled
# $1 - message (string)
msg()
{
[[ "$VERBOSE" -eq 1 ]] && echo "$1"
return 0
# Check that required dependencies are installed
check_dependencies() {
for cmd in curl jq; do
if ! command -v "$cmd" &>/dev/null; then
echo "Error: '$cmd' is required but not installed." >&2
exit 1
fi
done
}
# Function to fetch the latest release version from GitHub
# Fetches the latest release or the oldest if OLDEST_RELEASE=1
# $1 - GitHub repository (string)
get_latest_release()
{
local repo=$1
get_release_version() {
local repo="$1"
local include_prereleases="${INCLUDE_PRERELEASES:-0}"
local oldest_release="${OLDEST_RELEASE:-0}"
local api_url="${GITHUB_API_URL}/${repo}/releases"
local auth_header=()
if [[ -n "${GITHUB_TOKEN:-}" ]]; then
auth_header=(-H "Authorization: token $GITHUB_TOKEN")
fi
msg "Fetching release data from: $api_url (Include prereleases: $include_prereleases, Oldest: $oldest_release)"
local json_response
json_response=$(curl -sSL "${auth_header[@]}" "$api_url")
# Check for API errors
if echo "$json_response" | jq -e 'has("message")' >/dev/null; then
msg "GitHub API error: $(echo "$json_response" | jq -r '.message')"
exit 1
fi
local filter='.[] | select(.tag_name)'
[[ "$include_prereleases" -eq 0 ]] && filter+='.prerelease == false'
local version
version=$(curl -s "https://api.github.com/repos/${repo}/releases/latest" \
| grep "tag_name" \
| awk -F '"' '{print $4}')
if [[ "$oldest_release" -eq 1 ]]; then
version=$(echo "$json_response" | jq -r "[${filter}] | last.tag_name // empty")
else
version=$(echo "$json_response" | jq -r "[${filter}] | first.tag_name // empty")
fi
if [ -z "$version" ]; then
msg "Failed to fetch the latest release version for repository: $repo"
echo ""
if [[ -z "$version" ]]; then
msg "Failed to fetch release version for repository: $repo"
exit 1
fi
echo "$version"
return 0
}
# Fetches the latest tag from the specified branch
get_latest_branch_tag() {
local repo="$1"
local branch="${BRANCH:-main}"
local api_url="${GITHUB_API_URL}/${repo}/git/refs/tags"
msg "Fetching latest tag for branch '$branch' from: $api_url"
local json_response
json_response=$(curl -sSL "$api_url")
local version
version=$(echo "$json_response" | jq -r "[.[] | select(.ref | contains(\"refs/tags/$branch\"))] | last.ref | sub(\"refs/tags/\"; \"\") // empty")
if [[ -z "$version" ]]; then
msg "Failed to fetch latest tag for branch: $branch"
exit 1
fi
echo "$version"
}
# Fetches the latest commit SHA from the specified branch
get_latest_commit() {
local repo="$1"
local branch="${BRANCH:-main}"
local api_url="${GITHUB_API_URL}/${repo}/commits/$branch"
msg "Fetching latest commit SHA from: $api_url"
local json_response
json_response=$(curl -sSL "$api_url")
local sha
sha=$(echo "$json_response" | jq -r '.sha // empty')
if [[ -z "$sha" ]]; then
msg "Failed to fetch latest commit SHA for branch: $branch"
exit 1
fi
echo "$sha"
}
# Main function
main()
{
if [ "$#" -ne 1 ]; then
# $1 - GitHub repository (string)
main() {
if [[ $# -ne 1 ]]; then
usage
fi
local repo=$1
check_dependencies
msg "Fetching the latest release version for repository: $repo"
local repo="$1"
local result
local version
version=$(get_latest_release "$repo")
if [[ "${LATEST_COMMIT:-0}" -eq 1 ]]; then
result=$(get_latest_commit "$repo")
elif [[ -n "${BRANCH:-}" ]]; then
result=$(get_latest_branch_tag "$repo")
else
result=$(get_release_version "$repo")
fi
echo "$version"
return 0
if [[ "${OUTPUT:-text}" == "json" ]]; then
echo "{\"repository\": \"$repo\", \"result\": \"$result\"}"
else
echo "$result"
fi
}
main "$@"

129
local/bin/x-localip Executable file
View File

@@ -0,0 +1,129 @@
#!/bin/bash
#
# x-localip: script to display the local IP addresses of the system
#
# Author: Ismo Vuorinen <https://github.com/ivuorinen>
# License: MIT
VERSION="1.0.0"
SCRIPT_NAME="$(basename "$0")"
# Function to display usage
usage()
{
echo "Usage: $SCRIPT_NAME [options] [interface]"
echo "Options:"
echo " --help Show this help message"
echo " --version Show version information"
echo " --ipv4 Show only IPv4 addresses"
echo " --ipv6 Show only IPv6 addresses"
echo "If an interface is specified, only the IP address of that interface will be returned."
}
# Initialize flags for filtering
show_ipv4=true
show_ipv6=true
# Check for arguments
while [[ $# -gt 0 ]]; do
case $1 in
--help)
usage
exit 0
;;
--version)
echo "$SCRIPT_NAME version $VERSION"
exit 0
;;
--ipv4)
show_ipv6=false
;;
--ipv6)
show_ipv4=false
;;
*)
iface=$1
;;
esac
shift
done
declare -a interfaces
# Detect platform (macOS or Linux)
platform="$(uname)"
if [[ $platform == "Darwin" ]]; then
read -r -a interfaces <<< "$(ifconfig -lu | grep -v '^bridge')"
elif [[ $platform == "Linux" ]]; then
read -r -a interfaces <<< "$(ip link show | awk -F: '/^[0-9]+:/{print $2}' | tr -d ' ' | grep -v '^bridge')"
else
echo "Error: Unsupported platform. Only macOS and Linux are supported."
exit 1
fi
# Function to fetch IP addresses for an interface
fetch_ips()
{
iface="$1"
local ipv4 ipv6
if [[ $platform == "Darwin" ]]; then
ipv4=$(ipconfig getifaddr "$iface" 2> /dev/null || echo "")
ipv6=$(ipconfig getifaddr -v6 "$iface" 2> /dev/null || echo "")
else
ipv4=$(ip -4 addr show "$iface" 2> /dev/null | awk '/inet / {print $2}' || echo "")
ipv6=$(ip -6 addr show "$iface" 2> /dev/null | awk '/inet6 / {print $2}' || echo "")
fi
if [[ -n $ipv4 || -n $ipv6 ]]; then
echo "$iface:$ipv4:$ipv6"
fi
}
# Determine maximum lengths for formatting
max_iface_length=9 # "Interface" length
max_ipv4_length=11 # "IPv4 Address" length
max_ipv6_length=11 # "IPv6 Address" length
interface_ip_list=()
for iface in "${interfaces[@]}"; do
result=$(fetch_ips "$iface")
if [[ -n $result ]]; then
interface_ip_list+=("$result")
fi
done
interface_ip_list_array=()
for entry in "${interface_ip_list[@]}"; do
IFS=: read -r iface ipv4 ipv6 <<< "$entry"
[[ ${#iface} -gt $max_iface_length ]] && max_iface_length=${#iface}
[[ ${#ipv4} -gt $max_ipv4_length ]] && max_ipv4_length=${#ipv4}
[[ ${#ipv6} -gt $max_ipv6_length ]] && max_ipv6_length=${#ipv6}
interface_ip_list_array+=("$iface:$ipv4:$ipv6")
done
# Print headers
printf "%-${max_iface_length}s : %-${max_ipv4_length}s : %-${max_ipv6_length}s\n" "Interface" "IPv4 Address" "IPv6 Address"
printf "%0.s-" $(seq 1 $((max_iface_length + max_ipv4_length + max_ipv6_length + 6)))
printf "\n"
# Print the results in a formatted table
for entry in "${interface_ip_list_array[@]}"; do
# Split the entry into interface, IPv4, and IPv6
iface="${entry%%:*}"
rest="${entry#*:}"
ipv4="${rest%%:*}"
ipv6="${rest#*:}"
# Skip IPv4 or IPv6 as per the flags
ipv4_display=$([[ $show_ipv4 == true ]] && echo "$ipv4" || echo "")
ipv6_display=$([[ $show_ipv6 == true ]] && echo "$ipv6" || echo "")
# Print the interface name, padded to max_iface_length, followed by the IPs
printf "%-${max_iface_length}s" "$iface"
if $show_ipv4; then
printf " : %-${max_ipv4_length}s" "$ipv4_display"
fi
if $show_ipv6; then
printf " : %-${max_ipv6_length}s" "$ipv6_display"
fi
printf "\n"
done

183
local/bin/x-multi-ping Executable file
View File

@@ -0,0 +1,183 @@
#!/usr/bin/env bash
# x-multi-ping: Multi-protocol ping wrapper in Bash
#
# Description:
# This script pings a list of hostnames using both IPv4 and IPv6 protocols.
# It uses the 'dig' command to resolve the hostnames and then pings each IP
# address found. The script can run once or loop indefinitely with a sleep
# interval between iterations.
#
# This script is based on the original work by Steve Kemp.
# Original work Copyright (c) 2014 by Steve Kemp.
#
# The code in the original repository may be modified and distributed under your choice of:
# * The Perl Artistic License (http://dev.perl.org/licenses/artistic.html) or
# * The GNU General Public License, version 2 or later (http://www.gnu.org/licenses/gpl2.txt).
#
# Modifications and enhancements by Ismo Vuorinen on 2025.
#
# Usage:
# x-multi-ping [--loop|--forever] [--sleep=N] hostname1 hostname2 ...
#
# Options:
# --help Display this help message.
# --verbose Enable verbose output.
# --loop, --forever Loop indefinitely.
# --sleep=N Sleep N seconds between iterations (default: 1).
#
# Examples:
# x-multi-ping example.com
# x-multi-ping --loop --sleep=5 example.com
# x-multi-ping --forever example.com example.org
#
# Dependencies:
# - dig (DNS lookup utility)
# - ping (ICMP ping utility)
# - ping6 (IPv6 ping utility) or ping -6 (alternative)
#
# Defaults
LOOP=0
SLEEP=1
VERBOSE=0
TIMEOUT=5
usage()
{
echo "Usage: $0 [--loop|--forever] [--sleep=N] hostname1 hostname2 ..."
echo "Options:"
echo " --help Display this help message."
echo " --verbose Enable verbose output."
echo " --loop, --forever Loop indefinitely."
echo " --sleep=N Sleep N seconds between iterations (default: 1)."
}
# Parse command-line options
while [[ $# -gt 0 ]]; do
case "$1" in
--help)
usage
exit 0
;;
--verbose)
# shellcheck disable=SC2034
VERBOSE=1
shift
;;
--loop | --forever)
LOOP=1
shift
;;
--sleep=*)
SLEEP="${1#*=}"
shift
;;
--sleep)
if [[ -n "$2" ]]; then
SLEEP="$2"
shift 2
else
echo "Error: --sleep requires a numeric value."
exit 1
fi
;;
--*)
echo "Unknown option: $1"
usage
exit 1
;;
*)
break
;;
esac
done
# Check for required hostnames
if [[ $# -lt 1 ]]; then
usage
exit 1
fi
# Dependency check for dig and ping
if ! command -v dig > /dev/null 2>&1; then
echo "The required 'dig' command is missing. Aborting."
exit 1
fi
if ! command -v ping > /dev/null 2>&1; then
echo "The required 'ping' command is missing. Aborting."
exit 1
fi
# Determine how to invoke IPv6 ping
if command -v ping6 > /dev/null 2>&1; then
PING6="ping6"
elif ping -6 -c1 ::1 > /dev/null 2>&1; then
PING6="ping -6"
else
echo "The required IPv6 ping command (ping6 or ping -6) is missing. Aborting."
exit 1
fi
# Function to remove any URI scheme and port from the hostname.
strip_hostname()
{
local host="$1"
# Remove leading scheme (e.g., http://) if present.
if [[ "$host" =~ ^[a-z]+://([^/]+)/? ]]; then
host="${BASH_REMATCH[1]}"
fi
# Remove a port if specified (e.g., example.com:80).
if [[ "$host" =~ ^([^:]+):[0-9]+$ ]]; then
host="${BASH_REMATCH[1]}"
fi
echo "$host"
}
# Function to ping a given host based on DNS lookups.
pingHost()
{
local original_host="$1"
local host
host=$(strip_hostname "$original_host")
for type in A AAAA; do
# Look up the DNS records for the host.
ips=$(dig +short "$host" "$type")
if [[ -z "$ips" ]]; then
echo "WARNING: Failed to resolve $host [$type]"
else
# For each IP address found, perform the appropriate ping.
while IFS= read -r ip; do
if [[ "$type" == "A" ]]; then
ping_binary="ping"
else
ping_binary="$PING6"
fi
# Execute ping with one packet and a timeout.
$ping_binary -c1 -w"$TIMEOUT" -W"$TIMEOUT" "$host" > /dev/null 2>&1
# shellcheck disable=SC2181
if [[ $? -eq 0 ]]; then
echo "Host $host - $ip - alive"
else
echo "Host $host - $ip - FAILED"
fi
done <<< "$ips"
fi
done
}
# Main loop: run once or forever based on the options.
if [[ $LOOP -eq 1 ]]; then
while true; do
for host in "$@"; do
pingHost "$host"
done
sleep "$SLEEP"
done
else
for host in "$@"; do
pingHost "$host"
done
fi

View File

@@ -1,37 +1,141 @@
#!/usr/bin/env bash
#
# List open (listened) ports, without the crud that
# usually comes with `lsof -i`
# List open (listened) ports in Markdown or JSON format.
#
# Modified by: Ismo Vuorinen <https://github.com/ivuorinen> 2020
# Modified by: Ismo Vuorinen <https://github.com/ivuorinen> 2020, 2025
# Originally from: https://www.commandlinefu.com/commands/view/8951
# Original author: https://www.commandlinefu.com/commands/by/wickedcpj
set -euo pipefail
# Function to print the header
print_header()
FORMAT="markdown"
# Function to print help message
print_help()
{
echo 'User: Command: PID: Port:'
echo '========================================================='
cat << EOF
Usage: $(basename "$0") [OPTIONS]
List open (listened) ports in a formatted table (Markdown) or JSON.
Options:
--json Output results in JSON format instead of Markdown
--help Show this help message
Examples:
$(basename "$0") # List open ports as a Markdown table
$(basename "$0") --json # List open ports in JSON format
EOF
exit 0
}
# Function to list open ports
# Function to print the Markdown table header
print_header()
{
echo "| User | Command | PID | Port |"
echo "|------------------|----------------------------|----------|---------|"
}
# Function to list open ports using lsof
list_open_ports_lsof()
{
lsof -i -P -n -sTCP:LISTEN +c 0 2> /dev/null | awk '
NR > 1 {
port = $9
sub(/.*:/, "", port) # Extract port number
printf "| %-16s | %-26s | %-8s | %-7s |\n", substr($3, 1, 16), substr($1, 1, 26), substr($2, 1, 8), port
}
' | sort -k3,3n | uniq
}
# Function to list open ports using ss (alternative)
list_open_ports_ss()
{
ss -ltpn 2> /dev/null | awk '
NR > 1 {
split($5, addr, ":")
port = addr[length(addr)]
user = $1
cmd = $7
sub(/users:\(\(/, "", cmd) # Cleanup command
sub(/\)\)/, "", cmd)
pid = "-"
match(cmd, /pid=([0-9]+)/, m)
if (m[1] != "") pid = m[1]
printf "| %-16s | %-26s | %-8s | %-7s |\n", substr(user, 1, 16), substr(cmd, 1, 26), substr(pid, 1, 8), port
}
' | sort -k3,3n | uniq
}
# Function to print JSON output
list_open_ports_json()
{
if command -v lsof &> /dev/null; then
lsof -i -P -n -sTCP:LISTEN +c 0 2> /dev/null | awk '
NR > 1 {
port = $9
sub(/.*:/, "", port) # Extract port number
printf "{\"user\": \"%s\", \"command\": \"%s\", \"pid\": \"%s\", \"port\": \"%s\"},\n", $3, $1, $2, port
}
' | sort -k3,3n | uniq | sed '$ s/,$//'
elif command -v ss &> /dev/null; then
ss -ltpn 2> /dev/null | awk '
NR > 1 {
split($5, addr, ":")
port = addr[length(addr)]
user = $1
cmd = $7
sub(/users:\(\(/, "", cmd)
sub(/\)\)/, "", cmd)
pid = "-"
match(cmd, /pid=([0-9]+)/, m)
if (m[1] != "") pid = m[1]
printf "{\"user\": \"%s\", \"command\": \"%s\", \"pid\": \"%s\", \"port\": \"%s\"},\n", user, cmd, pid, port
}
' | sort -k3,3n | uniq | sed '$ s/,$//'
else
echo "[]"
fi
}
# Function to determine available command
list_open_ports()
{
lsof -i 4 -P -n +c 0 \
| grep -i 'listen' \
| awk '{print $3, $1, $2, $9}' \
| sed 's/ [a-z0-9\.\*]*:/ /' \
| sort -k 3 -n \
| xargs printf '%-15s %-25s %-8s %-5s\n' \
| uniq
if [[ "$FORMAT" == "json" ]]; then
echo "["
list_open_ports_json
echo "]"
else
print_header
if command -v lsof &> /dev/null; then
list_open_ports_lsof
elif command -v ss &> /dev/null; then
list_open_ports_ss
else
echo "**Error:** Neither 'lsof' nor 'ss' is available."
exit 1
fi
fi
}
# Main function
main()
{
print_header
case "${1:-}" in
--json)
FORMAT="json"
;;
--help)
print_help
;;
"") ;;
*)
echo "Unknown option: $1"
print_help
;;
esac
list_open_ports
echo ""
}

281
local/bin/x-path Executable file
View File

@@ -0,0 +1,281 @@
#!/usr/bin/env bash
#
# x-path: A unified script to manipulate the PATH variable.
#
# This script supports four subcommands:
# - append (or a): Remove duplicates and append one or more directories.
# - prepend (or p): Remove duplicates and prepend one or more directories.
# - remove: Remove one or more directories from PATH.
# - check: Check if the directories (or all directories in PATH if none provided) are valid.
#
# All directory arguments are normalized (trailing slashes removed, except for "/"),
# and the current PATH is normalized before any operations.
#
# Usage:
# x-path <command> <directory1> [<directory2> ...]
#
# Examples:
# x-path append /usr/local/bin /opt/bin
# x-path p /home/user/bin
# x-path remove /usr/local/bin
# x-path check # Check all directories in PATH
# x-path check /usr/local/bin /bin
#
# Enable verbose output by setting:
# export VERBOSE=1
VERBOSE="${VERBOSE:-0}"
#######################################
# Normalize a directory by removing a trailing slash (unless the directory is "/").
# Globals:
# None
# Arguments:
# $1 - Directory path to normalize
# Returns:
# Echoes the normalized directory.
#######################################
normalize_dir()
{
local d="$1"
if [ "$d" != "/" ]; then
d="${d%/}"
fi
echo "$d"
}
#######################################
# Normalize the PATH variable by normalizing each of its components.
# Globals:
# PATH
# Arguments:
# None
# Returns:
# Updates and exports PATH.
#######################################
normalize_path_var()
{
local new_path=""
local d
IFS=':' read -r -a arr <<< "$PATH"
for d in "${arr[@]}"; do
d=$(normalize_dir "$d")
if [ -z "$new_path" ]; then
new_path="$d"
else
new_path="$new_path:$d"
fi
done
PATH="$new_path"
export PATH
}
#######################################
# Remove all occurrences of a normalized directory from PATH.
# Globals:
# PATH
# Arguments:
# $1 - Normalized directory to remove from PATH.
# Returns:
# Updates PATH.
#######################################
remove_from_path()
{
local d="$1"
PATH=":${PATH}:"
PATH="${PATH//:$d:/:}"
PATH="${PATH#:}"
PATH="${PATH%:}"
}
#######################################
# Append one or more directories to PATH.
# Globals:
# PATH, VERBOSE
# Arguments:
# One or more directory paths.
# Returns:
# Updates PATH.
#######################################
do_append()
{
local processed=""
local d
for arg in "$@"; do
d=$(normalize_dir "$arg")
if [[ " $processed " == *" $d "* ]]; then
continue
else
processed="$processed $d"
fi
if [ ! -d "$d" ]; then
[ "$VERBOSE" -eq 1 ] && echo "(?) Directory '$d' does not exist. Skipping."
continue
fi
remove_from_path "$d"
PATH="${PATH:+"$PATH:"}$d"
[ "$VERBOSE" -eq 1 ] && echo "Appended '$d' to PATH."
done
export PATH
}
#######################################
# Prepend one or more directories to PATH.
# Directories are processed in reverse order so that the first argument ends up leftmost.
# Globals:
# PATH, VERBOSE
# Arguments:
# One or more directory paths.
# Returns:
# Updates PATH.
#######################################
do_prepend()
{
local processed=""
local d
local -a arr=("$@")
local i
for ((i = ${#arr[@]} - 1; i >= 0; i--)); do
d=$(normalize_dir "${arr[i]}")
if [[ " $processed " == *" $d "* ]]; then
continue
else
processed="$processed $d"
fi
if [ ! -d "$d" ]; then
[ "$VERBOSE" -eq 1 ] && echo "(?) Directory '$d' does not exist. Skipping."
continue
fi
remove_from_path "$d"
PATH="$d${PATH:+":$PATH"}"
[ "$VERBOSE" -eq 1 ] && echo "Prepended '$d' to PATH."
done
export PATH
}
#######################################
# Remove one or more directories from PATH.
# Globals:
# PATH, VERBOSE
# Arguments:
# One or more directory paths.
# Returns:
# Updates PATH.
#######################################
do_remove()
{
local processed=""
local d
for arg in "$@"; do
d=$(normalize_dir "$arg")
if [[ " $processed " == *" $d "* ]]; then
continue
else
processed="$processed $d"
fi
case ":$PATH:" in
*":$d:"*)
remove_from_path "$d"
[ "$VERBOSE" -eq 1 ] && echo "Removed '$d' from PATH."
;;
*)
[ "$VERBOSE" -eq 1 ] && echo "(?) '$d' is not in PATH."
;;
esac
done
export PATH
}
#######################################
# Check the validity of directories.
# If arguments are provided, check those directories; otherwise, check all directories in PATH.
# Globals:
# PATH
# Arguments:
# Zero or more directory paths.
# Returns:
# Outputs the validity status of each directory.
#######################################
do_check()
{
local d
if [ "$#" -eq 0 ]; then
echo "Checking all directories in PATH:"
IFS=':' read -r -a arr <<< "$PATH"
for d in "${arr[@]}"; do
d=$(normalize_dir "$d")
if [ -d "$d" ]; then
echo "Valid: $d"
else
echo "Invalid: $d"
fi
done
else
for arg in "$@"; do
d=$(normalize_dir "$arg")
if [ -d "$d" ]; then
echo "Valid: $d"
else
echo "Invalid: $d"
fi
done
fi
}
#######################################
# Main routine: Parse subcommand and arguments, normalize PATH,
# and dispatch to the appropriate functionality.
#######################################
if [ "$#" -lt 1 ]; then
echo "Usage: $0 <command> <directory1> [<directory2> ...]"
echo "Commands:"
echo " append (or a) - Append directories to PATH"
echo " prepend (or p) - Prepend directories to PATH"
echo " remove - Remove directories from PATH"
echo " check - Check validity of directories (or all in PATH if none given)"
exit 1
fi
cmd="$1"
shift
# Normalize the current PATH variable.
normalize_path_var
case "$cmd" in
append | a)
[ "$#" -ge 1 ] || {
echo "Usage: $0 append <directory1> [<directory2> ...]"
exit 1
}
do_append "$@"
;;
prepend | p)
[ "$#" -ge 1 ] || {
echo "Usage: $0 prepend <directory1> [<directory2> ...]"
exit 1
}
do_prepend "$@"
;;
remove)
[ "$#" -ge 1 ] || {
echo "Usage: $0 remove <directory1> [<directory2> ...]"
exit 1
}
do_remove "$@"
;;
check)
# If no directories are provided, check all directories in PATH.
do_check "$@"
;;
*)
echo "Unknown command: $cmd"
echo "Usage: $0 <command> <directory1> [<directory2> ...]"
exit 1
;;
esac

View File

@@ -1,40 +1,44 @@
#!/usr/bin/env bash
#
# Add a directory to the beginning of the PATH if it's not already there.
# Usage: x-path-append <dir>
# Optimized script to append directories to PATH.
# For each given directory, it removes all duplicate occurrences from PATH
# and then appends it if the directory exists.
#
# Usage: x-path-append <directory1> [<directory2> ...]
#
# Enable verbose output by setting the environment variable VERBOSE=1.
#
# Author: Ismo Vuorinen <https://github.com/ivuorinen> 2024
# License: MIT
# Set verbosity with VERBOSE=1
VERBOSE="${VERBOSE:-0}"
# Function to print messages if VERBOSE is enabled
# $1 - message (string)
msg()
{
[[ "$VERBOSE" -eq 1 ]] && echo "$1"
# Ensure that at least one directory is provided.
[ "$#" -lt 1 ] && {
echo "Usage: $0 <directory> [<directory> ...]"
exit 1
}
if [ "$#" -ne 1 ]; then
echo "Usage: $0 <dir>"
exit 1
fi
for dir in "$@"; do
# Check if the specified directory exists.
if [ ! -d "$dir" ]; then
[ "$VERBOSE" -eq 1 ] && echo "(?) Directory '$dir' does not exist. Skipping."
continue
fi
dir="$1"
# Remove all duplicate occurrences of the directory from PATH.
case ":$PATH:" in
*":$dir:"*)
PATH=":${PATH}:"
PATH="${PATH//:$dir:/:}"
PATH="${PATH#:}"
PATH="${PATH%:}"
[ "$VERBOSE" -eq 1 ] && echo "Removed previous occurrences of '$dir' from PATH."
;;
*) ;;
esac
if echo "$PATH" | grep -qE "(^|:)$dir($|:)"; then
export PATH=$(echo -n "$PATH" | awk -v RS=: -v ORS=: "\$0 != \"$dir\"" | sed 's/:$//')
msg "Directory $dir has been removed from PATH"
else
msg "Directory $dir is not in PATH"
fi
if [ ! -d "$dir" ]; then
msg "(?) Directory $dir does not exist"
exit 0
fi
if echo "$PATH" | grep -qE "(^|:)$dir($|:)"; then
msg "(!) Directory $dir is already in PATH"
else
# Append the directory to PATH.
export PATH="${PATH:+"$PATH:"}$dir"
msg "(!) Directory $dir has been added to the end of PATH"
fi
[ "$VERBOSE" -eq 1 ] && echo "Appended '$dir' to PATH."
done

View File

@@ -1,33 +1,50 @@
#!/usr/bin/env bash
#
# Add a directory to the front of the PATH if it exists and is not already there
# Usage: x-path-prepend <dir>
# Optimized script to batch prepend directories to PATH.
# For each given directory, it removes all duplicate occurrences from PATH
# and then prepends it. Directories that do not exist are skipped.
#
# Usage: x-path-prepend <directory1> [<directory2> ...]
#
# Enable verbose output by setting the environment variable VERBOSE=1.
#
# Author: Ismo Vuorinen <https://github.com/ivuorinen> 2024
# License: MIT
# Set verbosity with VERBOSE=1
VERBOSE="${VERBOSE:-0}"
# Function to print messages if VERBOSE is enabled
# $1 - message (string)
msg()
{
[[ "$VERBOSE" -eq 1 ]] && echo "$1"
# Ensure that at least one argument is provided.
[ "$#" -lt 1 ] && {
echo "Usage: $0 <directory> [<directory> ...]"
exit 1
}
if [ "$#" -ne 1 ]; then
echo "Usage: $0 <dir>"
exit 1
fi
# Save the arguments in an array.
dirs=("$@")
dir="$1"
# Process the directories in reverse order so that the first argument ends up leftmost in PATH.
for ((idx = ${#dirs[@]} - 1; idx >= 0; idx--)); do
dir="${dirs[idx]}"
if [ ! -d "$dir" ]; then
msg "(?) Directory $dir does not exist"
exit 0
fi
# Check if the specified directory exists.
if [ ! -d "$dir" ]; then
[ "$VERBOSE" -eq 1 ] && echo "(?) Directory '$dir' does not exist. Skipping."
continue
fi
if echo "$PATH" | grep -qE "(^|:)$dir($|:)"; then
msg "(!) Directory $dir is already in PATH"
else
# Remove all duplicate occurrences of the directory from PATH using built-in string operations.
case ":$PATH:" in
*":$dir:"*)
PATH=":${PATH}:"
PATH="${PATH//:$dir:/:}"
PATH="${PATH#:}"
PATH="${PATH%:}"
[ "$VERBOSE" -eq 1 ] && echo "Removed duplicate occurrences of '$dir' from PATH."
;;
*) ;;
esac
# Prepend the directory to PATH.
export PATH="$dir${PATH:+":$PATH"}"
msg "(!) Directory $dir has been added to the front of PATH"
fi
[ "$VERBOSE" -eq 1 ] && echo "Prepended '$dir' to PATH."
done

View File

@@ -1,29 +1,41 @@
#!/usr/bin/env bash
#
# Remove a directory from the PATH
# Usage: x-path-remove <dir>
# Optimized script to remove directories from PATH.
# For each specified directory, all occurrences are removed from PATH.
#
# Usage: x-path-remove <directory1> [<directory2> ...]
#
# Enable verbose output by setting the environment variable VERBOSE=1.
#
# Author: Ismo Vuorinen <https://github.com/ivuorinen> 2024
# License: MIT
# Set verbosity with VERBOSE=1
VERBOSE="${VERBOSE:-0}"
# Function to print messages if VERBOSE is enabled
# $1 - message (string)
msg()
{
[[ "$VERBOSE" -eq 1 ]] && echo "$1"
# Ensure that at least one directory is provided.
[ "$#" -lt 1 ] && {
echo "Usage: $0 <directory> [<directory> ...]"
exit 1
}
if [ "$#" -ne 1 ]; then
echo "Usage: $0 <dir>"
exit 1
fi
for dir in "$@"; do
# Remove trailing slash if present, unless the directory is "/"
[ "$dir" != "/" ] && dir="${dir%/}"
dir="$1"
# Check if the directory is present in PATH.
case ":$PATH:" in
*":$dir:"*)
# Remove all occurrences of the directory from PATH using parameter expansion.
PATH=":${PATH}:"
PATH="${PATH//:$dir:/:}"
PATH="${PATH#:}"
PATH="${PATH%:}"
[ "$VERBOSE" -eq 1 ] && echo "Removed '$dir' from PATH."
;;
*)
[ "$VERBOSE" -eq 1 ] && echo "(?) '$dir' is not in PATH."
;;
esac
done
if ! echo "$PATH" | grep -qE "(^|:)$dir($|:)"; then
msg "(?) Directory $dir is not in PATH"
exit 0
fi
export PATH=$(echo -n "$PATH" | awk -v RS=: -v ORS=: "\$0 != \"$dir\"" | sed 's/:$//')
msg "(!) Directory $dir has been removed from PATH"
export PATH

View File

@@ -1,5 +1,6 @@
#!/usr/bin/env php
<?php
/**
* Quota usage
* Show quota usage
@@ -10,6 +11,7 @@
* @license MIT
* @author Ismo Vuorinen <https://github.com/ivuorinen>
*/
error_reporting(E_ALL);
$debug = false;

View File

@@ -1,4 +1,4 @@
#!/usr/bin/env sh
#!/usr/bin/env bash
#
# DESCRIPTION:
# Simple recording tool and wrapper around giph (ffmpeg).

View File

@@ -1,71 +1,137 @@
#!/usr/bin/env bash
# Check which PHP versions are installed with brew, and create aliases for each installation.
# Copyright (c) 2023 Ismo Vuorinen. All Rights Reserved.
# -----------------------------------------------------------------------------
# This script caches the list of PHP installations via Homebrew and generates
# shell aliases for each installation. Both the brew list and the generated
# alias definitions are stored in the XDG cache directory.
#
# If the brew list cache is invalid (older than CACHE_TTL), then both caches are
# regenerated. Otherwise, if only the alias cache is stale, it is regenerated
# from the brew list cache.
#
# Usage:
# source x-set-php-aliases.sh
#
# (C) 2023, 2025 Ismo Vuorinen. All Rights Reserved.
# -----------------------------------------------------------------------------
set -euo pipefail
# Set verbosity with VERBOSE=1 x-set-php-aliases
# Set verbosity level (0 by default; set to 1 or 2 for more detail)
VERBOSE="${VERBOSE:-0}"
# Enable debugging if verbosity is set to 2
[ "$VERBOSE" = "2" ] && set -x
# Check if brew is installed, if not exit.
# Exit early if Homebrew is not installed.
if ! command -v brew &> /dev/null; then
echo "Homebrew is not installed. Exiting."
exit 0
fi
# Function to read installed PHP versions using brew
get_php_versions()
# Determine Homebrew's prefix.
HOMEBREW_PREFIX="${HOMEBREW_PREFIX:-$(brew --prefix)}"
# Determine the XDG cache directory (default to ~/.cache).
XDG_CACHE="${XDG_CACHE_HOME:-$HOME/.cache}"
CACHE_DIR="${XDG_CACHE}/x-set-php-aliases"
mkdir -p "$CACHE_DIR"
# Define cache file paths.
BREW_LIST_CACHE="${CACHE_DIR}/brew_list.cache"
ALIASES_CACHE="${CACHE_DIR}/aliases.cache"
# Cache time-to-live in seconds (here 300 seconds = 5 minutes).
CACHE_TTL=300
# -----------------------------------------------------------------------------
# Function: cache_is_valid
# Returns 0 if the file exists and its modification time is within TTL.
# -----------------------------------------------------------------------------
cache_is_valid()
{
local versions=()
while IFS="" read -r line; do
versions+=("$line")
done < <(bkt -- brew list | grep '^php')
echo "${versions[@]}"
local file="$1"
local ttl="$2"
if [[ -f "$file" ]]; then
local mod_time
if stat --version &> /dev/null; then
mod_time=$(stat -c %Y "$file")
else
mod_time=$(stat -f %m "$file")
fi
local current_time
current_time=$(date +%s)
if ((current_time - mod_time < ttl)); then
return 0
fi
fi
return 1
}
# Function to create aliases for each PHP version
create_aliases()
# -----------------------------------------------------------------------------
# Function: generate_aliases
# Reads PHP formulas (one per line) from the specified file and prints out
# alias definitions for each valid PHP installation.
#
# The following aliases are created (assuming the formula is "php@80"):
#
# p80r : Raw PHP (executable only)
# p80 : PHP with an error reporting flag enabled
# p80s : Launches a PHP local server at localhost:9000
# p80c : Runs composer (if found) using this PHP and error reporting flag
# -----------------------------------------------------------------------------
generate_aliases()
{
local php_versions=("$@")
local brew_file="$1"
local php_error_reporting='-d error_reporting=22527'
local composer_path
composer_path=$(command -v composer 2> /dev/null || true)
for version in "${php_versions[@]}"; do
[ "$VERBOSE" = "1" ] && echo "Setting aliases for $version"
while IFS= read -r version || [[ -n "$version" ]]; do
# Remove any leading/trailing whitespace.
version=$(echo "$version" | xargs)
[[ -z "$version" ]] && continue
# Drop the dot from version (e.g., 8.0 -> 80)
# Compute an alias name: remove dots and replace "php@" with "p"
local php_abbr="${version//\./}"
# Replace "php@" with "p" so "php@80" becomes "p80"
local php_alias="${php_abbr//php@/p}"
# Fetch the exec path once
local php_exec="$HOMEBREW_PREFIX/opt/$version/bin/php"
if [ -f "$php_exec" ]; then
[ "$VERBOSE" = "1" ] && echo "-> php_exec $php_exec"
# Raw PHP without error_reporting flag.
alias "${php_alias}r"="$php_exec"
# PHP with error_reporting flag.
alias "$php_alias"="$php_exec $php_error_reporting"
# Local PHP Server.
alias "${php_alias}s"="$php_exec -S localhost:9000"
# Use composer with specific PHP and error_reporting flag on.
alias "${php_alias}c"="$php_exec $php_error_reporting $(which composer)"
local php_exec="${HOMEBREW_PREFIX}/opt/${version}/bin/php"
if [[ -x "$php_exec" ]]; then
echo "alias ${php_alias}r='$php_exec'"
echo "alias $php_alias='$php_exec $php_error_reporting'"
echo "alias ${php_alias}s='$php_exec -S localhost:9000'"
if [[ -n "$composer_path" ]]; then
echo "alias ${php_alias}c='$php_exec $php_error_reporting $composer_path'"
fi
else
[[ "$VERBOSE" -ge 1 ]] && echo "Executable not found: $php_exec (skipping alias for $version)"
fi
done
done < "$brew_file"
}
# Main function
main()
{
local php_versions
php_versions=($(get_php_versions))
create_aliases "${php_versions[@]}"
}
# -----------------------------------------------------------------------------
# Main Cache Update Logic
#
# If the brew list cache is stale (or missing), regenerate it and the aliases.
# If only the alias cache is stale, regenerate just the alias cache.
# -----------------------------------------------------------------------------
if ! cache_is_valid "$BREW_LIST_CACHE" "$CACHE_TTL"; then
[[ "$VERBOSE" -ge 1 ]] && echo "Brew list cache is stale or missing. Regenerating brew list and aliases."
# Regenerate the brew list cache (filtering only PHP formulas).
brew list | grep '^php' > "$BREW_LIST_CACHE"
# Generate the aliases cache from the new brew list.
generate_aliases "$BREW_LIST_CACHE" > "$ALIASES_CACHE"
else
[[ "$VERBOSE" -ge 1 ]] && echo "Using cached brew list from $BREW_LIST_CACHE."
if ! cache_is_valid "$ALIASES_CACHE" "$CACHE_TTL"; then
[[ "$VERBOSE" -ge 1 ]] && echo "Alias cache is stale or missing. Regenerating aliases."
generate_aliases "$BREW_LIST_CACHE" > "$ALIASES_CACHE"
fi
fi
main "$@"
# Source the cached alias definitions.
if [[ -f "$ALIASES_CACHE" ]]; then
# shellcheck source=/dev/null
source "$ALIASES_CACHE"
[[ "$VERBOSE" -ge 1 ]] && echo "Aliases loaded from cache."
else
[[ "$VERBOSE" -ge 1 ]] && echo "No alias cache found; no aliases were loaded."
fi

View File

@@ -1,78 +1,112 @@
#!/usr/bin/env bash
#
# x-sha256sum-matcher
#
# Check if two files are the same
# Compare two files by computing their SHA256 hashes.
#
# Ismo Vuorinen <https://github.com/ivuorinen> 2023
# MIT License
set -euo pipefail
# ENV Variables
: "${VERBOSE:=0}" # VERBOSE=1 x-sha256sum-matcher file1 file2
# Default settings
VERBOSE=0
# Return sha256sum for file
# $1 - filename (string)
get_sha256sum()
# Print usage/help message
usage()
{
sha256sum "$1" | head -c 64
cat << EOF
Usage: $0 [options] file1 file2
Compare two files by computing their SHA256 hashes.
Options:
-v Enable verbose output.
-h, --help Display this help message and exit.
EOF
}
# Print message if VERBOSE is enabled
# $1 - message (string)
msg()
# Check if a command exists
command_exists()
{
[[ "$VERBOSE" -eq 1 ]] && echo "$1"
command -v "$1" > /dev/null 2>&1
}
# Print error message and exit
# $1 - error message (string)
error()
{
msg "(!) ERROR: $1"
# Ensure sha256sum is available
if ! command_exists sha256sum; then
echo "Error: sha256sum command not found. Please install it." >&2
exit 1
}
fi
# Validate input arguments
validate_inputs()
{
if [ "$#" -ne 2 ]; then
echo "Usage: $0 file1 file2"
# Process command-line options
while [[ $# -gt 0 ]]; do
case "$1" in
-h | --help)
usage
exit 0
;;
-v)
VERBOSE=1
shift
;;
-*)
echo "Error: Unknown option: $1" >&2
usage
exit 1
;;
*)
break
;;
esac
done
# Validate input arguments: expect exactly 2 files
if [[ $# -ne 2 ]]; then
echo "Error: Two file arguments required." >&2
usage
exit 1
fi
file1="$1"
file2="$2"
# Check if files exist and are readable
for file in "$file1" "$file2"; do
if [[ ! -f "$file" ]]; then
echo "Error: File does not exist: $file" >&2
exit 1
elif [[ ! -r "$file" ]]; then
echo "Error: File is not readable: $file" >&2
exit 1
fi
}
done
# Check if file exists
# $1 - filename (string)
check_file_exists()
# Print verbose messages if enabled
msg()
{
local filename=$1
if [ ! -f "$filename" ]; then
error "File does not exist: $filename"
if [[ "$VERBOSE" -eq 1 ]]; then
echo "$1"
fi
}
# Main function
main()
# Compute SHA256 hash for a file using awk to extract the first field
get_sha256sum()
{
local file_1=$1
local file_2=$2
validate_inputs "$file_1" "$file_2"
check_file_exists "$file_1"
check_file_exists "$file_2"
local file_1_hash
local file_2_hash
file_1_hash=$(get_sha256sum "$file_1")
file_2_hash=$(get_sha256sum "$file_2")
if [ "$file_1_hash" != "$file_2_hash" ]; then
error "Files do not match"
else
msg "(*) Success: Files do match"
fi
sha256sum "$1" | awk '{print $1}'
}
main "$@"
msg "Computing SHA256 for '$file1'..."
hash1=$(get_sha256sum "$file1")
msg "SHA256 for '$file1': $hash1"
msg "Computing SHA256 for '$file2'..."
hash2=$(get_sha256sum "$file2")
msg "SHA256 for '$file2': $hash2"
if [[ "$hash1" != "$hash2" ]]; then
echo "Files do not match." >&2
exit 1
else
msg "Success: Files match."
exit 0
fi

View File

@@ -1,69 +1,192 @@
#!/usr/bin/env bash
# Generate thumbnails using ImageMagick (magick)
#
# Generate thumbnails using ImageMagick (magick) with MIME type filtering.
# https://imagemagick.org/script/download.php
#
# Defaults to current directory creating thumbnails with 1000x1000
# dimensions and 200px white borders around the original image.
# This script recursively processes images in a given directory (and its subdirectories)
# by using the `mimetype` command to detect file types. Files with MIME types that are not
# supported by ImageMagick (as defined in the ALLOWED_MIMETYPES array) are skipped.
#
# Defaults can be overridden with ENV variables like this:
# $ THMB_BACKGROUND=black x-thumbgen ~/images/
# Defaults (can be overridden by environment variables or command-line options):
# THUMB_SOURCE: Directory with images (provided as a positional argument)
# THUMB_OUTPUT: Directory to store thumbnails (default: same as THUMB_SOURCE)
# THUMB_BACKGROUND: Background color (default: white)
# THUMB_RESIZE: Resize dimensions (default: 800x800)
# THUMB_EXTENT: Canvas dimensions (default: 1000x1000)
# THUMB_SUFFIX: Suffix appended to filename (default: _thumb)
#
# Created by: Ismo Vuorinen <https://github.com/ivuorinen> 2015
# Options:
# -o output_directory Specify the output directory for thumbnails (default: same as source).
# -s suffix Specify a custom suffix for thumbnail filenames (default: _thumb).
# -h, --help Display this help message and exit.
#
# Example:
# THUMB_BACKGROUND=black x-thumbgen.sh -o ~/thumbnails ~/images/
#
# Author: Ismo Vuorinen <https://github.com/ivuorinen> 2015
# Improved in 2025
set -euo pipefail
# Default values
: "${THMB_SOURCE:=${1:-}}"
: "${THMB_BACKGROUND:=white}"
: "${THMB_RESIZE:=800x800}"
: "${THMB_EXTENT:=1000x1000}"
# Print usage information
usage()
{
echo "Usage: $0 /full/path/to/image/folder"
cat << EOF
Usage: $0 [options] source_directory
Options:
-o output_directory Specify the output directory for thumbnails (default: same as source).
-s suffix Specify a custom suffix for thumbnail filenames (default: _thumb).
-h, --help Display this help message and exit.
EOF
exit 1
}
# Check if ImageMagick is installed
# Default values (can be overridden by ENV variables)
THUMB_SOURCE=""
THUMB_OUTPUT=""
THUMB_BACKGROUND="${THUMB_BACKGROUND:-white}"
THUMB_RESIZE="${THUMB_RESIZE:-800x800}"
THUMB_EXTENT="${THUMB_EXTENT:-1000x1000}"
THUMB_SUFFIX="${THUMB_SUFFIX:-_thumb}"
# List of MIME types supported by ImageMagick (adjust as needed)
ALLOWED_MIMETYPES=("image/jpeg" "image/png" "image/gif" "image/bmp" "image/tiff" "image/webp")
check_magick_installed()
{
if ! command -v magick &> /dev/null; then
echo "magick not found in PATH, https://imagemagick.org/script/download.php"
echo "Error: 'magick' command not found. Please install ImageMagick from https://imagemagick.org/script/download.php" >&2
exit 1
fi
}
# Generate thumbnails
generate_thumbnails()
check_mimetype_installed()
{
local source=$1
magick \
"${source}/*" \
-resize "$THMB_RESIZE" \
-background "$THMB_BACKGROUND" \
-gravity center \
-extent "$THMB_EXTENT" \
-set filename:fname '%t_thumb.%e' +adjoin '%[filename:fname]'
if ! command -v mimetype &> /dev/null; then
echo "Error: 'mimetype' command not found. Please install it (e.g. via 'sudo apt install libfile-mimeinfo-perl' on Debian/Ubuntu)." >&2
exit 1
fi
}
# Main function
main()
# Helper function to check if a given MIME type is allowed
is_supported_mimetype()
{
# Validate input
if [ -z "$THMB_SOURCE" ]; then
local mt=$1
for allowed in "${ALLOWED_MIMETYPES[@]}"; do
if [[ "$mt" == "$allowed" ]]; then
return 0
fi
done
return 1
}
# Parse command-line options using getopts
parse_options()
{
while getopts ":o:s:h-:" opt; do
case $opt in
o)
THUMB_OUTPUT="$OPTARG"
;;
s)
THUMB_SUFFIX="$OPTARG"
;;
h)
usage
;;
-)
if [[ "$OPTARG" == "help" ]]; then
usage
else
echo "Error: Unknown option --$OPTARG" >&2
usage
fi
;;
\?)
echo "Error: Invalid option -$OPTARG" >&2
usage
;;
:)
echo "Error: Option -$OPTARG requires an argument." >&2
usage
;;
esac
done
shift $((OPTIND - 1))
# The remaining argument should be the source directory.
if [ $# -lt 1 ]; then
echo "Error: Source directory is required." >&2
usage
fi
# Check if the source directory is valid
if [ ! -d "$THMB_SOURCE" ]; then
echo "Invalid directory: $THMB_SOURCE"
THUMB_SOURCE="$1"
}
# Generate thumbnails recursively using find and filtering by MIME type
generate_thumbnails()
{
local source_dir=$1
local output_dir=$2
# Ensure the output directory exists (create if necessary)
if [ ! -d "$output_dir" ]; then
mkdir -p "$output_dir"
fi
# Recursively find all files.
while IFS= read -r -d '' file; do
# Use mimetype to determine the file's MIME type.
file_mimetype=$(mimetype -b "$file")
if ! is_supported_mimetype "$file_mimetype"; then
echo "Skipping unsupported MIME type '$file_mimetype' for file: $file" >&2
continue
fi
# Determine the relative path with respect to the source directory.
rel_path="${file#$source_dir/}"
dir="$(dirname "$rel_path")"
base="$(basename "$rel_path")"
filename="${base%.*}"
ext="${base##*.}"
# Create corresponding output subdirectory
out_dir="${output_dir}/${dir}"
mkdir -p "$out_dir"
outfile="${out_dir}/${filename}${THUMB_SUFFIX}.${ext}"
echo "Processing '$file' -> '$outfile'..."
magick "$file" \
-resize "$THUMB_RESIZE" \
-background "$THUMB_BACKGROUND" \
-gravity center \
-extent "$THUMB_EXTENT" \
"$outfile"
done < <(find "$source_dir" -type f -print0)
}
main()
{
parse_options "$@"
if [ -z "$THUMB_SOURCE" ]; then
echo "Error: Source directory not specified." >&2
usage
fi
if [ ! -d "$THUMB_SOURCE" ]; then
echo "Error: Source directory '$THUMB_SOURCE' does not exist or is not accessible." >&2
exit 1
fi
# If output directory is not specified, default to the source directory.
if [ -z "$THUMB_OUTPUT" ]; then
THUMB_OUTPUT="$THUMB_SOURCE"
fi
check_magick_installed
generate_thumbnails "$THMB_SOURCE"
check_mimetype_installed
generate_thumbnails "$THUMB_SOURCE" "$THUMB_OUTPUT"
}
main "$@"

View File

@@ -1,12 +1,92 @@
#!/bin/sh
#
# About
# -----
# Repeat the command until it fails - always run at least once.
# x-until-error: Repeatedly execute a command until it fails (non-zero exit status)
#
# Description:
# This script executes the given command repeatedly until it returns a non-zero
# exit status. It always runs the command at least once.
#
# This script is based on the original work by Steve Kemp.
# Original work Copyright (c) 2013 by Steve Kemp.
#
# The code in the original repository may be modified and distributed under your choice of:
# * The Perl Artistic License (http://dev.perl.org/licenses/artistic.html) or
# * The GNU General Public License, version 2 or later (http://www.gnu.org/licenses/gpl2.txt).
#
# Modifications and enhancements by Ismo Vuorinen on 2025.
#
# Usage:
# x-until-error [--sleep SECONDS] command [arguments...]
#
# Options:
# --sleep SECONDS Wait SECONDS (default: 1) between command executions.
# -h, --help Display this help message.
#
# Example:
# x-until-error --sleep 2 ls -l
"$@"
# Default sleep interval between executions.
SLEEP_INTERVAL=1
# If the status code was zero then repeat.
while [ $? -eq 0 ]; do
"$@"
# Function to display usage information.
usage()
{
cat << EOF
Usage: $0 [--sleep SECONDS] command [arguments...]
Repeats the given command until it fails (returns a non-zero exit status).
Options:
--sleep SECONDS Wait SECONDS (default: 1) between command executions.
-h, --help Display this help message.
Example:
$0 --sleep 2 ls -l
EOF
exit 1
}
# Parse command-line options.
while [ $# -gt 0 ]; do
case "$1" in
--sleep)
shift
if [ $# -eq 0 ]; then
echo "Error: --sleep requires a numeric argument." >&2
exit 1
fi
SLEEP_INTERVAL="$1"
shift
;;
-h | --help)
usage
;;
--) # End of options marker.
shift
break
;;
-*)
echo "Error: Unknown option: $1" >&2
usage
;;
*)
break
;;
esac
done
# Ensure a command is provided.
if [ $# -eq 0 ]; then
echo "Error: No command specified." >&2
usage
fi
# Execute the command repeatedly until it fails.
while true; do
"$@"
status=$?
if [ $status -ne 0 ]; then
exit $status
fi
sleep "$SLEEP_INTERVAL"
done

View File

@@ -1,24 +1,92 @@
#!/bin/sh
#
# About
# -----
# Repeat the command until it succeeds - always run at least once.
# x-until-success: Repeat the command until it succeeds - always run at least once.
#
# This script is based on the original work by Steve Kemp.
# Original work Copyright (c) 2013 by Steve Kemp.
#
# License
# -------
# The code in the original repository may be modified and distributed under your choice of:
# * The Perl Artistic License (http://dev.perl.org/licenses/artistic.html) or
# * The GNU General Public License, version 2 or later (http://www.gnu.org/licenses/gpl2.txt).
#
# Copyright (c) 2013 by Steve Kemp. All rights reserved.
# Modifications and enhancements by Ismo Vuorinen on 2025.
#
# This script is free software; you can redistribute it and/or modify it under
# the same terms as Perl itself.
# Usage:
# x-until-success [--sleep SECONDS] command [arguments...]
#
# The LICENSE file contains the full text of the license.
# Options:
# --sleep SECONDS Wait SECONDS (default: 1) between command executions.
# -h, --help Display this help message.
#
# Example:
# x-until-success --sleep 2 ls -l
# Run the first time.
"$@"
# Default sleep interval between command executions.
SLEEP_INTERVAL=1
# If the status code was not zero then repeat.
while [ $? -ne 0 ]; do
"$@"
# Display usage information.
usage()
{
cat << EOF
Usage: $0 [--sleep SECONDS] command [arguments...]
Repeats the given command until it succeeds (returns a zero exit status).
The command is always executed at least once.
Options:
--sleep SECONDS Wait SECONDS (default: 1) between command executions.
-h, --help Display this help message.
Example:
$0 --sleep 2 ping -c 1 google.com
EOF
exit 1
}
# Parse command-line options.
while [ $# -gt 0 ]; do
case "$1" in
--sleep)
shift
if [ $# -eq 0 ]; then
echo "Error: --sleep requires a numeric argument." >&2
usage
fi
SLEEP_INTERVAL="$1"
shift
;;
-h | --help)
usage
;;
--)
shift
break
;;
-*)
echo "Error: Unknown option: $1" >&2
usage
;;
*)
break
;;
esac
done
# Ensure that a command is provided.
if [ $# -eq 0 ]; then
echo "Error: No command specified." >&2
usage
fi
# Execute the command at least once.
"$@"
status=$?
# If the command did not succeed, repeat until it does.
while [ $status -ne 0 ]; do
sleep "$SLEEP_INTERVAL"
"$@"
status=$?
done
exit $status

View File

@@ -15,7 +15,7 @@ COLOR_P='\033[1;36m'
COLOR_S='\033[0;36m'
RESET='\033[0m'
# Print time-based personalized message, using figlet & lolcat if availible
# Print time-based personalized message, using figlet & lolcat if available
function welcome_greeting()
{
h=$(date +%H)
@@ -51,7 +51,7 @@ function welcome_sysinfo()
fi
}
# Print todays info: Date, IP, weather, etc
# Print today's info: Date, IP, weather, etc
function welcome_today()
{
timeout=1

View File

@@ -1,8 +1,17 @@
#!/bin/sh
#!/usr/bin/env bash
#
# Wait until a given host is down (determined by ping) then execute the
# given command
#
# This script is based on the original work by Steve Kemp.
# Original work Copyright (c) 2013 by Steve Kemp.
#
# The code in the original repository may be modified and distributed under your choice of:
# * The Perl Artistic License (http://dev.perl.org/licenses/artistic.html) or
# * The GNU General Public License, version 2 or later (http://www.gnu.org/licenses/gpl2.txt).
#
# Modifications and enhancements by Ismo Vuorinen on 2025.
#
# Usage:
# ./when-down HOST COMMAND...
#

View File

@@ -1,8 +1,17 @@
#!/bin/sh
#!/usr/bin/env bash
#
# Wait until a given host is online (determined by ping) then execute the
# given command
#
# This script is based on the original work by Steve Kemp.
# Original work Copyright (c) 2013 by Steve Kemp.
#
# The code in the original repository may be modified and distributed under your choice of:
# * The Perl Artistic License (http://dev.perl.org/licenses/artistic.html) or
# * The GNU General Public License, version 2 or later (http://www.gnu.org/licenses/gpl2.txt).
#
# Modifications and enhancements by Ismo Vuorinen on 2025.
#
# Usage:
# ./when-up HOST COMMAND...
#

View File

@@ -0,0 +1,67 @@
#!/usr/bin/env php
<?php
// @description Create file containing key mappings for aerospace
// Usage: ./create-aerospace-keymaps.sh
// vim: ft=php ts=4 sw=4 sts=4 sr et
$dotfiles_env = getenv("DOTFILES") ?? '~/.dotfiles';
$dest = "$dotfiles_env/docs/aerospace-keybindings.md";
exec("aerospace config --get mode --json", $output);
$output = implode(' ', $output);
$config = json_decode($output, true);
$main = $config['main'];
unset($config['main']);
function process_section(string $title, array $array): string
{
$bindings = $array['binding'] ?? [];
ksort($bindings);
$output = [];
$output[] = sprintf("\n## %s\n", $title);
$k_len = max(array_map('strlen', array_keys($bindings)));
$v_len = max(array_map('strlen', array_values($bindings)));
$output[] = sprintf(
"| %s | %s |",
str_pad('Key', $k_len + 1),
str_pad('Command(s) and actions', $v_len + 1)
);
$output[] = sprintf(
"|%s|%s|",
str_repeat('-', $k_len + 3),
str_repeat('-', $v_len + 3)
);
foreach ($bindings as $key => $value) {
$k = str_pad($key, $k_len + 1);
$v = str_pad($value, $v_len + 1);
$output[] = sprintf("| %s | %s |", $k, $v);
}
return implode("\n", $output);
}
$contents = [];
$contents[] = "# aerospace keybindings";
$contents[] = process_section("main", $main);
ksort($config);
foreach ($config as $mode => $bindings) {
$contents[] = process_section($mode, $bindings);
}
$contents[] = "\nFile generated: " . date("Y-m-d H:i:s") . "\n";
$config_file_name = 'config/aerospace/aerospace.toml';
$config_file_source = './../config/aerospace/aerospace.toml';
$contents[] = "Config file: [$config_file_name]($config_file_source)\n";
$file = implode("\n", $contents);
file_put_contents($dest, $file);

View File

@@ -1,5 +1,5 @@
#!/usr/bin/env bash
# Create file containing key mappings for Neovim
# @description Create file containing key mappings for Neovim
# Usage: ./create-nvim-keymaps.sh
#
# shellcheck source=shared.sh

View File

@@ -1,18 +0,0 @@
#!/usr/bin/env bash
#
# Export oh-my-posh configuration as an image
#
# shellcheck source=shared.sh
source "${DOTFILES}/config/shared.sh"
main()
{
cd "$DOTFILES" || msg_err "Failed to change directory to $DOTFILES"
oh-my-posh config export image \
--config "$OHMYPOSH_CFG" \
--output "$HOME/.dotfiles/.github/screenshots/oh-my-posh.png" \
--author "Ismo Vuorinen"
}
main "$@"

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