mirror of
https://github.com/ivuorinen/dotfiles.git
synced 2026-01-27 22:45:27 +00:00
Compare commits
59 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
ee47821089 | ||
|
|
b834ce04f7 | ||
|
|
6a62d73d7f | ||
|
|
440842ed34 | ||
|
|
d0563e4a29 | ||
|
|
bc404bfbea | ||
| 923f881725 | |||
| ccc5903290 | |||
|
|
786efc48fa | ||
| 2a11a28422 | |||
| 812a27ea61 | |||
| e73e61f01b | |||
| 314679b4fc | |||
|
|
516b27384a | ||
|
|
9e1af3053d | ||
|
|
9e4f8741b3 | ||
| c0995c1b49 | |||
| c9f1e824c3 | |||
| 3d301daeb1 | |||
| 8b4198dc90 | |||
| 66461f9b1b | |||
| 80851d1efd | |||
|
|
c457c0f3ab | ||
| 9936e4bd76 | |||
| c3a45e2653 | |||
| 506360a027 | |||
|
|
00074ec3ff | ||
|
|
7c7daf89ea | ||
|
|
267c54aa56 | ||
|
|
d72409efc0 | ||
| 3d9e0477b0 | |||
| cfab48eee0 | |||
| 624920b2ab | |||
|
|
fd82f1e36c | ||
|
|
48ec8cd7a7 | ||
|
|
3a61bd2b72 | ||
| 895b0ad353 | |||
| 3c733ec7eb | |||
| 5321ad7bd7 | |||
| 196077bea9 | |||
|
|
75147c7dd6 | ||
| f28ad41f67 | |||
| 61b66d3114 | |||
| 282f760a4f | |||
| 4a9c9b4cb9 | |||
| 16311ee5b4 | |||
| 2fddfa82c0 | |||
| 8f5f44db2d | |||
| 8ad1f5c4d0 | |||
| ac0aa1fbc0 | |||
| e8c6794ff6 | |||
| 4de9a649f0 | |||
|
|
e7f115680e | ||
| f3b4551d0c | |||
| 64725c57dc | |||
| b32ee414e3 | |||
|
|
6ea7807718 | ||
| 6a776bd3dd | |||
| 6ffe581326 |
@@ -8,11 +8,14 @@ indent_style = space
|
||||
insert_final_newline = true
|
||||
trim_trailing_whitespace = true
|
||||
|
||||
[*.fish]
|
||||
max_line_length = 80
|
||||
|
||||
[*.md]
|
||||
max_line_length = 100
|
||||
|
||||
[*.lua]
|
||||
max_line_length = 120
|
||||
max_line_length = 90
|
||||
|
||||
[*.{php,fish}]
|
||||
indent_size = 4
|
||||
|
||||
45
.gitattributes
vendored
45
.gitattributes
vendored
@@ -1,4 +1,4 @@
|
||||
## GITATTRIBUTES FOR WEB PROJECTS
|
||||
## GITATTRIBUTES
|
||||
#
|
||||
# These settings are for any web project.
|
||||
#
|
||||
@@ -20,20 +20,23 @@
|
||||
*.bat text eol=crlf
|
||||
*.cmd text eol=crlf
|
||||
*.coffee text
|
||||
*.css text diff=css
|
||||
*.htm text diff=html
|
||||
*.html text diff=html
|
||||
*.css text diff=css eol=lf
|
||||
*.fish text diff=shell eol=lf
|
||||
*.htm text diff=html eol=lf
|
||||
*.html text diff=html eol=lf
|
||||
*.inc text
|
||||
*.ini text
|
||||
*.js text
|
||||
*.json text
|
||||
*.jsx text
|
||||
*.less text
|
||||
*.lua text diff=lua eol=lf
|
||||
*.ls text
|
||||
*.map text -diff
|
||||
*.od text
|
||||
*.onlydata text
|
||||
*.php text diff=php
|
||||
*.plist text eol=lf
|
||||
*.pl text
|
||||
*.ps1 text eol=crlf
|
||||
*.py text diff=python
|
||||
@@ -41,15 +44,18 @@
|
||||
*.sass text
|
||||
*.scm text
|
||||
*.scss text diff=css
|
||||
*.sh text eol=lf
|
||||
*.sh text eol=lf diff=shell
|
||||
.husky/* text eol=lf
|
||||
*.sql text
|
||||
*.styl text
|
||||
*.tag text
|
||||
*.tmux text eol=lf diff=tmux
|
||||
*.ts text
|
||||
*.tsx text
|
||||
*.vim text eol=lf
|
||||
*.xml text
|
||||
*.xhtml text diff=html
|
||||
*.zsh text diff=zsh eol=lf
|
||||
|
||||
# Docker
|
||||
Dockerfile text
|
||||
@@ -68,6 +74,7 @@ Dockerfile text
|
||||
AUTHORS text
|
||||
CHANGELOG text
|
||||
CHANGES text
|
||||
CODEOWNERS text
|
||||
CONTRIBUTING text
|
||||
COPYING text
|
||||
copyright text
|
||||
@@ -105,6 +112,8 @@ TODO text
|
||||
*.config text
|
||||
.editorconfig text
|
||||
.env text
|
||||
*.env text
|
||||
*.env.* text
|
||||
.gitattributes text
|
||||
.gitconfig text
|
||||
.htaccess text
|
||||
@@ -208,15 +217,37 @@ Procfile text
|
||||
|
||||
*.gitignore text
|
||||
*.gitkeep text
|
||||
.gitattributes export-ignore
|
||||
.gitattributes text export-ignore
|
||||
*.gitattributes text export-ignore
|
||||
.gitmodules text export-ignore
|
||||
*.gitmodules text export-ignore
|
||||
**/.gitignore export-ignore
|
||||
**/.gitkeep export-ignore
|
||||
|
||||
# Repo specials
|
||||
local/bin/* text eol=lf
|
||||
local/bin/* text eol=lf diff=shell
|
||||
local/bin/*.md text eol=lf diff=markdown
|
||||
config/antigen.zsh text
|
||||
git/* text
|
||||
**/git/* text
|
||||
**/alias text
|
||||
ssh/* text
|
||||
ssh/shared.d/* text
|
||||
ssh/local.d/* text
|
||||
|
||||
# Auto-generated rules - 2025-04-16 10:28:04
|
||||
# Shell scripts detected by content
|
||||
install text eol=lf diff=shell
|
||||
|
||||
# File extension-based rules
|
||||
*.1 text eol=lf
|
||||
*.applescript text eol=lf
|
||||
*.d/work-git text eol=lf
|
||||
*.dirs text eol=lf
|
||||
*.example text eol=lf
|
||||
*.itermcolors text eol=lf
|
||||
*.locale text eol=lf
|
||||
*.python-version text eol=lf
|
||||
*.snippets text eol=lf
|
||||
*.theme text eol=lf
|
||||
*.yamlfmt text eol=lf
|
||||
|
||||
2
.github/workflows/new-release.yml
vendored
2
.github/workflows/new-release.yml
vendored
@@ -40,7 +40,7 @@ jobs:
|
||||
|
||||
- name: Create release
|
||||
if: steps.daily-version.outputs.created
|
||||
uses: softprops/action-gh-release@c95fe1489396fe8a9eb87c0abf8aa5b2ef267fda # v2.2.1
|
||||
uses: softprops/action-gh-release@da05d552573ad5aba039eaac05058a918a7bf631 # v2.2.2
|
||||
with:
|
||||
token: ${{ secrets.GITHUB_TOKEN }}
|
||||
tag_name: ${{ steps.daily-version.outputs.version }}
|
||||
|
||||
2
.github/workflows/pre-commit-autoupdate.yml
vendored
2
.github/workflows/pre-commit-autoupdate.yml
vendored
@@ -25,7 +25,7 @@ jobs:
|
||||
steps:
|
||||
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
|
||||
|
||||
- uses: actions/setup-python@8d9ed9ac5c53483de85588cdf95a591a75ab9f55 # v5.5.0
|
||||
- uses: actions/setup-python@a26af69be951a213d495a4c3e4e4022e16d87065 # v5.6.0
|
||||
|
||||
- run: pip install pre-commit && pre-commit autoupdate
|
||||
|
||||
|
||||
3
.gitignore
vendored
3
.gitignore
vendored
@@ -40,9 +40,12 @@ node_modules
|
||||
ssh/local.d/*
|
||||
!ssh/local.d/.gitkeep
|
||||
config/fish/fish_variables
|
||||
**/exports.secret.fish
|
||||
**/exports-secret.fish
|
||||
config/fish/completions/asdf.fish
|
||||
config/vim/.netrwhist
|
||||
config/vim/extra/*
|
||||
config/gh/hosts.yml
|
||||
dependency-check-report.html
|
||||
local/bin/yabai
|
||||
local/man/yabai.1
|
||||
|
||||
@@ -23,13 +23,13 @@ repos:
|
||||
args: [--autofix, --no-sort-keys]
|
||||
|
||||
- repo: https://github.com/igorshubovych/markdownlint-cli
|
||||
rev: v0.44.0
|
||||
rev: v0.45.0
|
||||
hooks:
|
||||
- id: markdownlint
|
||||
args: [-c, .markdownlint.json, --fix]
|
||||
|
||||
- repo: https://github.com/adrienverge/yamllint
|
||||
rev: v1.37.0
|
||||
rev: v1.37.1
|
||||
hooks:
|
||||
- id: yamllint
|
||||
|
||||
@@ -49,12 +49,12 @@ repos:
|
||||
- id: actionlint
|
||||
|
||||
- repo: https://github.com/renovatebot/pre-commit-hooks
|
||||
rev: 39.227.2
|
||||
rev: 40.36.8
|
||||
hooks:
|
||||
- id: renovate-config-validator
|
||||
|
||||
- repo: https://github.com/JohnnyMorganz/StyLua
|
||||
rev: v2.0.2
|
||||
rev: v2.1.0
|
||||
hooks:
|
||||
- id: stylua # or stylua-system / stylua-github
|
||||
|
||||
|
||||
@@ -1 +1 @@
|
||||
3.13.2
|
||||
3.13.3
|
||||
|
||||
@@ -9,13 +9,7 @@
|
||||
# - all
|
||||
registries:
|
||||
- type: standard
|
||||
ref: v4.331.0 # renovate: depName=aquaproj/aqua-registry
|
||||
ref: v4.346.0 # renovate: depName=aquaproj/aqua-registry
|
||||
packages:
|
||||
- name: cli/cli
|
||||
version: 'v2.69.0'
|
||||
- name: junegunn/fzf
|
||||
version: 'v0.60.3'
|
||||
- name: jqlang/jq
|
||||
version: 'jq-1.7.1'
|
||||
- name: 1password/cli
|
||||
version: '2.30.3'
|
||||
|
||||
176
config/fish/completions/git-profile.fish
Normal file
176
config/fish/completions/git-profile.fish
Normal file
@@ -0,0 +1,176 @@
|
||||
# fish completion for git-profile -*- shell-script -*-
|
||||
|
||||
function __git_profile_debug
|
||||
set -l file "$BASH_COMP_DEBUG_FILE"
|
||||
if test -n "$file"
|
||||
echo "$argv" >> $file
|
||||
end
|
||||
end
|
||||
|
||||
function __git_profile_perform_completion
|
||||
__git_profile_debug "Starting __git_profile_perform_completion"
|
||||
|
||||
# Extract all args except the last one
|
||||
set -l args (commandline -opc)
|
||||
# Extract the last arg and escape it in case it is a space
|
||||
set -l lastArg (string escape -- (commandline -ct))
|
||||
|
||||
__git_profile_debug "args: $args"
|
||||
__git_profile_debug "last arg: $lastArg"
|
||||
|
||||
set -l requestComp "$args[1] __complete $args[2..-1] $lastArg"
|
||||
|
||||
__git_profile_debug "Calling $requestComp"
|
||||
set -l results (eval $requestComp 2> /dev/null)
|
||||
|
||||
# Some programs may output extra empty lines after the directive.
|
||||
# Let's ignore them or else it will break completion.
|
||||
# Ref: https://github.com/spf13/cobra/issues/1279
|
||||
for line in $results[-1..1]
|
||||
if test (string trim -- $line) = ""
|
||||
# Found an empty line, remove it
|
||||
set results $results[1..-2]
|
||||
else
|
||||
# Found non-empty line, we have our proper output
|
||||
break
|
||||
end
|
||||
end
|
||||
|
||||
set -l comps $results[1..-2]
|
||||
set -l directiveLine $results[-1]
|
||||
|
||||
# For Fish, when completing a flag with an = (e.g., <program> -n=<TAB>)
|
||||
# completions must be prefixed with the flag
|
||||
set -l flagPrefix (string match -r -- '-.*=' "$lastArg")
|
||||
|
||||
__git_profile_debug "Comps: $comps"
|
||||
__git_profile_debug "DirectiveLine: $directiveLine"
|
||||
__git_profile_debug "flagPrefix: $flagPrefix"
|
||||
|
||||
for comp in $comps
|
||||
printf "%s%s\n" "$flagPrefix" "$comp"
|
||||
end
|
||||
|
||||
printf "%s\n" "$directiveLine"
|
||||
end
|
||||
|
||||
# This function does two things:
|
||||
# - Obtain the completions and store them in the global __git_profile_comp_results
|
||||
# - Return false if file completion should be performed
|
||||
function __git_profile_prepare_completions
|
||||
__git_profile_debug ""
|
||||
__git_profile_debug "========= starting completion logic =========="
|
||||
|
||||
# Start fresh
|
||||
set --erase __git_profile_comp_results
|
||||
|
||||
set -l results (__git_profile_perform_completion)
|
||||
__git_profile_debug "Completion results: $results"
|
||||
|
||||
if test -z "$results"
|
||||
__git_profile_debug "No completion, probably due to a failure"
|
||||
# Might as well do file completion, in case it helps
|
||||
return 1
|
||||
end
|
||||
|
||||
set -l directive (string sub --start 2 $results[-1])
|
||||
set --global __git_profile_comp_results $results[1..-2]
|
||||
|
||||
__git_profile_debug "Completions are: $__git_profile_comp_results"
|
||||
__git_profile_debug "Directive is: $directive"
|
||||
|
||||
set -l shellCompDirectiveError 1
|
||||
set -l shellCompDirectiveNoSpace 2
|
||||
set -l shellCompDirectiveNoFileComp 4
|
||||
set -l shellCompDirectiveFilterFileExt 8
|
||||
set -l shellCompDirectiveFilterDirs 16
|
||||
|
||||
if test -z "$directive"
|
||||
set directive 0
|
||||
end
|
||||
|
||||
set -l compErr (math (math --scale 0 $directive / $shellCompDirectiveError) % 2)
|
||||
if test $compErr -eq 1
|
||||
__git_profile_debug "Received error directive: aborting."
|
||||
# Might as well do file completion, in case it helps
|
||||
return 1
|
||||
end
|
||||
|
||||
set -l filefilter (math (math --scale 0 $directive / $shellCompDirectiveFilterFileExt) % 2)
|
||||
set -l dirfilter (math (math --scale 0 $directive / $shellCompDirectiveFilterDirs) % 2)
|
||||
if test $filefilter -eq 1; or test $dirfilter -eq 1
|
||||
__git_profile_debug "File extension filtering or directory filtering not supported"
|
||||
# Do full file completion instead
|
||||
return 1
|
||||
end
|
||||
|
||||
set -l nospace (math (math --scale 0 $directive / $shellCompDirectiveNoSpace) % 2)
|
||||
set -l nofiles (math (math --scale 0 $directive / $shellCompDirectiveNoFileComp) % 2)
|
||||
|
||||
__git_profile_debug "nospace: $nospace, nofiles: $nofiles"
|
||||
|
||||
# If we want to prevent a space, or if file completion is NOT disabled,
|
||||
# we need to count the number of valid completions.
|
||||
# To do so, we will filter on prefix as the completions we have received
|
||||
# may not already be filtered so as to allow fish to match on different
|
||||
# criteria than the prefix.
|
||||
if test $nospace -ne 0; or test $nofiles -eq 0
|
||||
set -l prefix (commandline -t | string escape --style=regex)
|
||||
__git_profile_debug "prefix: $prefix"
|
||||
|
||||
set -l completions (string match -r -- "^$prefix.*" $__git_profile_comp_results)
|
||||
set --global __git_profile_comp_results $completions
|
||||
__git_profile_debug "Filtered completions are: $__git_profile_comp_results"
|
||||
|
||||
# Important not to quote the variable for count to work
|
||||
set -l numComps (count $__git_profile_comp_results)
|
||||
__git_profile_debug "numComps: $numComps"
|
||||
|
||||
if test $numComps -eq 1; and test $nospace -ne 0
|
||||
# We must first split on \t to get rid of the descriptions to be
|
||||
# able to check what the actual completion will be.
|
||||
# We don't need descriptions anyway since there is only a single
|
||||
# real completion which the shell will expand immediately.
|
||||
set -l split (string split --max 1 \t $__git_profile_comp_results[1])
|
||||
|
||||
# Fish won't add a space if the completion ends with any
|
||||
# of the following characters: @=/:.,
|
||||
set -l lastChar (string sub -s -1 -- $split)
|
||||
if not string match -r -q "[@=/:.,]" -- "$lastChar"
|
||||
# In other cases, to support the "nospace" directive we trick the shell
|
||||
# by outputting an extra, longer completion.
|
||||
__git_profile_debug "Adding second completion to perform nospace directive"
|
||||
set --global __git_profile_comp_results $split[1] $split[1].
|
||||
__git_profile_debug "Completions are now: $__git_profile_comp_results"
|
||||
end
|
||||
end
|
||||
|
||||
if test $numComps -eq 0; and test $nofiles -eq 0
|
||||
# To be consistent with bash and zsh, we only trigger file
|
||||
# completion when there are no other completions
|
||||
__git_profile_debug "Requesting file completion"
|
||||
return 1
|
||||
end
|
||||
end
|
||||
|
||||
return 0
|
||||
end
|
||||
|
||||
# Since Fish completions are only loaded once the user triggers them, we trigger them ourselves
|
||||
# so we can properly delete any completions provided by another script.
|
||||
# Only do this if the program can be found, or else fish may print some errors; besides,
|
||||
# the existing completions will only be loaded if the program can be found.
|
||||
if type -q "git-profile"
|
||||
# The space after the program name is essential to trigger completion for the program
|
||||
# and not completion of the program name itself.
|
||||
# Also, we use '> /dev/null 2>&1' since '&>' is not supported in older versions of fish.
|
||||
complete --do-complete "git-profile " > /dev/null 2>&1
|
||||
end
|
||||
|
||||
# Remove any pre-existing completions for the program since we will be handling all of them.
|
||||
complete -c git-profile -e
|
||||
|
||||
# The call to __git_profile_prepare_completions will setup __git_profile_comp_results
|
||||
# which provides the program's completion choices.
|
||||
complete -c git-profile -n '__git_profile_prepare_completions' -f -a '$__git_profile_comp_results'
|
||||
|
||||
@@ -1,63 +0,0 @@
|
||||
# NVM (https://github.com/creationix/nvm) completions for Fish shell
|
||||
# Inspired on (https://github.com/derekstavis/plugin-nvm)
|
||||
|
||||
function __nvm_complete_ls_remote
|
||||
if not test "$__nvm_ls_remote"
|
||||
set -g __nvm_ls_remote (nvm ls-remote | grep -Po '(?:iojs-)?v[0-9]+\.[0-9]+\.[0-9]+')
|
||||
end
|
||||
|
||||
printf "%s\n" $__nvm_ls_remote
|
||||
end
|
||||
|
||||
function __nvm_complete_ls
|
||||
if not test "$__nvm_ls"
|
||||
set -g __nvm_ls (nvm ls | grep -Po '[[:space:]].\K(v[0-9]+\.[0-9]+\.[0-9]+)')
|
||||
end
|
||||
|
||||
printf "%s\n" $__nvm_ls
|
||||
end
|
||||
|
||||
#Install
|
||||
complete -f -c nvm -n '__fish_use_subcommand' -a 'install' -d 'Download and install a <version>. Uses .nvmrc if available'
|
||||
complete -f -c nvm -n "__fish_seen_subcommand_from install" -a "(__nvm_complete_ls_remote)"
|
||||
complete -f -c nvm -n "__fish_seen_subcommand_from install" -l reinstall-packages-from= -d 'When installing, reinstall packages installed in <node|iojs|node version number>'
|
||||
complete -f -c nvm -n "__fish_seen_subcommand_from install" -s s -d 'From source'
|
||||
|
||||
#Use
|
||||
complete -f -c nvm -n '__fish_use_subcommand' -a 'use' -d 'Modify PATH to use <version>. Uses .nvmrc if available'
|
||||
complete -f -c nvm -n "__fish_seen_subcommand_from use" -a "(__nvm_complete_ls)"
|
||||
complete -f -c nvm -n "__fish_seen_subcommand_from use" -l silent
|
||||
|
||||
#Exec
|
||||
complete -f -c nvm -n '__fish_use_subcommand' -a 'exec' -d 'Run <command> on <version>. Uses .nvmrc if available'
|
||||
complete -f -c nvm -n "__fish_seen_subcommand_from exec" -a "(__nvm_complete_ls)"
|
||||
complete -f -c nvm -n "__fish_seen_subcommand_from exec" -l silent
|
||||
|
||||
#Run
|
||||
complete -f -c nvm -n '__fish_use_subcommand' -a 'run' -d 'Run <command> on <version>. Uses .nvmrc if available'
|
||||
complete -f -c nvm -n "__fish_seen_subcommand_from run" -a "(__nvm_complete_ls)"
|
||||
complete -f -c nvm -n "__fish_seen_subcommand_from run" -l silent
|
||||
|
||||
|
||||
#Uninstall
|
||||
complete -f -c nvm -n '__fish_use_subcommand' -a 'uninstall' -d 'Uninstall a version'
|
||||
complete -f -c nvm -n "__fish_seen_subcommand_from uninstall" -a "(__nvm_complete_ls)"
|
||||
|
||||
#Which
|
||||
complete -f -c nvm -n '__fish_use_subcommand' -a 'which' -d 'Display path to installed node version. Uses .nvmrc if available'
|
||||
complete -f -c nvm -n "__fish_seen_subcommand_from which" -a "(__nvm_complete_ls)"
|
||||
|
||||
#Reinstall-Packages
|
||||
complete -f -c nvm -n '__fish_use_subcommand' -a 'reinstall-packages' -d 'Reinstall global `npm` packages contained in <version> to current version'
|
||||
complete -f -c nvm -n "__fish_seen_subcommand_from reinstall-packages" -a "(__nvm_complete_ls)"
|
||||
|
||||
#Completions
|
||||
complete -f -c nvm -n '__fish_use_subcommand' -a 'current' -d 'Display currently activated version'
|
||||
complete -f -c nvm -n '__fish_use_subcommand' -a 'ls' -d 'List installed versions'
|
||||
complete -f -c nvm -n '__fish_use_subcommand' -a 'ls-remote' -d 'List remote versions available for install'
|
||||
complete -f -c nvm -n '__fish_use_subcommand' -a 'version' -d 'Resolve the given description to a single local <version>'
|
||||
complete -f -c nvm -n '__fish_use_subcommand' -a 'version-remote' -d 'Resolve the given description to a single remote <version>'
|
||||
complete -f -c nvm -n '__fish_use_subcommand' -a 'deactivate' -d 'Undo effects of `nvm` on current shell'
|
||||
complete -f -c nvm -n '__fish_use_subcommand' -a 'alias' -d 'Show all aliases beginning with <pattern> or set an alias named <name> pointing to <version>'
|
||||
complete -f -c nvm -n '__fish_use_subcommand' -a 'unalias' -d 'Deletes the alias named <name>'
|
||||
complete -f -c nvm -n '__fish_use_subcommand' -a 'unload' -d 'Unload `nvm` from shell'
|
||||
@@ -1,22 +0,0 @@
|
||||
function ___paths_plugin_set_colors
|
||||
if not set -q ___paths_plugin_colors
|
||||
set -Ux ___paths_plugin_colors 27e6ff 29e0ff 5cd8ff 77d0ff 8ac8ff 9cbfff afb5ff c5a7ff d99bfe ea8feb f684d5 fe7abd ff73a3 ff708a fa7070 ff708a ff73a3 fe7abd f684d5 ea8feb d99bfe c5a7ff afb5ff 9cbfff 8ac8ff 77d0ff 5cd8ff 29e0ff
|
||||
end
|
||||
return 0
|
||||
end
|
||||
|
||||
function _paths_uninstall --on-event paths_uninstall
|
||||
for i in ___paths_plugin_wrap_color ___paths_plugin_output ___paths_plugin_handle_found_item ___paths_plugin_handle_source ___paths_plugin_cycle_color
|
||||
functions -e $i
|
||||
end
|
||||
set -e ___paths_plugin_colors
|
||||
set -e ___paths_plugin_current_color
|
||||
end
|
||||
|
||||
function _paths_install --on-event _paths_install
|
||||
___paths_plugin_set_colors
|
||||
end
|
||||
|
||||
function _paths_update --on-event paths_update
|
||||
___paths_plugin_set_colors
|
||||
end
|
||||
@@ -8,18 +8,29 @@ test -e "$HOME/.config/fish/alias.fish" &&
|
||||
test -e "$HOME/.config/fish/exports.fish" &&
|
||||
source "$HOME/.config/fish/exports.fish"
|
||||
|
||||
if status is-interactive
|
||||
# Commands to run in interactive sessions can go here
|
||||
test -e "$HOME/.dotfiles/config/fzf/key-bindings.fish" &&
|
||||
source "$HOME/.dotfiles/config/fzf/key-bindings.fish"
|
||||
|
||||
# Start tmux if not already running and not in SSH
|
||||
open-tmux # defined in functions/open-tmux.fish
|
||||
if status is-interactive
|
||||
# Commands to run in interactive shell
|
||||
|
||||
# 1Password plugins if op command is available
|
||||
type -q op; and test -e "$HOME/.config/op/plugins.sh" &&
|
||||
source "$HOME/.config/op/plugins.sh"
|
||||
|
||||
# version manager initializers
|
||||
type -q rbenv; and source (rbenv init -|psub)
|
||||
type -q pyenv; and source (pyenv init -|psub)
|
||||
type -q pyenv; and source (pyenv virtualenv-init -|psub)
|
||||
type -q goenv; and source (goenv init -|psub)
|
||||
# type -q fnm; and fnm env --use-on-cd --shell fish | source
|
||||
type -q load_nvm; and load_nvm > /dev/stderr
|
||||
|
||||
# Start tmux if not already running and not in SSH
|
||||
open-tmux # defined in functions/open-tmux.fish
|
||||
end
|
||||
|
||||
# Added by LM Studio CLI (lms)
|
||||
set -gx PATH $PATH $HOME/.lmstudio/bin
|
||||
|
||||
type -q rbenv; and source (rbenv init -|psub)
|
||||
type -q pyenv; and source (pyenv init -|psub)
|
||||
type -q goenv; and source (goenv init -|psub)
|
||||
type -q fnm; and fnm env --use-on-cd --shell fish | source
|
||||
|
||||
# vim: ft=fish ts=4 sw=4 et:
|
||||
|
||||
@@ -22,11 +22,6 @@ fish_add_path "$XDG_BIN_HOME"
|
||||
# Add cargo bin to path
|
||||
fish_add_path "$XDG_SHARE_HOME/cargo/bin"
|
||||
|
||||
# Set Aqua configuration
|
||||
set -q AQUA_BIN; or set -gx AQUA_BIN "$XDG_DATA_HOME/aquaproj-aqua/bin"
|
||||
set -q AQUA_CONFIG; or set -gx AQUA_CONFIG "$XDG_CONFIG_HOME/aqua/aqua.yaml"
|
||||
set -gx PATH $AQUA_BIN $PATH
|
||||
|
||||
# NPM/NVM configuration
|
||||
set -q NVM_DIR; or set -x NVM_DIR "$XDG_DATA_HOME/nvm"
|
||||
fish_add_path "$NVM_DIR/bin"
|
||||
@@ -109,7 +104,6 @@ set -q GNUPGHOME; or set -x GNUPGHOME "$XDG_DATA_HOME/gnupg"
|
||||
# Go configuration
|
||||
# set -q GOPATH; or set -x GOPATH "$XDG_DATA_HOME/go"
|
||||
set -q GOBIN; or set -x GOBIN "$XDG_BIN_HOME"
|
||||
fish_add_path "$GOBIN"
|
||||
|
||||
set -q GOENV_ROOT; or set -x GOENV_ROOT "$XDG_DATA_HOME/goenv"
|
||||
set -q GOENV_RC_FILE; or set -x GOENV_RC_FILE "$XDG_CONFIG_HOME/goenv/goenvrc.fish"
|
||||
@@ -131,7 +125,6 @@ set -q CARGO_HOME; or set -x CARGO_HOME "$XDG_DATA_HOME/cargo"
|
||||
set -q CARGO_BIN_HOME; or set -x CARGO_BIN_HOME "$XDG_BIN_HOME"
|
||||
set -q RUSTUP_HOME; or set -x RUSTUP_HOME "$XDG_DATA_HOME/rustup"
|
||||
set -x RUST_WITHOUT "clippy,docs,rls"
|
||||
fish_add_path "$CARGO_BIN_HOME"
|
||||
fish_add_path "$CARGO_HOME/bin"
|
||||
fish_add_path "$XDG_SHARE_HOME/bob/nvim-bin"
|
||||
|
||||
|
||||
@@ -2,9 +2,6 @@ jorgebucaran/fisher
|
||||
ilancosman/tide@v6
|
||||
jethrokuan/z
|
||||
halostatue/fish-macos@v7
|
||||
jgusta/paths
|
||||
danhper/fish-ssh-agent
|
||||
halostatue/fish-brew@v3
|
||||
edc/bass
|
||||
jorgebucaran/nvm.fish
|
||||
fabioantunes/fish-nvm
|
||||
|
||||
@@ -1,70 +0,0 @@
|
||||
function __nvm_run
|
||||
set count (count $argv)
|
||||
|
||||
if test "$count" -le 0
|
||||
echo 'No params'
|
||||
return 1
|
||||
end
|
||||
|
||||
if test (uname -s) = 'Darwin'; and string match -q "*versions/node/*/bin" $PATH
|
||||
set -l nvm_node_path (string match "*versions/node/*/bin" $PATH)
|
||||
set -l nvm_index (contains -i -- $nvm_node_path $PATH)
|
||||
if test $nvm_index -gt 1
|
||||
set -gx PATH $nvm_node_path (string match -v $nvm_node_path $PATH)
|
||||
end
|
||||
end
|
||||
|
||||
function run_command
|
||||
set stack (status stack-trace | grep called | cut -d " " -f 7)
|
||||
set count (count $argv)
|
||||
|
||||
if type -fq $argv[1]; and test "$stack[1]" != (type -fP $argv[1])
|
||||
set count (count $argv)
|
||||
if test "$count" -ge 2
|
||||
set args $argv[2..-1]
|
||||
|
||||
# https://stackoverflow.com/questions/45237675/proxying-arguments-from-one-function-to-a-command/45238056#45238056
|
||||
eval (string escape -- (type -fP $argv[1]) $args)
|
||||
else
|
||||
eval (string escape -- (type -fP $argv[1]))
|
||||
end
|
||||
else
|
||||
echo (set_color -o)"Fish nvm:"(set_color normal) "'$argv[1]' is currently not installed, try running npm i -g $argv[1]"
|
||||
return 1
|
||||
end
|
||||
end
|
||||
|
||||
function can_run_command
|
||||
if type -P $argv[1] > /dev/null 2>&1; or type -P node > /dev/null 2>&1
|
||||
return
|
||||
else
|
||||
return 1
|
||||
end
|
||||
end
|
||||
|
||||
function run_default
|
||||
nvm use default > /dev/null
|
||||
set -gx NVM_HAS_RUN 1
|
||||
if can_run_command $argv[1]
|
||||
run_command $argv
|
||||
end
|
||||
end
|
||||
|
||||
if not test -n "$NVM_HAS_RUN"
|
||||
if test -f .nvmrc;
|
||||
set nvm_output (nvm use)
|
||||
set nvm_status $status
|
||||
if test $nvm_status -gt 0
|
||||
echo $nvm_output
|
||||
end
|
||||
if test $nvm_status -eq 0; and can_run_command $argv[1]
|
||||
set -gx NVM_HAS_RUN 1
|
||||
run_command $argv
|
||||
end
|
||||
else
|
||||
run_default $argv
|
||||
end
|
||||
else
|
||||
run_command $argv
|
||||
end
|
||||
end
|
||||
16
config/fish/functions/load_nvm.fish
Normal file
16
config/fish/functions/load_nvm.fish
Normal file
@@ -0,0 +1,16 @@
|
||||
function load_nvm --on-variable="PWD"
|
||||
set -l default_node_version (nvm version default)
|
||||
set -l node_version (nvm version)
|
||||
set -l nvmrc_path (nvm_find_nvmrc)
|
||||
if test -n "$nvmrc_path"
|
||||
set -l nvmrc_node_version (nvm version (cat $nvmrc_path))
|
||||
if test "$nvmrc_node_version" = "N/A"
|
||||
nvm install (cat $nvmrc_path)
|
||||
else if test "$nvmrc_node_version" != "$node_version"
|
||||
nvm use $nvmrc_node_version
|
||||
end
|
||||
else if test "$node_version" != "$default_node_version"
|
||||
echo "Reverting to default Node version"
|
||||
nvm use default
|
||||
end
|
||||
end
|
||||
@@ -1,3 +0,0 @@
|
||||
function node -d "Server-side JavaScript runtime" -w node
|
||||
__nvm_run "node" $argv
|
||||
end
|
||||
@@ -1,3 +0,0 @@
|
||||
function npm -d "node package manager" -w npm
|
||||
__nvm_run "npm" $argv
|
||||
end
|
||||
@@ -1,3 +0,0 @@
|
||||
function npx -d "execute npm package binaries" -w npx
|
||||
__nvm_run "npx" $argv
|
||||
end
|
||||
@@ -1,24 +1,4 @@
|
||||
function nvm
|
||||
if not type -q bass
|
||||
echo 'Bass is not installed please install it running fisher edc/bass'
|
||||
return
|
||||
end
|
||||
set -q NVM_DIR; or set -gx NVM_DIR ~/.nvm
|
||||
set -q nvm_prefix; or set -gx nvm_prefix $NVM_DIR
|
||||
|
||||
bass source $nvm_prefix/nvm.sh --no-use ';' nvm $argv
|
||||
|
||||
set bstatus $status
|
||||
|
||||
if test $bstatus -gt 0
|
||||
return $bstatus
|
||||
end
|
||||
|
||||
if test (count $argv) -lt 1
|
||||
return 0
|
||||
end
|
||||
|
||||
if test $argv[1] = "use"; or test $argv[1] = "install"
|
||||
set -gx NVM_HAS_RUN 1
|
||||
end
|
||||
bass source $NVM_DIR/nvm.sh --no-use ';' nvm $argv
|
||||
end
|
||||
|
||||
|
||||
@@ -1,49 +0,0 @@
|
||||
function nvm_alias_command -d "Create an alias command"
|
||||
function __nvm_alias_output
|
||||
if test -z "$nvm_alias_output"
|
||||
echo "/usr/local/bin"
|
||||
else
|
||||
echo (string replace -r '/$' '' $nvm_alias_output)
|
||||
end
|
||||
end
|
||||
|
||||
function __create_alias_command
|
||||
if test -e "$argv[1]"
|
||||
set_color yellow
|
||||
echo "Ignored: $argv[1] (already exists)"
|
||||
set_color normal
|
||||
return 0
|
||||
else
|
||||
set -l template "__nvm_run \"COMMAND\" \$argv"
|
||||
printf "#!/usr/bin/env fish\n%s\n" (string replace COMMAND $argv[2] $template) > $argv[1]
|
||||
if test $status -eq 0
|
||||
printf "\U2705 %s alias command was created at %s\n" $argv[2] $argv[1]
|
||||
return (chmod +x $argv[1])
|
||||
else
|
||||
printf "\U274C failed creating %s alias command at %s\n" $argv[2] $argv[1]
|
||||
printf "Probably a permissions problem, try running sudo fish, and then nvm_alias_command\n"
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
set -l outputPath (__nvm_alias_output)
|
||||
mkdir -p $outputPath
|
||||
|
||||
if test $status -ge 1
|
||||
printf "\U274C failed creating dir $outputPath."
|
||||
printf "Probably a permissions problem, try running sudo fish, and then nvm_alias_command\n"
|
||||
exit 1
|
||||
end
|
||||
|
||||
if test (count $argv) -le 0
|
||||
set -l aliases node npm npx yarn
|
||||
|
||||
for alias in $aliases
|
||||
__create_alias_command "$outputPath/$alias" $alias
|
||||
end
|
||||
else
|
||||
for arg in $argv
|
||||
__create_alias_command "$outputPath/$arg" $arg
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -1,28 +0,0 @@
|
||||
function nvm_alias_function -d "Create an alias function"
|
||||
function __create_alias_function
|
||||
if test -e "$argv[1]"
|
||||
set_color yellow
|
||||
echo "Ignored: $argv[1] (already exists)"
|
||||
set_color normal
|
||||
return 0
|
||||
else
|
||||
set -l line1 "function COMMAND -w COMMAND"
|
||||
set -l line2 "__nvm_run \"COMMAND\" \$argv"
|
||||
echo (string replace -a COMMAND $argv[2] $line1) > $argv[1]
|
||||
echo (string replace COMMAND $argv[2] $line2) >> $argv[1]
|
||||
echo "end" >> $argv[1]
|
||||
return 0
|
||||
end
|
||||
end
|
||||
|
||||
if test (count $argv) -le 0
|
||||
set_color yellow
|
||||
echo "Please specify package(s) name(s)"
|
||||
set_color normal
|
||||
return 1
|
||||
else
|
||||
for arg in $argv
|
||||
__create_alias_function "$fish_function_path[1]/$arg.fish" $argv
|
||||
end
|
||||
end
|
||||
end
|
||||
3
config/fish/functions/nvm_find_nvmrc.fish
Normal file
3
config/fish/functions/nvm_find_nvmrc.fish
Normal file
@@ -0,0 +1,3 @@
|
||||
function nvm_find_nvmrc
|
||||
bass source $NVM_DIR/nvm.sh --no-use ';' nvm_find_nvmrc
|
||||
end
|
||||
@@ -1,175 +0,0 @@
|
||||
function ___paths_plugin_wrap_color
|
||||
set_color normal
|
||||
set_color "$argv[1]"
|
||||
echo -n (set_color "$argv[1]")"$argv[2..]"
|
||||
set_color normal
|
||||
end
|
||||
|
||||
# duplicated in conf.d
|
||||
function ___paths_plugin_set_colors
|
||||
if not set -q ___paths_plugin_colors
|
||||
set -Ux ___paths_plugin_colors 27e6ff 29e0ff 5cd8ff 77d0ff 8ac8ff 9cbfff afb5ff c5a7ff d99bfe ea8feb f684d5 fe7abd ff73a3 ff708a fa7070 ff708a ff73a3 fe7abd f684d5 ea8feb d99bfe c5a7ff afb5ff 9cbfff 8ac8ff 77d0ff 5cd8ff 29e0ff
|
||||
end
|
||||
return 0
|
||||
end
|
||||
|
||||
function ___paths_plugin_cycle_color
|
||||
if not set -q ___paths_plugin_current_color
|
||||
set -Ux ___paths_plugin_current_color 1
|
||||
else if test $___paths_plugin_current_color -gt (count $___paths_plugin_colors)
|
||||
set -Ux ___paths_plugin_current_color 1
|
||||
end
|
||||
echo $___paths_plugin_colors[$___paths_plugin_current_color]
|
||||
set -Ux ___paths_plugin_current_color (math $___paths_plugin_current_color + 1)
|
||||
end
|
||||
|
||||
function ___paths_plugin_handle_found_item -a testName outFlags
|
||||
set -f flags (string split -n ' ' -- "$outFlags")
|
||||
set -f options (fish_opt -s c -l clean)
|
||||
set -a options (fish_opt -s s -l single)
|
||||
set -a options (fish_opt -s k -l no-color)
|
||||
set -a options (fish_opt -s n -l inline)
|
||||
argparse $options -- $flags
|
||||
|
||||
set -f arrow "=>"
|
||||
# check if file exists
|
||||
if test -e "$testName"
|
||||
set -f nameOut (string trim -- "$testName")
|
||||
if not set -q _flag_c # is not clean
|
||||
if test -L "$testName" # is symlink
|
||||
set -f __linkname (readlink -f "$testName")
|
||||
set __linkname (string trim -- "$__linkname")
|
||||
set testName (string trim -- "$testName")
|
||||
if not set -q _flag_k # is color
|
||||
set nameOut (___paths_plugin_wrap_color (___paths_plugin_cycle_color) $testName) (___paths_plugin_wrap_color "yellow" "$arrow") (___paths_plugin_wrap_color (___paths_plugin_cycle_color) $__linkname)
|
||||
else # is color
|
||||
set nameOut (echo -n "$testName" "$arrow" "$__linkname")
|
||||
end
|
||||
else # is not symlink
|
||||
if not set -q _flag_k # is color
|
||||
set testName (string trim -- "$testName")
|
||||
set nameOut (___paths_plugin_wrap_color (___paths_plugin_cycle_color) "$testName")
|
||||
else
|
||||
set testName (string trim -- "$testName")
|
||||
set nameOut "$testName"
|
||||
end
|
||||
end
|
||||
|
||||
set nameOut (string trim -- "$nameOut")
|
||||
# do the tick
|
||||
if set -q _flag_k # is not color
|
||||
set nameOut "- $nameOut"
|
||||
else # is color
|
||||
set nameOut (___paths_plugin_wrap_color "yellow" "-") "$nameOut"
|
||||
end
|
||||
end
|
||||
set nameOut (string trim -- "$nameOut")
|
||||
echo -n $nameOut
|
||||
end
|
||||
end
|
||||
|
||||
function paths --description "Reveal the executable matches in shell paths or fish autoload."
|
||||
set -f options (fish_opt -s c -l clean)
|
||||
set -a options (fish_opt -s s -l single)
|
||||
set -a options (fish_opt -s k -l no-color)
|
||||
set -a options (fish_opt -s q -l quiet)
|
||||
set -a options (fish_opt -s n -l inline)
|
||||
argparse $options -- $argv
|
||||
|
||||
if test (count $argv) -lt 1
|
||||
echo "paths - executable matches in shell paths or fish autoload."
|
||||
and echo "usage: paths [-c|-s|-k] <name>"
|
||||
and echo -e "\t-c or --no-color: output without color"
|
||||
and echo -e "\t-s or --single: output without color or headers, the first result"
|
||||
and echo -e "\t-k or --clean: output without tick marks or headers"
|
||||
# and echo -e "\t-n or --inline: output without endline"
|
||||
and return 1
|
||||
end
|
||||
|
||||
set -f foundStatus 1
|
||||
set -f input (string trim -- $argv)
|
||||
# deprecated
|
||||
if set -q _flag_q
|
||||
set _flag_c True
|
||||
end
|
||||
|
||||
if set -q _flag_s
|
||||
set _flag_k True
|
||||
set _flag_c True
|
||||
end
|
||||
|
||||
set -f outFlags ''
|
||||
set -q _flag_n; and set -a outFlags -n
|
||||
set -q _flag_c; and set -a outFlags -c
|
||||
set -q _flag_k; and set -a outFlags -k
|
||||
set -q _flag_s; and set -a outFlags -s
|
||||
set outFlags (string split -n " " -- "$outFlags")
|
||||
___paths_plugin_set_colors
|
||||
# loop over list of path lists
|
||||
for pVar in VIRTUAL_ENV fisher_path fish_function_path fish_user_paths PATH
|
||||
set -e acc
|
||||
set -f acc ''
|
||||
set -e hit
|
||||
# see if variable is empty
|
||||
if test -z "$pVar"
|
||||
continue
|
||||
end
|
||||
set -f acc (begin
|
||||
for t in $$pVar
|
||||
for snit in "$t/$input.fish" "$t/$input"
|
||||
set -f found (___paths_plugin_handle_found_item "$snit" "$outFlags")
|
||||
set found (string trim -- "$found")
|
||||
if test -n "$found"
|
||||
set -f hit True
|
||||
echo "$found"
|
||||
if set -q _flag_s
|
||||
break
|
||||
end
|
||||
end
|
||||
end
|
||||
if set -q _flag_s
|
||||
if set -q hit
|
||||
break
|
||||
end
|
||||
end
|
||||
end
|
||||
end)
|
||||
|
||||
# prepend source
|
||||
if not set -q _flag_c
|
||||
if set -q hit
|
||||
set pVar (string trim -- "$pVar")
|
||||
echo -e -n "$pVar\n"
|
||||
end
|
||||
end
|
||||
|
||||
if test -n "$acc"
|
||||
set foundStatus 0
|
||||
for fk in $acc
|
||||
echo $fk
|
||||
if set -q _flag_s
|
||||
# stop after one
|
||||
return $foundStatus
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
# check
|
||||
set -l built (type --type $input 12&>/dev/null)
|
||||
if test -n "$built"
|
||||
and test "$built" = 'builtin'
|
||||
set $foundStatus 0
|
||||
if not set -q _flag_c
|
||||
echo -e -n "builtin\n"
|
||||
if set -q _flag_k
|
||||
echo - "$input"
|
||||
else # is color
|
||||
echo (___paths_plugin_wrap_color "yellow" "-") (___paths_plugin_wrap_color (___paths_plugin_cycle_color) "$input")
|
||||
end
|
||||
else
|
||||
echo "$input"
|
||||
end
|
||||
end
|
||||
return $foundStatus
|
||||
end
|
||||
@@ -1,3 +0,0 @@
|
||||
function yarn -d "yarn package manager" -w yarn
|
||||
__nvm_run "yarn" $argv
|
||||
end
|
||||
@@ -46,7 +46,7 @@
|
||||
autoStash = true
|
||||
updateRefs = true
|
||||
[merge]
|
||||
conflictstyle = zdiff3
|
||||
conflictStyle = diff3
|
||||
[pull]
|
||||
rebase = true
|
||||
[color "diff-highlight"]
|
||||
|
||||
@@ -89,6 +89,8 @@ brew "coreutils"
|
||||
brew "bats-core"
|
||||
# Parser generator
|
||||
brew "bison"
|
||||
# Freely available high-quality data compressor
|
||||
brew "bzip2"
|
||||
# Software library to render fonts
|
||||
brew "freetype"
|
||||
# XML-based font configuration API for X Windows
|
||||
@@ -113,10 +115,10 @@ brew "harfbuzz"
|
||||
brew "dependency-check"
|
||||
# Lightweight DNS forwarder and DHCP server
|
||||
brew "dnsmasq"
|
||||
# .NET Core
|
||||
brew "dotnet@8", link: true
|
||||
# Spellchecker wrapping library
|
||||
brew "enchant"
|
||||
# Command-line tool to interact with exercism.io
|
||||
brew "exercism"
|
||||
# Perl lib for reading and writing EXIF metadata
|
||||
brew "exiftool"
|
||||
# Banner-like program prints strings as ASCII art
|
||||
@@ -222,7 +224,7 @@ brew "nginx"
|
||||
# Port scanning utility for large networks
|
||||
brew "nmap"
|
||||
# Platform built on V8 to build network applications
|
||||
brew "node"
|
||||
brew "node", link: false
|
||||
# Libraries for security-enabled client and server applications
|
||||
brew "nss"
|
||||
# Command-line Git information tool
|
||||
@@ -232,9 +234,9 @@ brew "openldap"
|
||||
# ISO-C API and CLI for generating UUIDs
|
||||
brew "ossp-uuid"
|
||||
# General-purpose scripting language
|
||||
brew "php"
|
||||
brew "php", link: false
|
||||
# General-purpose scripting language
|
||||
brew "php@8.2"
|
||||
brew "php@8.2", link: true
|
||||
# General-purpose scripting language
|
||||
brew "php@8.3"
|
||||
# Pins GitHub Actions to full hashes and versions
|
||||
@@ -259,6 +261,8 @@ brew "re2c"
|
||||
brew "rustup"
|
||||
# Static analysis and lint tool, for (ba)sh scripts
|
||||
brew "shellcheck"
|
||||
# User interface to the TELNET protocol
|
||||
brew "telnet"
|
||||
# Send macOS User Notifications from the command-line
|
||||
brew "terminal-notifier"
|
||||
# Tool which checks for the support of TLS/SSL ciphers and flaws
|
||||
@@ -317,8 +321,6 @@ brew "shivammathur/php/php-debug"
|
||||
brew "shivammathur/php/php@8.2-debug"
|
||||
# Command-line interface for 1Password
|
||||
cask "1password-cli"
|
||||
# AeroSpace is an i3-like tiling window manager for macOS
|
||||
cask "aerospace"
|
||||
# Universal database tool and SQL client
|
||||
cask "dbeaver-community"
|
||||
# Database version management tool
|
||||
@@ -340,8 +342,6 @@ cask "jetbrains-toolbox"
|
||||
cask "keybase"
|
||||
# Kubernetes IDE
|
||||
cask "lens"
|
||||
# Neovim Client
|
||||
cask "neovide"
|
||||
# Reverse proxy, secure introspectable tunnels to localhost
|
||||
cask "ngrok"
|
||||
# Simple application that will prevent iTunes or Apple Music from launching
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
"" Source your .vimrc
|
||||
source ~/.dotfiles/config/vim/vimrc
|
||||
source $HOME/.dotfiles/config/vim/vimrc
|
||||
|
||||
" https://github.com/ville6000/dotfiles/blob/main/vimrc
|
||||
" To get a list of Actions run `:actionlist `
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
# EditorConfig is awesome: https://editorconfig.org
|
||||
|
||||
# top-most EditorConfig file
|
||||
root = true
|
||||
root = false
|
||||
|
||||
[*]
|
||||
end_of_line = lf
|
||||
@@ -18,3 +18,7 @@ trim_trailing_whitespace = false
|
||||
|
||||
[*.json]
|
||||
max_line_length = off
|
||||
|
||||
[*.lua]
|
||||
max_line_length = 90
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
column_width = 80
|
||||
column_width = 90
|
||||
line_endings = "Unix"
|
||||
indent_type = "Spaces"
|
||||
indent_width = 2
|
||||
|
||||
2
config/nvim/ftdetect/env.vim
Normal file
2
config/nvim/ftdetect/env.vim
Normal file
@@ -0,0 +1,2 @@
|
||||
autocmd BufRead,BufNewFile *.env set ft=env
|
||||
autocmd BufRead,BufNewFile *.env.* set ft=env
|
||||
@@ -28,10 +28,7 @@ end
|
||||
vim.opt.rtp:prepend(lazypath)
|
||||
|
||||
-- ── Add ~/.local/bin to the PATH ────────────────────────────────────
|
||||
vim.fn.setenv(
|
||||
'PATH',
|
||||
vim.fn.expand '$HOME/.local/bin' .. ':' .. vim.fn.expand '$PATH'
|
||||
)
|
||||
vim.fn.setenv('PATH', vim.fn.expand '$HOME/.local/bin' .. ':' .. vim.fn.expand '$PATH')
|
||||
|
||||
require 'options'
|
||||
require 'autogroups'
|
||||
@@ -68,4 +65,4 @@ require('lazy').setup(
|
||||
|
||||
require 'keymaps'
|
||||
|
||||
-- vim: ts=2 sts=2 sw=2 et
|
||||
-- vim: set ts=2 sts=2 sw=2 wrap et :
|
||||
|
||||
@@ -21,9 +21,7 @@ autocmd({ 'BufEnter', 'BufWinEnter', 'TabEnter' }, {
|
||||
callback = function()
|
||||
local max_line_count = vim.fn.line '$'
|
||||
-- Only adjust if the file is large enough to matter
|
||||
if max_line_count > 99 then
|
||||
vim.opt.numberwidth = #tostring(max_line_count) + 1
|
||||
end
|
||||
if max_line_count > 99 then vim.opt.numberwidth = #tostring(max_line_count) + 1 end
|
||||
end,
|
||||
})
|
||||
|
||||
@@ -104,5 +102,3 @@ autocmd({ 'BufRead', 'BufNewFile' }, {
|
||||
},
|
||||
command = 'set filetype=sshconfig',
|
||||
})
|
||||
|
||||
-- vim: ts=2 sts=2 sw=2 et
|
||||
|
||||
@@ -1,5 +1,3 @@
|
||||
-- vim: set ft=lua ts=2 sw=2 tw=0 et cc=130 :
|
||||
|
||||
require 'utils'
|
||||
|
||||
-- ╭─────────────────────────────────────────────────────────╮
|
||||
@@ -20,16 +18,8 @@ K.n('<C-w>+', ':resize +10<CR>', { desc = 'H Resize +' })
|
||||
K.n('<C-w>=', '<C-w>=', { desc = 'Equal Size Splits' })
|
||||
|
||||
-- ── Deal with word wrap ─────────────────────────────────────────────
|
||||
K.n(
|
||||
'k',
|
||||
"v:count == 0 ? 'gk' : 'k'",
|
||||
{ desc = 'Move up', noremap = true, expr = true }
|
||||
)
|
||||
K.n(
|
||||
'j',
|
||||
"v:count == 0 ? 'gj' : 'j'",
|
||||
{ desc = 'Move down', noremap = true, expr = true }
|
||||
)
|
||||
K.n('k', "v:count == 0 ? 'gk' : 'k'", { desc = 'Move up', noremap = true, expr = true })
|
||||
K.n('j', "v:count == 0 ? 'gj' : 'j'", { desc = 'Move down', noremap = true, expr = true })
|
||||
|
||||
-- ── Text manipulation ───────────────────────────────────────────────
|
||||
K.d('<', { 'n', 'v' }, '<gv', 'Indent Left')
|
||||
@@ -111,12 +101,10 @@ K.nl('cbt', '<Cmd>CBllline<CR>', 'CB: Titled Line')
|
||||
-- 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,
|
||||
}
|
||||
)
|
||||
require('telescope.builtin').find_files(require('telescope.themes').get_dropdown {
|
||||
winblend = 20,
|
||||
previewer = true,
|
||||
})
|
||||
end
|
||||
|
||||
local lazy_plugins = function()
|
||||
@@ -159,9 +147,7 @@ K.nl('tn', ':Noice dismiss<cr>', 'Noice: Dismiss Notification')
|
||||
-- Convention is 'q' followed by the operation
|
||||
K.nl('qf', ':q<CR>', 'Quicker close split')
|
||||
K.nl('qq', function()
|
||||
if vim.fn.confirm('Force save and quit?', '&Yes\n&No', 2) == 1 then
|
||||
vim.cmd 'wq!'
|
||||
end
|
||||
if vim.fn.confirm('Force save and quit?', '&Yes\n&No', 2) == 1 then vim.cmd 'wq!' end
|
||||
end, 'Quit with force saving')
|
||||
K.nl('qw', ':wq<CR>', 'Write and quit')
|
||||
K.nl('qQ', function()
|
||||
|
||||
@@ -77,10 +77,8 @@ function M.setup(opts)
|
||||
-- Set vim.g.node_host_prog and vim.g.copilot_node_command
|
||||
local current_nvm_version_path =
|
||||
string.format('%s/versions/node/%s', nvm_path, node_version)
|
||||
local current_nvm_node_bin_path =
|
||||
string.format('%s/bin', current_nvm_version_path)
|
||||
local current_nvm_node_bin =
|
||||
string.format('%s/node', current_nvm_node_bin_path)
|
||||
local current_nvm_node_bin_path = string.format('%s/bin', current_nvm_version_path)
|
||||
local current_nvm_node_bin = string.format('%s/node', current_nvm_node_bin_path)
|
||||
local neovim_node_host_bin_path =
|
||||
string.format('%s/neovim-node-host', current_nvm_node_bin_path)
|
||||
|
||||
|
||||
@@ -38,7 +38,7 @@ o.scrolloff = 8 -- Show context around cursor
|
||||
o.sidescrolloff = 8 -- Show context around cursor
|
||||
o.signcolumn = 'yes' -- Keep signcolumn on by default
|
||||
o.spell = true -- Enable spell checking
|
||||
o.spelllang = 'fi,en_us' -- Set the spell checking language
|
||||
o.spelllang = 'en_gb,en_us' -- Set the spell checking language
|
||||
o.splitbelow = true -- split to the bottom
|
||||
o.splitright = true -- vsplit to the right
|
||||
o.termguicolors = true -- Enable GUI colors
|
||||
@@ -64,4 +64,7 @@ vim.schedule(function()
|
||||
o.clipboard = c
|
||||
end)
|
||||
|
||||
-- xiyaowong/transparent.nvim
|
||||
vim.g.transparent_enabled = true
|
||||
|
||||
-- vim: ts=2 sts=2 sw=2 et
|
||||
|
||||
@@ -3,7 +3,7 @@ return {
|
||||
-- https:/github.com/saghen/blink.cmp
|
||||
{
|
||||
'saghen/blink.cmp',
|
||||
version = '*',
|
||||
version = '1.*',
|
||||
lazy = false, -- lazy loading handled internally
|
||||
dependencies = {
|
||||
-- Compatibility layer for using nvim-cmp sources on blink.cmp
|
||||
@@ -58,10 +58,10 @@ return {
|
||||
-- 'default' for mappings similar to built-in completion
|
||||
-- 'super-tab' for mappings similar to vscode (tab to accept, arrow keys to navigate)
|
||||
-- 'enter' for mappings similar to 'super-tab' but with 'enter' to accept
|
||||
-- see the "default configuration" section below for full documentation on how to define
|
||||
-- your own keymap.
|
||||
-- see the "default configuration" section below for full documentation on how to
|
||||
-- define your own keymap.
|
||||
keymap = {
|
||||
preset = 'super-tab',
|
||||
preset = 'default',
|
||||
-- Use Ctrl-x to trigger auto completion
|
||||
['<C-x>'] = { 'show', 'show_documentation', 'hide_documentation' },
|
||||
},
|
||||
@@ -86,7 +86,8 @@ return {
|
||||
},
|
||||
},
|
||||
documentation = {
|
||||
auto_show = true,
|
||||
auto_show = false,
|
||||
auto_show_delay_ms = 500,
|
||||
},
|
||||
ghost_text = {
|
||||
enabled = false,
|
||||
@@ -97,12 +98,12 @@ return {
|
||||
-- elsewhere in your config, without redefining it, via `opts_extend`
|
||||
sources = {
|
||||
default = {
|
||||
'lazydev',
|
||||
'lsp',
|
||||
'snippets',
|
||||
'copilot',
|
||||
'path',
|
||||
'snippets',
|
||||
'buffer',
|
||||
'lazydev',
|
||||
},
|
||||
providers = {
|
||||
copilot = {
|
||||
@@ -118,6 +119,15 @@ return {
|
||||
},
|
||||
},
|
||||
|
||||
-- Blink.cmp includes an optional, recommended rust fuzzy matcher,
|
||||
-- which automatically downloads a prebuilt binary when enabled.
|
||||
--
|
||||
-- By default, we use the Lua implementation instead, but you may enable
|
||||
-- the rust implementation via `'prefer_rust_with_warning'`
|
||||
--
|
||||
-- See :h blink-cmp-config-fuzzy for more information
|
||||
fuzzy = { implementation = 'lua' },
|
||||
|
||||
-- experimental signature help support
|
||||
signature = { enabled = true },
|
||||
},
|
||||
|
||||
@@ -1,17 +1,9 @@
|
||||
return {
|
||||
-- A better annotation generator.
|
||||
-- Supports multiple languages and annotation conventions.
|
||||
-- https://github.com/danymat/neogen
|
||||
{
|
||||
'danymat/neogen',
|
||||
version = '*',
|
||||
opts = { enabled = true, snippet_engine = 'luasnip' },
|
||||
},
|
||||
|
||||
-- Terminal manager for (neo)vim
|
||||
-- https://github.com/voldikss/vim-floaterm
|
||||
{
|
||||
'voldikss/vim-floaterm',
|
||||
lazy = true,
|
||||
cmd = { 'FloatermToggle' },
|
||||
init = function()
|
||||
vim.g.floaterm_width = 0.8
|
||||
@@ -49,34 +41,6 @@ return {
|
||||
end,
|
||||
},
|
||||
|
||||
-- Cloak allows you to overlay *'s over defined patterns in defined files.
|
||||
-- https://github.com/laytan/cloak.nvim
|
||||
{
|
||||
'laytan/cloak.nvim',
|
||||
version = '*',
|
||||
opts = {
|
||||
enabled = true,
|
||||
cloak_character = '*',
|
||||
-- The applied highlight group (colors) on the cloaking, see `:h highlight`.
|
||||
highlight_group = 'Comment',
|
||||
patterns = {
|
||||
{
|
||||
-- Match any file starting with ".env".
|
||||
-- This can be a table to match multiple file patterns.
|
||||
file_pattern = {
|
||||
'.env*',
|
||||
'wrangler.toml',
|
||||
'.dev.vars',
|
||||
},
|
||||
-- Match an equals sign and any character after it.
|
||||
-- This can also be a table of patterns to cloak,
|
||||
-- example: cloak_pattern = { ":.+", "-.+" } for yaml files.
|
||||
cloak_pattern = '=.+',
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
|
||||
-- projectionist.vim: Granular project configuration
|
||||
-- https://github.com/tpope/vim-projectionist
|
||||
{
|
||||
@@ -150,21 +114,7 @@ return {
|
||||
{
|
||||
'whatyouhide/vim-textobj-xmlattr',
|
||||
dependencies = { 'kana/vim-textobj-user' },
|
||||
},
|
||||
|
||||
-- Describe the regexp under the cursor
|
||||
-- https://github.com/bennypowers/nvim-regexplainer
|
||||
{
|
||||
'bennypowers/nvim-regexplainer',
|
||||
event = 'BufEnter',
|
||||
dependencies = {
|
||||
'nvim-treesitter/nvim-treesitter',
|
||||
'MunifTanjim/nui.nvim',
|
||||
},
|
||||
opts = {
|
||||
-- automatically show the explainer when the cursor enters a regexp
|
||||
auto = true,
|
||||
},
|
||||
ft = { 'html', 'xml', 'javascriptreact', 'typescriptreact', 'vue' },
|
||||
},
|
||||
|
||||
-- Clarify and beautify your comments using boxes and lines.
|
||||
@@ -174,38 +124,4 @@ return {
|
||||
event = 'BufEnter',
|
||||
opts = {},
|
||||
},
|
||||
|
||||
-- Plugin to improve viewing Markdown files in Neovim
|
||||
-- https://github.com/MeanderingProgrammer/render-markdown.nvim
|
||||
{
|
||||
'MeanderingProgrammer/render-markdown.nvim',
|
||||
event = 'BufEnter',
|
||||
dependencies = {
|
||||
'nvim-treesitter/nvim-treesitter',
|
||||
'nvim-tree/nvim-web-devicons',
|
||||
},
|
||||
ft = 'markdown',
|
||||
opts = {},
|
||||
},
|
||||
|
||||
{
|
||||
'ray-x/go.nvim',
|
||||
dependencies = { -- optional packages
|
||||
'ray-x/guihua.lua',
|
||||
'neovim/nvim-lspconfig',
|
||||
'nvim-treesitter/nvim-treesitter',
|
||||
},
|
||||
config = function() require('go').setup() end,
|
||||
event = { 'CmdlineEnter' },
|
||||
ft = { 'go', 'gomod' },
|
||||
build = ':lua require("go.install").update_all_sync()', -- if you need to install/update all binaries
|
||||
},
|
||||
|
||||
-- Mainly a PHP Language Server with more features than you can shake a stick at
|
||||
-- https://github.com/phpactor/phpactor
|
||||
{
|
||||
'phpactor/phpactor',
|
||||
build = 'composer install --no-dev --optimize-autoloader',
|
||||
ft = 'php',
|
||||
},
|
||||
}
|
||||
|
||||
66
config/nvim/lua/plugins/conform.lua
Normal file
66
config/nvim/lua/plugins/conform.lua
Normal file
@@ -0,0 +1,66 @@
|
||||
return {
|
||||
{
|
||||
'stevearc/conform.nvim',
|
||||
event = 'BufWritePre',
|
||||
config = function()
|
||||
local conform = require 'conform'
|
||||
|
||||
conform.setup {
|
||||
formatters_by_ft = {
|
||||
lua = { 'stylua' },
|
||||
},
|
||||
format_on_save = function(bufnr)
|
||||
-- Disable autoformat for files in a certain paths
|
||||
local bufname = vim.api.nvim_buf_get_name(bufnr)
|
||||
if bufname:match '/dist|node_modules|vendor/' then return end
|
||||
|
||||
local disable_lsp = {
|
||||
c = true,
|
||||
cpp = true,
|
||||
}
|
||||
return {
|
||||
lsp_fallback = not disable_lsp[vim.bo[bufnr].filetype],
|
||||
timeout_ms = 500,
|
||||
}
|
||||
end,
|
||||
notify_on_error = true,
|
||||
}
|
||||
|
||||
vim.o.formatexpr = "v:lua.require'conform'.formatexpr()"
|
||||
|
||||
-- Autoformat toggle keybinding
|
||||
local autoformat = true
|
||||
vim.g.autoformat_enabled = autoformat
|
||||
|
||||
vim.api.nvim_create_user_command('ToggleFormat', function()
|
||||
autoformat = not autoformat
|
||||
vim.g.autoformat_enabled = autoformat
|
||||
vim.notify('Autoformat on save: ' .. (autoformat and 'enabled' or 'disabled'))
|
||||
end, {})
|
||||
|
||||
vim.keymap.set(
|
||||
'n',
|
||||
'<leader>tf',
|
||||
':ToggleFormat<CR>',
|
||||
{ desc = 'Toggle autoformat on save' }
|
||||
)
|
||||
|
||||
vim.api.nvim_create_autocmd('BufWritePre', {
|
||||
callback = function(args)
|
||||
if autoformat then
|
||||
conform.format {
|
||||
bufnr = args.buf,
|
||||
async = true,
|
||||
lsp_format = 'fallback',
|
||||
}
|
||||
end
|
||||
end,
|
||||
})
|
||||
|
||||
-- Global statusline helper function
|
||||
function _G.autoformat_status()
|
||||
return vim.g.autoformat_enabled and '[ fmt:on]' or '[ fmt:off]'
|
||||
end
|
||||
end,
|
||||
},
|
||||
}
|
||||
@@ -2,15 +2,17 @@ return {
|
||||
-- A collection of small QoL plugins for Neovim
|
||||
-- https://github.com/folke/snacks.nvim
|
||||
{
|
||||
---@module 'snacks'
|
||||
'folke/snacks.nvim',
|
||||
priority = 1000,
|
||||
lazy = false,
|
||||
---@diagnostic disable-next-line: undefined-doc-name
|
||||
---@type snacks.Config
|
||||
opts = {
|
||||
bigfile = { enabled = true },
|
||||
input = {
|
||||
input = { enabled = true },
|
||||
notifier = {
|
||||
enabled = true,
|
||||
timeout = 3000,
|
||||
},
|
||||
gitbrowse = { enabled = true },
|
||||
quickfile = { enabled = true },
|
||||
@@ -20,7 +22,7 @@ return {
|
||||
right = { 'fold', 'git' }, -- priority of signs on the right (high to low)
|
||||
folds = {
|
||||
open = true, -- show open fold icons
|
||||
git_hl = false, -- use Git Signs hl for fold icons
|
||||
git_hl = true, -- use Git Signs hl for fold icons
|
||||
},
|
||||
git = {
|
||||
-- patterns to match Git signs
|
||||
@@ -41,8 +43,14 @@ return {
|
||||
-- replaces the UI for messages, cmdline and the popupmenu.
|
||||
-- https://github.com/folke/noice.nvim
|
||||
{
|
||||
---@module 'noice'
|
||||
'folke/noice.nvim',
|
||||
event = 'VeryLazy',
|
||||
dependencies = {
|
||||
-- if you lazy-load any plugin below, make sure to add proper `module="..."` entries
|
||||
'MunifTanjim/nui.nvim',
|
||||
'rcarriga/nvim-notify',
|
||||
},
|
||||
opts = {
|
||||
lsp = {
|
||||
-- override markdown rendering so that **cmp** and other plugins use **Treesitter**
|
||||
@@ -65,7 +73,10 @@ return {
|
||||
filter = {
|
||||
event = 'msg_show',
|
||||
kind = '',
|
||||
find = 'written',
|
||||
any = {
|
||||
{ find = 'written' },
|
||||
{ find = '%d of %d --%d%--' },
|
||||
},
|
||||
},
|
||||
opts = { skip = true },
|
||||
},
|
||||
@@ -106,14 +117,6 @@ return {
|
||||
},
|
||||
},
|
||||
},
|
||||
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,
|
||||
@@ -121,10 +124,12 @@ return {
|
||||
-- trouble your code is causing.
|
||||
-- https://github.com/folke/trouble.nvim
|
||||
{
|
||||
---@module 'trouble'
|
||||
'folke/trouble.nvim',
|
||||
lazy = false,
|
||||
cmd = 'Trouble',
|
||||
dependencies = { 'nvim-tree/nvim-web-devicons' },
|
||||
---@type trouble.Config
|
||||
opts = {
|
||||
auto_preview = true,
|
||||
auto_fold = true,
|
||||
@@ -136,7 +141,7 @@ return {
|
||||
},
|
||||
modes = {
|
||||
diagnostics = {
|
||||
auto_open = true,
|
||||
auto_open = false,
|
||||
},
|
||||
test = {
|
||||
mode = 'diagnostics',
|
||||
@@ -144,7 +149,7 @@ return {
|
||||
type = 'split',
|
||||
relative = 'win',
|
||||
position = 'right',
|
||||
size = 0.3,
|
||||
size = 0.25,
|
||||
},
|
||||
},
|
||||
cascade = {
|
||||
@@ -163,13 +168,4 @@ return {
|
||||
},
|
||||
},
|
||||
},
|
||||
|
||||
-- Navigate your code with search labels, enhanced
|
||||
-- character motions and Treesitter integration
|
||||
-- https://github.com/folke/flash.nvim
|
||||
{
|
||||
'folke/flash.nvim',
|
||||
event = 'VeryLazy',
|
||||
opts = {},
|
||||
},
|
||||
}
|
||||
|
||||
@@ -4,359 +4,296 @@
|
||||
|
||||
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 = {},
|
||||
diagnosticls = {},
|
||||
gopls = {
|
||||
settings = {
|
||||
gopls = {
|
||||
hints = {
|
||||
rangeVariableTypes = true,
|
||||
parameterNames = true,
|
||||
constantValues = true,
|
||||
assignVariableTypes = true,
|
||||
compositeLiteralFields = true,
|
||||
compositeLiteralTypes = true,
|
||||
functionTypeParameters = true,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
html = {},
|
||||
intelephense = {
|
||||
init_options = {
|
||||
licenceKey = GetIntelephenseLicense(),
|
||||
},
|
||||
},
|
||||
jsonls = {},
|
||||
lua_ls = {
|
||||
settings = {
|
||||
Lua = {
|
||||
completion = {
|
||||
callSnippet = 'Replace',
|
||||
},
|
||||
diagnostics = {
|
||||
globals = {
|
||||
'vim',
|
||||
},
|
||||
disable = {
|
||||
-- Ignore lua_ls noisy `missing-fields` warnings
|
||||
'missing-fields',
|
||||
},
|
||||
},
|
||||
hint = {
|
||||
enable = true,
|
||||
arrayIndex = 'Auto',
|
||||
await = true,
|
||||
paramName = 'All',
|
||||
paramType = true,
|
||||
semicolon = 'SameLine',
|
||||
setType = false,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
tailwindcss = {},
|
||||
ts_ls = {
|
||||
settings = {
|
||||
typescript = {
|
||||
inlayHints = {
|
||||
includeInlayParameterNameHints = 'all',
|
||||
includeInlayParameterNameHintsWhenArgumentMatchesName = false,
|
||||
includeInlayFunctionParameterTypeHints = true,
|
||||
includeInlayVariableTypeHints = true,
|
||||
includeInlayVariableTypeHintsWhenTypeMatchesName = false,
|
||||
includeInlayPropertyDeclarationTypeHints = true,
|
||||
includeInlayFunctionLikeReturnTypeHints = true,
|
||||
includeInlayEnumMemberValueHints = true,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
vimls = {},
|
||||
volar = {
|
||||
settings = {
|
||||
typescript = {
|
||||
inlayHints = {
|
||||
enumMemberValues = {
|
||||
enabled = true,
|
||||
},
|
||||
functionLikeReturnTypes = {
|
||||
enabled = true,
|
||||
},
|
||||
propertyDeclarationTypes = {
|
||||
enabled = true,
|
||||
},
|
||||
parameterTypes = {
|
||||
enabled = true,
|
||||
suppressWhenArgumentMatchesName = true,
|
||||
},
|
||||
variableTypes = {
|
||||
enabled = true,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
-- Mason tools to automatically install and configure.
|
||||
-- These are automatically configured by WhoIsSethDaniel/mason-tool-installer.nvim
|
||||
local mason_tools = {
|
||||
'actionlint',
|
||||
'ast-grep',
|
||||
'black',
|
||||
'editorconfig-checker',
|
||||
'goimports',
|
||||
'golangci-lint',
|
||||
'golines',
|
||||
'gopls',
|
||||
'gotests',
|
||||
'isort',
|
||||
'phpcbf',
|
||||
'phpmd',
|
||||
'phpstan',
|
||||
'pint',
|
||||
'prettierd',
|
||||
'revive',
|
||||
'semgrep',
|
||||
'shellcheck',
|
||||
'shfmt',
|
||||
'sonarlint-language-server',
|
||||
'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
|
||||
-- https://github.com/folke/lazydev.nvim
|
||||
{
|
||||
'folke/lazydev.nvim',
|
||||
ft = 'lua',
|
||||
opts = {
|
||||
library = {
|
||||
-- Load luvit types when the `vim.uv` word is found
|
||||
{ path = 'luvit-meta/library', words = { 'vim%.uv' } },
|
||||
-- load assert and describe paths
|
||||
{ path = 'luassert/library', words = { 'assert' } },
|
||||
{ path = 'busted/library', words = { 'describe' } },
|
||||
},
|
||||
'neovim/nvim-lspconfig',
|
||||
dependencies = {
|
||||
{ 'williamboman/mason.nvim', opts = {} },
|
||||
'williamboman/mason-lspconfig.nvim',
|
||||
'WhoIsSethDaniel/mason-tool-installer.nvim',
|
||||
|
||||
'folke/lazydev.nvim',
|
||||
'zapling/mason-conform.nvim',
|
||||
|
||||
-- Allows extra capabilities provided by blink.cmp
|
||||
'saghen/blink.cmp',
|
||||
},
|
||||
},
|
||||
config = function()
|
||||
local lazydev = require 'lazydev'
|
||||
|
||||
-- Meta type definitions for the Lua platform Luvit.
|
||||
-- https://github.com/Bilal2453/luvit-meta
|
||||
{ 'Bilal2453/luvit-meta', lazy = true },
|
||||
|
||||
-- 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 = 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',
|
||||
opts = {
|
||||
default_mappings = false,
|
||||
servers = lsp_servers,
|
||||
},
|
||||
config = function(_, opts)
|
||||
require('lazydev').setup()
|
||||
require('lsp-setup').setup(opts)
|
||||
local cmp = require 'blink.cmp'
|
||||
local lspconfig = require 'lspconfig'
|
||||
for server, config in pairs(opts.servers) do
|
||||
-- passing config.capabilities to blink.cmp merges with the capabilities in your
|
||||
-- `opts[server].capabilities, if you've defined it
|
||||
config.capabilities = cmp.get_lsp_capabilities(config.capabilities)
|
||||
lspconfig[server].setup(config)
|
||||
end
|
||||
|
||||
lspconfig.lua_ls.on_init = function(client)
|
||||
if client.workspace_folders then
|
||||
local path = client.workspace_folders[1].name
|
||||
if
|
||||
vim.loop.fs_stat(path .. '/.luarc.json')
|
||||
or vim.loop.fs_stat(path .. '/.luarc.jsonc')
|
||||
then
|
||||
return
|
||||
vim.api.nvim_create_autocmd('LspAttach', {
|
||||
group = vim.api.nvim_create_augroup('lsp-attach', { clear = true }),
|
||||
callback = function(event)
|
||||
local map = function(keys, func, desc, mode)
|
||||
mode = mode or 'n'
|
||||
vim.keymap.set(
|
||||
mode,
|
||||
keys,
|
||||
func,
|
||||
{ buffer = event.buf, desc = 'LSP: ' .. desc }
|
||||
)
|
||||
end
|
||||
end
|
||||
client.config.settings.Lua =
|
||||
vim.tbl_deep_extend('force', client.config.settings.Lua, {
|
||||
runtime = {
|
||||
-- Tell the language server which version of Lua you're using
|
||||
-- (most likely LuaJIT in the case of Neovim)
|
||||
version = 'LuaJIT',
|
||||
},
|
||||
-- Make the server aware of Neovim runtime files
|
||||
workspace = {
|
||||
checkThirdParty = false,
|
||||
library = {
|
||||
vim.env.VIMRUNTIME,
|
||||
|
||||
local tsb = require 'telescope.builtin'
|
||||
|
||||
-- Rename the variable under your cursor.
|
||||
-- Most Language Servers support renaming across files, etc.
|
||||
map('grn', vim.lsp.buf.rename, '[R]e[n]ame')
|
||||
|
||||
-- Execute a code action, usually your cursor needs to be on top of an error
|
||||
-- or a suggestion from your LSP for this to activate.
|
||||
map('gra', vim.lsp.buf.code_action, '[G]oto Code [A]ction', { 'n', 'x' })
|
||||
|
||||
-- Find references for the word under your cursor.
|
||||
map('grr', tsb.lsp_references, '[G]oto [R]eferences')
|
||||
|
||||
-- Jump to the implementation of the word under your cursor.
|
||||
-- Useful when your language has ways of declaring types without
|
||||
-- an actual implementation.
|
||||
map('gri', tsb.lsp_implementations, '[G]oto [I]mplementation')
|
||||
|
||||
-- Jump to the definition of the word under your cursor.
|
||||
-- This is where a variable was first declared, or where a function is
|
||||
-- defined, etc. To jump back, press <C-t>.
|
||||
map('grd', tsb.lsp_definitions, '[G]oto [D]efinition')
|
||||
|
||||
-- WARN: This is not Goto Definition, this is Goto Declaration.
|
||||
-- For example, in C this would take you to the header.
|
||||
map('grD', vim.lsp.buf.declaration, '[G]oto [D]eclaration')
|
||||
|
||||
-- Fuzzy find all the symbols in your current document.
|
||||
-- Symbols are things like variables, functions, types, etc.
|
||||
map('gO', tsb.lsp_document_symbols, 'Open Document Symbols')
|
||||
|
||||
-- Fuzzy find all the symbols in your current workspace.
|
||||
-- Similar to document symbols, except searches over your entire project.
|
||||
map('gW', tsb.lsp_dynamic_workspace_symbols, 'Open Workspace Symbols')
|
||||
|
||||
-- Jump to the type of the word under your cursor.
|
||||
-- Useful when you're not sure what type a variable is and you want to see
|
||||
-- the definition of its *type*, not where it was *defined*.
|
||||
map('grt', tsb.lsp_type_definitions, '[G]oto [T]ype Definition')
|
||||
|
||||
-- This function resolves a difference between neovim nightly
|
||||
-- (version 0.11) and stable (version 0.10)
|
||||
---@param client vim.lsp.Client
|
||||
---@param method vim.lsp.protocol.Method
|
||||
---@param bufnr? integer some lsp support methods only in specific files
|
||||
---@return boolean
|
||||
local function client_supports_method(client, method, bufnr)
|
||||
if vim.fn.has 'nvim-0.11' == 1 then
|
||||
return client:supports_method(method, bufnr)
|
||||
else
|
||||
---@diagnostic disable-next-line: param-type-mismatch
|
||||
return client.supports_method(method, { bufnr = bufnr })
|
||||
end
|
||||
end
|
||||
|
||||
-- The following two autocommands are used to highlight references of the
|
||||
-- word under your cursor when your cursor rests there for a little while.
|
||||
-- See `:help CursorHold` for information about when this is executed
|
||||
--
|
||||
-- When you move your cursor, the highlights will be cleared
|
||||
-- (the second autocommand).
|
||||
local client = vim.lsp.get_client_by_id(event.data.client_id)
|
||||
if
|
||||
client
|
||||
and client_supports_method(
|
||||
client,
|
||||
vim.lsp.protocol.Methods.textDocument_documentHighlight,
|
||||
event.buf
|
||||
)
|
||||
then
|
||||
local highlight_augroup =
|
||||
vim.api.nvim_create_augroup('lsp-highlight', { clear = false })
|
||||
vim.api.nvim_create_autocmd({ 'CursorHold', 'CursorHoldI' }, {
|
||||
buffer = event.buf,
|
||||
group = highlight_augroup,
|
||||
callback = vim.lsp.buf.document_highlight,
|
||||
})
|
||||
|
||||
vim.api.nvim_create_autocmd({ 'CursorMoved', 'CursorMovedI' }, {
|
||||
buffer = event.buf,
|
||||
group = highlight_augroup,
|
||||
callback = vim.lsp.buf.clear_references,
|
||||
})
|
||||
|
||||
vim.api.nvim_create_autocmd('LspDetach', {
|
||||
group = vim.api.nvim_create_augroup('lsp-detach', { clear = true }),
|
||||
callback = function(event2)
|
||||
vim.lsp.buf.clear_references()
|
||||
vim.api.nvim_clear_autocmds {
|
||||
group = 'lsp-highlight',
|
||||
buffer = event2.buf,
|
||||
}
|
||||
end,
|
||||
})
|
||||
end
|
||||
end,
|
||||
})
|
||||
|
||||
-- Diagnostic Config
|
||||
-- See :help vim.diagnostic.Opts
|
||||
vim.diagnostic.config {
|
||||
severity_sort = true,
|
||||
float = { border = 'rounded', source = 'if_many' },
|
||||
underline = { severity = vim.diagnostic.severity.ERROR },
|
||||
signs = vim.g.have_nerd_font and {
|
||||
text = {
|
||||
[vim.diagnostic.severity.ERROR] = ' ',
|
||||
[vim.diagnostic.severity.WARN] = ' ',
|
||||
[vim.diagnostic.severity.INFO] = ' ',
|
||||
[vim.diagnostic.severity.HINT] = ' ',
|
||||
},
|
||||
} or {},
|
||||
virtual_text = {
|
||||
source = 'if_many',
|
||||
spacing = 2,
|
||||
format = function(diagnostic)
|
||||
local diagnostic_message = {
|
||||
[vim.diagnostic.severity.ERROR] = diagnostic.message,
|
||||
[vim.diagnostic.severity.WARN] = diagnostic.message,
|
||||
[vim.diagnostic.severity.INFO] = diagnostic.message,
|
||||
[vim.diagnostic.severity.HINT] = diagnostic.message,
|
||||
}
|
||||
return diagnostic_message[diagnostic.severity]
|
||||
end,
|
||||
},
|
||||
}
|
||||
|
||||
local capabilities = require('blink.cmp').get_lsp_capabilities()
|
||||
|
||||
local servers = {
|
||||
ansiblels = {},
|
||||
ast_grep = {},
|
||||
bashls = {},
|
||||
cssls = {},
|
||||
dockerls = {},
|
||||
gopls = {
|
||||
settings = {
|
||||
gopls = {
|
||||
hints = {
|
||||
assignVariableTypes = true,
|
||||
compositeLiteralFields = true,
|
||||
compositeLiteralTypes = true,
|
||||
constantValues = true,
|
||||
functionTypeParameters = true,
|
||||
parameterNames = true,
|
||||
rangeVariableTypes = true,
|
||||
},
|
||||
},
|
||||
})
|
||||
end
|
||||
lspconfig.jsonls.settings = {
|
||||
json = {
|
||||
schemas = require('schemastore').json.schemas(),
|
||||
validate = { enable = true },
|
||||
},
|
||||
yaml = {
|
||||
schemaStore = {
|
||||
-- You must disable built-in SchemaStore support if you want to use
|
||||
-- this plugin and its advanced options like `ignore`.
|
||||
enable = false,
|
||||
-- Avoid TypeError: Cannot read properties of undefined (reading 'length')
|
||||
url = '',
|
||||
},
|
||||
schemas = require('schemastore').yaml.schemas(),
|
||||
validate = { enable = true },
|
||||
},
|
||||
html = {},
|
||||
intelephense = {
|
||||
init_options = {
|
||||
licenceKey = vim.env.INTELEPHENSE_LICENSE or GetIntelephenseLicense() or nil,
|
||||
},
|
||||
},
|
||||
jsonls = {},
|
||||
lua_ls = {
|
||||
settings = {
|
||||
Lua = {
|
||||
diagnostics = {
|
||||
globals = { 'vim' },
|
||||
disable = { 'missing-fields' },
|
||||
},
|
||||
completion = { callSnippet = 'Replace' },
|
||||
workspace = { checkThirdParty = true },
|
||||
hint = {
|
||||
enable = true,
|
||||
arrayIndex = 'Auto',
|
||||
await = true,
|
||||
paramName = 'All',
|
||||
paramType = true,
|
||||
semicolon = 'SameLine',
|
||||
setType = false,
|
||||
},
|
||||
},
|
||||
},
|
||||
on_init = function(client)
|
||||
client.config.settings.Lua.workspace.library = {
|
||||
vim.env.VIMRUNTIME,
|
||||
}
|
||||
client.config.settings.Lua.runtime = { version = 'LuaJIT' }
|
||||
client.notify(
|
||||
'workspace/didChangeConfiguration',
|
||||
{ settings = client.config.settings }
|
||||
)
|
||||
end,
|
||||
},
|
||||
omnisharp = {}, -- C# OmniSharp (will respect EditorConfig for formatting)
|
||||
pyright = {},
|
||||
tailwindcss = {},
|
||||
terraformls = {},
|
||||
ts_ls = {},
|
||||
volar = {
|
||||
settings = {
|
||||
typescript = {
|
||||
inlayHints = {
|
||||
enumMemberValues = { enabled = true },
|
||||
functionLikeReturnTypes = { enabled = true },
|
||||
propertyDeclarationTypes = { enabled = true },
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
vimls = {},
|
||||
eslint = {},
|
||||
yamlls = {
|
||||
settings = {
|
||||
yaml = {
|
||||
keyOrdering = false, -- don't auto-sort YAML keys on format
|
||||
schemaStore = { enable = true }, -- use JSON Schema Store for validation
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
-- Diagnostic configuration
|
||||
local signs = {
|
||||
{ name = 'DiagnosticSignError', text = '' }, -- Error icon
|
||||
{ name = 'DiagnosticSignWarn', text = '' }, -- Warning icon
|
||||
{ name = 'DiagnosticSignHint', text = '' }, -- Hint icon
|
||||
{ name = 'DiagnosticSignInfo', text = '' }, -- Information icon
|
||||
local ensure_installed = vim.tbl_keys(servers or {})
|
||||
vim.list_extend(ensure_installed, {
|
||||
'actionlint', -- GitHub Actions linter
|
||||
'shfmt', -- Shell formatter
|
||||
'stylua', -- Lua formatter
|
||||
'shellcheck', -- Shell linter
|
||||
})
|
||||
|
||||
require('mason-tool-installer').setup {
|
||||
auto_install = true,
|
||||
auto_update = true,
|
||||
ensure_installed = ensure_installed,
|
||||
}
|
||||
|
||||
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
|
||||
require('mason-conform').setup {
|
||||
ensure_installed = ensure_installed,
|
||||
}
|
||||
|
||||
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
|
||||
require('mason-lspconfig').setup {
|
||||
ensure_installed = {}, -- explicitly set to an empty table
|
||||
automatic_installation = false,
|
||||
handlers = {
|
||||
function(server_name)
|
||||
local server = servers[server_name] or {}
|
||||
server.capabilities =
|
||||
vim.tbl_deep_extend('force', {}, capabilities, server.capabilities or {})
|
||||
require('lspconfig')[server_name].setup(server)
|
||||
end,
|
||||
},
|
||||
update_in_insert = false,
|
||||
underline = true,
|
||||
severity_sort = true,
|
||||
virtual_text = true,
|
||||
}
|
||||
|
||||
vim.diagnostic.config(diagnostics_config)
|
||||
|
||||
-- end of junnplus/lsp-setup config
|
||||
lazydev.setup {
|
||||
---@type boolean|(fun(root:string):boolean?)
|
||||
enabled = true,
|
||||
debug = false,
|
||||
runtime = vim.env.VIMRUNTIME --[[@as string]],
|
||||
library = {
|
||||
{ path = '${3rd}/luv/library', words = { 'vim%.uv' } },
|
||||
},
|
||||
integrations = {
|
||||
lspconfig = true,
|
||||
cmp = true,
|
||||
},
|
||||
}
|
||||
end,
|
||||
},
|
||||
|
||||
-- Lightweight yet powerful formatter plugin for Neovim
|
||||
-- https://github.com/stevearc/conform.nvim
|
||||
{
|
||||
'stevearc/conform.nvim',
|
||||
event = { 'BufWritePre' },
|
||||
cmd = { 'ConformInfo' },
|
||||
opts = {
|
||||
notify_on_error = false,
|
||||
---@type nil|conform.FormatOpts|fun(bufnr: integer): nil|conform.FormatOpts
|
||||
format_on_save = function(bufnr)
|
||||
-- Disable "format_on_save lsp_fallback" for languages that don't
|
||||
-- have a well standardized coding style. You can add additional
|
||||
-- languages here or re-enable it for the disabled ones.
|
||||
local disable_filetypes = { c = true, cpp = true }
|
||||
local lsp_format_opt
|
||||
if disable_filetypes[vim.bo[bufnr].filetype] then
|
||||
lsp_format_opt = 'never'
|
||||
else
|
||||
lsp_format_opt = 'fallback'
|
||||
end
|
||||
|
||||
-- Disable autoformat for files in a certain paths
|
||||
local bufname = vim.api.nvim_buf_get_name(bufnr)
|
||||
if bufname:match '/dist|node_modules|vendor/' then return end
|
||||
|
||||
return {
|
||||
timeout_ms = 500,
|
||||
lsp_format = lsp_format_opt,
|
||||
}
|
||||
end,
|
||||
formatters_by_ft = {
|
||||
lua = { 'stylua' },
|
||||
sh = { 'shfmt' },
|
||||
bash = { 'shfmt' },
|
||||
php = { 'phpcbf' },
|
||||
python = { 'isort', 'black' },
|
||||
-- Conform can also run multiple formatters sequentially
|
||||
-- python = { "isort", "black" },
|
||||
--
|
||||
-- You can use 'stop_after_first' to run the first available formatter from the list
|
||||
-- javascript = { "prettierd", "prettier", stop_after_first = true },
|
||||
},
|
||||
},
|
||||
init = function()
|
||||
-- If you want the formatexpr, here is the place to set it
|
||||
vim.o.formatexpr = "v:lua.require'conform'.formatexpr()"
|
||||
end,
|
||||
},
|
||||
-- Automatically install formatters registered with conform.nvim via mason.nvim
|
||||
-- https://github.com/zapling/mason-conform.nvim
|
||||
{ 'zapling/mason-conform.nvim', opts = {} },
|
||||
}
|
||||
|
||||
@@ -12,6 +12,42 @@ return {
|
||||
version = '*',
|
||||
priority = 1001,
|
||||
config = function()
|
||||
-- ╭─────────────────────────────────────────────────────────╮
|
||||
-- │ Text editing │
|
||||
-- ╰─────────────────────────────────────────────────────────╯
|
||||
|
||||
-- Better Around/Inside textobjects
|
||||
-- Examples:
|
||||
-- - va) - [V]isually select [A]round [)]paren
|
||||
-- - yinq - [Y]ank [I]nside [N]ext [Q]uote
|
||||
-- - ci' - [C]hange [I]nside [']quote
|
||||
require('mini.ai').setup { n_lines = 500 }
|
||||
|
||||
-- Comment lines
|
||||
require('mini.comment').setup()
|
||||
|
||||
-- Text edit operators
|
||||
-- g= - Evaluate text and replace with output
|
||||
-- gx - Exchange text regions
|
||||
-- gm - Multiply (duplicate) text
|
||||
-- gr - Replace text with register
|
||||
-- gs - Sort text
|
||||
require('mini.operators').setup()
|
||||
|
||||
-- Split and join arguments, lists, and other sequences
|
||||
require('mini.splitjoin').setup()
|
||||
|
||||
-- Fast and feature-rich surround actions
|
||||
-- - saiw) - [S]urround [A]dd [I]nner [W]ord [)]Paren
|
||||
-- - sd' - [S]urround [D]elete [']quotes
|
||||
-- - sr)' - [S]urround [R]eplace [)] [']
|
||||
-- - sff - find right (`sf`) part of surrounding function call (`f`)
|
||||
require('mini.surround').setup()
|
||||
|
||||
-- ╭─────────────────────────────────────────────────────────╮
|
||||
-- │ General workflow │
|
||||
-- ╰─────────────────────────────────────────────────────────╯
|
||||
|
||||
-- Presets for common options and mappings
|
||||
-- h: MiniBasics.config
|
||||
require('mini.basics').setup {
|
||||
@@ -25,17 +61,12 @@ return {
|
||||
},
|
||||
}
|
||||
|
||||
-- Animate common Neovim actions
|
||||
-- Replaced anuvyklack/windows.nvim
|
||||
require('mini.animate').setup()
|
||||
|
||||
-- Buffer removing (unshow, delete, wipeout), which saves window layout
|
||||
-- Replaced famiu/bufdelete.nvim
|
||||
require('mini.bufremove').setup()
|
||||
|
||||
-- Show next key clues
|
||||
-- Replaced folke/which-key.nvim
|
||||
local miniclue = require 'mini.clue'
|
||||
---@modules mini.clue
|
||||
miniclue.setup {
|
||||
window = {
|
||||
config = {
|
||||
@@ -100,22 +131,30 @@ return {
|
||||
},
|
||||
}
|
||||
|
||||
-- Comment lines
|
||||
-- Replaced numToStr/Comment.nvim
|
||||
require('mini.comment').setup()
|
||||
|
||||
-- Highlight cursor word and its matches
|
||||
require('mini.cursorword').setup()
|
||||
|
||||
-- Work with diff hunks
|
||||
-- Replaced lewis6991/gitsigns.nvim
|
||||
require('mini.diff').setup()
|
||||
|
||||
-- Git integration
|
||||
require('mini.git').setup()
|
||||
|
||||
-- Session management (read, write, delete)
|
||||
require('mini.sessions').setup {
|
||||
autowrite = true,
|
||||
directory = vim.g.sessions_dir or vim.fn.stdpath 'data' .. '/sessions',
|
||||
file = '',
|
||||
}
|
||||
|
||||
-- ╭─────────────────────────────────────────────────────────╮
|
||||
-- │ Appearance │
|
||||
-- ╰─────────────────────────────────────────────────────────╯
|
||||
|
||||
-- Animate common Neovim actions
|
||||
require('mini.animate').setup()
|
||||
|
||||
-- Highlight cursor word and its matches
|
||||
require('mini.cursorword').setup()
|
||||
|
||||
-- Highlight patterns in text
|
||||
-- Replaced folke/todo-comments.nvim
|
||||
local hp = require 'mini.hipatterns'
|
||||
hp.setup {
|
||||
highlighters = {
|
||||
@@ -162,36 +201,16 @@ return {
|
||||
}
|
||||
|
||||
-- Visualize and work with indent scope
|
||||
-- Replaced lukas-reineke/indent-blankline.nvim
|
||||
require('mini.indentscope').setup()
|
||||
|
||||
-- Text edit operators
|
||||
-- g= - Evaluate text and replace with output
|
||||
-- gx - Exchange text regions
|
||||
-- gm - Multiply (duplicate) text
|
||||
-- gr - Replace text with register
|
||||
-- gs - Sort text
|
||||
require('mini.operators').setup()
|
||||
|
||||
-- Session management (read, write, delete)
|
||||
require('mini.sessions').setup {
|
||||
autowrite = true,
|
||||
directory = vim.g.sessions_dir or vim.fn.stdpath 'data' .. '/sessions',
|
||||
file = '',
|
||||
}
|
||||
|
||||
-- Split and join arguments, lists, and other sequences
|
||||
-- Replaced Wansmer/treesj
|
||||
require('mini.splitjoin').setup()
|
||||
|
||||
-- Fast and flexible start screen
|
||||
-- Replaced glepnir/dashboard-nvim
|
||||
local starter = require 'mini.starter'
|
||||
---@modules mini.starter
|
||||
starter.setup {
|
||||
items = {
|
||||
starter.sections.telescope(),
|
||||
starter.sections.builtin_actions(),
|
||||
starter.sections.sessions(5, true),
|
||||
starter.sections.recent_files(5),
|
||||
},
|
||||
content_hooks = {
|
||||
starter.gen_hook.adding_bullet(),
|
||||
@@ -201,25 +220,38 @@ return {
|
||||
}
|
||||
|
||||
-- Minimal and fast statusline module with opinionated default look
|
||||
-- Replaced nvim-lualine/lualine.nvim
|
||||
local sl = require 'mini.statusline'
|
||||
---@modules mini.statusline
|
||||
sl.setup {
|
||||
use_icons = true,
|
||||
set_vim_settings = true,
|
||||
content = {
|
||||
active = function()
|
||||
local mode, mode_hl = sl.section_mode { trunc_width = 120 }
|
||||
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 mode, mode_hl = sl.section_mode { trunc_width = 100 }
|
||||
local git = sl.section_git { trunc_width = 40 }
|
||||
local diagnostics = sl.section_diagnostics {
|
||||
trunc_width = 75,
|
||||
signs = {
|
||||
ERROR = 'E ',
|
||||
WARN = 'W ',
|
||||
INFO = 'I ',
|
||||
HINT = 'H ',
|
||||
},
|
||||
}
|
||||
local lsp = MiniStatusline.section_lsp { trunc_width = 75 }
|
||||
local filename = sl.section_filename { trunc_width = 140 }
|
||||
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 } },
|
||||
{
|
||||
hl = 'MiniStatuslineDevinfo',
|
||||
strings = { git, lsp },
|
||||
},
|
||||
'%<', -- Mark general truncate point
|
||||
{ hl = 'statuslineFilename', strings = { filename } },
|
||||
'%=', -- End left alignment
|
||||
{ hl = 'statuslineFileinfo', strings = { diagnostics } },
|
||||
{ hl = 'statuslineFileinfo', strings = { fileinfo } },
|
||||
{ hl = mode_hl, strings = { location } },
|
||||
}
|
||||
@@ -227,13 +259,6 @@ return {
|
||||
},
|
||||
}
|
||||
|
||||
-- Fast and feature-rich surround actions
|
||||
-- Replaced kylechui/nvim-surround
|
||||
-- - saiw) - [S]urround [A]dd [I]nner [W]ord [)]Paren
|
||||
-- - sd' - [S]urround [D]elete [']quotes
|
||||
-- - sr)' - [S]urround [R]eplace [)] [']
|
||||
require('mini.surround').setup()
|
||||
|
||||
-- Work with trailing whitespace
|
||||
require('mini.trailspace').setup()
|
||||
end,
|
||||
|
||||
@@ -54,9 +54,7 @@ return {
|
||||
event_handlers = {
|
||||
{
|
||||
event = 'file_opened',
|
||||
handler = function(_)
|
||||
require('neo-tree.command').execute { action = 'close' }
|
||||
end,
|
||||
handler = function(_) require('neo-tree.command').execute { action = 'close' } end,
|
||||
},
|
||||
},
|
||||
default_component_configs = {
|
||||
|
||||
@@ -1,44 +1,13 @@
|
||||
return {
|
||||
{
|
||||
'rmagatti/auto-session',
|
||||
lazy = false,
|
||||
version = '*',
|
||||
opts = {
|
||||
suppressed_dirs = {
|
||||
'/',
|
||||
'~/',
|
||||
'~/Downloads',
|
||||
'~/Library',
|
||||
},
|
||||
bypass_save_filetypes = {
|
||||
'PlenaryTestPopup',
|
||||
'alpha',
|
||||
'checkhealth',
|
||||
'dashboard',
|
||||
'dbout',
|
||||
'gitsigns.blame',
|
||||
'grug-far',
|
||||
'help',
|
||||
'lspinfo',
|
||||
'man',
|
||||
'neo-tree',
|
||||
'neotest-output',
|
||||
'neotest-output-panel',
|
||||
'neotest-summary',
|
||||
'notify',
|
||||
'qf',
|
||||
'spectre_panel',
|
||||
'startuptime',
|
||||
'trouble',
|
||||
'tsplayground',
|
||||
},
|
||||
-- log_level = 'debug',
|
||||
},
|
||||
},
|
||||
|
||||
{
|
||||
'nvim-lua/plenary.nvim',
|
||||
version = '*',
|
||||
lazy = false,
|
||||
},
|
||||
|
||||
-- Vim plugin for automatic time tracking and metrics
|
||||
-- generated from your programming activity.
|
||||
-- https://github.com/wakatime/vim-wakatime
|
||||
{ 'wakatime/vim-wakatime', lazy = false, enabled = true },
|
||||
}
|
||||
|
||||
@@ -3,7 +3,8 @@ return {
|
||||
-- https://github.com/nvim-telescope/telescope.nvim
|
||||
'nvim-telescope/telescope.nvim',
|
||||
version = '*',
|
||||
lazy = false,
|
||||
lazy = true,
|
||||
cmd = 'Telescope',
|
||||
dependencies = {
|
||||
{ 'nvim-lua/plenary.nvim' },
|
||||
{ 'nvim-telescope/telescope-symbols.nvim' },
|
||||
@@ -16,10 +17,6 @@ return {
|
||||
-- https://github.com/polirritmico/telescope-lazy-plugins.nvim
|
||||
{ 'polirritmico/telescope-lazy-plugins.nvim' },
|
||||
|
||||
-- Neovim plugin. Telescope.nvim extension that adds LuaSnip integration.
|
||||
-- https://github.com/benfowler/telescope-luasnip.nvim
|
||||
{ 'benfowler/telescope-luasnip.nvim' },
|
||||
|
||||
-- Fuzzy Finder Algorithm which requires local dependencies to be built.
|
||||
-- Only load if `make` is available
|
||||
{
|
||||
@@ -27,27 +24,45 @@ return {
|
||||
build = 'make',
|
||||
cond = vim.fn.executable 'make' == 1,
|
||||
},
|
||||
|
||||
-- Import modules with ease
|
||||
-- https://github.com/piersolenski/telescope-import.nvim
|
||||
{ 'piersolenski/telescope-import.nvim' },
|
||||
},
|
||||
config = function()
|
||||
local t = require 'telescope'
|
||||
local a = require 'telescope.actions'
|
||||
local c = require 'telescope.config'
|
||||
|
||||
local open_with_trouble = require('trouble.sources.telescope').open
|
||||
local add_to_trouble = require('trouble.sources.telescope').add
|
||||
|
||||
-- Clone the default Telescope configuration
|
||||
local vimgrep_arguments = { unpack(c.values.vimgrep_arguments) }
|
||||
|
||||
-- I want to search in hidden/dot files.
|
||||
table.insert(vimgrep_arguments, '--hidden')
|
||||
-- I don't want to search in the `.git` directory.
|
||||
table.insert(vimgrep_arguments, '--glob')
|
||||
table.insert(vimgrep_arguments, '!**/.git/*')
|
||||
|
||||
-- [[ Configure Telescope ]]
|
||||
-- See `:help telescope` and `:help telescope.setup()`
|
||||
t.setup {
|
||||
defaults = {
|
||||
-- `hidden = true` is not supported in text grep commands.
|
||||
vimgrep_arguments = vimgrep_arguments,
|
||||
|
||||
layout_strategy = 'horizontal',
|
||||
pickers = {
|
||||
find_files = {
|
||||
-- `hidden = true` will still show the inside of `.git/` as
|
||||
-- it's not `.gitignore`d.
|
||||
find_command = { 'rg', '--files', '--hidden', '--glob', '!**/.git/*' },
|
||||
theme = 'dropdown',
|
||||
},
|
||||
mappings = {
|
||||
i = {
|
||||
['<C-s>'] = a.cycle_previewers_next,
|
||||
['<C-a>'] = a.cycle_previewers_prev,
|
||||
},
|
||||
},
|
||||
},
|
||||
mappings = {
|
||||
i = {
|
||||
@@ -64,28 +79,28 @@ return {
|
||||
},
|
||||
},
|
||||
},
|
||||
highlight = {
|
||||
enable = true,
|
||||
additional_vim_regex_highlighting = false,
|
||||
},
|
||||
incremental_selection = {
|
||||
enable = true,
|
||||
keymaps = {
|
||||
init_selection = '<CR>',
|
||||
node_incremental = '<CR>',
|
||||
scope_incremental = '<TAB>',
|
||||
node_decremental = '<S-TAB>',
|
||||
},
|
||||
},
|
||||
context_commentstring = {
|
||||
enable = true,
|
||||
enable_autocmd = false,
|
||||
},
|
||||
extensions = {
|
||||
lazy_plugins = {
|
||||
-- Must be a valid path to the file containing the lazy spec and setup() call.
|
||||
lazy_config = vim.fn.stdpath 'config' .. '/init.lua',
|
||||
},
|
||||
import = {
|
||||
-- Imports can be added at a specified line whilst keeping the cursor in place
|
||||
insert_at_top = true,
|
||||
-- Optionally support additional languages or modify existing languages...
|
||||
custom_languages = {
|
||||
{
|
||||
-- The filetypes that ripgrep supports (find these via `rg --type-list`)
|
||||
extensions = { 'js', 'ts' },
|
||||
-- The Vim filetypes
|
||||
filetypes = { 'vue' },
|
||||
-- Optionally set a line other than 1
|
||||
insert_at_line = 2, ---@type function|number
|
||||
-- The regex pattern for the import statement
|
||||
regex = [[^(?:import(?:[\"'\s]*([\w*{}\n, ]+)from\s*)?[\"'\s](.*?)[\"'\s].*)]],
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
|
||||
@@ -1,17 +1,8 @@
|
||||
return {
|
||||
-- https://github.com/rmehri01/onenord.nvim
|
||||
{
|
||||
'rmehri01/onenord.nvim',
|
||||
priority = 1000, -- Make sure to load this before all the other start plugins.
|
||||
opts = {
|
||||
borders = true,
|
||||
fade_nc = true,
|
||||
disable = {
|
||||
float_background = true,
|
||||
},
|
||||
},
|
||||
opts = {},
|
||||
},
|
||||
|
||||
-- Automatic dark mode
|
||||
-- https://github.com/f-person/auto-dark-mode.nvim
|
||||
{
|
||||
@@ -33,6 +24,7 @@ return {
|
||||
-- https://github.com/catgoose/nvim-colorizer.lua
|
||||
{
|
||||
'catgoose/nvim-colorizer.lua',
|
||||
event = 'BufReadPre',
|
||||
opts = {
|
||||
user_default_options = {
|
||||
names = false,
|
||||
@@ -40,13 +32,27 @@ return {
|
||||
},
|
||||
},
|
||||
|
||||
-- A neovim plugin that shows colorcolumn dynamically
|
||||
-- https://github.com/Bekaboo/deadcolumn.nvim
|
||||
{ 'Bekaboo/deadcolumn.nvim' },
|
||||
|
||||
-- Remove all background colors to make nvim transparent
|
||||
-- https://github.com/xiyaowong/nvim-transparent
|
||||
{ 'xiyaowong/nvim-transparent', opts = {} },
|
||||
{
|
||||
'xiyaowong/nvim-transparent',
|
||||
lazy = false,
|
||||
config = function()
|
||||
local t = require 'transparent'
|
||||
t.setup {
|
||||
extra_groups = {
|
||||
'NormalNC',
|
||||
'NormalFloat',
|
||||
'FloatBorder',
|
||||
'TelescopeBorder',
|
||||
'TelescopePromptBorder',
|
||||
'TelescopeResultsBorder',
|
||||
'TelescopePreviewBorder',
|
||||
},
|
||||
}
|
||||
t.clear_prefix 'NeoTree'
|
||||
end,
|
||||
},
|
||||
|
||||
-- Display a character as the colorcolumn
|
||||
-- https://github.com/lukas-reineke/virt-column.nvim
|
||||
|
||||
@@ -1,4 +0,0 @@
|
||||
-- Vim plugin for automatic time tracking and metrics
|
||||
-- generated from your programming activity.
|
||||
-- https://github.com/wakatime/vim-wakatime
|
||||
return { 'wakatime/vim-wakatime', lazy = false, enabled = true }
|
||||
31
config/nvim/syntax/env.vim
Normal file
31
config/nvim/syntax/env.vim
Normal file
@@ -0,0 +1,31 @@
|
||||
" Vim syntax file
|
||||
" Language: env files (NOT shell code)
|
||||
" Maintainer: Gernot Schulz <gernot.schulz@overleaf.com>
|
||||
" Source: https://github.com/overleaf/vim-env-syntax
|
||||
|
||||
" quit when a syntax file was already loaded
|
||||
if exists("b:current_syntax")
|
||||
finish
|
||||
endif
|
||||
|
||||
syn match envComment '^#.*'
|
||||
syn match envVariableUnassigned "^\<\h\w*$"
|
||||
|
||||
syn match envVariable "^\<\h\w*\ze=" nextgroup=envVarAssign
|
||||
syn match envVarAssign contained "=" nextgroup=envVar,envQuotedVarOpen,envSpace
|
||||
syn match envVar contained "\h\w*"
|
||||
syn match envSpace contained "\s\+" nextgroup=envQuotedVarOpen
|
||||
syn match envQuotedVarOpen contained "[\"']"
|
||||
|
||||
syn match envSpace "\s$"
|
||||
syn match envQuotedVarClose "[\"']$"
|
||||
|
||||
let b:current_syntax = "env"
|
||||
|
||||
hi def link envComment Comment
|
||||
hi def link envVariableUnassigned Error
|
||||
hi def link envVariable Identifier
|
||||
hi def link envVarAssign Operator
|
||||
hi def link envSpace Error
|
||||
hi def link envQuotedVarOpen Error
|
||||
hi def link envQuotedVarClose Error
|
||||
2
config/op/plugins.sh
Normal file
2
config/op/plugins.sh
Normal file
@@ -0,0 +1,2 @@
|
||||
export OP_PLUGIN_ALIASES_SOURCED=1
|
||||
alias gh="op plugin run -- gh"
|
||||
15
config/op/plugins/gh.json
Normal file
15
config/op/plugins/gh.json
Normal file
@@ -0,0 +1,15 @@
|
||||
{
|
||||
"account_id": "S5Z2DMNFKJEZBPCWRHRWC4DCGI",
|
||||
"entrypoint": [
|
||||
"gh"
|
||||
],
|
||||
"credentials": [
|
||||
{
|
||||
"plugin": "github",
|
||||
"credential_type": "personal_access_token",
|
||||
"usage_id": "personal_access_token",
|
||||
"vault_id": "injcin7obv3jdet3r2u3kfihfy",
|
||||
"item_id": "f6vinbnc6l7ngdzvlw66ayewlq"
|
||||
}
|
||||
]
|
||||
}
|
||||
1
config/op/plugins/used_items/gh.json
Normal file
1
config/op/plugins/used_items/gh.json
Normal file
@@ -0,0 +1 @@
|
||||
[{"account_id":"S5Z2DMNFKJEZBPCWRHRWC4DCGI","vault_id":"injcin7obv3jdet3r2u3kfihfy","item_id":"f6vinbnc6l7ngdzvlw66ayewlq"}]
|
||||
@@ -17,13 +17,53 @@ DEBUG="${DEBUG:-0}"
|
||||
# Enable debugging with DEBUG=1
|
||||
[ "${DEBUG:-0}" -eq 1 ] && set -x
|
||||
|
||||
# Detect the current shell
|
||||
CURRENT_SHELL=$(ps -p $$ -ocomm= | awk -F/ '{print $NF}')
|
||||
|
||||
# Function to prepend a path to PATH based on the shell
|
||||
x-path-prepend()
|
||||
{
|
||||
local dir=$1
|
||||
case "$CURRENT_SHELL" in
|
||||
fish)
|
||||
set -U fish_user_paths "$dir" $fish_user_paths
|
||||
;;
|
||||
sh | bash | zsh)
|
||||
PATH="$dir:$PATH"
|
||||
;;
|
||||
*)
|
||||
echo "Unsupported shell: $CURRENT_SHELL"
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
}
|
||||
|
||||
# Function to set environment variables based on the shell
|
||||
x-set-env()
|
||||
{
|
||||
local var=$1
|
||||
local value=$2
|
||||
case "$CURRENT_SHELL" in
|
||||
fish)
|
||||
set -x "$var" "$value"
|
||||
;;
|
||||
sh | bash | zsh)
|
||||
export "$var=$value"
|
||||
;;
|
||||
*)
|
||||
echo "Unsupported shell: $CURRENT_SHELL"
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
}
|
||||
|
||||
# Explicitly set XDG folders, if not already set
|
||||
# https://specifications.freedesktop.org/basedir-spec/basedir-spec-latest.html
|
||||
[ -z "$XDG_CONFIG_HOME" ] && export XDG_CONFIG_HOME="$HOME/.config"
|
||||
[ -z "$XDG_DATA_HOME" ] && export XDG_DATA_HOME="$HOME/.local/share"
|
||||
[ -z "$XDG_CACHE_HOME" ] && export XDG_CACHE_HOME="$HOME/.cache"
|
||||
[ -z "$XDG_STATE_HOME" ] && export XDG_STATE_HOME="$HOME/.local/state"
|
||||
[ -z "$XDG_BIN_HOME" ] && export XDG_BIN_HOME="$HOME/.local/bin"
|
||||
x-set-env XDG_CONFIG_HOME "$HOME/.config"
|
||||
x-set-env XDG_DATA_HOME "$HOME/.local/share"
|
||||
x-set-env XDG_CACHE_HOME "$HOME/.cache"
|
||||
x-set-env XDG_STATE_HOME "$HOME/.local/state"
|
||||
x-set-env XDG_BIN_HOME "$HOME/.local/bin"
|
||||
|
||||
# Paths
|
||||
x-path-prepend "/usr/local/bin"
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
set-option -g status-style 'fg=#4c4f69,bg=#eff1f5'
|
||||
set-window-option -g window-status-style 'fg=#4c4f69,bg=#eff1f5 dim'
|
||||
set-window-option -g window-status-current-style 'fg=#8839ef,bg=#eff1f5'
|
||||
set-window-option -g window-status-activity-style 'fg=#4c4f69,bg=#eff1f5 nodim'
|
||||
set-window-option -g window-status-bell-style 'fg=#4c4f69,bg=#eff1f5'
|
||||
set-option -g status-style 'fg=#4c4f69,bg=default'
|
||||
set-window-option -g window-status-style 'fg=#4c4f69,bg=default dim'
|
||||
set-window-option -g window-status-current-style 'fg=#8839ef,bg=default'
|
||||
set-window-option -g window-status-activity-style 'fg=#4c4f69,bg=default nodim'
|
||||
set-window-option -g window-status-bell-style 'fg=#4c4f69,bg=default'
|
||||
set -g message-style 'fg=#8839ef bg=#e6e9ef bold' # fg magenta, bg black
|
||||
|
||||
|
||||
@@ -15,6 +15,9 @@
|
||||
# -o : Set the option only if it is not already set.
|
||||
# -u : Unset the specified option.
|
||||
|
||||
set -ag terminal-overrides ",xterm-256color:RGB"
|
||||
set -ag terminal-features 'xterm-256color:RGB'
|
||||
|
||||
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
|
||||
@@ -49,11 +52,12 @@ if-shell '[ "$DEBUG" = "1" ]' 'set -g debug-file ~/.cache/tmux-debug.log'
|
||||
|
||||
set -g pane-active-border-style "fg=#7aa2f7"
|
||||
set -g pane-border-style "fg=#3b4261"
|
||||
set -g status-style "bg=default"
|
||||
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 "#S@#h #{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 '
|
||||
|
||||
@@ -17,7 +17,7 @@ cnoreabbrev Qall qall " quit all
|
||||
"" Mappings
|
||||
"*****************************************************************************
|
||||
|
||||
noremap <C-S> :w<CR> " save buffer
|
||||
noremap <C-s> :w<CR> " save buffer
|
||||
|
||||
" Split
|
||||
noremap <Leader>h :<C-u>split<CR> " horizontal split
|
||||
@@ -57,7 +57,7 @@ noremap <Leader>r :tabe <C-R>=expand("%:p:h") . "/" <CR>
|
||||
" fzf.vim
|
||||
let $FZF_DEFAULT_COMMAND = "find * -path '*/\.*' -prune -o -path 'node_modules/**' -prune -o -path 'target/**' -prune -o -path 'vendor/**' -prune -o -path 'dist/**' -prune -o -type f -print -o -type l -print 2> /dev/null"
|
||||
|
||||
cnoremap <C-P> <C-R>=expand("%:p:h") . "/" <CR>
|
||||
cnoremap <C-p> <C-R>=expand("%:p:h") . "/" <CR>
|
||||
nnoremap <silent> <leader>b :Buffers<CR>
|
||||
nnoremap <silent> <leader>e :FZF -m<CR>
|
||||
" Recovery commands from history through FZF
|
||||
|
||||
@@ -6,7 +6,7 @@ config.set_environment_variables = {
|
||||
}
|
||||
|
||||
-- Font and font size
|
||||
config.font_size = 14.0
|
||||
config.font_size = 14.5
|
||||
config.font = wezterm.font_with_fallback {
|
||||
{
|
||||
family = 'Operator Mono',
|
||||
@@ -17,16 +17,31 @@ config.font = wezterm.font_with_fallback {
|
||||
'JetBrains Mono',
|
||||
'Symbols Nerd Font Mono',
|
||||
}
|
||||
config.harfbuzz_features = { 'zero', 'ss01', 'cv05' }
|
||||
config.font_shaper = 'Harfbuzz'
|
||||
config.harfbuzz_features = { 'calt=1', 'clig=1', 'liga=1' }
|
||||
|
||||
-- Make the window a bit transparent
|
||||
config.window_background_opacity = 0.98
|
||||
config.selection_word_boundary = ' \t\n{[}]()"\'`,;:'
|
||||
|
||||
-- Window configuration
|
||||
config.window_background_opacity = 0.95
|
||||
config.window_decorations = 'RESIZE'
|
||||
config.macos_window_background_blur = 10
|
||||
config.window_padding = {
|
||||
left = 5,
|
||||
right = 5,
|
||||
top = 5,
|
||||
bottom = 5,
|
||||
}
|
||||
|
||||
-- Don't show tab bar
|
||||
config.enable_tab_bar = false
|
||||
|
||||
-- Fix alt on macOS
|
||||
config.send_composed_key_when_left_alt_is_pressed = true
|
||||
config.send_composed_key_when_right_alt_is_pressed = true
|
||||
|
||||
-- Scrolling deactivated, using tmux for that
|
||||
config.scrollback_lines = 0
|
||||
|
||||
-- Function to detect the theme based on appearance
|
||||
function Scheme_for_appearance(appearance)
|
||||
|
||||
@@ -7,7 +7,6 @@
|
||||
# yabai -m signal --add event=dock_did_restart action="sudo yabai --load-sa"
|
||||
|
||||
yabai -m config \
|
||||
active_window_border_color 0xff775759 \
|
||||
auto_balance on \
|
||||
layout bsp \
|
||||
top_padding 0 \
|
||||
|
||||
@@ -3,22 +3,22 @@
|
||||
"metrics": false
|
||||
},
|
||||
"assistant": {
|
||||
"always_allow_tool_actions": false,
|
||||
"default_model": {
|
||||
"provider": "copilot_chat",
|
||||
"model": "claude-3-5-sonnet"
|
||||
"model": "gpt-4.1"
|
||||
},
|
||||
"version": "2"
|
||||
},
|
||||
"formatter": {
|
||||
"external": {
|
||||
"command": "prettier",
|
||||
"arguments": [
|
||||
"--stdin-filepath",
|
||||
"{buffer_path}"
|
||||
]
|
||||
}
|
||||
},
|
||||
"languages": {
|
||||
"Python": {
|
||||
"enable_language_server": true,
|
||||
"allow_rewrap": "anywhere",
|
||||
"auto_indent_on_paste": true
|
||||
},
|
||||
"Shell Script": {
|
||||
"enable_language_server": true
|
||||
},
|
||||
"JavaScript": {
|
||||
"enable_language_server": true,
|
||||
"code_actions_on_format": {
|
||||
@@ -55,8 +55,8 @@
|
||||
"vim_mode": true,
|
||||
"theme": {
|
||||
"mode": "system",
|
||||
"light": "Iceberg",
|
||||
"dark": "Iceberg"
|
||||
"light": "Tokyo Night Light",
|
||||
"dark": "Tokyo Night Storm"
|
||||
},
|
||||
"inlay_hints": {
|
||||
"enabled": true,
|
||||
@@ -66,13 +66,9 @@
|
||||
},
|
||||
"ui_font_size": 16,
|
||||
"buffer_font_size": 16,
|
||||
"buffer_font_fallbacks": [
|
||||
"JetBrainsMono Nerd Font"
|
||||
],
|
||||
"buffer_font_fallbacks": ["JetBrainsMono Nerd Font"],
|
||||
"edit_predictions": {
|
||||
"disabled_globs": [
|
||||
".env"
|
||||
]
|
||||
"disabled_globs": [".env", ".env.*"]
|
||||
},
|
||||
"hour_format": "hour24"
|
||||
}
|
||||
|
||||
@@ -35,11 +35,20 @@
|
||||
glob: true
|
||||
path: base/*
|
||||
prefix: '.'
|
||||
# Most of the configs
|
||||
~/.config/:
|
||||
glob: true
|
||||
relink: true
|
||||
path: config/*
|
||||
exclude: [config/nvm, config/fzf]
|
||||
exclude: [config/nvm, config/fzf, config/op]
|
||||
# 1Password CLI plugins
|
||||
~/.config/op/plugins.sh:
|
||||
relink: true
|
||||
path: config/op/plugins.sh
|
||||
~/.config/op/plugins:
|
||||
relink: true
|
||||
path: config/op/plugins
|
||||
# Scripts
|
||||
~/.local/bin:
|
||||
glob: true
|
||||
path: local/bin/*
|
||||
@@ -47,22 +56,27 @@
|
||||
~/.local/fzf:
|
||||
glob: true
|
||||
path: config/fzf/*
|
||||
# Manuals
|
||||
~/.local/man:
|
||||
glob: true
|
||||
path: local/man/**
|
||||
~/.local/share:
|
||||
glob: true
|
||||
path: local/share/*
|
||||
# SSH Configuration
|
||||
~/.ssh/:
|
||||
glob: true
|
||||
mode: 0600
|
||||
path: ssh/*
|
||||
|
||||
- shell:
|
||||
# Add Git submodules and remove old ones
|
||||
- bash add-submodules.sh || true
|
||||
# Update submodules recursively
|
||||
- git submodule update --init --recursive --force
|
||||
|
||||
- shell:
|
||||
# Use my dotfiles manager to install everything
|
||||
- bash local/bin/dfm install all
|
||||
|
||||
- pipx:
|
||||
|
||||
@@ -6,8 +6,15 @@ Some problematic code has been fixed per `shellcheck` suggestions.
|
||||
## Homegrown
|
||||
|
||||
- dfm
|
||||
- git-dirty (based on git-extra-tools)
|
||||
- git-fsck-dirs
|
||||
- git-update-dirs
|
||||
- php-switcher
|
||||
- x-backup-folder
|
||||
- x-backup-mysql-with-prefix
|
||||
- x-check-git-attributes
|
||||
- x-clean-vendordirs
|
||||
- x-env-list
|
||||
- x-open-ports
|
||||
|
||||
## Sourced
|
||||
@@ -25,9 +32,15 @@ Some problematic code has been fixed per `shellcheck` suggestions.
|
||||
| `x-when-up` | skx/sysadmin-util |
|
||||
|
||||
- Sources:
|
||||
- [skx/sysadmin-utils](https://github.com/skx/sysadmin-util/)
|
||||
- [skx/sysadmin-utils][skx]
|
||||
- Tools for Linux/Unix sysadmins.
|
||||
- [Licence](https://github.com/skx/sysadmin-util/blob/master/LICENSE)
|
||||
- [onnimonni](https://github.com/onnimonni)
|
||||
- [validate_sha256sum](https://gist.github.com/onnimonni/b49779ebc96216771a6be3de46449fa1)
|
||||
- [mvdan/dotfiles](https://github.com/mvdan/dotfiles)
|
||||
- [Licence][skx-license]
|
||||
- [onnimonni][onnimonni]
|
||||
- [validate_sha256sum][onnimonni-gist]
|
||||
- [mvdan/dotfiles][mvdan]
|
||||
|
||||
[onnimonni]: https://github.com/onnimonni
|
||||
[onnimonni-gist]: https://gist.github.com/onnimonni/b49779ebc96216771a6be3de46449fa1
|
||||
[skx]: https://github.com/skx/sysadmin-util
|
||||
[skx-license]: https://github.com/skx/sysadmin-util/blob/master/LICENSE
|
||||
[mvdan]: https://github.com/mvdan/dotfiles
|
||||
|
||||
@@ -15,9 +15,35 @@
|
||||
|
||||
SCRIPT=$(basename "$0")
|
||||
|
||||
# Loads configs for better installation experience
|
||||
source "$DOTFILES/config/shared.sh"
|
||||
source "${DOTFILES}/local/bin/msgr"
|
||||
# Detect the current shell
|
||||
CURRENT_SHELL=$(ps -p $$ -ocomm= | awk -F/ '{print $NF}')
|
||||
|
||||
# Function to source files based on the shell
|
||||
source_file()
|
||||
{
|
||||
local file=$1
|
||||
case "$CURRENT_SHELL" in
|
||||
fish)
|
||||
if [[ -f "$file.fish" ]]; then
|
||||
source "$file.fish"
|
||||
else
|
||||
echo "Fish shell file not found: $file.fish"
|
||||
exit 1
|
||||
fi
|
||||
;;
|
||||
sh | bash | zsh)
|
||||
source "$file"
|
||||
;;
|
||||
*)
|
||||
echo "Unsupported shell: $CURRENT_SHELL"
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
}
|
||||
|
||||
# Modify the source commands to use the new function
|
||||
source_file "$DOTFILES/config/shared.sh"
|
||||
source_file "${DOTFILES}/local/bin/msgr"
|
||||
|
||||
# Menu builder
|
||||
menu_builder()
|
||||
@@ -267,7 +293,7 @@ section_helpers()
|
||||
{
|
||||
USAGE_PREFIX="$SCRIPT helpers <command>"
|
||||
MENU=(
|
||||
"aliases:<shell> (bash, zsh) Show aliases"
|
||||
"aliases:<shell> (bash, zsh, fish) Show aliases"
|
||||
"colors:Show colors"
|
||||
"env:Show environment variables"
|
||||
"functions:Show functions"
|
||||
@@ -297,8 +323,11 @@ section_helpers()
|
||||
"bash")
|
||||
bash -ixc : 2>&1 | grep -E '> alias' | sed "s|$HOME|~|" | grep -v "(eval)"
|
||||
;;
|
||||
"fish")
|
||||
fish -ic "alias" | sed "s|$HOME|~|"
|
||||
;;
|
||||
*)
|
||||
echo "$SCRIPT helpers aliases <shell> (bash, zsh)"
|
||||
echo "$SCRIPT helpers aliases <shell> (bash, zsh, fish)"
|
||||
;;
|
||||
esac
|
||||
;;
|
||||
|
||||
694
local/bin/git-attributes
Executable file
694
local/bin/git-attributes
Executable file
@@ -0,0 +1,694 @@
|
||||
#!/usr/bin/env bash
|
||||
#
|
||||
# Check git repo's files .gitattributes and ensure all of them are mapped.
|
||||
#
|
||||
# Author: Ismo Vuorinen <https://github.com/ivuorinen> 2022
|
||||
# License: MIT
|
||||
|
||||
set -euo pipefail
|
||||
|
||||
# Default configuration
|
||||
VERBOSE=0
|
||||
CHECK_PATTERN="text: auto"
|
||||
EXIT_ON_MISSING=0
|
||||
SUGGEST_RULES=1 # Suggestions enabled by default
|
||||
WRITE_RULES=0 # Writing to file is opt-in
|
||||
FORMAT_WIDTH=0 # Auto-width by default (0 means auto)
|
||||
MIN_FORMAT_WIDTH=20 # Minimum format width
|
||||
|
||||
DEBUG="${DEBUG:-0}"
|
||||
|
||||
if [ "$DEBUG" -eq 1 ]; then
|
||||
set -x
|
||||
fi
|
||||
|
||||
# Output functions
|
||||
msg_err()
|
||||
{
|
||||
echo -e "\e[31m$@\e[0m" >&2
|
||||
}
|
||||
|
||||
msg_success()
|
||||
{
|
||||
echo -e "\e[32m$@\e[0m"
|
||||
}
|
||||
|
||||
msg_warn()
|
||||
{
|
||||
echo -e "\e[33m$@\e[0m" >&2
|
||||
}
|
||||
|
||||
msg_info()
|
||||
{
|
||||
echo -e "\e[36m$@\e[0m"
|
||||
}
|
||||
|
||||
msg_debug()
|
||||
{
|
||||
[[ $VERBOSE -eq 1 ]] && echo -e "\e[35m$@\e[0m"
|
||||
}
|
||||
|
||||
show_help()
|
||||
{
|
||||
cat << EOF
|
||||
Usage: $(basename "$0") [OPTIONS]
|
||||
|
||||
Check if all git-tracked files have corresponding rules in .gitattributes
|
||||
|
||||
Options:
|
||||
-h, --help Display this help message
|
||||
-v, --verbose Enable verbose output
|
||||
-e, --exit Exit with error code if missing attributes found
|
||||
-p, --pattern Pattern to check (default: "text: auto")
|
||||
-n, --no-suggest Don't suggest .gitattributes rules (suggestions are on by default)
|
||||
-w, --write Write suggested rules to .gitattributes file
|
||||
-f, --format-width Specify width for formatting rule patterns (default: auto, min: $MIN_FORMAT_WIDTH)
|
||||
|
||||
EOF
|
||||
}
|
||||
|
||||
# Parse arguments
|
||||
while [[ $# -gt 0 ]]; do
|
||||
case "$1" in
|
||||
-h | --help)
|
||||
show_help
|
||||
exit 0
|
||||
;;
|
||||
-v | --verbose)
|
||||
VERBOSE=1
|
||||
shift
|
||||
;;
|
||||
-e | --exit)
|
||||
EXIT_ON_MISSING=1
|
||||
shift
|
||||
;;
|
||||
-p | --pattern)
|
||||
CHECK_PATTERN="$2"
|
||||
shift 2
|
||||
;;
|
||||
-n | --no-suggest)
|
||||
SUGGEST_RULES=0
|
||||
shift
|
||||
;;
|
||||
-w | --write)
|
||||
WRITE_RULES=1
|
||||
shift
|
||||
;;
|
||||
-f | --format-width)
|
||||
if [[ $2 =~ ^[0-9]+$ ]]; then
|
||||
FORMAT_WIDTH=$2
|
||||
shift 2
|
||||
else
|
||||
msg_err "Error: --format-width requires a numeric argument"
|
||||
exit 1
|
||||
fi
|
||||
;;
|
||||
*)
|
||||
msg_err "Unknown option: $1"
|
||||
show_help
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
done
|
||||
|
||||
# Function to check if git is installed
|
||||
check_git_installed()
|
||||
{
|
||||
if ! command -v git &> /dev/null; then
|
||||
msg_err "git could not be found, please install it first"
|
||||
exit 1
|
||||
fi
|
||||
}
|
||||
|
||||
# Check if we're in a git repository
|
||||
check_git_repo()
|
||||
{
|
||||
if ! git rev-parse --is-inside-work-tree &> /dev/null; then
|
||||
msg_err "Not inside a git repository"
|
||||
exit 1
|
||||
fi
|
||||
}
|
||||
|
||||
# Check if we're in the git root directory
|
||||
check_git_root()
|
||||
{
|
||||
local git_root
|
||||
git_root=$(git rev-parse --show-toplevel)
|
||||
local current_dir
|
||||
current_dir=$(pwd)
|
||||
|
||||
if [[ "$git_root" != "$current_dir" ]]; then
|
||||
msg_err "Not in git repository root directory"
|
||||
msg_warn "Please run this command from: $git_root"
|
||||
exit 1
|
||||
fi
|
||||
}
|
||||
|
||||
# Check if .gitattributes exists
|
||||
check_gitattributes_exists()
|
||||
{
|
||||
if [[ ! -f ".gitattributes" ]]; then
|
||||
msg_err ".gitattributes file not found in the repository root"
|
||||
msg_warn "Create a .gitattributes file before running this command"
|
||||
exit 1
|
||||
fi
|
||||
}
|
||||
|
||||
# Format rule with proper alignment
|
||||
format_rule()
|
||||
{
|
||||
local pattern="$1"
|
||||
local attributes="$2"
|
||||
local width="$3"
|
||||
|
||||
# If pattern starts with "#", it's a comment, don't format
|
||||
if [[ "$pattern" == "#"* ]]; then
|
||||
echo "$pattern"
|
||||
return
|
||||
fi
|
||||
|
||||
# If pattern is empty, return empty
|
||||
if [[ -z "$pattern" ]]; then
|
||||
echo ""
|
||||
return
|
||||
fi
|
||||
|
||||
printf "%-${width}s %s\n" "$pattern" "$attributes"
|
||||
}
|
||||
|
||||
# Get the file extension properly, handling special cases
|
||||
get_file_extension()
|
||||
{
|
||||
local file="$1"
|
||||
local basename=$(basename "$file")
|
||||
local extension=""
|
||||
|
||||
# Check if file has no extension or is a dotfile
|
||||
if [[ "$basename" == .* && ! "$basename" =~ \..+$ ]]; then
|
||||
# It's a dotfile without extension (like .gitignore)
|
||||
extension="$basename"
|
||||
elif [[ "$basename" =~ \..+$ ]]; then
|
||||
# Normal file with extension
|
||||
extension="${basename##*.}"
|
||||
|
||||
# Check for special cases like .d/ directories
|
||||
if [[ "$extension" == "d" ]]; then
|
||||
# This is likely a .d directory - use the full filename as pattern
|
||||
if [[ -f "$file" ]]; then
|
||||
# For files in .d directories, use the complete path as pattern
|
||||
extension=$(basename "$file")
|
||||
else
|
||||
# For .d directory itself, use *.d
|
||||
extension="d"
|
||||
fi
|
||||
fi
|
||||
else
|
||||
# No extension at all
|
||||
extension="$basename"
|
||||
fi
|
||||
|
||||
echo "$extension"
|
||||
}
|
||||
|
||||
# Suggest appropriate gitattributes rules based on file extension
|
||||
suggest_rule()
|
||||
{
|
||||
local file="$1"
|
||||
local extension=""
|
||||
local pattern=""
|
||||
local attributes=""
|
||||
|
||||
msg_debug "Checking file: $file"
|
||||
|
||||
# Skip directories
|
||||
if [[ -d "$file" ]]; then
|
||||
return
|
||||
fi
|
||||
|
||||
# Get proper file extension
|
||||
extension=$(get_file_extension "$file")
|
||||
|
||||
# If file path contains .d/ pattern, we need special handling
|
||||
if [[ "$file" =~ \.d/ ]]; then
|
||||
# Extract the pattern part that includes the .d/ directory
|
||||
local dir_part=$(dirname "$file")
|
||||
local base_name=$(basename "$file")
|
||||
|
||||
# Check if it's a config directory pattern worth capturing
|
||||
if [[ "$dir_part" =~ /(\.d|[^/]+\.d)$ ]]; then
|
||||
pattern="$dir_part/*"
|
||||
msg_debug "Detected .d directory pattern: $pattern"
|
||||
else
|
||||
# Use standard extension pattern
|
||||
pattern="*.${extension}"
|
||||
fi
|
||||
else
|
||||
# Standard file with extension
|
||||
pattern="*.${extension}"
|
||||
fi
|
||||
|
||||
# Common text files
|
||||
case "$extension" in
|
||||
# Shell scripts
|
||||
sh | bash | zsh | fish)
|
||||
attributes="text eol=lf diff=shell"
|
||||
;;
|
||||
|
||||
# Web development
|
||||
html | htm | xhtml | css | scss | sass | less)
|
||||
attributes="text eol=lf diff=html"
|
||||
;;
|
||||
js | jsx | ts | tsx | json | json5)
|
||||
attributes="text eol=lf diff=javascript"
|
||||
;;
|
||||
|
||||
# Programming languages
|
||||
php)
|
||||
attributes="text eol=lf diff=php"
|
||||
;;
|
||||
py)
|
||||
attributes="text eol=lf diff=python"
|
||||
;;
|
||||
rb)
|
||||
attributes="text eol=lf diff=ruby"
|
||||
;;
|
||||
go)
|
||||
attributes="text eol=lf diff=golang"
|
||||
;;
|
||||
java | kt | scala)
|
||||
attributes="text eol=lf diff=java"
|
||||
;;
|
||||
c | cpp | h | hpp)
|
||||
attributes="text eol=lf diff=cpp"
|
||||
;;
|
||||
|
||||
# Documentation
|
||||
md | markdown | txt)
|
||||
attributes="text eol=lf"
|
||||
;;
|
||||
|
||||
# Configuration files
|
||||
yml | yaml | toml | ini | cfg | conf)
|
||||
attributes="text eol=lf"
|
||||
;;
|
||||
|
||||
# Git config files and similar patterns
|
||||
git)
|
||||
attributes="text eol=lf"
|
||||
;;
|
||||
gitignore | gitattributes)
|
||||
attributes="text eol=lf"
|
||||
;;
|
||||
|
||||
# Binary files
|
||||
png | jpg | jpeg | gif | ico | svg | webp | avif)
|
||||
attributes="binary"
|
||||
;;
|
||||
pdf | doc | docx | xls | xlsx | ppt | pptx)
|
||||
attributes="binary"
|
||||
;;
|
||||
zip | tar | gz | 7z | rar)
|
||||
attributes="binary"
|
||||
;;
|
||||
mp3 | mp4 | avi | mov | wav | ogg)
|
||||
attributes="binary"
|
||||
;;
|
||||
ttf | otf | woff | woff2 | eot)
|
||||
attributes="binary"
|
||||
;;
|
||||
|
||||
# Default for unknown extensions
|
||||
*)
|
||||
# Try to guess if it's text by checking if it contains null bytes
|
||||
if file "$file" | grep -q text; then
|
||||
attributes="text eol=lf"
|
||||
else
|
||||
attributes="binary"
|
||||
fi
|
||||
;;
|
||||
esac
|
||||
|
||||
msg_debug "...suggesting $pattern $attributes"
|
||||
|
||||
echo "$pattern:$attributes"
|
||||
}
|
||||
|
||||
# Function to check for missing .gitattributes
|
||||
check_gitattributes()
|
||||
{
|
||||
local missing_attributes
|
||||
msg_info "Checking for pattern: $CHECK_PATTERN"
|
||||
|
||||
missing_attributes=$(git ls-files | git check-attr -a --stdin | grep "$CHECK_PATTERN" || true)
|
||||
|
||||
if [[ -n "$missing_attributes" ]]; then
|
||||
msg_warn "Missing .gitattributes rules detected"
|
||||
|
||||
if [[ $SUGGEST_RULES -eq 1 ]]; then
|
||||
# Generate suggestions
|
||||
local suggestions
|
||||
|
||||
# Generate the suggestions
|
||||
suggestions=$(suggest_gitattributes "$missing_attributes")
|
||||
|
||||
# Display the suggestions
|
||||
echo ""
|
||||
echo "$suggestions"
|
||||
echo ""
|
||||
|
||||
if [[ $WRITE_RULES -eq 1 ]]; then
|
||||
msg_debug "...writing to .gitattributes"
|
||||
write_to_gitattributes "$suggestions"
|
||||
fi
|
||||
else
|
||||
msg_err ".gitattributes rule missing for the following files:"
|
||||
echo "$missing_attributes"
|
||||
fi
|
||||
|
||||
if [[ $EXIT_ON_MISSING -eq 1 ]]; then
|
||||
return 1
|
||||
fi
|
||||
else
|
||||
msg_success "All files have a corresponding rule in .gitattributes"
|
||||
fi
|
||||
|
||||
return 0
|
||||
}
|
||||
|
||||
# Parse rule string and extract pattern and attributes
|
||||
parse_rule()
|
||||
{
|
||||
local rule="$1"
|
||||
|
||||
if [[ "$rule" == "#"* ]]; then
|
||||
# This is a comment line
|
||||
echo "$rule::"
|
||||
return
|
||||
fi
|
||||
|
||||
if [[ "$rule" =~ ^([^[:space:]]+)[[:space:]]+(.*)$ ]]; then
|
||||
echo "${BASH_REMATCH[1]}:${BASH_REMATCH[2]}"
|
||||
else
|
||||
echo "$rule::"
|
||||
fi
|
||||
}
|
||||
|
||||
# Check shell scripts by name regardless of extension
|
||||
detect_shell_scripts()
|
||||
{
|
||||
msg_debug "Detecting shell scripts by name regardless of extension..."
|
||||
|
||||
local shell_scripts_rules=""
|
||||
local shell_scripts_found=0
|
||||
local patterns=()
|
||||
local attributes=()
|
||||
|
||||
# Get already defined rules in .gitattributes
|
||||
local existing_rules
|
||||
existing_rules=$(grep -v "^#" .gitattributes || true)
|
||||
|
||||
# Get all shell scripts regardless of extension
|
||||
local shell_scripts
|
||||
shell_scripts=$(git ls-files | xargs file | grep "shell script" | cut -d: -f1)
|
||||
|
||||
if [[ -n "$shell_scripts" ]]; then
|
||||
shell_scripts_found=$(echo "$shell_scripts" | wc -l | tr -d ' ')
|
||||
msg_debug "Found $shell_scripts_found potential shell scripts."
|
||||
|
||||
# Track scripts that need rules
|
||||
declare -A scripts_by_dir=()
|
||||
local need_rule_count=0
|
||||
|
||||
# Process each script
|
||||
while IFS= read -r script; do
|
||||
local rel_path="${script#./}"
|
||||
|
||||
# Skip if exact path already in .gitattributes
|
||||
if grep -q "^${rel_path} " <<< "$existing_rules"; then
|
||||
msg_debug "Script already in .gitattributes: $rel_path"
|
||||
continue
|
||||
fi
|
||||
|
||||
# Skip if file extension already covered
|
||||
local extension=$(get_file_extension "$rel_path")
|
||||
if [[ "$extension" != "$rel_path" ]] && grep -q "^\*\.$extension " <<< "$existing_rules"; then
|
||||
msg_debug "Script covered by extension rule: $rel_path (*.$extension)"
|
||||
continue
|
||||
fi
|
||||
|
||||
# Check if any parent directory is already covered
|
||||
local is_covered=0
|
||||
local dir_path="$rel_path"
|
||||
while [[ "$dir_path" != "." && "$dir_path" != "/" ]]; do
|
||||
dir_path=$(dirname "$dir_path")
|
||||
if [[ "$dir_path" == "." ]]; then
|
||||
break
|
||||
fi
|
||||
|
||||
# Check if directory or any of its contents are covered
|
||||
if grep -q "^${dir_path}/\?" <<< "$existing_rules" || grep -q "^${dir_path}/\*" <<< "$existing_rules"; then
|
||||
msg_debug "Script covered by directory rule: $rel_path (${dir_path})"
|
||||
is_covered=1
|
||||
break
|
||||
fi
|
||||
done
|
||||
|
||||
if [[ $is_covered -eq 1 ]]; then
|
||||
continue
|
||||
fi
|
||||
|
||||
# Group by directory
|
||||
local dir=$(dirname "$rel_path")
|
||||
if [[ "$dir" == "." ]]; then
|
||||
dir="root"
|
||||
fi
|
||||
|
||||
# Add to appropriate group
|
||||
if [[ -z "${scripts_by_dir[$dir]:-}" ]]; then
|
||||
scripts_by_dir[$dir]="$rel_path"
|
||||
else
|
||||
scripts_by_dir[$dir]="${scripts_by_dir[$dir]}\n$rel_path"
|
||||
fi
|
||||
|
||||
((need_rule_count++))
|
||||
done <<< "$shell_scripts"
|
||||
|
||||
# Output grouped results
|
||||
if [[ $need_rule_count -gt 0 ]]; then
|
||||
patterns+=("# Shell scripts detected by content")
|
||||
attributes+=("")
|
||||
|
||||
# Check if we can use directory-based rules instead of individual files
|
||||
for dir in "${!scripts_by_dir[@]}"; do
|
||||
local files_in_dir=$(echo -e "${scripts_by_dir[$dir]}" | wc -l)
|
||||
local dir_path="$dir"
|
||||
|
||||
if [[ "$dir" == "root" ]]; then
|
||||
# For root directory files, list each individually
|
||||
while IFS= read -r file; do
|
||||
patterns+=("$file")
|
||||
attributes+=("text eol=lf diff=shell")
|
||||
done <<< "$(echo -e "${scripts_by_dir[$dir]}")"
|
||||
elif [[ $files_in_dir -gt 2 ]]; then
|
||||
# If directory has multiple scripts, suggest a directory pattern
|
||||
patterns+=("# Found $files_in_dir scripts in $dir_path")
|
||||
attributes+=("")
|
||||
|
||||
# Special handling for .d directories
|
||||
if [[ "$dir_path" =~ \.d$ || "$dir_path" =~ \.d/ ]]; then
|
||||
patterns+=("$dir_path/*")
|
||||
else
|
||||
patterns+=("$dir_path/*")
|
||||
fi
|
||||
attributes+=("text eol=lf diff=shell")
|
||||
|
||||
# List the files as comments for reference
|
||||
while IFS= read -r file; do
|
||||
patterns+=("# - ${file}")
|
||||
attributes+=("")
|
||||
done <<< "$(echo -e "${scripts_by_dir[$dir]}" | sort)"
|
||||
else
|
||||
# For directories with few scripts, list them individually
|
||||
while IFS= read -r file; do
|
||||
patterns+=("$file")
|
||||
attributes+=("text eol=lf diff=shell")
|
||||
done <<< "$(echo -e "${scripts_by_dir[$dir]}")"
|
||||
fi
|
||||
done
|
||||
|
||||
msg_debug "Adding $need_rule_count shell scripts to suggestions (grouped by directory)."
|
||||
else
|
||||
msg_debug "All detected shell scripts already have rules."
|
||||
fi
|
||||
else
|
||||
msg_debug "No shell scripts detected."
|
||||
fi
|
||||
|
||||
# Return the formatted arrays
|
||||
local rules_count=${#patterns[@]}
|
||||
for ((i = 0; i < rules_count; i++)); do
|
||||
echo "${patterns[$i]}:${attributes[$i]}"
|
||||
done
|
||||
}
|
||||
|
||||
# Function to suggest gitattributes rules
|
||||
suggest_gitattributes()
|
||||
{
|
||||
local missing_attributes="$1"
|
||||
local files
|
||||
local extension_suggestions=()
|
||||
local formatted_suggestions=""
|
||||
local all_patterns=()
|
||||
local all_attributes=()
|
||||
local max_pattern_length=0
|
||||
|
||||
# Add header to suggestions
|
||||
all_patterns+=("# Auto-generated rules - $(date +"%Y-%m-%d %H:%M:%S")")
|
||||
all_attributes+=("")
|
||||
|
||||
msg_info "Suggested .gitattributes rules:"
|
||||
|
||||
# First, detect shell scripts and add them to suggestions
|
||||
msg_info "Detecting shell scripts by content..."
|
||||
local shell_scripts_rules
|
||||
shell_scripts_rules=$(detect_shell_scripts)
|
||||
|
||||
# Add shell script rules to patterns and attributes arrays
|
||||
if [[ -n "$shell_scripts_rules" ]]; then
|
||||
while IFS=':' read -r pattern attributes; do
|
||||
if [[ -n "$pattern" ]]; then
|
||||
all_patterns+=("$pattern")
|
||||
all_attributes+=("$attributes")
|
||||
|
||||
# Update max pattern length (skip comments)
|
||||
if [[ "$pattern" != "#"* ]] && [[ ${#pattern} -gt $max_pattern_length ]]; then
|
||||
max_pattern_length=${#pattern}
|
||||
fi
|
||||
fi
|
||||
done <<< "$shell_scripts_rules"
|
||||
fi
|
||||
|
||||
# Extract filenames from git check-attr output
|
||||
files=$(echo "$missing_attributes" | awk -F': ' '{print $1}')
|
||||
|
||||
# Get suggestions for each file
|
||||
declare -A seen_patterns=()
|
||||
|
||||
while IFS= read -r file; do
|
||||
local suggestion=$(suggest_rule "$file")
|
||||
if [[ -n "$suggestion" ]]; then
|
||||
IFS=':' read -r pattern attributes <<< "$suggestion"
|
||||
|
||||
# Only add each pattern once
|
||||
if [[ -z "${seen_patterns[$pattern]:-}" ]]; then
|
||||
extension_suggestions+=("$suggestion")
|
||||
seen_patterns[$pattern]=1
|
||||
fi
|
||||
fi
|
||||
done <<< "$files"
|
||||
|
||||
# Remove duplicates and sort
|
||||
local unique_extensions=()
|
||||
mapfile -t unique_extensions < <(printf '%s\n' "${extension_suggestions[@]}" | sort -u)
|
||||
|
||||
# Add extension-based suggestions header if we have any
|
||||
if [[ ${#unique_extensions[@]} -gt 0 ]]; then
|
||||
all_patterns+=("")
|
||||
all_attributes+=("")
|
||||
|
||||
all_patterns+=("# File extension-based rules")
|
||||
all_attributes+=("")
|
||||
|
||||
# Add extension rules to patterns and attributes arrays
|
||||
for suggestion in "${unique_extensions[@]}"; do
|
||||
IFS=':' read -r pattern attributes <<< "$suggestion"
|
||||
|
||||
all_patterns+=("$pattern")
|
||||
all_attributes+=("$attributes")
|
||||
|
||||
# Update max pattern length
|
||||
if [[ ${#pattern} -gt $max_pattern_length ]]; then
|
||||
max_pattern_length=${#pattern}
|
||||
fi
|
||||
done
|
||||
fi
|
||||
|
||||
# Use user-specified format width if provided, otherwise use max_pattern_length
|
||||
# But ensure it's at least MIN_FORMAT_WIDTH
|
||||
local format_width=$max_pattern_length
|
||||
if [[ $FORMAT_WIDTH -gt 0 ]]; then
|
||||
format_width=$FORMAT_WIDTH
|
||||
fi
|
||||
|
||||
# Ensure minimum width
|
||||
if [[ $format_width -lt $MIN_FORMAT_WIDTH ]]; then
|
||||
format_width=$MIN_FORMAT_WIDTH
|
||||
fi
|
||||
|
||||
msg_debug "Using format width: $format_width"
|
||||
|
||||
# Format and output all suggestions with proper alignment
|
||||
local rule_count=${#all_patterns[@]}
|
||||
|
||||
for ((i = 0; i < rule_count; i++)); do
|
||||
local pattern="${all_patterns[$i]}"
|
||||
local attributes="${all_attributes[$i]}"
|
||||
|
||||
# Handle comments separately
|
||||
if [[ "$pattern" == "#"* ]] || [[ -z "$attributes" ]]; then
|
||||
formatted_suggestions+="$pattern\n"
|
||||
echo "$pattern"
|
||||
else
|
||||
local formatted_rule=$(printf "%-${format_width}s %s\n" "$pattern" "$attributes")
|
||||
formatted_suggestions+="$formatted_rule\n"
|
||||
echo "$formatted_rule"
|
||||
fi
|
||||
done
|
||||
|
||||
# Add final message
|
||||
echo ""
|
||||
msg_info "Add these rules to your .gitattributes file to resolve missing attributes."
|
||||
|
||||
# Return the full suggestion text so it can be both displayed and written to file
|
||||
echo -e "$formatted_suggestions"
|
||||
}
|
||||
|
||||
# Write suggestions to .gitattributes file
|
||||
write_to_gitattributes()
|
||||
{
|
||||
local suggestions="$1"
|
||||
local gitattributes=".gitattributes"
|
||||
|
||||
# Check if file exists and is writable
|
||||
if [[ ! -w "$gitattributes" ]]; then
|
||||
msg_err "Cannot write to $gitattributes. Check permissions."
|
||||
return 1
|
||||
fi
|
||||
|
||||
# Add a newline at the end of the file if it doesn't have one
|
||||
if [[ -s "$gitattributes" ]] && [[ $(tail -c 1 "$gitattributes" | wc -l) -eq 0 ]]; then
|
||||
echo "" >> "$gitattributes"
|
||||
fi
|
||||
|
||||
# Append suggestions to the file
|
||||
echo -e "$suggestions" >> "$gitattributes"
|
||||
|
||||
msg_success "Added suggested rules to $gitattributes"
|
||||
|
||||
# Remind to check the file
|
||||
msg_warn "Please review the changes to ensure they're appropriate for your project."
|
||||
|
||||
return 0
|
||||
}
|
||||
|
||||
# Main function
|
||||
main()
|
||||
{
|
||||
check_git_installed
|
||||
check_git_repo
|
||||
check_git_root
|
||||
check_gitattributes_exists
|
||||
check_gitattributes
|
||||
}
|
||||
|
||||
main "$@"
|
||||
1080
local/bin/git-dirty
1080
local/bin/git-dirty
File diff suppressed because it is too large
Load Diff
185
local/bin/git-dirty.md
Normal file
185
local/bin/git-dirty.md
Normal file
@@ -0,0 +1,185 @@
|
||||
# git-dirty
|
||||
|
||||
A powerful tool to recursively check Git repository status across multiple directories.
|
||||
|
||||
## Overview
|
||||
|
||||
`git-dirty` scans directories to identify Git repositories and reports their status.
|
||||
It quickly shows which repositories have uncommitted changes, untracked files, or need
|
||||
to be pushed, making it easy to maintain clean workspaces across multiple projects.
|
||||
|
||||
## Features
|
||||
|
||||
- 🔍 **Recursive scanning** of directories to find Git repositories
|
||||
- 🚦 **Visual indicators** showing repository status (clean/dirty/not git)
|
||||
- 🔄 **Parallel processing** for faster scanning of large directory structures
|
||||
- 🌳 **Tree-like display** with customizable depth
|
||||
- 📊 **Progress tracking** for large repository scans
|
||||
- 🎨 **Colorized output** (can be disabled)
|
||||
- 📏 **Path truncation** for cleaner display
|
||||
- 🔀 **Branch display** with smart formatting for main branches
|
||||
- ⏱️ **Performance metrics** showing scan speed and ETA
|
||||
- 📈 **Smart sorting** to maintain tree hierarchy in output
|
||||
- ⚙️ **Configurable** via environment variables or config files
|
||||
|
||||
## Installation
|
||||
|
||||
Place the script in your PATH and make it executable:
|
||||
|
||||
```bash
|
||||
# Clone the repository or download the script
|
||||
curl -o ~/.local/bin/git-dirty https://raw.githubusercontent.com/ivuorinen/dotfiles/main/local/bin/git-dirty
|
||||
chmod +x ~/.local/bin/git-dirty
|
||||
```
|
||||
|
||||
## Usage
|
||||
|
||||
```bash
|
||||
git-dirty [OPTIONS] [DIRECTORY]
|
||||
# or if the file is in the PATH, you can use it as an git command
|
||||
git dirty [OPTIONS] [DIRECTORY]
|
||||
|
||||
# to show help
|
||||
git dirty -h
|
||||
```
|
||||
|
||||
If no directory is specified, it will use `$HOME/Code` as the default.
|
||||
|
||||
### Options
|
||||
|
||||
- `-h` Show help message and exit
|
||||
- `-d NUM` Set maximum depth for showing non-git directories (default: 5)
|
||||
- `-p` Process directories in parallel (requires 'parallel' command)
|
||||
- `-v` Enable verbose output
|
||||
- `-a` Show all status details (stash, untracked files, etc.)
|
||||
- `-e PATTERNS` Additional patterns to exclude (comma separated)
|
||||
- `-m NUM` Set maximum recursion depth (default: 15)
|
||||
- `-c` Toggle colorized output
|
||||
- `-t` Toggle path truncation
|
||||
- `-b` Toggle branch name display
|
||||
|
||||
### Examples
|
||||
|
||||
```bash
|
||||
# Check default directory
|
||||
git-dirty
|
||||
|
||||
# Check specific directory
|
||||
git-dirty ~/Projects
|
||||
|
||||
# Check with extended status information
|
||||
git-dirty -a ~/Code
|
||||
|
||||
# Exclude certain directories
|
||||
git-dirty -e 'build,dist,node_modules' ~/Code
|
||||
|
||||
# Use parallel processing for faster results
|
||||
git-dirty -p ~/large-directory
|
||||
|
||||
# Hide branch names in output
|
||||
git-dirty -b ~/Code
|
||||
```
|
||||
|
||||
## Status Indicators
|
||||
|
||||
The script uses the following status indicators:
|
||||
|
||||
- ✅ Clean repository
|
||||
- ❌ Dirty repository with details:
|
||||
- `M` = Modified files
|
||||
- `S` = Staged changes
|
||||
- `?` = Untracked files (with `-a` flag)
|
||||
- `$` = Stashed changes (with `-a` flag)
|
||||
- `↑` = Unpushed commits
|
||||
- ⚠️ Not a Git repository
|
||||
|
||||
## Branch Display
|
||||
|
||||
The script shows branch names for repositories not on main branches. This helps identify
|
||||
repositories where work is happening on feature branches. Main branches (configurable as
|
||||
`main`, `master`, and `trunk` by default) are hidden to reduce output clutter.
|
||||
|
||||
## Configuration
|
||||
|
||||
You can customize the default behavior using environment variables:
|
||||
|
||||
```bash
|
||||
# in your .bashrc, .zshrc, etc.
|
||||
export GIT_DIRTY_DIR="$HOME/Projects" # Set default directory
|
||||
export GIT_DIRTY_DEPTH=3 # Show non-git dirs up to depth 3
|
||||
export GIT_DIRTY_MAXDEPTH=15 # Maximum recursion depth
|
||||
export GIT_DIRTY_COLOR=1 # Enable colorized output (0 to disable)
|
||||
export GIT_DIRTY_TRUNCATE=1 # Enable path truncation (0 to disable)
|
||||
export GIT_DIRTY_SHOW_BRANCH=1 # Show branch names (0 to disable)
|
||||
export GIT_DIRTY_MAIN_BRANCHES="main master trunk" # Main branches (not shown in output)
|
||||
export GIT_DIRTY_EXCLUDE="node_modules vendor .cache build dist .tests .test" # Default excludes
|
||||
```
|
||||
|
||||
### Config File
|
||||
|
||||
You can also create a configuration file at `$XDG_CONFIG_HOME/git-dirty/config`
|
||||
(typically `~/.config/git-dirty/config`):
|
||||
|
||||
```bash
|
||||
# Example config file
|
||||
GIT_DIRTY_DIR="$HOME/Projects"
|
||||
GIT_DIRTY_DEPTH=3
|
||||
GIT_DIRTY_CHECK_STASH=1
|
||||
GIT_DIRTY_SHOW_BRANCH=1
|
||||
GIT_DIRTY_MAIN_BRANCHES="main master trunk develop"
|
||||
GIT_DIRTY_EXCLUDE="node_modules vendor .cache build dist tmp"
|
||||
```
|
||||
|
||||
## Skip Directories from Checking
|
||||
|
||||
If you want to skip a directory from being checked, add a `.ignore` file next to the `.git` folder.
|
||||
You can add `.ignore` to your global `.gitignore` file to avoid committing these files.
|
||||
|
||||
## Performance Features
|
||||
|
||||
- **Parallel processing**: Significant speed improvements when using the `-p` flag
|
||||
- **Progress bars**: Real-time feedback on scanning progress with ETA
|
||||
- **Rate limiting**: Controls parallel jobs to prevent system overloading
|
||||
- **Smart directory traversal**: Skips excluded directories for faster processing
|
||||
|
||||
## Tips
|
||||
|
||||
1. **Add an alias**: Create an alias in your shell configuration:
|
||||
|
||||
```bash
|
||||
alias gd='git-dirty'
|
||||
```
|
||||
|
||||
2. **Use it with specific directories**:
|
||||
|
||||
```bash
|
||||
git-dirty ~/specific/project
|
||||
```
|
||||
|
||||
3. **Run in parallel mode for large codebases**:
|
||||
|
||||
```bash
|
||||
git-dirty -p ~/huge-monorepo
|
||||
```
|
||||
|
||||
4. **Turn off branch display for cleaner output**:
|
||||
|
||||
```bash
|
||||
git-dirty -b
|
||||
```
|
||||
|
||||
## Requirements
|
||||
|
||||
- Bash (version 4+)
|
||||
- Git
|
||||
- Optional: GNU Parallel for parallel processing
|
||||
|
||||
## License
|
||||
|
||||
MIT
|
||||
|
||||
## Credits
|
||||
|
||||
Created with ❤️ by Ismo Vuorinen
|
||||
|
||||
<!-- vim: set ft=markdown cc=80 : -->
|
||||
@@ -10,42 +10,116 @@ set -euo pipefail
|
||||
|
||||
# Enable verbosity with VERBOSE=1
|
||||
VERBOSE="${VERBOSE:-0}"
|
||||
DEBUG="${DEBUG:-0}"
|
||||
|
||||
if [ "$DEBUG" -eq 1 ]; then
|
||||
set -x
|
||||
fi
|
||||
|
||||
# Function to print messages if VERBOSE is enabled
|
||||
# $1 - message (string)
|
||||
msg()
|
||||
{
|
||||
[ "$VERBOSE" -eq 1 ] && echo "$1"
|
||||
if [ "$VERBOSE" -eq 1 ]; then
|
||||
echo "$1"
|
||||
fi
|
||||
return 0
|
||||
}
|
||||
|
||||
# Show red error message
|
||||
# $1 - message (string)
|
||||
msg_err()
|
||||
{
|
||||
echo "$(tput setaf 1)Error: $1$(tput sgr0)"
|
||||
}
|
||||
|
||||
# Function to perform git fsck on a repository
|
||||
# $1 - directory (string)
|
||||
fsck_repo()
|
||||
{
|
||||
local dir=$1
|
||||
msg "Processing dir: $dir"
|
||||
(
|
||||
cd "$dir" || exit 1
|
||||
if [ -d ".git" ]; then
|
||||
git fsck --no-dangling --full --no-progress
|
||||
echo ""
|
||||
fi
|
||||
)
|
||||
local dir dirs collected_errors collected_repos
|
||||
dir="$(realpath "$1")"
|
||||
collected_errors="$2"
|
||||
collected_repos="$3"
|
||||
|
||||
msg "Processing: $dir"
|
||||
|
||||
if [ ! -d "$dir/.git" ]; then
|
||||
echo "$dir" >> "$collected_errors"
|
||||
msg " (!) Skipping (no .git)"
|
||||
return
|
||||
fi
|
||||
|
||||
echo "$dir" >> "$collected_repos"
|
||||
|
||||
if ! git -C "$dir" fsck --no-dangling --full --no-progress 2>&1 | grep -vE '^notice:'; then
|
||||
echo "$dir" >> "$collected_errors"
|
||||
msg " (!) Issues found in: $dir"
|
||||
fi
|
||||
}
|
||||
|
||||
# Main function
|
||||
main()
|
||||
{
|
||||
local starting_path=${1:-$(pwd)}
|
||||
local dirs
|
||||
local starting_path errors_file repo_count_file dirs dirs_count REPO_COUNT ERROR_COUNT
|
||||
|
||||
starting_path=${1:-$(pwd)}
|
||||
errors_file="${2:-/tmp/git-fsck-errors.txt}"
|
||||
repo_count_file="${3:-/tmp/git-fsck-repo-count.txt}"
|
||||
|
||||
# If starting_point=. or starting_point=.., set it to the current directory
|
||||
if [ "$starting_path" = "." ]; then
|
||||
starting_path="$(pwd)"
|
||||
elif [ "$starting_path" = ".." ]; then
|
||||
starting_path="$(dirname "$(pwd)")"
|
||||
fi
|
||||
|
||||
# Check if starting_path exists
|
||||
if [ ! -d "$starting_path" ]; then
|
||||
msg_err "Error: Directory '$starting_path' not found."
|
||||
return 1
|
||||
fi
|
||||
|
||||
# Collect the directories
|
||||
dirs=$(find "$starting_path" -mindepth 1 -maxdepth 1 -type d)
|
||||
# Filter out unwanted directories
|
||||
dirs=$(echo "$dirs" \
|
||||
| grep -vE '^\./\.git$' \
|
||||
| grep -vE '^\./\.svn$' \
|
||||
| grep -vE '^\./\.hg$' \
|
||||
| grep -vE '^\./\.bzr$')
|
||||
# Count the directories for reporting and processing
|
||||
dirs_count=$(echo "$dirs" | wc -l | tr -d ' ')
|
||||
|
||||
# If dirs_count is 0, exit early
|
||||
if [ "$dirs_count" -eq 0 ]; then
|
||||
msg_err "No directories found in $starting_path."
|
||||
return 0
|
||||
fi
|
||||
|
||||
echo "Checking $dirs_count directories in $starting_path..."
|
||||
|
||||
for dir in $dirs; do
|
||||
fsck_repo "$dir"
|
||||
fsck_repo "$dir" "$errors_file" "$repo_count_file"
|
||||
done
|
||||
|
||||
# Collect the results and trim the output
|
||||
REPO_COUNT=$(wc -l < "$repo_count_file" | tr -d ' ')
|
||||
ERROR_COUNT=$(wc -l < "$errors_file" | tr -d ' ')
|
||||
|
||||
rm -f "$errors_file" "$repo_count_file"
|
||||
|
||||
echo ""
|
||||
echo "Done."
|
||||
echo "Summary:"
|
||||
echo "Checked $REPO_COUNT repositories from $dirs_count directories."
|
||||
if [ "$ERROR_COUNT" -gt 0 ]; then
|
||||
echo "Found issues in $ERROR_COUNT repositories."
|
||||
return 1
|
||||
else
|
||||
echo "All repositories passed."
|
||||
return 0
|
||||
fi
|
||||
}
|
||||
|
||||
main "$@"
|
||||
exit $?
|
||||
|
||||
65
local/bin/git-fsck-dirs.md
Normal file
65
local/bin/git-fsck-dirs.md
Normal file
@@ -0,0 +1,65 @@
|
||||
# git-fsck-dirs
|
||||
|
||||
A utility to check multiple Git repositories for corruption
|
||||
using `git fsck`.
|
||||
|
||||
## Overview
|
||||
|
||||
`git-fsck-dirs` scans all subdirectories within a specified path
|
||||
and performs a `git fsck` operation on each Git repository found.
|
||||
This helps identify corrupted repositories or those with integrity
|
||||
issues.
|
||||
|
||||
## Features
|
||||
|
||||
- Recursively checks all Git repositories in the given directory
|
||||
- Provides a summary of repositories checked and any issues found
|
||||
- Filters out common version control directories (.git, .svn, etc.)
|
||||
- Supports verbose and debug modes
|
||||
|
||||
## Usage
|
||||
|
||||
```bash
|
||||
git-fsck-dirs [path] [errors_file] [repo_count_file]
|
||||
git fsck-dirs [path] [errors_file] [repo_count_file]
|
||||
```
|
||||
|
||||
### Arguments
|
||||
|
||||
- `path`: Directory to scan (defaults to current directory)
|
||||
- `errors_file`: Path to save errors (defaults to /tmp/git-fsck-errors.txt)
|
||||
- `repo_count_file`: Path to save repository count
|
||||
(defaults to /tmp/git-fsck-repo-count.txt)
|
||||
|
||||
### Environment Variables
|
||||
|
||||
- `VERBOSE=1`: Enable verbose output
|
||||
- `DEBUG=1`: Enable debug mode (shows executed commands)
|
||||
|
||||
## Examples
|
||||
|
||||
Check repositories in the current directory:
|
||||
|
||||
```bash
|
||||
git fsck-dirs
|
||||
git-fsck-dirs
|
||||
```
|
||||
|
||||
Check repositories in a specific directory:
|
||||
|
||||
```bash
|
||||
git fsck-dirs ~/projects
|
||||
git-fsck-dirs ~/projects
|
||||
```
|
||||
|
||||
Enable verbose output:
|
||||
|
||||
```bash
|
||||
VERBOSE=1 git-fsck-dirs
|
||||
```
|
||||
|
||||
## License
|
||||
|
||||
MIT License - Copyright 2023 Ismo Vuorinen
|
||||
|
||||
<!-- vim: set ft=markdown cc=80 : -->
|
||||
@@ -8,39 +8,688 @@
|
||||
# Copyright (c) 2023 Ismo Vuorinen. All Rights Reserved.
|
||||
# License: MIT <https://opensource.org/license/mit/>
|
||||
|
||||
set -euo pipefail
|
||||
set -uo pipefail
|
||||
|
||||
# Enable verbosity with VERBOSE=1
|
||||
VERBOSE="${VERBOSE:-0}"
|
||||
# Script version
|
||||
VERSION="1.0.0"
|
||||
|
||||
# Default settings
|
||||
VERBOSE=0
|
||||
QUIET=0
|
||||
EXCLUDE_DIRS=""
|
||||
CLEANUP=0
|
||||
CONFIG_FILE=""
|
||||
LOG_FILE=""
|
||||
|
||||
# Define color variables if terminal supports it
|
||||
if [[ -t 1 ]]; then
|
||||
RED='\033[0;31m'
|
||||
GREEN='\033[0;32m'
|
||||
YELLOW='\033[0;33m'
|
||||
BLUE='\033[0;34m'
|
||||
CYAN='\033[0;36m'
|
||||
NC='\033[0m' # No Color
|
||||
else
|
||||
RED=''
|
||||
GREEN=''
|
||||
YELLOW=''
|
||||
BLUE=''
|
||||
CYAN=''
|
||||
NC=''
|
||||
fi
|
||||
|
||||
# Counters
|
||||
TOTAL=0
|
||||
SUCCESS=0
|
||||
FAILED=0
|
||||
CONFLICTS=0
|
||||
UPDATED=0
|
||||
PROCESSED=0
|
||||
SKIPPED=0
|
||||
UNTRACKED=0
|
||||
UNMERGED=0
|
||||
BRANCHES_CLEANED=0
|
||||
|
||||
# Function to display help message
|
||||
show_help()
|
||||
{
|
||||
BIN=$(basename "$0")
|
||||
cat << EOF
|
||||
Usage: $BIN [OPTIONS]
|
||||
|
||||
Updates all git repositories in subdirectories.
|
||||
|
||||
Options:
|
||||
--help, -h Display this help message and exit
|
||||
--version, -v Display version information and exit
|
||||
--verbose Display detailed output
|
||||
--quiet, -q Suppress all output except errors
|
||||
--exclude DIR Exclude directory from updates (can be used multiple times)
|
||||
--cleanup Remove local branches that have been merged into current branch
|
||||
--config FILE Read options from configuration file
|
||||
--log FILE Log details and errors to FILE
|
||||
|
||||
Environment variables:
|
||||
VERBOSE Set to 1 to enable verbose output
|
||||
EXCLUDE_DIRS Space-separated list of directories to exclude
|
||||
|
||||
Examples:
|
||||
$BIN Update all git repositories
|
||||
$BIN --verbose Update with detailed output
|
||||
$BIN --exclude node_modules --exclude vendor
|
||||
Update repositories but skip node_modules
|
||||
and vendor dirs
|
||||
$BIN --cleanup Update and clean up merged branches
|
||||
$BIN --config ~/.gitupdate.conf
|
||||
Use options from config file
|
||||
EOF
|
||||
exit 0
|
||||
}
|
||||
|
||||
# Function to display version
|
||||
show_version()
|
||||
{
|
||||
echo "$(basename "$0") version $VERSION"
|
||||
exit 0
|
||||
}
|
||||
|
||||
# Function to log messages
|
||||
# $1 - level (string: INFO, WARNING, ERROR)
|
||||
# $2 - message (string)
|
||||
log()
|
||||
{
|
||||
local level message timestamp
|
||||
|
||||
level="$1"
|
||||
message="$2"
|
||||
timestamp=$(date +"%Y-%m-%d %H:%M:%S")
|
||||
|
||||
if [[ -n "$LOG_FILE" ]]; then
|
||||
echo "[$timestamp] [$level] $message" >> "$LOG_FILE"
|
||||
fi
|
||||
|
||||
# For errors, also log to stderr if in verbose mode
|
||||
if [[ "$level" == "ERROR" && "$VERBOSE" -eq 1 && "$QUIET" -eq 0 ]]; then
|
||||
echo -e "${RED}[$timestamp] [$level] $message${NC}" >&2
|
||||
fi
|
||||
}
|
||||
|
||||
# Process command-line arguments
|
||||
process_args()
|
||||
{
|
||||
while [[ $# -gt 0 ]]; do
|
||||
case "$1" in
|
||||
--help | -h)
|
||||
show_help
|
||||
;;
|
||||
--version | -v)
|
||||
show_version
|
||||
;;
|
||||
--verbose)
|
||||
VERBOSE=1
|
||||
;;
|
||||
--quiet | -q)
|
||||
QUIET=1
|
||||
;;
|
||||
--exclude)
|
||||
if [[ -n "$2" ]]; then
|
||||
EXCLUDE_DIRS="$EXCLUDE_DIRS $2"
|
||||
shift
|
||||
else
|
||||
echo "Error: --exclude requires a directory argument" >&2
|
||||
exit 1
|
||||
fi
|
||||
;;
|
||||
--cleanup)
|
||||
CLEANUP=1
|
||||
;;
|
||||
--config)
|
||||
if [[ -n "$2" && -f "$2" ]]; then
|
||||
CONFIG_FILE="$2"
|
||||
shift
|
||||
else
|
||||
echo "Error: --config requires a valid file argument" >&2
|
||||
exit 1
|
||||
fi
|
||||
;;
|
||||
--log)
|
||||
if [[ -n "$2" ]]; then
|
||||
LOG_FILE="$2"
|
||||
shift
|
||||
else
|
||||
echo "Error: --log requires a file argument" >&2
|
||||
exit 1
|
||||
fi
|
||||
;;
|
||||
*)
|
||||
echo "Unknown option: $1" >&2
|
||||
echo "Use --help for usage information" >&2
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
shift
|
||||
done
|
||||
|
||||
# Process config file if specified
|
||||
if [[ -n "$CONFIG_FILE" && -f "$CONFIG_FILE" ]]; then
|
||||
log "INFO" "Reading configuration from $CONFIG_FILE"
|
||||
while IFS= read -r line || [[ -n "$line" ]]; do
|
||||
# Skip comments and empty lines
|
||||
[[ "$line" =~ ^[[:space:]]*# ]] && continue
|
||||
[[ -z "${line// /}" ]] && continue
|
||||
|
||||
# Process each option from the config file
|
||||
option=$(echo "$line" | awk '{print $1}')
|
||||
value=$(echo "$line" | cut -d' ' -f2-)
|
||||
|
||||
case "$option" in
|
||||
exclude) EXCLUDE_DIRS="$EXCLUDE_DIRS $value" ;;
|
||||
verbose) VERBOSE=1 ;;
|
||||
quiet) QUIET=1 ;;
|
||||
cleanup) CLEANUP=1 ;;
|
||||
log) LOG_FILE="$value" ;;
|
||||
*) log "WARNING" "Unknown option in config file: $option" ;;
|
||||
esac
|
||||
done < "$CONFIG_FILE"
|
||||
fi
|
||||
|
||||
# Environment variables override command-line options
|
||||
[[ -n "${VERBOSE:-}" && "$VERBOSE" -eq 1 ]] && VERBOSE=1
|
||||
# shellcheck disable=SC2269
|
||||
[[ -n "${EXCLUDE_DIRS:-}" ]] && EXCLUDE_DIRS="${EXCLUDE_DIRS}"
|
||||
|
||||
# Initialize log file if specified
|
||||
if [[ -n "$LOG_FILE" ]]; then
|
||||
# Create log directory if it doesn't exist
|
||||
mkdir -p "$(dirname "$LOG_FILE")" 2> /dev/null || true
|
||||
# Initialize log file
|
||||
echo "[$(date +"%Y-%m-%d %H:%M:%S")] [INFO] Started git-update-dirs version $VERSION" > "$LOG_FILE"
|
||||
fi
|
||||
}
|
||||
|
||||
# Terminal width for progress bar
|
||||
TERM_WIDTH=$(tput cols 2> /dev/null || echo 120)
|
||||
PROGRESS_WIDTH=$((TERM_WIDTH - 40))
|
||||
MAX_DIR_LENGTH=$((TERM_WIDTH - PROGRESS_WIDTH - 25)) # Add 5 for extra padding
|
||||
|
||||
# Last status message, used for clearing properly
|
||||
LAST_STATUS_LENGTH=0
|
||||
|
||||
# Function to print messages if VERBOSE is enabled
|
||||
# $1 - message (string)
|
||||
msg()
|
||||
{
|
||||
[ "$VERBOSE" -eq 1 ] && echo "$1"
|
||||
local message
|
||||
message="$1"
|
||||
if [[ "$VERBOSE" -eq 1 && "$QUIET" -eq 0 ]]; then
|
||||
echo "$message"
|
||||
[[ -n "$LOG_FILE" ]] && log "INFO" "$message"
|
||||
elif [[ -n "$LOG_FILE" ]]; then
|
||||
log "DEBUG" "$message"
|
||||
fi
|
||||
}
|
||||
|
||||
# Function to print normal output unless QUIET is enabled
|
||||
# $1 - message (string)
|
||||
print()
|
||||
{
|
||||
local message
|
||||
message="$1"
|
||||
if [[ "$QUIET" -eq 0 ]]; then
|
||||
echo -e "$message"
|
||||
[[ -n "$LOG_FILE" ]] && log "INFO" "$message"
|
||||
elif [[ -n "$LOG_FILE" ]]; then
|
||||
log "INFO" "$message"
|
||||
fi
|
||||
}
|
||||
|
||||
# Function to display progress bar
|
||||
# $1 - current (int)
|
||||
# $2 - total (int)
|
||||
# $3 - status message (string)
|
||||
show_progress()
|
||||
{
|
||||
[[ "$QUIET" -eq 1 ]] && return
|
||||
|
||||
local current total status percent filled empty
|
||||
|
||||
current=$1
|
||||
total=$2
|
||||
status=$3
|
||||
|
||||
# If TERM_WIDTH is less than LAST_STATUS_LENGTH set TERM_WIDTH
|
||||
# to it.
|
||||
if [[ $TERM_WIDTH -lt $LAST_STATUS_LENGTH ]]; then
|
||||
TERM_WIDTH=$LAST_STATUS_LENGTH
|
||||
fi
|
||||
|
||||
# Clear the entire line before updating to avoid artifacts
|
||||
printf "\r%-${TERM_WIDTH}s" " "
|
||||
|
||||
# Avoid division by zero
|
||||
if [[ "$total" -eq 0 ]]; then
|
||||
percent=0
|
||||
else
|
||||
percent=$((current * 100 / total))
|
||||
fi
|
||||
|
||||
filled=$((percent * PROGRESS_WIDTH / 100))
|
||||
# Ensure filled doesn't exceed PROGRESS_WIDTH
|
||||
[[ $filled -gt $PROGRESS_WIDTH ]] && filled=$PROGRESS_WIDTH
|
||||
empty=$((PROGRESS_WIDTH - filled))
|
||||
|
||||
# Truncate status message if too long
|
||||
if [[ ${#status} -gt $MAX_DIR_LENGTH ]]; then
|
||||
status="...${status:$((${#status} - MAX_DIR_LENGTH + 4))}"
|
||||
fi
|
||||
|
||||
# Pad the status message to ensure consistent width and add extra space
|
||||
printf -v padded_status "%-${MAX_DIR_LENGTH}s" "$status"
|
||||
|
||||
# Create and display the progress bar with fixed width for percentage and colors
|
||||
printf "\r[${BLUE}%s${NC}%s] ${GREEN}%3d%%${NC} ${CYAN}%s${NC}" \
|
||||
"$(printf '#%.0s' $(seq 1 $filled))" \
|
||||
"$(printf ' %.0s' $(seq 1 $empty))" \
|
||||
"$percent" \
|
||||
"$padded_status"
|
||||
|
||||
# Store the length of the current status
|
||||
LAST_STATUS_LENGTH=${#status}
|
||||
|
||||
# Log progress if logging is enabled
|
||||
[[ -n "$LOG_FILE" ]] && log "DEBUG" "Progress: $percent% - $status"
|
||||
}
|
||||
|
||||
# Is the directory path excluded?
|
||||
# $1: Directory path
|
||||
# Return 0 if the directory should be skipped, 1 otherwise
|
||||
excluded_path()
|
||||
{
|
||||
local dir home
|
||||
dir="$(realpath "$1")"
|
||||
home="$(realpath "$HOME")"
|
||||
|
||||
# Check if directory should be excluded
|
||||
for exclude in $EXCLUDE_DIRS; do
|
||||
# Check for parts of the directory name
|
||||
if [[ "$dir" == *"$exclude"* ]] || [[ "$dir" == "$exclude" ]]; then
|
||||
msg "Skipping excluded directory: $dir"
|
||||
return 0
|
||||
fi
|
||||
|
||||
# Run only if home is not empty
|
||||
if [[ -n "$home" ]]; then
|
||||
# Remove home directory from path
|
||||
relative_dir="${dir/"$home"/}"
|
||||
|
||||
# Check if we should exclude based on relative paths based on the home directory
|
||||
if [[ "$relative_dir" == *"$exclude"* ]] || [[ "$relative_dir" == "$exclude" ]]; then
|
||||
msg "Skipping excluded relative directory: $dir"
|
||||
return 0
|
||||
fi
|
||||
fi
|
||||
done
|
||||
|
||||
# Check if it's a git repository
|
||||
if [[ ! -d "$dir/.git" ]]; then
|
||||
msg "Skipping non-git directory: $dir"
|
||||
return 0
|
||||
fi
|
||||
|
||||
return 1
|
||||
}
|
||||
|
||||
# Function to count git repositories
|
||||
count_git_repos()
|
||||
{
|
||||
local count=0
|
||||
for dir in */; do
|
||||
if ! excluded_path "$dir"; then
|
||||
((count++))
|
||||
fi
|
||||
done
|
||||
echo $count
|
||||
}
|
||||
|
||||
# Check for unmerged files or conflicts in a git repository
|
||||
# Returns 0 if there are unmerged files, 1 otherwise
|
||||
has_unmerged_files()
|
||||
{
|
||||
git ls-files --unmerged | grep -q "^" \
|
||||
&& return 0 || return 1
|
||||
}
|
||||
|
||||
# Check for clean working directory
|
||||
# Returns 0 if working directory is clean, 1 otherwise
|
||||
is_repo_clean()
|
||||
{
|
||||
git diff --quiet \
|
||||
&& git diff --cached --quiet \
|
||||
&& return 0 || return 1
|
||||
}
|
||||
|
||||
# Function to clean up local branches that have been merged
|
||||
# Returns the number of branches cleaned
|
||||
cleanup_branches()
|
||||
{
|
||||
local cleaned=0
|
||||
local current_branch output
|
||||
|
||||
current_branch=$(git symbolic-ref --short HEAD 2> /dev/null)
|
||||
|
||||
# Skip branch cleanup if we're not on a main branch
|
||||
if [[ ! "$current_branch" =~ ^(master|main|develop)$ ]]; then
|
||||
msg "Skipping branch cleanup: not on a main branch ($current_branch)"
|
||||
return 0
|
||||
fi
|
||||
|
||||
# Get list of merged branches, excluding current branch, master, main, and develop
|
||||
output=$(git branch --merged | grep -v -E "^\*|master|main|develop" | sed 's/^[[:space:]]*//')
|
||||
|
||||
if [[ -n "$output" ]]; then
|
||||
if [[ "$VERBOSE" -eq 1 ]]; then
|
||||
msg "Cleaning up merged branches in $(pwd):"
|
||||
echo "$output" | while read -r branch; do
|
||||
msg " - $branch"
|
||||
done
|
||||
fi
|
||||
|
||||
# Delete branches
|
||||
for branch in $output; do
|
||||
if [[ -n "$branch" ]]; then
|
||||
if git branch -d "$branch" &> /dev/null; then
|
||||
((cleaned++))
|
||||
log "INFO" "Deleted merged branch $branch in $(pwd)"
|
||||
else
|
||||
log "WARNING" "Failed to delete branch $branch in $(pwd)"
|
||||
fi
|
||||
fi
|
||||
done
|
||||
fi
|
||||
|
||||
return $cleaned
|
||||
}
|
||||
|
||||
# Function to update a git repository
|
||||
# $1 - directory (string)
|
||||
update_repo()
|
||||
{
|
||||
local dir=$1
|
||||
(
|
||||
cd "$dir" || exit
|
||||
msg "Updating $dir"
|
||||
git pull --rebase --autostash --prune
|
||||
)
|
||||
local dir output exit_status git_args current_branch \
|
||||
remote_name cleaned_branches
|
||||
|
||||
dir="$1"
|
||||
log "INFO" "Processing repository: $dir"
|
||||
|
||||
# Increment the processed counter
|
||||
((PROCESSED++))
|
||||
|
||||
# Show progress before starting the operation
|
||||
show_progress "$PROCESSED" "$TOTAL" "${dir%/}"
|
||||
|
||||
cd "$dir" 2> /dev/null || {
|
||||
log "ERROR" "Could not enter directory $dir"
|
||||
echo -e "\n${RED}Error: Could not enter directory $dir${NC}" >&2
|
||||
((FAILED++))
|
||||
return 1
|
||||
}
|
||||
|
||||
# If there are no remotes, skip
|
||||
if ! git remote -v &> /dev/null; then
|
||||
log "INFO" "Skipping directory with no remotes: $dir"
|
||||
msg "Skipping directory with no remotes: $dir"
|
||||
((SKIPPED++))
|
||||
cd - > /dev/null || true
|
||||
return 1
|
||||
fi
|
||||
|
||||
# Get current branch name
|
||||
current_branch=$(git symbolic-ref --short HEAD 2> /dev/null)
|
||||
if [[ -z "$current_branch" ]]; then
|
||||
log "INFO" "Skipping repository in detached HEAD state: $dir"
|
||||
msg "Skipping repository in detached HEAD state: $dir"
|
||||
((SKIPPED++))
|
||||
cd - > /dev/null || true
|
||||
return 1
|
||||
fi
|
||||
|
||||
# Check if current branch has tracking information
|
||||
eval "git rev-parse --abbrev-ref --symbolic-full-name @{u} 2>/dev/null" &> /dev/null || {
|
||||
log "INFO" "Skipping branch '$current_branch' without tracking info in $dir"
|
||||
msg "Skipping branch '$current_branch' without tracking info in $dir"
|
||||
((SKIPPED++))
|
||||
cd - > /dev/null || true
|
||||
return 1
|
||||
}
|
||||
|
||||
# Check if remote is accessible
|
||||
remote_name=$(git config --get branch."$current_branch".remote)
|
||||
if [[ -n "$remote_name" ]]; then
|
||||
if ! git ls-remote --exit-code "$remote_name" &> /dev/null; then
|
||||
log "WARNING" "Skipping repository with inaccessible remote '$remote_name': $dir"
|
||||
msg "Skipping repository with inaccessible remote: $dir"
|
||||
((SKIPPED++))
|
||||
cd - > /dev/null || true
|
||||
return 1
|
||||
fi
|
||||
fi
|
||||
|
||||
# Check for unmerged files before attempting pull
|
||||
if has_unmerged_files; then
|
||||
log "WARNING" "Skipping repository with unmerged files: $dir"
|
||||
msg "Skipping repository with unmerged files: $dir"
|
||||
((UNMERGED++))
|
||||
cd - > /dev/null || true
|
||||
return 1
|
||||
fi
|
||||
|
||||
# Configure Git arguments based on verbosity
|
||||
git_args="--rebase --autostash --prune"
|
||||
if [[ "$VERBOSE" -eq 0 ]]; then
|
||||
git_args="$git_args --quiet"
|
||||
fi
|
||||
|
||||
# Disable Git hints and set other environment variables
|
||||
export GIT_MERGE_AUTOEDIT=no
|
||||
export GIT_CONFIG_COUNT=4
|
||||
export GIT_CONFIG_KEY_0="advice.skipHints"
|
||||
export GIT_CONFIG_VALUE_0="true"
|
||||
export GIT_CONFIG_KEY_1="advice.detachedHead"
|
||||
export GIT_CONFIG_VALUE_1="false"
|
||||
export GIT_CONFIG_KEY_2="advice.pushUpdateRejected"
|
||||
export GIT_CONFIG_VALUE_2="false"
|
||||
export GIT_CONFIG_KEY_3="advice.statusHints"
|
||||
export GIT_CONFIG_VALUE_3="false"
|
||||
|
||||
# Capture the output of git pull
|
||||
if [[ "$VERBOSE" -eq 1 ]]; then
|
||||
# shellcheck disable=SC2086
|
||||
output=$(git pull $git_args 2>&1)
|
||||
exit_status=$?
|
||||
# In verbose mode, show the git output
|
||||
[[ "$QUIET" -eq 0 ]] && echo -e "\n$output\n"
|
||||
log "DEBUG" "Git pull output: $output"
|
||||
else
|
||||
# In non-verbose mode, suppress normal output but capture errors
|
||||
# shellcheck disable=SC2086
|
||||
output=$(git pull $git_args 2>&1) || {
|
||||
exit_status=$?
|
||||
}
|
||||
|
||||
# If no error occurred, set exit_status to 0
|
||||
exit_status=${exit_status:-0}
|
||||
fi
|
||||
|
||||
# Unset environment variables
|
||||
unset GIT_MERGE_AUTOEDIT GIT_CONFIG_COUNT \
|
||||
GIT_CONFIG_KEY_0 GIT_CONFIG_KEY_1 \
|
||||
GIT_CONFIG_KEY_2 GIT_CONFIG_KEY_3 \
|
||||
GIT_CONFIG_VALUE_0 GIT_CONFIG_VALUE_1 \
|
||||
GIT_CONFIG_VALUE_2 GIT_CONFIG_VALUE_3
|
||||
|
||||
# Check for specific error conditions
|
||||
if echo "$output" | grep -q "Merge conflict"; then
|
||||
if [[ "$VERBOSE" -eq 1 ]]; then
|
||||
echo ""
|
||||
echo -e "${YELLOW}Merge conflict detected in $dir. Aborting update.${NC}" >&2
|
||||
fi
|
||||
log "WARNING" "Merge conflict detected in $dir. Aborting update."
|
||||
git rebase --abort &> /dev/null || git merge --abort &> /dev/null || true
|
||||
((CONFLICTS++))
|
||||
elif echo "$output" | grep -q "unmerged files"; then
|
||||
if [[ "$VERBOSE" -eq 1 ]]; then
|
||||
echo ""
|
||||
echo -e "${YELLOW}Unmerged files detected in $dir. Aborting update.${NC}" >&2
|
||||
fi
|
||||
log "WARNING" "Unmerged files detected in $dir. Aborting update."
|
||||
((UNMERGED++))
|
||||
elif echo "$output" | grep -q "untracked working tree files would be overwritten by merge"; then
|
||||
if [[ "$VERBOSE" -eq 1 ]]; then
|
||||
echo ""
|
||||
echo -e "${YELLOW}Untracked files would be overwritten in $dir. Aborting update.${NC}" >&2
|
||||
fi
|
||||
log "WARNING" "Untracked files would be overwritten in $dir. Aborting update."
|
||||
((UNTRACKED++))
|
||||
elif [[ $exit_status -ne 0 ]]; then
|
||||
if [[ "$VERBOSE" -eq 1 || "$QUIET" -eq 0 ]]; then
|
||||
echo ""
|
||||
echo -e "${RED}Error updating $dir${NC}" >&2
|
||||
echo "$output" >&2
|
||||
fi
|
||||
log "ERROR" "Failed to update $dir: $output"
|
||||
((FAILED++))
|
||||
else
|
||||
# Check if any changes were pulled
|
||||
if echo "$output" | grep -qE '(file changed|files changed|insertions|deletions)' \
|
||||
|| ! echo "$output" | grep -q "Already up to date."; then
|
||||
log "INFO" "Repository updated with changes: $dir"
|
||||
((UPDATED++))
|
||||
else
|
||||
log "INFO" "Repository already up to date: $dir"
|
||||
fi
|
||||
((SUCCESS++))
|
||||
|
||||
# Clean up branches if requested
|
||||
if [[ "$CLEANUP" -eq 1 ]]; then
|
||||
cleaned_branches=$(cleanup_branches)
|
||||
if [[ $cleaned_branches -gt 0 ]]; then
|
||||
((BRANCHES_CLEANED += cleaned_branches))
|
||||
log "INFO" "Cleaned up $cleaned_branches merged branches in $dir"
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
|
||||
# Return to original directory
|
||||
cd - > /dev/null || true
|
||||
|
||||
# Show progress after completion
|
||||
show_progress "$PROCESSED" "$TOTAL" "${dir%/} - Done"
|
||||
}
|
||||
|
||||
# Main function to update all subfolder git repositories
|
||||
main()
|
||||
{
|
||||
local current_dir start_time end_time duration
|
||||
|
||||
# Record start time
|
||||
start_time=$(date +%s)
|
||||
|
||||
# Process command-line args before doing anything else
|
||||
process_args "$@"
|
||||
|
||||
# Save current directory to return to it later
|
||||
current_dir=$(pwd)
|
||||
log "INFO" "Starting repository updates in $current_dir"
|
||||
|
||||
# Count repositories and set TOTAL
|
||||
TOTAL=$(count_git_repos)
|
||||
print "Found $TOTAL git repositories to update"
|
||||
|
||||
# Reset other counters
|
||||
PROCESSED=0
|
||||
SUCCESS=0
|
||||
FAILED=0
|
||||
CONFLICTS=0
|
||||
UPDATED=0
|
||||
SKIPPED=0
|
||||
UNTRACKED=0
|
||||
UNMERGED=0
|
||||
BRANCHES_CLEANED=0
|
||||
|
||||
# Process each repository
|
||||
for dir in */; do
|
||||
# Skip if excluded
|
||||
if excluded_path "$dir"; then
|
||||
continue
|
||||
fi
|
||||
update_repo "$dir"
|
||||
done
|
||||
|
||||
echo "Done."
|
||||
echo ""
|
||||
# Return to original directory
|
||||
cd "$current_dir" || true
|
||||
|
||||
# Clear the progress line completely
|
||||
[[ "$QUIET" -eq 0 ]] && printf "\r%-${TERM_WIDTH}s\r" " "
|
||||
|
||||
# Calculate duration
|
||||
end_time=$(date +%s)
|
||||
duration=$((end_time - start_time))
|
||||
minutes=$((duration / 60))
|
||||
seconds=$((duration % 60))
|
||||
|
||||
# Format duration nicely
|
||||
if [[ $minutes -gt 0 ]]; then
|
||||
duration_str="${minutes}m ${seconds}s"
|
||||
else
|
||||
duration_str="${seconds}s"
|
||||
fi
|
||||
|
||||
# Print summary unless quiet mode is enabled
|
||||
if [[ "$QUIET" -eq 0 ]]; then
|
||||
echo ""
|
||||
print "${GREEN}Summary: Updated $SUCCESS/$TOTAL repositories successfully in $duration_str.${NC}"
|
||||
print "${CYAN}Repositories with changes pulled: $UPDATED${NC}"
|
||||
|
||||
if [[ $SKIPPED -gt 0 ]]; then
|
||||
print "${YELLOW}Skipped $SKIPPED repositories (no tracking branch or other issues).${NC}"
|
||||
fi
|
||||
|
||||
if [[ $UNMERGED -gt 0 ]]; then
|
||||
print "${YELLOW}Skipped $UNMERGED repositories with unmerged files.${NC}"
|
||||
fi
|
||||
|
||||
if [[ $UNTRACKED -gt 0 ]]; then
|
||||
print "${YELLOW}Skipped $UNTRACKED repositories with untracked files that would be overwritten.${NC}"
|
||||
fi
|
||||
|
||||
if [[ $CONFLICTS -gt 0 ]]; then
|
||||
print "${YELLOW}Encountered merge conflicts in $CONFLICTS repositories.${NC}"
|
||||
fi
|
||||
|
||||
if [[ $CLEANUP -eq 1 && $BRANCHES_CLEANED -gt 0 ]]; then
|
||||
print "${BLUE}Cleaned up $BRANCHES_CLEANED merged branches.${NC}"
|
||||
fi
|
||||
|
||||
if [[ $FAILED -gt 0 ]]; then
|
||||
echo -e "${RED}Failed to update $FAILED repositories.${NC}" >&2
|
||||
else
|
||||
print "${GREEN}Done.${NC}"
|
||||
fi
|
||||
fi
|
||||
|
||||
# Log final summary
|
||||
if [[ -n "$LOG_FILE" ]]; then
|
||||
log "INFO" "Completed in $duration_str"
|
||||
log "INFO" "Summary: $SUCCESS/$TOTAL repositories updated successfully"
|
||||
log "INFO" "Repositories with changes pulled: $UPDATED"
|
||||
log "INFO" "Skipped: $SKIPPED, Unmerged: $UNMERGED, Untracked: $UNTRACKED, Conflicts: $CONFLICTS, Failed: $FAILED"
|
||||
if [[ $CLEANUP -eq 1 ]]; then
|
||||
log "INFO" "Branches cleaned up: $BRANCHES_CLEANED"
|
||||
fi
|
||||
fi
|
||||
|
||||
# Return appropriate exit code
|
||||
[[ $FAILED -gt 0 ]] && return 1 || return 0
|
||||
}
|
||||
|
||||
# Call main with all arguments
|
||||
main "$@"
|
||||
|
||||
116
local/bin/git-update-dirs.md
Normal file
116
local/bin/git-update-dirs.md
Normal file
@@ -0,0 +1,116 @@
|
||||
# git-update-dirs
|
||||
|
||||
A tool that efficiently updates all Git repositories in subdirectories
|
||||
of the current folder.
|
||||
|
||||
## Overview
|
||||
|
||||
`git-update-dirs` scans the current directory for Git repositories
|
||||
and updates them with:
|
||||
|
||||
- Fast parallel execution
|
||||
- Intelligent error handling
|
||||
- Progress visualization
|
||||
- Detailed logging
|
||||
- Optional branch cleanup
|
||||
|
||||
## Installation
|
||||
|
||||
Place the script in your PATH and make it executable:
|
||||
|
||||
```bash
|
||||
# Using wget
|
||||
wget -O ~/bin/git-update-dirs https://raw.githubusercontent.com/ivuorinen/dotfiles/main/local/bin/git-update-dirs
|
||||
chmod +x ~/bin/git-update-dirs
|
||||
|
||||
# Or simply copy the script to a location in your PATH
|
||||
cp git-update-dirs ~/bin/
|
||||
chmod +x ~/bin/git-update-dirs
|
||||
```
|
||||
|
||||
## Usage
|
||||
|
||||
```text
|
||||
Usage: git-update-dirs [OPTIONS]
|
||||
|
||||
Updates all git repositories in subdirectories.
|
||||
|
||||
Options:
|
||||
--help, -h Display this help message and exit
|
||||
--version, -v Display version information and exit
|
||||
--verbose Display detailed output
|
||||
--quiet, -q Suppress all output except errors
|
||||
--exclude DIR Exclude directory from updates
|
||||
(can be used multiple times)
|
||||
--cleanup Remove local branches that have been merged into
|
||||
current branch
|
||||
--config FILE Read options from configuration file
|
||||
--log FILE Log details and errors to FILE
|
||||
|
||||
Environment variables:
|
||||
VERBOSE Set to 1 to enable verbose output
|
||||
EXCLUDE_DIRS Space-separated list of directories to exclude
|
||||
```
|
||||
|
||||
## Examples
|
||||
|
||||
Basic usage to update all repositories:
|
||||
|
||||
```bash
|
||||
git-update-dirs
|
||||
```
|
||||
|
||||
Update with detailed output:
|
||||
|
||||
```bash
|
||||
git-update-dirs --verbose
|
||||
```
|
||||
|
||||
Exclude specific directories:
|
||||
|
||||
```bash
|
||||
git-update-dirs --exclude node_modules --exclude vendor
|
||||
```
|
||||
|
||||
Update and clean up merged branches:
|
||||
|
||||
```bash
|
||||
git-update-dirs --cleanup
|
||||
```
|
||||
|
||||
Use options from a configuration file:
|
||||
|
||||
```bash
|
||||
git-update-dirs --config ~/.gitupdate.conf
|
||||
```
|
||||
|
||||
## Configuration File
|
||||
|
||||
You can create a configuration file to store your preferred options:
|
||||
|
||||
```text
|
||||
# Example ~/.gitupdate.conf
|
||||
verbose
|
||||
exclude node_modules
|
||||
exclude vendor
|
||||
cleanup
|
||||
log ~/.gitupdate.log
|
||||
```
|
||||
|
||||
## Features
|
||||
|
||||
- **Smart Updates**: Uses `--rebase --autostash --prune`
|
||||
for clean updates
|
||||
- **Error Handling**: Skips repositories with conflicts or
|
||||
untracked files that would be overwritten
|
||||
- **Visual Progress**: Shows a progress bar with current status
|
||||
- **Repository Management**: Optionally cleans up merged branches
|
||||
- **Detailed Logging**: Records all operations with timestamps
|
||||
|
||||
## License
|
||||
|
||||
[MIT License][MIT] - Copyright 2023 Ismo Vuorinen
|
||||
|
||||
[MIT]: https://opensource.org/license/mit/
|
||||
|
||||
<!-- vim: set ft=markdown cc=80 : -->
|
||||
443
local/bin/php-switcher
Executable file
443
local/bin/php-switcher
Executable file
@@ -0,0 +1,443 @@
|
||||
#!/usr/bin/env bash
|
||||
#
|
||||
# Brew PHP Switcher
|
||||
#
|
||||
# Use to switch between PHP versions installed via Homebrew.
|
||||
#
|
||||
# Usage: php-switcher <version> [--help|--installed|--current|--auto]
|
||||
# Example: php-switcher 7.4
|
||||
# Example: php-switcher 8.0
|
||||
# Example: php-switcher latest
|
||||
# Example: php-switcher --auto
|
||||
#
|
||||
# Created by Ismo Vuorinen <https://github.com/ivuorinen> (2025)
|
||||
# Licensed under the MIT License (https://opensource.org/licenses/MIT)
|
||||
|
||||
set -euo pipefail # Add error handling
|
||||
|
||||
# Configuration
|
||||
LATEST_VERSION_FORMULA="php" # The formula name for latest PHP version
|
||||
PHP_VERSION_FILE=".php-version" # File name to look for when auto-switching
|
||||
|
||||
# Switch brew php version
|
||||
function check_dependencies()
|
||||
{
|
||||
if ! command -v brew > /dev/null 2>&1; then
|
||||
echo "Error: Homebrew is not installed"
|
||||
exit 1
|
||||
fi
|
||||
}
|
||||
|
||||
function usage()
|
||||
{
|
||||
echo "Brew PHP Switcher - Switch between PHP versions installed via Homebrew"
|
||||
echo ""
|
||||
echo "Usage: php-switcher <version> [options]"
|
||||
echo ""
|
||||
echo "Options:"
|
||||
echo " --help Show this help message"
|
||||
echo " --installed List installed PHP versions"
|
||||
echo " --current Show currently active PHP version"
|
||||
echo " --auto Auto-switch based on .php-version file in current directory"
|
||||
echo ""
|
||||
echo "Examples:"
|
||||
echo " php-switcher 7.4"
|
||||
echo " php-switcher 8.0"
|
||||
echo " php-switcher latest"
|
||||
echo " php-switcher --auto"
|
||||
echo ""
|
||||
echo "Auto-switching:"
|
||||
echo " Create a .php-version file in your project directory with a PHP version"
|
||||
echo " Example .php-version content: 8.1"
|
||||
echo ""
|
||||
exit 0
|
||||
}
|
||||
|
||||
function list_php_versions()
|
||||
{
|
||||
# Check Homebrew's installation path for PHP versions
|
||||
local brew_cellar
|
||||
brew_cellar="$(brew --cellar)"
|
||||
local php_paths=()
|
||||
local versions=()
|
||||
local formulas=()
|
||||
local active=()
|
||||
|
||||
# Look for all PHP installations in Homebrew Cellar
|
||||
if [[ -d "$brew_cellar/php" ]]; then
|
||||
php_paths+=("$brew_cellar/php")
|
||||
fi
|
||||
|
||||
# Look for versioned PHP installations
|
||||
while IFS= read -r dir; do
|
||||
if [[ -d $dir ]]; then
|
||||
php_paths+=("$dir")
|
||||
fi
|
||||
done < <(find "$brew_cellar" \
|
||||
-maxdepth 1 -name 'php@*' \
|
||||
-type d 2> /dev/null || echo "")
|
||||
|
||||
if [[ ${#php_paths[@]} -eq 0 ]]; then
|
||||
echo "No PHP versions installed through Homebrew."
|
||||
return 1
|
||||
fi
|
||||
|
||||
# Find which version is currently linked
|
||||
local current_bin
|
||||
current_bin=$(readlink -f \
|
||||
"$(command -v php 2> /dev/null)" \
|
||||
2> /dev/null || echo "")
|
||||
|
||||
# Collect data for each installed PHP version
|
||||
for path in "${php_paths[@]}"; do
|
||||
local formula
|
||||
formula=$(basename "$path")
|
||||
local version_label
|
||||
|
||||
if [[ $formula == "php" ]]; then
|
||||
version_label="latest"
|
||||
else
|
||||
version_label="${formula#php@}"
|
||||
fi
|
||||
|
||||
# Find the actual version from the directory structure
|
||||
local version_dir
|
||||
version_dir=$(find "$path" -maxdepth 1 -type d \
|
||||
| grep -v "^$path$" | sort -V | tail -1)
|
||||
|
||||
if [[ -n $version_dir && -d "$version_dir/bin" ]]; then
|
||||
local full_version
|
||||
full_version=$("$version_dir/bin/php" -v 2> /dev/null \
|
||||
| grep -oE 'PHP [0-9]+\.[0-9]+\.[0-9]+' \
|
||||
| head -1 \
|
||||
| cut -d' ' -f2 \
|
||||
|| echo "$version_label.x")
|
||||
|
||||
# Determine if this is the active version
|
||||
local is_active="No"
|
||||
if [[ -n $current_bin && $current_bin == "$version_dir/bin/php" ]]; then
|
||||
is_active="Yes"
|
||||
fi
|
||||
|
||||
# Handle the 'latest' case - replace with actual version number
|
||||
local display_version
|
||||
if [[ $version_label == "latest" ]]; then
|
||||
display_version="${full_version%.*}" # Get major.minor version
|
||||
else
|
||||
display_version="$version_label"
|
||||
fi
|
||||
|
||||
# Store data for table display
|
||||
versions+=("$display_version")
|
||||
formulas+=("$formula")
|
||||
active+=("$is_active")
|
||||
fi
|
||||
done
|
||||
|
||||
# Calculate maximum column widths
|
||||
local max_version_width=7 # "Version" header length
|
||||
local max_formula_width=7 # "Formula" header length
|
||||
local max_active_width=6 # "Active" header length
|
||||
|
||||
local count=${#versions[@]}
|
||||
for ((i = 0; i < count; i++)); do
|
||||
# Update max widths if needed
|
||||
if [[ ${#versions[i]} -gt $max_version_width ]]; then
|
||||
max_version_width=${#versions[i]}
|
||||
fi
|
||||
if [[ ${#formulas[i]} -gt $max_formula_width ]]; then
|
||||
max_formula_width=${#formulas[i]}
|
||||
fi
|
||||
done
|
||||
|
||||
# Build header with correct widths
|
||||
local header_format="| %-${max_version_width}s | %-${max_formula_width}s | "
|
||||
header_format+="%-${max_active_width}s |"
|
||||
|
||||
local separator_line="|"
|
||||
for ((i = 0; i < max_version_width + 2; i++)); do
|
||||
separator_line="${separator_line}-"
|
||||
done
|
||||
separator_line="${separator_line}|"
|
||||
|
||||
for ((i = 0; i < max_formula_width + 2; i++)); do
|
||||
separator_line="${separator_line}-"
|
||||
done
|
||||
separator_line="${separator_line}|"
|
||||
|
||||
for ((i = 0; i < max_active_width + 2; i++)); do
|
||||
separator_line="${separator_line}-"
|
||||
done
|
||||
separator_line="${separator_line}|"
|
||||
|
||||
# Print table header
|
||||
# shellcheck disable=SC2059
|
||||
printf "$header_format\n" "Version" "Formula" "Active"
|
||||
echo "$separator_line"
|
||||
|
||||
# Print table rows
|
||||
local row_format="| %-${max_version_width}s | %-${max_formula_width}s | "
|
||||
row_format+="%-${max_active_width}s |"
|
||||
|
||||
for ((i = 0; i < count; i++)); do
|
||||
# shellcheck disable=SC2059
|
||||
printf "$row_format\n" "${versions[i]}" "${formulas[i]}" "${active[i]}"
|
||||
done
|
||||
}
|
||||
|
||||
function get_php_formula_for_version()
|
||||
{
|
||||
local version="$1"
|
||||
|
||||
# Handle "latest" as a special case
|
||||
if [[ $version == "latest" ]]; then
|
||||
echo "$LATEST_VERSION_FORMULA"
|
||||
return 0
|
||||
fi
|
||||
|
||||
# The regular version case (e.g., 7.4, 8.1)
|
||||
echo "php@$version"
|
||||
}
|
||||
|
||||
function check_formula_installed()
|
||||
{
|
||||
local formula="$1"
|
||||
local brew_cellar
|
||||
brew_cellar="$(brew --cellar)"
|
||||
|
||||
if [[ $formula == "php" ]]; then
|
||||
if [[ -d "$brew_cellar/php" ]]; then
|
||||
return 0
|
||||
fi
|
||||
elif [[ -d "$brew_cellar/$formula" ]]; then
|
||||
return 0
|
||||
fi
|
||||
|
||||
return 1
|
||||
}
|
||||
|
||||
function unlink_current_php()
|
||||
{
|
||||
local current_formula=""
|
||||
|
||||
# Find formulas more safely
|
||||
while IFS= read -r formula; do
|
||||
if [[ -n $formula ]]; then
|
||||
local linked
|
||||
linked=$(brew info --json=v1 "$formula" \
|
||||
| grep -o '"linked_keg":"[^"]*"' \
|
||||
| grep -v ':"null"')
|
||||
if [[ -n $linked ]]; then
|
||||
current_formula="$formula"
|
||||
break
|
||||
fi
|
||||
fi
|
||||
done < <(brew list --formula | grep -E '^php(@[0-9]+\.[0-9]+)?$' || echo "")
|
||||
|
||||
# If we found a linked formula, unlink it
|
||||
if [[ -n $current_formula ]]; then
|
||||
echo "Unlinking current PHP version ($current_formula)..."
|
||||
brew unlink "$current_formula" > /dev/null 2>&1 || true
|
||||
fi
|
||||
}
|
||||
|
||||
function link_php_version()
|
||||
{
|
||||
local formula="$1"
|
||||
|
||||
if ! check_formula_installed "$formula"; then
|
||||
echo "Error: PHP formula '$formula' is not installed"
|
||||
echo "Available versions:"
|
||||
list_php_versions
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo "Linking $formula..."
|
||||
if ! brew link --force --overwrite "$formula" > /dev/null 2>&1; then
|
||||
echo "Error: Failed to link $formula. Try running manually:"
|
||||
echo " brew link --force --overwrite $formula"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Verify the switch worked
|
||||
if ! command -v php > /dev/null 2>&1; then
|
||||
echo "Warning: PHP was linked but may not be working correctly"
|
||||
fi
|
||||
}
|
||||
|
||||
function get_current_version()
|
||||
{
|
||||
if ! command -v php > /dev/null 2>&1; then
|
||||
echo "No PHP currently linked"
|
||||
return 1
|
||||
fi
|
||||
|
||||
local version
|
||||
version=$(php -v 2> /dev/null \
|
||||
| grep -oE 'PHP [0-9]+\.[0-9]+\.[0-9]+' \
|
||||
| head -1)
|
||||
|
||||
if [[ -z $version ]]; then
|
||||
echo "Unable to determine PHP version"
|
||||
return 1
|
||||
fi
|
||||
|
||||
# Find the corresponding formula
|
||||
local current_version
|
||||
current_version=$(echo "$version" | cut -d' ' -f2)
|
||||
local major_minor
|
||||
major_minor=$(echo "$current_version" | cut -d'.' -f1,2)
|
||||
|
||||
# Check if it's the latest version
|
||||
if check_formula_installed "php" \
|
||||
&& brew info --json=v1 php \
|
||||
| grep -o '"linked_keg":"[^"]*"' \
|
||||
| grep -v ':"null"' \
|
||||
| grep -q .; then
|
||||
echo "Current PHP version: $current_version (latest)"
|
||||
else
|
||||
echo "Current PHP version: $current_version (php@$major_minor)"
|
||||
fi
|
||||
}
|
||||
|
||||
function validate_version()
|
||||
{
|
||||
local version="$1"
|
||||
|
||||
# Valid formats: x.y or latest
|
||||
if [[ ! $version =~ ^([0-9]+\.[0-9]+|latest)$ ]]; then
|
||||
echo "Error: Invalid PHP version format. Use x.y format (e.g., 7.4) or"
|
||||
echo " 'latest'"
|
||||
exit 1
|
||||
fi
|
||||
}
|
||||
|
||||
function find_php_version_file()
|
||||
{
|
||||
local dir="$PWD"
|
||||
|
||||
# Look for .php-version file in current directory and all parent directories
|
||||
while [[ $dir != "/" ]]; do
|
||||
if [[ -f "$dir/$PHP_VERSION_FILE" ]]; then
|
||||
echo "$dir/$PHP_VERSION_FILE"
|
||||
return 0
|
||||
fi
|
||||
dir=$(dirname "$dir")
|
||||
done
|
||||
|
||||
# Check the root directory as well
|
||||
if [[ -f "/$PHP_VERSION_FILE" ]]; then
|
||||
echo "/$PHP_VERSION_FILE"
|
||||
return 0
|
||||
fi
|
||||
|
||||
return 1
|
||||
}
|
||||
|
||||
function auto_switch_php_version()
|
||||
{
|
||||
local version_file
|
||||
|
||||
# Try to find a .php-version file
|
||||
version_file=$(find_php_version_file) || {
|
||||
echo "No .php-version file found in current directory or any parent"
|
||||
echo "directory. Create a $PHP_VERSION_FILE file with your desired"
|
||||
echo "PHP version (e.g., 8.1)"
|
||||
exit 1
|
||||
}
|
||||
|
||||
# Read the version from the file
|
||||
local version
|
||||
version=$(tr -d '[:space:]' < "$version_file")
|
||||
|
||||
echo "Found $PHP_VERSION_FILE file at: $version_file"
|
||||
echo "Requested PHP version: $version"
|
||||
|
||||
# Validate the version
|
||||
validate_version "$version"
|
||||
|
||||
# Switch to the specified version
|
||||
switch_php_version "$version"
|
||||
}
|
||||
|
||||
function switch_php_version()
|
||||
{
|
||||
local version="$1"
|
||||
|
||||
# Get the formula name for the version
|
||||
local formula
|
||||
formula=$(get_php_formula_for_version "$version")
|
||||
|
||||
# Check if the requested PHP version is installed
|
||||
if ! check_formula_installed "$formula"; then
|
||||
echo "Error: PHP version $version is not installed"
|
||||
echo ""
|
||||
list_php_versions
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Get the current version info for comparison
|
||||
local current_info
|
||||
current_info=$(get_current_version 2> /dev/null || echo "None")
|
||||
|
||||
# Skip if we're already on the requested version
|
||||
if [[ $current_info == *"$version"* ]]; then
|
||||
echo "PHP version $version is already active"
|
||||
exit 0
|
||||
fi
|
||||
|
||||
# Perform the switch
|
||||
unlink_current_php
|
||||
link_php_version "$formula"
|
||||
|
||||
# Verify the switch
|
||||
echo ""
|
||||
echo "Switched to:"
|
||||
get_current_version
|
||||
echo ""
|
||||
echo "PHP executable: $(command -v php)"
|
||||
}
|
||||
|
||||
function main()
|
||||
{
|
||||
local version=""
|
||||
|
||||
# Parse arguments
|
||||
case "${1:-}" in
|
||||
--help)
|
||||
usage
|
||||
;;
|
||||
--installed)
|
||||
list_php_versions
|
||||
exit 0
|
||||
;;
|
||||
--current)
|
||||
get_current_version
|
||||
exit 0
|
||||
;;
|
||||
--auto)
|
||||
auto_switch_php_version
|
||||
exit 0
|
||||
;;
|
||||
"")
|
||||
usage
|
||||
;;
|
||||
*)
|
||||
version="$1"
|
||||
;;
|
||||
esac
|
||||
|
||||
# Validate and switch to the specified version
|
||||
validate_version "$version"
|
||||
switch_php_version "$version"
|
||||
}
|
||||
|
||||
# Run the script
|
||||
check_dependencies
|
||||
if [[ ${#@} -eq 0 ]]; then
|
||||
usage
|
||||
else
|
||||
main "$@"
|
||||
fi
|
||||
|
||||
# vim: ft=bash sw=4 ts=4 et tw=80 cc=80 :
|
||||
@@ -1,49 +0,0 @@
|
||||
#!/usr/bin/swift
|
||||
|
||||
// Required parameters:
|
||||
// @raycast.schemaVersion 1
|
||||
// @raycast.title Zalgo Text
|
||||
// @raycast.mode silent
|
||||
// @raycast.author Adam Zethraeus
|
||||
// @raycast.authorURL https://github.com/adam-zethraeus
|
||||
// @raycast.packageName Conversions
|
||||
// @raycast.icon 👹
|
||||
// @raycast.argument1 { "type": "text", "placeholder": "Text to Z̶̶͚̯͗a̩̞͜͜l̫͕ͬͨ̿g͈̫͂ͤ͆͢o̠͚̞ͥ" }
|
||||
// @raycast.argument2 { "type": "text", "optional": true, "placeholder": "Intensity=5" }
|
||||
|
||||
// Documentation:
|
||||
// @raycast.description Converts text to z̫̫̐a̳ͩl̓͂̀ͅg͔̚o̷̦̣͢ t̳͆ḛ̊͟ẍ̮̝́t̵̔ͯ͝
|
||||
|
||||
import Cocoa
|
||||
|
||||
// zalgo function credit mattt @ https://gist.github.com/mattt/b46ab5027f1ee6ab1a45583a41240033
|
||||
func zalgo(_ string: String, intensity: Int = 5) -> String {
|
||||
let combiningDiacriticMarks = 0x0300...0x036f
|
||||
let latinAlphabetUppercase = 0x0041...0x005a
|
||||
let latinAlphabetLowercase = 0x0061...0x007a
|
||||
|
||||
var output: [UnicodeScalar] = []
|
||||
for scalar in string.unicodeScalars {
|
||||
output.append(scalar)
|
||||
guard (latinAlphabetUppercase).contains(numericCast(scalar.value)) ||
|
||||
(latinAlphabetLowercase).contains(numericCast(scalar.value))
|
||||
else {
|
||||
continue
|
||||
}
|
||||
|
||||
for _ in 0...(Int.random(in: 1...intensity)) {
|
||||
let randomScalarValue = Int.random(in: combiningDiacriticMarks)
|
||||
output.append(Unicode.Scalar(randomScalarValue)!)
|
||||
}
|
||||
}
|
||||
|
||||
return String(String.UnicodeScalarView(output))
|
||||
}
|
||||
|
||||
NSPasteboard.general.clearContents()
|
||||
let text = CommandLine.arguments[1]
|
||||
let intensityString = CommandLine.arguments[2]
|
||||
let intensity = Int(intensityString) ?? 5
|
||||
let zalgoText = zalgo(text, intensity: intensity)
|
||||
NSPasteboard.general.setString(zalgoText, forType: .string)
|
||||
print("\(zalgoText) copied to clipboard")
|
||||
@@ -1,41 +0,0 @@
|
||||
#!/usr/bin/env bash
|
||||
#
|
||||
# Check git repo's files .gitattributes and ensure all of them are mapped.
|
||||
# Ismo Vuorinen <https://github.com/ivuorinen> 2022
|
||||
source "${DOTFILES}/config/shared.sh"
|
||||
|
||||
set -euo pipefail
|
||||
|
||||
# Enable verbosity with VERBOSE=1
|
||||
VERBOSE="${VERBOSE:-0}"
|
||||
|
||||
# Function to check if git is installed
|
||||
check_git_installed()
|
||||
{
|
||||
if ! command -v git &> /dev/null; then
|
||||
msg_err "git could not be found, please install it first"
|
||||
fi
|
||||
}
|
||||
|
||||
# Function to check for missing .gitattributes
|
||||
check_gitattributes()
|
||||
{
|
||||
local missing_attributes
|
||||
missing_attributes=$(git ls-files | git check-attr -a --stdin | grep "text: auto" || true)
|
||||
|
||||
if [[ -n "$missing_attributes" ]]; then
|
||||
echo ".gitattributes rule missing for the following files:"
|
||||
echo "$missing_attributes"
|
||||
else
|
||||
echo "All files have a corresponding rule in .gitattributes"
|
||||
fi
|
||||
}
|
||||
|
||||
# Main function
|
||||
main()
|
||||
{
|
||||
check_git_installed
|
||||
check_gitattributes
|
||||
}
|
||||
|
||||
main "$@"
|
||||
@@ -1,209 +0,0 @@
|
||||
#!/usr/bin/env perl
|
||||
|
||||
=head1 NAME
|
||||
|
||||
dupes - Report on files with duplicate contents, via SHA1 hash.
|
||||
|
||||
=cut
|
||||
|
||||
=head1 SYNOPSIS
|
||||
|
||||
dupes [options] directory
|
||||
|
||||
General Options:
|
||||
|
||||
--help Show the help information for this script.
|
||||
--verbose Show useful debugging information.
|
||||
|
||||
=cut
|
||||
|
||||
|
||||
=head1 ABOUT
|
||||
|
||||
dupes is a simple script to report upon files that are identical,
|
||||
recursively.
|
||||
|
||||
The process involves calculating the SHA1 hash of the file contents
|
||||
and reporting on anything collisions we see.
|
||||
|
||||
Note that a collision might be caused by a symbolic link, or hardlink,
|
||||
so blindly deleting duplicates without investigation is almost certainly
|
||||
a mistake.
|
||||
|
||||
=cut
|
||||
|
||||
=head1 AUTHOR
|
||||
|
||||
Steve
|
||||
--
|
||||
http://www.steve.org.uk/
|
||||
|
||||
=cut
|
||||
|
||||
|
||||
=head1 LICENSE
|
||||
|
||||
Copyright (c) 2013 by Steve Kemp. All rights reserved.
|
||||
|
||||
This script is free software;you can redistribute it and/or modify it under
|
||||
the same terms as Perl itself.
|
||||
|
||||
The LICENSE file contains the full text of the license.
|
||||
|
||||
=cut
|
||||
|
||||
|
||||
|
||||
use strict;
|
||||
use warnings;
|
||||
|
||||
use File::Find;
|
||||
use Getopt::Long;
|
||||
use Pod::Usage;
|
||||
|
||||
|
||||
#
|
||||
# Parse the arguments
|
||||
#
|
||||
my %config = parsedOptions();
|
||||
|
||||
|
||||
#
|
||||
# The path to examine.
|
||||
#
|
||||
my $path = $ARGV[0] || '.';
|
||||
|
||||
|
||||
#
|
||||
# Get the hashing object, dynamically.
|
||||
#
|
||||
my $ctx = getHashObject();
|
||||
my %digest;
|
||||
|
||||
|
||||
#
|
||||
# Find files and store the hash of their contents.
|
||||
#
|
||||
find( {
|
||||
'wanted' => sub {
|
||||
if ( -f $_ )
|
||||
{
|
||||
lstat;
|
||||
if ( ( -r _ ) && ( !-l _ ) )
|
||||
{
|
||||
$ctx->reset;
|
||||
$ctx->addfile($_);
|
||||
my $md5 = $ctx->hexdigest;
|
||||
if ( exists $digest{ $md5 } )
|
||||
{
|
||||
push @{ $digest{ $md5 }->{ 'dupes' } }, $_;
|
||||
}
|
||||
else
|
||||
{
|
||||
$digest{ $md5 } = { 'file' => $_,
|
||||
'dupes' => [] };
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
$config{ 'verbose' } && print "Entering $_\n";
|
||||
}
|
||||
},
|
||||
'no_chdir' => 1
|
||||
},
|
||||
$path
|
||||
);
|
||||
|
||||
|
||||
#
|
||||
# Report upon collisions.
|
||||
#
|
||||
foreach my $hash ( keys %digest )
|
||||
{
|
||||
my $dupes = $digest{ $hash }->{ 'dupes' };
|
||||
my $src = $digest{ $hash }->{ 'file' };
|
||||
|
||||
if (@$dupes)
|
||||
{
|
||||
print $src . "\n";
|
||||
foreach my $dupe (@$dupes)
|
||||
{
|
||||
print "\t$dupe\n";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#
|
||||
# All done.
|
||||
#
|
||||
exit(0);
|
||||
|
||||
|
||||
=begin doc
|
||||
|
||||
Load one of M<Digest::SHA> and M<Digest::SHA1>, depending on what is available.
|
||||
|
||||
=end doc
|
||||
|
||||
=cut
|
||||
|
||||
sub getHashObject
|
||||
{
|
||||
my $hash = undef;
|
||||
|
||||
foreach my $module (qw! Digest::SHA Digest::SHA1 !)
|
||||
{
|
||||
|
||||
# If we succeeded in calculating the hash we're done.
|
||||
next if ( defined($hash) );
|
||||
|
||||
# Attempt to load the module
|
||||
my $eval = "use $module;";
|
||||
|
||||
## no critic (Eval)
|
||||
eval($eval);
|
||||
## use critic
|
||||
|
||||
if ( !$@ )
|
||||
{
|
||||
$hash = $module->new;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if ($hash)
|
||||
{
|
||||
return ($hash);
|
||||
}
|
||||
else
|
||||
{
|
||||
print "Failed to load either DIgest::SHA or Digest::SHA1\n";
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
=begin doc
|
||||
|
||||
Parse the options and return suitable values.
|
||||
|
||||
=end doc
|
||||
|
||||
=cut
|
||||
|
||||
sub parsedOptions
|
||||
{
|
||||
my %vars;
|
||||
|
||||
exit
|
||||
if (
|
||||
!GetOptions( "help" => \$vars{ 'help' },
|
||||
"verbose" => \$vars{ 'verbose' } ) );
|
||||
|
||||
pod2usage(1) if ( $vars{ 'help' } );
|
||||
|
||||
return (%vars);
|
||||
|
||||
}
|
||||
|
||||
@@ -1,38 +1,66 @@
|
||||
#!/usr/bin/env bash
|
||||
#
|
||||
# Get latest release version, branch tag, or latest commit from GitHub
|
||||
# Usage: x-gh-get-latest-version <repo>
|
||||
# Usage: x-gh-get-latest-version <repo> [options]
|
||||
# Author: Ismo Vuorinen <https://github.com/ivuorinen> 2024
|
||||
|
||||
set -euo pipefail
|
||||
|
||||
# Environment variables, more under get_release_version() and get_latest_branch_tag()
|
||||
# functions. These can be overridden by the user.
|
||||
# Environment variables, can be overridden by command line arguments
|
||||
GITHUB_API_URL="${GITHUB_API_URL:-https://api.github.com/repos}"
|
||||
VERBOSE="${VERBOSE:-0}"
|
||||
INCLUDE_PRERELEASES="${INCLUDE_PRERELEASES:-0}"
|
||||
OLDEST_RELEASE="${OLDEST_RELEASE:-0}"
|
||||
BRANCH=""
|
||||
LATEST_COMMIT="${LATEST_COMMIT:-0}"
|
||||
LATEST_TAG="${LATEST_TAG:-0}"
|
||||
OUTPUT="${OUTPUT:-text}"
|
||||
SHOW_HELP=0
|
||||
REPOSITORY=""
|
||||
COMBINED=0
|
||||
|
||||
BIN=$(basename "$0")
|
||||
|
||||
# Prints a message if VERBOSE=1
|
||||
msg()
|
||||
{
|
||||
[[ "$VERBOSE" -eq 1 ]] && echo "$1"
|
||||
if [[ $VERBOSE -eq 1 ]]; then
|
||||
echo "$1" >&2
|
||||
fi
|
||||
}
|
||||
|
||||
# Show usage information
|
||||
usage()
|
||||
{
|
||||
cat << EOF
|
||||
Usage: $0 <repo> (e.g. ivuorinen/dotfiles)
|
||||
Usage: $BIN <repo> [options]
|
||||
|
||||
Fetches the latest release version, latest branch tag, or latest commit SHA from GitHub.
|
||||
|
||||
Arguments:
|
||||
<repo> Repository in format 'owner/repo' (e.g. ivuorinen/dotfiles)
|
||||
|
||||
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).
|
||||
-h, --help Show this help message and exit
|
||||
-v, --verbose Enable verbose output
|
||||
-p, --prereleases Include prerelease versions (default: only stable releases)
|
||||
-o, --oldest Fetch the oldest release instead of the latest
|
||||
-b, --branch <branch> Fetch the latest tag from a specific branch (default: main)
|
||||
-c, --commit Fetch the latest commit SHA from the specified branch
|
||||
-t, --tag Fetch the latest Git tag (any branch)
|
||||
-j, --json Return output as JSON (default: plain text)
|
||||
-a, --all Fetch all information types in a combined output
|
||||
|
||||
Environment Variables (can be used instead of command line options):
|
||||
- INCLUDE_PRERELEASES=1 Same as --prereleases
|
||||
- OLDEST_RELEASE=1 Same as --oldest
|
||||
- BRANCH=<branch> Same as --branch <branch>
|
||||
- LATEST_COMMIT=1 Same as --commit
|
||||
- LATEST_TAG=1 Same as --tag
|
||||
- OUTPUT=json Same as --json
|
||||
- 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)
|
||||
- VERBOSE=1 Same as --verbose
|
||||
|
||||
Requirements:
|
||||
- curl
|
||||
@@ -40,28 +68,34 @@ Requirements:
|
||||
|
||||
Examples:
|
||||
# Fetch the latest stable release
|
||||
$0 ivuorinen/dotfiles
|
||||
$BIN ivuorinen/dotfiles
|
||||
|
||||
# Fetch the latest release including prereleases
|
||||
INCLUDE_PRERELEASES=1 $0 ivuorinen/dotfiles
|
||||
$BIN ivuorinen/dotfiles --prereleases
|
||||
|
||||
# Fetch the oldest release
|
||||
OLDEST_RELEASE=1 $0 ivuorinen/dotfiles
|
||||
$BIN ivuorinen/dotfiles --oldest
|
||||
|
||||
# Fetch the latest tag from the 'develop' branch
|
||||
BRANCH=develop $0 ivuorinen/dotfiles
|
||||
$BIN ivuorinen/dotfiles --branch develop
|
||||
|
||||
# Fetch the latest commit SHA from 'main' branch
|
||||
LATEST_COMMIT=1 $0 ivuorinen/dotfiles
|
||||
$BIN ivuorinen/dotfiles --commit
|
||||
|
||||
# Fetch the latest Git tag (any branch)
|
||||
$BIN ivuorinen/dotfiles --tag
|
||||
|
||||
# Fetch all information types in a combined output
|
||||
$BIN ivuorinen/dotfiles --all
|
||||
|
||||
# Output result in JSON format
|
||||
OUTPUT=json $0 ivuorinen/dotfiles
|
||||
$BIN ivuorinen/dotfiles --json
|
||||
|
||||
# Use GitHub API token for higher rate limits
|
||||
GITHUB_TOKEN="your_personal_access_token" $0 ivuorinen/dotfiles
|
||||
GITHUB_TOKEN="your_personal_access_token" $BIN ivuorinen/dotfiles
|
||||
|
||||
# Use GitHub Enterprise API
|
||||
GITHUB_API_URL="https://github.example.com/api/v3/repos" $0 ivuorinen/dotfiles
|
||||
GITHUB_API_URL="https://github.example.com/api/v3/repos" $BIN ivuorinen/dotfiles
|
||||
EOF
|
||||
exit 1
|
||||
}
|
||||
@@ -77,6 +111,140 @@ check_dependencies()
|
||||
done
|
||||
}
|
||||
|
||||
# Check GitHub API rate limits and warn if they're getting low
|
||||
check_rate_limits()
|
||||
{
|
||||
local auth_status="unauthenticated"
|
||||
local auth_header=()
|
||||
|
||||
if [[ -n ${GITHUB_TOKEN:-} ]]; then
|
||||
auth_status="authenticated"
|
||||
auth_header=(-H "Authorization: token $GITHUB_TOKEN")
|
||||
fi
|
||||
|
||||
msg "Making $auth_status GitHub API requests"
|
||||
|
||||
local rate_limit_info
|
||||
rate_limit_info=$(curl -sSL "${auth_header[@]}" "https://api.github.com/rate_limit")
|
||||
|
||||
local remaining
|
||||
local reset_timestamp
|
||||
local reset_time
|
||||
|
||||
remaining=$(echo "$rate_limit_info" | jq -r '.resources.core.remaining')
|
||||
reset_timestamp=$(echo "$rate_limit_info" | jq -r '.resources.core.reset')
|
||||
|
||||
# Handle date command differences between Linux and macOS
|
||||
if date --version > /dev/null 2>&1; then
|
||||
# GNU date (Linux)
|
||||
reset_time=$(date -d "@$reset_timestamp" "+%H:%M:%S %Z" 2> /dev/null)
|
||||
else
|
||||
# BSD date (macOS)
|
||||
reset_time=$(date -r "$reset_timestamp" "+%H:%M:%S %Z" 2> /dev/null)
|
||||
fi
|
||||
|
||||
msg "Rate limit status: $remaining requests remaining, reset at $reset_time"
|
||||
|
||||
if [[ $remaining -le 5 ]]; then
|
||||
echo "Warning: GitHub API rate limit nearly reached ($remaining requests left)" >&2
|
||||
echo "Rate limits will reset at: $reset_time" >&2
|
||||
|
||||
if [[ $auth_status == "unauthenticated" ]]; then
|
||||
echo "Tip: Set GITHUB_TOKEN to increase your rate limits (60 → 5000 requests/hour)" >&2
|
||||
fi
|
||||
fi
|
||||
}
|
||||
|
||||
# Make a GitHub API request with proper error handling
|
||||
api_request()
|
||||
{
|
||||
local url="$1"
|
||||
local auth_header=()
|
||||
|
||||
if [[ -n ${GITHUB_TOKEN:-} ]]; then
|
||||
auth_header=(-H "Authorization: token $GITHUB_TOKEN")
|
||||
fi
|
||||
|
||||
local response
|
||||
local status_code
|
||||
|
||||
# Use a temporary file to capture both headers and body
|
||||
local tmp_file
|
||||
tmp_file=$(mktemp)
|
||||
|
||||
msg "Making API request to: $url"
|
||||
|
||||
status_code=$(curl -sSL -w "%{http_code}" -o "$tmp_file" "${auth_header[@]}" "$url")
|
||||
response=$(< "$tmp_file")
|
||||
rm -f "$tmp_file"
|
||||
|
||||
# Check for HTTP errors
|
||||
if [[ $status_code -ge 400 ]]; then
|
||||
local error_msg
|
||||
error_msg=$(echo "$response" | jq -r '.message // "Unknown error"')
|
||||
|
||||
if [[ $status_code -eq 403 && $error_msg == *"API rate limit exceeded"* ]]; then
|
||||
# Extract rate limit reset info
|
||||
local reset_timestamp
|
||||
reset_timestamp=$(echo "$response" | jq -r '.rate.reset // empty')
|
||||
|
||||
local reset_time
|
||||
if date --version > /dev/null 2>&1; then
|
||||
# GNU date (Linux)
|
||||
reset_time=$(date -d "@$reset_timestamp" "+%H:%M:%S %Z" 2> /dev/null \
|
||||
|| echo "unknown time")
|
||||
else
|
||||
# BSD date (macOS)
|
||||
reset_time=$(date -r "$reset_timestamp" "+%H:%M:%S %Z" 2> /dev/null \
|
||||
|| echo "unknown time")
|
||||
fi
|
||||
|
||||
echo "Error: GitHub API rate limit exceeded" >&2
|
||||
echo "Rate limit will reset at: $reset_time" >&2
|
||||
|
||||
if [[ -z ${GITHUB_TOKEN:-} ]]; then
|
||||
echo "Tip: Set GITHUB_TOKEN to increase your rate limits (60 → 5000 requests/hour)" >&2
|
||||
else
|
||||
echo "You've exceeded even authenticated rate limits (5000 requests/hour)" >&2
|
||||
fi
|
||||
|
||||
exit 3
|
||||
elif [[ $status_code -eq 404 ]]; then
|
||||
echo "Error: Repository not found or no access permission: $url" >&2
|
||||
exit 2
|
||||
else
|
||||
echo "GitHub API error ($status_code): $error_msg" >&2
|
||||
exit 1
|
||||
fi
|
||||
fi
|
||||
|
||||
echo "$response"
|
||||
}
|
||||
|
||||
# Check if repository exists before proceeding
|
||||
check_repository()
|
||||
{
|
||||
local repo="$1"
|
||||
local api_url="${GITHUB_API_URL}/${repo}"
|
||||
|
||||
msg "Checking if repository exists: $api_url"
|
||||
|
||||
local response
|
||||
response=$(api_request "$api_url")
|
||||
|
||||
# If we got here, the repository exists (otherwise api_request would have exited)
|
||||
msg "Repository found: $(echo "$response" | jq -r '.full_name')"
|
||||
|
||||
# Get default branch if no branch is specified
|
||||
if [[ -z ${BRANCH} ]]; then
|
||||
BRANCH=$(echo "$response" | jq -r '.default_branch')
|
||||
msg "Using default branch: $BRANCH"
|
||||
fi
|
||||
|
||||
# Return the repository full name (in case it differs from input due to redirects)
|
||||
echo "$response" | jq -r '.full_name'
|
||||
}
|
||||
|
||||
# Fetches the latest release or the oldest if OLDEST_RELEASE=1
|
||||
# $1 - GitHub repository (string)
|
||||
get_release_version()
|
||||
@@ -86,38 +254,55 @@ get_release_version()
|
||||
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)"
|
||||
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")
|
||||
json_response=$(api_request "$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 version=""
|
||||
local prerelease_version=""
|
||||
|
||||
local filter='.[] | select(.tag_name)'
|
||||
[[ "$include_prereleases" -eq 0 ]] && filter+='.prerelease == false'
|
||||
|
||||
local version
|
||||
if [[ "$oldest_release" -eq 1 ]]; then
|
||||
version=$(echo "$json_response" | jq -r "[${filter}] | last.tag_name // empty")
|
||||
# Get stable release version
|
||||
if [[ $oldest_release -eq 1 ]]; then
|
||||
version=$(echo "$json_response" \
|
||||
| jq -r '[.[] | select(.tag_name != null and .prerelease == false)] | sort_by(.created_at) | first.tag_name // empty')
|
||||
else
|
||||
version=$(echo "$json_response" | jq -r "[${filter}] | first.tag_name // empty")
|
||||
version=$(echo "$json_response" \
|
||||
| jq -r '[.[] | select(.tag_name != null and .prerelease == false)] | sort_by(.created_at) | reverse | first.tag_name // empty')
|
||||
fi
|
||||
|
||||
if [[ -z "$version" ]]; then
|
||||
msg "Failed to fetch release version for repository: $repo"
|
||||
# Get prerelease version if requested
|
||||
if [[ $include_prereleases -eq 1 ]]; then
|
||||
if [[ $oldest_release -eq 1 ]]; then
|
||||
prerelease_version=$(echo "$json_response" \
|
||||
| jq -r '[.[] | select(.tag_name != null and .prerelease == true)] | sort_by(.created_at) | first.tag_name // empty')
|
||||
else
|
||||
prerelease_version=$(echo "$json_response" \
|
||||
| jq -r '[.[] | select(.tag_name != null and .prerelease == true)] | sort_by(.created_at) | reverse | first.tag_name // empty')
|
||||
fi
|
||||
fi
|
||||
|
||||
# Error if no releases found and we're not in combined mode
|
||||
if [[ -z $version && -z $prerelease_version && $COMBINED -eq 0 ]]; then
|
||||
echo "No releases found for repository: $repo" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo "$version"
|
||||
# Return both values for combined output
|
||||
if [[ $COMBINED -eq 1 ]]; then
|
||||
echo "$version"
|
||||
echo "$prerelease_version"
|
||||
else
|
||||
# Return prerelease if specifically requested, otherwise stable
|
||||
if [[ $include_prereleases -eq 1 && -n $prerelease_version ]]; then
|
||||
msg "Found prerelease version: $prerelease_version"
|
||||
echo "$prerelease_version"
|
||||
else
|
||||
msg "Found stable release version: $version"
|
||||
echo "$version"
|
||||
fi
|
||||
fi
|
||||
}
|
||||
|
||||
# Fetches the latest tag from the specified branch
|
||||
@@ -130,16 +315,42 @@ get_latest_branch_tag()
|
||||
msg "Fetching latest tag for branch '$branch' from: $api_url"
|
||||
|
||||
local json_response
|
||||
json_response=$(curl -sSL "$api_url")
|
||||
json_response=$(api_request "$api_url")
|
||||
|
||||
local version
|
||||
version=$(echo "$json_response" | jq -r "[.[] | select(.ref | contains(\"refs/tags/$branch\"))] | last.ref | sub(\"refs/tags/\"; \"\") // empty")
|
||||
version=$(echo "$json_response" \
|
||||
| jq -r "[.[] | select(.ref | contains(\"refs/tags/$branch\"))] | sort_by(.ref) | reverse | first.ref | sub(\"refs/tags/\"; \"\") // empty")
|
||||
|
||||
if [[ -z "$version" ]]; then
|
||||
msg "Failed to fetch latest tag for branch: $branch"
|
||||
if [[ -z $version && $COMBINED -eq 0 ]]; then
|
||||
echo "No tags found for branch: $branch in repository: $repo" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
msg "Found branch tag: $version"
|
||||
echo "$version"
|
||||
}
|
||||
|
||||
# Fetches the latest Git tag (regardless of branch)
|
||||
get_latest_git_tag()
|
||||
{
|
||||
local repo="$1"
|
||||
local api_url="${GITHUB_API_URL}/${repo}/git/refs/tags"
|
||||
|
||||
msg "Fetching latest Git tag from: $api_url"
|
||||
|
||||
local json_response
|
||||
json_response=$(api_request "$api_url")
|
||||
|
||||
local version
|
||||
version=$(echo "$json_response" \
|
||||
| jq -r '[.[] | select(.ref | startswith("refs/tags/"))] | sort_by(.ref) | reverse | first.ref | sub("refs/tags/"; "") // empty')
|
||||
|
||||
if [[ -z $version && $COMBINED -eq 0 ]]; then
|
||||
echo "No Git tags found in repository: $repo" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
msg "Found Git tag: $version"
|
||||
echo "$version"
|
||||
}
|
||||
|
||||
@@ -153,42 +364,240 @@ get_latest_commit()
|
||||
msg "Fetching latest commit SHA from: $api_url"
|
||||
|
||||
local json_response
|
||||
json_response=$(curl -sSL "$api_url")
|
||||
json_response=$(api_request "$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"
|
||||
if [[ -z $sha && $COMBINED -eq 0 ]]; then
|
||||
echo "Failed to fetch latest commit SHA for branch: $branch in repository: $repo" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
msg "Found commit SHA: $sha"
|
||||
echo "$sha"
|
||||
}
|
||||
|
||||
# Format combined text output
|
||||
format_combined_text()
|
||||
{
|
||||
local repo="$1"
|
||||
local branch="$2"
|
||||
local tag="$3"
|
||||
local commit="$4"
|
||||
local release="$5"
|
||||
local prerelease="$6"
|
||||
|
||||
echo "Repository: $repo"
|
||||
|
||||
if [[ -n $branch ]]; then
|
||||
echo "Branch: $branch"
|
||||
fi
|
||||
|
||||
if [[ -n $tag ]]; then
|
||||
echo "Git Tag: $tag"
|
||||
fi
|
||||
|
||||
if [[ -n $commit ]]; then
|
||||
echo "Commit: $commit"
|
||||
fi
|
||||
|
||||
if [[ -n $prerelease ]]; then
|
||||
echo "Prerelease: $prerelease"
|
||||
fi
|
||||
|
||||
if [[ -n $release ]]; then
|
||||
echo "Release: $release"
|
||||
fi
|
||||
}
|
||||
|
||||
# Format combined JSON output
|
||||
format_combined_json()
|
||||
{
|
||||
local repo="$1"
|
||||
local branch="$2"
|
||||
local tag="$3"
|
||||
local commit="$4"
|
||||
local release="$5"
|
||||
local prerelease="$6"
|
||||
|
||||
local json="{"
|
||||
json+="\"repository\":\"$repo\""
|
||||
|
||||
if [[ -n $branch ]]; then
|
||||
json+=",\"branch\":\"$branch\""
|
||||
fi
|
||||
|
||||
if [[ -n $tag ]]; then
|
||||
json+=",\"tag\":\"$tag\""
|
||||
fi
|
||||
|
||||
if [[ -n $commit ]]; then
|
||||
json+=",\"commit\":\"$commit\""
|
||||
fi
|
||||
|
||||
if [[ -n $prerelease ]]; then
|
||||
json+=",\"prerelease\":\"$prerelease\""
|
||||
fi
|
||||
|
||||
if [[ -n $release ]]; then
|
||||
json+=",\"release\":\"$release\""
|
||||
fi
|
||||
|
||||
json+="}"
|
||||
|
||||
echo "$json"
|
||||
}
|
||||
|
||||
# Parse command line arguments
|
||||
parse_arguments()
|
||||
{
|
||||
# If no arguments provided, show usage
|
||||
if [[ $# -eq 0 ]]; then
|
||||
usage
|
||||
fi
|
||||
|
||||
# Parse arguments
|
||||
while [[ $# -gt 0 ]]; do
|
||||
case "$1" in
|
||||
-h | --help)
|
||||
SHOW_HELP=1
|
||||
shift
|
||||
;;
|
||||
-v | --verbose)
|
||||
VERBOSE=1
|
||||
shift
|
||||
;;
|
||||
-p | --prereleases)
|
||||
INCLUDE_PRERELEASES=1
|
||||
shift
|
||||
;;
|
||||
-o | --oldest)
|
||||
OLDEST_RELEASE=1
|
||||
shift
|
||||
;;
|
||||
-b | --branch)
|
||||
if [[ $# -lt 2 ]]; then
|
||||
echo "Error: --branch option requires a branch name" >&2
|
||||
exit 1
|
||||
fi
|
||||
BRANCH="$2"
|
||||
shift 2
|
||||
;;
|
||||
-c | --commit)
|
||||
LATEST_COMMIT=1
|
||||
shift
|
||||
;;
|
||||
-t | --tag)
|
||||
LATEST_TAG=1
|
||||
shift
|
||||
;;
|
||||
-j | --json)
|
||||
OUTPUT="json"
|
||||
shift
|
||||
;;
|
||||
-a | --all)
|
||||
COMBINED=1
|
||||
shift
|
||||
;;
|
||||
-*)
|
||||
echo "Error: Unknown option: $1" >&2
|
||||
usage
|
||||
;;
|
||||
*)
|
||||
# If repository is already set, this is an error
|
||||
if [[ -n $REPOSITORY ]]; then
|
||||
echo "Error: Unexpected argument: $1" >&2
|
||||
usage
|
||||
fi
|
||||
REPOSITORY="$1"
|
||||
shift
|
||||
;;
|
||||
esac
|
||||
done
|
||||
|
||||
# Validate that we have a repository
|
||||
if [[ -z $REPOSITORY && $SHOW_HELP -eq 0 ]]; then
|
||||
echo "Error: Repository argument is required" >&2
|
||||
usage
|
||||
fi
|
||||
}
|
||||
|
||||
# Main function
|
||||
# $1 - GitHub repository (string)
|
||||
main()
|
||||
{
|
||||
if [[ $# -ne 1 ]]; then
|
||||
# Parse command line arguments
|
||||
parse_arguments "$@"
|
||||
|
||||
# Show help if requested
|
||||
if [[ $SHOW_HELP -eq 1 ]]; then
|
||||
usage
|
||||
fi
|
||||
|
||||
check_dependencies
|
||||
|
||||
local repo="$1"
|
||||
local result
|
||||
# Check rate limits before making other API calls
|
||||
check_rate_limits
|
||||
|
||||
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")
|
||||
# Validate repository existence and get normalized repository name
|
||||
local repo_fullname
|
||||
repo_fullname=$(check_repository "$REPOSITORY")
|
||||
|
||||
# If --all specified, get all information types
|
||||
if [[ $COMBINED -eq 1 ]]; then
|
||||
local branch="${BRANCH:-main}"
|
||||
local git_tag=""
|
||||
local commit_sha=""
|
||||
local release_version=""
|
||||
local prerelease_version=""
|
||||
|
||||
# Get Git tag if requested
|
||||
git_tag=$(get_latest_git_tag "$repo_fullname")
|
||||
|
||||
# Get commit SHA
|
||||
commit_sha=$(get_latest_commit "$repo_fullname")
|
||||
|
||||
# Get release versions (stable and prerelease)
|
||||
read -r release_version prerelease_version < <(get_release_version "$repo_fullname")
|
||||
|
||||
# Format output based on selected format
|
||||
if [[ $OUTPUT == "json" ]]; then
|
||||
format_combined_json \
|
||||
"$repo_fullname" \
|
||||
"$branch" \
|
||||
"$git_tag" \
|
||||
"$commit_sha" \
|
||||
"$release_version" \
|
||||
"$prerelease_version"
|
||||
else
|
||||
format_combined_text \
|
||||
"$repo_fullname" \
|
||||
"$branch" \
|
||||
"$git_tag" \
|
||||
"$commit_sha" \
|
||||
"$release_version" \
|
||||
"$prerelease_version"
|
||||
fi
|
||||
|
||||
exit 0
|
||||
fi
|
||||
|
||||
if [[ "${OUTPUT:-text}" == "json" ]]; then
|
||||
echo "{\"repository\": \"$repo\", \"result\": \"$result\"}"
|
||||
# Not combined mode - get only the requested information type
|
||||
local result=""
|
||||
|
||||
if [[ $LATEST_COMMIT -eq 1 ]]; then
|
||||
result=$(get_latest_commit "$repo_fullname")
|
||||
elif [[ $LATEST_TAG -eq 1 ]]; then
|
||||
result=$(get_latest_git_tag "$repo_fullname")
|
||||
elif [[ -n $BRANCH ]]; then
|
||||
result=$(get_latest_branch_tag "$repo_fullname")
|
||||
else
|
||||
result=$(get_release_version "$repo_fullname")
|
||||
fi
|
||||
|
||||
# Output the result in the requested format
|
||||
if [[ $OUTPUT == "json" ]]; then
|
||||
echo "{\"repository\": \"$repo_fullname\", \"result\": \"$result\"}"
|
||||
else
|
||||
echo "$result"
|
||||
fi
|
||||
|
||||
196
local/bin/x-gh-get-latest-version.md
Normal file
196
local/bin/x-gh-get-latest-version.md
Normal file
@@ -0,0 +1,196 @@
|
||||
# GitHub Latest Version Fetcher
|
||||
|
||||
`x-gh-get-latest-version` is a versatile command-line tool for fetching the
|
||||
latest version information from GitHub repositories. It can retrieve release
|
||||
versions, Git tags, branch tags, and commit SHAs with simple commands.
|
||||
|
||||
## Features
|
||||
|
||||
- Fetch latest or oldest stable releases
|
||||
- Include prerelease versions
|
||||
- Get latest Git tags from any branch
|
||||
- Fetch latest commit SHA from a specific branch
|
||||
- Output in plain text or JSON format
|
||||
- Combined output mode to get all information at once
|
||||
- Rate limit checking to avoid GitHub API throttling
|
||||
- Authenticated requests with GitHub token support
|
||||
|
||||
## Requirements
|
||||
|
||||
- `curl` for making HTTP requests
|
||||
- `jq` for processing JSON responses
|
||||
- A GitHub personal access token
|
||||
(optional, but recommended to avoid rate limiting)
|
||||
|
||||
## Installation
|
||||
|
||||
1. Save the script to a location in your PATH
|
||||
2. Make it executable: `chmod +x x-gh-get-latest-version`
|
||||
3. Optionally set up a GitHub token as an environment variable:
|
||||
|
||||
```bash
|
||||
export GITHUB_TOKEN="your_personal_access_token"
|
||||
```
|
||||
|
||||
## Usage
|
||||
|
||||
```text
|
||||
Usage: x-gh-get-latest-version <repo> [options]
|
||||
|
||||
Arguments:
|
||||
<repo> Repository in format 'owner/repo' (e.g. ivuorinen/dotfiles)
|
||||
|
||||
Options:
|
||||
-h, --help Show this help message and exit
|
||||
-v, --verbose Enable verbose output
|
||||
-p, --prereleases Include prerelease versions (default: only stable releases)
|
||||
-o, --oldest Fetch the oldest release instead of the latest
|
||||
-b, --branch <branch> Fetch the latest tag from a specific branch (default: main)
|
||||
-c, --commit Fetch the latest commit SHA from the specified branch
|
||||
-t, --tag Fetch the latest Git tag (any branch)
|
||||
-j, --json Return output as JSON (default: plain text)
|
||||
-a, --all Fetch all information types in a combined output
|
||||
```
|
||||
|
||||
## Examples
|
||||
|
||||
### Fetch the Latest Release Version
|
||||
|
||||
```bash
|
||||
x-gh-get-latest-version ivuorinen/dotfiles
|
||||
```
|
||||
|
||||
Output: `v1.2.3`
|
||||
|
||||
### Include Prereleases
|
||||
|
||||
```bash
|
||||
x-gh-get-latest-version ivuorinen/dotfiles --prereleases
|
||||
```
|
||||
|
||||
Output: `v1.3.0-rc.1`
|
||||
|
||||
### Get the Oldest Release
|
||||
|
||||
```bash
|
||||
x-gh-get-latest-version ivuorinen/dotfiles --oldest
|
||||
```
|
||||
|
||||
Output: `v0.1.0`
|
||||
|
||||
### Fetch from a Specific Branch
|
||||
|
||||
```bash
|
||||
x-gh-get-latest-version ivuorinen/dotfiles --branch develop
|
||||
```
|
||||
|
||||
Output: `develop-v1.3.0`
|
||||
|
||||
### Get Latest Commit SHA
|
||||
|
||||
```bash
|
||||
x-gh-get-latest-version ivuorinen/dotfiles --commit
|
||||
```
|
||||
|
||||
Output: `a1b2c3d4e5f6g7h8i9j0k1l2m3n4o5p6q7r8s9t0`
|
||||
|
||||
### Fetch Latest Git Tag
|
||||
|
||||
```bash
|
||||
x-gh-get-latest-version ivuorinen/dotfiles --tag
|
||||
```
|
||||
|
||||
Output: `v2.0.0-beta.1`
|
||||
|
||||
### Output as JSON
|
||||
|
||||
```bash
|
||||
x-gh-get-latest-version ivuorinen/dotfiles --json
|
||||
```
|
||||
|
||||
Output: `{"repository": "ivuorinen/dotfiles", "result": "v1.2.3"}`
|
||||
|
||||
### Combined Information Output
|
||||
|
||||
```bash
|
||||
x-gh-get-latest-version ivuorinen/dotfiles --all
|
||||
```
|
||||
|
||||
Output:
|
||||
|
||||
```text
|
||||
Repository: ivuorinen/dotfiles
|
||||
Branch: main
|
||||
Git Tag: v2.0.0-beta.1
|
||||
Commit: a1b2c3d4e5f6g7h8i9j0k1l2m3n4o5p6q7r8s9t0
|
||||
Prerelease: v1.3.0-rc.1
|
||||
Release: v1.2.3
|
||||
```
|
||||
|
||||
### Combined Output as JSON
|
||||
|
||||
```bash
|
||||
x-gh-get-latest-version ivuorinen/dotfiles --all --json
|
||||
```
|
||||
|
||||
Output:
|
||||
|
||||
```json
|
||||
{
|
||||
"repository": "ivuorinen/dotfiles",
|
||||
"branch": "main",
|
||||
"tag": "v2.0.0-beta.1",
|
||||
"commit": "a1b2c3d4e5f6g7h8i9j0k1l2m3n4o5p6q7r8s9t0",
|
||||
"prerelease": "v1.3.0-rc.1",
|
||||
"release": "v1.2.3"
|
||||
}
|
||||
```
|
||||
|
||||
## Environment Variables
|
||||
|
||||
You can use environment variables instead of command-line options:
|
||||
|
||||
- `INCLUDE_PRERELEASES=1` - Include prerelease versions
|
||||
- `OLDEST_RELEASE=1` - Fetch the oldest release instead of the latest
|
||||
- `BRANCH=branch_name` - Specify a branch to fetch tags from
|
||||
- `LATEST_COMMIT=1` - Fetch latest commit SHA
|
||||
- `LATEST_TAG=1` - Fetch latest Git tag
|
||||
- `OUTPUT=json` - Output results as JSON
|
||||
- `GITHUB_API_URL=url` - Override GitHub API URL (useful for GitHub Enterprise)
|
||||
- `GITHUB_TOKEN=token` - Use GitHub API token to increase rate limits
|
||||
- `VERBOSE=1` - Enable verbose output
|
||||
|
||||
## GitHub API Rate Limits
|
||||
|
||||
GitHub enforces rate limits on API requests:
|
||||
|
||||
- Unauthenticated requests: 60 requests per hour
|
||||
- Authenticated requests: 5,000 requests per hour
|
||||
|
||||
For frequent use, it's strongly recommended to set up a GitHub token:
|
||||
|
||||
```bash
|
||||
export GITHUB_TOKEN="your_personal_access_token"
|
||||
```
|
||||
|
||||
The script will automatically warn you when you're approaching your rate limit
|
||||
and suggest using a token if you haven't already.
|
||||
|
||||
## Error Handling
|
||||
|
||||
The script provides informative error messages for common issues:
|
||||
|
||||
- Repository not found
|
||||
- Rate limit exceeded
|
||||
- No releases/tags found
|
||||
- Invalid arguments
|
||||
|
||||
## Author
|
||||
|
||||
Ismo Vuorinen (<https://github.com/ivuorinen>)
|
||||
|
||||
## License
|
||||
|
||||
MIT
|
||||
|
||||
<!-- vim: set ft=markdown spell spelllang=en_us cc=80 : -->
|
||||
BIN
local/bin/yabai
BIN
local/bin/yabai
Binary file not shown.
1313
local/man/yabai.1
1313
local/man/yabai.1
File diff suppressed because it is too large
Load Diff
@@ -11,8 +11,8 @@ msgr run "Installing go packages"
|
||||
|
||||
! x-have "go" && msgr err "go hasn't been installed yet." && exit 0
|
||||
|
||||
[[ -z "$ASDF_GOLANG_DEFAULT_PACKAGES_FILE" ]] && \
|
||||
ASDF_GOLANG_DEFAULT_PACKAGES_FILE="$DOTFILES/config/asdf/golang-packages"
|
||||
[[ -z "$ASDF_GOLANG_DEFAULT_PACKAGES_FILE" ]] \
|
||||
&& ASDF_GOLANG_DEFAULT_PACKAGES_FILE="$DOTFILES/config/asdf/golang-packages"
|
||||
|
||||
# Packages are defined in $DOTFILES/config/asdf/golang-packages, one per line
|
||||
# Skip comments and empty lines
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
column_width = 120
|
||||
column_width = 90
|
||||
line_endings = "Unix"
|
||||
indent_type = "Spaces"
|
||||
indent_width = 2
|
||||
|
||||
@@ -6947,9 +6947,9 @@ http-proxy-agent@^7.0.0:
|
||||
debug "^4.3.4"
|
||||
|
||||
http-proxy-middleware@^2.0.3:
|
||||
version "2.0.7"
|
||||
resolved "https://registry.yarnpkg.com/http-proxy-middleware/-/http-proxy-middleware-2.0.7.tgz#915f236d92ae98ef48278a95dedf17e991936ec6"
|
||||
integrity sha512-fgVY8AV7qU7z/MmXJ/rxwbrtQH4jBQ9m7kp3llF0liB7glmFeVZFBepQb32T3y8n8k2+AEYuMPCpinYW+/CuRA==
|
||||
version "2.0.9"
|
||||
resolved "https://registry.yarnpkg.com/http-proxy-middleware/-/http-proxy-middleware-2.0.9.tgz#e9e63d68afaa4eee3d147f39149ab84c0c2815ef"
|
||||
integrity sha512-c1IyJYLYppU574+YI7R4QyX2ystMtVXZwIdzazUIPIJsHuWNd+mho2j+bKoHftndicGj9yh+xjd+l0yj7VeT1Q==
|
||||
dependencies:
|
||||
"@types/http-proxy" "^1.17.8"
|
||||
http-proxy "^1.18.1"
|
||||
|
||||
Reference in New Issue
Block a user