mirror of
https://github.com/ivuorinen/dotfiles.git
synced 2026-01-27 21:45:41 +00:00
Compare commits
51 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 88efedf26b | |||
|
|
cdd68748e0 | ||
|
|
f8ff2699e6 | ||
| c5e06888b8 | |||
|
|
4f138eee73 | ||
|
|
90258e5105 | ||
| efc53fc9bf | |||
|
|
f62c17d940 | ||
|
|
fb15b93887 | ||
|
|
222276486a | ||
|
|
4446d59e73 | ||
| a22709a0f0 | |||
| 76598ad33b | |||
| 56ccb7c136 | |||
|
|
b6d933d018 | ||
| f9856a27b9 | |||
| b36b52ad57 | |||
| 1e60ccf49b | |||
|
|
9ca9439b9a | ||
| 6d30ae7e84 | |||
| 031e124663 | |||
| bb50c9fe18 | |||
| 8e608de501 | |||
|
|
8917b7736b | ||
| 18ff879f1d | |||
| c5a258d7be | |||
| 7525f1f71d | |||
| 3b665bdba0 | |||
| 99477364bd | |||
|
|
629fdf6d4c | ||
| 1288599b1f | |||
| be3a68fecb | |||
| 101e4da1d6 | |||
| 23430a609a | |||
| bb0d56e403 | |||
| d3b08bdf4f | |||
| e1ec501c55 | |||
| f92c3407f0 | |||
| b5971439b6 | |||
| 8ea8a2797a | |||
| b0f9222482 | |||
| 825ccc1031 | |||
| dab7a8a38a | |||
| 1dbc7ae5cd | |||
| 7038da568e | |||
| bfcaa26070 | |||
| f6488aecce | |||
| ad166e8012 | |||
| 2a76a414a0 | |||
| bb8ddf0bba | |||
| bf3e746010 |
2
.github/workflows/pre-commit-autoupdate.yml
vendored
2
.github/workflows/pre-commit-autoupdate.yml
vendored
@@ -13,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
23
.github/workflows/sync-labels.yml
vendored
Normal 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
|
||||
24
.gitmodules
vendored
24
.gitmodules
vendored
@@ -1,4 +1,4 @@
|
||||
# vim: set expandtab:
|
||||
# vim: noexpandtab filetype=gitconfig
|
||||
[submodule "dotbot"]
|
||||
path = tools/dotbot
|
||||
url = https://github.com/anishathalye/dotbot.git
|
||||
@@ -23,47 +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
|
||||
|
||||
@@ -23,7 +23,7 @@ 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.json, --fix]
|
||||
@@ -44,12 +44,12 @@ repos:
|
||||
- id: shfmt
|
||||
|
||||
- repo: https://github.com/rhysd/actionlint
|
||||
rev: v1.7.6
|
||||
rev: v1.7.7
|
||||
hooks:
|
||||
- id: actionlint
|
||||
|
||||
- repo: https://github.com/renovatebot/pre-commit-hooks
|
||||
rev: 39.100.1
|
||||
rev: 39.164.1
|
||||
hooks:
|
||||
- id: renovate-config-validator
|
||||
|
||||
|
||||
@@ -1 +1 @@
|
||||
3.13.1
|
||||
3.13.2
|
||||
|
||||
@@ -46,7 +46,7 @@ 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
|
||||
echo "Ignoring submodule changes for submodule.${MODULE}..."
|
||||
git config "submodule.${MODULE}.ignore" all
|
||||
git config "submodule.${MODULE}.ignore" "dirty"
|
||||
done
|
||||
|
||||
# Mark certain repositories shallow
|
||||
|
||||
6
base/ignore
Normal file
6
base/ignore
Normal file
@@ -0,0 +1,6 @@
|
||||
Applications/
|
||||
Library/
|
||||
Movies/
|
||||
Music/
|
||||
Pictures/
|
||||
Google Drive/
|
||||
@@ -43,14 +43,30 @@ automatically-unhide-macos-hidden-apps = true
|
||||
if.app-name-regex-substring = 'settings' # All settings
|
||||
run = ['layout floating']
|
||||
|
||||
[[on-window-detected]]
|
||||
if.app-id = 'com.apple.systempreferences' # macOS System Preferences
|
||||
run = ['layout floating']
|
||||
|
||||
[[on-window-detected]]
|
||||
if.app-id = 'com.1password.1password' # 1Password
|
||||
run = ['layout floating']
|
||||
|
||||
[[on-window-detected]]
|
||||
if.app-id = 'org.ferdium.ferdium-app' # Ferdium, has WhatsApp etc.
|
||||
run = ['layout floating']
|
||||
|
||||
[[on-window-detected]]
|
||||
if.app-id = 'com.jetbrains.PhpStorm' # PhpStorm
|
||||
run = ['layout floating']
|
||||
|
||||
[[on-window-detected]]
|
||||
if.app-id = 'com.apple.finder' # Finder
|
||||
run = ['layout floating']
|
||||
|
||||
[[on-window-detected]]
|
||||
if.app-id = 'com.apple.Preview' # Preview
|
||||
run = ['layout floating']
|
||||
|
||||
[[on-window-detected]]
|
||||
if.app-id = 'com.apple.mail' # Mail
|
||||
run = ['layout floating']
|
||||
@@ -87,6 +103,19 @@ run = ['layout floating']
|
||||
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
|
||||
[key-mapping]
|
||||
@@ -113,6 +142,9 @@ outer.left = 0
|
||||
# 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
|
||||
@@ -150,10 +182,10 @@ alt-l = 'focus right'
|
||||
# See: https://nikitabobko.github.io/AeroSpace/commands#workspace
|
||||
alt-shift-1 = 'workspace 1' # Main
|
||||
alt-shift-2 = 'workspace 2' # Media
|
||||
ctrl-shift-1 = 'move-node-to-workspace 1'
|
||||
ctrl-shift-2 = 'move-node-to-workspace 2'
|
||||
ctrl-shift-1 = 'move-node-to-workspace 1' # Move node to Main
|
||||
ctrl-shift-2 = 'move-node-to-workspace 2' # Move node to Media
|
||||
|
||||
alt-shift-tab = 'workspace-back-and-forth'
|
||||
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
|
||||
|
||||
22
config/alias
22
config/alias
@@ -12,8 +12,19 @@ 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'
|
||||
@@ -95,10 +106,13 @@ 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'
|
||||
|
||||
if [[ $(uname) == 'Darwin' ]]; then
|
||||
# Laravel artisan shortcut
|
||||
alias art='[ -f artisan ] && php artisan || php vendor/bin/artisan'
|
||||
|
||||
# Laravel Sail shortcut
|
||||
alias sail='[ -f sail ] && bash sail || bash vendor/bin/sail'
|
||||
# Laravel Sail shortcut
|
||||
alias sail='[ -f sail ] && bash sail || bash vendor/bin/sail'
|
||||
|
||||
if [[ $(uname) == 'Darwin' ]]; then
|
||||
|
||||
# Flush Directory Service cache
|
||||
alias flushdns="sudo dscacheutil -flushcache; sudo killall -HUP mDNSResponder"
|
||||
|
||||
@@ -469,11 +469,12 @@ export TF_PLUGIN_CACHE_DIR="$XDG_CACHE_HOME/terraform/plugin-cache"
|
||||
# https://tmux.github.io/
|
||||
msg "Setting up tmux configuration"
|
||||
export TMUX_TMPDIR="$XDG_STATE_HOME/tmux"
|
||||
export TMUX_PLUGINS="$XDG_CONFIG_HOME/tmux/plugins"
|
||||
export TMUX_CONF="$XDG_CONFIG_HOME/tmux/tmux.conf"
|
||||
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
|
||||
|
||||
@@ -61,30 +61,28 @@ brew "apr"
|
||||
brew "apr-util"
|
||||
# Password hashing library and CLI utility
|
||||
brew "argon2"
|
||||
# Automatic configure script builder
|
||||
brew "autoconf"
|
||||
# Tool for generating GNU Standards-compliant Makefiles
|
||||
brew "automake"
|
||||
# GNU multiple precision arithmetic library
|
||||
brew "gmp"
|
||||
# GNU File, Shell, and Text utilities
|
||||
brew "coreutils"
|
||||
# Extendable version manager with support for Ruby, Node.js, Erlang & more
|
||||
brew "asdf"
|
||||
# Spell checker with better logic than ispell
|
||||
brew "aspell"
|
||||
# Automatic configure script builder
|
||||
brew "autoconf"
|
||||
# Collection of over 500 reusable autoconf macros
|
||||
brew "autoconf-archive"
|
||||
# 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"
|
||||
# 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
|
||||
@@ -97,6 +95,8 @@ brew "fontconfig"
|
||||
brew "gettext"
|
||||
# Core application library for C
|
||||
brew "glib"
|
||||
# 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
|
||||
@@ -149,8 +149,6 @@ brew "unbound"
|
||||
brew "gnutls"
|
||||
# GNU Pretty Good Privacy (PGP) package
|
||||
brew "gnupg"
|
||||
# Open source programming language to build simple/reliable/efficient software
|
||||
brew "go"
|
||||
# Library access to GnuPG
|
||||
brew "gpgme"
|
||||
# Manage your GnuPG keys with ease!
|
||||
@@ -303,8 +301,6 @@ brew "shivammathur/php/php@7.4"
|
||||
brew "shivammathur/php/php@8.0", link: true
|
||||
# Find & fix known vulnerabilities in open-source dependencies
|
||||
brew "snyk/tap/snyk"
|
||||
# Command-line interface for 1Password
|
||||
cask "1password-cli"
|
||||
# AeroSpace is an i3-like tiling window manager for macOS
|
||||
cask "aerospace"
|
||||
# Text editor
|
||||
|
||||
@@ -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',
|
||||
|
||||
@@ -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',
|
||||
},
|
||||
|
||||
@@ -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'
|
||||
|
||||
@@ -54,6 +54,12 @@ 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
|
||||
@@ -69,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
|
||||
@@ -102,25 +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
|
||||
|
||||
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('pm', ':PhpactorContextMenu<cr>', 'PHPactor: Context Menu')
|
||||
K.nl('pn', ':PhpactorClassNew<cr>', 'PHPactor: Class New')
|
||||
K.nl('ps', ':PhpactorClassSearch<cr>', 'PHPactor: Class Search')
|
||||
K.nl('pt', ':PhpactorTransform<cr>', 'PHPactor: Transform')
|
||||
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')
|
||||
@@ -129,11 +134,7 @@ 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('sw', ':Telescope grep_string<cr>', 'Grep String')
|
||||
@@ -141,7 +142,7 @@ 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')
|
||||
@@ -169,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.
|
||||
|
||||
@@ -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
|
||||
@@ -27,6 +28,8 @@ g.loaded_java_provider = 0 -- Disable java provider
|
||||
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
|
||||
@@ -40,20 +43,24 @@ o.splitright = true -- vsplit to the right
|
||||
o.termguicolors = true -- Enable GUI colors
|
||||
o.timeoutlen = 250 -- Decrease mapped sequence wait time
|
||||
o.updatetime = 250 -- 250 ms = 2,5 seconds
|
||||
o.sessionoptions =
|
||||
'buffers,curdir,folds,tabpages,winsize,winpos,terminal,localoptions'
|
||||
|
||||
-- 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
|
||||
|
||||
@@ -18,11 +18,14 @@ return {
|
||||
},
|
||||
},
|
||||
|
||||
{ 'L3MON4D3/LuaSnip', version = 'v2.*' },
|
||||
{ '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
|
||||
@@ -50,7 +53,6 @@ return {
|
||||
},
|
||||
},
|
||||
---@module 'blink.cmp'
|
||||
---@type blink.cmp.Config
|
||||
opts = {
|
||||
snippets = { preset = 'luasnip' },
|
||||
-- 'default' for mappings similar to built-in completion
|
||||
|
||||
@@ -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',
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
@@ -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 = {},
|
||||
@@ -27,12 +28,8 @@ local lsp_servers = {
|
||||
},
|
||||
html = {},
|
||||
intelephense = {
|
||||
commands = {
|
||||
IntelephenseIndex = {
|
||||
function()
|
||||
vim.lsp.buf.execute_command { command = 'intelephense.index.workspace' }
|
||||
end,
|
||||
},
|
||||
init_options = {
|
||||
licenceKey = GetIntelephenseLicense(),
|
||||
},
|
||||
},
|
||||
jsonls = {},
|
||||
@@ -45,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
|
||||
@@ -58,7 +49,7 @@ local lsp_servers = {
|
||||
},
|
||||
},
|
||||
hint = {
|
||||
enable = false,
|
||||
enable = true,
|
||||
arrayIndex = 'Auto',
|
||||
await = true,
|
||||
paramName = 'All',
|
||||
@@ -113,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
|
||||
@@ -135,113 +148,61 @@ 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',
|
||||
},
|
||||
'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 = {
|
||||
'actionlint',
|
||||
'editorconfig-checker',
|
||||
'goimports',
|
||||
'gotests',
|
||||
'phpcbf',
|
||||
'phpmd',
|
||||
'phpstan',
|
||||
'pint',
|
||||
'prettierd',
|
||||
'semgrep',
|
||||
'shellcheck',
|
||||
'shfmt',
|
||||
'staticcheck',
|
||||
'stylua',
|
||||
'trivy',
|
||||
'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)
|
||||
@@ -301,30 +262,39 @@ return {
|
||||
}
|
||||
|
||||
-- Diagnostic configuration
|
||||
vim.diagnostic.config {
|
||||
virtual_text = false,
|
||||
float = {
|
||||
source = true,
|
||||
},
|
||||
local signs = {
|
||||
{ name = 'DiagnosticSignError', text = '' }, -- Error icon
|
||||
{ name = 'DiagnosticSignWarn', text = '' }, -- Warning icon
|
||||
{ name = 'DiagnosticSignHint', text = '' }, -- Hint icon
|
||||
{ name = 'DiagnosticSignInfo', text = '' }, -- Information icon
|
||||
}
|
||||
|
||||
-- Sign configuration
|
||||
vim.fn.sign_define(
|
||||
'DiagnosticSignError',
|
||||
{ text = '', texthl = 'DiagnosticSignError' }
|
||||
)
|
||||
vim.fn.sign_define(
|
||||
'DiagnosticSignWarn',
|
||||
{ text = '', texthl = 'DiagnosticSignWarn' }
|
||||
)
|
||||
vim.fn.sign_define(
|
||||
'DiagnosticSignInfo',
|
||||
{ text = '', texthl = 'DiagnosticSignInfo' }
|
||||
)
|
||||
vim.fn.sign_define(
|
||||
'DiagnosticSignHint',
|
||||
{ text = '', texthl = 'DiagnosticSignHint' }
|
||||
)
|
||||
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,
|
||||
@@ -336,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
|
||||
@@ -361,9 +321,9 @@ return {
|
||||
lsp_format_opt = 'fallback'
|
||||
end
|
||||
|
||||
-- Disable autoformat for files in a certain path
|
||||
-- Disable autoformat for files in a certain paths
|
||||
local bufname = vim.api.nvim_buf_get_name(bufnr)
|
||||
if bufname:match '/node_modules/' then return end
|
||||
if bufname:match '/node_modules|vendor/' then return end
|
||||
|
||||
return {
|
||||
timeout_ms = 500,
|
||||
|
||||
@@ -82,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' },
|
||||
@@ -164,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
|
||||
@@ -222,11 +209,11 @@ 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 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 = 120 }
|
||||
local location = sl.section_location { trunc_width = 75 }
|
||||
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 } },
|
||||
|
||||
@@ -3,8 +3,6 @@ return {
|
||||
'rmagatti/auto-session',
|
||||
lazy = false,
|
||||
version = '*',
|
||||
---@module "auto-session"
|
||||
---@type AutoSession.Config
|
||||
opts = {
|
||||
suppressed_dirs = {
|
||||
'/',
|
||||
@@ -12,6 +10,28 @@ return {
|
||||
'~/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',
|
||||
},
|
||||
},
|
||||
|
||||
@@ -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,
|
||||
},
|
||||
},
|
||||
},
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -7,121 +7,6 @@ return {
|
||||
init = function() vim.cmd.colorscheme(vim.g.colors_theme) end,
|
||||
opts = {
|
||||
transparent = true,
|
||||
on_colors = function(colors)
|
||||
colors.gitSigns = {
|
||||
add = colors.teal,
|
||||
change = colors.purple,
|
||||
delete = colors.red,
|
||||
}
|
||||
end,
|
||||
on_highlights = function(hl, c)
|
||||
local util = require 'tokyonight.util'
|
||||
local prompt = '#2d3149'
|
||||
|
||||
hl.NeoTreeFileNameOpened = {
|
||||
fg = c.orange,
|
||||
}
|
||||
|
||||
hl.GitSignsCurrentLineBlame = {
|
||||
fg = c.fg_gutter,
|
||||
}
|
||||
|
||||
hl.StatusLine = {
|
||||
bg = util.darken(c.bg_dark, 0.98, '#000000'),
|
||||
fg = c.fg_dark,
|
||||
}
|
||||
hl.StatusLineComment = {
|
||||
bg = util.darken(c.bg_dark, 0.85, '#000000'),
|
||||
fg = c.comment,
|
||||
}
|
||||
|
||||
hl.LineNrAbove = {
|
||||
fg = c.fg_gutter,
|
||||
}
|
||||
hl.LineNr = {
|
||||
fg = util.lighten(c.fg_gutter, 0.7),
|
||||
}
|
||||
hl.LineNrBelow = {
|
||||
fg = c.fg_gutter,
|
||||
}
|
||||
|
||||
hl.MsgArea = {
|
||||
bg = util.darken(c.bg_dark, 0.85, '#000000'),
|
||||
}
|
||||
|
||||
-- Spelling
|
||||
hl.SpellBad = {
|
||||
undercurl = true,
|
||||
sp = '#7F3A43',
|
||||
}
|
||||
|
||||
-- Telescope
|
||||
hl.TelescopeNormal = {
|
||||
bg = c.bg_dark,
|
||||
fg = c.fg_dark,
|
||||
}
|
||||
hl.TelescopeBorder = {
|
||||
bg = c.bg_dark,
|
||||
fg = c.bg_dark,
|
||||
}
|
||||
hl.TelescopePromptNormal = {
|
||||
bg = prompt,
|
||||
}
|
||||
hl.TelescopePromptBorder = {
|
||||
bg = prompt,
|
||||
fg = prompt,
|
||||
}
|
||||
hl.TelescopePromptTitle = {
|
||||
bg = c.bg,
|
||||
fg = c.fg_dark,
|
||||
}
|
||||
hl.TelescopePreviewTitle = {
|
||||
bg = c.bg_dark,
|
||||
fg = c.bg_dark,
|
||||
}
|
||||
hl.TelescopeResultsTitle = {
|
||||
bg = c.bg_dark,
|
||||
fg = c.bg_dark,
|
||||
}
|
||||
|
||||
-- Indent
|
||||
hl.MiniIndentscopeSymbol = {
|
||||
fg = util.darken(c.bg_highlight, 0.30),
|
||||
}
|
||||
hl.IblScope = {
|
||||
fg = util.darken(c.bg_highlight, 0.80),
|
||||
}
|
||||
|
||||
-- Floaterm
|
||||
hl.Floaterm = {
|
||||
bg = prompt,
|
||||
}
|
||||
hl.FloatermBorder = {
|
||||
bg = prompt,
|
||||
fg = prompt,
|
||||
}
|
||||
|
||||
-- Copilot
|
||||
hl.CopilotSuggestion = {
|
||||
fg = c.comment,
|
||||
}
|
||||
|
||||
-- NeoTree
|
||||
hl.NeoTreeFileNameOpened = {
|
||||
fg = c.fg,
|
||||
bold = true,
|
||||
}
|
||||
hl.NvimTreeNormal = {
|
||||
bg = util.darken(c.bg_dark, 0.85, '#000000'),
|
||||
}
|
||||
hl.NvimTreeNormalNC = {
|
||||
bg = util.darken(c.bg_dark, 0.85, '#000000'),
|
||||
}
|
||||
hl.NvimTreeWinSeparator = {
|
||||
fg = util.darken(c.bg_dark, 0.85, '#000000'),
|
||||
bg = util.darken(c.bg_dark, 0.85, '#000000'),
|
||||
}
|
||||
end,
|
||||
},
|
||||
},
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
1
config/tmux/.ignore
Normal file
@@ -0,0 +1 @@
|
||||
plugins/*
|
||||
37
config/tmux/config-keybinds.conf
Normal file
37
config/tmux/config-keybinds.conf
Normal 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
|
||||
50
config/tmux/config-plugins.conf
Normal file
50
config/tmux/config-plugins.conf
Normal 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
|
||||
40
config/tmux/config-settings.conf
Normal file
40
config/tmux/config-settings.conf
Normal 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
|
||||
16
config/tmux/config-themes.conf
Normal file
16
config/tmux/config-themes.conf
Normal 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
|
||||
28
config/tmux/rename-session.sh
Executable file
28
config/tmux/rename-session.sh
Executable 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
16
config/tmux/theme-activate.sh
Executable 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"
|
||||
@@ -4,149 +4,22 @@
|
||||
# - https://tmuxguide.readthedocs.io/en/latest/tmux/tmux.html
|
||||
# - https://github.com/dreamsofcode-io/tmux/blob/main/tmux.conf
|
||||
|
||||
# ╭──────────────────────────────────────────────────────────╮
|
||||
# │ 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.
|
||||
# Load the configuration settings
|
||||
source-file "$TMUX_CONF_DIR/config-settings.conf"
|
||||
|
||||
set -g default-terminal "tmux-256color"
|
||||
# set -ag terminal-overrides ",xterm-256color:RGB"
|
||||
# Load the theme settings
|
||||
source-file "$TMUX_CONF_DIR/config-themes.conf"
|
||||
|
||||
# undercurl
|
||||
set -as terminal-overrides ',*:Smulx=\E[4::%p1%dm' # undercurl support
|
||||
set -as terminal-overrides ',*:Setulc=\E[58::2::::%p1%{65536}%/%d::%p1%{256}%/%{255}%&%d::%p1%{255}%&%d%;m' # underscore colors - needs tmux-3.0
|
||||
# Load the keybindings
|
||||
source-file "$TMUX_CONF_DIR/config-keybinds.conf"
|
||||
|
||||
# Enable hyperlinks
|
||||
# set -as terminal-overrides ',*:Hls=\E]8;id=%p1%s;%p2%s\E\\:Hlr=\E]8;;\E\\''
|
||||
# Load the plugins and plugin settings
|
||||
source-file "$TMUX_CONF_DIR/config-plugins.conf"
|
||||
|
||||
set -g status-keys vi # vi keys to move between panes
|
||||
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 set-titles on # Expose window title
|
||||
set -g status "on" # Setting status on
|
||||
# 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"
|
||||
|
||||
# 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
|
||||
|
||||
# ╭──────────────────────────────────────────────────────────╮
|
||||
# │ 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 '
|
||||
|
||||
# ╭──────────────────────────────────────────────────────────╮
|
||||
# │ 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 '~/.dotfiles/config/tmux/theme-light.conf'
|
||||
set -g @dark-notify-theme-path-dark '~/.dotfiles/config/tmux/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'
|
||||
|
||||
# ╭──────────────────────────────────────────────────────────╮
|
||||
# │ 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-Down select-pane -D
|
||||
bind -n M-Left select-pane -L
|
||||
bind -n M-Right select-pane -R
|
||||
bind -n M-Up select-pane -U
|
||||
|
||||
# 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
|
||||
|
||||
# ╭──────────────────────────────────────────────────────────╮
|
||||
# │ 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-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
|
||||
run-shell ~/.dotfiles/config/tmux/plugins/tmux-fzf-url/fzf-url.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"
|
||||
# If we started tmux with a session name, rename it.
|
||||
run-shell "$TMUX_CONF_DIR/rename-session.sh"
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -1,8 +1,11 @@
|
||||
{
|
||||
"telemetry": {
|
||||
"metrics": false
|
||||
},
|
||||
"assistant": {
|
||||
"default_model": {
|
||||
"provider": "copilot_chat",
|
||||
"model": "gpt-4o"
|
||||
"model": "claude-3-5-sonnet"
|
||||
},
|
||||
"version": "2"
|
||||
},
|
||||
|
||||
66
docs/aerospace-keybindings.md
Normal file
66
docs/aerospace-keybindings.md
Normal 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
52
docs/alias.md
Normal 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
|
||||
@@ -54,7 +54,7 @@ n <Space>xq * :Trouble quickfix<CR>
|
||||
Quickfix
|
||||
n <Space>xl * :Trouble loclist<CR>
|
||||
Location List
|
||||
n <Space>xd * :Trouble document_diagnostics<CR>
|
||||
n <Space>xd * :Trouble diagnostics<CR>
|
||||
Document Diagnostics
|
||||
n <Space>sx * :Telescope import<CR>
|
||||
Telescope: Import
|
||||
@@ -64,7 +64,7 @@ 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
|
||||
@@ -80,14 +80,6 @@ n <Space>sd * :Telescope diagnostics<CR>
|
||||
Search Diagnostics
|
||||
n <Space>sc * :Telescope commands<CR>
|
||||
Commands
|
||||
n <Space>pt * :PhpactorTransform<CR>
|
||||
PHPactor: Transform
|
||||
n <Space>ps * :PhpactorClassSearch<CR>
|
||||
PHPactor: Class Search
|
||||
n <Space>pn * :PhpactorClassNew<CR>
|
||||
PHPactor: Class New
|
||||
n <Space>pm * :PhpactorContextMenu<CR>
|
||||
PHPactor: Context Menu
|
||||
n <Space>/ * ~/.config/nvim/lua/keymaps.lua
|
||||
Fuzzily search in current buffer
|
||||
n <Space>, * :Telescope buffers<CR>
|
||||
@@ -104,37 +96,33 @@ 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
|
||||
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>
|
||||
x <Space>cf * :lua vim.lsp.buf.format()<CR>
|
||||
Format
|
||||
n <Space>cf * :lua vim.lsp.buf.format()<CR>
|
||||
Format
|
||||
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>bw * :lua MiniBufremove.wipeout()<CR>
|
||||
Wipeout
|
||||
@@ -150,6 +138,14 @@ 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>
|
||||
@@ -184,8 +180,6 @@ 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'
|
||||
<Space>cf * ~/.local/share/nvim/lazy/lazy.nvim/lua/lazy/core/handler/keys.lua
|
||||
Format buffer
|
||||
x # * vim/_defaults.lua
|
||||
:help v_#-default
|
||||
o % <Plug>(MatchitOperationForward)
|
||||
@@ -194,17 +188,11 @@ 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>30_:.Start!
|
||||
n '<Space> & <SNR>30_:.Start<Space>
|
||||
n '<CR> & <SNR>30_:.Start<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.nvim/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
|
||||
@@ -217,31 +205,19 @@ n @ * ~/.local/share/nvim/lazy/mini.nvim/lua/mini/clue.lua
|
||||
Execute macro without 'mini.clue' triggers
|
||||
x @ * mode() ==# 'V' ? ':normal! @'.getcharstr().'<CR>' : '@'
|
||||
:help v_@-default
|
||||
o F * ~/.local/share/nvim/lazy/mini.nvim/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.nvim/lua/mini/clue.lua
|
||||
Execute macro without 'mini.clue' triggers
|
||||
x Q * mode() ==# 'V' ? ':normal! @<C-R>=reg_recorded()<CR><CR>' : 'Q'
|
||||
:help v_Q-default
|
||||
o T * ~/.local/share/nvim/lazy/mini.nvim/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
|
||||
o Zk * ~/.local/share/nvim/lazy/lazy.nvim/lua/lazy/core/handler/keys.lua
|
||||
x Zk * ~/.config/nvim/lua/keymaps.lua
|
||||
Flash Treesitter
|
||||
x 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)
|
||||
@@ -289,10 +265,10 @@ n ]h * <Cmd>lua MiniDiff.goto_hunk('next')<CR>
|
||||
Next hunk
|
||||
n ]d * vim/_defaults.lua
|
||||
Jump to the next diagnostic
|
||||
n `? & <SNR>30_:.FocusDispatch<CR>
|
||||
n `! & <SNR>30_:.Dispatch!
|
||||
n `<Space> & <SNR>30_:.Dispatch<Space>
|
||||
n `<CR> & <SNR>30_:.Dispatch<CR>
|
||||
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)
|
||||
@@ -300,25 +276,19 @@ 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.nvim/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)
|
||||
n g`? & :<C-U>echo ":Spawn" dispatch#spawn_focus(v:count > 1 ? 0 : v:count ? line(".") : -1)<CR>
|
||||
n g`! & <SNR>30_:.Spawn!
|
||||
n g`<Space> & <SNR>30_:.Spawn<Space>
|
||||
n g`<CR> & <SNR>30_:.Spawn<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>30_:.Spawn!
|
||||
n g'<Space> & <SNR>30_:.Spawn<Space>
|
||||
n g'<CR> & <SNR>30_:.Spawn<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") . " "
|
||||
@@ -400,9 +370,9 @@ x k * v:count == 0 ? 'gk' : 'k'
|
||||
n k * v:count == 0 ? 'gk' : 'k'
|
||||
Move up
|
||||
n m? & :<C-U>echo ":Dispatch" dispatch#make_focus(v:count > 1 ? 0 : v:count ? line(".") : -1)<CR>
|
||||
n m! & <SNR>30_:.Make!
|
||||
n m<Space> & <SNR>30_:.Make<Space>
|
||||
n m<CR> & <SNR>30_:.Make<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.nvim/lua/mini/surround.lua
|
||||
@@ -439,17 +409,11 @@ n sd * ~/.local/share/nvim/lazy/mini.nvim/lua/mini/surround.lua
|
||||
Delete surrounding
|
||||
n sa * ~/.local/share/nvim/lazy/mini.nvim/lua/mini/surround.lua
|
||||
Add surrounding
|
||||
o t * ~/.local/share/nvim/lazy/mini.nvim/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
|
||||
o zk * ~/.local/share/nvim/lazy/lazy.nvim/lua/lazy/core/handler/keys.lua
|
||||
o zk * ~/.config/nvim/lua/keymaps.lua
|
||||
Flash
|
||||
x zk * ~/.local/share/nvim/lazy/lazy.nvim/lua/lazy/core/handler/keys.lua
|
||||
x zk * ~/.config/nvim/lua/keymaps.lua
|
||||
Flash
|
||||
n zk * ~/.local/share/nvim/lazy/lazy.nvim/lua/lazy/core/handler/keys.lua
|
||||
n zk * ~/.config/nvim/lua/keymaps.lua
|
||||
Flash
|
||||
n <F1> * :FloatermToggle<CR>
|
||||
Toggle Floaterm
|
||||
@@ -492,30 +456,30 @@ 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 <SNR>30_:. & :<C-R>=getcmdline() =~ ',' ? "\0250" : ""<CR>
|
||||
o <Plug>(textobj-xmlattr-attr-i) & <SNR>26_(save-cursor-pos):<C-U>call g:__textobj_xmlattr.do_by_pattern("select","attr-i","o")<CR>
|
||||
v <Plug>(textobj-xmlattr-attr-i) & <SNR>26_(save-cursor-pos):<C-U>call g:__textobj_xmlattr.do_by_pattern("select","attr-i","v")<CR>
|
||||
o <Plug>(textobj-xmlattr-attr-a) & <SNR>26_(save-cursor-pos):<C-U>call g:__textobj_xmlattr.do_by_pattern("select","attr-a","o")<CR>
|
||||
v <Plug>(textobj-xmlattr-attr-a) & <SNR>26_(save-cursor-pos):<C-U>call g:__textobj_xmlattr.do_by_pattern("select","attr-a","v")<CR>
|
||||
n <SNR>26_ * <SNR>26_
|
||||
<SNR>26_(save-cursor-pos) * <SNR>26_save_cursor_pos()
|
||||
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>
|
||||
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
|
||||
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>
|
||||
@@ -528,4 +492,4 @@ n <C-L> * :lua vim.lsp.buf.signature_help()<CR>
|
||||
Signature
|
||||
```
|
||||
|
||||
- Generated on Tue 7 Jan 2025 21:37:18 EET
|
||||
- Generated on Tue 21 Jan 2025 15:24:13 EET
|
||||
|
||||
@@ -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 |
|
||||
|
||||
125
local/bin/dfm
125
local/bin/dfm
@@ -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`
|
||||
@@ -18,8 +19,7 @@ SCRIPT=$(basename "$0")
|
||||
source "$DOTFILES/config/shared.sh"
|
||||
source "${DOTFILES}/local/bin/msgr"
|
||||
|
||||
# -- Menu builder -- #
|
||||
|
||||
# Menu builder
|
||||
menu_builder()
|
||||
{
|
||||
local title=$1
|
||||
@@ -35,54 +35,6 @@ menu_builder()
|
||||
local desc=${cmd#*:}
|
||||
printf " %-20s %s\n" "$name" "$desc"
|
||||
done
|
||||
# printf "\n"
|
||||
}
|
||||
|
||||
menu_section()
|
||||
{
|
||||
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"
|
||||
}
|
||||
|
||||
# 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=("$@")
|
||||
|
||||
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"
|
||||
done
|
||||
}
|
||||
|
||||
section_install()
|
||||
@@ -480,10 +432,11 @@ 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"
|
||||
'path:Show $PATH dir by dir'
|
||||
"tmux:Show tmux keybindings"
|
||||
@@ -542,6 +495,7 @@ section_helpers()
|
||||
|
||||
"env") env | sort ;;
|
||||
"functions") declare -F ;;
|
||||
"aerospace") cat "$DOTFILES/docs/aerospace-keybindings.md" ;;
|
||||
"nvim") cat "$DOTFILES/docs/nvim-keybindings.md" ;;
|
||||
"tmux") cat "$DOTFILES/docs/tmux-keybindings.md" ;;
|
||||
"wezterm") cat "$DOTFILES/docs/wezterm-keybindings.md" ;;
|
||||
@@ -549,12 +503,76 @@ section_helpers()
|
||||
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"
|
||||
@@ -562,10 +580,12 @@ section_docs()
|
||||
|
||||
case "$1" in
|
||||
all)
|
||||
$0 docs aerospace
|
||||
$0 docs tmux
|
||||
$0 docs nvim
|
||||
$0 docs wezterm
|
||||
;;
|
||||
aerospace) bash "$DOTFILES/scripts/create-aerospace-keymaps.php" ;;
|
||||
tmux) bash "$DOTFILES/local/bin/x-dfm-docs-xterm-keybindings" ;;
|
||||
nvim) bash "$DOTFILES/scripts/create-nvim-keymaps.sh" ;;
|
||||
wezterm) bash "$DOTFILES/scripts/create-wezterm-keymaps.sh" ;;
|
||||
@@ -756,6 +776,8 @@ usage()
|
||||
echo ""
|
||||
section_install
|
||||
echo ""
|
||||
section_apt
|
||||
echo ""
|
||||
section_asdf
|
||||
echo ""
|
||||
section_brew
|
||||
@@ -778,6 +800,7 @@ 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 "$@" ;;
|
||||
|
||||
@@ -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 "$@"
|
||||
|
||||
134
local/bin/t
134
local/bin/t
@@ -1,45 +1,143 @@
|
||||
#!/usr/bin/env bash
|
||||
#
|
||||
# Credit to ThePrimeagen, jessarcher
|
||||
# https://github.com/jessarcher/dotfiles/blob/master/scripts/t
|
||||
# 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()
|
||||
{
|
||||
error_exit() {
|
||||
echo "Error: $1" >&2
|
||||
exit 1
|
||||
}
|
||||
|
||||
# Select the directory
|
||||
# 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
|
||||
items=$(find "$T_ROOT" -maxdepth 2 -mindepth 1 -type d)
|
||||
items+="$(printf "\n%s" "$DOTFILES")"
|
||||
items+="$(printf "\n/tmp")"
|
||||
selected=$(echo -e "$items" | fzf) || exit 0 # Exit if no selection is made
|
||||
# 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
|
||||
|
||||
# Exit if no directory was selected
|
||||
[[ -z $selected ]] && error_exit "No directory selected."
|
||||
# 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
|
||||
dirname=$(basename "$selected" | tr '.' '_')
|
||||
session_name=$(basename "$selected")
|
||||
if [[ -z "$session_name" ]]; then
|
||||
session_name="$selected"
|
||||
fi
|
||||
# Remove dots since tmux dislikes them
|
||||
session_name="${session_name//./}"
|
||||
|
||||
# Try to switch to the tmux session
|
||||
if tmux switch-client -t "=$dirname" 2> /dev/null; then
|
||||
# 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 tmux session or attach to an existing one
|
||||
if tmux new-session -c "$selected" -d -s "$dirname" 2> /dev/null; then
|
||||
tmux switch-client -t "$dirname"
|
||||
# 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
|
||||
tmux new -c "$selected" -A -s "$dirname"
|
||||
# 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
54
local/bin/x-clean-vendordirs
Executable 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"
|
||||
226
local/bin/x-env-list
Executable file
226
local/bin/x-env-list
Executable 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
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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 "$@"
|
||||
|
||||
@@ -6,11 +6,12 @@
|
||||
# License: MIT
|
||||
|
||||
VERSION="1.0.0"
|
||||
SCRIPT_NAME="$(basename "$0")"
|
||||
|
||||
# Function to display usage
|
||||
usage()
|
||||
{
|
||||
echo "Usage: x-localip [options] [interface]"
|
||||
echo "Usage: $SCRIPT_NAME [options] [interface]"
|
||||
echo "Options:"
|
||||
echo " --help Show this help message"
|
||||
echo " --version Show version information"
|
||||
@@ -31,7 +32,7 @@ while [[ $# -gt 0 ]]; do
|
||||
exit 0
|
||||
;;
|
||||
--version)
|
||||
echo "x-localip version $VERSION"
|
||||
echo "$SCRIPT_NAME version $VERSION"
|
||||
exit 0
|
||||
;;
|
||||
--ipv4)
|
||||
|
||||
183
local/bin/x-multi-ping
Executable file
183
local/bin/x-multi-ping
Executable 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
|
||||
@@ -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
281
local/bin/x-path
Executable 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
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
#!/usr/bin/env sh
|
||||
#!/usr/bin/env bash
|
||||
#
|
||||
# DESCRIPTION:
|
||||
# Simple recording tool and wrapper around giph (ffmpeg).
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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 "$@"
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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...
|
||||
#
|
||||
|
||||
@@ -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...
|
||||
#
|
||||
|
||||
67
scripts/create-aerospace-keymaps.php
Executable file
67
scripts/create-aerospace-keymaps.php
Executable 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);
|
||||
@@ -26,7 +26,7 @@ msgr nested "Change user shell to zsh if it is available and not the current"
|
||||
|
||||
# Change user shell to zsh if not that already.
|
||||
if hash zsh 2> /dev/null; then
|
||||
[[ "$SHELL" != $(which zsh) ]] && chsh -s "$(which zsh)"
|
||||
[[ $SHELL != $(which zsh) ]] && chsh -s "$(which zsh)"
|
||||
fi
|
||||
|
||||
###############################################################################
|
||||
@@ -150,7 +150,7 @@ msgr nested "Settings for Finder"
|
||||
# Set Desktop as the default location for new Finder windows
|
||||
# For other paths, use `PfLo` and `file:///full/path/here/`
|
||||
defaults write com.apple.finder NewWindowTarget -string "PfDe"
|
||||
defaults write com.apple.finder NewWindowTargetPath -string "file://${HOME}/Desktop/"
|
||||
defaults write com.apple.finder NewWindowTargetPath -string "file://${HOME}/"
|
||||
|
||||
# Show icons for external hard drives, servers, and removable media on the desktop
|
||||
defaults write com.apple.finder ShowExternalHardDrivesOnDesktop -bool true
|
||||
@@ -201,6 +201,10 @@ defaults write com.apple.finder FXInfoPanesExpanded -dict \
|
||||
OpenWith -bool true \
|
||||
Privileges -bool true
|
||||
|
||||
# Move windows by dragging any part of the window
|
||||
# From https://nikitabobko.github.io/AeroSpace/goodies
|
||||
defaults write -g NSWindowShouldDragOnGesture -bool true
|
||||
|
||||
###############################################################################
|
||||
# Screenshots #
|
||||
###############################################################################
|
||||
|
||||
86
scripts/update-readme-aliases.sh
Executable file
86
scripts/update-readme-aliases.sh
Executable file
@@ -0,0 +1,86 @@
|
||||
#!/usr/bin/env bash
|
||||
# update-readme-aliases.sh
|
||||
# @description Update alias documentation in $DOTFILES/docs/alias.md
|
||||
#
|
||||
# Author: Ismo Vuorinen <https://github.com/ivuorinen> 2025
|
||||
# License: MIT
|
||||
|
||||
set -euo pipefail
|
||||
|
||||
# Paths
|
||||
ALIAS_FILE="$DOTFILES/config/alias"
|
||||
OUTPUT_FILE="$DOTFILES/docs/alias.md"
|
||||
|
||||
# Check if alias file exists
|
||||
if [[ ! -f $ALIAS_FILE ]]; then
|
||||
echo "Alias file not found: $ALIAS_FILE"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Declare associative array
|
||||
declare -a alias_table
|
||||
|
||||
echo "Parsing aliases..."
|
||||
while IFS= read -r line; do
|
||||
# Skip all lines that do not start with 'alias'
|
||||
if [[ ! $line =~ ^alias\ ]]; then
|
||||
continue
|
||||
fi
|
||||
|
||||
# Split alias and command and handle both ' and "
|
||||
if [[ $line =~ ^alias\ ([^=]+)=[\'\"](.*)[\'\"]$ ]]; then
|
||||
alias_name="${BASH_REMATCH[1]}"
|
||||
alias_command="${BASH_REMATCH[2]//|/\\|}" # fix markdown table separator
|
||||
|
||||
# Save alias to table
|
||||
alias_table+=("\`$alias_name\`␟\`$alias_command\`")
|
||||
else
|
||||
echo "Warning: Could not parse line: $line"
|
||||
fi
|
||||
|
||||
done < "$ALIAS_FILE"
|
||||
|
||||
# Sort array by alias name
|
||||
# shellcheck disable=SC2207
|
||||
IFS=$'\n' sorted_aliases=($(sort <<< "${alias_table[*]}"))
|
||||
unset IFS
|
||||
|
||||
# Calculate cell max lengths
|
||||
max_alias_length=5 # "Alias" min length
|
||||
max_command_length=7 # "Command" min length
|
||||
|
||||
for entry in "${sorted_aliases[@]}"; do
|
||||
IFS=$'␟' read -r alias_name alias_command <<< "$entry"
|
||||
max_alias_length=$((${#alias_name} > max_alias_length ? ${#alias_name} : max_alias_length))
|
||||
max_command_length=$((${#alias_command} > max_command_length ? ${#alias_command} : max_command_length))
|
||||
done
|
||||
|
||||
# Empty the markdown file and add header
|
||||
printf "# Alias Commands\n\nThis file lists all aliases defined in \`config/alias\`.\n\n" > "$OUTPUT_FILE"
|
||||
|
||||
# Add table header
|
||||
printf "| %-*s | %-*s |\n" \
|
||||
"$max_alias_length" "Alias" \
|
||||
"$max_command_length" "Command" >> "$OUTPUT_FILE"
|
||||
|
||||
# Add table header separator
|
||||
printf "| %-*s | %-*s |\n" \
|
||||
"$max_alias_length" "$(printf '%0.s-' $(seq 1 $max_alias_length))" \
|
||||
"$max_command_length" "$(printf '%0.s-' $(seq 1 $max_command_length))" >> "$OUTPUT_FILE"
|
||||
|
||||
# Create table with max cell lengths
|
||||
for entry in "${sorted_aliases[@]}"; do
|
||||
IFS=$'␟' read -r alias_name alias_command <<< "$entry"
|
||||
printf "| %-*s | %-*s |\n" \
|
||||
"$max_alias_length" "$alias_name" \
|
||||
"$max_command_length" "$alias_command" >> "$OUTPUT_FILE"
|
||||
done
|
||||
|
||||
{
|
||||
printf "\n"
|
||||
printf "Total aliases: %d\n" "${#sorted_aliases[@]}"
|
||||
printf "Last updated: %s\n" "$(date)"
|
||||
} >> "$OUTPUT_FILE"
|
||||
|
||||
# Announce process completion
|
||||
echo "Alias documentation updated: $OUTPUT_FILE"
|
||||
@@ -1,7 +1,9 @@
|
||||
# vim: ft=sshconfig
|
||||
Include shared.d/*
|
||||
Include local.d/*
|
||||
|
||||
Host *
|
||||
ServerAliveInterval 300 # send null packets every 5min to keep connection alive
|
||||
ServerAliveCountMax 2 # if the server doesn't respond 2 times, it's gone so give up
|
||||
# IdentityAgent "~/Library/Group Containers/2BUA8C4S2C.com.1password/t/agent.sock"
|
||||
ForwardAgent yes
|
||||
# IdentityAgent "~/Library/Group Containers/2BUA8C4S2C.com.1password/t/agent.sock"
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
# vim: ft=sshconfig
|
||||
|
||||
Host t1
|
||||
User ubuntu
|
||||
HostName t1.home.antiprocess.net
|
||||
@@ -14,4 +16,3 @@ Host t4
|
||||
User ubuntu
|
||||
HostName t4.home.antiprocess.net
|
||||
IdentityFile ~/.ssh/id_rsa
|
||||
|
||||
|
||||
1
tools/apt.txt
Normal file
1
tools/apt.txt
Normal file
@@ -0,0 +1 @@
|
||||
# apt install list
|
||||
Reference in New Issue
Block a user