├── .asdfrc ├── .editorconfig ├── .eslintignore ├── .eslintrc.js ├── .genaiscript ├── .gitattributes └── .gitignore ├── .gitconfig ├── .gitconfig-no_push ├── .github ├── ISSUE_TEMPLATE │ ├── bug_report.yml │ ├── config.yml │ └── feature_request.yml ├── PULL_REQUEST_TEMPLATE.md ├── config │ ├── labeller.yml │ └── labels.yml ├── release-drafter.yml ├── renovate.json └── workflows │ ├── auto-approve.yml │ ├── codeball.yml │ ├── codeql.yml │ ├── delete-disabled-workflows.yml │ ├── detect-secrets-generate-baseline.yml │ ├── detect-secrets.yml │ ├── label-sync.yml │ ├── lint-codeowners.yml │ ├── lint-docker.yml │ ├── lint-pr-actions-skip.yml │ ├── lint-pr-actions.yml │ ├── lint-pr-markdown.yml │ ├── lint-shell.yml │ ├── lint-tf.yml │ ├── mirror.yml │ ├── pr-labeller.yml │ └── pre-commit.yml ├── .gitignore ├── .gitignoreglobal ├── .pre-commit-config.yaml ├── .prettierignore ├── .prettierrc.js ├── .secrets.baseline ├── .vimrc ├── .whitesource ├── 0-paths.rc ├── 1-zgen.rc ├── 10-prompt.rc ├── 14-source-files.rc ├── 15-events.rc ├── 16-fabric.rc ├── 3-location_specifics.rc ├── 4-aliases.rc ├── 5-exports.rc ├── 6-zsh_options.rc ├── 7-history.rc ├── 9-functions.rc ├── CODEOWNERS ├── LICENSE ├── NOTES.md ├── README.md ├── bat-config ├── bootstrap_shell.sh ├── commitlint.config.js ├── dircolors ├── githooks └── pre-push ├── htoprc ├── renovate.json ├── rsyncd.conf ├── run_tests.sh ├── tmux.conf └── zshrc /.asdfrc: -------------------------------------------------------------------------------- 1 | legacy_version_file = yes 2 | -------------------------------------------------------------------------------- /.editorconfig: -------------------------------------------------------------------------------- 1 | #### THIS FILE IS MANAGED BY AN AUTOMATED WORKFLOW #### 2 | 3 | # EditorConfig https://EditorConfig.org 4 | 5 | # top-most EditorConfig file 6 | root = true 7 | 8 | # Unix-style newlines with a newline ending every file 9 | [*] 10 | end_of_line = lf 11 | insert_final_newline = true 12 | trim_trailing_whitespace = true 13 | charset = utf-8 14 | 15 | # Ensure we're standardising on 2 space soft-tabs for most files 16 | [*.md, *.markdown, *.yml, *.yaml, *.json, *.js, *.ts, *.tsx, *.sh] 17 | indent_style = space 18 | indent_size = 2 19 | 20 | # Makefile specific 21 | [Makefile] 22 | indent_style = tab 23 | indent_size = 4 24 | 25 | # Python specific 26 | [*.py, *.pyi] 27 | indent_style = space 28 | indent_size = 4 29 | -------------------------------------------------------------------------------- /.eslintignore: -------------------------------------------------------------------------------- 1 | #### THIS FILE IS MANAGED BY AN AUTOMATED WORKFLOW #### 2 | 3 | .ide 4 | .idea 5 | .vscode 6 | **/__pycache__ 7 | **/__pypackages__ 8 | **/.bin 9 | **/.DS_Store 10 | **/.env.* 11 | **/.git 12 | **/.out 13 | **/.venv 14 | **/*.log 15 | **/*.tmp 16 | **/build 17 | **/cdk.out 18 | **/coverage 19 | **/dist 20 | **/global.setup.ts 21 | **/htmlcov 22 | **/logs 23 | **/node_modules 24 | **/public 25 | **/temp 26 | **/tmp 27 | **/venv 28 | 29 | # Obsidian 30 | .obsidian 31 | -------------------------------------------------------------------------------- /.eslintrc.js: -------------------------------------------------------------------------------- 1 | // THIS FILE IS MANAGED BY AN AUTOMATED WORKFLOW 2 | 3 | // Required packages: 4 | // 'eslint-config-prettier' 5 | // 'eslint-plugin-deprecation' 6 | // 'eslint-plugin-import' 7 | // 'eslint-plugin-jest' 8 | // 'eslint-plugin-unused-imports' 9 | // 'eslint' 10 | // 'prettier-plugin-packagejson' 11 | // 'prettier' 12 | 13 | module.exports = { 14 | env: { 15 | browser: true, 16 | commonjs: true, 17 | es2021: true, 18 | jest: true, 19 | }, 20 | parserOptions: { 21 | ecmaVersion: 'latest', 22 | sourceType: 'module', 23 | }, 24 | plugins: ['import', 'prettier'], 25 | extends: ['plugin:prettier/recommended', 'eslint:recommended'], 26 | root: true, 27 | rules: { 28 | quotes: ['error', 'single', { avoidEscape: true }], 29 | 'comma-dangle': ['error', 'always-multiline'], 30 | 'comma-spacing': ['error', { before: false, after: true }], 31 | 'no-multi-spaces': ['error', { ignoreEOLComments: false }], 32 | 'array-bracket-newline': ['error', 'consistent'], 33 | 'object-curly-spacing': ['error', 'always'], 34 | 'array-bracket-spacing': ['error', 'never'], 35 | 'object-curly-newline': ['error', { multiline: true, consistent: true }], 36 | 'object-property-newline': ['error', { allowAllPropertiesOnSameLine: true }], 37 | 'keyword-spacing': ['error'], 38 | 'brace-style': ['error', '1tbs', { allowSingleLine: true }], 39 | 'space-before-blocks': 'error', 40 | curly: ['error', 'multi-line', 'consistent'], 41 | 'no-bitwise': ['error'], 42 | 'no-console': 0, 43 | 'no-trailing-spaces': ['error'], 44 | 'no-duplicate-imports': ['error'], 45 | 'no-shadow': 'off', 46 | 'no-use-before-define': 'off', 47 | 'import/order': 'error', 48 | 'prettier/prettier': 'error', 49 | 'max-classes-per-file': ['error', 3], 50 | 'no-underscore-dangle': 'off', 51 | 'lines-between-class-members': ['error', 'always', { exceptAfterSingleLine: true }], 52 | }, 53 | ignorePatterns: [ 54 | '!**/*.eslintrc.js*', 55 | '!**/*.prettierrc.js*', 56 | '**/node_modules/**', 57 | '**/dist/**', 58 | '**/build/**', 59 | '**/coverage/**', 60 | '**/cdk.out/**', 61 | 'jest.setup.ts', 62 | ], 63 | }; 64 | -------------------------------------------------------------------------------- /.genaiscript/.gitattributes: -------------------------------------------------------------------------------- 1 | # avoid merge issues and ignore files in diffs 2 | *.json -diff merge=ours linguist-generated 3 | *.jsonl -diff merge=ours linguist-generated 4 | *.js -diff merge=ours linguist-generated 5 | -------------------------------------------------------------------------------- /.genaiscript/.gitignore: -------------------------------------------------------------------------------- 1 | runs/ 2 | cache/ 3 | retrieval/ 4 | containers/ 5 | temp/ 6 | tests/ 7 | stats/ 8 | *.csv 9 | -------------------------------------------------------------------------------- /.gitconfig: -------------------------------------------------------------------------------- 1 | [core] 2 | excludesfile = ~/.gitignoreglobal 3 | ignorecase = true 4 | 5 | [credential] 6 | helper = store 7 | 8 | [include] 9 | path = ~/.gitconfig.private 10 | 11 | #[url "git@github.com:"] 12 | # insteadOf = https://github.com/ 13 | 14 | ## Behaviour 15 | [init] 16 | defaultBranch = main 17 | [push] 18 | default = current 19 | autoSetupRemote = true 20 | followtags = true 21 | [pull] 22 | rebase = true 23 | [rebase] 24 | autosquash = true 25 | [branch] 26 | autoSetupMerge = true 27 | sort = -committerdate 28 | [mergetool] 29 | prompt = false 30 | [filter "lfs"] 31 | required = true 32 | clean = git-lfs clean -- %f 33 | smudge = git-lfs smudge -- %f 34 | process = git-lfs filter-process 35 | [tar "tar.xz"] 36 | command = xz -c 37 | 38 | ### DIFF TOOLING ### 39 | [core] 40 | pager = delta #--features=interactive #,diff-so-fancy,decorations 41 | #page = diff-so-fancy | less --tabs=2 -RFX 42 | [merge] 43 | conflictstyle = zdiff3 44 | tool = delta 45 | 46 | [diff] 47 | colorMoved = default 48 | submodule = log 49 | algorithm = histogram 50 | tool = delta 51 | # external = delta 52 | prompt = false 53 | 54 | [delta] 55 | side-by-side = true 56 | navigate = true 57 | features = decorations unobtrusive-line-numbers diff-so-fancy dark 58 | syntax-theme = Dracula 59 | tabs = 4 60 | true-color = always 61 | hyperlinks = true 62 | hyperlinks-file-link-format = "vscode://file/{path}:{line}" 63 | # or: hyperlinks-file-link-format = "idea://open?file={path}&line={line}" 64 | # or: hyperlinks-file-link-format = "pycharm://open?file={path}&line={line}" 65 | [delta "interactive"] 66 | diffFilter = delta --color-only --dark --features=interactive,unobtrusive-line-numbers,diff-so-fancy 67 | keep-plus-minus-markers = false 68 | [delta "decorations"] 69 | commit-decoration-style = bold yellow box ul 70 | file-style = bold yellow ul 71 | file-decoration-style = none 72 | hunk-header-decoration-style = yellow box 73 | commit-decoration-style = blue ol 74 | # commit-style = raw 75 | # file-style = omit 76 | # hunk-header-decoration-style = blue box 77 | hunk-header-file-style = red 78 | # hunk-header-line-number-style = "#067a00" 79 | hunk-header-style = file line-number syntax 80 | [delta "unobtrusive-line-numbers"] 81 | line-numbers = true 82 | line-numbers-minus-style = "#444444" 83 | line-numbers-zero-style = "#444444" 84 | line-numbers-plus-style = "#444444" 85 | line-numbers-left-format = "{nm:>4}┊" 86 | line-numbers-right-format = "{np:>4}│" 87 | line-numbers-left-style = blue 88 | line-numbers-right-style = blue 89 | 90 | 91 | # Diff-so-fancy diff-tool 92 | [interactive] 93 | diffFilter = delta --diff-so-fancy # diff-so-fancy --patch 94 | [diff-so-fancy] 95 | changeHunkIndicators = true 96 | ### END DIFF ### 97 | 98 | [safe] 99 | directory = /github/workspace 100 | [status] 101 | submodulesummary = 1 102 | [rerere] # Reuse Recorded Resolution 103 | enable = true 104 | enabled = true 105 | autoUpdate = true 106 | [help] 107 | autocorrect = 1 108 | [fetch] 109 | prunetags = true 110 | [log] 111 | date = iso 112 | 113 | # Alases 114 | [alias] 115 | init-safe-commit = !~/.safe-commit-hook/install-for-project.sh 116 | quick-stats = ! /usr/local/bin/git-quick-stats 117 | prune = fetch --prune 118 | undo = reset --soft HEAD^ 119 | glog = log --graph --pretty=format:'%Cred%h%Creset -%C(yellow)%d%Creset %s %Cgreen(%cr) %C(bold blue)<%an>%Creset' 120 | logline = log --graph --pretty=format:'%Cred%h%Creset -%C(yellow)%d%Creset %s %Cgreen(%cr) %C(bold blue)<%an>%Creset' --abbrev-commit 121 | tree = log --graph --decorate --pretty=oneline --abbrev-commit 122 | squash-all = "!f(){ git reset $(git commit-tree HEAD^{tree} -m \"${1:-A new start}\");};f" 123 | #squash-all = "!f(){ git reset $(git commit-tree HEAD^{tree} -m \"${1:-Make Actions Great Again}\");};f" 124 | scrub = reset --hard @{upstream} 125 | recentb = "!r() { refbranch=$1 count=$2; git for-each-ref --sort=-committerdate refs/heads --format='%(refname:short)|%(HEAD)%(color:yellow)%(refname:short)|%(color:bold green)%(committerdate:relative)|%(color:blue)%(subject)|%(color:magenta)%(authorname)%(color:reset)' --color=always --count=${count:-20} | while read line; do branch=$(echo \"$line\" | awk 'BEGIN { FS = \"|\" }; { print $1 }' | tr -d '*'); ahead=$(git rev-list --count \"${refbranch:-origin/master}..${branch}\"); behind=$(git rev-list --count \"${branch}..${refbranch:-origin/master}\"); colorline=$(echo \"$line\" | sed 's/^[^|]*|//'); echo \"$ahead|$behind|$colorline\" | awk -F'|' -vOFS='|' '{$5=substr($5,1,70)}1' ; done | ( echo \"ahead|behind||branch|lastcommit|message|author\\n\" && cat) | column -ts'|';}; r" 126 | runs = "!f() { \ 127 | watch_gha_runs \ 128 | \"$(git remote get-url origin)\" \ 129 | \"$(git rev-parse --abbrev-ref HEAD)\"; \ 130 | }; f" 131 | 132 | # ********************* 133 | # Rebase workflow 134 | mainbranch = "!git remote show origin | sed -n '/HEAD branch/s/.*: //p'" 135 | synced = "!git pull origin $(git mainbranch) --rebase" 136 | update = "!git pull origin $(git rev-parse --abbrev-ref HEAD) --rebase" 137 | squash = "!git rebase -v -i $(git mainbranch)" 138 | publish = push origin HEAD --force-with-lease 139 | pub = publish 140 | ammend = commit --amend 141 | amend = commit --amend 142 | fpush = push 143 | # ********************* 144 | 145 | 146 | # [maintenance] 147 | # repo = /path/to/example/repo 148 | -------------------------------------------------------------------------------- /.gitconfig-no_push: -------------------------------------------------------------------------------- 1 | # Prevents accidental pushing to branches 2 | 3 | [branch "master"] 4 | pushRemote = no_push 5 | [branch "main"] 6 | # pushRemote = no_push 7 | 8 | # this can be undone for a specific directory by running: 9 | # git config --worktree branch.main.pushRemote origin 10 | # git config --worktree branch.master.pushRemote origin 11 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/bug_report.yml: -------------------------------------------------------------------------------- 1 | #### THIS FILE IS MANAGED BY AN AUTOMATED WORKFLOW #### 2 | 3 | name: 🐛 Bug report 4 | description: Create a bug report to help us improve 5 | labels: ["bug"] 6 | body: 7 | - type: textarea 8 | id: description 9 | attributes: 10 | label: 🐞 Describe the bug 11 | description: | 12 | A brief description of the bug. 13 | validations: 14 | required: true 15 | 16 | - type: textarea 17 | id: reproduce 18 | attributes: 19 | label: 📚 To reproduce 20 | description: | 21 | Steps to reproduce the behaviour. 22 | validations: 23 | required: false 24 | 25 | - type: textarea 26 | id: expected 27 | attributes: 28 | label: 💡 Expected behaviour 29 | description: | 30 | A description of what you expected to happen. 31 | validations: 32 | required: false 33 | 34 | - type: textarea 35 | id: suggestion 36 | attributes: 37 | label: 🤔 Suggestion 38 | description: | 39 | Any suggestions on how to fix the bug? 40 | validations: 41 | required: false 42 | 43 | 44 | - type: textarea 45 | id: screenshots 46 | attributes: 47 | label: 🖼️ Screenshots 48 | description: | 49 | If applicable, add screenshots to help explain your problem. 50 | validations: 51 | required: false 52 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/config.yml: -------------------------------------------------------------------------------- 1 | #### THIS FILE IS MANAGED BY AN AUTOMATED WORKFLOW #### 2 | 3 | blank_issues_enabled: false 4 | # contact_links: 5 | # - name: 📚 Docs 6 | # url: https://github.com/sammcj/${{ github.repository }}#-usage 7 | # about: Checkout ${{ github.repository }}'s documentation. 8 | # - name: 🚀 Feature Request 9 | # url: https://github.com/sammcj/${{ github.repository }}/discussions/new?category=ideas 10 | # about: Share ideas for new features 11 | # - name: ❓ Ask a Question 12 | # url: https://github.com/sammcj/${{ github.repository }}/discussions/new?category=q-a 13 | # about: Ask the community for help 14 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/feature_request.yml: -------------------------------------------------------------------------------- 1 | #### THIS FILE IS MANAGED BY AN AUTOMATED WORKFLOW #### 2 | 3 | name: "💡 Feature Request" 4 | description: Create a new ticket for a new feature request 5 | title: "💡 [REQUEST] - " 6 | labels: ["question"] 7 | 8 | body: 9 | - type: textarea 10 | id: related_issues 11 | attributes: 12 | label: "Related Issues" 13 | description: Are there any related issues? 14 | validations: 15 | required: false 16 | 17 | - type: textarea 18 | id: summary 19 | attributes: 20 | label: "Summary" 21 | description: Provide a brief explanation of the feature 22 | placeholder: Describe in a few lines your feature request 23 | validations: 24 | required: true 25 | 26 | - type: textarea 27 | id: example 28 | attributes: 29 | label: "Example" 30 | description: Indicate here some basic examples of your feature. 31 | validations: 32 | required: false 33 | -------------------------------------------------------------------------------- /.github/PULL_REQUEST_TEMPLATE.md: -------------------------------------------------------------------------------- 1 | <!-- 2 | Please include a summary of the change and which issue is fixed along with any relevant motivation, context and any dependencies that are required for this change along with any breaking changes that may be introduced. 3 | --> 4 | -------------------------------------------------------------------------------- /.github/config/labeller.yml: -------------------------------------------------------------------------------- 1 | #### THIS FILE IS MANAGED BY AN AUTOMATED WORKFLOW #### 2 | 3 | # .github/config/labeller.yml 4 | 5 | version: v1 6 | 7 | labels: 8 | - label: "Feat" 9 | sync: true 10 | matcher: 11 | title: ".*(feat:|(IF-[0-9]+ -- (feat))).*/i" 12 | body: "(feat:.*|feature:.*)/i" 13 | branch: "(^feat\/.*)/i" 14 | baseBranch: "(^feat\/.*)/i" 15 | commits: "(^feat:.*|(IF-[0-9]+ -- (feat))).*/i" 16 | 17 | - label: "Fix" 18 | sync: true 19 | matcher: 20 | title: "(^hotfix:.*|^fix:.*|(IF-[0-9]+ -- (fix|hotfix).*))/i" 21 | body: "(hotfix:.*|fix:.*|bug:.*)/i" 22 | branch: "(^hotfix\/.*|^fix\/.*)/i" 23 | baseBranch: "(^hotfix\/.*|^fix\/.*)/i" 24 | commits: "(^hotfix:.*|^fix:.*|(IF-[0-9]+ -- (fix|hotfix).*))/i" 25 | 26 | - label: "Chore" 27 | sync: true 28 | matcher: 29 | title: "(^chore:.*|(IF-[0-9]+ -- chore.*))/i" 30 | body: "(hotfix:.*|fix:.*|bug:.*)/i" 31 | branch: "(^chore\/.*)/i" 32 | baseBranch: "(^chore\/.*)/i" 33 | commits: "(^chore:.*|(IF-[0-9]+ -- chore.*))/i" 34 | author: 35 | - "renovatebot" 36 | - "renovatebot[bot]" 37 | 38 | - label: "Docs" 39 | sync: true 40 | matcher: 41 | title: "(^docs:.*|(IF-[0-9]+ -- docs.*))/i" 42 | body: "(docs:.*|documentation:)/i" 43 | branch: "(^docs\/.*)/i" 44 | baseBranch: "(^docs\/.*)/i" 45 | commits: "(^docs:.*|(IF-[0-9]+ -- docs.*))/i" 46 | files: 47 | any: ["**/docs/**", "**/doc/**", "**/*.md", "**/*.markdown", "**/*.rst", "**/*.txt"] 48 | count: 49 | gte: 1 50 | lte: 1000 51 | 52 | - label: "CDK" 53 | sync: true 54 | matcher: 55 | title: "(.*cdk|(IF-[0-9]+ -- cdk).*)/i" 56 | body: ".*(cdk:|cloudformation:).*/i" 57 | branch: "(.*cdk\/.*)/i" 58 | baseBranch: "(.*cdk\/.*)/i" 59 | commits: "(.*cdk:|(IF-[0-9]+ -- cdk)).*/i" 60 | files: 61 | any: ["**/cdk/**", "**/cloudformation/**", "**/*.cdk.*", "**/*.stack.*"] 62 | count: 63 | gte: 1 64 | lte: 1000 65 | 66 | - label: "Github" 67 | sync: true 68 | matcher: 69 | title: "(^actions:.*|(IF-[0-9]+ -- actions.*)|^workflow:.*|(IF-[0-9]+ -- workflow.*)|.*github:.*|(IF-[0-9]+ -- github.*))/i" 70 | body: ".*(actions:.*|github-actions:|github:|workflow:).*/i" 71 | branch: "(^actions\/.*|^github\/.*^workflow\/.*)/i" 72 | baseBranch: "(^actions\/.*|^github\/.*^workflow\/.*)/i" 73 | commits: "(^actions:.*|(IF-[0-9]+ -- actions.*)|^workflow:.*|(IF-[0-9]+ -- workflow.*)|^github:.*|(IF-[0-9]+ -- github.*))/i" 74 | files: 75 | any: [".github\/*", "CODEOWNERS"] 76 | count: 77 | gte: 1 78 | lte: 1000 79 | 80 | - label: "Test" 81 | sync: true 82 | matcher: 83 | title: "(^test|(IF-[0-9]+ -- test)|jest).*/i" 84 | body: ".*(tests:|test:|testing:|jest:).*/i" 85 | branch: "(^test\/.*)/i" 86 | baseBranch: "(^test\/.*)/i" 87 | commits: "(^tests:.*|^test:.*|(IF-[0-9]+ -- test.*))/i" 88 | files: 89 | any: ["**/.*(test|.spec).*", "**/.*jest.*"] 90 | count: 91 | gte: 1 92 | lte: 1000 93 | 94 | - label: "Performance" 95 | sync: true 96 | matcher: 97 | title: "(^perf:|(IF-[0-9]+ -- perf)).*/i" 98 | body: "(perf:|performance:).*/i" 99 | branch: "(^perf\/.*)/i" 100 | baseBranch: "(^perf\/.*)/i" 101 | commits: "(^perf:|(IF-[0-9]+ -- perf)).*/i" 102 | 103 | - label: "Style" 104 | sync: true 105 | matcher: 106 | title: ".*(style:|(IF-[0-9]+ -- (style|lint)|lint)).*/i" 107 | body: ".*(style:|styling:|lint:|linting|format:|formatting).*/i" 108 | branch: "(^style\/.*)/i" 109 | baseBranch: "(^style\/.*)/i" 110 | commits: ".*(style:|(IF-[0-9]+ -- style)|lint|formatting.*)/i" 111 | files: 112 | any: 113 | [ 114 | "**/.*prettier.*", 115 | "**/.*eslint.*", 116 | "**/.*stylelint.*", 117 | "**/.*style.*", 118 | "**/.*lint.*", 119 | "**/.*editorconfig.*", 120 | ] 121 | count: 122 | gte: 1 123 | lte: 1000 124 | 125 | - label: "Database" 126 | sync: true 127 | matcher: 128 | title: "(^db:.*|.*sql.*|(IF-[0-9]+ -- db.*))/i" 129 | body: ".*(db:|database:).*/i" 130 | branch: "(^db\/.*)/i" 131 | baseBranch: "(^db\/.*)/i" 132 | commits: "(^db:.*|.*sql|(IF-[0-9]+ -- db.*))/i" 133 | files: 134 | # regex glob to match a file with extension .sql in any directory recursively 135 | any: ["**/*.sql", "**/*.db", "**/db/**", "**/flyway.*", "**/migrations/**", "**/*.sqlite.*"] 136 | count: 137 | gte: 1 138 | lte: 1000 139 | 140 | - label: "Security" 141 | sync: true 142 | matcher: 143 | title: ".*(CVE|sec:|security).*/i" 144 | body: ".*(CVE|sec:|security).*/i/i" 145 | branch: ".*(CVE|sec:|security).*/i" 146 | baseBranch: ".*(CVE|sec:|security).*/i" 147 | commits: ".*(CVE|sec:|security).*/i" 148 | files: 149 | any: 150 | [ 151 | "CODEOWNERS", 152 | "SECURITY.*", 153 | ".github/settings.yml", 154 | "**/*.pem", 155 | "**/*.crt", 156 | "**/.*password.*", 157 | "**/.*secret.*", 158 | "**/.*token.*", 159 | "**/.*key.*", 160 | ] 161 | count: 162 | gte: 1 163 | lte: 1000 164 | 165 | - label: "Git" 166 | sync: true 167 | matcher: 168 | title: ".*git.*/i" 169 | files: 170 | any: ["**/.git.*", "**/.husky/*", "**/.pre-commit-config.*"] 171 | count: 172 | gte: 1 173 | lte: 1000 174 | 175 | - label: "Sync-Files" 176 | sync: true 177 | matcher: 178 | title: ".*Sync-Files.*/i" 179 | 180 | - label: "DO NOT MERGE" 181 | sync: true 182 | matcher: 183 | title: ".*(DO NOT MERGE|DONT MERGE|DON'T MERGE).*" 184 | body: ".*(DO NOT MERGE|DONT MERGE|DON'T MERGE).*" 185 | commits: ".*(DO NOT MERGE|DONT MERGE|DON'T MERGE).*" 186 | 187 | checks: 188 | - context: "Merge check" 189 | description: "Disable merging when 'DO NOT MERGE' label is set" 190 | labels: 191 | none: ["DO NOT MERGE"] 192 | -------------------------------------------------------------------------------- /.github/config/labels.yml: -------------------------------------------------------------------------------- 1 | #### THIS FILE IS MANAGED BY AN AUTOMATED WORKFLOW #### 2 | 3 | # .github/config/labels.yml 4 | 5 | - name: "Feat" 6 | color: "c52bff" 7 | aliases: ["Feature", "Features"] 8 | 9 | - name: "Fix" 10 | color: "125a29" 11 | aliases: ["bug", "bugfix", "patched", "Hotfix"] 12 | 13 | - name: "Chore" 14 | color: "293535" 15 | aliases: ["maintenance", "maint"] 16 | 17 | - name: "Bug" 18 | color: "b45f06" 19 | aliases: ["problem"] 20 | 21 | - name: "High" 22 | color: "ff0000" 23 | aliases: ["high", "urgent", "critical"] 24 | 25 | - name: "Medium" 26 | color: "6fa8dc" 27 | aliases: ["medium"] 28 | 29 | - name: "Low" 30 | color: "ade0d6" 31 | aliases: ["low"] 32 | 33 | - name: "Docs" 34 | color: "7c9e9d" 35 | aliases: ["doco", "Documentation"] 36 | 37 | - name: "CDK" 38 | color: "ce7e00" 39 | aliases: ["AWS", "cloudformation", "CFn"] 40 | 41 | - name: "Github" 42 | color: "ff1089" 43 | aliases: ["Actions", "Workflow"] 44 | 45 | - name: "Git" 46 | color: "3e6890" 47 | 48 | - name: "Test" 49 | color: "981f5c" 50 | aliases: ["testing", "tests", "Jest"] 51 | 52 | - name: "Style" 53 | color: "0018a8" 54 | aliases: ["lint", "formatting", "styling", "prettier", "eslint"] 55 | 56 | - name: "Database" 57 | color: "43e8d8" 58 | aliases: ["DB", "SQL", "Flyway", "Migrations"] 59 | 60 | - name: "Security" 61 | color: "f51100" 62 | aliases: ["sec", "vulnerability", "CVE", "vuln", "CODEOWNERS"] 63 | 64 | - name: "Performance" 65 | color: "ff825a" 66 | aliases: ["perf", "optimisation"] 67 | 68 | - name: "DO NOT MERGE" 69 | color: "d54360" 70 | aliases: ["DONT MERGE", "WIP", "Work In Progress"] 71 | 72 | - name: "renovatebot" 73 | color: "123000" 74 | aliases: ["Renovate"] 75 | 76 | - name: "minor" 77 | color: "123000" 78 | aliases: ["minor-update"] 79 | 80 | - name: "major" 81 | color: "123000" 82 | aliases: ["major-update"] 83 | 84 | - name: "patch" 85 | color: "123000" 86 | aliases: ["patch-update"] 87 | 88 | - name: "comments" 89 | color: "4360d5" 90 | aliases: ["comment", "blog-comments"] 91 | 92 | - name: "sync-files" 93 | color: "130000" 94 | 95 | - name: "codeball:needs-careful-review" 96 | color: "fde68a" 97 | description: "This PR needs careful review" 98 | aliases: ["codeball:needs-review"] 99 | 100 | - name: "codeball:approved" 101 | color: "86efac" 102 | description: "This PR has been approved by Codeball AI" 103 | -------------------------------------------------------------------------------- /.github/release-drafter.yml: -------------------------------------------------------------------------------- 1 | template: | 2 | ## What's Changed 3 | 4 | $CHANGES 5 | -------------------------------------------------------------------------------- /.github/renovate.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": ["github>sammcj/renovate-config"], 3 | "description": "This file is managed in template-repo", 4 | "ignorePaths": [ 5 | ".github/workflows/codeball.yml", 6 | ".github/workflows/label-sync.yml", 7 | ".github/workflows/lint-pr-actions.yml", 8 | ".github/workflows/lint-pr-actions-skip.yml", 9 | ".github/workflows/lint-pr-markdown.yml", 10 | ".github/workflows/pr-labeller.yml", 11 | ".github/workflows/todo.yml", 12 | ".github/workflows/mirror.yml" 13 | ] 14 | } 15 | -------------------------------------------------------------------------------- /.github/workflows/auto-approve.yml: -------------------------------------------------------------------------------- 1 | name: Auto approve gha-template-repo-token-generator PRs # and renovate 2 | 3 | on: 4 | pull_request_target: #Disabling on PRs for now 5 | workflow_dispatch: 6 | 7 | # One build per branch, cancel out of date builds 8 | concurrency: 9 | group: ${{ github.workflow }}-${{ github.ref }} 10 | cancel-in-progress: true 11 | 12 | jobs: 13 | auto-approve: 14 | runs-on: ubuntu-latest 15 | timeout-minutes: 5 16 | permissions: 17 | pull-requests: write 18 | if: github.actor == 'gha-template-repo-token-generator' # || github.actor == 'renovate[bot]' || github.actor == 'apps/renovate' 19 | steps: 20 | - uses: hmarr/auto-approve-action@v3 21 | -------------------------------------------------------------------------------- /.github/workflows/codeball.yml: -------------------------------------------------------------------------------- 1 | #### THIS FILE IS MANAGED BY AN AUTOMATED WORKFLOW #### 2 | 3 | name: Codeball 4 | 5 | on: 6 | pull_request: 7 | branches: 8 | - main 9 | - master 10 | - "!repo-sync/**" 11 | - "!renovate/**" 12 | - "!update/pre-commit-hooks/**" 13 | workflow_dispatch: 14 | 15 | permissions: 16 | contents: read 17 | issues: write 18 | pull-requests: write 19 | checks: write 20 | statuses: write 21 | actions: read 22 | 23 | # One build per branch, cancel out of date builds 24 | concurrency: 25 | group: ${{ github.workflow }}-${{ github.ref }} 26 | cancel-in-progress: true 27 | 28 | jobs: 29 | codeball-review: 30 | runs-on: ubuntu-latest 31 | timeout-minutes: 10 32 | if: ${{ !github.event.pull_request.draft }} 33 | name: Run Codeball Code Review 34 | steps: 35 | - name: Codeball AI Actions 36 | uses: sturdy-dev/codeball-action@v2 37 | with: 38 | approvePullRequests: "false" 39 | labelPullRequestsWhenApproved: "true" 40 | labelPullRequestsWhenReviewNeeded: "true" 41 | failJobsWhenReviewNeeded: "false" 42 | -------------------------------------------------------------------------------- /.github/workflows/codeql.yml: -------------------------------------------------------------------------------- 1 | #### THIS FILE IS MANAGED BY AN AUTOMATED WORKFLOW #### 2 | 3 | name: "CodeQL" 4 | 5 | on: 6 | schedule: 7 | - cron: "25 17 * * 3" 8 | 9 | jobs: 10 | analyze: 11 | name: Analyze 12 | runs-on: ubuntu-24.04 13 | permissions: 14 | actions: read 15 | contents: read 16 | security-events: write 17 | pull-requests: write 18 | checks: write 19 | 20 | steps: 21 | - name: Checkout repository 22 | uses: actions/checkout@0ad4b8fadaa221de15dcec353f45205ec38ea70b # v4 23 | 24 | - name: Initialize CodeQL 25 | uses: github/codeql-action/init@d39d31e687223d841ef683f52467bd88e9b21c14 # v3 26 | 27 | # Autobuild attempts to build any compiled languages (C/C++, C#, or Java). 28 | # If this step fails, then you should remove it and run the build manually (see below) 29 | - name: Autobuild 30 | uses: github/codeql-action/autobuild@d39d31e687223d841ef683f52467bd88e9b21c14 # v3 31 | 32 | - name: Perform CodeQL Analysis 33 | uses: github/codeql-action/analyze@d39d31e687223d841ef683f52467bd88e9b21c14 # v3 34 | -------------------------------------------------------------------------------- /.github/workflows/delete-disabled-workflows.yml: -------------------------------------------------------------------------------- 1 | name: Delete Disabled and Deprecated Workflows 2 | 3 | on: 4 | workflow_dispatch: 5 | inputs: 6 | github-token: 7 | description: 'Custom GitHub Token, to not be rate limited to 1,000 requests, defaults to GITHUB_TOKEN' 8 | required: false 9 | purge-deprecated: 10 | description: 'Delete deprecated workflows, defaults to true' 11 | required: false 12 | default: "true" 13 | delete-disabled: 14 | description: 'Delete disabled workflows, defaults to true' 15 | required: false 16 | default: "true" 17 | wait-days: 18 | description: 'Number of days to wait before deleting disabled workflows, defaults to 7' 19 | required: false 20 | default: 7 21 | type: number 22 | schedule: 23 | - cron: '0 0 * * 4' # At 00:00, only on Thursday 24 | 25 | permissions: 26 | actions: write 27 | contents: read 28 | 29 | jobs: 30 | delete-deprecated-workflows: 31 | runs-on: ubuntu-latest 32 | timeout-minutes: 15 33 | if: inputs.purge-deprecated == true 34 | steps: 35 | - uses: otto-de/purge-deprecated-workflow-runs@v1 36 | with: 37 | token: ${{ inputs.github-token || secrets.GITHUB_TOKEN }} 38 | 39 | delete-disabled-workflows: 40 | runs-on: ubuntu-latest 41 | timeout-minutes: 15 42 | if: inputs.delete-disabled == true 43 | steps: 44 | - uses: actions/github-script@v6 45 | with: 46 | github-token: ${{ inputs.github-token || secrets.GITHUB_TOKEN }} 47 | script: | 48 | const githubContext = { 49 | owner: context.repo.owner, 50 | repo: context.repo.repo, 51 | } 52 | 53 | // filter out workflows that are not disabled 54 | const allDisabledWorkflows = await github.paginate( 55 | github.rest.actions.listRepoWorkflows, 56 | githubContext 57 | ).then(workflows => workflows.filter(workflow => workflow.state == 'disabled_manually')) 58 | 59 | // filter out workflows that have only been disabled for less than wait-days 60 | const disabledWorkflows = allDisabledWorkflows.filter(workflow => { 61 | const now = new Date() 62 | const disabledAt = new Date(workflow.updated_at) 63 | const diff = now - disabledAt 64 | const days = diff / (1000 * 60 * 60 * 24) 65 | return days > ${{ inputs.wait-days }} 66 | }) 67 | 68 | console.log(`::group::List of disabled workflows older than ${{ inputs.wait-days }}`) 69 | console.log(disabledWorkflows) 70 | console.log('::endgroup::') 71 | 72 | // get the runs for each workflow 73 | for (const workflow of disabledWorkflows) { 74 | const runs = await github.paginate( 75 | github.rest.actions.listWorkflowRuns, 76 | { 77 | ...githubContext, 78 | workflow_id: workflow.id, 79 | } 80 | ) 81 | 82 | console.log(`::group::Workflow ${workflow.id} >> Title`) 83 | console.log(`::group::Workflow ${workflow.id} >> Runs`) 84 | 85 | // log the title of each run 86 | for (const run of runs) { 87 | console.log(`::group::Workflow ${workflow.id} >> Run ${run.id} >> Title`) 88 | console.log(run.head_commit.message) 89 | console.log('::endgroup::') 90 | } 91 | console.log('::endgroup::') 92 | 93 | // delete each run 94 | for (const run of runs) { 95 | const response = await github.rest.actions.deleteWorkflowRun({ 96 | ...githubContext, 97 | run_id: run.id, 98 | }) 99 | 100 | console.log(`::group::Workflow ${workflow.id} >> Run ${run.id} >> Delete`) 101 | console.log(response) 102 | console.log('::endgroup::') 103 | 104 | } 105 | 106 | } 107 | -------------------------------------------------------------------------------- /.github/workflows/detect-secrets-generate-baseline.yml: -------------------------------------------------------------------------------- 1 | #### THIS FILE IS MANAGED BY AN AUTOMATED WORKFLOW #### 2 | 3 | name: detect-secrets update baseline 4 | 5 | on: 6 | workflow_dispatch: 7 | 8 | permissions: 9 | contents: write 10 | pull-requests: write 11 | checks: write 12 | 13 | env: 14 | EXCLUDE_LINES: | 15 | --exclude-lines='CHECKSUM' 16 | --exclude-lines='MOCKING' 17 | --exclude-lines='GOOGLE_API_KEY' 18 | --exclude-lines='google-api-key' 19 | --exclude-lines='NODE_OPTIONS' 20 | --exclude-lines='http://localhost' 21 | --exclude-lines='#*tag=v' 22 | --exclude-lines='secrets*inherit' 23 | EXCLUDE_FILES: | 24 | --exclude-files='node_modules' 25 | --exclude-files='dist' 26 | --exclude-files='*secrets*baseline' 27 | 28 | jobs: 29 | detect-secrets-baseline-update: 30 | runs-on: ubuntu-latest 31 | steps: 32 | - uses: actions/checkout@0ad4b8fadaa221de15dcec353f45205ec38ea70b # v4 33 | - name: "Set output variable to update or create baseline" 34 | id: baseline 35 | run: | 36 | if [ -f .secrets.baseline ]; then 37 | echo "::set-output name=baseline::--baseline .secrets.baseline" 38 | else 39 | echo "::set-output name=baseline::> .secrets.baseline" 40 | fi 41 | 42 | - name: run detect-secrets update baseline 43 | uses: reviewdog/action-detect-secrets@master 44 | with: 45 | github_token: ${{ secrets.github_token }} 46 | reporter: github-pr-review 47 | fail_on_error: "true" 48 | level: warning 49 | detect_secrets_flags: "${{ env.EXCLUDE_FILES }} ${{ env.EXCLUDE_LINES }} ${{ steps.baseline.outputs.baseline }}" 50 | 51 | # Create a PR with the new baseline 52 | - uses: peter-evans/create-pull-request@5e914681df9dc83aa4e4905692ca88beb2f9e91f # v7 53 | with: 54 | token: ${{ secrets.GITHUB_TOKEN }} 55 | branch: update/security-baseline 56 | title: "update detect-secrets baseline" 57 | commit-message: "chore: update detect-secrets baseline" 58 | body: Update versions of detect-secrets baseline, remember to check the file for unexpected additions. 59 | add-paths: | 60 | .secrets.baseline 61 | -------------------------------------------------------------------------------- /.github/workflows/detect-secrets.yml: -------------------------------------------------------------------------------- 1 | #### THIS FILE IS MANAGED BY AN AUTOMATED WORKFLOW #### 2 | 3 | name: "Detect Secrets" 4 | 5 | # https://github.com/Yelp/detect-secrets 6 | # https://github.com/reviewdog/action-detect-secrets 7 | 8 | on: 9 | # Disabled automated running as I'm not convinced in it's value. 10 | # pull_request: 11 | # branches: 12 | # - main 13 | # - master 14 | # - "!repo-sync/**" 15 | # - "!renovate/**" 16 | # - "!update/pre-commit-hooks/**" 17 | workflow_dispatch: 18 | 19 | permissions: 20 | contents: read 21 | issues: write 22 | pull-requests: write 23 | checks: write 24 | 25 | env: 26 | EXCLUDE_LINES: | 27 | --exclude-lines='CHECKSUM' 28 | --exclude-lines='MOCKING' 29 | --exclude-lines='GOOGLE_API_KEY' 30 | --exclude-lines='google-api-key' 31 | --exclude-lines='NODE_OPTIONS' 32 | --exclude-lines='http://localhost' 33 | --exclude-lines='#*tag=v' 34 | --exclude-lines='secrets*inherit' 35 | EXCLUDE_FILES: | 36 | --exclude-files='node_modules' 37 | --exclude-files='dist/*' 38 | --exclude-files='*secrets*baseline' 39 | 40 | jobs: 41 | detect-secrets: 42 | name: "Detect Secrets in Code" 43 | runs-on: ubuntu-22.04 44 | steps: 45 | - uses: actions/checkout@93ea575cb5d8a053eaa0ac8fa3b40d7e05a33cc8 # tag=v3 46 | # Detect if .secrets.baseline exists and if so set the variable BASELINE to '--baseline .secrets.baseline' 47 | - name: "Set BASELINE variable if baseline exists" 48 | id: baseline 49 | run: | 50 | if [ -f .secrets.baseline ]; then 51 | echo "::set-output name=baseline::--baseline .secrets.baseline" 52 | fi 53 | 54 | - name: run detect-secrets 55 | uses: reviewdog/action-detect-secrets@master 56 | with: 57 | github_token: ${{ secrets.github_token }} 58 | reporter: github-pr-review 59 | fail_on_error: "true" 60 | level: warning 61 | detect_secrets_flags: "${{ env.EXCLUDE_FILES }} ${{ env.EXCLUDE_LINES }} ${{ steps.baseline.outputs.baseline }}" 62 | # 63 | # 64 | # Allowlisting Secrets 65 | # 66 | # You can add exclude-lines as above that will apply to all repositories this runs against. 67 | # 68 | # It is also possible to disable detection for individual lines of code in case of false positives. 69 | # To do this, add a comment at the end of the line with text `pragma: allowlist secret` 70 | # 71 | # public_key: | # pragma: allowlist secret 72 | # gX69YO4CvBsVjzAwYxdG 73 | # yDd30t5+9ez31gKATtj4 74 | # 75 | # Or add a comment with the text `pragma: allowlist nextline secret` before the line. 76 | # pragma: allowlist nextline secret 77 | # public_key = gX69YO4CvBsVjzAwYxdG 78 | # 79 | # Baselines 80 | # - To create a baseline file allowlisting the current secrets, run the following command: 81 | # detect-secrets scan <detect_secrets_flags here> > .secrets.baseline 82 | # e.g. detect-secrets scan --exclude-lines 'CHECKSUM' --exclude-lines 'MOCKING' > .secrets.baseline 83 | # 84 | # - To update an existing baseline file, run the following command: 85 | # detect-secrets scan <detect_secrets_flags here> --baseline .secrets.baseline 86 | # 87 | # - To audit an existing baseline file, run the following command: 88 | # detect-secrets audit .secrets.baseline 89 | # 90 | # For more information see https://github.com/Yelp/detect-secrets#quickstart 91 | -------------------------------------------------------------------------------- /.github/workflows/label-sync.yml: -------------------------------------------------------------------------------- 1 | #### THIS FILE IS MANAGED BY AN AUTOMATED WORKFLOW #### 2 | 3 | name: "Sync Available Github Labels" 4 | 5 | on: 6 | workflow_dispatch: 7 | schedule: 8 | - cron: "30 4 * * 0" 9 | push: 10 | paths: 11 | - .github/config/labels.yml 12 | - .github/config/labeller.yml 13 | - .github/workflows/label-sync.yml 14 | 15 | permissions: 16 | pull-requests: write 17 | contents: read 18 | issues: write 19 | 20 | # One build per branch, cancel out of date builds 21 | concurrency: 22 | group: ${{ github.workflow }}-${{ github.ref }} 23 | cancel-in-progress: true 24 | 25 | jobs: 26 | sync-labels: 27 | name: Sync Github Labels 28 | runs-on: ubuntu-latest 29 | timeout-minutes: 10 30 | steps: 31 | - uses: actions/checkout@8e5e7e5ab8b370d6c329ec480221332ada57f0ab # v3 32 | - uses: EndBug/label-sync@da00f2c11fdb78e4fae44adac2fdd713778ea3e8 # v2 33 | with: 34 | delete-other-labels: true 35 | dry-run: false 36 | token: ${{ secrets.GITHUB_TOKEN }} 37 | config-file: .github/config/labels.yml 38 | -------------------------------------------------------------------------------- /.github/workflows/lint-codeowners.yml: -------------------------------------------------------------------------------- 1 | #### THIS FILE IS MANAGED BY AN AUTOMATED WORKFLOW #### 2 | 3 | name: "Lint CODEOWNERS" 4 | on: 5 | pull_request: 6 | paths: 7 | - "**/CODEOWNERS" 8 | - "!**/node_modules/**" 9 | branches: 10 | - main 11 | - master 12 | 13 | # One build per branch, cancel out of date builds 14 | concurrency: 15 | group: ${{ github.workflow }}-${{ github.ref }} 16 | cancel-in-progress: true 17 | 18 | permissions: 19 | issues: write 20 | pull-requests: write 21 | statuses: write 22 | checks: write 23 | contents: read 24 | security-events: read 25 | 26 | jobs: 27 | lint-codeowners: 28 | name: "Lint CODEOWNERS file" 29 | runs-on: ubuntu-24.04 30 | timeout-minutes: 10 31 | steps: 32 | - uses: actions/checkout@0ad4b8fadaa221de15dcec353f45205ec38ea70b # v4 33 | - uses: mszostok/codeowners-validator@7f3f5e28c6d7b8dfae5731e54ce2272ca384592f # tag=v0.7.4 34 | with: 35 | checks: "files,duppatterns,syntax" 36 | experimental_checks: "avoid-shadowing" 37 | github_access_token: "${{ secrets.GITHUB_TOKEN }}" 38 | -------------------------------------------------------------------------------- /.github/workflows/lint-docker.yml: -------------------------------------------------------------------------------- 1 | #### THIS FILE IS MANAGED BY AN AUTOMATED WORKFLOW #### 2 | 3 | name: "Lint Docker" 4 | 5 | on: 6 | pull_request: 7 | paths: 8 | - "**/Dockerfile.*" 9 | - "**/docker-compose.*" 10 | - "!**/node_modules/**" 11 | branches: 12 | - main 13 | - master 14 | - "!repo-sync/**" 15 | - "!renovate/**" 16 | - "!update/pre-commit-hooks/**" 17 | workflow_dispatch: 18 | 19 | jobs: 20 | hadolint: 21 | name: "Lint Docker with hadolint" 22 | runs-on: ubuntu-22.04 23 | steps: 24 | - uses: actions/checkout@93ea575cb5d8a053eaa0ac8fa3b40d7e05a33cc8 # tag=v3 25 | - name: run tflint 26 | uses: reviewdog/action-hadolint@master 27 | with: 28 | github_token: ${{ secrets.github_token }} 29 | reporter: github-pr-review 30 | fail_on_error: "false" 31 | level: warning 32 | filter_mode: "nofilter" # Optional. Check all files, not just the diff 33 | # tflint_version: "v0.24.0" # Optional. Custom version, instead of latest 34 | # tflint_rulesets: "azurerm google" # Optional. Extra official rulesets to install 35 | # flags: "--module" # Optional. Add custom tflint flags 36 | -------------------------------------------------------------------------------- /.github/workflows/lint-pr-actions-skip.yml: -------------------------------------------------------------------------------- 1 | #### THIS FILE IS MANAGED BY AN AUTOMATED WORKFLOW #### 2 | 3 | name: "Lint Github Actions Workflows" 4 | 5 | # This is a gross hack to allow PRs that don't require a specific workflow to run (e.g. don't lint files not touched) by providing a positive status check in their place. 6 | # This workflow runs on an inverse match using the paths-ignore filter, so it will only run if the PR doesn't touch any of the paths that the other linting workflow does 7 | # The "name:" must match the name of the workflow it's skipping. 8 | # As recommended by Github - https://docs.github.com/en/repositories/configuring-branches-and-merges-in-your-repository/defining-the-mergeability-of-pull-requests/troubleshooting-required-status-checks#handling-skipped-but-required-checks 9 | 10 | on: 11 | pull_request: 12 | types: 13 | - opened 14 | - edited 15 | - reopened 16 | - synchronize 17 | branches: 18 | - main 19 | - master 20 | - "!repo-sync/**" 21 | - "!renovate/**" 22 | - "!update/pre-commit-hooks/**" 23 | paths-ignore: 24 | - ".github/**" 25 | - "!**/node_modules/**" 26 | 27 | # One build per branch, cancel out of date builds 28 | concurrency: 29 | group: ${{ github.workflow }}-${{ github.ref }}-skipped 30 | cancel-in-progress: true 31 | 32 | jobs: 33 | lint-actions-workflows: 34 | name: Lint Actions Workflows 35 | runs-on: ubuntu-latest 36 | timeout-minutes: 5 37 | if: ${{ !github.event.pull_request.draft }} 38 | steps: 39 | - run: echo "This workflow is a placeholder for PRs that don't require linting of Github Actions workflows" 40 | -------------------------------------------------------------------------------- /.github/workflows/lint-pr-actions.yml: -------------------------------------------------------------------------------- 1 | #### THIS FILE IS MANAGED BY AN AUTOMATED WORKFLOW #### 2 | 3 | name: "Lint Github Actions Workflows" 4 | on: 5 | pull_request: 6 | types: 7 | - opened 8 | - edited 9 | - reopened 10 | - synchronize 11 | branches: 12 | - main 13 | - master 14 | - "!repo-sync/**" 15 | - "!renovate/**" 16 | - "!update/pre-commit-hooks/**" 17 | paths: 18 | - ".github/**" 19 | - "!**/node_modules/**" 20 | 21 | permissions: 22 | contents: read 23 | checks: write 24 | pull-requests: write 25 | issues: write 26 | statuses: write 27 | actions: read 28 | 29 | # One build per branch, cancel out of date builds 30 | concurrency: 31 | group: ${{ github.workflow }}-${{ github.ref }} 32 | cancel-in-progress: true 33 | 34 | jobs: 35 | lint-actions-workflows: 36 | name: Lint Actions Workflows 37 | runs-on: ubuntu-latest 38 | timeout-minutes: 10 39 | steps: 40 | - uses: actions/checkout@8e5e7e5ab8b370d6c329ec480221332ada57f0ab # v3 41 | - uses: reviewdog/action-actionlint@42de1e3a0f52d5f8b8390894de87bc603844e530 # v1 42 | with: 43 | fail_on_error: false 44 | level: error 45 | reporter: github-pr-review 46 | filter_mode: file 47 | env: 48 | REVIEWDOG_GITHUB_API_TOKEN: ${{ secrets.GITHUB_TOKEN }} 49 | GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} 50 | SHELLCHECK_OPTS: "-e SC2086 -e SC2129 -e SC1091 -e SC2050 -e SC2194 -e SC2154 -e SC2157" 51 | -------------------------------------------------------------------------------- /.github/workflows/lint-pr-markdown.yml: -------------------------------------------------------------------------------- 1 | #### THIS FILE IS MANAGED BY AN AUTOMATED WORKFLOW #### 2 | 3 | name: Lint Markdown Files 4 | 5 | # https://github.com/reviewdog/action-markdownlint 6 | 7 | on: 8 | pull_request: 9 | paths: 10 | - "*.md" 11 | - "pages/**/*.md" 12 | - "posts/**/*.md" 13 | - "_pages/**/*.md" 14 | - "_posts/**/*.md" 15 | - "docs/**/*.md" 16 | - "documentation/**/*.md" 17 | - "!**/node_modules/**" 18 | branches: 19 | - main 20 | - master 21 | - "!repo-sync/**" 22 | - "!renovate/**" 23 | - "!update/pre-commit-hooks/**" 24 | workflow_dispatch: 25 | 26 | permissions: 27 | contents: read 28 | checks: write 29 | pull-requests: write 30 | 31 | # One build per branch, cancel out of date builds 32 | concurrency: 33 | group: ${{ github.workflow }}-${{ github.ref }} 34 | cancel-in-progress: true 35 | 36 | jobs: 37 | lint-markdown: 38 | name: Lint Markdown 39 | runs-on: ubuntu-22.04 40 | timeout-minutes: 10 41 | steps: 42 | - uses: actions/checkout@93ea575cb5d8a053eaa0ac8fa3b40d7e05a33cc8 # tag=v3 43 | - name: markdownlint 44 | uses: reviewdog/action-markdownlint@97e3df02fe1573d505a7b268046a44fa5409cbc3 # tag=v0 45 | with: 46 | github_token: ${{ secrets.GITHUB_TOKEN }} 47 | reporter: github-pr-review 48 | level: error 49 | filter_mode: added 50 | fail_on_error: false 51 | markdownlint_flags: "'**/*.md' --ignore node_modules --disable MD013" 52 | -------------------------------------------------------------------------------- /.github/workflows/lint-shell.yml: -------------------------------------------------------------------------------- 1 | #### THIS FILE IS MANAGED BY AN AUTOMATED WORKFLOW #### 2 | 3 | name: "Lint Shell Files" 4 | 5 | on: 6 | pull_request: 7 | paths: 8 | - "**/*.sh" 9 | - "**/*.rc" 10 | - "!**/node_modules/**" 11 | branches: 12 | - main 13 | - master 14 | - "!repo-sync/**" 15 | - "!renovate/**" 16 | - "!update/pre-commit-hooks/**" 17 | workflow_dispatch: 18 | 19 | jobs: 20 | shellcheck: 21 | name: lint-shell 22 | runs-on: ubuntu-24.04 23 | timeout-minutes: 10 24 | steps: 25 | - uses: actions/checkout@0ad4b8fadaa221de15dcec353f45205ec38ea70b # v4 26 | - name: shellcheck 27 | uses: reviewdog/action-shellcheck@72365a51bf6476fe952a117c3ff703eb7775e40a # v1 28 | with: 29 | github_token: ${{ secrets.GITHUB_TOKEN }} 30 | reporter: github-pr-review 31 | path: "." 32 | pattern: | 33 | *.sh 34 | *.rc 35 | exclude: | 36 | ./.git/* 37 | ./**/node_modules/* 38 | check_all_files_with_shebangs: false 39 | fail_on_error: false 40 | level: warning 41 | shellcheck_flags: "--external-sources" 42 | -------------------------------------------------------------------------------- /.github/workflows/lint-tf.yml: -------------------------------------------------------------------------------- 1 | #### THIS FILE IS MANAGED BY AN AUTOMATED WORKFLOW #### 2 | 3 | name: "tflint and tfsec" 4 | 5 | on: 6 | pull_request: 7 | paths: 8 | - "**/*.tf" 9 | - "**/*.tf.*" 10 | - "**/*.tfvars.*" 11 | - "**/*.terraform.*" 12 | - "!**/node_modules/**" 13 | branches: 14 | - main 15 | - master 16 | - "!repo-sync/**" 17 | - "!renovate/**" 18 | - "!update/pre-commit-hooks/**" 19 | workflow_dispatch: 20 | 21 | jobs: 22 | tflint: 23 | name: "Lint Terraform" 24 | runs-on: ubuntu-22.04 25 | steps: 26 | - uses: actions/checkout@93ea575cb5d8a053eaa0ac8fa3b40d7e05a33cc8 # tag=v3 27 | # Install latest Terraform manually as 28 | # Docker-based GitHub Actions are slow due to lack of caching 29 | # Note: Terraform is not needed for tflint 30 | - name: Install Terraform 31 | run: | 32 | curl -sSL https://apt.releases.hashicorp.com/gpg | sudo apt-key add - 33 | sudo apt-add-repository "deb [arch=amd64] https://apt.releases.hashicorp.com $(lsb_release -cs) main" 34 | sudo apt-get update && sudo apt-get install terraform -y 35 | # Run init to get module code to be able to use `--module` 36 | - name: Terraform init 37 | run: | 38 | terraform init 39 | - name: run tflint 40 | uses: reviewdog/action-tflint@master 41 | with: 42 | github_token: ${{ secrets.github_token }} 43 | reporter: github-pr-review 44 | fail_on_error: "false" 45 | level: warning 46 | filter_mode: "nofilter" # Optional. Check all files, not just the diff 47 | # tflint_version: "v0.24.0" # Optional. Custom version, instead of latest 48 | # tflint_rulesets: "azurerm google" # Optional. Extra official rulesets to install 49 | # flags: "--module" # Optional. Add custom tflint flags 50 | 51 | tfsec: 52 | name: "tfsec" 53 | runs-on: ubuntu-22.04 54 | steps: 55 | - uses: actions/checkout@93ea575cb5d8a053eaa0ac8fa3b40d7e05a33cc8 # tag=v3 56 | - name: Run tfsec 57 | uses: reviewdog/action-tfsec@master 58 | with: 59 | github_token: ${{ secrets.github_token }} 60 | level: warning 61 | reporter: github-pr-review 62 | filter_mode: nofilter # Check all files, not just the diff 63 | fail_on_error: false # Fail action if errors are found 64 | # flags: -tee # Add debug flag to reviewdog 65 | # tfsec_flags: "" # Optional 66 | -------------------------------------------------------------------------------- /.github/workflows/mirror.yml: -------------------------------------------------------------------------------- 1 | name: Mirror repo to GitLab 2 | 3 | on: [push, delete, workflow_dispatch] 4 | 5 | jobs: 6 | to_gitlab: 7 | runs-on: ubuntu-latest 8 | steps: 9 | - uses: actions/checkout@v3 10 | with: 11 | fetch-depth: 0 12 | - uses: pixta-dev/repository-mirroring-action@v1 13 | with: 14 | target_repo_url: 15 | git@gitlab.com:sammcj/zsh_bootstrap_mirror.git 16 | ssh_private_key: 17 | ${{ secrets.GITLAB_SSH_PRIVATE_KEY }} 18 | -------------------------------------------------------------------------------- /.github/workflows/pr-labeller.yml: -------------------------------------------------------------------------------- 1 | #### THIS FILE IS MANAGED BY AN AUTOMATED WORKFLOW #### 2 | 3 | name: "Pull Request Labeller" 4 | on: 5 | pull_request: 6 | types: 7 | - opened 8 | - edited 9 | - reopened 10 | - synchronize 11 | - ready_for_review 12 | branches: 13 | - main 14 | - master 15 | 16 | # One build per branch, cancel out of date builds 17 | concurrency: 18 | group: ${{ github.workflow }}-${{ github.ref }} 19 | cancel-in-progress: true 20 | 21 | permissions: 22 | issues: write 23 | pull-requests: write 24 | statuses: write 25 | checks: write 26 | contents: read 27 | security-events: read 28 | 29 | jobs: 30 | pr-labeller: 31 | name: "Pull Request Labeller" 32 | runs-on: ubuntu-latest 33 | timeout-minutes: 5 34 | if: ${{ !github.event.pull_request.draft }} 35 | steps: 36 | - uses: fuxingloh/multi-labeler@v2 # tag=v2 37 | id: pr-labeller 38 | with: 39 | github-token: ${{ secrets.GITHUB_TOKEN }} 40 | config-path: .github/config/labeller.yml 41 | -------------------------------------------------------------------------------- /.github/workflows/pre-commit.yml: -------------------------------------------------------------------------------- 1 | #### THIS FILE IS MANAGED BY AN AUTOMATED WORKFLOW #### 2 | 3 | name: pre-commit 4 | 5 | on: 6 | workflow_dispatch: 7 | 8 | permissions: 9 | contents: read 10 | pull-requests: write 11 | checks: write 12 | 13 | jobs: 14 | pre-commit: 15 | runs-on: ubuntu-latest 16 | steps: 17 | - uses: actions/checkout@0ad4b8fadaa221de15dcec353f45205ec38ea70b # v4 18 | - uses: actions/setup-node@60edb5dd545a775178f52524783378180af0d1f8 # v4 19 | with: 20 | node-version: 16 21 | - run: | 22 | npm install -g npm 23 | npm ci 24 | - uses: actions/setup-python@82c7e631bb3cdc910f68e0081d67478d79c6982d # v5 25 | - uses: pre-commit/action@2c7b3805fd2a0fd8c1884dcaebf91fc102a13ecd # v3.0.1 26 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | #### THIS FILE IS MANAGED BY AN AUTOMATED WORKFLOW #### 2 | 3 | # This is a generic .gitignore for JS/TS/Java/Python projects 4 | 5 | # Inverse matchs to ensure these aren't ignored 6 | !*.env.template 7 | !*.template.env 8 | !*.eslintrc.js 9 | !*.prettierrc.js 10 | !*.config.js 11 | 12 | # Typescipt and CDK 13 | **/*.cdk.staging 14 | **/*.d.ts 15 | **/*.tabl.json 16 | **/*.tsbuildinfo 17 | **/cdk.context.json 18 | **/cdk.out 19 | 20 | # NodeJS 21 | **/node_modules 22 | node_modules/** 23 | 24 | # Test and coverage output 25 | **/coverage/ 26 | **/test-report.xml 27 | .coverage.* 28 | htmlcov/ 29 | megalinter-reports/ 30 | 31 | # Editors 32 | .project 33 | .settings 34 | .springBeans 35 | **/.favorites.json 36 | **/.idea 37 | **/.vscode 38 | **/*.Session.vim 39 | **/*.sw[a-z] 40 | **/*.vim 41 | **/*.zwc 42 | **/*~ 43 | 44 | # OS generated files 45 | **/._* 46 | **/.AppleDouble 47 | **/.dccache 48 | **/.dropbox 49 | **/.dropbox.attr 50 | **/.dropbox.cache 51 | **/.DS_Store 52 | **/.DS_STORE 53 | **/.lnk 54 | **/.LSOverride 55 | **/$RECYCLE.BIN/ 56 | **/Desktop.ini 57 | **/ehthumbs.db 58 | **/Thumbs.db 59 | 60 | # Files that might appear in the root of a volume 61 | **/.com.apple.timemachine.donotpresent 62 | **/.DocumentRevisions-V100 63 | **/.fseventsd 64 | **/.Spotlight-V100 65 | **/.TemporaryItems 66 | **/.Trashes 67 | **/.VolumeIcon.icns 68 | 69 | # Directories potentially created on remote AFP share 70 | **/.apdisk 71 | **/.AppleDB 72 | **/.AppleDesktop 73 | **/Network Trash Folder 74 | **/Temporary Items 75 | 76 | # Temp files 77 | **/.temp 78 | **/.tmp 79 | tmp/ 80 | 81 | # Files that commonly contain secrets 82 | **/*.key 83 | **/*.pem 84 | **/*.pfx 85 | **/*.p12 86 | **/*.jks 87 | **/*.keystore 88 | **/*.pkcs12 89 | **/*.pkcs8 90 | **/*.pkpass 91 | **/*.secrets 92 | 93 | # git mu-repo 94 | **/.mu_repo 95 | 96 | # Local state files / misc 97 | .dynamodb/ 98 | .eslintcache 99 | .env 100 | .fusebox/ 101 | .grunt 102 | .local 103 | .lock-wscript 104 | .next 105 | .node_repl_history 106 | .npm 107 | .nuxt 108 | .nyc_output 109 | .serverless/ 110 | .vuepress/dist 111 | .yarn-integrity 112 | *.seed 113 | *.tgz 114 | **/.BUILD_COMPLETED 115 | **/.cache 116 | **/.filesystem 117 | **/.LAST_BUILD 118 | **/.local-npm 119 | **/.nyc_output 120 | **/.nycrc 121 | **/.tools 122 | **/.webassets-cache 123 | **/*.lock 124 | **/*.lock.hcl 125 | **/*.pid 126 | **/db.sqlite3 127 | **/db.sqlite3-journal 128 | bower_components 129 | jspm_packages/ 130 | lib-cov 131 | 132 | # Logs 133 | **/*.log 134 | 135 | # Build directories 136 | **/_build/ 137 | **/dist 138 | build/ 139 | out/ 140 | target/ 141 | 142 | # Python 143 | __pycache__/ 144 | __pypackages__/ 145 | .ipynb_checkpoints 146 | *$py.class 147 | celerybeat-schedule 148 | develop-eggs/ 149 | dmypy.json 150 | eggs/ 151 | ipython_config.py 152 | local_settings.py 153 | pip-delete-this-directory.txt 154 | pip-log.txt 155 | pip-wheel-metadata/ 156 | venv 157 | 158 | # Jekyll 159 | _site 160 | .jekyll-cache 161 | .jekyll-metadata 162 | .sass-cache 163 | Gemfile.lock 164 | 165 | # Windows Installer files 166 | *.cab 167 | *.msi 168 | *.msm 169 | *.msp 170 | 171 | # Bootstrap files 172 | *private*.rc 173 | .gitconfig.private 174 | redo_aliases 175 | 176 | # Local .terraform directories 177 | **/.terraform/* 178 | *.tfstate 179 | *.tfstate.* 180 | override.tf 181 | override.tf.json 182 | *_override.tf 183 | *_override.tf.json 184 | 185 | # Docker 186 | **/docker-compose.override.y*ml 187 | 188 | # Hugo 189 | /public/ 190 | /resources/_gen/ 191 | /assets/jsconfig.json 192 | hugo_stats.json 193 | hugo.linux 194 | hugo.darwin 195 | /.hugo_build.lock 196 | 197 | # aws thing I'm trying 198 | update-aws-creds.sh 199 | -------------------------------------------------------------------------------- /.gitignoreglobal: -------------------------------------------------------------------------------- 1 | # Editors 2 | **/.dccache 3 | 4 | **/.vscode/extensions.json 5 | **/.vscode/* 6 | **/.vscode 7 | .vscode/settings.json 8 | **/.vscode/settings.json 9 | .idea 10 | *.swp 11 | *.swo 12 | Session.vim 13 | 14 | # Apple 15 | .DS_STORE 16 | 17 | # misc 18 | .tmp 19 | 20 | # git mu-repo 21 | .mu_repo 22 | 23 | # node 24 | #node_modules 25 | 26 | # Trunk linter for vscode (can be included per repo) 27 | .trunk 28 | 29 | #AI 30 | .aider* 31 | 32 | #vscode 33 | **/.vscode 34 | 35 | #cmake 36 | CMakeFiles/* 37 | CMakeCache.txt 38 | 39 | **/*.log 40 | **/*.pem 41 | **/*.key 42 | **/*.crt 43 | **/*.csr 44 | **/*.cer 45 | **/*.pfx 46 | **/*.p12 47 | 48 | **/*.pdf 49 | 50 | DEV_TASKS.md 51 | DEVELOPMENT_TASKS.md 52 | DEV_PLAN.md 53 | DEVELOPMENT_PLAN.md 54 | 55 | **/.repomix 56 | -------------------------------------------------------------------------------- /.pre-commit-config.yaml: -------------------------------------------------------------------------------- 1 | #### THIS FILE IS MANAGED BY AN AUTOMATED WORKFLOW #### 2 | 3 | # See https://pre-commit.com for more information 4 | # See https://pre-commit.com/hooks.html for more hooks 5 | 6 | exclude: '(^themes.*|^static/files/.*)' 7 | repos: 8 | - repo: https://github.com/pre-commit/pre-commit-hooks 9 | rev: v4.4.0 10 | hooks: 11 | - id: trailing-whitespace 12 | - id: check-yaml 13 | files: \.yaml$, \.yml$ 14 | types: [file] 15 | - id: check-case-conflict 16 | - id: check-json 17 | files: \.json$ 18 | types: [file] 19 | - id: check-symlinks 20 | - id: check-toml 21 | files: \.toml$ 22 | types: [file] 23 | - id: check-xml 24 | files: \.xml$ 25 | types: [file] 26 | - id: check-merge-conflict 27 | - id: mixed-line-ending 28 | args: [ --fix=no ] 29 | - id: pretty-format-json 30 | files: '!htmltest_output/refcache.json$' 31 | 32 | - repo: https://github.com/pre-commit/mirrors-eslint 33 | rev: v8.29.0 34 | hooks: 35 | - id: eslint 36 | files: \.[jt]sx?$ # *.js, *.jsx, *.ts and *.tsx 37 | types: [file] 38 | additional_dependencies: 39 | - eslint-config-prettier@8.5.0 40 | - eslint-plugin-deprecation@1.3.2 41 | - eslint-plugin-import@2.26.0 42 | - eslint-plugin-unused-imports@2.0.0 43 | 44 | - repo: https://github.com/syntaqx/git-hooks 45 | rev: v0.0.17 46 | hooks: 47 | - id: shellcheck 48 | files: \.sh$ 49 | types: [file] 50 | - id: shfmt 51 | files: \.sh$ 52 | types: [file] 53 | args: ["-i", "2", "-d", "-l"] 54 | -------------------------------------------------------------------------------- /.prettierignore: -------------------------------------------------------------------------------- 1 | #### THIS FILE IS MANAGED BY AN AUTOMATED WORKFLOW #### 2 | 3 | .ide 4 | .idea 5 | .vscode 6 | **/__pycache__ 7 | **/__pypackages__ 8 | **/.bin 9 | **/.DS_Store 10 | **/.env.* 11 | **/.git 12 | **/.out 13 | **/.venv 14 | **/*.log 15 | **/*.tmp 16 | **/build 17 | **/cdk.out 18 | **/coverage 19 | **/dist 20 | **/global.setup.ts 21 | **/htmlcov 22 | **/logs 23 | **/node_modules 24 | **/public 25 | **/temp 26 | **/tmp 27 | **/venv 28 | 29 | # Obsidian 30 | .obsidian 31 | -------------------------------------------------------------------------------- /.prettierrc.js: -------------------------------------------------------------------------------- 1 | // THIS FILE IS MANAGED BY AN AUTOMATED WORKFLOW 2 | 3 | module.exports = { 4 | overrides: [ 5 | { 6 | files: ['*.yml', '*.yaml'], 7 | options: { singleQuote: false }, 8 | }, 9 | { 10 | files: ['Makefile'], 11 | options: { useTabs: true }, 12 | }, 13 | ], 14 | tabWidth: 2, 15 | useTabs: false, 16 | singleQuote: true, 17 | trailingComma: 'all', 18 | semi: true, 19 | printWidth: 100, 20 | htmlWhitespaceSensitivity: 'ignore', 21 | }; 22 | -------------------------------------------------------------------------------- /.secrets.baseline: -------------------------------------------------------------------------------- 1 | { 2 | "version": "1.4.0", 3 | "plugins_used": [ 4 | { 5 | "name": "ArtifactoryDetector" 6 | }, 7 | { 8 | "name": "AWSKeyDetector" 9 | }, 10 | { 11 | "name": "AzureStorageKeyDetector" 12 | }, 13 | { 14 | "name": "Base64HighEntropyString", 15 | "limit": 4.5 16 | }, 17 | { 18 | "name": "BasicAuthDetector" 19 | }, 20 | { 21 | "name": "CloudantDetector" 22 | }, 23 | { 24 | "name": "DiscordBotTokenDetector" 25 | }, 26 | { 27 | "name": "GitHubTokenDetector" 28 | }, 29 | { 30 | "name": "HexHighEntropyString", 31 | "limit": 3.0 32 | }, 33 | { 34 | "name": "IbmCloudIamDetector" 35 | }, 36 | { 37 | "name": "IbmCosHmacDetector" 38 | }, 39 | { 40 | "name": "JwtTokenDetector" 41 | }, 42 | { 43 | "name": "KeywordDetector", 44 | "keyword_exclude": "" 45 | }, 46 | { 47 | "name": "MailchimpDetector" 48 | }, 49 | { 50 | "name": "NpmDetector" 51 | }, 52 | { 53 | "name": "PrivateKeyDetector" 54 | }, 55 | { 56 | "name": "SendGridDetector" 57 | }, 58 | { 59 | "name": "SlackDetector" 60 | }, 61 | { 62 | "name": "SoftlayerDetector" 63 | }, 64 | { 65 | "name": "SquareOAuthDetector" 66 | }, 67 | { 68 | "name": "StripeDetector" 69 | }, 70 | { 71 | "name": "TwilioKeyDetector" 72 | } 73 | ], 74 | "filters_used": [ 75 | { 76 | "path": "detect_secrets.filters.allowlist.is_line_allowlisted" 77 | }, 78 | { 79 | "path": "detect_secrets.filters.common.is_baseline_file", 80 | "filename": ".secrets.baseline" 81 | }, 82 | { 83 | "path": "detect_secrets.filters.common.is_ignored_due_to_verification_policies", 84 | "min_level": 2 85 | }, 86 | { 87 | "path": "detect_secrets.filters.heuristic.is_indirect_reference" 88 | }, 89 | { 90 | "path": "detect_secrets.filters.heuristic.is_likely_id_string" 91 | }, 92 | { 93 | "path": "detect_secrets.filters.heuristic.is_lock_file" 94 | }, 95 | { 96 | "path": "detect_secrets.filters.heuristic.is_not_alphanumeric_string" 97 | }, 98 | { 99 | "path": "detect_secrets.filters.heuristic.is_potential_uuid" 100 | }, 101 | { 102 | "path": "detect_secrets.filters.heuristic.is_prefixed_with_dollar_sign" 103 | }, 104 | { 105 | "path": "detect_secrets.filters.heuristic.is_sequential_string" 106 | }, 107 | { 108 | "path": "detect_secrets.filters.heuristic.is_swagger_file" 109 | }, 110 | { 111 | "path": "detect_secrets.filters.heuristic.is_templated_secret" 112 | } 113 | ], 114 | "results": {}, 115 | "generated_at": "2022-10-17T02:06:04Z" 116 | } 117 | -------------------------------------------------------------------------------- /.vimrc: -------------------------------------------------------------------------------- 1 | " vi: ft=vimrc 2 | 3 | "" Vundle begin 4 | " :PluginList - lists configured plugins 5 | " :PluginInstall - installs plugins; append `!` to update or just :PluginUpdate 6 | " :PluginSearch foo - searches for foo; append `!` to refresh local cache 7 | " :PluginClean - confirms removal of unused plugins; append `!` to auto-approve removal 8 | 9 | " Install Vundle if it's not already 10 | let vundleInstalled=1 11 | let vundle_readme=expand('~/.vim/bundle/Vundle.vim/README.md') 12 | if !filereadable(vundle_readme) 13 | echo "Installing Vundle.." 14 | echo "" 15 | silent !mkdir -p ~/.vim/bundle 16 | silent !git clone https://github.com/VundleVim/Vundle.vim.git ~/.vim/bundle/Vundle.vim 17 | let vundleInstalled=0 18 | endif 19 | set rtp+=~/.vim/bundle/Vundle.vim/ 20 | call vundle#rc() 21 | 22 | " let Vundle manage Vundle, required 23 | Plugin 'VundleVim/Vundle.vim' 24 | if vundleInstalled == 0 25 | echo "Installing Bundles, please ignore key map error messages" 26 | echo "" 27 | :PluginInstall 28 | endif 29 | 30 | set nocompatible 31 | filetype off 32 | set rtp+=~/.vim/bundle/Vundle.vim 33 | 34 | " Plugins begin 35 | call vundle#begin() 36 | Plugin 'VundleVim/Vundle.vim' 37 | Plugin 'tpope/vim-fugitive' 38 | Plugin 'airblade/vim-gitgutter' 39 | Plugin 'jonhiggs/tabline.vim' 40 | Plugin 'scrooloose/syntastic' 41 | Plugin 'dracula/vim', { 'name': 'dracula' } 42 | Plugin 'github/copilot.vim' 43 | "Plugin 'preservim/nerdtree' 44 | "Plugin 'tiagofumo/vim-nerdtree-syntax-highlight' 45 | Plugin 'ryanoasis/vim-devicons' 46 | Plugin 'robertbasic/vim-hugo-helper' 47 | Plugin 'junegunn/fzf', { 'do': { -> fzf#install() } } 48 | Plugin 'nanotee/zoxide.vim' 49 | call vundle#end() 50 | " Plugins END 51 | filetype plugin on " required 52 | "" Vundle END 53 | 54 | 55 | "" SETTINGS BEGIN 56 | 57 | set autochdir " change to directory of current file. 58 | set backspace=indent,eol,start " allow backspace to delete before insert point. 59 | set listchars=tab:▸\ ,eol:$ " configure the invisible characters. 60 | set modeline " make sure the modeline is used if it exists. 61 | set mouse=a 62 | set nocursorline " disabled because it makes keyboard repeat too slow. 63 | set ruler 64 | set visualbell 65 | set scrolloff=8 " start scrolling before reaching the bottom. 66 | set rtp+=/opt/homebrew/bin/fzf 67 | set encoding=UTF-8 68 | set laststatus=2 " always show status line. 69 | set magic " For regular expressions turn magic on 70 | set showmatch " Show matching brackets when text indicator is over them 71 | set ignorecase " Ignore case when searching 72 | set hlsearch " Highlight search results 73 | set incsearch " Makes search act like search in modern browsers 74 | set autoread " Set to auto read when a file is changed from the outside 75 | set wildmenu " Turn on wildmenu 76 | au FocusGained,BufEnter * checktime 77 | 78 | "set nofoldenable 79 | "set nowrap 80 | 81 | "" Spellchecking 82 | set spelllang=en_uk 83 | 84 | 85 | "" Filetypes 86 | au BufRead,BufNewFile *.md set filetype=markdown 87 | set ffs=unix " Use Unix as the standard file type 88 | 89 | "" Theme begin 90 | set background=dark 91 | if (has("termguicolors")) 92 | set termguicolors 93 | endif 94 | set t_Co=256 " enable 256 colours. 95 | syntax on 96 | syntax enable 97 | colorscheme dracula 98 | "" Theme end 99 | 100 | "" nerdtree begin 101 | "nnoremap <leader>n :NERDTreeFocus<CR> 102 | "nnoremap <C-n> :NERDTree<CR> 103 | "nnoremap <C-t> :NERDTreeToggle<CR> 104 | "nnoremap <C-f> :NERDTreeFind<CR> 105 | "let NERDTreeShowHidden=1 106 | "let NERDTreeIgnore = ['\.pyc$', '__pycache__', 'node_modules'] 107 | " Start NERDTree. If a file is specified, move the cursor to its window. 108 | "autocmd StdinReadPre * let s:std_in=1 109 | "autocmd VimEnter * NERDTree | if argc() > 0 || exists("s:std_in") | wincmd p | endif 110 | " If another buffer tries to replace NERDTree, put it in the other window, and bring back NERDTree. 111 | "autocmd BufEnter * if bufname('#') =~ 'NERD_tree_\d\+' && bufname('%') !~ 'NERD_tree_\d\+' && winnr('$') > 1 | 112 | " \ let buf=bufnr() | buffer# | execute "normal! \<C-W>w" | execute 'buffer'.buf | endif 113 | " Exit Vim if NERDTree is the only window remaining in the only tab. 114 | "autocmd BufEnter * if tabpagenr('$') == 1 && winnr('$') == 1 && exists('b:NERDTree') && b:NERDTree.isTabTree() | quit | endif 115 | "" nerdtree END 116 | 117 | " airline settings 118 | let g:airline_theme='dark' 119 | let g:airline#extensions#tabline#enabled = 1 120 | let g:airline_powerline_fonts = 1 121 | 122 | "" Tabs / Spacing 123 | " Default to soft tabs, 2 spaces 124 | set shiftwidth=2 125 | set showtabline=2 126 | set tabstop=2 127 | set expandtab 128 | set sw=2 129 | set sts=2 130 | " Except for Makefiles 131 | autocmd FileType make set noexpandtab shiftwidth=8 softtabstop=0 132 | " Except for Python 133 | autocmd FileType python set noexpandtab shiftwidth=4 softtabstop=0 134 | " Dont add comments 135 | autocmd FileType * setlocal formatoptions-=c formatoptions-=r formatoptions-=o 136 | 137 | 138 | "" Syntastic 139 | set statusline+=%#warningmsg# 140 | set statusline+=%{SyntasticStatuslineFlag()} 141 | set statusline+=%* 142 | let g:syntastic_always_populate_loc_list = 1 143 | let g:syntastic_auto_loc_list = 1 144 | let g:syntastic_check_on_open = 1 145 | let g:syntastic_aggregate_errors = 1 146 | let g:syntastic_check_on_wq = 0 147 | let g:syntastic_exit_checks = 0 148 | 149 | "" GitGutter 150 | let g:gitgutter_eager = 1 151 | let g:gitgutter_realtime = 1 152 | let g:gitgutter_sign_column_always = 0 153 | let g:gitgutter_sign_added = '█' 154 | let g:gitgutter_sign_modified = '█' 155 | let g:gitgutter_sign_modified_removed = '▁' 156 | let g:gitgutter_sign_removed = '▁' 157 | let g:gitgutter_sign_removed_first_line = '▔' 158 | autocmd BufEnter * GitGutterAll 159 | autocmd ShellCmdPost * GitGutterAll 160 | 161 | "" KEY MAPPINGS 162 | 163 | " Map leader key 164 | let mapleader = "," 165 | 166 | " Move between panes with ctrl+arrow 167 | map <C-up> <C-w><up> 168 | map <C-down> <C-w><down> 169 | map <C-left> <C-w><left> 170 | map <C-right> <C-w><right> 171 | 172 | " Fix Delete (backspace) on Mac OS X 173 | set backspace=2 174 | 175 | " Do not attempt to fix style on paste 176 | nnoremap <silent> p "+p 177 | 178 | " When you press <leader>r you can search and replace the selected text 179 | vnoremap <silent> <leader>r :call VisualSelection('replace', '')<CR> 180 | 181 | " Pressing ,ss will toggle and untoggle spell checking 182 | map <leader>ss :setlocal spell!<cr> 183 | map <F3> :setlocal spell! spell?<CR> 184 | 185 | " Shortcuts using <leader> 186 | map <leader>sn ]s 187 | map <leader>sp [s 188 | map <leader>sa zg 189 | map <leader>s? z= 190 | 191 | " Fast reload of vimrc 192 | map <leader>e :e! ~/.vimrc<cr> 193 | autocmd! bufwritepost ~/.vimrc source ~/.vimrc 194 | 195 | " Bash like keys for the command line 196 | cnoremap <C-A> <Home> 197 | cnoremap <C-E> <End> 198 | cnoremap <C-K> <C-U> 199 | cnoremap <C-P> <Up> 200 | cnoremap <C-N> <Down> 201 | 202 | " Tab Shortcuts 203 | map <C-n> :tabnext<CR> 204 | map <C-p> :tabprevious<CR> 205 | 206 | " Setup the F Key maps. 207 | set pastetoggle=<F1> 208 | map <F2> :set hlsearch!<CR> 209 | 210 | " Redraw Screen 211 | map <F5> :GitGutterAll<CR>:redraw!<CR> 212 | 213 | " Fix current word with first spelling suggestion. 214 | map Z 1z= 215 | 216 | " Enable incremental search 217 | set is hls 218 | 219 | 220 | "" FUNCTIONS 221 | " RemoveFancyCharacters COMMAND 222 | function! RemoveFancyCharacters() 223 | let typo = {} 224 | let typo["“"] = '"' 225 | let typo["”"] = '"' 226 | let typo["‘"] = "'" 227 | let typo["’"] = "'" 228 | let typo["–"] = '--' 229 | let typo["—"] = '---' 230 | let typo["…"] = '...' 231 | :exe ":%s/".join(keys(typo), '\|').'/\=typo[submatch(0)]/ge' 232 | endfunction 233 | command! RemoveFancyCharacters :call RemoveFancyCharacters() 234 | -------------------------------------------------------------------------------- /.whitesource: -------------------------------------------------------------------------------- 1 | { 2 | "scanSettings": { 3 | "baseBranches": [] 4 | }, 5 | "checkRunSettings": { 6 | "vulnerableCheckRunConclusionLevel": "failure", 7 | "displayMode": "diff", 8 | "useMendCheckNames": true 9 | }, 10 | "issueSettings": { 11 | "minSeverityLevel": "MEDIUM", 12 | "issueType": "DEPENDENCY" 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /0-paths.rc: -------------------------------------------------------------------------------- 1 | # shellcheck disable=SC2148 disable=SC1090 shell=bash 2 | 3 | # homebrew 4 | export PATH="/opt/homebrew/bin:/usr/local/bin:/opt/homebrew/sbin:/opt/homebrew/opt/gnu-getopt/bin:${PATH}" 5 | 6 | # my scripts 7 | export PATH="${PATH}:${HOME}/Library/Mobile\ Documents/com\~apple\~CloudDocs/Dropbox\ Import/bin:${HOME}/git/scripts:${HOME}/.local/bin:${HOME}/bin" 8 | 9 | # Golang 10 | export PATH="${PATH}:${HOME}/go/bin" 11 | 12 | # macOS Sonoma fix 13 | export PATH="/sbin:${PATH}" 14 | 15 | # added by Miniconda3 installer 16 | export PATH="/Users/samm/miniconda3/bin:${PATH}" 17 | 18 | # cargo 19 | export PATH="${HOME}/.cargo/bin:${PATH}" 20 | 21 | ### Kubernetes / k8s related exports ### 22 | 23 | # Krew Kubernetes plugin manager 24 | # export PATH="${KREW_ROOT:-$HOME/.krew}/bin:${PATH}" 25 | 26 | #source $HOME/.helm/helmenv.sh 27 | 28 | function conda_init() { 29 | 30 | # >>> conda initialize >>> 31 | # !! Contents within this block are managed by 'conda init' !! 32 | __conda_setup="$('/opt/homebrew/Caskroom/mambaforge/base/bin/conda' 'shell.zsh' 'hook' 2>/dev/null)" 33 | if [ $? -eq 0 ]; then 34 | eval "$__conda_setup" 35 | # else 36 | # if [ -f "/opt/homebrew/Caskroom/mambaforge/base/etc/profile.d/conda.sh" ]; then 37 | # # . "/opt/homebrew/Caskroom/mambaforge/base/etc/profile.d/conda.sh" # commented out by conda initialize 38 | # else 39 | # # export PATH="/opt/homebrew/Caskroom/mambaforge/base/bin:$PATH" # commented out by conda initialize 40 | # fi 41 | fi 42 | unset __conda_setup 43 | # <<< conda initialize <<< 44 | 45 | } 46 | 47 | # pnpm 48 | export PNPM_HOME="/Users/samm/Library/pnpm" 49 | case ":$PATH:" in 50 | *":$PNPM_HOME:"*) ;; 51 | *) export PATH="$PNPM_HOME:$PATH" ;; 52 | esac 53 | # pnpm end 54 | 55 | # [ -f ~/.inshellisense/key-bindings.zsh ] && source ~/.inshellisense/key-bindings.zsh 56 | export PATH="/opt/homebrew/opt/llvm/bin:$PATH" 57 | export PATH="/opt/homebrew/opt/qt@5/bin:$PATH" 58 | export PATH="/opt/homebrew/opt/openjdk/bin:$PATH" 59 | 60 | # to fix Library not loaded: @rpath/libllama.dylib 61 | export PATH="${HOME}/git/llama.cpp/bin:$PATH" 62 | -------------------------------------------------------------------------------- /1-zgen.rc: -------------------------------------------------------------------------------- 1 | # shellcheck disable=SC2148 disable=SC1090 shell=bash 2 | 3 | autoload -Uz compinit -C 4 | compinit -C 5 | autoload -U +X bashcompinit 6 | bashcompinit 7 | 8 | # load zgen 9 | source "${HOME}/.zgen/zgen.zsh" 10 | 11 | export ZGEN_RESET_ON_CHANGE="${HOME}/.zshrc" 12 | export ZSH_DISABLE_AUTO_UPDATE=7 # Only check for oh-my-zsh updates every 7 days 13 | 14 | # start compdef 15 | # compinit -u 16 | 17 | if ! zgen saved; then 18 | # echo "Creating a zgen save" 19 | 20 | ## load omz plugins ## 21 | # zgen oh-my-zsh 22 | zgen oh-my-zsh plugins/gitfast 23 | zgen oh-my-zsh plugins/command-not-found 24 | zgen oh-my-zsh plugins/fzf # https://github.com/ohmyzsh/ohmyzsh/issues/12412 25 | # zgen oh-my-zsh plugins/fnm 26 | # zgen oh-my-zsh plugins/docker 27 | zgen oh-my-zsh plugins/docker-compose 28 | zgen oh-my-zsh plugins/aws 29 | zgen oh-my-zsh plugins/colored-man-pages 30 | # plugins/macos - throwing compdef errors 31 | # zgen oh-my-zsh plugins/nmap 32 | # zgen oh-my-zsh plugins/gh 33 | 34 | ## load normal plugins ## 35 | zgen loadall <<EOPLUGINS 36 | zsh-users/zsh-completions src 37 | # zgen load zsh-users/zsh-completions 38 | # zsh-users/zsh-syntax-highlighting 39 | zsh-users/zsh-autosuggestions 40 | zsh-users/zsh-history-substring-search 41 | zdharma-continuum/fast-syntax-highlighting 42 | 43 | # git related 44 | peterhurford/git-it-on.zsh 45 | 46 | # fzf wrappers 47 | bigH/git-fuzzy 48 | EOPLUGINS 49 | # sunlei/zsh-ssh 50 | # ocodo/ollama_zsh_completion 51 | 52 | # save zgen cache 53 | zgen save 54 | fi 55 | 56 | -------------------------------------------------------------------------------- /10-prompt.rc: -------------------------------------------------------------------------------- 1 | # shellcheck disable=SC2148 disable=SC1090 disable=SC2034 disable=SC2154 disable=SC1087 shell=bash 2 | 3 | ### Prompt! ### 4 | autoload -U colors && colors 5 | 6 | # Outputs current branch info in prompt format 7 | # function git_prompt_info() { 8 | # local ref 9 | # # if [[ "$(command git config --get oh-my-zsh.hide-status 2>/dev/null)" != "1" ]]; then 10 | # # ref=$(command git symbolic-ref HEAD 2>/dev/null) || - ref=$(command git rev-parse --short HEAD 2>/dev/null) || return 0 11 | # # echo "$ZSH_THEME_GIT_PROMPT_PREFIX${ref#refs/heads/}$(parse_git_dirty)$ZSH_THEME_GIT_PROMPT_SUFFIX" 12 | # echo "${ZSH_THEME_GIT_PROMPT_PREFIX}${ref#refs/heads/}${ZSH_THEME_GIT_PROMPT_SUFFIX}" 13 | # # fi 14 | # } 15 | 16 | # show git changes on the command line 17 | autoload -Uz vcs_info add-zsh-hook 18 | setopt prompt_subst 19 | add-zsh-hook precmd vcs_info 20 | 21 | zstyle ':vcs_info:*' enable git 22 | precmd() { 23 | vcs_info 24 | } 25 | 26 | # Enable checking for (un)staged changes, enabling use of %u and %c 27 | zstyle ':vcs_info:*' check-for-changes true 28 | zstyle ':vcs_info:git:*' formats '[%b%u%c]' 29 | zstyle ':vcs_info:git:*' actionformats '[%b|%a%u%c]' 30 | # add the number of unstaged/staged changes to the prompt 31 | zstyle ':vcs_info:git:*' enable git 32 | 33 | # %s - The current version control system, like git or svn. 34 | # %r - The name of the root directory of the repository 35 | # %S - The current path relative to the repository root directory 36 | # %b - Branch information, like master 37 | # %m - In case of Git, show information about stashes 38 | # %u - Show unstaged changes in the repository 39 | # %c - Show staged changes in the repository 40 | 41 | # %{$(tput setaf 60)%}%m # this is the machine IP/hostname 42 | 43 | # Right hand side of the prompt line 44 | # RPROMPT="%{$(tput setaf 177)%}\$vcs_info_msg_0_" 45 | 46 | # PROMPT="%{$(tput setaf 60)%}%m %{$(tput setaf 105)%}%~${vcs_info_msg_0_}%{$(tput sgr0)%} %(?..[%?] )$ " 47 | 48 | # %{$(tput setaf 177)%}\$vcs_info_msg_0_ # means pink git information 49 | 50 | PROMPT="%{$(tput setaf 177)%}\$vcs_info_msg_0_ %{$(tput setaf 105)%}%~${vcs_info_msg_0_}%{$(tput sgr0)%} %(?..[%?] )$ " 51 | -------------------------------------------------------------------------------- /14-source-files.rc: -------------------------------------------------------------------------------- 1 | # shellcheck disable=SC2148 disable=SC1090 shell=bash 2 | 3 | # Node / Javascript 4 | # Note: If this doesn't work, make sure you've cleaned up nvm directories and related PATHs 5 | eval "$(/opt/homebrew/bin/fnm env --use-on-cd --corepack-enabled)" 6 | 7 | #saml2aws 8 | eval "$(saml2aws --completion-script-zsh)" 9 | 10 | #asdf 11 | # . /opt/homebrew/opt/asdf/libexec/asdf.sh 12 | 13 | #pyenv 14 | export PYENV_ROOT="$HOME/.pyenv" 15 | command -v pyenv >/dev/null || export PATH="$PYENV_ROOT/bin:$PATH" 16 | eval "$(pyenv init -)" 17 | 18 | . ~/.venv/bin/activate 19 | 20 | # # pnpm 21 | # export PNPM_HOME="/Users/samm/Library/pnpm" 22 | # case ":$PATH:" in 23 | # *":$PNPM_HOME:"*) ;; 24 | # *) export PATH="$PNPM_HOME:$PATH" ;; 25 | # esac 26 | # pnpm end 27 | 28 | #nav 29 | # source "${HOME}/.nav/nav.zsh" 30 | # nav bindkeys 31 | 32 | #cargo 33 | if [ -f "$HOME/.cargo/env" ]; then 34 | . "$HOME/.cargo/env" 35 | fi 36 | -------------------------------------------------------------------------------- /15-events.rc: -------------------------------------------------------------------------------- 1 | # shellcheck disable=SC2148 disable=SC1090 shell=bash 2 | 3 | # Events - things that are triggered by other things 4 | 5 | # ### remindme ### 6 | # REMINDME_PATH="${HOME}/git/scripts/remindme.sh" 7 | # COMMAND_NAME="remind" 8 | # # 9 | # # Configure directories to check for reminders 10 | # # shellcheck disable=SC2088 11 | # CHECK_REMINDER_DIRECTORIES=("${HOME}/git" "~/git" "${HOME}/Documents" "~/Downloads" "~/Documents") 12 | # # 13 | # # Function to check if the current directory is in the list of directories to check 14 | # should_check_reminders() { 15 | # local dir 16 | # for dir in "${CHECK_REMINDER_DIRECTORIES[@]}"; do 17 | # if [[ "${PWD/#$HOME/~}" == "$dir" ]]; then 18 | # return 0 19 | # fi 20 | # done 21 | # return 1 22 | # } 23 | 24 | # # Function to check for reminders related to the current directory 25 | # check_reminders_on_chdir() { 26 | # if should_check_reminders; then 27 | # local reminders 28 | # reminders=$(source "$REMINDME_PATH" -l | while IFS= read -r line; do 29 | # if [[ "$line" == *"$PWD"* ]]; then 30 | # echo "${line#*= }" 31 | # fi 32 | # done) 33 | # if [ -n "$reminders" ]; then 34 | # echo "Reminders for this directory:" 35 | # echo "$reminders" 36 | # echo "Use \"${COMMAND_NAME} -d <reminder_id>\" to mark a reminder as completed." 37 | # fi 38 | # fi 39 | # } 40 | 41 | # # Call the check_reminders_on_chdir function whenever you change directories 42 | # autoload -U add-zsh-hook 43 | # add-zsh-hook chpwd check_reminders_on_chdir 44 | 45 | # # Define the reminder_me function for convenience 46 | # remind() { 47 | # source "$REMINDME_PATH" "$@" 48 | # } 49 | 50 | ### END remindme ### 51 | -------------------------------------------------------------------------------- /16-fabric.rc: -------------------------------------------------------------------------------- 1 | # shellcheck disable=SC2148 disable=SC1090 shell=bash 2 | # 3 | # Reminder: you can save with fabric by piping text to save, e.g. pbpaste|save 4 | # 5 | -------------------------------------------------------------------------------- /3-location_specifics.rc: -------------------------------------------------------------------------------- 1 | # shellcheck disable=SC2148 2 | 3 | case $HOST in 4 | samm-digio*) 5 | # placeholder 6 | ;; 7 | Sams-Air*) 8 | # placeholder 9 | ;; 10 | *) 11 | # placeholder for all 12 | ;; 13 | esac 14 | -------------------------------------------------------------------------------- /4-aliases.rc: -------------------------------------------------------------------------------- 1 | # shellcheck disable=SC2148 disable=SC1090 shell=bash 2 | 3 | #TODO: cleanup this, move stuff out of Dropbox\ Import 4 | THIS_DIRECTORY="/Users/samm/Library/Mobile Documents/com~apple~CloudDocs/Dropbox Import/dotfiles/shell_config" 5 | 6 | ### Aliases ### 7 | 8 | # Directory Jumps 9 | alias d="cd ~/Downloads && ls -ltarh" 10 | alias icloud_drive="cd ~/Library/Mobile\ Documents/com\~apple\~CloudDocs/" 11 | 12 | # IDE Projects 13 | #shellcheck disable=SC2139 14 | alias zshconfig="code '${THIS_DIRECTORY}'" 15 | alias zzshconfig="zed '${THIS_DIRECTORY}'" 16 | # shellcheck disable=SC2139 17 | alias wezedit="code '${HOME}'/.config/wezterm/wezterm.lua" 18 | #shellcheck disable=SC2139 19 | alias zshconfigd="cd '${THIS_DIRECTORY}'" 20 | 21 | alias app_store_upgrade_mmas="mas upgrade" 22 | alias go_update_all="gup update" 23 | alias pa="pip freeze --local | grep -v '^\-e' | cut -d = -f 1 | xargs -n1 pip install -U" 24 | 25 | # Second homebrew install with x86 arch 26 | alias brew86="arch -x86_64 /usr/local/homebrew/bin/brew" 27 | 28 | # Git 29 | # alias gbd="git branch -d" Moved to functions 30 | #alias gitrb='for branch in $(git branch -r --merged | grep -v HEAD); do echo -e $(git show --format="%ci %cr %an" "$branch" | head -n 1) \\t$branch; done | sort -r' 31 | alias amend="git commit --amend --no-edit" 32 | alias bfg="java -jar ~/bin/bfg.jar" 33 | alias ch="commit-hotfix" 34 | alias cj="commit-jira" 35 | alias commit="git commit -m" 36 | alias git-cleanup-repack="bfg" 37 | alias git-delete-local-branches="git fetch --all --prune" 38 | alias git-delete-remote-branch="git push origin --delete" 39 | alias git-my-recent-branches="git reflog show --pretty=format:'%gs ~ %gd' --date=relative | grep 'checkout:' | grep -oE '[^ ]+ ~ .*' | awk -F~ '!seen[$1]++' | head -n 10 | awk -F' ~ HEAD@{' '{printf(" %12s:\t%s\n", substr($2, 1, length($2) - 1), $1)}'" 40 | alias git-remove-untracked-branches="git fetch -p; git branch --merged main | egrep -v '^\s*\*?\s*main$' | xargs -r git branch -d" #and re-run with -D if required 41 | alias gitamendrebase="GIT_SEQUENCE_EDITOR=\"sed -i -re 's/^pick /e /'\"; git rebase -i" 42 | alias gitclean="git fetch -p; git remote prune origin; git repack -a -d -f --max-pack-size=10g --depth=500 --window=250; git gc --aggressive" 43 | alias gitday="git diff HEAD 'HEAD@{1 day ago}'" 44 | alias gitdiff="git diff --color-words --color=always" 45 | alias githist="git log --graph --pretty=oneline --abbrev-commit" 46 | alias github-runs="github_actions_watcher" 47 | alias gitlast="git add .;git commit --amend -C HEAD ; git push" 48 | alias gitmonth="git diff HEAD 'HEAD@{1 month ago}'" 49 | alias gitupdateallrepos="find . -name .git -type d | xargs -n1 -P4 -I% git --git-dir=% --work-tree=%/.. fetch --all --recurse-submodules" 50 | alias gitweek="git diff HEAD 'HEAD@{1 week ago}'" 51 | alias gitwip="git add .; git commit -n -m 'minor updates'; git push" 52 | alias hotfix-checkout="checkout-hotfix" 53 | alias hotfix-commit="commit-hotfix" 54 | alias hotfix="checkout-hotfix" 55 | alias L="ls -ltarh" 56 | alias j="checkout-jira" 57 | alias jira-checkout="checkout-jira" 58 | alias jira-commit="commit-jira" 59 | alias jira="checkout-jira" 60 | alias main="git checkout main && git pull" 61 | alias minor="git commit -m 'chore: minor tweaks [skip ci]" 62 | ### Short git aliases 63 | alias add="git add ." 64 | alias c="git commit -m" 65 | alias h="hugo serve --disableFastRender --buildDrafts" 66 | alias m="git checkout main" 67 | alias p="git pull" 68 | alias P="git push" 69 | 70 | # GNU tools 71 | alias sed="gsed" 72 | 73 | # Find commands I type often so I can alias them 74 | alias typeless='history n 20000 | sed "s/.* //" | sort | uniq -c | sort -g | tail -n 100' 75 | 76 | # alias jpgcompress='echo convert INPUTFILE -sampling-factor 4:2:0 -strip -interlace JPEG -colorspace sRGB OUTPUTFILE' 77 | 78 | # NPM / Yarn 79 | # Check for unused packages 80 | alias npm-check-unused="npx npm-check" 81 | 82 | # Misc 83 | alias farsync='rsync -xrhm --numeric-ids -e "ssh -T -c aes128-gcm@openssh.com -o Compression=no" -x --partial --progress' #TODO: fix bug where this overwrites file name 84 | alias arcfarsync="rsync -rhm --numeric-ids -e 'ssh -T -c arcfour -o Compression=no -x' --partial --progress" 85 | alias tree="tree -ChF" 86 | alias mtr="sudo mtr" 87 | alias iftop="sudo iftop -i en0" 88 | alias ls='gls --color=auto -AHhF --group-directories-first' 89 | alias updatedb='sudo /usr/libexec/locate.updatedb' 90 | alias netwatch='lsof -i' 91 | alias flushdns='sudo discoveryutil udnsflushcaches' 92 | alias httpserver='sudo python3 -m http.server 80' 93 | alias cc='colorize.py' 94 | alias rmid="ssh-keygen -R" 95 | # alias aria="aria2c -s 5 -j 5 -x 5 -c --enable-http-pipelining=true --http-accept-gzip=true --max-connection-per-server=10 --content-disposition-default-utf8=true" 96 | # alias a=aria 97 | alias dmesg="dmesg -LT" 98 | alias cpuinfo="sysctl -n machdep.cpu.brand_string" 99 | # alias psql="/Applications/Postgres.app/Contents/Versions/latest/bin/psql" 100 | alias fastmail_you_there_bro="openssl s_client -connect imap.fastmail.com:993 -crlf" 101 | alias zmv='noglob zmv -W' 102 | alias mc='yazi' 103 | 104 | # MacOS shortcuts 105 | # alias delete-all-local-snapshots='for d in $(tmutil listlocalsnapshotdates | grep -v "Snapshot dates for all disks"); do sudo tmutil deletelocalsnapshots $d; done' 106 | alias clear-download-history="sqlite3 ~/Library/Preferences/com.apple.LaunchServices.QuarantineEventsV* 'delete from LSQuarantineEvent'" 107 | alias screenshots-jpg='defaults write com.apple.screencapture type JPG' 108 | alias screenshots-png='defaults write com.apple.screencapture type PNG' 109 | 110 | # Kubes 111 | alias kubes-busybox='kubectl run -i --tty loader --image=busybox /bin/sh' 112 | alias k='kubectl' 113 | 114 | # VSC 115 | alias code='/Applications/Visual\ Studio\ Code.app/Contents/Resources/app/bin/code' 116 | 117 | # Merge two files with diff 118 | alias merge='diff --line-format %L' 119 | 120 | # Terraform 121 | alias t='terraform' 122 | alias tf='terraform' 123 | alias tfn='terraform' 124 | 125 | # DNS benchmarking using https://github.com/redsift/dnstrace 126 | alias dnsbenchmark='dnstrace -n 10 -c 10 --server 192.168.0.1 --recurse microsoft.com' 127 | 128 | # Docker 129 | # podman machine init --cpus=3 --disk-size=30 --memory=3192 podman-machine-default 130 | # colima start --cpu 3 --memory 3 --disk 30 --mount $HOME/.vault-tokens:w 131 | # ln -s /usr/local/bin/colima /usr/local/bin/docker 132 | # alias docker='colima' 133 | 134 | alias youtube-dl='yt-dlp' 135 | 136 | alias nvm='echo I think you meant FNM' 137 | 138 | # node / typescript 139 | # update all packages in package.json except @types/node 140 | alias ncu='ncu -u \!@types/node --deep' 141 | 142 | # nice JSON graphing / visualisation tool 143 | alias json-graph='colima start && docker run -p 8888:8080 jsonvisio && open http://localhost:8888/editor' 144 | 145 | # Backblaze 146 | alias backblaze_edit='code /Library/Backblaze.bzpkg/bzdata/bzexcluderules_editable.xml' 147 | 148 | alias scripts='cd ~/git/scripts' 149 | alias nzb="cd ~/git/sammcj/nzb-docker" 150 | alias nzbdocker="open vscode://vscode-remote/ssh-remote+nas/root/git/nzb-docker/.vscode/nas-docker.code-workspace" 151 | 152 | ### Suffix Aliases ### 153 | 154 | # VSCode 155 | alias -s {ts,json,yaml,css,yml}=code 156 | 157 | # Firefox 158 | alias -s html=/Applications/Firefox.app 159 | 160 | # VLC 161 | alias -s {mkv,mp4,m4v,avi,mpg,mpeg}=vlc 162 | 163 | # Preview 164 | alias -s {jpg,jpeg,png,gif,bmp,ico,svg,webp}=open 165 | 166 | # Glow for Markdown 167 | alias -s md=glow 168 | 169 | # Networking 170 | alias ip6="curl -s 6.ipquail.com/ip" 171 | alias ip4="curl -s 4.ipquail.com/ip" 172 | alias ptr6="curl -s 6.ipquail.com/ptr" 173 | alias ptr4="curl -s 4.ipquail.com/ptr" 174 | 175 | # Find files modified today 176 | alias modified-today="mdfind 'kMDItemFSContentChangeDate>\$time.today'" 177 | 178 | # If running on macOS replace lsusb with ioreg -p IOUSB -l -w 0 179 | if [[ "$OSTYPE" == "darwin"* ]]; then 180 | alias lsusb='ioreg -p IOUSB -l -w 0' 181 | fi 182 | 183 | # 3D Printing 184 | alias rockpi='ssh root@rockpi' 185 | alias cura='open -a /Applications/UltiMaker Cura.app' 186 | alias cura-backup='cp -r ~/Library/Application\ Support/cura/*.zip ~/Library/Mobile\ Documents/com~apple~CloudDocs/Backups/3dprinting/cura/' 187 | 188 | alias backup-models="rsync -avr --partial '/Users/samm/Library/Mobile Documents/com~apple~CloudDocs/3D Printing/Models' root@nas:/mnt/raid/3dprinting/" 189 | alias backup-models-delete="rsync -avr --partial '/Users/samm/Library/Mobile Documents/com~apple~CloudDocs/3D Printing/Models' root@nas:/mnt/raid/3dprinting/ --delete" 190 | 191 | alias creality='/Users/samm/git/sammcj/ender-configs/creality-sonic-pad/login.exp' 192 | alias ender='cd ~/git/sammcj/ender-configs/ && code .' 193 | 194 | # pip install git+https://github.com/ChristophSchranz/Tweaker-3.git 195 | alias rotate='tweaker3 -vb -x -i' 196 | alias rotate_min_supports='tweaker3 -vb -x -min sur -i' 197 | 198 | alias obsidian='cd /Users/samm/Library/Mobile\ Documents/iCloud~md~obsidian/Documents/Main && ls -ltarh' 199 | 200 | # ML / AI 201 | # shellcheck disable=SC2139 202 | alias clinerules="code /Users/samm/Library/Mobile\ Documents/com\~apple\~CloudDocs/Documents/Cline" 203 | alias clinerulesd="cd /Users/samm/Library/Mobile\ Documents/com\~apple\~CloudDocs/Documents/Cline" 204 | alias sync_ollama_models="${HOME}/git/sammcj/scripts/ollama/export_ollama_model.py" 205 | alias copilot="gh copilot suggest -t shell" 206 | alias copilot-explain="gh copilot explain" 207 | alias '??'='copilot' 208 | alias wtf='copilot' 209 | alias l="OLLAMA_HOST=http://localhost:11434 gollama -l" 210 | alias i="ingest" 211 | alias code2prompt="ingest" 212 | alias ln="gollama -l" 213 | alias gl="gollama" 214 | alias ol="mods" 215 | alias idf='. $HOME/git/esp-idf/export.sh' 216 | alias o='tlm explain' 217 | alias hf="hfdownloader -c 10 -t \$HUGGINGFACE_TOKEN -j" 218 | alias imagesearch="sisi search" 219 | 220 | # uv 221 | alias venv='uv venv ; source .venv/bin/activate' 222 | 223 | ### AWS ### 224 | alias aws-rds-list-instances="aws rds describe-db-instances --region ap-southeast-2 --query \"DBInstances[].{Instance: DBInstanceIdentifier, Class: DBInstanceClass, Endpoint: Endpoint.Address, Status: DBInstanceStatus}\" --output text | sed -r 's/\x1B\[([0-9]{1,2}(;[0-9]{1,2})?)?[m|K]//g'" 225 | -------------------------------------------------------------------------------- /5-exports.rc: -------------------------------------------------------------------------------- 1 | # shellcheck disable=SC2148 disable=SC1090 shell=bash 2 | 3 | ### Exports ### 4 | export SAM_CLI_TELEMETRY=0 TELEMETRY=0 ENABLE_TELEMETRY=0 SEND_TELEMETRY=0 DO_NOT_TRACK=1 ANALYTICS=0 DISABLE_ANALYTICS=1 NO_ANALYTICS=1 DOTNET_CLI_TELEMETRY_OPTOUT=1 # General catch-all 5 | export GREP_OPTIONS="--color" 6 | # export LSCOLORS="ExFxCxDxBxegedabagacad" 7 | export LS_COLORS="$(vivid generate dracula)" 8 | export CLICOLOR=1 9 | export GOPATH="${HOME}/go" 10 | export XZ_OPT="--threads=8" 11 | export MU_REPO_SERIAL=false 12 | export EDITOR=vim 13 | 14 | # colima / docker 15 | # export DOCKER_HOST="unix://$HOME/.colima/docker.sock" 16 | # export DOCKER_HOST="unix:///Users/samm/.colima/default/docker.sock" 17 | 18 | # Tells 'less' not to paginate if less than a page 19 | export LESS="-F -X $LESS" 20 | 21 | # Options to fzf command 22 | export FZF_COMPLETION_OPTS='--border --info=inline' 23 | 24 | # Export a variable that contains the directory this script is sourced from (e.g. /Users/username/icloud docs/somedir/). 25 | # we can't use BASH_SOURCE[0] because it's not available in zsh 26 | # DOTFILES_DIR="$(cd "$(dirname "$0")" && pwd)" 27 | # export DOTFILES_DIR 28 | 29 | # # Global package manager caches to save on disk space 30 | # export PIP_DOWNLOAD_CACHE="${HOME}/Library/Caches/pip" 31 | # export NPM_CONFIG_CACHE="${HOME}/.npm" 32 | 33 | ## Text formatting shortcuts ## 34 | export _FMT_ITL="\e[3m" 35 | export _FMT_BLD="\e[1m" 36 | export _FMT_RED="\e[31m" 37 | export _FMT_GRN="\e[32m" 38 | export _FMT_YLW="\e[33m" 39 | export _FMT_BLU="\e[34m" 40 | export _FMT_MAG="\e[35m" 41 | export _FMT_CYN="\e[36m" 42 | export _FMT_WHT="\e[37m" 43 | export _FMT_BRED="\e[1;31m" 44 | export _FMT_BGRN="\e[1;32m" 45 | export _FMT_BYLW="\e[1;33m" 46 | export _FMT_BBLU="\e[1;34m" 47 | export _FMT_BMAG="\e[1;35m" 48 | export _FMT_BCYN="\e[1;36m" 49 | export _FMT_BWHT="\e[1;37m" 50 | export _FMT_END="\e[0m" # end of line stop formatting 51 | ## 52 | 53 | ## AI/ML ## 54 | 55 | # automatic1111 56 | # export COMMANDLINE_ARGS="${COMMANDLINE_ARGS:-$COMMANDLINE_ARGS --skip-torch-cuda-test --upcast-sampling --opt-sub-quad-attention}" # --use-cpu interrogate 57 | export HF_HUB_ENABLE_HF_TRANSFER=1 58 | export CONDA_SUBDIR=osx-arm64 59 | 60 | # SEE ALSO private exports for Ollama things 61 | 62 | # if running on macos 63 | # if [[ "$OSTYPE" == "darwin"* ]]; then 64 | # BLAS_INCLUDE_DIRS=/opt/homebrew/Cellar/clblast/1.6.2/ 65 | # export CMAKE_ARGS="${CMAKE_ARGS} -DLLAMA_CUDA=off -DLLAMA_METAL=on -DLLAMA_CLBLAST=1" 66 | # fi 67 | 68 | export ENABLE_ANALYTICS=0 69 | -------------------------------------------------------------------------------- /6-zsh_options.rc: -------------------------------------------------------------------------------- 1 | # shellcheck disable=SC2148 disable=SC1090 shell=bash 2 | 3 | ### Options ### 4 | 5 | #unalias run-help 6 | # autoload run-help 7 | # HELPDIR=/usr/local/share/zsh/help 8 | 9 | # Useful for moving / renaming files with glob patterns 10 | # e.g. zmv -W '**/*.js' '**/*.ts' # recursively move anything matching the first pattern to the second pattern 11 | autoload -Uz zmv 12 | 13 | zmodload zsh/complist 14 | zmodload zsh/mapfile # bring mapfile to zsh 15 | # zmodload zsh/attr # attrs info 16 | 17 | # Keep echo "station" > station from clobbering station 18 | setopt NO_CLOBBER 19 | 20 | # Case insensitive globbing 21 | setopt NO_CASE_GLOB 22 | 23 | # Be Reasonable! 24 | setopt NUMERIC_GLOB_SORT 25 | 26 | # I don't know why I never set this before. 27 | setopt EXTENDED_GLOB 28 | 29 | ### Completion Stuff ### 30 | 31 | ## zsh-completion-generator ## 32 | # Requires zgen load RobSis/zsh-completion-generator - see 1-zgen.rc 33 | # Can also be run on the cli using: gencomp <command> 34 | zstyle :plugin:zsh-completion-generator programs ggrep tr cat xattr 35 | ## 36 | 37 | # If we have a glob this will expand it 38 | setopt GLOB_COMPLETE 39 | setopt PUSHD_MINUS 40 | 41 | bindkey -M viins '\C-i' complete-word 42 | 43 | zstyle ':zle:*-word-shell' word-style shell 44 | 45 | zle -N forward-word-shell forward-word-match 46 | zle -N backward-word-shell backward-word-match 47 | 48 | # Faster! (?) 49 | zstyle ':completion::complete:*' use-cache 1 50 | 51 | # case insensitive completion 52 | # NOTE THIS MAY CAUSE PERFORMANCE ISSUES 53 | zstyle ':completion:*' matcher-list '' 'm:{a-zA-Z}={A-Za-z}' 'r:|[._-]=* r:|=*' 'l:|=* r:|=*' 54 | 55 | # tab completion for the middle of words 56 | autoload compinstall 57 | zstyle ':completion:*' matcher-list '' '' '' 'l:|=* r:|=*' 58 | 59 | zstyle ':completion:*' verbose yes 60 | zstyle ':completion:*:descriptions' format '%B%d%b' 61 | zstyle ':completion:*:messages' format '%d' 62 | zstyle ':completion:*:warnings' format 'No matches for: %d' 63 | zstyle ':completion:*' group-name '' 64 | 65 | # AWS specific 66 | zstyle ':completion:*:*:aws' fzf-search-display true 67 | 68 | # Note these need functions to be defined, see functions.rc 69 | zstyle ':completion:*' completer _oldlist _expand _force_rehash _complete 70 | zstyle ':completion:*' completer _expand _force_rehash _complete _ignored 71 | 72 | zstyle ':completion:*:*:docker:*' option-stacking yes 73 | zstyle ':completion:*:*:docker-*:*' option-stacking yes 74 | 75 | # Group completions by type (file, external command, etc) 76 | zstyle ':completion:*:matches' group 'yes' 77 | 78 | # don't mess up url passing as arguments 79 | zstyle ':urlglobber' url-other-schema 80 | 81 | # generate descriptions with magic. 82 | zstyle ':completion:*' auto-description 'specify: %d' 83 | 84 | # Don't prompt for a huge list, page it! 85 | zstyle ':completion:*:default' list-prompt '%S%M matches%s' 86 | 87 | # Don't prompt for a huge list, menu it! 88 | zstyle ':completion:*:default' menu 'select=0' 89 | 90 | # Have the newer files last so I see them first 91 | zstyle ':completion:*' file-sort modification reverse 92 | 93 | # color code completion!!!! Wohoo! 94 | zstyle ':completion:*' list-colors "=(#b) #([0-9]#)*=36=31" 95 | 96 | # don't tab complete hosts (slow and if you have ad-blocking in your hosts file annoying) 97 | #zstyle ':completion:*' hosts off 98 | 99 | unsetopt LIST_AMBIGUOUS 100 | setopt COMPLETE_IN_WORD 101 | 102 | # Separate man page sections. Neat. 103 | zstyle ':completion:*:manuals' separate-sections true 104 | 105 | zstyle ':completion:*' list-separator '»»' 106 | 107 | # complete with a menu for xwindow ids 108 | zstyle ':completion:*:windows' menu on=0 109 | zstyle ':completion:*:expand:*' tag-order all-expansions 110 | 111 | # more errors allowed for large words and fewer for small words 112 | zstyle ':completion:*:approximate:*' max-errors "reply=( $((($#PREFIX + $#SUFFIX) / 3)) )" 113 | 114 | # Errors format 115 | zstyle ':completion:*:corrections' format '%B%d (errors %e)%b' 116 | zstyle ':completion:*:correct:*' insert-unambiguous true 117 | zstyle ':completion:*:correct:*' original true 118 | 119 | # Don't complete stuff already on the line 120 | zstyle ':completion::*:(rm|vi):*' ignore-line true 121 | 122 | # Don't complete directory we are already in (../here) 123 | zstyle ':completion:*' ignore-parents parent pwd 124 | 125 | zstyle ':completion::approximate*:*' prefix-needed false 126 | 127 | # make kill way awesome 128 | zstyle ':completion:*:processes' command 'ps -au$USER -o pid,time,cmd|grep -v "ps -au$USER -o pid,time,cmd"' 129 | zstyle ':completion:*:*:kill:*:processes' list-colors '=(#b) #([0-9]#)[ 0-9:]#([^ ]#)*=01;30=01;31=01;38' 130 | 131 | ### Auto Suggest Settings ### 132 | # Autosuggest highlight colour 133 | export ZSH_AUTOSUGGEST_HIGHLIGHT_STYLE="fg=#7c4fef,bold,underline" 134 | 135 | # Autosuggestions from history, if none use the completion engine. 136 | export ZSH_AUTOSUGGEST_STRATEGY=(history completion) 137 | 138 | # Accept autosuggestion with shift+tab - I use this EVERY day 139 | bindkey '^I' complete-word # tab | complete 140 | bindkey '^[[Z' autosuggest-accept # shift + tab | autosuggest 141 | 142 | # Autocomplete kubectl for k alias 143 | # complete -F __start_kubectl k 144 | # compdef __start_kubectl k 145 | 146 | ### END Autocompletion ### 147 | 148 | ### Key bindings ### 149 | 150 | # Who doesn't want home and end to work? 151 | bindkey '\e[1~' beginning-of-line 152 | bindkey '\e[4~' end-of-line 153 | 154 | # Incremental search is elite! 155 | bindkey -M vicmd "/" history-incremental-search-backward 156 | bindkey -M vicmd "?" history-incremental-search-forward 157 | 158 | # Search based on what you typed in already 159 | bindkey -M vicmd "//" history-beginning-search-backward 160 | bindkey -M vicmd "??" history-beginning-search-forward 161 | 162 | # oh wow! This is killer... try it! 163 | bindkey -M vicmd "q" push-line 164 | 165 | # Ensure that arrow keys work as they should 166 | bindkey '\e[A' up-line-or-history 167 | bindkey '\e[B' down-line-or-history 168 | 169 | bindkey '\eOA' up-line-or-history 170 | bindkey '\eOB' down-line-or-history 171 | 172 | bindkey '\e[C' forward-char 173 | bindkey '\e[D' backward-char 174 | 175 | bindkey '\eOC' forward-char 176 | bindkey '\eOD' backward-char 177 | 178 | # bindkey "5C" emacs-forward-word 179 | # bindkey "5D" backward-word 180 | bindkey "5C" forward-word #control left 181 | bindkey "5D" backward-word #control right 182 | bindkey "^[[1;5C" forward-word #control left in xterm/tmux 183 | bindkey "^[[1;5D" backward-word #control right in xterm/tmux 184 | 185 | bindkey "^[[A" history-search-backward # Search history with up arrow 186 | bindkey "^[[B" history-search-forward # Search history with up arrow 187 | 188 | # gross. Makes Meta-' write '\'' for you 189 | bindkey -s \\e\' \'\\\\\'\' 190 | 191 | # bindkey "^[[3~" delete-char # delete keys 192 | # bindkey "^[3;5~" delete-char # delete keys 193 | 194 | bindkey -M emacs '^H' backward-kill-word # backwards delete word 195 | 196 | # it's like, space AND completion. Gnarlbot. 197 | bindkey -M viins ' ' magic-space 198 | 199 | # Push your line to the stack and run another command then pop it back 200 | bindkey -M vicmd "^q" push-line 201 | 202 | # cd into a directory when you type its name 203 | setopt autocd 204 | 205 | ### Fix slowness of pastes with zsh-syntax-highlighting.zsh ### 206 | # Still needed as of 2023-06-24! 207 | pasteinit() { 208 | # shellcheck disable=SC2296,SC2298 209 | OLD_SELF_INSERT=${${(s.:.)widgets[self-insert]}[2,3]} 210 | zle -N self-insert url-quote-magic 211 | } 212 | 213 | pastefinish() { 214 | zle -N self-insert "$OLD_SELF_INSERT" 215 | } 216 | zstyle :bracketed-paste-magic paste-init pasteinit 217 | zstyle :bracketed-paste-magic paste-finish pastefinish 218 | ### End fix slowness of pastes ### 219 | 220 | # Suggest corrections for commands 221 | setopt correct 222 | 223 | # ### Expand aliases 224 | # globalias() { 225 | # zle _expand_alias 226 | # zle expand-word 227 | # zle self-insert 228 | # } 229 | # zle -N globalias 230 | # # space expands all aliases, including global 231 | # bindkey -M emacs " " globalias 232 | # bindkey -M viins " " globalias 233 | 234 | # # control-space to make a normal space 235 | # bindkey -M emacs "^ " magic-space 236 | # bindkey -M viins "^ " magic-space 237 | 238 | # # normal space during searches 239 | # bindkey -M isearch " " magic-space 240 | 241 | #nav bindkeys 242 | # bindkey '^[[1;5A' nav-up # cmd + up 243 | # bindkey '^[[1;5B' nav-down # cmd + down 244 | # bindkey '^[[1;5C' nav-forward # cmd + right 245 | # bindkey '^[[1;5D' nav-back # cmd + left 246 | # # 247 | 248 | # Bind ctrl+g to run the command 'git status' 249 | _git_status() { 250 | git status 251 | zle redisplay 252 | } 253 | zle -N _git_status 254 | bindkey '^g' '_git_status' # ctrl + g 255 | 256 | # Bind ctrl+l to run sgpt with all text on the command line as a single quoted argument 257 | _sgptline() { 258 | LINE=$LBUFFER 259 | echo -e "\n" 260 | sgpt "'$LINE'" 261 | LBUFFER="" 262 | zle redisplay 263 | } 264 | zle -N _sgptline 265 | bindkey '^l' '_sgptline' # ctrl + l 266 | 267 | 268 | # https://github.com/ohmyzsh/ohmyzsh/wiki/Settings 269 | 270 | # Oh My Zsh will print a red ellipsis to indicate that Zsh is still processing a completion request 271 | export COMPLETION_WAITING_DOTS=true 272 | -------------------------------------------------------------------------------- /7-history.rc: -------------------------------------------------------------------------------- 1 | # shellcheck disable=SC2148 disable=SC1090 shell=bash 2 | 3 | ### History Stuff ### 4 | 5 | # Don't share tab history on iTerm2 6 | #unsetopt inc_append_history 7 | 8 | # Where it gets saved 9 | HISTFILE=~/.history 10 | 11 | # Remember a lot of history (AWESOME) 12 | export SAVEHIST=2000000 13 | export HISTSIZE=2000000 14 | 15 | # Don't overwrite, append! 16 | setopt APPEND_HISTORY 17 | 18 | # Write after each command 19 | # setopt INC_APPEND_HISTORY 20 | 21 | # Killer: share history between multiple shells 22 | setopt SHARE_HISTORY 23 | 24 | # If I type cd and then cd again, only save the last one 25 | setopt HIST_IGNORE_DUPS 26 | 27 | # Even if there are commands in between commands that are the same, still only save the last one 28 | setopt HIST_IGNORE_ALL_DUPS 29 | 30 | # Pretty Obvious. Right? 31 | setopt HIST_REDUCE_BLANKS 32 | 33 | # If a line starts with a space, don't save it. 34 | setopt HIST_IGNORE_SPACE 35 | setopt HIST_NO_STORE 36 | 37 | # When using a hist thing, make a newline show the change before executing it. 38 | setopt HIST_VERIFY 39 | 40 | # Save the time and how long a command ran 41 | setopt EXTENDED_HISTORY 42 | 43 | setopt HIST_SAVE_NO_DUPS 44 | setopt HIST_EXPIRE_DUPS_FIRST 45 | setopt HIST_FIND_NO_DUPS 46 | 47 | # When outputting history, print it out with timestamps and command only 48 | alias history="history -i" 49 | -------------------------------------------------------------------------------- /9-functions.rc: -------------------------------------------------------------------------------- 1 | # shellcheck disable=SC2148 disable=SC1090 shell=bash 2 | 3 | function mkcd { 4 | dir="$*" 5 | mkdir -p "$dir" && cd "$dir" || exit 6 | } 7 | 8 | # change /dev/null to youtube-dl-"$(date +%Y%m%d-%H%M%S)".log if you want logging 9 | 10 | function git_sparse_clone() ( 11 | rurl="$1" localdir="$2" && shift 2 12 | 13 | mkdir -p "$localdir" 14 | cd "$localdir" 15 | 16 | git init 17 | git remote add -f origin "$rurl" 18 | 19 | git sparse-checkout init 20 | 21 | # Loops over remaining args 22 | for i; do 23 | echo "$i" >>.git/info/sparse-checkout 24 | done 25 | 26 | git pull origin main 27 | 28 | git sparse-checkout list 29 | ) 30 | 31 | # A function that checks a git repo for any incorrect casing / cashing clashes and force over-rides local changes if so 32 | git-fix-casing() { 33 | local original_dir 34 | original_dir=$(pwd) 35 | cd "$1" || return 1 36 | sh -c 'git ls-files -ci --exclude-standard -z | xargs -0 git rm --cached' 37 | git status 38 | if [[ $(git ls-files -ci --exclude-standard) ]]; then 39 | echo "There are files with incorrect casing in the git repo" 40 | git reset --hard 41 | git status 42 | fi 43 | cd "$original_dir" || return 1 44 | } 45 | 46 | # wrapper for adding advanced git cli customisation 47 | alias git='git_wrapper' 48 | git_wrapper() { 49 | set +m # Make jobs quiet by default 50 | # If invoked by another function, alias or xargs, interpret it as normal 51 | if [[ -n ${FUNCNAME[*]} ]] || [[ -n $ALIASES ]] || [[ -n $XARGS ]]; then 52 | command git "$@" 53 | return 54 | fi 55 | 56 | # clone with depth=1 if no depth is not specified 57 | if [[ $1 == "clone" ]] && [[ $* != *"--depth"* ]]; then 58 | shift 59 | command git clone --depth=1 "$@" 60 | 61 | # Move into the cloned directory (taking into account the destination directory might be provided) 62 | if [[ $* == *" "* ]]; then 63 | local dest_dir 64 | dest_dir=$(echo "$*" | awk '{print $NF}') 65 | cd "$dest_dir" 66 | else 67 | cd "$(basename "$1" .git)" 68 | fi 69 | 70 | # Update the fetch configuration to track all upstream branches 71 | git config remote.origin.fetch "+refs/heads/*:refs/remotes/origin/*" 72 | 73 | # Fetch all branches in the background, silently 74 | git fetch --all --quiet #&>/dev/null & 75 | 76 | # Move back to the original directory 77 | cd - 78 | else 79 | command git "$@" 80 | fi 81 | set -m # Make jobs verbose again 82 | } 83 | 84 | function gco() { 85 | if [[ -n $1 ]]; then 86 | if [[ $1 == "-b" ]]; then 87 | # shift to remove -b from args 88 | shift 1 89 | fi 90 | local branchname remote_branch_exist 91 | branchname="$1" 92 | 93 | # If the branch name is "main" or "master" just check it out 94 | if [[ "$branchname" == "main" ]] || [[ "$branchname" == "master" ]]; then 95 | command git switch "$branchname" 96 | return 97 | fi 98 | 99 | # check to see if the branch exists locally, if it doesn't offer to create it and check it out otherwise just check it out 100 | if command git show-ref --verify --quiet refs/heads/"$branchname"; then 101 | echo "Branch exists locally, switching branch..." 102 | command git switch "$branchname" 103 | else 104 | echo "Checking if branch exists remotely..." 105 | remote_branch_exist=$(command git ls-remote --heads origin "$branchname") 106 | if [ -n "$remote_branch_exist" ]; then 107 | echo "Branch exists remotely, checking out and pulling..." 108 | command git fetch # origin "$branchname" 109 | # command git checkout "$branchname" "origin/${branchname}" || echo "Error - available branches: $(git branch -v -a)" 110 | command git switch -c "$branchname" "origin/${branchname}" || echo "Error - available branches: $(git branch -v -a)" 111 | command git pull 112 | else 113 | # If the branch doesn't exist either locally or remotely 114 | echo "Branch doesn't exist locally or remotely, creating and switching..." 115 | command git switch -c "$branchname" 116 | fi 117 | fi 118 | else 119 | # shellcheck disable=SC2033 120 | command git branch --sort=-committerdate | fzf --header 'Checkout Recent Branch' --preview 'git diff --color=always {1}' --pointer='>' | xargs command git switch 121 | echo -e "${_FMT_ITL}Hint: You can check remote branches with 'gcor'${_FMT_END}" 122 | fi 123 | } 124 | 125 | function gcor() { 126 | # list all remote branches and select one with fzf git branch -v -a 127 | command git branch -v -a | fzf --header 'Checkout Remote Branch' --preview 'git diff --color=always {1}' --pointer='>' | awk '{print $1}' | xargs command git checkout 128 | } 129 | 130 | function gbd() { 131 | if [[ -n $* ]]; then 132 | command git branch -d "$@" 133 | else 134 | # shellcheck disable=SC2033 135 | command git branch --sort=-committerdate | fzf --header 'Delete Git Branch' --preview 'git diff --color=always {1}' --pointer='>' | xargs command git branch -d 136 | fi 137 | } 138 | 139 | # generate_commit_msg() { 140 | # # This function generates a commit message using the ollama API 141 | # # Map the function to a keybinding (e.g., gcm) in your .zshrc file: 142 | # # bindkey '^Xg' generate_commit_msg 143 | # local -r model="tinydolphin:1.1b- v2.8-q5_ K_ M" 144 | # local -r prompt=$(git diff --cached --name-only | xargs -I{} echo "Why did you change {}?") 145 | # local -r api_url="http://localhost:11434/api/generate" 146 | # } 147 | 148 | # A function that provides an untracked_files check for other functions 149 | function __staged_changes() { 150 | # Display all changes including untracked files 151 | local STAGED_FILES 152 | STAGED_FILES=$(git diff --cached --name-only) 153 | if [[ -n "$STAGED_FILES" ]]; then 154 | echo "Staged files:" 155 | echo "$STAGED_FILES" 156 | else 157 | echo "No staged changes to add." 158 | # Ask the user if they want to stage all changes 159 | echo "Do you want to add all changes to the commit? (y/n)" 160 | read -r yn 161 | if [[ "$yn" =~ ^[Yy]$ ]]; then 162 | # Stage all changes 163 | git add . 164 | else 165 | echo "Staging cancelled by the user." 166 | return 1 # Return failure to indicate staging was not done 167 | fi 168 | fi 169 | } 170 | 171 | function checkout-hotfix() { 172 | local PREFIX="hotfix-${USER}" 173 | local DATESTAMP 174 | DATESTAMP=$(date +%Y-%m-%d) 175 | # If the hotfix branch already exists, append a number to the branch name, if the number already exists increment it 176 | if command git branch -a | grep -q "$PREFIX-$DATESTAMP"; then 177 | local COUNT=1 178 | while git branch -a | grep -q "$PREFIX-$DATESTAMP-$COUNT"; do 179 | COUNT=$((COUNT + 1)) 180 | done 181 | command git checkout -b "${PREFIX}-${DATESTAMP}-${COUNT}" 182 | else 183 | command git checkout -b "${PREFIX}-${DATESTAMP}" 184 | fi 185 | } 186 | 187 | function commit-hotfix() { 188 | local DATESTAMP 189 | DATESTAMP=$(date +%Y/%m/%d) 190 | local GIT_ARGS=() 191 | local MESSAGE="" 192 | 193 | # Check for the '-n' flag and prepare commit options accordingly 194 | if [[ "$1" == "-n" ]]; then 195 | GIT_ARGS+=("-n") # Add '-n' to the git commit command options 196 | shift # Remove '-n' from the argument list so it's not included in the commit message 197 | fi 198 | 199 | # After shifting '-n', all remaining arguments form the commit message 200 | MESSAGE="$*" 201 | 202 | # Attempt to stage changes; if the user cancels, abort the commit 203 | if ! __staged_changes; then 204 | echo "Commit aborted due to no changes being staged." 205 | return 1 206 | fi 207 | 208 | # Proceed with commit 209 | local CURRENT_BRANCH 210 | CURRENT_BRANCH=$(git rev-parse --abbrev-ref HEAD) 211 | git commit "${GIT_ARGS[@]}" -m "Hotfix-${DATESTAMP} -- ${MESSAGE}" 212 | 213 | # Check if the commit was successful before attempting to push 214 | if git rev-parse --verify "$CURRENT_BRANCH" >/dev/null 2>&1; then 215 | git push --set-upstream origin "$CURRENT_BRANCH" 216 | echo "Changes committed and pushed to $CURRENT_BRANCH." 217 | else 218 | echo "Failed to push changes. Branch $CURRENT_BRANCH does not exist." 219 | fi 220 | } 221 | 222 | function checkout-jira() { 223 | JIRA_BRANCH="IF-${1}-${USER}-$(date +%Y-%m-%d)" 224 | # If the JIRA branch already exists, append the current time to the branch name 225 | if command git branch -a | grep -q "remotes/origin/${JIRA_BRANCH}" || command git branch -a | grep -q "${JIRA_BRANCH}"; then 226 | JIRA_BRANCH="${JIRA_BRANCH}-$(date +%H-%M-%S)" 227 | fi 228 | command git checkout -b "${JIRA_BRANCH}" 229 | } 230 | 231 | function commit-jira() { 232 | local GIT_ARGS=() 233 | local MESSAGE="" 234 | local BRANCH_PREFIX CURRENT_BRANCH 235 | 236 | # Check for the '-n' flag and prepare commit options accordingly 237 | if [[ "$1" == "-n" ]]; then 238 | GIT_ARGS+=("-n") # Add '-n' to the git commit command options 239 | shift # Remove '-n' from the argument list so it's not included in the commit message 240 | fi 241 | 242 | # After shifting '-n', all remaining arguments form the commit message 243 | MESSAGE="$*" 244 | 245 | # Call the updated function to check and stage all changes 246 | if ! __staged_changes; then 247 | echo "Commit aborted due to no changes being staged." 248 | return 1 249 | fi 250 | 251 | # add the branch prefix to the message (e.g. IF-1234 -- message) 252 | CURRENT_BRANCH=$(git rev-parse --abbrev-ref HEAD) 253 | BRANCH_PREFIX=$(echo "$CURRENT_BRANCH" | cut -d'-' -f1 -f2) 254 | MESSAGE="${BRANCH_PREFIX} -- ${MESSAGE}" 255 | 256 | # Proceed with commit 257 | if ! git diff --cached --quiet; then 258 | echo "No changes to commit." 259 | # Check if the branch exists on the remote 260 | if ! git ls-remote --heads origin "$CURRENT_BRANCH" | grep -q "$CURRENT_BRANCH"; then 261 | # Offer to push and track the branch if it doesn't exist on the remote 262 | echo "Current branch '$CURRENT_BRANCH' does not exist on the remote. Would you like to push it? (y/n)" 263 | read -r yn 264 | if [[ "$yn" =~ ^[Yy]$ ]]; then 265 | git push --set-upstream origin "$CURRENT_BRANCH" 266 | echo "Branch pushed and tracked on remote." 267 | else 268 | echo "Push cancelled by the user." 269 | fi 270 | fi 271 | else 272 | # Execute the commit with any options and the message 273 | git commit "${GIT_ARGS[@]}" -m "$MESSAGE" 274 | git push --set-upstream origin "$CURRENT_BRANCH" 275 | echo "Changes committed and pushed to '$CURRENT_BRANCH'." 276 | fi 277 | } 278 | 279 | # Outputs the name of the current branch 280 | # Usage example: git pull origin "$(git_current_branch)" 281 | # Using '--quiet' with 'symbolic-ref' will not cause a fatal error (128) if 282 | # it's not a symbolic ref, but in a Git repo. 283 | function git_current_branch() { 284 | local ref 285 | ref=$(command git symbolic-ref --quiet HEAD 2>/dev/null) 286 | local ret=$? 287 | if [[ $ret != 0 ]]; then 288 | [[ $ret == 128 ]] && return # no git repo. 289 | ref=$(command git rev-parse --short HEAD 2>/dev/null) || return 290 | fi 291 | echo "${ref#refs/heads/}" 292 | } 293 | 294 | function pr-checkout() { 295 | local jq_template pr_number 296 | 297 | jq_template='"''#\(.number) - \(.title)''\t''Author: \(.user.login)\n''Created: \(.created_at)\n''Updated: \(.updated_at)\n\n''\(.body)''"' 298 | 299 | pr_number=$( 300 | gh api 'repos/:owner/:repo/pulls' | 301 | jq ".[] | $jq_template" | 302 | sed -e 's/"\(.*\)"/\1/' -e 's/\\t/\t/' | 303 | fzf \ 304 | --with-nth=1 \ 305 | --delimiter='\t' \ 306 | --preview='echo -e {2}' \ 307 | --preview-window=top:wrap | 308 | sed 's/^#\([0-9]\+\).*/\1/' 309 | ) 310 | 311 | if [ -n "$pr_number" ]; then 312 | gh pr checkout "$pr_number" 313 | fi 314 | } 315 | 316 | function git_add_global_prepush_hook() { 317 | local repo_path=$1 318 | local branch_name=$2 319 | local hooks_path="$repo_path/.git/hooks" 320 | 321 | # Check if the repo_path is a Git repository 322 | if [ ! -d "$repo_path/.git" ]; then 323 | echo "$repo_path is not a Git repository" 324 | return 1 325 | fi 326 | 327 | # Create the pre-push hook if it doesn't exist 328 | if [ ! -f "$hooks_path/pre-push" ]; then 329 | touch "$hooks_path/pre-push" 330 | chmod +x "$hooks_path/pre-push" 331 | fi 332 | 333 | # Add the code to the pre-push hook 334 | cat <<EOF >>"$hooks_path/pre-push" 335 | #!/usr/bin/env bash 336 | 337 | # This script can be run as a pre-push hook locally on repositories to add messages / ensure we're not pushing to the wrong branch etc... 338 | 339 | branch_name=$(git symbolic-ref --short HEAD) 340 | if [ "$branch_name" == "main" ] || [ "$branch_name" == "master" ]; then 341 | echo "WARNING: You are pushing to the $branch_name branch!" 342 | read -r -p "Are you sure you want to push to $branch_name? [y/N] " response 343 | if [[ "$response" =~ ^([yY][eE][sS]|[yY])$ ]]; then 344 | echo "$response - Pushing to $branch_name" 345 | else 346 | echo "Aborting push" 347 | exit 1 348 | fi 349 | fi 350 | EOF 351 | 352 | echo "Global pre-push hook added to $repo_path" 353 | } 354 | 355 | # Gets the number of commits ahead from remote 356 | function git_commits_ahead() { 357 | if command git rev-parse --git-dir &>/dev/null; then 358 | local commits 359 | commits="$(git rev-list --count @{upstream}..HEAD)" 360 | if [[ "$commits" != 0 ]]; then 361 | echo "$ZSH_THEME_GIT_COMMITS_AHEAD_PREFIX$commits$ZSH_THEME_GIT_COMMITS_AHEAD_SUFFIX" 362 | fi 363 | fi 364 | } 365 | 366 | # Gets the number of commits behind remote 367 | function git_commits_behind() { 368 | if command git rev-parse --git-dir &>/dev/null; then 369 | local commits 370 | commits="$(git rev-list --count HEAD..@{upstream})" 371 | if [[ "$commits" != 0 ]]; then 372 | echo "$ZSH_THEME_GIT_COMMITS_BEHIND_PREFIX$commits$ZSH_THEME_GIT_COMMITS_BEHIND_SUFFIX" 373 | fi 374 | fi 375 | } 376 | 377 | # Outputs if current branch is ahead of remote 378 | function git_prompt_ahead() { 379 | if [[ -n "$(command git rev-list origin/"$(git_current_branch)"..HEAD 2>/dev/null)" ]]; then 380 | echo "$ZSH_THEME_GIT_PROMPT_AHEAD" 381 | fi 382 | } 383 | 384 | # Outputs if current branch is behind remote 385 | function git_prompt_behind() { 386 | if [[ -n "$(command git rev-list HEAD..origin/"$(git_current_branch)" 2>/dev/null)" ]]; then 387 | echo "$ZSH_THEME_GIT_PROMPT_BEHIND" 388 | fi 389 | } 390 | 391 | # Outputs if current branch exists on remote or not 392 | function git_prompt_remote() { 393 | if [[ -n "$(command git show-ref origin/"$(git_current_branch)" 2>/dev/null)" ]]; then 394 | echo "$ZSH_THEME_GIT_PROMPT_REMOTE_EXISTS" 395 | else 396 | echo "$ZSH_THEME_GIT_PROMPT_REMOTE_MISSING" 397 | fi 398 | } 399 | 400 | # Formats prompt string for current git commit short SHA 401 | function git_prompt_short_sha() { 402 | local SHA 403 | SHA=$(command git rev-parse --short HEAD 2>/dev/null) && echo "$ZSH_THEME_GIT_PROMPT_SHA_BEFORE$SHA$ZSH_THEME_GIT_PROMPT_SHA_AFTER" 404 | } 405 | 406 | # Formats prompt string for current git commit long SHA 407 | function git_prompt_long_sha() { 408 | local SHA 409 | SHA=$(command git rev-parse HEAD 2>/dev/null) && echo "$ZSH_THEME_GIT_PROMPT_SHA_BEFORE$SHA$ZSH_THEME_GIT_PROMPT_SHA_AFTER" 410 | } 411 | 412 | # # Get the status of the working tree 413 | # function git_prompt_status() { 414 | # local INDEX STATUS 415 | # INDEX=$(command git status --porcelain -b 2>/dev/null) 416 | # STATUS="" 417 | # if eval "$(echo "$INDEX" | command grep -E '^\?\? ' &>/dev/null)"; then 418 | # STATUS="$ZSH_THEME_GIT_PROMPT_UNTRACKED$STATUS" 419 | # fi 420 | # if eval "$(echo "$INDEX" | grep '^A ' &>/dev/null)"; then 421 | # STATUS="$ZSH_THEME_GIT_PROMPT_ADDED$STATUS" 422 | # elif eval "$(echo "$INDEX" | grep '^M ' &>/dev/null)"; then 423 | # STATUS="$ZSH_THEME_GIT_PROMPT_ADDED$STATUS" 424 | # fi 425 | # if eval "$(echo "$INDEX" | grep '^ M ' &>/dev/null)"; then 426 | # STATUS="$ZSH_THEME_GIT_PROMPT_MODIFIED$STATUS" 427 | # elif eval "$(echo "$INDEX" | grep '^AM ' &>/dev/null)"; then 428 | # STATUS="$ZSH_THEME_GIT_PROMPT_MODIFIED$STATUS" 429 | # elif eval "$(echo "$INDEX" | grep '^ T ' &>/dev/null)"; then 430 | # STATUS="$ZSH_THEME_GIT_PROMPT_MODIFIED$STATUS" 431 | # fi 432 | # if eval "$(echo "$INDEX" | grep '^R ' &>/dev/null)"; then 433 | # STATUS="$ZSH_THEME_GIT_PROMPT_RENAMED$STATUS" 434 | # fi 435 | # if eval "$(echo "$INDEX" | grep '^ D ' &>/dev/null)"; then 436 | # STATUS="$ZSH_THEME_GIT_PROMPT_DELETED$STATUS" 437 | # elif eval "$(echo "$INDEX" | grep '^D ' &>/dev/null)"; then 438 | # STATUS="$ZSH_THEME_GIT_PROMPT_DELETED$STATUS" 439 | # elif eval "$(echo "$INDEX" | grep '^AD ' &>/dev/null)"; then 440 | # STATUS="$ZSH_THEME_GIT_PROMPT_DELETED$STATUS" 441 | # fi 442 | # if eval "$(command git rev-parse --verify refs/stash >/dev/null 2>&1)"; then 443 | # STATUS="$ZSH_THEME_GIT_PROMPT_STASHED$STATUS" 444 | # fi 445 | # if eval "$(echo "$INDEX" | grep '^UU ' &>/dev/null)"; then 446 | # STATUS="$ZSH_THEME_GIT_PROMPT_UNMERGED$STATUS" 447 | # fi 448 | # if eval "$(echo "$INDEX" | grep '^## [^ ]\+ .*ahead' &>/dev/null)"; then 449 | # STATUS="$ZSH_THEME_GIT_PROMPT_AHEAD$STATUS" 450 | # fi 451 | # if eval "$(echo "$INDEX" | grep '^## [^ ]\+ .*behind' &>/dev/null)"; then 452 | # STATUS="$ZSH_THEME_GIT_PROMPT_BEHIND$STATUS" 453 | # fi 454 | # if eval "$(echo "$INDEX" | grep '^## [^ ]\+ .*diverged' &>/dev/null)"; then 455 | # STATUS="$ZSH_THEME_GIT_PROMPT_DIVERGED$STATUS" 456 | # fi 457 | # echo "$STATUS" 458 | # } 459 | 460 | # # TODO: replace this with something more standard, this was a temporary workaround for poor performance of the stock oh-my-zsh git plugin 461 | # # Compares the provided version of git to the version installed and on path 462 | # # Outputs -1, 0, or 1 if the installed version is less than, equal to, or 463 | # # greater than the input version, respectively. 464 | # function git_compare_version() { 465 | # local INPUT_GIT_VERSION INSTALLED_GIT_VERSION 466 | # # shellcheck disable=SC2206,SC2207,SC2296 467 | # INPUT_GIT_VERSION=(${(s/./)1}) 468 | # # shellcheck disable=SC2206,SC2207,SC2296 469 | # INSTALLED_GIT_VERSION=($(command git --version 2>/dev/null)) 470 | # # shellcheck disable=SC2206,SC2207,SC2296 471 | # INSTALLED_GIT_VERSION=(${(s/./)INSTALLED_GIT_VERSION[3]}) 472 | 473 | # for i in {1..3}; do 474 | # if [[ ${INSTALLED_GIT_VERSION[$i]} -gt ${INPUT_GIT_VERSION[$i]} ]]; then 475 | # echo 1 476 | # return 0 477 | # fi 478 | # if [[ ${INSTALLED_GIT_VERSION[$i]} -lt ${INPUT_GIT_VERSION[$i]} ]]; then 479 | # echo -1 480 | # return 0 481 | # fi 482 | # done 483 | # echo 0 484 | # } 485 | 486 | # Outputs the name of the current user 487 | # Usage example: $(git_current_user_name) 488 | function git_current_user_name() { 489 | command git config user.name 2>/dev/null 490 | } 491 | 492 | # Outputs the email of the current user 493 | # Usage example: $(git_current_user_email) 494 | function git_current_user_email() { 495 | command git config user.email 2>/dev/null 496 | } 497 | 498 | # Clean up the namespace slightly by removing the checker function 499 | # unfunction git_compare_version 500 | 501 | #source /usr/local/etc/profile.d/autojump.sh 502 | 503 | pdfcompress() { 504 | gs -q -dNOPAUSE -dBATCH -dSAFER -sDEVICE=pdfwrite -dCompatibilityLevel=1.3 -dPDFSETTINGS=/screen -dEmbedAllFonts=true -dSubsetFonts=true -dColorImageDownsampleType=/Bicubic -dColorImageResolution=144 -dGrayImageDownsampleType=/Bicubic -dGrayImageResolution=144 -dMonoImageDownsampleType=/Bicubic -dMonoImageResolution=144 -sOutputFile="$1".compressed.pdf "$1" 505 | } 506 | 507 | # Usage: mv oldfilename 508 | # If you call mv without the second parameter it will prompt you to edit the filename on command line. 509 | # Original mv is called when it's called with more than one argument. 510 | # It's useful when you want to change just a few letters in a long name. 511 | 512 | function mv() { 513 | if [ "$#" -ne 1 ]; then 514 | command mv "$@" 515 | return 516 | fi 517 | if [ ! -f "$1" ]; then 518 | command file "$@" 519 | return 520 | fi 521 | 522 | read -ei "$1" newfilename 523 | mv -v "$1" "$newfilename" 524 | } 525 | 526 | _force_rehash() { 527 | ((CURRENT == 1)) && rehash 528 | return 1 # Because we didn't really complete anything 529 | } 530 | 531 | # This was causing tab complete errors such as zle-line-init:1: command not found 532 | # edit-command-output() { 533 | # BUFFER=$(eval "$BUFFER") 534 | # CURSOR=0 535 | # } 536 | # zle -N edit-command-output 537 | 538 | __mkdir() { if [[ ! -d $1 ]]; then mkdir -p "$1"; fi; } 539 | 540 | tch() { 541 | for x in "$@"; do 542 | __mkdir "${x:h}" 543 | done 544 | touch "$@" 545 | } 546 | 547 | # Interactive git diff 548 | function git-diff() { 549 | git log --graph --color=always \ 550 | --format="%C(auto)%h%d %s %C(black)%C(bold)%cr" "$@" | 551 | fzf --ansi --preview "echo {} \ 552 | | grep -o '[a-f0-9]\{7\}' \ 553 | | head -1 \ 554 | | xargs -I % sh -c 'git show --color=always %'" \ 555 | --bind "enter:execute: 556 | (grep -o '[a-f0-9]\{7\}' \ 557 | | head -1 \ 558 | | xargs -I % sh -c 'git show --color=always % \ 559 | | less -R') << 'FZF-EOF' 560 | {} 561 | FZF-EOF" 562 | } 563 | 564 | # Github 565 | # Deletes workflow logs from a given repo older than 1 month 566 | # e.g. USER=myuser REPO=myrepo ghac 567 | function ghac() { 568 | DATE=$(date -v "-1m" +"%Y-%m-%d") gh api "repos/${USER}/${REPO}/actions/runs" --paginate -q '.workflow_runs[] | select (.run_started_at <= "env.DATE") | (.id)' | 569 | xargs -n1 -I % gh api "repos/${USER}/${REPO}/actions/runs"/% -X DELETE 570 | } 571 | 572 | function github_actions_watcher() { 573 | # https://github.com/nedbat/watchgha 574 | TOKEN_BACKUP=$GITHUB_TOKEN 575 | unset GITHUB_TOKEN 576 | watch_gha_runs "$@" \ 577 | "$(git remote get-url origin)" \ 578 | "$(git rev-parse --abbrev-ref HEAD)" 579 | GITHUB_TOKEN=$TOKEN_BACKUP 580 | } 581 | 582 | # Git checkout new branch, git add, git commit, git push in all subdirectories matching a pattern 583 | function git_add_commit_push() { 584 | if [[ -z $1 ]] || [[ -z "$2" ]] || [[ -z "$3" ]]; then 585 | echo 'You must pass three paramters, branchname, commit message, dir match - e.g. "my-branch" "commit message" ABC*' 586 | fi 587 | BRANCHNAME="$1" 588 | COMMITNAME="$2" 589 | MATCHDIRS="$3" 590 | for dir in $MATCHDIRS; do 591 | ( 592 | cd "$dir" && 593 | git checkout -b "$BRANCHNAME" && 594 | git add . && 595 | git commit -n -m "$COMMITNAME" && 596 | git push 597 | ) 598 | done 599 | } 600 | 601 | # Interactive cd using fzf 602 | function fcd() { 603 | local dir 604 | 605 | while true; do 606 | # exit with ^D 607 | dir="$(ls -a1p | grep '/$' | grep -v '^./$' | fzf --height 40% --reverse --no-multi --preview 'pwd' --preview-window=up,1,border-none --no-info)" 608 | if [[ -z "${dir}" ]]; then 609 | break 610 | else 611 | cd "${dir}" || exit 612 | fi 613 | done 614 | } 615 | 616 | # list env variables with fzf 617 | list_env() { 618 | var=$(printenv | cut -d= -f1 | fzf) && 619 | echo "$var=$(printenv "$var")" && 620 | unset var 621 | } 622 | 623 | # Encryption (using age) 624 | 625 | # File with generated password 626 | encrypt_file_pw() { 627 | # Suggest installing age if not installed 628 | if ! command -v age &>/dev/null; then 629 | echo "age could not be found. Install it with 'brew install age'" 630 | return 631 | else 632 | age -p "$1" -o "${1}.age" 633 | fi 634 | } 635 | 636 | conda_setup() { 637 | # CONDA - is managed via a function when needed 638 | # >>> conda initialize >>> 639 | # !! Contents within this block are managed by 'conda init' !! 640 | __conda_setup="$('/Users/samm/miniconda3/bin/conda' 'shell.zsh' 'hook' 2>/dev/null)" 641 | if [ $? -eq 0 ]; then 642 | eval "$__conda_setup" 643 | else 644 | if [ -f "/Users/samm/miniconda3/etc/profile.d/conda.sh" ]; then 645 | . "/Users/samm/miniconda3/etc/profile.d/conda.sh" 646 | else 647 | export PATH="/Users/samm/miniconda3/bin:$PATH" 648 | fi 649 | fi 650 | unset __conda_setup 651 | # <<< conda initialize <<< 652 | } 653 | 654 | function update_asdf() { 655 | asdf update 656 | asdf plugin-update --all 657 | } 658 | 659 | # Prompts for a name and a password and stores it in keychain 660 | keychain_password_prompt() { 661 | echo "Enter a name for the password:" 662 | read -r name 663 | echo "Enter the password:" 664 | stty -echo # disable echoing the password 665 | read -r password 666 | security add-generic-password -s "$name" -a "$(whoami)" -w "$password" 667 | stty echo # re-enable echoing 668 | } 669 | 670 | # Reads a password from keychain and outputs it 671 | # usage: keychain_password <service name to match on> <account> 672 | keychain_password() { 673 | stty -echo # disable echoing the password 674 | security find-generic-password -s "$1" -a "$(whoami)" -w 675 | stty echo # re-enable echoing 676 | } 677 | 678 | ### AWS Auth ### 679 | # aws-profile uses s2a-keychain to login to AWS using saml2aws and then exports the AWS_PROFILE variable 680 | # Requires saml2aws, fzf, and keychain_password 681 | alias aad=aws-profile 682 | alias awslogin=aws-profile 683 | alias aws-azure-login=aws-profile 684 | 685 | # shellcheck disable=SC2068 disable=SC2046 disable=SC2145 686 | function s2a() { 687 | eval $($(command saml2aws) script --shell=bash --profile=$@) 688 | } 689 | 690 | # Logs into AWS using saml2aws and a password stored in keychain 691 | function s2a-keychain() { 692 | local IDPPW INPUT_PROFILE KEYCHAIN_ITEM 693 | KEYCHAIN_ITEM=${KEYCHAIN_ITEM:-"saml2awspw"} 694 | INPUT_PROFILE=${1:-"default"} 695 | CHECK_SCREENRECORDER=${CHECK_SCREENRECORDER:-"false"} 696 | 697 | IDPPW=$(keychain_password "$KEYCHAIN_ITEM") # requires mfa and keychain authentication 698 | 699 | aws configure list --profile "${INPUT_PROFILE}" 700 | 701 | # Login to AWS 702 | # /Users/samm/git/saml2aws-fork/dist/saml2aws_darwin_arm64/saml2aws 703 | saml2aws login -a "$INPUT_PROFILE" \ 704 | --skip-prompt \ 705 | --password="$IDPPW" \ 706 | --profile="$INPUT_PROFILE" 707 | # --skip-verify 708 | export AWS_PROFILE="$INPUT_PROFILE" 709 | export AWSCLIPARAMS="--profile=${INPUT_PROFILE}" 710 | export AWS_DEFAULT_REGION=ap-southeast-2 711 | unset IDPPW 712 | } 713 | 714 | # Interactively export AWS_PROFILE 715 | function aws-profile() { 716 | # if provided an argument, use that as the profile 717 | if [[ -n $1 ]]; then 718 | export AWS_PROFILE=$1 719 | export AWSCLIPARAMS="--profile=$1" 720 | else 721 | # otherwise, use fzf to select a profile 722 | AWS_PROFILE=$(grep profile "${HOME}"/.aws/config | 723 | awk '{print $2}' | sed 's,],,g' | 724 | fzf --layout reverse --height=30% --border) 725 | export AWS_PROFILE 726 | export AWSCLIPARAMS="--profile=${AWS_PROFILE}" 727 | fi 728 | s2a-keychain "$AWS_PROFILE" 729 | 730 | echo "[You are now using the ${AWS_PROFILE} profile]" 731 | } 732 | 733 | ### END AWS Auth ### 734 | 735 | # A function that checks ssh-add and adds my keys if they're not already added 736 | function ssh-add-keys() { 737 | if ! ssh-add -l | grep -qe 'ED25519\|RSA'; then 738 | ssh-add --apple-use-keychain ~/.ssh/id_*.key 739 | fi 740 | } 741 | 742 | function tmux_create() { 743 | SESSION="$1" 744 | echo "Creating tmux session ${SESSION}" 745 | tmux new-session -d -s "$SESSION" 746 | tmux switch-client -t "$SESSION" 747 | } 748 | 749 | function tmux_attach() { 750 | # If not provided an argument, use fzf to select a session 751 | if [[ -n $1 ]]; then 752 | SESSION="$1" 753 | 754 | # check if there are any sessions 755 | if [[ -z $(tmux ls) ]]; then 756 | echo "No tmux sessions found" 757 | return 1 758 | fi 759 | else 760 | SESSION=$(tmux ls | grep -Eo '^[0-9]+.*' | fzf --layout reverse --height=40% --border | awk '{print $1}') 761 | fi 762 | echo "Attaching to tmux session ${SESSION}" 763 | tmux switch-client -t "$SESSION" 764 | } 765 | 766 | clean_string() { 767 | # Escape special characters in a string such as $, ", ', `, \, and newline. 768 | # Usage: escape_string "string to escape" 769 | local string="${1}" 770 | local escaped_string 771 | escaped_string=$(printf '%q' "${string}") 772 | echo "${escaped_string}" 773 | } 774 | 775 | docker_login_ghcr() { 776 | # Dependencies: gh 777 | set -e 778 | 779 | if [ ! -f ~/.docker/config.json ]; then 780 | echo '{"credsStore": "desktop","credHelpers": {"docker.pkg.github.com": "gh","ghcr.io": "gh"}}' >~/.docker/config.json 781 | fi 782 | 783 | cmd="${1}" 784 | if [ "erase" = "${cmd}" ]; then 785 | cat - >/dev/null 786 | exit 0 787 | fi 788 | if [ "store" = "${cmd}" ]; then 789 | cat - >/dev/null 790 | exit 0 791 | fi 792 | if [ "get" != "${cmd}" ]; then 793 | exit 1 794 | fi 795 | 796 | host="$(cat -)" 797 | host="${host#https://}" 798 | host="${host%/}" 799 | if [ "${host}" != "ghcr.io" ] && [ "${host}" != "docker.pkg.github.com" ]; then 800 | exit 1 801 | fi 802 | 803 | token="$(gh config get -h github.com oauth_token)" 804 | if [ -z "${token}" ]; then 805 | exit 1 806 | fi 807 | 808 | printf '{"Username":"%s", "Secret":"%s"}\n' "$(gh config get -h github.com user)" "${token}" 809 | } 810 | 811 | docker_inspect_all() { 812 | # Get the IDs of all running containers 813 | local container_ids=("$(docker ps -q)") 814 | 815 | # Iterate over each container ID 816 | for container_id in "${container_ids[@]}"; do 817 | # Run docker inspect command and store the output in a variable 818 | local inspect_output=$(docker inspect --format='{{json .}}' "$container_id") 819 | 820 | # Extract container name and remove leading '/' 821 | local container_name=$(jq -r '.Name[1:]' <<<"$inspect_output") 822 | 823 | # Extract container status, creation timestamp, and IP addresses 824 | local container_status=$(jq -r '.State.Status' <<<"$inspect_output") 825 | local created_timestamp=$(jq -r '.Created' <<<"$inspect_output") 826 | local ip_address=$(jq -r '.NetworkSettings.Networks[].IPAddress' <<<"$inspect_output") 827 | local ipv6_address=$(jq -r '.NetworkSettings.Networks[].GlobalIPv6Address' <<<"$inspect_output") 828 | 829 | # Extract forwarded ports 830 | local ports=$(jq -r '.NetworkSettings.Ports | to_entries[] | .key + " -> " + .value[0].HostPort' <<<"$inspect_output") 831 | 832 | # Display the extracted information 833 | echo "Container ID: $container_id" 834 | echo "Container Name: $container_name" 835 | echo "Container Status: $container_status" 836 | echo "Created Timestamp: $created_timestamp" 837 | echo "IP Address: $ip_address" 838 | echo "IPv6 Address: $ipv6_address" 839 | echo "Forwarded Ports: $ports" 840 | echo "-----------------------" 841 | done 842 | } 843 | 844 | ps-docker() { 845 | # ps -aux but with the container name and nice formatting 846 | echo -e "Processing docker containers, this may take a moment...\n" 847 | { 848 | echo -e "CONTAINER NAME\tUSER\tPID\t%CPU\t%MEM\tRUN TIME\tCOMMAND" 849 | ps -aux | awk '{print $2}' | while read pid; do 850 | container_id=$(grep -Eo "docker-([a-f0-9]{64})\.scope" /proc/"$pid"/cgroup 2>/dev/null | head -n1 | grep -Eo "([a-f0-9]{64})") 851 | if [ ! -z "$container_id" ]; then 852 | container_name=$(docker ps --no-trunc | grep "$container_id" | awk '{print $NF}') 853 | if [ ! -z "$container_name" ]; then 854 | ps -p "$pid" -o user,pid,%cpu,%mem,etime,cmd --no-headers | awk -v cn="$container_name" '{printf "%-20s\t%-8s\t%-8s\t%-5s\t%-5s\t%-10s\t%-40s\n", cn, $1, $2, $3, $4, $5, substr($0, index($0,$6))}' 855 | fi 856 | fi 857 | done 858 | } | awk 'BEGIN {OFS="\t"; prev="none"} NR==1 {print} NR>1 {split($0,a,"\t"); if (a[1]!=prev && NR>2) print "--------------------\t\t\t\t\t\t\t"; print; prev=a[1]}' 859 | } 860 | 861 | # 3D Printing 862 | function cura-backup() { 863 | # Zip up the latest cura config from the newest number cura config directory (~/Library/Application\ Support/cura/(number.number) (e.g. 4.8) 864 | # and copy it to the cloud backup folder 865 | local cura_base_dir="${HOME}/Library/Application Support/cura" 866 | local destination="${HOME}/Library/Mobile Documents/com~apple~CloudDocs/Backups/3dprinting/cura" 867 | local latest_version_dir="$(ls -d "${cura_base_dir}"/*/ | tail -n1)" 868 | 869 | # zip it up with the date 870 | local date="$(date +%Y-%m-%d)" 871 | local zip_file="${destination}/cura-${date}.zip" 872 | zip -r "${zip_file}" "${latest_version_dir}" 873 | echo "Created ${zip_file}" 874 | } 875 | 876 | function ripSearch() { 877 | # 1. Search for text in files using Ripgrep 878 | # 2. Interactively narrow down the list using fzf 879 | # 3. Open the file in vscode 880 | 881 | while getopts n OPTION; do 882 | case "${OPTION}" in 883 | n) NEW_WINDOW="--new-window" ;; 884 | *) echo "ERROR: we only support -n" && exit 1 ;; 885 | esac 886 | done 887 | shift $((OPTIND - 1)) 888 | 889 | : "${NEW_WINDOW:=""}" 890 | 891 | # Allow the function to be cancelled with Ctrl-C, but don't exit the shell 892 | trap 'return 1' INT 893 | 894 | ARGLIST="" 895 | while IFS=: read -rA SELECTED; do 896 | if [ "${#SELECTED[@]}" -gt 0 ]; then 897 | ARGLIST+="--goto ${SELECTED[0]}:${SELECTED[1]} " 898 | fi 899 | done < <( 900 | rg --color=always --line-number --no-heading --smart-case "${*:-}" | 901 | fzf --ansi \ 902 | --color "hl:-1:underline,hl+:-1:underline:reverse" \ 903 | --delimiter : \ 904 | --multi \ 905 | --preview 'bat --color=always {1} --highlight-line {2} --style=header,grid {}' \ 906 | --preview-window 'right,60%,border-bottom,+{2}+3/3,~3' 907 | ) 908 | if [ -n "${ARGLIST}" ]; then 909 | code "${NEW_WINDOW}" "${ARGLIST}" 910 | fi 911 | } 912 | 913 | ### CAPTURE AND RETURN OUTPUT OF A COMMAND ### 914 | # Usage: 915 | # $ find . -name 'filename' | cap 916 | # /path/to/filename 917 | # $ ret 918 | # /path/to/filename 919 | 920 | # capture the output of a command so it can be retrieved with ret 921 | cap() { tee /tmp/capture.out; } 922 | 923 | # return the output of the most recent command that was captured by cap 924 | ret() { cat /tmp/capture.out; } 925 | ### END CAPTURE AND RETURN OUTPUT OF A COMMAND ### 926 | 927 | # Backup VSCode extensions settings 928 | function backup-vscode() { 929 | local date 930 | date="$(date +%Y-%m-%d)" 931 | local destination="${HOME}/Library/Mobile Documents/com~apple~CloudDocs/Backups/vscode/${date}" 932 | local extensions_file="${destination}/extensions.txt" 933 | local settings_file="${destination}/settings.json" 934 | local keybindings_file="${destination}/keybindings.json" 935 | 936 | mkdir -p "${destination}" 937 | 938 | # List extensions 939 | code --list-extensions >"${extensions_file}" 940 | echo "Created ${extensions_file}" 941 | 942 | # Backup settings 943 | cp "${HOME}/Library/Application Support/Code/User/settings.json" "${settings_file}" 944 | echo "Created:" 945 | echo "$settings_file" 946 | 947 | # Backup keybindings 948 | cp "${HOME}/Library/Application Support/Code/User/keybindings.json" "${keybindings_file}" 949 | echo "$keybindings_file" 950 | } 951 | 952 | ### Github Functions ### 953 | function gh() { 954 | # unset GITHUB_TOKEN for gh cli 955 | GITHUB_TOKEN="" command gh "$@" 956 | } 957 | 958 | function gh_pr_list_open() { 959 | local search_param="" 960 | local other_params=() 961 | 962 | while [[ $# -gt 0 ]]; do 963 | case "$1" in 964 | --match) 965 | search_param="$2" 966 | shift 2 967 | ;; 968 | *) 969 | other_params+=("$1") 970 | shift 971 | ;; 972 | esac 973 | done 974 | 975 | if [[ -n "$search_param" ]]; then 976 | other_params+=("--search=\"$search_param\"") 977 | fi 978 | 979 | gh pr list --state open "${other_params[@]}" 980 | } 981 | 982 | function gh_pr_list_open_dir_repos() { 983 | local search_param="" 984 | local other_params=() 985 | 986 | while [[ $# -gt 0 ]]; do 987 | case "$1" in 988 | --match) 989 | search_param="$2" 990 | shift 2 991 | ;; 992 | *) 993 | other_params+=("$1") 994 | shift 995 | ;; 996 | esac 997 | done 998 | 999 | for repo in */; do 1000 | if [[ -d "$repo" ]]; then 1001 | # Get the repo name from the git config 1002 | repo_name=$(git -C "$repo" config --get remote.origin.url | sed -E 's/.*github.com[:/].*\/(.*)\.git/\1/') 1003 | # Get the repo owner from the git config 1004 | repo_owner=$(git -C "$repo" config --get remote.origin.url | sed -E 's/.*github.com[:/](.*)\/.*/\1/') 1005 | 1006 | echo "Repository: $repo_owner/$repo_name" 1007 | 1008 | gh_pr_list_open --repo "$repo_owner/$repo_name" --match "$search_param" "${other_params[@]}" 1009 | 1010 | echo "" 1011 | fi 1012 | done 1013 | } 1014 | 1015 | function gh_pr_merge_matching() { 1016 | local search_param="$1" 1017 | local other_params=() 1018 | 1019 | while [[ $# -gt 0 ]]; do 1020 | case "$1" in 1021 | --match) 1022 | search_param="$2" 1023 | shift 2 1024 | ;; 1025 | *) 1026 | other_params+=("$1") 1027 | shift 1028 | ;; 1029 | esac 1030 | done 1031 | 1032 | local pr_numbers=() 1033 | gh_pr_list_open --match "$search_param" "${other_params[@]}" | while IFS= read -r pr_info; do 1034 | pr_number=$(echo "$pr_info" | jq -r '.number') 1035 | pr_numbers+=("$pr_number") 1036 | echo "PR #$pr_number: $(echo "$pr_info" | jq -r '.title')" 1037 | done 1038 | 1039 | if [[ ${#pr_numbers[@]} -eq 0 ]]; then 1040 | echo "No matching PRs found." 1041 | return 1 1042 | fi 1043 | 1044 | read -p "Merge and resolve these PRs? (y/n): " choice 1045 | if [[ $choice == [yY] ]]; then 1046 | for pr_number in "${pr_numbers[@]}"; do 1047 | gh pr merge "$pr_number" --auto "${other_params[@]}" 1048 | done 1049 | fi 1050 | } 1051 | 1052 | ### END Github Functions ### 1053 | 1054 | ### Get output from last command ### 1055 | # CTRL+Q,CTRL+L 1056 | zmodload -i zsh/parameter 1057 | 1058 | insert-last-command-output() { 1059 | # shellcheck disable=SC2154 1060 | LBUFFER+="$(eval "$history"[$((HISTCMD - 1))])" 1061 | } 1062 | zle -N insert-last-command-output 1063 | 1064 | bindkey "^Q^L" insert-last-command-output 1065 | ### End get output from last command ### 1066 | 1067 | # if ifup or ifdown is run - remind the user of the correct 1068 | ifup() { 1069 | echo "Did you mean 'ip link set $1 up'?" 1070 | } 1071 | 1072 | ifdown() { 1073 | echo "Did you mean 'ip link set $1 down'?" 1074 | } 1075 | 1076 | # A small function that updates chromium (don't worry - my main browser is Firefox) and removes the extended attributes that cause it to be quarantined by macOS 1077 | __update_chromium() { 1078 | # check if there is an update available from homebrew 1079 | local chromium_update 1080 | chromium_update=$(brew outdated --cask --greedy | grep -i chromium) 1081 | 1082 | if [[ -n $chromium_update ]]; then 1083 | brew upgrade --cask --greedy --no-quarantine chromium 1084 | xattr -d com.apple.quarantine /Applications/Chromium.app 1085 | echo "Updated Chromium to $chromium_update, and removed quarantine attributes." 1086 | fi 1087 | } 1088 | 1089 | # a function that checks for macOS OS updates and downloads them (without installing) then pops up a notification in the background 1090 | function __update_macos() { 1091 | # check for updates 1092 | softwareupdate -l 1093 | if [[ $? -eq 0 ]]; then 1094 | # notify the user there are updates to download and that they may have to enter their password in the terminal 1095 | osascript -e 'display notification "macOS updates are available. You may need to enter your password in the terminal to download them." with title "macOS Update" action button "Show iTerm"' 1096 | # download updates 1097 | softwareupdate -d -a --no-scan --agree-to-license --background 1098 | fi 1099 | } 1100 | 1101 | function ba() { 1102 | # trap ctrl-c 1103 | trap '' SIGINT 1104 | 1105 | # create a log file, if it already exists move it to .1 and create a new one 1106 | local log_file="${HOME}/.ba.log" 1107 | local error_log="${HOME}/.ba.errors.log" 1108 | 1109 | # link all ollama models to lm-studio 1110 | llamalink >>"${log_file}" 2>&1 & 1111 | 1112 | # update vscode packages 1113 | code --update-extensions >>"${log_file}" 2>&1 & 1114 | 1115 | # update homebrew and all apps 1116 | brew update >>"${error_log}" 2>&1 1117 | 1118 | mv "${log_file}" "${log_file}.1" 1119 | 1120 | echo "Upgrading shell and packages in the background, tail -f ${log_file} for details." 1121 | 1122 | touch "${log_file}" "${error_log}" 1123 | echo "Starting update at $(date +%Y-%m-%d) ..." >>"${log_file}" 1124 | 1125 | __upgrade_shell >>"${log_file}" 2>&1 & 1126 | __upgrade_packages >>"${log_file}" 2>&1 & 1127 | 1128 | echo "Upgrading apps in the foreground..." 1129 | __upgrade_apps # >>"${log_file}" 1130 | 1131 | echo "Checking and downloading macOS updates in the background..." 1132 | __update_macos >>"${log_file}" 2>&1 & 1133 | 1134 | # ~/bin/build_ollama.sh >>"${log_file}" 2>&1 & 1135 | 1136 | echo "Upgrading rust in the background..." 1137 | rustup update >>"${log_file}" 2>&1 & 1138 | 1139 | echo "Updating Github Copilot CLI in the background..." 1140 | gh extension upgrade gh-copilot >>"${log_file}" 2>&1 & 1141 | 1142 | # list all background jobs 1143 | jobs 1144 | 1145 | # every 5 seconds, check if any background jobs are paused, if so, foreground them 1146 | while true; do 1147 | sleep 5 1148 | if [[ -n $(jobs -p -s) ]]; then 1149 | sleep 1 1150 | echo -e "" 1151 | fg 1152 | else 1153 | break 1154 | fi 1155 | done 1156 | 1157 | # wait for all background jobs to finish 1158 | wait 1159 | fg # bring the last background job to the foreground 1160 | 1161 | compdump # recompile zsh completion files 1162 | 1163 | echo "Updates complete, see ${log_file} for details." 1164 | 1165 | # unset trap 1166 | trap - SIGINT 1167 | } 1168 | 1169 | function __upgrade_apps() { 1170 | trap 'fg' SIGINT 1171 | 1172 | brew update 1173 | NONINTERACTIVE=1 __update_chromium 1174 | NONINTERACTIVE=1 brew upgrade --greedy --greedy-latest 1175 | NONINTERACTIVE=1 brew upgrade --cask --greedy 1176 | NONINTERACTIVE=1 mas upgrade 1177 | brew cleanup 1178 | brew autoremove 1179 | gup update 1180 | 1181 | # unset trap 1182 | trap - SIGINT 1183 | 1184 | # check for any suspended jobs and foreground them 1185 | if [[ -n $(jobs -p -s) ]]; then 1186 | fg 1187 | fi 1188 | } 1189 | 1190 | function __upgrade_packages() { 1191 | trap 'fg' SIGINT 1192 | 1193 | pip3 install -U pip 1194 | npm i -g npm-check-updates 1195 | \ncu --global 1196 | echo | vim +PluginInstall +qall &>/dev/null 1197 | 1198 | # unset trap 1199 | trap - SIGINT 1200 | } 1201 | 1202 | function __upgrade_shell() { 1203 | zgen selfupdate 1204 | zgen update 1205 | omz update 1206 | } 1207 | 1208 | function __upgrade_docker_compose() { 1209 | VERSION=$(curl --silent https://api.github.com/repos/docker/compose/releases/latest | jq .name -r) 1210 | DESTINATION=/usr/local/bin/docker-compose 1211 | COMPOSE_LOCATION=$(which docker-compose 2>/dev/null) 1212 | 1213 | # Check if we've got docker-compose already installed and if we're using the homebrew version 1214 | if [[ $COMPOSE_LOCATION == "/opt/homebrew/bin/docker-compose" ]]; then 1215 | echo "You're using the homebrew version of docker-compose, skipping update." 1216 | return 1217 | fi 1218 | 1219 | if [[ -f $DESTINATION ]] && [[ $(docker-compose version --short) == "$VERSION" ]]; then 1220 | echo "docker-compose is already up to date." 1221 | return 1222 | else 1223 | curl -L "https://github.com/docker/compose/releases/download/${VERSION}/docker-compose-$(uname -s)-$(uname -m)" -o "$DESTINATION" 1224 | chmod 755 "$DESTINATION" 1225 | ln -fs "$(which docker-compose)" /usr/libexec/docker/cli-plugins/docker-compose 1226 | echo "Updated docker-compose to ${VERSION}" 1227 | fi 1228 | } 1229 | 1230 | # Now in 1-zgen.rc 1231 | # bg_silent() { 1232 | # # background a task quietly and disown 1233 | # { "$@" 2>&3 & } 3>&2 2>/dev/null 1234 | # disown &>/dev/null 1235 | # } 1236 | 1237 | ### OLD 1238 | # # AWS Azure AD login 1239 | # function aws-azure-login() { 1240 | # command aws-azure-login --no-prompt --profile "$@" 1241 | # export AWS_PROFILE=$* 1242 | # export AWSCLIPARAMS="--profile=$*" 1243 | # } 1244 | 1245 | # # saml2aws 1246 | # aad() { 1247 | # local IDPPW INPUT_PROFILE 1248 | 1249 | # # Check for input 1250 | # if [ -z "${1}" ]; then 1251 | # echo "ERROR: account name required, e.g. $(basename "$0") data-dev" 1252 | # return 1 1253 | # else 1254 | # # Cleanup the input 1255 | # INPUT_PROFILE=$(echo "$1" | sed -e 's/dosa/kis/g;s/cust/klue/g') 1256 | # fi 1257 | 1258 | # # Fetch the password from keychain 1259 | # IDPPW=$(keychain_password awsazurepw) # requires mfa and keychain authentication 1260 | 1261 | # aws configure list --profile "${1}" 1262 | # # Login to AWS 1263 | # saml2aws login -a "$INPUT_PROFILE" \ 1264 | # --skip-prompt \ 1265 | # --password="$IDPPW" \ 1266 | # --profile="$INPUT_PROFILE" \ 1267 | # --cache-saml && 1268 | # export AWS_PROFILE="$INPUT_PROFILE" && 1269 | # export AWSCLIPARAMS="--profile=${INPUT_PROFILE}" && 1270 | # export AWS_DEFAULT_REGION=ap-southeast-2 1271 | # unset IDPPW 1272 | 1273 | # # Check the login was successful 1274 | # aws --profile "$AWS_PROFILE" sts get-caller-identity 1275 | # } 1276 | 1277 | # function awslogin() { 1278 | # if [ -z "${1}" ]; then 1279 | # echo "ERROR: account name required, e.g. awslogin data-dev" 1280 | # else 1281 | # # Check credentials are current, refresh if needed and export into shell 1282 | # aws configure list --profile "${1}" && eval "$(saml2aws script --profile "${1}")" 1283 | # fi 1284 | # } 1285 | 1286 | # Function to recursively replace the registry in package-lock.json files 1287 | npm_replace_registry() { 1288 | # Define the string to search for and the string to replace it with 1289 | local search_string="${LOCAL_NPM_REGISTRY}" 1290 | local replace_string="registry.npmjs.org" 1291 | 1292 | # skip if search string is empty 1293 | if [ -z "$search_string" ]; then 1294 | return 0 1295 | fi 1296 | 1297 | # Use find to locate all package-lock.json files and loop through them 1298 | find . -type f -name 'package-lock.json' | while read -r file; do 1299 | echo "Processing $file" 1300 | 1301 | # Use sed to perform the string replacement 1302 | sed -i.bak "s|$search_string|$replace_string|g" "$file" 1303 | 1304 | # Remove the backup file created by sed 1305 | rm -f "${file}.bak" 1306 | 1307 | echo "Replaced $search_string with $replace_string in $file" 1308 | done 1309 | } 1310 | 1311 | ### Docker Compose ### 1312 | # Functions to help when working with docker-compose especially with multiple docker-compose files and profiles 1313 | 1314 | # ddc() { 1315 | # local command="$1" 1316 | # shift 1317 | # local service_name="$1" 1318 | # shift 1319 | # local profile="" 1320 | 1321 | # # Iterate through all docker-compose*.yaml files to find the profile 1322 | # for file in docker-compose*.yaml; do 1323 | # # Check if the specified service exists in the file 1324 | # if grep -q "^ $service_name:" "$file"; then 1325 | # # Extract profile name 1326 | # profile_name=$(awk -v service="$service_name" '$1 == service":" { getline; getline; print $3 }' "$file") 1327 | # profile_name="${profile_name#- }" 1328 | # profile_name="${profile_name%\"}" 1329 | # profile_name="${profile_name#\"}" 1330 | # if [[ ! -z "$profile_name" ]]; then 1331 | # profile="--profile $profile_name" 1332 | # fi 1333 | # break 1334 | # fi 1335 | # done 1336 | 1337 | # # Run the docker-compose command 1338 | # docker-compose $profile $command "$service_name" "$@" 1339 | # } 1340 | 1341 | function docker-network() { 1342 | docker ps -q | xargs -n 1 docker inspect --format '{{range .NetworkSettings.Networks}}{{.IPAddress}}{{end}} {{ .Name }}' | sed 's/ \// /' | sort 1343 | } 1344 | 1345 | dpup() { 1346 | pushd "$DOCKER_COMPOSE_DIR" || return 1347 | docker-compose --profile "$1" up -d "$1" 1348 | echo "----" 1349 | docker logs -f "$1" 1350 | popd 1351 | } 1352 | 1353 | # Run docker-compose profiles on a remote (ssh) server 1354 | nas_dcup() { 1355 | local server="$1" 1356 | local profile="$2" 1357 | local service="$3" 1358 | local command="$4" 1359 | 1360 | ssh "$server" "cd ${DOCKER_COMPOSE_DIR} && docker-compose --profile ${profile} ${command} ${service}" 1361 | } 1362 | 1363 | # Yazi https://github.com/sxyazi/yazi 1364 | # https://github.com/sxyazi/yazi/tree/main/config/docs 1365 | function y() { 1366 | tmp="$(mktemp -t "yazi-cwd.XXXXX")" 1367 | yazi --cwd-file="$tmp" 1368 | if cwd="$(cat -- "$tmp")" && [ -n "$cwd" ] && [ "$cwd" != "$PWD" ]; then 1369 | cd -- "$cwd" 1370 | fi 1371 | rm -f -- "$tmp" 1372 | } 1373 | 1374 | function brewbackup() { 1375 | # shellcheck disable=SC2139,SC2153 1376 | brew bundle dump --force --file="/Users/${USER}/Library/Mobile Documents/com~apple~CloudDocs/Backups/homebrew/Brewfile-${HOST}" 1377 | } 1378 | 1379 | # Function to reload updated Zsh functions 1380 | zsh_reload_updated_functions() { 1381 | # Create a unique temporary file to store currently loaded functions 1382 | local temp_file 1383 | temp_file="/tmp/zsh_functions_$(date +%s%N)" 1384 | 1385 | # Extract currently loaded functions into the temporary file 1386 | typeset -f >"$temp_file" 1387 | 1388 | # File containing the function definitions (e.g., ~/.zshrc) 1389 | local source_file="$HOME/.zshrc" 1390 | 1391 | # Find updated functions 1392 | local updated_functions 1393 | updated_functions=$(comm -13 <(awk '/^function / {print $2}' "$temp_file" | sort) <(awk '/^function / {print $2}' "$source_file" | sort)) 1394 | 1395 | # Reload updated functions 1396 | for fn in $updated_functions; do 1397 | unfunction "$fn" 2>/dev/null 1398 | source "$source_file" 1399 | echo "Reloaded function: $fn" 1400 | done 1401 | 1402 | # Remove temporary file 1403 | rm -f "$temp_file" 1404 | } 1405 | 1406 | # Update pam to enable touchID for sudo 1407 | function touchid_sudo() { 1408 | # Check if pam is already configured 1409 | if grep -q "pam_tid.so" /etc/pam.d/sudo; then 1410 | echo "pam_tid.so is already configured in /etc/pam.d/sudo" 1411 | return 0 1412 | fi 1413 | 1414 | cat /etc/pam.d/sudo 1415 | 1416 | # Add pam_tid.so to /etc/pam.d/sudo 1417 | echo "Adding pam_tid.so to /etc/pam.d/sudo" 1418 | sudo sed -i '' '1s/^/auth sufficient pam_tid.so\n/' /etc/pam.d/sudo 1419 | } 1420 | 1421 | a() { 1422 | # Extract filename from the URL (the part after the last slash) 1423 | local filename 1424 | filename=$(basename "$1") 1425 | 1426 | # Base aria2c options 1427 | local aria_opts=( 1428 | --split=12 1429 | --always-resume=true 1430 | --max-tries=15 1431 | --retry-wait=3 1432 | --enable-http-pipelining=true 1433 | --http-accept-gzip=true 1434 | --max-connection-per-server=14 1435 | --max-concurrent-downloads=5 1436 | --min-split-size=10M 1437 | --auto-file-renaming=false 1438 | --content-disposition-default-utf8=true 1439 | --disk-cache=64M 1440 | --file-allocation=prealloc 1441 | --out="$filename" 1442 | ) 1443 | 1444 | # Check if URL is from Huggingface 1445 | if [[ "$1" == *"huggingface.co"* ]] || [[ "$1" == *"hf.co"* ]]; then 1446 | # Check if HUGGINGFACE_TOKEN is set 1447 | if [ -z "${HUGGINGFACE_TOKEN}" ]; then 1448 | echo "Warning: HUGGINGFACE_TOKEN is not set. You may experience rate limiting." 1449 | else 1450 | # Verify token is valid by making a test request to the newer endpoint 1451 | echo "Verifying Huggingface token..." 1452 | local token_check 1453 | token_check=$(curl -s -I -H "Authorization: Bearer ${HUGGINGFACE_TOKEN}" "https://huggingface.co/api/whoami-v2" | grep -c "HTTP/2 200") 1454 | 1455 | if [ "$token_check" -eq 1 ]; then 1456 | echo "✅ Huggingface token is valid." 1457 | aria_opts+=(--header="Authorization: Bearer ${HUGGINGFACE_TOKEN}") 1458 | else 1459 | echo "⚠️ Huggingface token appears to be invalid. Downloads may be rate limited." 1460 | echo "Note: If your token starts with 'hf_', this is expected format for newer tokens." 1461 | # shellcheck disable=SC2162 1462 | read -p "Continue anyway? (y/n): " confirm 1463 | if [[ "$confirm" != "y" ]]; then 1464 | echo "Download cancelled." 1465 | return 1 1466 | fi 1467 | # Add the token anyway as it might still work for downloads even if validation fails 1468 | aria_opts+=(--header="Authorization: Bearer ${HUGGINGFACE_TOKEN}") 1469 | fi 1470 | fi 1471 | fi 1472 | 1473 | # Run aria2c with the assembled options 1474 | aria2c "${aria_opts[@]}" "$1" 1475 | 1476 | echo "downloaded ${1} as ${filename}" 1477 | } 1478 | 1479 | rename_files() { 1480 | # see also, one liner - find . -name "*sdc-maps*" -exec bash -c 'mv "$0" "${0/sdc/spl}"' {} \; 1481 | local find_word="$1" 1482 | local replace_word="$2" 1483 | local files_to_rename=() 1484 | local new_names=() 1485 | 1486 | if [ -z "$find_word" ] || [ -z "$replace_word" ]; then 1487 | echo "Usage: rename_files <find_word> <replace_word>" 1488 | return 1 1489 | fi 1490 | 1491 | # Collect the list of files to be renamed 1492 | for f in *"$find_word"*; do 1493 | if [ -e "$f" ]; then # Check if file exists 1494 | files_to_rename+=("$f") 1495 | new_names+=("${f//$find_word/$replace_word}") 1496 | fi 1497 | done 1498 | 1499 | # Display the list of files to be renamed 1500 | echo "Files to be renamed:" 1501 | for i in "${!files_to_rename[@]}"; do 1502 | echo "'${files_to_rename[$i]}' -> '${new_names[$i]}'" 1503 | done 1504 | 1505 | # Ask for confirmation 1506 | echo "Proceed with renaming? (y/n)" 1507 | read -r confirm 1508 | if [ "$confirm" = "y" ] || [ "$confirm" = "Y" ]; then 1509 | for i in "${!files_to_rename[@]}"; do 1510 | mv "${files_to_rename[$i]}" "${new_names[$i]}" 1511 | done 1512 | else 1513 | echo "Renaming cancelled." 1514 | fi 1515 | } 1516 | 1517 | hfdl() { 1518 | local cliargs=() 1519 | # Huggingface download wrapper 1520 | if [[ $# -eq 0 ]]; then 1521 | echo "Usage: hfdl <huggingface URL>" 1522 | return 1 1523 | fi 1524 | 1525 | local url=$1 1526 | 1527 | # if a third argument is provided, treat it as a file to download (include) 1528 | if [[ $# -eq 2 ]]; then 1529 | local file_to_download="$2" 1530 | cliargs+=("--include" "$file_to_download") 1531 | fi 1532 | 1533 | local stripped_url=$(echo "$url" | sed 's|https://huggingface.co/||') 1534 | local owner=$(echo "$stripped_url" | cut -d'/' -f1) 1535 | local repo=$(echo "$stripped_url" | cut -d'/' -f2) 1536 | 1537 | HF_HUB_ENABLE_HF_TRANSFER=1 huggingface-cli download "$owner/$repo" --local-dir-use-symlinks False --local-dir "$repo" "${cliargs[@]}" 1538 | } 1539 | 1540 | # hide overlayfs in df 1541 | df() { 1542 | # if macOS use /bin/df 1543 | if [[ $(uname) == "Darwin" ]]; then 1544 | /bin/df "$@" 1545 | return 1546 | fi 1547 | /usr/bin/df -x overlay "$@" 1548 | } 1549 | 1550 | gpumem() { 1551 | # Increase the GPU memory limit for my 96GB MBP 1552 | sudo /usr/sbin/sysctl iogpu.wired_limit_mb=86000 1553 | } 1554 | 1555 | # loops through all subdirectories one level deep that are git repos and runs the specified command 1556 | function git-loop() { 1557 | local command="$1" 1558 | shift 1559 | local args=("$@") 1560 | 1561 | for dir in */; do 1562 | if [ -d "$dir/.git" ]; then 1563 | echo "Running $command in $dir" 1564 | git -C "$dir" "$command" "${args[@]}" 1565 | fi 1566 | done 1567 | } 1568 | # Register each git repo in directory with maintenance 1569 | alias git-maintenance-register="git-loop maintenance register" 1570 | 1571 | # If the user runs the conda activate command before running conda init - offer to run conda init, otherwise run conda activate 1572 | function conda() { 1573 | if [[ $1 == "activate" ]]; then 1574 | if [[ -z $CONDA_EXE ]]; then 1575 | echo "Conda is not initialized, would you like to initialize it? (y/n)" 1576 | read -r response 1577 | if [[ $response == "y" ]]; then 1578 | conda_init 1579 | fi 1580 | else 1581 | command conda "$@" 1582 | fi 1583 | else 1584 | command conda "$@" 1585 | fi 1586 | } 1587 | 1588 | # a function that overrides pip commands with uv pip 1589 | function pip() { 1590 | # if the first argument is -n, use the normal pip command 1591 | if [[ $1 == "-n" ]]; then 1592 | command pip "${@:2}" 1593 | return 1594 | fi 1595 | echo "using uv for pip..." 1596 | if [[ $1 == "install" ]]; then 1597 | uv pip install "${@:2}" 1598 | elif [[ $1 == "uninstall" ]]; then 1599 | uv pip uninstall "${@:2}" 1600 | else 1601 | command pip "$@" 1602 | fi 1603 | } 1604 | 1605 | # A function that does an ollama cp of any models that start with sammcj to instead start with registry.domain/ollama/<rest of the tag without sammcj> 1606 | # function ollama-cp() { 1607 | # local models 1608 | # local registry 1609 | # registry=$(echo "$OLLAMA_REGISTRY" | sed 's/\//\\\//g') 1610 | # # shellcheck disable=SC2207 # array assignment is intentional 1611 | # models=($(ollama list | grep sammcj | grep -v grep | awk '{print $1}')) 1612 | # # sort by smallest to largest (human readable MB/GB) 1613 | # # calulate the total size of the models 1614 | # total_size=$(ollama list | grep sammcj | grep -v grep | awk '{print $3}' | paste -sd+ - | bc) 1615 | # echo "Total size of models to be considered: ${total_size}GB" 1616 | # # shellcheck disable=SC2207 1617 | # models=($(echo "${models[@]}" | tr ' ' '\n' | sort -h)) 1618 | # for model in "${models[@]}"; do 1619 | # echo "Model: $model" 1620 | # new_model=$(echo "$model" | gsed -e s/sammcj/"$registry"/ | tr '[:upper:]' '[:lower:]') 1621 | # # if ollama list | grep -q "$new_model"; then 1622 | # # echo "Model $new_model already exists, skipping" 1623 | # # continue 1624 | # # fi 1625 | # echo "Copying $model to $new_model" 1626 | # ollama cp "$model" "$new_model" && ollama rm "$model" 1627 | # echo "Pushing $new_model" 1628 | # ollama push "$new_model" 1629 | # done 1630 | # } 1631 | 1632 | function ollama-pull-all() { 1633 | local BATCH_SIZE 1634 | local PULL_LOCAL_REGISTRY_MODELS 1635 | PULL_LOCAL_REGISTRY_MODELS=true 1636 | BATCH_SIZE=3 1637 | 1638 | if $PULL_LOCAL_REGISTRY_MODELS; then 1639 | echo "pulling all models in batches of ${BATCH_SIZE}..." 1640 | ollama list | awk '$1 {print $1}' | while read -r model; do 1641 | # pull the modules in parallel batches 1642 | batch_count=$(jobs -p | wc -l) 1643 | if [ "$batch_count" -ge "$BATCH_SIZE" ]; then 1644 | sleep 1 1645 | wait -n 1646 | fi 1647 | echo "Pulling $model" 1648 | ollama pull "$model" & 1649 | done 1650 | else 1651 | echo "pulling all models not in the local registry in batches of ${BATCH_SIZE}..." 1652 | ollama list | awk '$1 !~ /^${OLLAMA_REGISTRY}/ {print $1}' | while read -r model; do 1653 | # pull the modules in parallel batches 1654 | batch_count=$(jobs -p | wc -l) 1655 | if [ "$batch_count" -ge "$BATCH_SIZE" ]; then 1656 | sleep 1 1657 | wait -n 1658 | fi 1659 | echo "Pulling $model" 1660 | ollama pull "$model" & 1661 | done 1662 | fi 1663 | 1664 | # wait for all background jobs to finish 1665 | wait 1666 | 1667 | echo "All models pulled" 1668 | 1669 | } 1670 | 1671 | function aws-sso() { 1672 | if [[ -z $1 ]]; then 1673 | echo "Usage: aws-sso <profile>" 1674 | return 1 1675 | fi 1676 | aws sso login --profile "$1" 1677 | eval "$(aws configure export-credentials --format env --profile "$1")" 1678 | export AWS_PROFILE="$1" 1679 | export AWS_REGION=ap-southeast-2 1680 | } 1681 | alias aws-ai="aws-sso aisandpit" 1682 | 1683 | function aws-nas() { 1684 | /Users/samm/Library/Mobile\ Documents/com~apple~CloudDocs/Dropbox\ Import/dotfiles/shell_config/update-aws-creds.sh aisandpit 1685 | } 1686 | 1687 | ollama_extend_models() { 1688 | local ctx_size=${1:-32768} 1689 | 1690 | # Prompt the user if they want to proceed 1691 | read -r -p "This will create longer context (${ctx_size}) models for all ollama models. Do you want to proceed? (y/n): " choice 1692 | if [[ $choice != [yY] ]]; then 1693 | echo "Aborting..." 1694 | return 1 1695 | fi 1696 | 1697 | # Run ollama ls and process each line 1698 | ollama ls | tail -n +2 | while read -r line; do 1699 | # Extract model name 1700 | model_name=$(echo "$line" | awk '{print $1}') 1701 | 1702 | # Split model name into base name and variant 1703 | base_name=$(echo "$model_name" | cut -d':' -f1) 1704 | variant=$(echo "$model_name" | cut -d':' -f2) 1705 | 1706 | # Create Modelfile 1707 | cat >"Modelfile-$model_name" <<EOF 1708 | FROM $model_name 1709 | 1710 | PARAMETER num_ctx $ctx_size 1711 | EOF 1712 | 1713 | # Create extended model 1714 | ollama create "$base_name-$ctx_size:$variant" -f "Modelfile-$model_name" 1715 | 1716 | echo "Created extended model: $base_name-$ctx_size:$variant" 1717 | done 1718 | } 1719 | 1720 | if_not_in_vscode() { 1721 | # if not running in vscode, run the rest of the arguments 1722 | # requires setting RUNNING_IN_VSCODE to true in vscode's terminal env settings 1723 | if [ -z "$RUNNING_IN_VSCODE" ]; then 1724 | "$@" 1725 | fi 1726 | } 1727 | 1728 | # Amazon Q wrapper because their Q CLI installer completely hoses terminal performance 1729 | # https://github.com/aws/amazon-q-developer-cli/issues/844 1730 | # https://github.com/aws/amazon-q-developer-cli/discussions/202 1731 | # doesn't quite work yet as their MCP integrations seem to fail, e.g 1732 | # failed installing shell integration bash pre post into .bashrc err=Integration not installed: /Users/samm/.bashrc does not source pre integration 1733 | # Failed installing shell integration bash pre post into .profile err=File does not exist: /Users/samm/.profile 1734 | # Failed installing shell integration zsh pre post into .zshrc err=Integration not installed: /Users/samm/.zshrc does not source pre integration 1735 | # Failed installing shell integration zsh pre post into .zprofile err=Integration not installed: /Users/samm/.zprofile does not source pre integration 1736 | q() { 1737 | # Amazon Q pre block for .zprofile 1738 | [[ -f "${HOME}/Library/Application Support/amazon-q/shell/zprofile.pre.zsh" ]] && builtin source "${HOME}/Library/Application Support/amazon-q/shell/zprofile.pre.zsh" 1739 | # Amazon Q post block for .zprofile 1740 | [[ -f "${HOME}/Library/Application Support/amazon-q/shell/zprofile.post.zsh" ]] && builtin source "${HOME}/Library/Application Support/amazon-q/shell/zprofile.post.zsh" 1741 | 1742 | # Amazon Q pre block for .zshrc 1743 | [[ -f "${HOME}/Library/Application Support/amazon-q/shell/zshrc.pre.zsh" ]] && builtin source "${HOME}/Library/Application Support/amazon-q/shell/zshrc.pre.zsh" 1744 | # Amazon Q post block for .zshrc 1745 | [[ -f "${HOME}/Library/Application Support/amazon-q/shell/zshrc.post.zsh" ]] && builtin source "${HOME}/Library/Application Support/amazon-q/shell/zshrc.post.zsh" 1746 | 1747 | command /Users/samm/.local/bin/q "$@" 1748 | } 1749 | 1750 | cline-workflows() { 1751 | SOURCE_DIR="/Users/samm/git/sammcj/agentic-coding/Cline/Rules/workflows" 1752 | DEST_DIR=.clinerules/workflows 1753 | 1754 | read -r -p "This will copy all workflows from $SOURCE_DIR to $DEST_DIR. Do you want to proceed? (y/n): " choice 1755 | if [[ $choice != [yY] ]]; then 1756 | echo "Aborting..." 1757 | return 1 1758 | fi 1759 | mkdir -p $DEST_DIR 1760 | cp -r $SOURCE_DIR/*.md $DEST_DIR/ 1761 | } 1762 | -------------------------------------------------------------------------------- /CODEOWNERS: -------------------------------------------------------------------------------- 1 | # Sam McLeod 2 | *.sh @sammcj 3 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2023 Sam McLeod 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /NOTES.md: -------------------------------------------------------------------------------- 1 | # General notes related to this repo 2 | 3 | ## ASDF 4 | 5 | Get install path to source 6 | 7 | ```shell 8 | echo -e "\n. $(brew --prefix asdf)/libexec/asdf.sh" 9 | ``` 10 | 11 | Plugins 12 | 13 | # languages 14 | 15 | ```shell 16 | asdf plugin-add { 17 | nodejs https: //github.com/asdf-vm/asdf-nodejs.git 18 | yarn https: //github.com/twuni/asdf-yarn.git 19 | python https: //github.com/danhper/asdf-python.git 20 | golang https: //github.com/kennyp/asdf-golang.git 21 | bundler https: //github.com/jonathanmorley/asdf-bundler.git 22 | ruby https: //github.com/asdf-vm/asdf-ruby.git 23 | rust https: //github.com/code-lever/asdf-rust.git 24 | } 25 | 26 | # Tools that are only available via asdf 27 | asdf plugin-add { 28 | action-validator https: //github.com/mpalmer/action-validator.git 29 | semver https: //github.com/mathew-fleisch/asdf-semver.git 30 | } 31 | 32 | # Terraform 33 | asdf plugin-add { 34 | tfenv https: //github.com/carlduevel/asdf-tfenv.git 35 | tfsec https: //github.com/woneill/asdf-tfsec.git 36 | terraform https: //github.com/asdf-community/asdf-hashicorp.git 37 | terraform-ls https: //github.com/asdf-community/asdf-hashicorp.git 38 | terraform-validator https: //github.com/asdf-community/asdf-hashicorp.git 39 | tfupdate https: //github.com/yuokada/asdf-tfupdate.git 40 | tfstate-lookup https: //github.com/carnei-ro/asdf-tfstate-lookup.git 41 | } 42 | 43 | ``` 44 | 45 | `.tool-versions` 46 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # zsh shell bootstrap and dotfiles 2 | 3 | This repository bootstraps my zsh shell, brew packages and dotfiles. 4 | 5 | [![Issue Count](https://codeclimate.com/github/sammcj/zsh-bootstrap/badges/issue_count.svg)](https://codeclimate.com/github/sammcj/zsh-bootstrap) 6 | 7 | ## Install 8 | 9 | ```shell 10 | ./bootstrap_shell.sh 11 | ``` 12 | 13 | ## Update 14 | 15 | ```shell 16 | # Make changes 17 | pre-commit install 18 | git add . && git commit -m "fix/feat/chore: commit message" && git push 19 | ``` 20 | 21 | ## Assumptions 22 | 23 | - Internet access. 24 | - [Homebrew](https://brew.sh/) is installed. 25 | - Any private exports such as github API tokens etc... can be put in `*private*.rc` which are [ignored by git](.gitignore) and checked for in CI. 26 | - iCloud Drive setup (if you want to use the iCloud Drive dotfiles). 27 | - Signed in to the Apple App Store if you want to use the [mas](https://github.com/mas-cli/mas) package manager. 28 | 29 | ## Files 30 | 31 | - [`bootstrap_shell.sh`](bootstrap_shell.sh) - Installs homebrew packages, sets up zsh, and symlinks dotfiles 32 | - [`Brewfile`](Brewfile) - Homebrew packages to install 33 | - [`commitlint.config.js`](commitlint.config.js) - Commitlint config 34 | 35 | ## Tools 36 | 37 | Generate completions for commands that don't have them: 38 | 39 | ```shell 40 | gencomp ggrep 41 | ``` 42 | 43 | ## SSH Configuration 44 | 45 | See [Mozilla's SSH Client Configuration Guide](https://infosec.mozilla.org/guidelines/openssh#key-generation) for more information on best practices. 46 | -------------------------------------------------------------------------------- /bat-config: -------------------------------------------------------------------------------- 1 | # This is `bat`s configuration file. Each line either contains a comment or 2 | # a command-line option that you want to pass to `bat` by default. You can 3 | # run `bat --help` to get a list of all possible configuration options. 4 | 5 | # Specify desired highlighting theme (e.g. "TwoDark"). Run `bat --list-themes` 6 | # for a list of all available themes 7 | --theme="Dracula" 8 | 9 | # Enable this to use italic text on the terminal. This is not supported on all 10 | # terminal emulators (like tmux, by default): 11 | #--italic-text=always 12 | 13 | # Uncomment the following line to disable automatic paging: 14 | --paging=never 15 | 16 | # Uncomment the following line if you are using less version >= 551 and want to 17 | # enable mouse scrolling support in `bat` when running inside tmux. This might 18 | # disable text selection, unless you press shift. 19 | #--pager="less --RAW-CONTROL-CHARS --quit-if-one-screen --mouse" 20 | 21 | # Syntax mappings: map a certain filename pattern to a language. 22 | # Example 1: use the C++ syntax for Arduino .ino files 23 | # Example 2: Use ".gitignore"-style highlighting for ".ignore" files 24 | #--map-syntax "*.ino:C++" 25 | #--map-syntax ".ignore:Git Ignore" 26 | -------------------------------------------------------------------------------- /bootstrap_shell.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | # Sets up my: 4 | # - zsh shell 5 | # - dotfiles 6 | # - packages 7 | # 8 | # Requirements: 9 | # - macOS 10 | # - iCloud synced, internet access 11 | # - Homebrew, git installed 12 | # - Probably some other things I've forgotten 13 | 14 | THIS_REPO="${HOME}/Library/Mobile\ Documents/com\~apple\~CloudDocs/Dropbox\ Import/dotfiles/shell_config/" 15 | 16 | # If ssh keys are not already added, add them 17 | if ! ssh-add -l | grep -e 'ED25519\|RSA'; then 18 | ssh-add --apple-use-keychain ~/.ssh/id_*.key 19 | fi 20 | 21 | function installHomebrew() { 22 | if ! command -v brew &>/dev/null; then 23 | /bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)" 24 | fi 25 | 26 | # Brew installs moved to Brewfile (brew bundle dump to generate) 27 | brew bundle 28 | } 29 | 30 | function installPythonPackages() { 31 | curl -LsSf https://astral.sh/uv/install.sh | sh # Install uv via astral 32 | 33 | pushd "$HOME" 34 | uv venv 35 | . venv/bin/activate 36 | popd 37 | uv pip3 install -U mu-repo oterm 38 | 39 | oterm --install-completion zsh 40 | } 41 | 42 | # Ensure we don't have those pesky ^ in our package.json files 43 | npm config set save-exact=true 44 | 45 | function installNpmPackages() { 46 | npm install -g npm-check-updates eslint prettier editorconfig \ 47 | @typescript-eslint/parser typescript ts-node bash-language-server 48 | } 49 | 50 | function clone_repo() { 51 | if [[ -d "$1" ]]; then 52 | echo "Directory $1 already exists" 53 | read -r -p "Do you want to replace it with a clone of the repo $2? [y/N] " response 54 | if [[ "$response" =~ ^([yY][eE][sS]|[yY])$ ]]; then 55 | rm -rf "$1" 56 | git clone "$2" "$1" --depth=1 57 | fi 58 | else 59 | echo "No changes made to $1" 60 | fi 61 | } 62 | 63 | function installGoPackages() { 64 | go install github.com/rhysd/actionlint/cmd/actionlint@latest 65 | go install github.com/nao1215/gup@latest # gup - updates go packages 66 | go install github.com/jesseduffield/lazydocker@latest 67 | go install github.com/rs/dnstrace@latest 68 | 69 | } 70 | 71 | function installCargoPackages() { 72 | if ! command -v cargo &>/dev/null; then 73 | curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh # Install rust via rustup 74 | fi 75 | 76 | # Install cargo packages 77 | cargo install cai code2prompt gitu lazycli 78 | } 79 | 80 | function installAsdf() { 81 | ### asdf ### 82 | 83 | ## install plugins 84 | # languages 85 | asdf plugin-add nodejs https://github.com/asdf-vm/asdf-nodejs.git 86 | asdf plugin-add yarn https://github.com/twuni/asdf-yarn.git 87 | asdf plugin-add golang https://github.com/kennyp/asdf-golang.git 88 | asdf plugin-add rust https://github.com/code-lever/asdf-rust.git 89 | 90 | # asdf plugin-add python https://github.com/danhper/asdf-python.git 91 | 92 | # Tools that are only available via asdf 93 | asdf plugin-add action-validator https://github.com/mpalmer/action-validator.git 94 | asdf plugin-add semver https://github.com/mathew-fleisch/asdf-semver.git 95 | 96 | # # Terraform 97 | # asdf plugin-add tfenv https://github.com/carlduevel/asdf-tfenv.git 98 | # asdf plugin-add tfsec https://github.com/woneill/asdf-tfsec.git 99 | # asdf plugin-add terraform https://github.com/asdf-community/asdf-hashicorp.git 100 | # asdf plugin-add terraform-ls https://github.com/asdf-community/asdf-hashicorp.git 101 | # asdf plugin-add terraform-validator https://github.com/asdf-community/asdf-hashicorp.git 102 | # asdf plugin-add tfupdate https://github.com/yuokada/asdf-tfupdate.git 103 | # asdf plugin-add tfstate-lookup https://github.com/carnei-ro/asdf-tfstate-lookup.git 104 | 105 | # Install all asdf plugins 106 | asdf plugin-update --all 107 | } 108 | 109 | function installDockerCompose() { 110 | # Docker compose v2 111 | mkdir -p ~/.docker/cli-plugins/ 112 | chmod +x ~/.docker/cli-plugins/docker-compose 113 | ln -sfn /opt/homebrew/opt/docker-compose/bin/docker-compose "${HOME}/.docker/cli-plugins/docker-compose" 114 | } 115 | 116 | function installZshZgen() { 117 | mkdir -p "${HOME}/.zsh.d" 118 | grep -q -F '/opt/homebrew/bin/zsh' /etc/shells || echo '/opt/homebrew/bin/zsh' | sudo tee -a /etc/shells 119 | clone_repo "${HOME}/.zgen" "https://github.com/tarjoilija/zgen.git" 120 | } 121 | 122 | function installTmuxTpm() { 123 | clone_repo "${HOME}/.tmux/plugins/tpm" 124 | } 125 | 126 | ## Local functions ## 127 | function link_dotfile() { 128 | # Error if there are more than two arguments 129 | if [[ $# -gt 2 ]]; then 130 | echo "Too many arguments" 131 | return 1 132 | fi 133 | # Check if there is a second argument, if so, use it as the destination file name otherwise use the source file name 134 | if [ -z "$2" ]; then 135 | local DEST="${HOME}/${1}" 136 | else 137 | local DEST="${HOME}/${2}" 138 | # Check if the directories up to the destination file exist, if not, create them 139 | if [ ! -d "$(dirname "${DEST}")" ]; then 140 | mkdir -p "$(dirname "${DEST}")" 141 | fi 142 | fi 143 | if [[ -f "$DEST" ]]; then 144 | echo "File $DEST already exists" 145 | read -r -p "Do you want to replace it with a symlink to the file in this repo? [y/N] " response 146 | if [[ "$response" =~ ^([yY][eE][sS]|[yY])$ ]]; then 147 | rm -f "$DEST" 148 | ln -s "${THIS_REPO}/$1" "${HOME}/${DEST}" 149 | else 150 | exit 1 151 | #shellcheck disable=SC2317 152 | echo "No changes made to ${DEST}" 153 | fi 154 | 155 | fi 156 | } 157 | 158 | function gitConfig() { 159 | clone_repo "${HOME}/.git/fuzzy" "https://github.com/bigH/git-fuzzy.git" && ln -s "${HOME}/.git/fuzzy/bin/git-fuzzy" "${HOME}/bin/git-fuzzy" 160 | 161 | # git 162 | git config --global branch.autoSetupMerge true 163 | git config --global --add --bool push.autoSetupRemote true 164 | git config --global rerere.enabled true 165 | git config --global rerere.autoUpdate true 166 | git config --global branch.sort -committerdate 167 | git config --global alias.fpush push --force-with-lease 168 | git config --global help.autocorrect 1 169 | git config --global diff.algorithm histogram 170 | git config --global rebase.autosquash true 171 | git config --global merge.conflictstyle zdiff3 172 | git config --global fetch.prunetags true 173 | git config --global log.date iso 174 | git config --global diff.tool difftastic # brew install difftastic / cargo install --locked difftastic 175 | git config --global push.followtags true 176 | git maintenance start 177 | git maintenance register 178 | } 179 | 180 | function macOSConfig() { 181 | # Completion plugins 182 | gh completion -s zsh >/usr/local/share/zsh/site-functions/_gh 183 | 184 | # Increase the density of status bar icons 185 | defaults -currentHost write -globalDomain NSStatusItemSelectionPadding -int 3 186 | 187 | echo "Do you want to enable touchID for sudo? [y/N]" 188 | read -r response 189 | if [[ "$response" =~ ^([yY][eE][sS]|[yY])$ ]]; then 190 | source '9-functions.rc' 191 | touchid_sudo 192 | fi 193 | } 194 | 195 | function configureDotfiles() { 196 | # Link dotfiles 197 | dotfiles=(".gitignoreglobal" ".gitconfig" ".vimrc" ".gitconfig_nopush" ".gitconfig.private" ".dircolors" ".tmux.conf" ".zshrc" ".asdfrc") 198 | for dotfile in "${dotfiles[@]}"; do 199 | link_dotfile "$dotfile" 200 | done 201 | 202 | link_dotfile "bat-config" "/Users/samm/.config/bat/config" 203 | link_dotfile "rsyncd.conf" "/Users/samm/.rsyncd.conf" 204 | 205 | # TODO: clean this up 206 | ln -s /Users/samm/Library/Mobile\ Documents/com~apple~CloudDocs/Dropbox\ Import/dotfiles/aider/.aider.conf.yml $HOME/.aider.conf.yml 207 | ln -s /Users/samm/Library/Mobile\ Documents/com~apple~CloudDocs/Dropbox\ Import/dotfiles/aider/.aider.models.json $HOME/.aider.models.json 208 | } 209 | 210 | function main() { 211 | installHomebrew 212 | installPythonPackages 213 | installGoPackages 214 | installCargoPackages 215 | installNpmPackages 216 | 217 | installDockerCompose 218 | 219 | installZshZgen 220 | installTmuxTpm 221 | 222 | macOSConfig 223 | gitConfig 224 | configureDotfiles 225 | } 226 | 227 | # Run the main functions to install and configure 228 | main 229 | 230 | echo "Done" 231 | -------------------------------------------------------------------------------- /commitlint.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | parserPreset: 'conventional-changelog-conventionalcommits', 3 | rules: { 4 | 'body-leading-blank': [1, 'always'], 5 | 'body-max-line-length': [2, 'always', 100], 6 | 'footer-leading-blank': [1, 'always'], 7 | 'footer-max-line-length': [2, 'always', 100], 8 | 'header-max-length': [2, 'always', 100], 9 | 'subject-case': [2, 'never', ['sentence-case', 'start-case', 'pascal-case', 'upper-case']], 10 | 'subject-empty': [2, 'never'], 11 | 'subject-full-stop': [2, 'never', '.'], 12 | 'type-case': [2, 'always', 'lower-case'], 13 | 'type-empty': [2, 'never'], 14 | 'type-enum': [ 15 | 2, 16 | 'always', 17 | [ 18 | 'build', 19 | 'chore', 20 | 'ci', 21 | 'docs', 22 | 'feat', 23 | 'fix', 24 | 'perf', 25 | 'refactor', 26 | 'revert', 27 | 'style', 28 | 'test', 29 | ], 30 | ], 31 | }, 32 | prompt: { 33 | questions: { 34 | type: { 35 | description: "Select the type of change that you're committing", 36 | enum: { 37 | feat: { 38 | description: 'A new feature', 39 | title: 'Features', 40 | emoji: '✨', 41 | }, 42 | fix: { 43 | description: 'A bug fix', 44 | title: 'Bug Fixes', 45 | emoji: '🐛', 46 | }, 47 | docs: { 48 | description: 'Documentation only changes', 49 | title: 'Documentation', 50 | emoji: '📚', 51 | }, 52 | style: { 53 | description: 54 | 'Changes that do not affect the meaning of the code (white-space, formatting, missing semi-colons, etc)', 55 | title: 'Styles', 56 | emoji: '💎', 57 | }, 58 | refactor: { 59 | description: 'A code change that neither fixes a bug nor adds a feature', 60 | title: 'Code Refactoring', 61 | emoji: '📦', 62 | }, 63 | perf: { 64 | description: 'A code change that improves performance', 65 | title: 'Performance Improvements', 66 | emoji: '🚀', 67 | }, 68 | test: { 69 | description: 'Adding missing tests or correcting existing tests', 70 | title: 'Tests', 71 | emoji: '🚨', 72 | }, 73 | build: { 74 | description: 75 | 'Changes that affect the build system or external dependencies (example scopes: gulp, broccoli, npm)', 76 | title: 'Builds', 77 | emoji: '🛠', 78 | }, 79 | ci: { 80 | description: 81 | 'Changes to our CI configuration files and scripts (example scopes: Travis, Circle, BrowserStack, SauceLabs)', 82 | title: 'Continuous Integrations', 83 | emoji: '⚙️', 84 | }, 85 | chore: { 86 | description: "Other changes that don't modify src or test files", 87 | title: 'Chores', 88 | emoji: '♻️', 89 | }, 90 | revert: { 91 | description: 'Reverts a previous commit', 92 | title: 'Reverts', 93 | emoji: '🗑', 94 | }, 95 | }, 96 | }, 97 | scope: { 98 | description: 'What is the scope of this change (e.g. component or file name)', 99 | }, 100 | subject: { 101 | description: 'Write a short, imperative tense description of the change', 102 | }, 103 | body: { 104 | description: 'Provide a longer description of the change', 105 | }, 106 | isBreaking: { 107 | description: 'Are there any breaking changes?', 108 | }, 109 | breakingBody: { 110 | description: 111 | 'A BREAKING CHANGE commit requires a body. Please enter a longer description of the commit itself', 112 | }, 113 | breaking: { 114 | description: 'Describe the breaking changes', 115 | }, 116 | isIssueAffected: { 117 | description: 'Does this change affect any open issues?', 118 | }, 119 | issuesBody: { 120 | description: 121 | 'If issues are closed, the commit requires a body. Please enter a longer description of the commit itself', 122 | }, 123 | issues: { 124 | description: 'Add issue references (e.g. "fix #123", "re #123".)', 125 | }, 126 | }, 127 | }, 128 | }; 129 | -------------------------------------------------------------------------------- /dircolors: -------------------------------------------------------------------------------- 1 | # Configuration file for dircolors, a utility to help you set the 2 | # LS_COLORS environment variable used by GNU ls with the --color option. 3 | 4 | # Copyright (C) 1996-2022 Free Software Foundation, Inc. 5 | # Copying and distribution of this file, with or without modification, 6 | # are permitted provided the copyright notice and this notice are preserved. 7 | 8 | # The keywords COLOR, OPTIONS, and EIGHTBIT (honored by the 9 | # slackware version of dircolors) are recognized but ignored. 10 | 11 | # Global config options can be specified before TERM or COLORTERM entries 12 | 13 | # Below are TERM or COLORTERM entries, which can be glob patterns, which 14 | # restrict following config to systems with matching environment variables. 15 | COLORTERM ?* 16 | TERM Eterm 17 | TERM ansi 18 | TERM *color* 19 | TERM con[0-9]*x[0-9]* 20 | TERM cons25 21 | TERM console 22 | TERM *direct* 23 | TERM dtterm 24 | TERM gnome 25 | TERM hurd 26 | TERM jfbterm 27 | TERM konsole 28 | TERM kterm 29 | TERM linux 30 | TERM linux-c 31 | TERM mlterm 32 | TERM putty 33 | TERM rxvt* 34 | TERM screen* 35 | TERM st 36 | TERM terminator 37 | TERM tmux* 38 | TERM vt48;2;98;114;164 39 | TERM xterm* 40 | 41 | # Below are the color init strings for the basic file types. 42 | # One can use codes for 256 or more colors supported by modern terminals. 43 | # The default color codes use the capabilities of an 8 color terminal 44 | # with some additional attributes as per the following codes: 45 | # Attribute codes: 46 | # 00=none 01=bold 04=underscore 05=blink 07=reverse 08=concealed 47 | # Text color codes: 48 | # 38;2;33;34;44=black 38;2;255;85;85=red 38;2;80;250;123=green 38;2;241;250;140=yellow 38;2;189;147;249=blue 38;2;255;121;198=magenta 38;2;139;233;253=cyan 38;2;248;248;242=white 49 | # Background color codes: 50 | # 48;2;33;34;44=black 48;2;255;85;85=red 48;2;80;250;123=green 48;2;241;250;140=yellow 48;2;189;147;249=blue 48;2;255;121;198=magenta 48;2;139;233;253=cyan 48;2;248;248;242=white 51 | #NORMAL 00 # no color code at all 52 | #FILE 00 # regular file: use no color at all 53 | RESET 0 # reset to "normal" color 54 | DIR 01;38;2;189;147;249 # directory 55 | LINK 01;38;2;139;233;253 # symbolic link. (If you set this to 'target' instead of a 56 | # numerical value, the color is as for the file pointed to.) 57 | MULTIHARDLINK 00 # regular file with more than one link 58 | FIFO 48;2;33;34;44;38;2;241;250;140 # pipe 59 | SOCK 01;38;2;255;121;198 # socket 60 | DOOR 01;38;2;255;121;198 # door 61 | BLK 48;2;33;34;44;38;2;241;250;140;01 # block device driver 62 | CHR 48;2;33;34;44;38;2;241;250;140;01 # character device driver 63 | ORPHAN 48;2;33;34;44;38;2;255;85;85;01 # symlink to nonexistent file, or non-stat'able file ... 64 | MISSING 00 # ... and the files they point to 65 | SETUID 38;2;248;248;242;48;2;255;85;85 # file that is setuid (u+s) 66 | SETGID 38;2;33;34;44;48;2;241;250;140 # file that is setgid (g+s) 67 | CAPABILITY 00 # file with capability (very expensive to lookup) 68 | STICKY_OTHER_WRITABLE 38;2;33;34;44;48;2;80;250;123 # dir that is sticky and other-writable (+t,o+w) 69 | OTHER_WRITABLE 38;2;189;147;249;48;2;80;250;123 # dir that is other-writable (o+w) and not sticky 70 | STICKY 38;2;248;248;242;48;2;189;147;249 # dir with the sticky bit set (+t) and not other-writable 71 | 72 | # This is for files with execute permission: 73 | EXEC 01;38;2;80;250;123 74 | 75 | # List any file extensions like '.gz' or '.tar' that you would like ls 76 | # to color below. Put the extension, a space, and the color init string. 77 | # (and any comments you want to add after a '#') 78 | 79 | # If you use DOS-style suffixes, you may want to uncomment the following: 80 | #.cmd 01;38;2;80;250;123 # executables (bright green) 81 | #.exe 01;38;2;80;250;123 82 | #.com 01;38;2;80;250;123 83 | #.btm 01;38;2;80;250;123 84 | #.bat 01;38;2;80;250;123 85 | # Or if you want to color scripts even if they do not have the 86 | # executable bit actually set. 87 | #.sh 01;38;2;80;250;123 88 | #.csh 01;38;2;80;250;123 89 | 90 | # archives or compressed (bright red) 91 | .tar 01;38;2;255;85;85 92 | .tgz 01;38;2;255;85;85 93 | .arc 01;38;2;255;85;85 94 | .arj 01;38;2;255;85;85 95 | .taz 01;38;2;255;85;85 96 | .lha 01;38;2;255;85;85 97 | .lz4 01;38;2;255;85;85 98 | .lzh 01;38;2;255;85;85 99 | .lzma 01;38;2;255;85;85 100 | .tlz 01;38;2;255;85;85 101 | .txz 01;38;2;255;85;85 102 | .tzo 01;38;2;255;85;85 103 | .t7z 01;38;2;255;85;85 104 | .zip 01;38;2;255;85;85 105 | .z 01;38;2;255;85;85 106 | .dz 01;38;2;255;85;85 107 | .gz 01;38;2;255;85;85 108 | .lrz 01;38;2;255;85;85 109 | .lz 01;38;2;255;85;85 110 | .lzo 01;38;2;255;85;85 111 | .xz 01;38;2;255;85;85 112 | .zst 01;38;2;255;85;85 113 | .tzst 01;38;2;255;85;85 114 | .bz2 01;38;2;255;85;85 115 | .bz 01;38;2;255;85;85 116 | .tbz 01;38;2;255;85;85 117 | .tbz2 01;38;2;255;85;85 118 | .tz 01;38;2;255;85;85 119 | .deb 01;38;2;255;85;85 120 | .rpm 01;38;2;255;85;85 121 | .jar 01;38;2;255;85;85 122 | .war 01;38;2;255;85;85 123 | .ear 01;38;2;255;85;85 124 | .sar 01;38;2;255;85;85 125 | .rar 01;38;2;255;85;85 126 | .alz 01;38;2;255;85;85 127 | .ace 01;38;2;255;85;85 128 | .zoo 01;38;2;255;85;85 129 | .cpio 01;38;2;255;85;85 130 | .7z 01;38;2;255;85;85 131 | .rz 01;38;2;255;85;85 132 | .cab 01;38;2;255;85;85 133 | .wim 01;38;2;255;85;85 134 | .swm 01;38;2;255;85;85 135 | .dwm 01;38;2;255;85;85 136 | .esd 01;38;2;255;85;85 137 | 138 | # image formats 139 | .avif 01;38;2;255;121;198 140 | .jpg 01;38;2;255;121;198 141 | .jpeg 01;38;2;255;121;198 142 | .mjpg 01;38;2;255;121;198 143 | .mjpeg 01;38;2;255;121;198 144 | .gif 01;38;2;255;121;198 145 | .bmp 01;38;2;255;121;198 146 | .pbm 01;38;2;255;121;198 147 | .pgm 01;38;2;255;121;198 148 | .ppm 01;38;2;255;121;198 149 | .tga 01;38;2;255;121;198 150 | .xbm 01;38;2;255;121;198 151 | .xpm 01;38;2;255;121;198 152 | .tif 01;38;2;255;121;198 153 | .tiff 01;38;2;255;121;198 154 | .png 01;38;2;255;121;198 155 | .svg 01;38;2;255;121;198 156 | .svgz 01;38;2;255;121;198 157 | .mng 01;38;2;255;121;198 158 | .pcx 01;38;2;255;121;198 159 | .mov 01;38;2;255;121;198 160 | .mpg 01;38;2;255;121;198 161 | .mpeg 01;38;2;255;121;198 162 | .m2v 01;38;2;255;121;198 163 | .mkv 01;38;2;255;121;198 164 | .webm 01;38;2;255;121;198 165 | .webp 01;38;2;255;121;198 166 | .ogm 01;38;2;255;121;198 167 | .mp4 01;38;2;255;121;198 168 | .m4v 01;38;2;255;121;198 169 | .mp4v 01;38;2;255;121;198 170 | .vob 01;38;2;255;121;198 171 | .qt 01;38;2;255;121;198 172 | .nuv 01;38;2;255;121;198 173 | .wmv 01;38;2;255;121;198 174 | .asf 01;38;2;255;121;198 175 | .rm 01;38;2;255;121;198 176 | .rmvb 01;38;2;255;121;198 177 | .flc 01;38;2;255;121;198 178 | .avi 01;38;2;255;121;198 179 | .fli 01;38;2;255;121;198 180 | .flv 01;38;2;255;121;198 181 | .gl 01;38;2;255;121;198 182 | .dl 01;38;2;255;121;198 183 | .xcf 01;38;2;255;121;198 184 | .xwd 01;38;2;255;121;198 185 | .yuv 01;38;2;255;121;198 186 | .cgm 01;38;2;255;121;198 187 | .emf 01;38;2;255;121;198 188 | 189 | # https://wiki.xiph.org/MIME_Types_and_File_Extensions 190 | .ogv 01;38;2;255;121;198 191 | .ogx 01;38;2;255;121;198 192 | 193 | # audio formats 194 | .aac 00;38;2;139;233;253 195 | .au 00;38;2;139;233;253 196 | .flac 00;38;2;139;233;253 197 | .m4a 00;38;2;139;233;253 198 | .mid 00;38;2;139;233;253 199 | .midi 00;38;2;139;233;253 200 | .mka 00;38;2;139;233;253 201 | .mp3 00;38;2;139;233;253 202 | .mpc 00;38;2;139;233;253 203 | .ogg 00;38;2;139;233;253 204 | .ra 00;38;2;139;233;253 205 | .wav 00;38;2;139;233;253 206 | 207 | # https://wiki.xiph.org/MIME_Types_and_File_Extensions 208 | .oga 00;38;2;139;233;253 209 | .opus 00;38;2;139;233;253 210 | .spx 00;38;2;139;233;253 211 | .xspf 00;38;2;139;233;253 212 | 213 | # backup files 214 | *~ 00;38;2;98;114;164 215 | *# 00;38;2;98;114;164 216 | .bak 00;38;2;98;114;164 217 | .old 00;38;2;98;114;164 218 | .orig 00;38;2;98;114;164 219 | .part 00;38;2;98;114;164 220 | .rej 00;38;2;98;114;164 221 | .swp 00;38;2;98;114;164 222 | .tmp 00;38;2;98;114;164 223 | .dpkg-dist 00;38;2;98;114;164 224 | .dpkg-old 00;38;2;98;114;164 225 | .ucf-dist 00;38;2;98;114;164 226 | .ucf-new 00;38;2;98;114;164 227 | .ucf-old 00;38;2;98;114;164 228 | .rpmnew 00;38;2;98;114;164 229 | .rpmorig 00;38;2;98;114;164 230 | .rpmsave 00;38;2;98;114;164 231 | 232 | # Subsequent TERM or COLORTERM entries, can be used to add / override 233 | # config specific to those matching environment variables. 234 | -------------------------------------------------------------------------------- /githooks/pre-push: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | # This script can be run as a pre-push hook locally on repositories to add messages / ensure we're not pushing to the wrong branch etc... 4 | 5 | branch_name=$(git symbolic-ref --short HEAD) 6 | if [ "$branch_name" == "main" ] || [ "$branch_name" == "master" ]; then 7 | echo "WARNING: You are pushing to the $branch_name branch!" 8 | read -r -p "Are you sure you want to push to $branch_name? [y/N] " response 9 | if [[ "$response" =~ ^([yY][eE][sS]|[yY])$ ]]; then 10 | echo "Pushing to $branch_name" 11 | else 12 | echo "Aborting push" 13 | exit 1 14 | fi 15 | fi 16 | -------------------------------------------------------------------------------- /htoprc: -------------------------------------------------------------------------------- 1 | # Beware! This file is rewritten by htop when settings are changed in the interface. 2 | # The parser is also very primitive, and not human-friendly. 3 | htop_version=3.2.2 4 | config_reader_min_version=3 5 | fields=0 48 17 18 38 39 40 2 52 46 47 111 115 116 49 1 6 | hide_kernel_threads=1 7 | hide_userland_threads=1 8 | hide_running_in_container=0 9 | shadow_other_users=1 10 | show_thread_names=0 11 | show_program_path=1 12 | highlight_base_name=1 13 | highlight_deleted_exe=1 14 | shadow_distribution_path_prefix=1 15 | highlight_megabytes=1 16 | highlight_threads=1 17 | highlight_changes=0 18 | highlight_changes_delay_secs=5 19 | find_comm_in_cmdline=1 20 | strip_exe_from_cmdline=1 21 | show_merged_command=1 22 | header_margin=1 23 | screen_tabs=1 24 | detailed_cpu_time=1 25 | cpu_count_from_one=0 26 | show_cpu_usage=1 27 | show_cpu_frequency=1 28 | show_cpu_temperature=1 29 | degree_fahrenheit=0 30 | update_process_names=0 31 | account_guest_in_cpu_meter=0 32 | color_scheme=6 33 | enable_mouse=0 34 | delay=15 35 | hide_function_bar=0 36 | header_layout=two_50_50 37 | column_meters_0=AllCPUs2 Memory 38 | column_meter_modes_0=1 1 39 | column_meters_1=Tasks Systemd Swap LoadAverage DiskIO NetworkIO Uptime 40 | column_meter_modes_1=2 2 1 2 2 2 2 41 | tree_view=0 42 | sort_key=47 43 | tree_sort_key=46 44 | sort_direction=-1 45 | tree_sort_direction=-1 46 | tree_view_always_by_pid=0 47 | all_branches_collapsed=0 48 | screen:Main=PID USER PRIORITY NICE M_VIRT M_RESIDENT M_SHARE STATE PERCENT_NORM_CPU PERCENT_CPU PERCENT_MEM IO_RATE PERCENT_CPU_DELAY PERCENT_IO_DELAY TIME Command 49 | .sort_key=PERCENT_MEM 50 | .tree_sort_key=PERCENT_CPU 51 | .tree_view=0 52 | .tree_view_always_by_pid=0 53 | .sort_direction=-1 54 | .tree_sort_direction=-1 55 | .all_branches_collapsed=0 56 | screen:I/O=PID USER IO_PRIORITY IO_RATE IO_READ_RATE IO_WRITE_RATE PERCENT_SWAP_DELAY PERCENT_IO_DELAY Command 57 | .sort_key=IO_RATE 58 | .tree_sort_key=PID 59 | .tree_view=0 60 | .tree_view_always_by_pid=0 61 | .sort_direction=-1 62 | .tree_sort_direction=1 63 | .all_branches_collapsed=0 64 | -------------------------------------------------------------------------------- /renovate.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "https://docs.renovatebot.com/renovate-schema.json", 3 | "extends": ["github>sammcj/renovate-config"], 4 | "description": "This file is managed in automation-repo", 5 | "assignees": ["sammcj"], 6 | "ignorePaths": [ 7 | ".github/workflows/codeball.yml", 8 | ".github/workflows/detect-secrets.yml", 9 | ".github/workflows/label-sync.yml", 10 | ".github/workflows/lint-docker.yml", 11 | ".github/workflows/lint-pr-actions-skip.yml", 12 | ".github/workflows/lint-pr-actions.yml", 13 | ".github/workflows/lint-pr-markdown.yml", 14 | ".github/workflows/lint-tf.yml", 15 | ".github/workflows/mirror.yml", 16 | ".github/workflows/pr-labeller.yml", 17 | ".github/workflows/todo.yml", 18 | ".github/workflows/workflows_disabled/*.yml", 19 | ".github/workflows/delete-disabled-workflows.yml", 20 | "files/**", 21 | "themes/**", 22 | "dist/**", 23 | "node_modules/**" 24 | ] 25 | } 26 | -------------------------------------------------------------------------------- /rsyncd.conf: -------------------------------------------------------------------------------- 1 | # ~/.rsyncd.conf 2 | 3 | exclude=lost+found/ .DS_Store 4 | ignore_nonreadable=yes 5 | rsync_long_args=--partial --progress --verbose 6 | -------------------------------------------------------------------------------- /run_tests.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # 3 | # Assumptions 4 | # - shellcheck is installed `brew install shellcheck` 5 | 6 | echo "Testing bootstrap_shells.sh for bash errors..." 7 | shellcheck bootstrap_shell.sh 8 | 9 | echo "Testing this script (run_tests.sh) for bash errors..." 10 | shellcheck run_tests.sh 11 | 12 | echo "Testing included .rc files for bash errors..." 13 | shellcheck -e SC1090 -e SC2148 -e SC2034 ./*.rc 14 | -------------------------------------------------------------------------------- /tmux.conf: -------------------------------------------------------------------------------- 1 | # vim: ft=tmux 2 | 3 | # List of plugins 4 | set -g @plugin 'tmux-plugins/tpm' 5 | set -g @plugin 'tmux-plugins/tmux-sensible' 6 | set -g @plugin '27medkamal/tmux-session-wizard' 7 | set -g @plugin 'dracula/tmux' 8 | set -g @plugin 'laktak/extrakto' 9 | # Don't forget to run prefix + I to install plugins 10 | 11 | # Source .tmux.conf as suggested in `man tmux` 12 | unbind r 13 | bind r source-file ~/.tmux.conf \; display-message 'Configuration reloaded.' 14 | 15 | 16 | # Dracula 17 | set -g @dracula-show-fahrenheit false 18 | set -g @dracula-show-weather false 19 | set -g @dracula-show-location false 20 | set -g @dracula-show-empty-plugins false 21 | set -g @dracula-show-timezone false 22 | set -g @dracula-show-battery false 23 | set -g @dracula-cpu-display-load false 24 | set -g @dracula-cpu-display-temperature false 25 | set -g @dracula-cpu-display-frequency false 26 | set -g @dracula-cpu-display-usage false 27 | set -g @dracula-cpu-display-cores false 28 | set -g @dracula-cpu-display-threads false 29 | set -g @dracula-cpu-display-temperature false 30 | set -g @dracula-plugins "git time" 31 | 32 | # Bind to CTRL+z 33 | unbind C-b 34 | set-option -g prefix C-z 35 | bind-key C-z send-prefix 36 | bind z last-window 37 | 38 | # bind CTRL+a to go to start of line 39 | unbind C-a 40 | bind C-a send-prefix 41 | # bind-key C-a send-key C-a 42 | 43 | # Bind to CTRL+a 44 | # unbind C-b 45 | # set-option -g prefix C-a 46 | # bind-key C-a send-prefix 47 | # bind a last-window 48 | 49 | # Dont break CTRL+Left/Right 50 | # also in ~/.zshrc: 51 | # bindkey "^[[1;5C" forward-word #control left in xterm/tmux 52 | # bindkey "^[[1;5D" backward-word #control right in xterm/tmux 53 | set-window-option -g xterm-keys on 54 | set -g xterm-keys on 55 | unbind C-Left 56 | unbind C-Right 57 | 58 | # Improve colors 59 | set -g default-terminal xterm-256color 60 | 61 | # Increase scrollback buffer 62 | set -g history-limit 30000 63 | 64 | # Increase tmux messages display duration from 750ms to 4s 65 | set -g display-time 4000 66 | 67 | # Refresh 'status-left' and 'status-right' more often, from every 15s to 5s 68 | set -g status-interval 5 69 | 70 | # Customize the status line 71 | set -g status-fg green 72 | set -g status-bg black 73 | 74 | # Emacs key bindings in tmux command prompt (prefix + :) are better than 75 | # vi keys, even for vim users 76 | set -g status-keys emacs 77 | 78 | setw -g mode-keys emacs 79 | 80 | # split panes using | and - 81 | bind | split-window -h 82 | bind - split-window -v 83 | unbind '"' 84 | unbind % 85 | 86 | 87 | # switch panes using Alt-arrow without prefix 88 | bind -n M-Left select-pane -L 89 | bind -n M-Right select-pane -R 90 | bind -n M-Up select-pane -U 91 | bind -n M-Down select-pane -D 92 | 93 | # Window navigation 94 | bind-key C-Tab next-window 95 | bind-key C-S-Tab previous-window 96 | bind C-p previous-window 97 | bind C-n next-window 98 | 99 | # dim inactive window text 100 | set -g window-style fg=colour15 101 | set -g window-active-style fg=colour7 102 | 103 | # Focus events enabled for terminals that support them 104 | set -g focus-events on 105 | 106 | # Super useful when using "grouped sessions" and multi-monitor setup 107 | setw -g aggressive-resize on 108 | 109 | # Extract output using FZF 110 | # set -g @extrakto_key 'e' 111 | 112 | # Enable mouse mode (tmux 2.1 and above) 113 | set -g mouse on 114 | 115 | # Address vim mode switching delay (http://superuser.com/a/252717/65504) 116 | set -s escape-time 0 117 | 118 | # Initialize TMUX plugin manager (keep this line at the very bottom of tmux.conf) 119 | run '~/.tmux/plugins/tpm/tpm' 120 | -------------------------------------------------------------------------------- /zshrc: -------------------------------------------------------------------------------- 1 | # Amazon Q pre block. Keep at the top of this file. 2 | ### q slow debugging ### 3 | # date 4 | # echo "STARTING: amazon q pre block loading from .zshrc" 5 | # # set zsh to echo verbose 6 | # set -x 7 | # ### 8 | # only run if LOADING_Q is true 9 | if [[ "$LOADING_Q" == "true" ]]; then 10 | # Amazon Q post block. Keep at the bottom of this file. 11 | [[ -f "${HOME}/Library/Application Support/amazon-q/shell/zshrc.pre.zsh" ]] && builtin source "${HOME}/Library/Application Support/amazon-q/shell/zshrc.pre.zsh" 12 | fi 13 | # ### q slow debugging ### 14 | # date 15 | # # unset zsh to echo verbose 16 | # set +x 17 | # echo "DONE: amazon q pre block loaded from .zshrc" 18 | ### 19 | ## AMAZON Q MAKES EVERYTHING SLOWWWWWW 20 | 21 | # shellcheck disable=SC2148 disable=SC1090 shell=bash 22 | # ~/.zshrc 23 | 24 | # set +x 25 | 26 | # only run set +m if we're interactive 27 | if [[ $- == *i* ]]; then 28 | set +m # Make jobs quiet by default 29 | fi 30 | # There is an alias to jump to the directory with the various 31 | # included zsh configs, simply type `zshconfig` at the prompt. 32 | 33 | ####### PROFILING ####### 34 | # Uncomment below to enable debug timing 35 | # zmodload zsh/zprof 36 | # Remember to uncomment zprof at the end of the file! 37 | #### END PROFILING ###### 38 | 39 | bg_silent() { 40 | # background a task quietly and disown 41 | { "$@" 2>&3 & } 3>&2 2>/dev/null 42 | disown &>/dev/null 43 | } 44 | 45 | ## Source all configs 46 | 47 | if [[ -d $HOME/Library/Mobile\ Documents/com\~apple\~CloudDocs/Dropbox\ Import/dotfiles/shell_config ]]; then 48 | for file in "$HOME"/Library/Mobile\ Documents/com\~apple\~CloudDocs/Dropbox\ Import/dotfiles/shell_config/*.rc; do 49 | source "$file" 50 | done 51 | fi 52 | 53 | ## Add ssh keys to agent if not already added 54 | # ssh-add-keys # TODO: disabled 2025-03-16 to see if it helps performance, reenable if ssh stops working 55 | 56 | ### Below are items added by installer scripts (usually homebrew) #### 57 | 58 | [ -f ~/.fzf.zsh ] && source ~/.fzf.zsh 59 | source /opt/homebrew/Cellar/fzf/*/shell/key-bindings.zsh 60 | 61 | # Enable direnv - https://direnv.net 62 | # eval "$(direnv hook zsh)" 63 | 64 | if_not_in_vscode bg_silent test -e "${HOME}/.iterm2_shell_integration.zsh" && bg_silent source "${HOME}/.iterm2_shell_integration.zsh" 65 | 66 | zstyle ':completion:*' menu select 67 | fpath+=~/.zfunc 68 | 69 | # only run set -m if we're interactive 70 | if [[ $- == *i* ]]; then 71 | set -m # reenable job output 72 | fi 73 | 74 | # >>> mamba initialize >>> 75 | # !! Contents within this block are managed by 'mamba init' !! 76 | # export MAMBA_EXE='/opt/homebrew/opt/micromamba/bin/micromamba'; 77 | # export MAMBA_ROOT_PREFIX='/Users/samm/micromamba'; 78 | # __mamba_setup="$("$MAMBA_EXE" shell hook --shell zsh --root-prefix "$MAMBA_ROOT_PREFIX" 2> /dev/null)" 79 | # if [ $? -eq 0 ]; then 80 | # eval "$__mamba_setup" 81 | # else 82 | # alias micromamba="$MAMBA_EXE" # Fallback on help from mamba activate 83 | # fi 84 | # unset __mamba_setup 85 | # # <<< mamba initialize <<< 86 | 87 | # >>> conda initialize >>> 88 | # !! Contents within this block are managed by 'conda init' !! 89 | # __conda_setup="$('/opt/homebrew/Caskroom/mambaforge/base/bin/conda' 'shell.zsh' 'hook' 2> /dev/null)" 90 | # if [ $? -eq 0 ]; then 91 | # eval "$__conda_setup" 92 | # else 93 | # if [ -f "/opt/homebrew/Caskroom/mambaforge/base/etc/profile.d/conda.sh" ]; then 94 | # . "/opt/homebrew/Caskroom/mambaforge/base/etc/profile.d/conda.sh" 95 | # else 96 | # export PATH="/opt/homebrew/Caskroom/mambaforge/base/bin:$PATH" 97 | # fi 98 | # fi 99 | # unset __conda_setup 100 | 101 | # if [ -f "/opt/homebrew/Caskroom/mambaforge/base/etc/profile.d/mamba.sh" ]; then 102 | # . "/opt/homebrew/Caskroom/mambaforge/base/etc/profile.d/mamba.sh" 103 | # fi 104 | # <<< conda initialize <<< 105 | 106 | ### zoxide ### 107 | eval "$(zoxide init zsh)" 108 | ### zoxide ### 109 | 110 | # Load custom aliases 111 | export PATH="$PATH:/Users/samm/Fltr" 112 | 113 | # tabtab source for electron-forge package 114 | # uninstall by removing these lines or running `tabtab uninstall electron-forge` 115 | # [[ -f /Users/samm/.npm/_npx/6913fdfd1ea7a741/node_modules/tabtab/.completions/electron-forge.zsh ]] && . /Users/samm/.npm/_npx/6913fdfd1ea7a741/node_modules/tabtab/.completions/electron-forge.zsh 116 | 117 | # Added by LM Studio CLI tool (lms) 118 | export PATH="$PATH:/Users/samm/.cache/lm-studio/bin" 119 | if [ -f "/Users/samm/.config/fabric/fabric-bootstrap.inc" ] && if_not_in_vscode; then . "/Users/samm/.config/fabric/fabric-bootstrap.inc"; fi 120 | 121 | fpath+=~/.zfunc 122 | 123 | export PATH="/opt/homebrew/opt/tcl-tk@8/bin:$PATH" 124 | 125 | # # The next line updates PATH for the Google Cloud SDK. 126 | if [ -f '/Users/samm/Downloads/google-cloud-sdk/path.zsh.inc' ] && if_not_in_vscode; then . '/Users/samm/Downloads/google-cloud-sdk/path.zsh.inc'; fi 127 | 128 | # The next line enables shell command completion for gcloud. 129 | if [ -f '/Users/samm/Downloads/google-cloud-sdk/completion.zsh.inc' ] && if_not_in_vscode; then . '/Users/samm/Downloads/google-cloud-sdk/completion.zsh.inc'; fi 130 | 131 | # # Amazon Q post block. Keep at the bottom of this file. 132 | if [[ "$LOADING_Q" == "true" ]]; then 133 | # Amazon Q post block. Keep at the bottom of this file. 134 | [[ -f "${HOME}/Library/Application Support/amazon-q/shell/zshrc.post.zsh" ]] && builtin source "${HOME}/Library/Application Support/amazon-q/shell/zshrc.post.zsh" 135 | fi 136 | 137 | # ####### PROFILING ####### 138 | # # Uncomment below to enable debug timing 139 | # zprof 140 | # #### END PROFILING ###### 141 | 142 | # echo ".zshrc loaded now" 143 | 144 | # >>> CLOI_HISTORY_SETTINGS >>> 145 | setopt INC_APPEND_HISTORY 146 | setopt SHARE_HISTORY 147 | # <<< CLOI_HISTORY_SETTINGS <<< 148 | --------------------------------------------------------------------------------