Repository: bkuhlmann/dotfiles Branch: main Commit: 40162a1db1b9 Files: 72 Total size: 193.3 KB Directory structure: gitextract_v40a_637/ ├── .circleci/ │ └── config.yml ├── .config/ │ └── rubocop/ │ └── config.yml ├── .github/ │ ├── FUNDING.yml │ ├── ISSUE_TEMPLATE/ │ │ ├── config.yml │ │ └── issue.md │ └── PULL_REQUEST_TEMPLATE.md ├── .gitignore ├── .ruby-version ├── CITATION.cff ├── Gemfile ├── LICENSE.adoc ├── README.adoc ├── Rakefile ├── bin/ │ ├── rake │ └── run └── lib/ ├── options.sh ├── templates/ │ ├── .agignore.tt │ ├── .bash_profile.tt │ ├── .bashrc.tt │ ├── .cache/ │ │ └── pgenv/ │ │ └── config/ │ │ └── default.conf.tt │ ├── .config/ │ │ ├── aprc.tt │ │ ├── bash/ │ │ │ ├── aliases.sh.tt │ │ │ ├── colors.sh.tt │ │ │ ├── environment.sh.tt │ │ │ ├── functions-private.sh.tt │ │ │ ├── functions-public.sh.tt │ │ │ └── prompt.sh.tt │ │ ├── duti/ │ │ │ └── configuration.duti.tt │ │ ├── git/ │ │ │ ├── attributes.tt │ │ │ ├── commit_message.txt.tt │ │ │ ├── configuration.tt │ │ │ ├── hooks/ │ │ │ │ ├── applypatch-msg.tt │ │ │ │ ├── commit-msg.tt │ │ │ │ ├── extensions/ │ │ │ │ │ ├── brakeman.sh.tt │ │ │ │ │ ├── bundler.sh.tt │ │ │ │ │ ├── comments.sh.tt │ │ │ │ │ ├── ctags.sh.tt │ │ │ │ │ ├── dotenv.sh.tt │ │ │ │ │ ├── git.sh.tt │ │ │ │ │ ├── hadolint.sh.tt │ │ │ │ │ ├── java_script.sh.tt │ │ │ │ │ ├── license_finder.sh.tt │ │ │ │ │ ├── osv.sh.tt │ │ │ │ │ ├── reek.sh.tt │ │ │ │ │ ├── rspec.sh.tt │ │ │ │ │ ├── rubocop.sh.tt │ │ │ │ │ └── support.sh.tt │ │ │ │ ├── post-applypatch.tt │ │ │ │ ├── post-checkout.tt │ │ │ │ ├── post-commit.tt │ │ │ │ ├── post-merge.tt │ │ │ │ ├── post-rewrite.tt │ │ │ │ ├── pre-applypatch.tt │ │ │ │ ├── pre-commit.tt │ │ │ │ ├── pre-merge-commit.tt │ │ │ │ ├── pre-push.tt │ │ │ │ ├── pre-rebase.tt │ │ │ │ └── prepare-commit-msg.tt │ │ │ ├── ignore.tt │ │ │ └── template/ │ │ │ └── mkdir.command │ │ ├── irb/ │ │ │ └── irbrc.tt │ │ ├── pgenv/ │ │ │ └── initialize.tt │ │ └── rubocop/ │ │ └── config.yml.tt │ ├── .ctags.tt │ ├── .erdconfig.tt │ ├── .hushlogin.tt │ ├── .inputrc.tt │ ├── .npmrc.tt │ ├── .psqlrc.tt │ ├── .ruby-version.tt │ └── .vimrc.tt └── utilities.sh ================================================ FILE CONTENTS ================================================ ================================================ FILE: .circleci/config.yml ================================================ version: 2.1 jobs: build: working_directory: ~/project docker: - image: bkuhlmann/alpine-ruby:latest steps: - checkout - restore_cache: name: Gems Restore keys: - gem-cache-{{.Branch}}-{{checksum "Gemfile"}} - gem-cache- - run: name: Gems Install command: | gem update --system bundle config set path "vendor/bundle" bundle install - save_cache: name: Gems Store key: gem-cache-{{.Branch}}-{{checksum "Gemfile"}} paths: - vendor/bundle - run: name: Rake command: bundle exec rake ================================================ FILE: .config/rubocop/config.yml ================================================ inherit_gem: caliber: config/all.yml ================================================ FILE: .github/FUNDING.yml ================================================ github: [bkuhlmann] ================================================ FILE: .github/ISSUE_TEMPLATE/config.yml ================================================ blank_issues_enabled: false contact_links: - name: Community url: https://alchemists.io/community about: Please ask questions or discuss specifics here. - name: Security url: https://alchemists.io/policies/security about: Please report security vulnerabilities here. ================================================ FILE: .github/ISSUE_TEMPLATE/issue.md ================================================ --- name: Issue title: "Add|Update|Fix|Remove|Refactor " about: Report an issue. Please use only one of the subject prefixes. --- ## Why ## How ## Notes ================================================ FILE: .github/PULL_REQUEST_TEMPLATE.md ================================================ ## Overview ## Screenshots/Screencasts ## Details ================================================ FILE: .gitignore ================================================ Gemfile.lock ================================================ FILE: .ruby-version ================================================ 4.0.3 ================================================ FILE: CITATION.cff ================================================ cff-version: 1.2.0 message: Please use the following metadata when citing this project in your work. title: Dotfiles abstract: Shell scripts for applying default settings to UNIX-based operating systems. version: 57.0.0 license: Hippocratic-2.1 date-released: 2026-04-17 authors: - family-names: Kuhlmann given-names: Brooke affiliation: Alchemists orcid: https://orcid.org/0000-0002-5810-6268 keywords: - bash - shell - scripts - dotfiles repository-code: https://github.com/bkuhlmann/dotfiles repository-artifact: https://alchemists.io/projects/dotfiles url: https://alchemists.io/projects/dotfiles ================================================ FILE: Gemfile ================================================ # frozen_string_literal: true ruby file: ".ruby-version" source "https://rubygems.org" gem "caliber", "~> 0.90" gem "debug", "~> 1.11" gem "git-lint", "~> 10.0" gem "rake", "~> 13.4" ================================================ FILE: LICENSE.adoc ================================================ = Hippocratic License Version: 2.1.0. Purpose. The purpose of this License is for the Licensor named above to permit the Licensee (as defined below) broad permission, if consistent with Human Rights Laws and Human Rights Principles (as each is defined below), to use and work with the Software (as defined below) within the full scope of Licensor’s copyright and patent rights, if any, in the Software, while ensuring attribution and protecting the Licensor from liability. Permission and Conditions. The Licensor grants permission by this license ("License"), free of charge, to the extent of Licensor’s rights under applicable copyright and patent law, to any person or entity (the "Licensee") obtaining a copy of this software and associated documentation files (the "Software"), to do everything with the Software that would otherwise infringe (i) the Licensor’s copyright in the Software or (ii) any patent claims to the Software that the Licensor can license or becomes able to license, subject to all of the following terms and conditions: * Acceptance. This License is automatically offered to every person and entity subject to its terms and conditions. Licensee accepts this License and agrees to its terms and conditions by taking any action with the Software that, absent this License, would infringe any intellectual property right held by Licensor. * Notice. Licensee must ensure that everyone who gets a copy of any part of this Software from Licensee, with or without changes, also receives the License and the above copyright notice (and if included by the Licensor, patent, trademark and attribution notice). Licensee must cause any modified versions of the Software to carry prominent notices stating that Licensee changed the Software. For clarity, although Licensee is free to create modifications of the Software and distribute only the modified portion created by Licensee with additional or different terms, the portion of the Software not modified must be distributed pursuant to this License. If anyone notifies Licensee in writing that Licensee has not complied with this Notice section, Licensee can keep this License by taking all practical steps to comply within 30 days after the notice. If Licensee does not do so, Licensee’s License (and all rights licensed hereunder) shall end immediately. * Compliance with Human Rights Principles and Human Rights Laws. [arabic] . Human Rights Principles. [loweralpha] .. Licensee is advised to consult the articles of the United Nations Universal Declaration of Human Rights and the United Nations Global Compact that define recognized principles of international human rights (the "Human Rights Principles"). Licensee shall use the Software in a manner consistent with Human Rights Principles. .. Unless the Licensor and Licensee agree otherwise, any dispute, controversy, or claim arising out of or relating to (i) Section 1(a) regarding Human Rights Principles, including the breach of Section 1(a), termination of this License for breach of the Human Rights Principles, or invalidity of Section 1(a) or (ii) a determination of whether any Law is consistent or in conflict with Human Rights Principles pursuant to Section 2, below, shall be settled by arbitration in accordance with the Hague Rules on Business and Human Rights Arbitration (the "Rules"); provided, however, that Licensee may elect not to participate in such arbitration, in which event this License (and all rights licensed hereunder) shall end immediately. The number of arbitrators shall be one unless the Rules require otherwise. + Unless both the Licensor and Licensee agree to the contrary: (1) All documents and information concerning the arbitration shall be public and may be disclosed by any party; (2) The repository referred to under Article 43 of the Rules shall make available to the public in a timely manner all documents concerning the arbitration which are communicated to it, including all submissions of the parties, all evidence admitted into the record of the proceedings, all transcripts or other recordings of hearings and all orders, decisions and awards of the arbitral tribunal, subject only to the arbitral tribunal’s powers to take such measures as may be necessary to safeguard the integrity of the arbitral process pursuant to Articles 18, 33, 41 and 42 of the Rules; and (3) Article 26(6) of the Rules shall not apply. . Human Rights Laws. The Software shall not be used by any person or entity for any systems, activities, or other uses that violate any Human Rights Laws. "Human Rights Laws" means any applicable laws, regulations, or rules (collectively, "Laws") that protect human, civil, labor, privacy, political, environmental, security, economic, due process, or similar rights; provided, however, that such Laws are consistent and not in conflict with Human Rights Principles (a dispute over the consistency or a conflict between Laws and Human Rights Principles shall be determined by arbitration as stated above). Where the Human Rights Laws of more than one jurisdiction are applicable or in conflict with respect to the use of the Software, the Human Rights Laws that are most protective of the individuals or groups harmed shall apply. . Indemnity. Licensee shall hold harmless and indemnify Licensor (and any other contributor) against all losses, damages, liabilities, deficiencies, claims, actions, judgments, settlements, interest, awards, penalties, fines, costs, or expenses of whatever kind, including Licensor’s reasonable attorneys’ fees, arising out of or relating to Licensee’s use of the Software in violation of Human Rights Laws or Human Rights Principles. * Failure to Comply. Any failure of Licensee to act according to the terms and conditions of this License is both a breach of the License and an infringement of the intellectual property rights of the Licensor (subject to exceptions under Laws, e.g., fair use). In the event of a breach or infringement, the terms and conditions of this License may be enforced by Licensor under the Laws of any jurisdiction to which Licensee is subject. Licensee also agrees that the Licensor may enforce the terms and conditions of this License against Licensee through specific performance (or similar remedy under Laws) to the extent permitted by Laws. For clarity, except in the event of a breach of this License, infringement, or as otherwise stated in this License, Licensor may not terminate this License with Licensee. * Enforceability and Interpretation. If any term or provision of this License is determined to be invalid, illegal, or unenforceable by a court of competent jurisdiction, then such invalidity, illegality, or unenforceability shall not affect any other term or provision of this License or invalidate or render unenforceable such term or provision in any other jurisdiction; provided, however, subject to a court modification pursuant to the immediately following sentence, if any term or provision of this License pertaining to Human Rights Laws or Human Rights Principles is deemed invalid, illegal, or unenforceable against Licensee by a court of competent jurisdiction, all rights in the Software granted to Licensee shall be deemed null and void as between Licensor and Licensee. Upon a determination that any term or provision is invalid, illegal, or unenforceable, to the extent permitted by Laws, the court may modify this License to affect the original purpose that the Software be used in compliance with Human Rights Principles and Human Rights Laws as closely as possible. The language in this License shall be interpreted as to its fair meaning and not strictly for or against any party. * Disclaimer. TO THE FULL EXTENT ALLOWED BY LAW, THIS SOFTWARE COMES "AS IS," WITHOUT ANY WARRANTY, EXPRESS OR IMPLIED, AND LICENSOR AND ANY OTHER CONTRIBUTOR SHALL NOT BE LIABLE TO ANYONE FOR ANY DAMAGES OR OTHER LIABILITY ARISING FROM, OUT OF, OR IN CONNECTION WITH THE SOFTWARE OR THIS LICENSE, UNDER ANY KIND OF LEGAL CLAIM. This Hippocratic License is an link:https://ethicalsource.dev[Ethical Source license] and is offered for use by licensors and licensees at their own risk, on an "AS IS" basis, and with no warranties express or implied, to the maximum extent permitted by Laws. ================================================ FILE: README.adoc ================================================ :toc: macro :toclevels: 5 :figure-caption!: = Dotfiles These dotfiles are a collection shell scripts for applying default settings to UNIX-based operating systems. They include useful shortcuts, performance augmentation, and advanced practices that -- even if you don't apply to your own dotfiles -- should be educational for improving your own practices. By default, these are set to my preferences (namely for macOS) but you can change them to your liking by editing any of the `.tt` template files in the `home_files` directory. Read on to learn more. toc::[] == Features * Configures link:https://github.com/amazing-print/amazing_print[Amazing Print] (`.aprc`). * Configures Bash (`.config/bash`, `.bashrc`, `.bash_profile`, and `.inputrc`). * Configures link:http://bash-completion.alioth.debian.org[Bash Completion]. * Configures link:http://ctags.sourceforge.net[CTags] (`.ctags`). * Configures link:https://direnv.net[direnv]. * Configures link:https://www.docker.com[Docker]. * Configures link:https://eza.rocks[Eza]. * Configures link:https://github.com/tako8ki/frum[Frum]. * Configures link:https://git-scm.com[Git] (`.config/git`). * Configures link:https://www.gnupg.org[GPG]. * Configures `.hushlogin`. * Configures link:https://nodejs.org[Node.js]. * Configures link:https://www.npmjs.org[NPM] (`.npmrc`). * Configures link:https://www.postgresql.org[PostgreSQL] (`.psqlrc`). * Configures link:https://voormedia.github.io/rails-erd[Rails ERD] (`.erdconfig`). * Configures link:https://rspec.info[RSpec] (`.rspec`). * Configures link:https://www.ruby-lang.org[Ruby] (`.ruby-version` and `.irbrc`). * Configures link:https://github.com/bbatsov/rubocop[Rubocop] (`.rubocop.yml`). * Configures link:https://www.rust-lang.org[Rust]. * Configures link:https://github.com/ggreer/the_silver_searcher[Silver Surfer] (`.agignore`). * Configures link:https://www.sublimetext.com[Sublime Text]. * Configures link:https://www.vim.org[Vim] (`.vimrc`). * Configures link:https://www.terraform.io[Terraform]. * Configures link:https://github.com/ajeetdsouza/zoxide[Zoxide]. == Requirements . link:https://alchemists.io/projects/mac_os-config[macOS Configuration] == Setup To install, run: [source,bash] ---- git clone https://github.com/bkuhlmann/dotfiles.git cd dotfiles git checkout 57.0.0 ---- == Upgrade When upgrading to a new version, run the following: . Run: `bin/run l`. Links new files. If not using linked files, then run `bin/run d` and `bin/run i` instead. . Run: `bin/run c`. Displays file differences, if any. Usually, this will be excluded files. . Run: `exec $SHELL`. Updates current shell with the above changes. == Usage Edit any of the `.tt` (template) and/or `.command` (command) files in the `home_files` directory as you see fit. Then open a terminal window and execute the following command to install: [source,bash] ---- cd dotfiles bin/run ---- Executing the `bin/run` script will present the following options: .... s: Show managed dotfiles. i: Install dotfiles (existing files are skipped). l: Link dotfiles to this project (interactive per file, excludes: env.sh and .gitconfig). c: Check for differences between $HOME files and this project's files. d: Delete dotfiles (interactive per file, excludes: env.sh and .gitconfig). q: Quit/Exit. .... The options prompt can be skipped by passing the desired option directly to the `bin/run` script. For example, executing `bin/run s` will show all managed dotfiles by this project. After install, the following files will require manual updating: * `.bash/env.sh`: Add secret/machine-specific environment settings (if any). * `.gitconfig`: Replace all `` values for name, email, and signingKey within the `[user]` section with your own credentials. The reason the above two files are not managed by this project -- especially via symbolic links -- is because sensitive data is usually stored in these files and you don't want this information accidentally checked into a source code repository or shared via other means. === Aliases ==== https://asciidoctor.org:[ASCII Doctor] .... ad = "asciidoctor" .... ==== https://www.gnu.org/software/bash:[Bash] .... bashe = '$EDITOR $HOME/.config/bash/environment.sh' bashs = 'exec $SHELL' .... ==== https://bundler.io:[Bundler] .... ba = "bundle add" bb = "bundle binstubs" bce = '$EDITOR $BUNDLE_USER_CONFIG' bch = "rm -f Gemfile.lock; bundle check" bd = "bundle doctor" be = "bundle exec" bi = "bundle install" blo = 'bundle list --paths | fzf | xargs $EDITOR' bo = "bundle outdated --only-explicit" br = "bundle remove" .... ==== https://crystal-lang.org:[Crystal] .... cr = "crystal" crb = "crystal build" crd = "crystal docs" crdo = "open docs/index.html" crr = "crystal run" crs = "crystal spec" .... ==== https://direnv.net:[direnv] .... denva = "direnv allow" denvr = "direnv reload" denvs = "direnv status" .... ==== https://www.docker.com:[Docker] .... dr = "docker" drb = "docker build" drd = "docker system prune --force && docker buildx prune --force" dri = "docker images" drp = "docker ps --all" drt = "docker tag" .... ==== http://duti.org:[duti] .... dutia = 'duti $HOME/.config/duti/configuration.duti' .... ==== https://eza.rocks:[Eza] .... x1 = "eza --oneline --all --group-directories-first" x = "eza --all --all --long --header --group --group-directories-first --time-style long-iso --git" xt = "eza --tree --all --group-directories-first --ignore-glob '*.git' --git-ignore" xtv = "eza --tree --all --group-directories-first --ignore-glob '*.git'" .... ==== https://github.com/Schniz/fnm:[Fast Node Manager] .... js = "fnm" jsd = "fnm default" jse = "fnm env" jsi = "fnm install" jsl = "fnm list" jss = "fnm use" jsu = "fnm uninstall" .... ==== https://github.com/TaKO8Ki/frum:[Frum] .... rb = "frum" rbd = "frum global" rbl = "frum versions" rbs = "frum local" rbu = "frum uninstall" .... ==== https://github.com/junegunn/fzf:[Fuzzy Finder] .... ff = "_fzf_preview_and_select | xargs -0 -o \$EDITOR" .... ==== https://alchemists.io/projects/gemsmith:[Gemsmith] .... gsb = "gemsmith build --name" gsc = "gemsmith config --edit" gse = "gemsmith --edit" gsi = "gemsmith --install" gsp = "gemsmith --publish" gsq = "rake quality" gsv = "gemsmith --view" .... ==== General .... ... = "cd ../.." .. = "cd .." c = "clear" cat = "bat --theme DarkNeon" cdb = "cd -" du = "dust" h = "history" l1 = "ls -A1 | _copy_and_print '\n'" l = "ls -alhT" o = "open" p = 'pwd | tr -d "\r\n" | _copy_and_print' pss = "pgrep -i -l -f" rmde = "find . -type d -empty -not -path '*.git*' -delete" .... ==== https://git-scm.com:[Git] .... gall = "git add --all ." gamend = "git commit --amend" gamenda = "git commit --amend --all --no-edit" gamendh = "git commit --amend --no-edit" gap = "git ls-files --modified | _fzf_preview_and_select | xargs -0 -o -t git add --patch" gatch = "git commit --patch" gau = "git add --update" gb = "git switch" gbb = "git switch -" gbe = "git branch --edit-description" gbi = "git bisect" gbv = 'git config get branch.$(_git_branch_name).description' gbib = "git bisect bad" gbig = "git bisect good" gbih = "git bisect help" gbil = "git bisect log" gbir = "git bisect reset" gbire = "git bisect replay" gbis = "git bisect start" gbisk = "git bisect skip" gbiv = 'git bisect visualize --reverse --pretty=format:"$(_git_log_line_format)"' gbm = 'git switch $(_git_branch_default)' gbn = "_git_branch_name | _copy_and_print" gbt = "git show-branch --topics" gca = "git commit --all" gcam = "git commit --all --message" gcd = "git config list --show-origin --show-scope | fzf" gce = 'cat .git/COMMIT_EDITMSG | pbcopy' gcge = "git config edit --global" gch = "git checkout" gcl = "git clone" gcle = "git config edit --local" gcm = "git commit --message" gco = "git commit" gcp = "git cherry-pick" gcpa = "git cherry-pick --abort" gcpc = "git cherry-pick --continue" gcps = "git cherry-pick --skip" gcs = "git commit --squash" gd = "git diff" gdc = "git diff --cached" gdm = 'git diff origin/$(_git_branch_default)' gdo = 'git diff --name-only | uniq | xargs $EDITOR' gdt = "git difftool" gdtc = "git difftool --cached" gdtm = 'git difftool origin/$(_git_branch_default)' gdw = "git diff --color-words" gel = "git rm" gelc = "git rm --cached" ges = "git diff --name-only --cached | _fzf_preview_and_select | xargs -0 -o -t git reset" gf = "git fetch" gg = "git grep" gge = "git config get --global --regexp includeif | fzf | xargs \$EDITOR" gget = "git config get" gi = "git init" gl = 'git log --graph --pretty=format:"$(_git_log_line_format)" "$(_git_branch_range)"' gld = 'git log --stat --pretty=format:"$(_git_log_details_format)" "$(_git_branch_range)"' glame = "git blame -M -C" glean = "git clean -d --force" glf = 'git fetch && git log --reverse --no-merges --pretty=format:"$(_git_log_line_format)" ..@{upstream}' glh = "_git_sha | _copy_and_print" gna = "git notes add" gnd = "git notes remove" gne = "git notes edit" gnl = "git notes list" gnp = "git notes prune" gns = "git notes show" gp = "git push" gpf = "git push --force-with-lease" gpn = "git push --no-verify" gpu = "git pull" gpuo = "git pull origin" gpuom = 'git pull origin $(_git_branch_default)' gpuum = 'git pull upstream $(_git_branch_default)' gr = "git ls-files --modified | _fzf_preview_and_select | xargs -0 -o -t git restore" grba = "git rebase --abort" grbc = "git rebase --continue" grbd = "git rebase --show-current-patch" grbo = "git rebase --onto" grbs = "git rebase --skip" grbt = "git rebase --edit-todo" grev = "git revert --no-commit" grl = "git reflog --relative-date" grom = 'git fetch --all && git reset --hard origin/$(_git_branch_default)' # Reset local branch to origin/main branch. UNRECOVERABLE! grr = "git rerere" gset = "git config set" gst = "git status --short --branch" gt = "git tag" gte = 'cat .git/TAG_EDITMSG | pbcopy' gtp = "git push --tags" gtv = "git tag --verify" guthors = "git shortlog --numbered --summary --group=author --group=trailer:Co-Authored-By" gwl = "git worktree list" gwp = "git worktree prune" .... ==== https://alchemists.io/projects/hanamismith:[Hanamismith] .... hsb = "hanamismith build --name" hse = "hanamismith config --edit" hsh = "hanamismith --help" .... ==== https://brew.sh:[Homebrew] .... hb = "brew" hbd = "brew doctor" hbi = "brew install" hbin = "brew info" hbl = "brew list --versions | fzf" hblc = "brew list --casks --versions | fzf" hblf = "brew list --formulae --versions | fzf" hbp = "brew pin" hbpu = "brew unpin" hbr = "brew reinstall" hbs = "brew search" hbsu = "brew update && brew upgrade && brew cleanup" hbu = "brew uninstall" hbug = "brew update && brew upgrade" .... ==== https://trac.webkit.org/wiki/JSC:[JavaScript Core] .... jsc = "/System/Library/Frameworks/JavaScriptCore.framework/Versions/Current/Helpers/jsc" .... ==== https://jless.io:[jless] .... jlr = "jless --mode line" .... ==== https://alchemists.io/projects/milestoner:[Milestoner] .... ms = "milestoner" mse = "milestoner config --edit" msp = "milestoner --publish" .... ==== https://en.wikipedia.org/wiki/Network_Computer:[Network] .... dnsi = "scutil --dns" dnss = "sudo dscacheutil -statistics" ipa = 'curl --silent checkip.dyndns.org | rg --only-matching "[0-9\.]+" | _copy_and_print' key = "open /Applications/Utilities/Keychain\ Access.app" ping = "gping" speed = "networkQuality" sshe = '$EDITOR $HOME/.ssh/config' top = "htop" .... ==== https://www.npmjs.com:[NPM] .... na = "npm login" nb = "npm run build" ni = "npm install" nid = "npm install --save-dev" nl = "npm ls" no = "npm outdated" np = "npm publish" nq = "npm run quality" nt = "npm test" ntw = "npm run test:watch" .... ==== https://cocoatech.com:[Path Finder] .... pfo = 'open -a "Path Finder.app" "$PWD"' .... ==== https://github.com/theory/pgenv:[pgenv] .... pgc = "pgenv clear" pgl = "pgenv log" pgs = "pgenv use" pgsp = "pgenv stop" pgst = "pgenv start" pgu = "pgenv remove" pgv = "pgenv versions" .... ==== https://redis.io:[Redis] .... redc = "redis-cli" reds = 'redis-server $HOMEBREW_PREFIX/etc/redis.conf &' .... ==== https://github.com/AlexB52/retest[Retest] .... rt = "COVERAGE=no retest" .... ==== https://github.com/BurntSushi/ripgrep:[ripgrep] .... rgf = "rg --files --glob" .... ==== https://rspec.info:[RSpec] .... rsf = "COVERAGE=no rspec spec --only-failures" rsn = "COVERAGE=no rspec spec --next-failure" rso = "COVERAGE=no rspec spec --dry-run --format doc > tmp/rspec-overview.txt && e tmp/rspec-overview.txt" rsr = "COVERAGE=no rspec" rss = "rspec" rst = "COVERAGE=no rspec spec --tag" .... ==== https://github.com/bbatsov/rubocop:[Rubocop] .... cop = "rubocop --parallel --display-cop-names --display-style-guide" copc = "rubocop --auto-gen-config" copf = "rubocop --autocorrect" copfo = "rubocop --autocorrect --only" copo = "rubocop --display-cop-names --only" cops = "rubocop --show-cops" copu = "rubocop --autocorrect-all" .... ==== https://www.ruby-lang.org:[Ruby] .... rbbe = '$EDITOR $HOME/Engineering/Misc/benchmark' rbbr = '$HOME/Engineering/Misc/benchmark' rbde = '$EDITOR $HOME/Engineering/Misc/demo' rbdr = '$HOME/Engineering/Misc/demo' rbdw = 'viddy $HOME/Engineering/Misc/demo' .... ==== https://rubyonrails.org:[Ruby on Rails] .... railsb = "rails console --sandbox" railse = "EDITOR = 'sublime --wait' rails credentials:edit" .... ==== https://rubygems.org:[RubyGems] .... gemc = "gem cleanup" gemcli = "rg 'spec\.executables' --no-messages --max-depth=2 --files-with-matches gemspec . | xargs basename | cut -d. -f1 | sort | _copy_and_print '\n'" gemcr = '$EDITOR $HOME/.gem/credentials' gemb = "gem build" geme = "gem environment" gemi = "gem install" geml = "gem list" gemp = "gem pristine" gemu = "gem uninstall" gemuc = "gem update --system && gem update && gem cleanup" .... ==== https://alchemists.io/projects/rubysmith:[Rubysmith] .... rbb = "rubysmith build --name" rbe = "rubysmith config --edit" rbh = "rubysmith --help" .... ==== https://github.com/colszowka/simplecov:[SimpleCov] .... cov = "open coverage/index.html" .... ==== https://www.sublimetext.com:[Sublime Text] .... e = "sublime" .... ==== https://www.gnu.org/software/tar/tar.html:[Tar] .... bzc = "tar --use-compress-program=pigz --create --preserve-permissions --bzip2 --verbose --file" bzx = "tar --extract --bzip2 --verbose --file" .... ==== https://www.terraform.io:[Terraform] .... tf = "terraform" tfa = "noti --title 'Terraform Apply' terraform apply" tfc = "terraform console" tff = "terraform fmt -recursive" tfg = "terraform graph | dot -Tsvg > tmp/graph.svg && open -a 'Firefox.app' tmp/graph.svg" tfi = "terraform init" tfo = "terraform output" tfp = "noti --title 'Terraform Plan' terraform plan" tft = "terraform taint" tfu = "terraform untaint" tfup = "terraform init -upgrade" tfv = "terraform validate" .... ==== http://tmux.sourceforge.net:[tmux] .... tsa = "tmux attach-session -t" tsk = "tmux kill-session -t" tsl = "tmux list-sessions" tsr = "tmux rename-session -t" .... ==== https://gitlab.com/procps-ng/procps:[Watch] .... wp = "watch --interval 1 --color --beep --exec" .... === Functions ==== link:https://asciidoctor.org[ASCII Doctor] .... ado = ASCII Doctor Open - Transforms ASCII Doc into HTML and opens in default browser. .... ==== https://bundler.io:[Bundler] .... bca = Bundler Clean (all) - Clean projects of gem artifacts. bcg = Bundler Config Gem - Configure Bundler to use local gem for development purposes. bl = Bundle List - List gem dependencies for project and copy them to clipboard. boa = Bundle Outdated (all) - Answer outdated gems for projects in current directory. bu = Bundle Update - Update all gems or a single gem in current project. bua = Bundle Update (all) - Update gems for projects in current directory. .... ==== https://alchemists.io/projects/caliber:[Code Quality] .... cqa = Code Quality (all) - Run code quality tasks for projects in current directory. cqi = Code Quality Issues - List all source files affected by code quality issues. .... ==== https://curl.se:[curl] .... curld = Curl Diagnostics - Curl with diagnostic information for request. curli = Curl Inspect - Inspect remote file with default editor. .... ==== https://www.docker.com:[Docker] .... drc = Docker Comppose - Run Docker Comppose for development (default) or production. drcb = Docker Compose Build - Build service for development (default) or production. drcd = Docker Compose Down - Shutdown services for development (default) or production. drce = Docker Compose Execute - Execute command for development (default) or production. drcr = Docker Compose Run - Run oneoff command for development (default) or production. drcu = Docker Compose Up - Startup services for development (default) or production. .... ==== Dotfiles .... dots = Dotfiles - Learn about dotfile aliases, functions, etc. .... ==== https://github.com/Schniz/fnm:[Fast Node Manager] .... jsf = JavaScript Force - Installs new Node version as default and removes previous version. jsua = JavaScript Upgrade (all) - Upgrade JavaScript projects in current directory to new JavaScript version. .... ==== General .... cype = Colorized Type - Identical to "type" system command but with Bat support. eup = Environment Update - Update environment with latest software. iso = ISO - Builds an ISO image from mounted volume. kilp = Kill Process - Kill errant/undesired process. t2s = Tab to Space - Convert file from tab to space indentation. .... ==== https://git-scm.com:[Git] .... ga = Git Add - Interactively adds modified/untracked files. gafe = Git Safe - Marks repository as safe for auto-loading project's `bin` path. galla = Git Add (all) - Apply file changes (including new files) for projects in current directory. gash = Git Stash - Creates stash of all changes. gasha = Git Stash (all) - Answer stash count for projects in current directory. gashc = Git Stash Clear - Clears all stashes. gashd = Git Stash Drop - Drop stash or prompt for stash to drop. gashi = Git Stash Import - Imports a remote stash. gashl = Git Stash List - List stashes. gashp = Git Stash Pop - Pop stash or prompt for stash to pop. gashs = Git Stash Show - Show stash or prompt for stash to show. gasht = Git Stash Stage - Creates stash of staged work. gbc = Git Branch Create - Create and switch to branch. gbca = Git Branch Create (all) - Create and switch to branch for projects in current directory. gbd = Git Branch Delete - Interactively delete local and/or remote branch. gbdl = Git Branch Delete (local) - Delete local branch. gbdm = Git Branch Delete (merged) - Delete remote and local merged branches. gbdr = Git Branch Delete (remote) - Delete remote branch. gbf = Git Branch Facsimile - Duplicate current branch with new name and switch to it. gbl = Git Branch List - List local and remote branch details. gbla = Git Branch List (all) - List current branch for projects in current directory. gblo = Git Branch List (owner) - List branches owned by current author or supplied author. gbna = Git Branch Number (all) - Answer number of branches for projects in current directory. gbr = Git Branch Rename - Rename current branch. gbs = Git Branch Switch - Switch between branches. gbsa = Git Branch Switch (all) - Switch to given branch for projects in current directory. gcaa = Git Commit (all) - Commit changes (unstaged and staged) for projects in current directory. gcap = Git Commit and Push (all) - Commit and push changes for projects in current directory. gcb = Git Commit Breakpoint - Create a breakpoint (empty) commit to denote related commits in a feature branch. gcf = Git Commit Fixup - Create fixup commit with optional amend or reword support. gcff = Git Commit Fix (file) - Create commit fix for file (ignores previous fixups). gcfi = Git Commit Fix (interactive) - Select which commit to fix within current feature branch. gdf = Git Diff Files - List all added/changed files on current branch. gday = Git Day - Answer summarized list of current day activity for projects in current directory. gesh = Git Reset Hard - Reset to HEAD, destroying all untracked, staged, and unstaged changes. UNRECOVERABLE! gesha = Git Reset Hard (all) - Destroy all untracked, staged, and unstaged changes for all projects in current directory. UNRECOVERABLE! gess = Git Reset Soft - Resets previous commit (default), resets back to number of commits, or resets to specific commit. ggeta = Git Get Config Value (all) - Answer key value for projects in current directory. gga = Git Guise Add - Adds Git configuration and associated profile. ggd = Git Guise Delete - Deletes Git configuration and associated profile. ghow = Git Show - Show commit details with optional diff support. ghurn = Git Churn - Answer commit churn for project files (sorted highest to lowest). gia = Git Init (all) - Initialize/re-initialize repositories in current directory. gile = Git File - Show file details for a specific commit (with optional diff support). gim = Git Import - Import remote repository commits into current local branch. gince = Git Since - Answer summarized list of activity since date/time for projects in current directory. ginfo = Git Info - Print repository overview information. gistory = Git File History - View file commit history (with optional diff support). glameh = Git Blame History - View commit history for file and/or lines (with optional diff support). gleana = Git Clean (all) - Clean uncommitted files from all projects in current directory. glear = Git Clear - Clear repository for packaging/shipping purposes. glg = Git Log Grep - Grep Git log by query. gli = Git Log (interactive) - List default or feature branch commits with commit show and/or diff support. gls = Git Log Search - Search Git log by query. glz = Git Log Fuzzy - Fuzzy find commits in the log. gm = Git Merge - Interactively select a branch to merge into the current branch and delete after. gma = Git Merge (all) - Merges, deletes, and pushes feature branch. gmonth = Git Month - Answer summarized list of current month activity for projects in current directory. gmpa = Git Amend Push (all) - Amend all changes and force push with lease for projects in current directory. gnai = Git Notes Add (interactive) - Select which commit note to add for current feature branch. gnei = Git Notes Edit (interactive) - Select which commit note to edit for current feature branch. gndi = Git Notes Remove (interactive) - Select which commit note to remove for current feature branch. gnri = Git Notes Show (interactive) - Select which commit note to show for current feature branch. gount = Git Commit Count - Answer total number of commits for current project. gpa = Git Push (all) - Push changes for projects in current directory. gpua = Git Pull (all) - Pull new changes from remote branch for projects in current directory. gra = Git Remote Add - Add remote repository. grd = Git Remote Delete - Delete local remote. grbi = Git Rebase (interactive) - Rebase commits, interactively. grbq = Git Rebase (quick) - Rebase commits, quickly. Identical to `grbi` function but skips editor. groot = Git Root - Change to repository root directory regardless of current depth. gseta = Git Set Config Value (all) - Set key value for projects in current directory. gsta = Git Status (all) - Answer status of projects with uncommited/unpushed changes. gstats = Git Statistics - Answer statistics for current project. gstatsa = Git Statistics (all) - Answer statistics for all projects in current directory. gsup = Git Standup - Answer summarized list of activity since yesterday for projects in current directory. gtd = Git Tag Delete - Delete local and remote tag (if found). gtl = Git Tag List - List tags in tabular form. gtr = Git Tag Rebuild - Rebuild a previous tag. WARNING: Use with caution, especially if previously published. gtail = Git Tail - Answer commit history since last tag for current project (copies results to clipboard). gtaila = Git Tail (all) - Answer commit history count since last tag for projects in current directory. gucca = Git Upstream Commit Count (all) - Answer upstream commit count since last pull for projects in current directory. guke = Git Nuke - Permanently destroy and erase a file from history. UNRECOVERABLE! garb = Git Garbage Collect - Garbage collect dangling commits for projects in current directory. gunseta = Git Unset (all) - Unset key value for projects in current directory. gup = Git Update - Fetch commits, prune untracked references, review each commit (optional, with diff), and pull (optional). guthorc = Git Author Contributions - Answers total lines added/removed by author for repo (with emphasis on deletion). guthorsa = Git Authors (all) - Answer author commit activity per project (ranked highest to lowest). gvac = Git Verify and Clean - Verify and clean objects for current project. gvaca = Git Verify and Clean (all) - Verify and clean objects for projects in current directory. gwa = Git Worktree Add - Add and switch to new worktree. gwd = Git Worktree Delete - Deletes current Git worktree. gweek = Git Week - Answer summarized list of current week activity for projects in current directory. gync = Git Sync - Syncs up remote changes and deletes pruned/merged branches. .... ==== https://github.com:[GitHub] .... gh = GitHub - View GitHub details for current project. ghpra = GitHub Pull Request (all) - Open pull requests for all projects in current directory (non-default branches only). .... ==== https://en.wikipedia.org/wiki/Less_(Unix):[less] .... lessi = Less Interactive - Inspect file, interactively. .... ==== https://github.com/pivotal/LicenseFinder:[License Finder] .... licensea = License Finder (add) - Adds library to global list. licensei = License Finder (include) - Include license in global list. .... ==== https://people.freebsd.org/~abe:[lsof] .... port = Port - List file activity on given port. .... ==== https://marked2app.com:[Marked 2] .... mo = Marked Open - Opens Markdown file in Marked. .... ==== https://alchemists.io/projects/milestoner:[Milestoner] .... msa = Milestoner (ASCII Doc) - Build milestone(s) in ASCII Doc format. msf = Milestoner (feed) - Build milestone(s) in feed (atom) format. msm = Milestoner (Markdown) - Build milestone(s) in Markdown format. mss = Milestoner (stream) - Build milestone(s) in stream format. msw = Milestoner (web) - Build milestone(s) in web format. .... ==== https://jedisct1.github.io/minisign:[Minisign] .... sigf = Minisign Sign File - Sign a file. sigg = Minisign Generate - Generate private and public key pair. sigv = Minisign Verify File - Verify signed file. .... ==== https://en.wikipedia.org/wiki/Network_Computer:[Network] .... dnsf = DNS Flush - Flush DNS cache. .... ==== https://openssl.org:[OpenSSL] .... sslc = SSL Certificate Creation - Create SSL certificate. .... ==== https://github.com/DarthSim/overmind:[Overmind] .... omc = Overmind Connect - Connect to running process. omr = Overmind Restart - Restart running process. oms = Overmind Start - Start processes. .... ==== https://github.com/theory/pgenv:[pgenv] .... pgi = PostgreSQL Install - Install (build) specific version. .... ==== https://www.postgresql.org:[PostgreSQL] .... pgt = PostgreSQL Template - Edit PostgreSQL template. pguc = PostgreSQL User Create - Create PostgreSQL user. pgud = PostgreSQL User Drop - Drop PostgreSQL user. .... ==== https://github.com/ruby/rake:[Rake] .... rakea = Rake (all) - Run default Rake tasks for projects in current directory. .... ==== https://rspec.info:[RSpec] .... rsall = RSpec (all) - Run RSpec for projects in current directory. rsb = RSpec Bisect - Debug RSpec failure using bisect to automatically determine the root cause. rsd = RSpec Debug - Debug intermittent RSpec failure(s) by running spec(s) until failure is detected. rsp = RSpec Profile - Runs RSpec specs with profiling enabled. .... ==== https://docs.rubocop.org:[Rubocop] .... copa = Rubocop (all) - Run Rubocop for all projects in current directory. .... ==== https://www.ruby-lang.org:[Ruby] .... rbi = Ruby Install - Install a specific version with safe defaults. reb = Ruby Web Server - Serve web content via WEBrick. rbw = Ruby Which - Locate path to current Ruby program. rbua = Ruby Upgrade (all) - Upgrade Ruby projects in current directory to new Ruby version. rbva = Ruby Version (all) - Show current Ruby version for all projects in current directory. .... ==== https://rubygems.org:[Ruby Gems] .... gemd = Gem Dependencies - Answers dependencies for a gem. gemdep = Gem Dependency Search - Finds a gem defined within a Gemfile or a gemspec. .... ==== https://rubyonrails.org:[Ruby on Rails] .... railsn = Ruby on Rails New - Create new Rails application from selected option. .... ==== https://github.com/colszowka/simplecov:[SimpleCov] .... cova = RSpec (all) - Run RSpec for projects in current directory. .... === Git Hooks .... brakeman_check = Brakeman Check - Scan Rails project for security vulnerabilities. bundler_gemfile_path = Bundler Gemfile Path - Detect gem path statements. bundler_audit_check = Bundler Audit Check - Scans gem dependencies for security vulnerabilities. comment_totals = Comment Totals - Print project comment totals. ctags_rebuild = CTags Rebuild - Rebuild project .tags file. dotenv_check = Dotenv Linter - Scan environment files for consistent style and security issues. git_lint_check = Git Lint Check - Enforce consistent Git commits. git_trailer_cleaner = Git Trailer Cleaner - Remove unused/empty Git commit body trailers. git_add_trailers = Git Add Trailers - Dynamically add trailers based on branch description. java_script_debugger = JavaScript Debugger - Detect JavaScript debug statements. java_script_console = JavaScript Console - Detect JavaScript console statements. java_script_alert = JavaScript Alert - Detect JavaScript alert statements. license_finder_check = License Finder Check - Scan project for valid licenses. osv_check = Open Source Vulnerability (OSV) Check - Scan Ruby dependencies for vulnerabilities. reek_branch_check = Reek Branch Check - Scan Ruby code -- feature branch only -- for poor style choices. reek_stage_check = Reek Stage Check - Scan Ruby code -- staged files only -- for poor style choices. rspec_dotfile = RSpec Dotfile - Detect RSpec dotfile. rspec_order = RSpec Order - Detect RSpec ordered specs. rubocop_branch_check = RuboCop Branch Check - Scan Ruby code -- feature branch only -- for poor style choices. rubocop_stage_check = RuboCop Stage Check - Scan Ruby code -- staged files only -- for poor style choices. .... == Development To contribute, run: [source,bash] ---- git clone https://github.com/bkuhlmann/dotfiles.git cd dotfiles ---- == link:https://alchemists.io/policies/license[License] == link:https://alchemists.io/policies/security[Security] == link:https://alchemists.io/policies/code_of_conduct[Code of Conduct] == link:https://alchemists.io/policies/contributions[Contributions] == link:https://alchemists.io/policies/developer_certificate_of_origin[Developer Certificate of Origin] == link:https://alchemists.io/projects/dotfiles/versions[Versions] == link:https://alchemists.io/community[Community] == Credits Engineered by link:https://alchemists.io/team/brooke_kuhlmann[Brooke Kuhlmann]. ================================================ FILE: Rakefile ================================================ # frozen_string_literal: true require "git/lint/rake/register" require "rubocop/rake_task" Git::Lint::Rake::Register.call RuboCop::RakeTask.new desc "Run code quality checks" task quality: %i[git_lint rubocop] task default: :quality ================================================ FILE: bin/rake ================================================ #! /usr/bin/env ruby # frozen_string_literal: true require "bundler/setup" load Gem.bin_path "rake", "rake" ================================================ FILE: bin/run ================================================ #! /usr/bin/env bash # DESCRIPTION # Executes the command line interface. # SETTINGS set -o errexit set -o pipefail # LIBRARY source lib/utilities.sh source lib/options.sh # EXECUTION if [[ -d "$HOME" ]]; then while true; do if [[ $# == 0 ]]; then printf "\n%s\n" "Usage: run OPTION" printf "\n%s\n" "Dotfile Options:" printf " %s\n" "s: Show managed files." printf " %s\n" "i: Install (existing files are skipped)." printf " %s\n" "l: Link (interactive, excludes: environment.sh and git/configuration)." printf " %s\n" "c: Check for differences between \$HOME files and this project's files." printf " %s\n" "d: Delete (interactive, excludes: environment.sh and git/configuration)." printf " %s\n\n" "q: Quit/Exit." read -r -p "Enter selection: " response printf "\n" process_option $response else process_option $1 fi break done else printf "%s\n" "ERROR: $HOME does not exist." return 1 fi ================================================ FILE: lib/options.sh ================================================ #! /usr/bin/env bash # DESCRIPTION # Defines command line prompt options. # Process option selection. # Parameters: # $1 = The option to process. process_option() { case $1 in 's') show_files;; 'i') install_files;; 'l') link_files;; 'c') check_files;; 'd') delete_files;; 'q');; *) printf "%s\n" "ERROR: Invalid option.";; esac } export -f process_option ================================================ FILE: lib/templates/.agignore.tt ================================================ /log/ /logs/ /tmp/ /.git/ *.tags *.tags* ================================================ FILE: lib/templates/.bash_profile.tt ================================================ #! /usr/bin/env bash # Send to .bashrc for all settings. if [[ -f $HOME/.bashrc ]]; then . $HOME/.bashrc fi ================================================ FILE: lib/templates/.bashrc.tt ================================================ #! /usr/bin/env bash if [[ BASH_VERSINFO[0] < 4 ]]; then printf "%s\n" "WARNING: Dotfiles requires Bash 4.x.x or higher to work correctly." fi # Editors export EDITOR=sublime export VISUAL=vim # History export HISTFILE="$HOME/.config/bash/history.log" export HISTTIMEFORMAT="%F %T " # Use YYYY-MM-DD HH:MM:SS date/time format. export HISTCONTROL="erasedups:ignoreboth" # Remove duplicate entries. export HISTSIZE=10000 # Keep lengthy command history. export HISTIGNORE="#*:..:...:c:h:l:l1:p:pwd:gst:gd:exit:* --help" # Exclude mundane commands. # XDG export XDG_CONFIG_HOME="$HOME/.config" export XDG_CACHE_HOME="$HOME/.cache" export PATH="$HOME/.local/bin:$PATH" # Homebrew export PATH="/opt/homebrew/bin:/opt/homebrew/sbin:$PATH" export HOMEBREW_BAT=1 export HOMEBREW_BOOTSNAP=1 export HOMEBREW_CURL_RETRIES=3 export HOMEBREW_FORCE_BREWED_CA_CERTIFICATES=1 export HOMEBREW_FORCE_BREWED_CURL=1 export HOMEBREW_FORCE_BREWED_GIT=1 export HOMEBREW_NO_ANALYTICS=1 export HOMEBREW_NO_AUTO_UPDATE=1 export HOMEBREW_NO_INSECURE_REDIRECT=1 export HOMEBREW_NO_INSTALL_CLEANUP=1 export HOMEBREW_PREFIX="$(brew --prefix)" # Environment source "$HOME/.config/bash/environment.sh" # Colors source "$HOME/.config/bash/colors.sh" # Aliases source "$HOME/.config/bash/aliases.sh" # Functions source "$HOME/.config/bash/functions-private.sh" source "$HOME/.config/bash/functions-public.sh" # Command Prompt (http://jonisalonen.com/2012/your-bash-prompt-needs-this) source "$HOME/.config/bash/prompt.sh" # Bash Completion source "$HOMEBREW_PREFIX/etc/profile.d/bash_completion.sh" || : # OpenSSL export PATH="$HOMEBREW_PREFIX/opt/openssl/bin:$PATH" # Rust export PATH="$HOME/.cargo/bin:$PATH" # Docker export DOCKER_CONFIG=$HOME/.config/docker # GPG export GPG_TTY=$(tty) # direnv if [[ -e "$HOMEBREW_PREFIX/bin/direnv" ]]; then eval "$(direnv hook bash)" fi # Eza export EZA_STRICT=true export EZA_COLORS="da=1;34:di=32:gm=33:gd=31" # Ruby export BUNDLE_USER_CACHE="$HOME/.cache/bundler" export BUNDLE_USER_CONFIG="$HOME/.config/bundler/configuration.yml" export BUNDLE_USER_HOME="$HOME/.local/share/bundler" export BUNDLE_USER_PLUGIN="$HOME/.local/share/bundler/plugin" export RUBYOPT="-W:deprecated -W:performance -W:strict_unused_block --yjit --debug-frozen-string-literal" # Fast Node Manager export FNM_DIR="$HOME/.cache/fnm" eval "$(fnm env --use-on-cd)" # Frum export FRUM_DIR="$HOME/.cache/frum" eval "$(frum init)" # Fx export FX_LINE_NUMBERS=true export FX_SHOW_SIZE=true export FX_THEME=8 # FZF export FZF_DEFAULT_COMMAND="fd --type file --follow --hidden --color always --exclude .git" export FZF_DEFAULT_OPTS="--multi --ansi" # Make export MAKEFLAGS="--jobs=$(sysctl -n hw.ncpu)" # Node export PATH="$PATH:$HOMEBREW_PREFIX/share/npm/bin" # Obsidian export PATH="$PATH:/Applications/Obsidian.app/Contents/MacOS" # OrbStack source "$HOME/.orbstack/shell/init.bash" 2>/dev/null || : # pgenv export PGENV_ROOT="$HOME/.cache/pgenv" export PATH="$HOME/.cache/pgenv/bin:$HOME/.cache/pgenv/pgsql/bin:$PATH" # Terraform export TF_PLUGIN_CACHE_DIR="$HOME/.cache/terraform/plugins" # Git export GIT_CONFIG_GLOBAL="$HOME/.config/git/configuration" source "$HOMEBREW_PREFIX/opt/git/etc/bash_completion.d/git-completion.bash" || : export PATH=".git/safe/../../bin:$PATH" # Zoxide export _ZO_DATA_DIR="$HOME/.cache/zoxide" eval "$(zoxide init bash)" # Checks the window size after each command and, if necessary, updates LINES and COLUMNS values. shopt -s checkwinsize # Attempts to save all lines of a multi-line command as a single history entry for easy re-editing. shopt -s cmdhist # Attempts word spelling correction on directory names if directory name supplied does not exist. shopt -s dirspell # Enables extended pattern matching features. shopt -s extglob # Using ** in a pathname expansion context will match all files and zero or more directories and # subdirectories. If the pattern is followed by a /, only directories and subdirectories match. shopt -s globstar # The history list is appended (instead of being overwritten) as defined by the HISTFILE variable. shopt -s histappend # Enables history expansion with space (i.e. `!!`). bind Space:magic-space ================================================ FILE: lib/templates/.cache/pgenv/config/default.conf.tt ================================================ # Enables debug output #export PGENV_DEBUG='' # Enables warning messages #export PGENV_WARNINGS='' ###### Build settings ##### # Make command to use for build export PGENV_MAKE='/usr/bin/make' # Make flags declare -a PGENV_MAKE_OPTIONS=([0]="-j3") export PGENV_MAKE_OPTIONS # Configure PostgreSQL build flags. PGENV_CONFIGURE_OPTIONS=( --enable-thread-safety --with-bonjour --with-llvm --with-openssl --with-uuid=e2fs PKG_CONFIG_PATH=$HOMEBREW_PREFIX/opt/icu4c/lib/pkgconfig LLVM_CONFIG=$HOMEBREW_PREFIX/opt/llvm@20/bin/llvm-config CLANG=$HOMEBREW_PREFIX/opt/llvm@20/bin/clang "CPPFLAGS=-I$HOMEBREW_PREFIX/opt/icu4c/include -I$HOMEBREW_PREFIX/opt/openssl/include -I$HOMEBREW_PREFIX/opt/readline/include" "CFLAGS=-I$HOMEBREW_PREFIX/opt/icu4c/include -I$HOMEBREW_PREFIX/opt/openssl/include -I$HOMEBREW_PREFIX/opt/readline/include" "LDFLAGS=-L$HOMEBREW_PREFIX/opt/icu4c/lib -L$HOMEBREW_PREFIX/opt/openssl/lib -L$HOMEBREW_PREFIX/opt/readline/lib" ) # A file that lists ordered patches to apply before building starts #export PGENV_PATCH_INDEX='' # Curl command to download source code export PGENV_CURL='/usr/bin/curl' # Patch command for specific versions export PGENV_PATCH='/usr/bin/patch' # Sed used to manipulate strings export PGENV_SED='/usr/bin/sed' ##### Runtime options ##### # Path to the cluster log file (mandatory) export PGENV_LOG="$HOME/.cache/pgenv/pgsql/data/server.log" # Initdb flags declare -a PGENV_INITDB_OPTIONS=([0]="-U" [1]="postgres" [2]="--locale" [3]="en_US.UTF-8" [4]="--encoding" [5]="UNICODE") export PGENV_INITDB_OPTIONS # Stop configuration flags declare -a PGENV_STOP_OPTIONS=() export PGENV_STOP_OPTIONS # Start configuration flags declare -a PGENV_START_OPTIONS=() export PGENV_START_OPTIONS # Restart configuration flags declare -a PGENV_RESTART_OPTIONS=() export PGENV_RESTART_OPTIONS # Script to execute when the build process finishes #export PGENV_SCRIPT_POSTINSTALL='' # Script to execute when initdb finishes (and the server has not started yet) export PGENV_SCRIPT_FIRSTSTART="$HOME/.config/pgenv/initialize" # Script to execute at the very first start of the instance #export PGENV_SCRIPT_FIRSTSTART='' # Script to execute before the cluster stops #export PGENV_SCRIPT_PRESTOP='' # Script to execute when the cluster has been stopped #export PGENV_SCRIPT_POSTSTOP='' # Script to execute when the cluster has been started #export PGENV_SCRIPT_POSTSTART='' # Script to execute when the cluster has been restarted #export PGENV_SCRIPT_POSTRESTART='' # Ensures configuration is preserved. export PGENV_WRITE_CONFIGURATION_FILE_AUTOMATICALLY=no ================================================ FILE: lib/templates/.config/aprc.tt ================================================ AmazingPrint.defaults = { indent: 2, index: false } ================================================ FILE: lib/templates/.config/bash/aliases.sh.tt ================================================ #! /usr/bin/env bash # Section: https://asciidoctor.org:[ASCII Doctor] alias ad="asciidoctor" # Section: https://www.gnu.org/software/bash:[Bash] alias bashe='$EDITOR $HOME/.config/bash/environment.sh' alias bashs='exec $SHELL' # Section: https://bundler.io:[Bundler] alias ba="bundle add" alias bb="bundle binstubs" alias bce='$EDITOR $BUNDLE_USER_CONFIG' alias bch="rm -f Gemfile.lock; bundle check" alias bd="bundle doctor" alias be="bundle exec" alias bi="bundle install" alias blo='bundle list --paths | fzf | xargs $EDITOR' alias bo="bundle outdated --only-explicit" alias br="bundle remove" # Section: https://crystal-lang.org:[Crystal] alias cr="crystal" alias crb="crystal build" alias crd="crystal docs" alias crdo="open docs/index.html" alias crr="crystal run" alias crs="crystal spec" # Section: https://direnv.net:[direnv] alias denva="direnv allow" alias denvr="direnv reload" alias denvs="direnv status" # Section: https://www.docker.com:[Docker] alias dr="docker" alias drb="docker build" alias drd="docker system prune --force && docker buildx prune --force" alias dri="docker images" alias drp="docker ps --all" alias drt="docker tag" # Section: http://duti.org:[duti] alias dutia='duti $HOME/.config/duti/configuration.duti' # Section: https://eza.rocks:[Eza] alias x1="eza --oneline --all --group-directories-first" alias x="eza --all --all --long --header --group --group-directories-first --time-style long-iso --git" alias xt="eza --tree --all --group-directories-first --ignore-glob '*.git' --git-ignore" alias xtv="eza --tree --all --group-directories-first --ignore-glob '*.git'" # Section: https://github.com/Schniz/fnm:[Fast Node Manager] alias js="fnm" alias jsd="fnm default" alias jse="fnm env" alias jsi="fnm install" alias jsl="fnm list" alias jss="fnm use" alias jsu="fnm uninstall" # Section: https://github.com/TaKO8Ki/frum:[Frum] alias rb="frum" alias rbd="frum global" alias rbl="frum versions" alias rbs="frum local" alias rbu="frum uninstall" # Section: https://github.com/junegunn/fzf:[Fuzzy Finder] alias ff="_fzf_preview_and_select | xargs -0 -o \$EDITOR" # Section: https://alchemists.io/projects/gemsmith:[Gemsmith] alias gsb="gemsmith build --name" alias gsc="gemsmith config --edit" alias gse="gemsmith --edit" alias gsi="gemsmith --install" alias gsp="gemsmith --publish" alias gsq="rake quality" alias gsv="gemsmith --view" # Section: General alias ...="cd ../.." alias ..="cd .." alias c="clear" alias cat="bat --theme DarkNeon" alias cdb="cd -" alias du="dust" alias h="history" alias l1="ls -A1 | _copy_and_print '\n'" alias l="ls -alhT" alias o="open" alias p='pwd | tr -d "\r\n" | _copy_and_print' alias pss="pgrep -i -l -f" alias rmde="find . -type d -empty -not -path '*.git*' -delete" # Section: https://ghostty.org:[Ghostty] alias ghoste="$EDITOR $HOME/.config/ghostty/config.ghostty" # Section: https://git-scm.com:[Git] alias gall="git add --all ." alias gamend="git commit --amend" alias gamenda="git commit --amend --all --no-edit" alias gamendh="git commit --amend --no-edit" alias gap="git ls-files --modified | _fzf_preview_and_select | xargs -0 -o -t git add --patch" alias gatch="git commit --patch" alias gau="git add --update" alias gb="git switch" alias gbb="git switch -" alias gbe="git branch --edit-description" alias gbi="git bisect" alias gbv='git config get branch.$(_git_branch_name).description' alias gbib="git bisect bad" alias gbig="git bisect good" alias gbih="git bisect help" alias gbil="git bisect log" alias gbir="git bisect reset" alias gbire="git bisect replay" alias gbis="git bisect start" alias gbisk="git bisect skip" alias gbiv='git bisect visualize --reverse --pretty=format:"$(_git_log_line_format)"' alias gbm='git switch $(_git_branch_default)' alias gbn="_git_branch_name | _copy_and_print" alias gbt="git show-branch --topics" alias gca="git commit --all" alias gcam="git commit --all --message" alias gcd="git config list --show-origin --show-scope | fzf" alias gce='cat .git/COMMIT_EDITMSG | pbcopy' alias gcge="git config edit --global" alias gch="git checkout" alias gcl="git clone" alias gcle="git config edit --local" alias gcm="git commit --message" alias gco="git commit" alias gcp="git cherry-pick" alias gcpa="git cherry-pick --abort" alias gcpc="git cherry-pick --continue" alias gcps="git cherry-pick --skip" alias gcs="git commit --squash" alias gd="git diff" alias gdc="git diff --cached" alias gdm='git diff origin/$(_git_branch_default)' alias gdo='git diff --name-only | uniq | xargs $EDITOR' alias gdt="git difftool" alias gdtc="git difftool --cached" alias gdtm='git difftool origin/$(_git_branch_default)' alias gdw="git diff --color-words" alias gel="git rm" alias gelc="git rm --cached" alias ges="git diff --name-only --cached | _fzf_preview_and_select | xargs -0 -o -t git reset" alias gf="git fetch" alias gg="git grep" alias gge="git config get --global --regexp includeif | fzf | xargs \$EDITOR" alias gget="git config get" alias gi="git init" alias gl='git log --graph --pretty=format:"$(_git_log_line_format)" "$(_git_branch_range)"' alias gld='git log --stat --pretty=format:"$(_git_log_details_format)" "$(_git_branch_range)"' alias glame="git blame -M -C" alias glean="git clean -d --force" alias glf='git fetch && git log --reverse --no-merges --pretty=format:"$(_git_log_line_format)" ..@{upstream}' alias glh="_git_sha | _copy_and_print" alias gna="git notes add" alias gnd="git notes remove" alias gne="git notes edit" alias gnl="git notes list" alias gnp="git notes prune" alias gns="git notes show" alias gp="git push" alias gpf="git push --force-with-lease" alias gpn="git push --no-verify" alias gpu="git pull" alias gpuo="git pull origin" alias gpuom='git pull origin $(_git_branch_default)' alias gpuum='git pull upstream $(_git_branch_default)' alias gr="git ls-files --modified | _fzf_preview_and_select | xargs -0 -o -t git restore" alias grba="git rebase --abort" alias grbc="git rebase --continue" alias grbd="git rebase --show-current-patch" alias grbo="git rebase --onto" alias grbs="git rebase --skip" alias grbt="git rebase --edit-todo" alias grev="git revert --no-commit" alias grl="git reflog --relative-date" alias grom='git fetch --all && git reset --hard origin/$(_git_branch_default)' # Reset local branch to origin/main branch. UNRECOVERABLE! alias grr="git rerere" alias gset="git config set" alias gst="git status --short --branch" alias gt="git tag" alias gte='cat .git/TAG_EDITMSG | pbcopy' alias gtp="git push --tags" alias gtv="git tag --verify" alias guthors="git shortlog --numbered --summary --group=author --group=trailer:Co-Authored-By" alias gwl="git worktree list" alias gwp="git worktree prune" # Section: https://alchemists.io/projects/hanamismith:[Hanamismith] alias hsb="hanamismith build --name" alias hse="hanamismith config --edit" alias hsh="hanamismith --help" # Section: https://brew.sh:[Homebrew] alias hb="brew" alias hbd="brew doctor" alias hbi="brew install" alias hbin="brew info" alias hbl="brew list --versions | fzf" alias hblc="brew list --casks --versions | fzf" alias hblf="brew list --formulae --versions | fzf" alias hbp="brew pin" alias hbpu="brew unpin" alias hbr="brew reinstall" alias hbs="brew search" alias hbsu="brew update && brew upgrade && brew cleanup" alias hbu="brew uninstall" alias hbug="brew update && brew upgrade" # Section: https://trac.webkit.org/wiki/JSC:[JavaScript Core] alias jsc="/System/Library/Frameworks/JavaScriptCore.framework/Versions/Current/Helpers/jsc" # Section: https://jless.io:[jless] alias jlr="jless --mode line" # Section: https://alchemists.io/projects/milestoner:[Milestoner] alias ms="milestoner" alias mse="milestoner config --edit" alias msp="milestoner --publish" # Section: https://en.wikipedia.org/wiki/Network_Computer:[Network] alias dnsi="scutil --dns" alias dnss="sudo dscacheutil -statistics" alias ipa='curl --silent checkip.dyndns.org | rg --only-matching "[0-9\.]+" | _copy_and_print' alias key="open /Applications/Utilities/Keychain\ Access.app" alias ping="gping" alias speed="networkQuality" alias sshe='$EDITOR $HOME/.ssh/config' alias top="htop" # Section: https://www.npmjs.com:[NPM] alias na="npm login" alias nb="npm run build" alias ni="npm install" alias nid="npm install --save-dev" alias nl="npm ls" alias no="npm outdated" alias np="npm publish" alias nq="npm run quality" alias nt="npm test" alias ntw="npm run test:watch" # Section: https://github.com/theory/pgenv:[pgenv] alias pgc="pgenv clear" alias pgl="pgenv log" alias pgs="pgenv use" alias pgsp="pgenv stop" alias pgst="pgenv start" alias pgu="pgenv remove" alias pgv="pgenv versions" # Section: https://redis.io:[Redis] alias redc="redis-cli" alias reds='redis-server $HOMEBREW_PREFIX/etc/redis.conf &' # Section: https://github.com/AlexB52/retest[Retest] alias rt="COVERAGE=no retest" # Section: https://github.com/BurntSushi/ripgrep:[ripgrep] alias rgf="rg --files --glob" # Section: https://rspec.info:[RSpec] alias rsf="COVERAGE=no rspec spec --only-failures" alias rsn="COVERAGE=no rspec spec --next-failure" alias rso="COVERAGE=no rspec spec --dry-run --format doc > tmp/rspec-overview.txt && e tmp/rspec-overview.txt" alias rsr="COVERAGE=no rspec" alias rss="rspec" alias rst="COVERAGE=no rspec spec --tag" # Section: https://github.com/bbatsov/rubocop:[Rubocop] alias cop="rubocop --parallel --display-cop-names --display-style-guide" alias copc="rubocop --auto-gen-config" alias copf="rubocop --autocorrect" alias copfo="rubocop --autocorrect --only" alias copo="rubocop --display-cop-names --only" alias cops="rubocop --show-cops" alias copu="rubocop --autocorrect-all" # Section: https://www.ruby-lang.org:[Ruby] alias rbbe='$EDITOR $HOME/Engineering/Misc/benchmark' alias rbbr='$HOME/Engineering/Misc/benchmark' alias rbde='$EDITOR $HOME/Engineering/Misc/demo' alias rbdr='$HOME/Engineering/Misc/demo' alias rbdw='viddy $HOME/Engineering/Misc/demo' # Section: https://rubyonrails.org:[Ruby on Rails] alias railsb="rails console --sandbox" alias railse="EDITOR='sublime --wait' rails credentials:edit" # Section: https://rubygems.org:[RubyGems] alias gemc="gem cleanup" alias gemcli="rg 'spec\.executables' --no-messages --max-depth=2 --files-with-matches gemspec . | xargs basename | cut -d. -f1 | sort | _copy_and_print '\n'" alias gemcr='$EDITOR $HOME/.gem/credentials' alias gemb="gem build" alias geme="gem environment" alias gemi="gem install" alias geml="gem list" alias gemp="gem pristine" alias gemu="gem uninstall" alias gemuc="gem update --system && gem update && gem cleanup" # Section: https://alchemists.io/projects/rubysmith:[Rubysmith] alias rbb="rubysmith build --name" alias rbe="rubysmith config --edit" alias rbh="rubysmith --help" # Section: https://github.com/colszowka/simplecov:[SimpleCov] alias cov="open coverage/index.html" # Section: https://www.sublimetext.com:[Sublime Text] alias e="sublime" # Section: https://www.gnu.org/software/tar/tar.html:[Tar] alias bzc="tar --use-compress-program=pigz --create --preserve-permissions --bzip2 --verbose --file" alias bzx="tar --extract --bzip2 --verbose --file" # Section: https://www.terraform.io:[Terraform] alias tf="terraform" alias tfa="noti --title 'Terraform Apply' terraform apply" alias tfc="terraform console" alias tff="terraform fmt -recursive" alias tfg="terraform graph | dot -Tsvg > tmp/graph.svg && open -a 'Firefox.app' tmp/graph.svg" alias tfi="terraform init" alias tfo="terraform output" alias tfp="noti --title 'Terraform Plan' terraform plan" alias tft="terraform taint" alias tfu="terraform untaint" alias tfup="terraform init -upgrade" alias tfv="terraform validate" # Section: http://tmux.sourceforge.net:[tmux] alias tsa="tmux attach-session -t" alias tsk="tmux kill-session -t" alias tsl="tmux list-sessions" alias tsr="tmux rename-session -t" ================================================ FILE: lib/templates/.config/bash/colors.sh.tt ================================================ #! /usr/bin/env bash # Terminal Colors # Color Designators: # a black # b red # c green # d brown # e blue # f magenta # g cyan # h light grey # A bold black, usually shows up as dark grey # B bold red # C bold green # D bold brown, usually shows up as yellow # E bold blue # F bold magenta # G bold cyan # H bold light grey; looks like bright white # x default foreground or background # Attribute Order: # 1. directory # 2. symbolic link # 3. socket # 4. pipe # 5. executable # 6. block special # 7. character special # 8. executable with setuid bit set # 9. executable with setgid bit set # 10. directory writable to others, with sticky bit # 11. directory writable to others, without sticky bit # Default: "exfxcxdxbxegedabagacad" export CLICOLOR=1 export LSCOLORS=cxfxcxdxbxegebabagacad # Bash Colors export BLACK='\e[0;30m' export GUNMETAL='\e[1;30m' export GREY='\e[0;37m' export RED='\e[0;31m' export LIGHT_RED='\e[1;31m' export PURPLE='\e[0;35m' export LIGHT_PURPLE='\e[1;35m' export BLUE='\e[0;34m' export LIGHT_BLUE='\e[1;34m' export GREEN='\e[0;32m' export LIGHT_GREEN='\e[1;32m' export CYAN='\e[0;36m' export LIGHT_CYAN='\e[1;36m' export GOLD='\e[0;33m' export YELLOW='\e[1;33m' export WHITE='\e[1;37m' export BLACK_UNDERLINE='\e[4;30m' export RED_UNDERLINE='\e[4;31m' export GREEN_UNDERLINE='\e[4;32m' export YELLOW_UNDERLINE='\e[4;33m' export BLUE_UNDERLINE='\e[4;34m' export PURPLE_UNDERLINE='\e[4;35m' export CYAN_UNDERLINE='\e[4;36m' export WHITE_UNDERLINE='\e[4;37m' export BLACK_BACKGROUND='\e[48;5;0m' export RED_BACKGROUND='\e[48;5;1m' export GREEN_BACKGROUND='\e[48;5;2m' export YELLOW_BACKGROUND='\e[48;5;11m' export SLATE_BACKGROUND='\e[48;5;23m' export BLUE_BACKGROUND='\e[48;5;19m' export PURPLE_BACKGROUND='\e[48;5;5m' export CYAN_BACKGROUND='\e[48;5;6m' export SILVER_BACKGROUND='\e[48;5;7m' export WHITE_BACKGROUND='\e[48;5;255m' export NORMAL='\e[0m' ================================================ FILE: lib/templates/.config/bash/environment.sh.tt ================================================ #! /usr/bin/env bash # Add secret/machine specific key/value pairs here. # export EXAMPLE="An example of a secret/machine-specific key/value." ================================================ FILE: lib/templates/.config/bash/functions-private.sh.tt ================================================ #! /usr/bin/env bash #-------------------# # Section: Dotfiles # #-------------------# # Label: Find Alias # Description: Find and print matching alias. # Parameters: $1 (required): The alias to search for. _find_alias() { while read -r line; do if [[ "$line" == "alias "*"$1"* ]]; then printf " %s " "Alias:" _print_alias "$line" fi done < "$HOME/.config/bash/aliases.sh" } # Label: Find Command # Description: Find and print matching alias or function. # Parameters: $1 (required): The alias or function to search for. _find_command() { if [[ "$1" ]]; then printf "%s\n" "\"$1\" Search Results:" _find_alias "$1" _find_function "$1" else printf "%s\n" "ERROR: Nothing to search for. Criteria must be supplied." fi } # Label: Find Function # Description: Find and print matching function. # Parameters: $1 (required): The function to search for. _find_function() { while read -r line; do _set_function_label "$line" _set_function_description "$line" if [[ "$line" == *"$1"*"()"* ]]; then printf " %s " "Function:" _print_function_name "$line" "$label" "$description" unset label unset description fi done < "$HOME/.config/bash/functions-public.sh" } # Label: Print Alias # Description: Print alias. # Parameters: $1 (required): The string from which to parse the alias from. _print_alias() { echo "$1" | sed 's/alias //' | sed 's/="/ = "/' | sed "s/='/ = '/" } # Label: Print Aliases # Description: Print aliases. _print_aliases() { while read -r line; do _print_section "$line" if [[ "$line" == "alias"* ]]; then _print_alias "$line" fi done < <(sed '2d' "$HOME/.config/bash/aliases.sh") printf "%s\n" "...." } # Label: Print All # Description: Print aliases, functions, and Git hooks. _print_all() { printf "%s\n" "=== Aliases" _print_aliases printf "\n%s\n" "=== Functions" unset section _print_functions printf "%s\n" "...." printf "\n%s\n\n" "=== Git Hooks" _print_git_hooks } # Label: Print Function Name # Description: Print function name. # Parameters: $1 (required): The string from which to parse the function name from. _print_function_name() { local name=$(printf "$1" | sed 's/() {//') printf "%s\n" "$name = $2 - $3" } # Label: Print Functions # Description: Print functions. _print_functions() { local path="${1:-$HOME/.config/bash/functions-public.sh}" while read -r line; do _print_section "$line" _set_function_label "$line" _set_function_description "$line" if [[ "$line" == *"() {" && "$line" != "_"* ]]; then _print_function_name "$line" "$label" "$description" unset label unset description fi done < "$path" } # Label: Print Git Hooks # Description: Print Git hooks. _print_git_hooks() { printf "%s\n" "...." for file in $(find "$HOME/.config/git/hooks/extensions" -type l | sort); do _print_functions "$file" done printf "%s\n" "...." } # Label: Print Section # Description: Print section. # Parameters: $1 (required): The string from which to parse the section from. _print_section() { if [[ "$1" == "# Section:"* ]]; then if [[ -n "${section+x}" ]]; then printf "%s\n" "...." fi section=$(printf "$1" | sed 's/# Section://' | sed 's/^ *//g' | tr -d '#') printf "\n%s\n\n" "==== $section" printf "%s\n" "...." fi } # Label: Process Dotfiles Option # Description: Process option for learning about dotfile aliases/functions. # Parameters: $1 (optional): The option selection, $2 (optional): The option input. _process_dots_option() { case $1 in 'a') _print_aliases | more;; 'f') _print_functions | more;; 'g') _print_git_hooks | more;; 'p') _print_all | more;; 's') _find_command "$2" | more;; 'q');; *) printf "%s\n" "ERROR: Invalid option.";; esac } # Label: Set Function Description # Description: Set function description. _set_function_description() { if [[ "$line" == "# Description:"* ]]; then description=$(printf "$line" | sed 's/# Description://' | sed 's/^ *//g') fi } # Label: Set Function Label # Description: Set function label. # Parameters: $1 (required): The string from which to parse the function label from. _set_function_label() { if [[ "$1" == "# Label:"* ]]; then label=$(printf "$1" | sed 's/# Label://' | sed 's/^ *//g') fi } #------------------# # Section: General # #------------------# # Label: Clip and Print # Description: Copy input to clipboard and print what what was copied (best used with a pipe). # Parameters: $1 (optional): Displays "(copied to cliboard)" on a new line. Default: false. _copy_and_print() { local delimiter=${1:-' '} local message="$delimiter(copied to clipboard)\n" pbcopy && printf "%s" "$(pbpaste)" && printf "$message" } # Label: Print Black on White # Description: Print black text on a white background. # Parameters: $1 (required): Content to print. _print_black_on_white() { local content="$1" printf "\e[0;30m\e[48;5;255m$content\033[m" } # Label: Toggle Total Color # Description: Format and conditionally color the total. # Parameters: $1 (required): The total, $2(required): The label, $3 (required): The color. _toggle_total_color() { local total="$1" local label="$2" local color="$3" if [[ $total -gt 0 ]]; then printf "$color$total $label\033[m" else printf "$total $label" fi } #------------------------------------# # Section: https://git-scm.com:[Git] # #------------------------------------# # Label: Git Branch Default # Description: Print Git default branch. _git_branch_default() { local default="$(git config get init.defaultBranch)" printf "${default:-main}" } # Label: Git Branch Name # Description: Print Git branch name. _git_branch_name() { git branch --show-current | tr -d '\n' } # Label: Git Branch Parent # Description: Answer parent branch of current branch or default branch if default branch. _git_branch_parent() { local format="" local name="" format="%(refname:lstrip=2)%(is-base:$(_git_sha))" if [[ "$(_git_branch_name)" == "$(_git_branch_default)" ]]; then _git_branch_default else name="$(git for-each-ref --format="$format" --count=1 | sed 's/([^)]*)//')" if [[ "$name" == "$(_git_branch_name)" ]]; then _git_branch_default else printf "%s" "$name" fi fi } # Label: Git Branch Range # Description: Answer branch commit range (i.e. starting and ending reference). _git_branch_range() { local range="" if [[ "$(_git_branch_name)" == "$(_git_branch_default)" ]]; then range="$(_git_sha)" else range="$(_git_branch_parent)..$(_git_sha)" fi printf "%s" "$range" } # Label: Git Branch SHAs # Description: Answer branch commit SHAs regardless of branch nesting. _git_branch_shas() { git log --pretty=format:%h "$(_git_branch_range)" } # Label: Git Commit Count Since Last Tag # Description: Answer commit count since last tag for project. # Parameters: $1 (optional): The output prefix. Default: null, $2 (optional): The output suffix. Default: null. _git_commit_count_since_last_tag() { local prefix="$1" local suffix="$2" local count=$(_git_commits_since_last_tag | wc -l | xargs -n 1) if [[ -n $count ]]; then # Prefix if [[ -n "$prefix" ]]; then printf "\033[36m${prefix}\033[m: " # Cyan. fi # Commit Count if [[ $count -ge 30 ]]; then printf "\033[31m$count\033[m" # Red. elif [[ $count -ge 20 && $count -le 29 ]]; then printf "\033[1;31m$count\033[m" # Light red. elif [[ $count -ge 10 && $count -le 19 ]]; then printf "\033[33m$count\033[m" # Yellow. else printf "$count" # White. fi # Suffix if [[ -n "$suffix" ]]; then printf "$suffix" fi fi } # Label: Git Commit Options # Description: Print options for interacting with Git commits. # Parameters: $1 (required): Commit array. _git_commit_options() { local commits=("${1}") local commit_total=${#commits[@]} local option_padding=${#commit_total} local counter=1 unset response if [[ ${#commits[@]} == 0 ]]; then printf "%s\n" "No commits found." return 0 fi for commit in ${commits[@]}; do option="$(printf "%${option_padding}s" $counter)" printf "%s\n" "$option: $(git log --color --pretty=format:"$(_git_log_enrich_format)" -n1 $commit | _git_log_enrich)" counter=$((counter + 1)) if [[ "$response" == "q" ]]; then break fi done } # Label: Git Commit Root # Description: Answer root commit of entire repository. _git_commit_root() { git rev-list --use-bitmap-index \ --max-parents=0 HEAD \ --pretty=format:%h | \ rg --invert-match "^commit" } # Label: Git Commits Since Last Tag # Description: Answer commit history since last tag for project. _git_commits_since_last_tag() { if [[ $(git tag) ]]; then git log --oneline "$(_git_tag_last)"..HEAD else git log --oneline fi } # Label: Git File Commits # Description: Print file commit history (with optional diff support). # Parameters: $1 (required): The file path. _git_file_commits() { local commits=("${!1}") local file="$2" local commit_total=${#commits[@]} local option_padding=${#commit_total} local counter=1 _git_commit_options "${commits[*]}" read -r -p "Enter selection: " response if [[ "$response" == 'q' ]]; then return fi printf "\n" local selected_commit=${commits[$((response - 1))]} _git_show_details $selected_commit printf "\n" read -p "View diff (y = yes, n = no)? " response if [[ "$response" == 'y' ]]; then gdt $selected_commit^! -- "$file" fi } # Label: Git Log Details Format # Description: Prints default log format. _git_log_details_format() { printf "%s" "$(_git_log_line_format) %n%n%b%n%N%-%n" } # Label: Git Log Enrich # Description: Enrich log for improved readability. _git_log_enrich() { sd "\[G\]" "🔒" \ | sd "\[[^G]\]" "🚨" \ | sd "\[major\]" "🔴" \ | sd "\[minor\]" "🔵" \ | sd "\[patch\]" "🟢" \ | sd "\[\]" "⚪️" } # Label: Git Log Enrich Format # Description: Print enriched log line format. _git_log_enrich_format() { printf "%s" "%C(yellow)%h%C(reset) [%G?] %C(bold blue)%an%C(reset) [%(trailers:key=Milestone,valueonly=true,separator=)] %s%C(bold cyan)%d%C(reset) %C(green)%cr.%C(reset)" } # Label: Git Log Line Format # Description: Print single line log format. _git_log_line_format() { printf "%s" "%C(yellow)%h%C(reset) %G? %C(bold blue)%an%C(reset) %s%C(bold cyan)%d%C(reset) %C(green)%cr.%C(reset)" } # Label: Git SHA # Description: Answer sha for branch, tag, or any kind of valid reference. # Parameters: $1 (optional): The reference name, otherwise current branch. _git_sha() { local reference="${1:-$(_git_branch_name)}" git rev-parse --short "$reference" } # Label: Git Show Details # Description: Show commit/file change details in a concise format. # Parameters: $1 (required): The params to pass to git show. _git_show_details() { git show --stat --patch --pretty=format:"$(_git_log_details_format)" $@ } # Label: Git Stash Count # Description: Answer total stash count for current project. _git_stash_count() { git stash list | wc -l | xargs -n 1 } # Label: Git Stash push # Description: Pushes changes to remote. _git_stash_push() { local reference="refs/stashes/$USER" if [[ -e ".git/$reference" ]]; then git push --no-verify --force origin "$reference" else printf "%s\n" "Push skipped. Reference doesn't exist: $reference." fi } # Label: Git Tag Last # Description: Answer last tag or last commit SHA. _git_tag_last() { git describe --abbrev=0 --tags --always } # Label: Git Tag Last Info # Description: Answer last tag for project (including commits added since tag was created). _git_tag_last_info() { printf "%s\n" "$(git describe --tags --always) ($(_git_commit_count_since_last_tag) commits since)" } # Label: Git Stash # Description: Enhance default git stash behavior by prompting for input (multiple) or using last stash (single). # Parameters: $1 (required): The Git stash command to execute, $2 (required): The prompt label (for multiple stashes). _process_git_stash() { local stash_command="$1" local stash_index=0 local prompt_label="$2" local ifs_original=$IFS IFS=$'\n' # Store existing stashes (if any) as an array. See public, "gashl" for details. stashes=($(gashl)) if [[ ${#stashes[@]} == 0 ]]; then printf "%s\n" "Git stash is empty. Nothing to do." return 0 fi # Ask which stash to show when multiple stashes are detected, otherwise show the existing stash. if [[ ${#stashes[@]} -gt 1 ]]; then printf "%s\n" "$prompt_label:" for ((index = 0; index < ${#stashes[*]}; index++)); do printf " %s\n" "$index: ${stashes[$index]}" done printf " %s\n\n" "q: Quit/Exit." read -p "Enter selection: " response local match="^[0-9]{1}$" if [[ "$response" =~ $match ]]; then printf "\n" stash_index="$response" else return 0 fi fi IFS=$ifs_original eval "$stash_command stash@{$stash_index}" } #--------------------------------------# # Section: https://github.com:[GitHub] # #--------------------------------------# # Label: GitHub URL # Description: Answer GitHub URL for current project. _gh_url() { printf "$(git remote -v | rg github.com | rg fetch | head -1 | cut -f2 | cut -d' ' -f1 | sed -e 's/git@/https:\/\//' -e 's/com:/com\//' -e 's/\.git//')" } # Label: GitHub Pull Request List # Description: List pull requests (local/remote) including subject, author, and relative time. # Parameters: $1 (optional): The output format. _gh_pr_list() { local format=${1:-"%(refname) %(color:yellow)%(refname)%(color:reset) %(subject) %(color:blue bold)%(authorname) %(color:green)(%(committerdate:relative))"} git for-each-ref --color \ --format="$format" \ refs/remotes/pull_requests \ | sed 's/refs\/remotes\/pull_requests\///g' \ | sort --numeric-sort \ | cut -d' ' -f2- } # Label: Process GitHub Branch Option # Description: Process GitHub branch option for remote repository viewing. # Parameters: $1 (optional): The option. _process_gh_branch_option() { case $1 in 'c') open "$(_gh_url)/tree/$(_git_branch_name)";; 'd') open "$(_gh_url)/compare/$(_git_branch_name)";; 'r') open "$(_gh_url)/compare/$(_git_branch_name)?expand=1";; *) open "$(_gh_url)/branches";; esac } # Label: Process GitHub Commit Option # Description: Process GitHub commit option for remote repository viewing. # Parameters: $1 (optional): The commit hash. _process_gh_commit_option() { local commit="$1" if [[ "$commit" ]]; then open "$(_gh_url)/commit/$commit" else open "$(_gh_url)/commits" fi } # Label: Process GitHub File Option # Description: Process GitHub file option for remote repository viewing. # Parameters: $1 (required): The local (relative) file path, $2 (optional): The line numbers. _process_gh_file_option() { local path="$1" local lines="$2" local start_index=$(pwd | wc -c) local end_index=$(printf "$path" | wc -c) local url="$(_gh_url)/blob/$(_git_branch_name)/${path:$start_index:$end_index}" if [[ -n "$lines" ]]; then url="$url#$lines" fi printf "$url" | _copy_and_print } # Label: Process GitHub Option # Description: Processes GitHub option for remote repository viewing. # Parameters: $1 (optional): The first option, $2 (optional): The second option. _process_gh_option() { case $1 in 'a') open $(_gh_url)/actions;; 'o') open $(_gh_url);; 'i') open "$(_gh_url)/issues";; 'c') _process_gh_commit_option "$2";; 'f') _process_gh_file_option "$2" "$3";; 'b') _process_gh_branch_option "$2";; 't') open "$(_gh_url)/tags";; 'r') _process_gh_pull_request_option "$2";; 'w') open "$(_gh_url)/wiki";; 'p') open "$(_gh_url)/pulse";; 'g') open "$(_gh_url)/graphs";; 's') open "$(_gh_url)/settings";; 'u') _process_gh_url_option "$2";; 'q');; *) printf "%s\n" "ERROR: Invalid option.";; esac } # Label: Process GitHub Pull Request Option # Description: Process GitHub pull request option for remote repository viewing. # Parameters: $1 (optional): The option. _process_gh_pull_request_option() { local option="$1" local number_match="^[0-9]+$" if [[ "$option" =~ $number_match ]]; then open "$(_gh_url)/pull/$option" elif [[ "$option" == 'l' ]]; then _gh_pr_list else open "$(_gh_url)/pulls" fi } # Label: Process GitHub URL Option # Description: Processes GitHub URL option for remote repository viewing. # Parameters: $1 (optional): The commit/option. _process_gh_url_option() { local commit="$1" local commit_match="^([0-9a-f]{40}|[0-9a-f]{7})$" if [[ "$commit" =~ $commit_match ]]; then printf "$(_gh_url)/commit/$commit" | _copy_and_print elif [[ "$commit" == 'l' ]]; then printf "$(_gh_url)/commit/$(_git_sha)" | _copy_and_print else _gh_url | _copy_and_print fi } #------------------------------------------------# # Section: https://github.com/junegunn/fzf:[FZF] # #------------------------------------------------# # Label: FZF Preview and Select # Description: Preview and select one ore more files. _fzf_preview_and_select() { fzf --preview 'bat --theme DarkNeon --color always {}' --multi --print0 } #--------------------------------------------------# # Section: https://rubyonrails.org:[Ruby on Rails] # #--------------------------------------------------# # Label: Process Ruby on Rails New Option # Description: Process option for constructing new Rails application skeletons with custom build settings. # Parameters: $1 (required): Application name, $2 (required): Option. _process_rails_new_option() { local flags="--skip-git --skip-action-cable --skip-action-text --skip-active-storage --skip-jbuilder --skip-hotwire --skip-test --skip-keeps --asset-pipeline propshaft --database postgresql" case $2 in "default") _create_rails_skeleton "$1";; "api") _create_rails_skeleton "$1" "$flags --api";; "slim") _create_rails_skeleton "$1" "$flags";; "static") _create_rails_skeleton "$1" "$flags --skip-javascript";; "dummy") _create_rails_skeleton "$1" "$flags --skip-bundle --skip-javascript";; 'q');; *) printf "%s\n" "ERROR: Invalid option.";; esac } # Label: Create Rails Skeleton # Description: Create new Rails application skeleton. # Parameters: $1 (required): The application name, $2 (optional): The build options to apply. _create_rails_skeleton() { printf "%s\n" "rails new $1 $2" rails new $1 $2 } ================================================ FILE: lib/templates/.config/bash/functions-public.sh.tt ================================================ #! /usr/bin/env bash #-----------------------------------------------------# # Section: link:https://asciidoctor.org[ASCII Doctor] # #-----------------------------------------------------# # Label: ASCII Doctor Open # Description: Transforms ASCII Doc into HTML and opens in default browser. # Parameters: $1 (optional): Path to ASCII Doc file. Default: README.adoc. ado() { local input=${1:-README.adoc} local output=$(mktemp -t asciidoc -u).html asciidoctor --failure-level WARN --out-file "$output" "$input" open "$output" read -p "Viewing: $output. Use any key to continue. " response rm -f "$output" } #---------------------------------------# # Section: https://bundler.io:[Bundler] # #---------------------------------------# # Label: Bundler Clean (all) # Description: Clean projects of gem artifacts. bca() { while read -r project; do ( cd "$project" if [[ -f "Gemfile.lock" ]]; then printf "\033[36m${project}\033[m\n" # Outputs project in cyan color. rm -rf pkg artifacts=("$(rg --no-ignore-vcs --files --glob "*.gem")") for artifact in ${artifacts[*]}; do printf "%s\n" " - $artifact" rm -f "$artifact" done fi ) done < <(ls -A1) } # Label: Bundler Config Gem # Description: Configure Bundler to use local gem for development purposes. # Parameters: $1 (required): Gem name, $2 (required): Gem path. bcg() { local gem_name=$1 local gem_path=$2 if [[ -z "$gem_name" ]]; then printf "%s\n" "ERROR: Gem name must be supplied!" return 1 fi if [[ -z "$gem_path" ]]; then printf "%s\n" "ERROR: Gem path must be supplied!" return 1 fi bundle config set --global "local.$gem_name" "$gem_path" printf "%s\n" "Added: $(tail -n 1 $BUNDLE_USER_CONFIG)" } # Label: Bundle List # Description: List gem dependencies for project and copy them to clipboard. bl() { local collection=() printf "%s\n" "Calculating gem dependencies (will be copied to clipboard)..." for gem in $(bundle list --name-only); do collection+=("$(bundle info "$gem")") done printf "%s\n" "${collection[@]}" | pbcopy && pbpaste } # Label: Bundle Outdated (all) # Description: Answer outdated gems for projects in current directory. boa() { while read -r project; do ( cd "$project" if [[ -f "Gemfile.lock" ]]; then printf "\033[36m${project}\033[m: " # Outputs project in cyan color. # Capture current project status: Search for bullets (*, outdated gems) or missing (not found) gems. local results=$(bundle outdated | rg --only-matching "(\*.+|.+not\sfind.+)") # Print project status if Bundler activity is detected, otherwise a checkmark for passing status. if [[ -n "$results" ]]; then printf "\n%s\n" "$results" else printf "✓\n" fi fi ) done < <(ls -A1) } # Label: Bundle Update # Description: Update all gems or a single gem in current project. # Parameters: $1 (optional): The desired gem. Default: nil. bu() { local gem="$1" if [[ -n "$gem" ]]; then bundle update "$gem" else bundle update --all fi } # Label: Bundle Update (all) # Description: Update gems for projects in current directory. bua() { while read -r project; do ( cd "$project" if [[ -f "Gemfile.lock" ]]; then rm -f Gemfile.lock bundle install --quiet # Print project status if Bundler activity is detected, otherwise a checkmark for passing status. printf "\033[36m${project}\033[m: " # Outputs project in cyan color. if [[ $(git diff | wc -l | tr -d ' ') -gt 0 ]]; then printf "↑\n" else printf "✓\n" fi fi ) done < <(ls -A1) } #--------------------------------------------------------------------# # Section: https://alchemists.io/projects/caliber:[Code Quality] # #--------------------------------------------------------------------# # Label: Code Quality (all) # Description: Run code quality tasks for projects in current directory. cqa() { while read -r project; do ( cd "$project" if [[ -f "Gemfile.lock" && -f "Rakefile" ]]; then # Prints project (cyan). printf "\033[36m${project}\033[m:\n" rake quality printf "\n" fi ) done < <(ls -A1) } # Label: Code Quality Issues # Description: List all source files affected by code quality issues. cqi() { local comments=( "TODO" "FIX" "DUPLICATE" "shellcheck disable" ":reek:" "rubocop:disable" "rubocop:todo" ":nocov:" ) for comment in ${comments[*]}; do rg --case-sensitive --iglob '!vendor' --regexp "^\s*?(#|--|//) $comment" . done } #---------------------------------# # Section: https://curl.se:[curl] # #---------------------------------# # Label: Curl Diagnostics # Description: Curl with diagnostic information for request. # Parameters: $1 (required): The URL. curld() { local url="$1" printf -v diagnostics "%s\n" "\n" \ "HTTP Version: %{http_version}" \ "HTTP Status: %{http_code}" \ "Content Type: %{content_type}" \ "DNS Lookup: %{time_namelookup} seconds" \ "Connect: %{time_connect} seconds" \ "App Connect: %{time_appconnect} seconds" \ "Pre-Transfer: %{time_pretransfer} seconds" \ "Start Transfer: %{time_starttransfer} seconds" \ "Speed: %{speed_upload}↑ %{speed_download}↓ bytes/second" \ "Total Time: %{time_total} seconds" \ "Total Size: %{size_download} bytes" curl --write-out "$diagnostics" --url "$url" } # Label: Curl Inspect # Description: Inspect remote file with default editor. # Parameters: $1 (required): The URL. curli() { if [[ "$1" ]]; then local file=$(mktemp -t suspicious_curl_file) || { printf "%s\n" "ERROR: Unable to create temporary file."; return; } curl --location --fail --silent --show-error "$1" > $file || { printf "%s\n" "Failed to curl file."; return; } $EDITOR --wait $file || { printf "Unable to open temporary curl file.\n"; return; } rm -f $file; else printf "%s\n" "ERROR: URL must be supplied." return 1 fi } #------------------------------------------# # Section: https://www.docker.com:[Docker] # #------------------------------------------# # Label: Docker Comppose # Description: Run Docker Comppose for development (default) or production. # Parameters: $1 (optional): Environment. Use: "p" for "production". Default: "". drc() { local environment="$1" shift if [[ "$environment" == "p" ]]; then docker-compose "$@" else docker-compose --file "compose.dev.yml" "$@" fi } # Label: Docker Compose Build # Description: Build service for development (default) or production. # Parameters: $1 (optional): Environment. Use: "p" for "production". Default: "". drcb() { local environment="$1" drc "$environment" "build" } # Label: Docker Compose Down # Description: Shutdown services for development (default) or production. # Parameters: $1 (optional): Environment. Use: "p" for "production". Default: "". drcd() { local environment="$1" drc "$environment" "down" } # Label: Docker Compose Execute # Description: Execute command for development (default) or production. # Parameters: $1 (optional): Environment. Use: "p" for "production". Default: "". drce() { local environment="$1" drc "$environment" "exec" } # Label: Docker Compose Run # Description: Run oneoff command for development (default) or production. # Parameters: $1 (optional): Environment. Use: "p" for "production". Default: "". drcr() { local environment="$1" drc "$environment" "run" "--rm" } # Label: Docker Compose Up # Description: Startup services for development (default) or production. # Parameters: $1 (optional): Environment. Use: "p" for "production". Default: "". drcu() { local environment="$1" drc "$environment" "up" } #-------------------# # Section: Dotfiles # #-------------------# # Label: Dotfiles # Description: Learn about dotfile aliases, functions, etc. # Parameters: $1 (optional): The option selection, $2 (optional): The option input. dots() { while true; do if [[ $# == 0 ]]; then printf "\n%s\n" "Usage: dots OPTION" printf "\n%s\n" "Dotfile Options:" printf " %s\n" "a: Print aliases." printf " %s\n" "f: Print functions." printf " %s\n" "g: Print Git hooks." printf " %s\n" "p: Print all." printf " %s\n" "s: Search for alias/function." printf " %s\n\n" "q: Quit/Exit." read -r -p "Enter selection: " response printf "\n" _process_dots_option $response "$2" else _process_dots_option $1 "$2" fi break done } #------------------------------------------------------------# # Section: https://github.com/Schniz/fnm:[Fast Node Manager] # #------------------------------------------------------------# # Label: JavaScript Force # Description: Installs new Node version as default and removes previous version. # Parameters: $1 (required): Version. jsf() { local version="$1" local previous previous="$(fnm current)" fnm install "$version" fnm default "$version" fnm uninstall "$previous" } # Label: JavaScript Upgrade (all) # Description: Upgrade JavaScript projects in current directory to new JavaScript version. # Parameters: $1 (required): The new version to upgrade to. Example: 1.2.3. jsua() { local new_version="$1" local paths=(".node-version" "home_files/.node-version.tt") if [[ "$new_version" ]]; then while read -r project; do ( cd "$project" printf "\033[36m${project}\033[m\n" # Outputs in cyan color. for path in "${paths[@]}"; do if [[ -e "$path" ]]; then old_version="$(head -n 1 "$path")" if [[ "$old_version" != "$new_version" ]]; then printf "%s\n" "$new_version" > "$path" printf "%s\n" " $path: $old_version --> $new_version" fi fi done ) done < <(ls -A1) else printf "%s\n" "ERROR: Version must be supplied." return 1 fi } #------------------# # Section: General # #------------------# # Label: Colorized Type # Description: Identical to "type" system command but with Bat support. # Parameters: $1 (required): The alias or function to inspect source code for. cype() { local name="$1" if [[ -n "$name" ]]; then type "$name" | cat --language "bash" fi } # Label: Environment Update # Description: Update environment with latest software. eup() { local oss_path="$HOME/Engineering/OSS" local alchemists_path="$HOME/Engineering/Companies/Alchemists" softwareupdate --all --install --agree-to-license xcode-select --install hbsu rustup update cargo install-update --all tldr --update docker system prune --force docker buildx prune --force ( cd "$HOME/.cache/pgenv" git pull ) if [[ -d "$oss_path" ]]; then ( cd "$oss_path" gpua gvaca gemuc bca bua ) else printf "%s\n" "Skipped. Unknown path: #oss_path." fi if [[ -d "$alchemists_path" ]]; then ( cd "$alchemists_path" gpua gvaca bca bua ) else printf "%s\n" "Skipped. Unknown path: #alchemists_path." fi noti --title "Environment Update" } # Label: ISO # Description: Builds an ISO image from mounted volume. # Parameters: $1 (required): Volume source path. $2 (required): ISO output file path. iso() { local source_path="$1" local output_path="$HOME/Downloads/$2.iso" if [[ ! -d "$source_path" ]]; then printf "%s\n" "Source path must be supplied or doesn't exist: $source_path." return 1 fi if [[ -z "$2" ]]; then printf "%s\n" "ISO file name must be supplied." return 1 fi printf "%s\n" "Creating $output_path..." hdiutil makehybrid -iso -joliet -o "$output_path" "$source_path" } # Label: Kill Process # Description: Kill errant/undesired process. # Parameters: $1 (required): The search query, $2 (optional): The signal. Default: 15. kilp() { local query="$1" local signal=${2:-15} pkill -$signal -l -f "$query" } # Label: Tab to Space # Description: Convert file from tab to space indentation. # Parameters: $1 (required): File path, $2 (optional): Number of spaces. Default: 2. t2s() { local number_of_spaces="${2:-2}" if [[ "$1" ]]; then local temp_file=$(mktemp -t tabs_to_spaces) || { printf "\n%s\n" "ERROR: Unable to create temporary file."; return; } expand -t $number_of_spaces "$1" > $temp_file cat $temp_file > "$1" printf "%s\n" "Converted: $1." rm -f $temp_file; else printf "%s\n" "ERROR: File must be supplied." return 1 fi } #------------------------------------# # Section: https://git-scm.com:[Git] # #------------------------------------# # Label: Git Add # Description: Interactively adds modified/untracked files. ga() { git ls-files --modified --other --exclude-standard \ | _fzf_preview_and_select \ | xargs -0 -o -t git add } # Label: Git Safe # Description: Marks repository as safe for auto-loading project's `bin` path. gafe() { if [[ -d ".git" ]]; then mkdir -p .git/safe printf "%s\n" "Repository has been marked safe." exec "$HOMEBREW_PREFIX/bin/bash" fi } # Label: Git Add (all) # Description: Apply file changes (including new files) for projects in current directory. galla() { while read -r project; do ( cd "$project" if [[ -d ".git" ]]; then # Apply all changes to Git. local results=$(git add --verbose --all .) # Print project name (cyan) and Git activity (white) only if Git activity was detected. if [[ -n "$results" ]]; then printf "\033[36m${project}\033[m:\n$results\n" fi fi ) done < <(ls -A1) } # Label: Git Stash # Description: Creates stash of all changes. # Parameters: $1 (optional): Label. Default: "All Work (YYYY-MM-DD HH:MM:SS AM|PM Z)." gash() { local label=${1:-"All Work ($(date '+%Y-%m-%d %r %Z'))"} local reference="refs/stashes/$USER" git stash push --include-untracked --message "$label" git stash export --to-ref "$reference" git push --no-verify --force origin "$reference" } # Label: Git Stash (all) # Description: Answer stash count for projects in current directory. gasha() { while read -r project; do ( cd "$project" if [[ -d ".git" ]]; then local count=$(_git_stash_count) if [[ -n $count && $count != 0 ]]; then printf "\033[36m${project}\033[m: $count\n" # Outputs in cyan color. fi fi ) done < <(ls -A1) } # Label: Git Stash Clear # Description: Clears all stashes. gashc() { local reference="refs/stashes/$USER" git stash clear git update-ref -d "$reference" git push --delete origin "$reference" } # Label: Git Stash Drop # Description: Drop stash or prompt for stash to drop. gashd() { _process_git_stash "git stash drop" "Git Stash Drop Options (select stash to drop)" _git_stash_push } # Label: Git Stash Import # Description: Imports a remote stash. # Parameters: $1 (optional): The remote name. Default: $USER. gashi() { local name="${1:-$USER}" git stash import "refs/stashes/$name" } # Label: Git Stash List # Description: List stashes. gashl() { git stash list --pretty=format:'%C(magenta)%gd%C(reset) %C(yellow)%h%C(reset) %s %C(green)(%cr)%C(reset)' } # Label: Git Stash Pop # Description: Pop stash or prompt for stash to pop. gashp() { _process_git_stash "git stash pop" "Git Stash Pop Options (select stash to pop)" _git_stash_push } # Label: Git Stash Show # Description: Show stash or prompt for stash to show. # Parameters: $1 (optional): Show git diff. Default: skipped. gashs() { local stash=($(git stash list)) local diff_option="$1" if [[ -n "$diff_option" ]]; then case "$diff_option" in 'd') _process_git_stash "git stash show" "Git Stash Diff Options (select stash to diff)";; 't') _process_git_stash "git difftool" "Git Stash Diff Options (select stash to diff)";; *) printf "%s\n\n" "Usage: gashs OPTION" printf "%s\n" "Available options:" printf "%s\n" " d: Git diff." printf "%s\n" " t: Git difftool." return;; esac else _process_git_stash "_git_show_details" "Git Stash Show Options (select stash to show)" fi } # Label: Git Stash Stage # Description: Creates stash of staged work. # Parameters: $1 (optional): Label. Default: "Staged Work (YYYY-MM-DD HH:MM:SS AM|PM Z)." gasht() { local label=${1:-"Staged Work ($(date '+%Y-%m-%d %r %Z'))."} git stash push --stage --message "$label" } # Label: Git Branch Create # Description: Create and switch to branch. # Parameters: $1 (required): New branch name. gbc() { local name="$1" if [[ "$name" ]]; then git switch --create "$name" else printf "%s\n" "ERROR: Branch name must be supplied." return 1 fi } # Label: Git Branch Create (all) # Description: Create and switch to branch for projects in current directory. # Parameters: $1 (required): The branch name. gbca() { local branch="$1" if [[ -n "$branch" ]]; then while read -r project; do ( cd "$project" if [[ -d ".git" ]]; then if [[ "$(_git_branch_name)" != "$branch" ]]; then git switch --create "$branch" --track printf "\033[36m${project}\033[m: $branch\n" # Output in cyan and branch in white color. fi fi ) done < <(ls -A1) else printf "%s\n" "ERROR: Branch name must be supplied." fi } # Label: Git Branch Delete # Description: Interactively delete local and/or remote branch. gbd() { local branch="$(gbl | fzf | awk '{print $1}')" if [[ -n "$branch" ]]; then gbdl "$branch" gbdr "$branch" fi } # Label: Git Branch Delete (local) # Description: Delete local branch. # Parameters: $1 (required): Branch name. gbdl() { local branch="$1" if [[ -n "$(git branch --list $branch)" ]]; then printf "\033[31m" # Red. read -p "Delete \"$branch\" local branch (y/n)?: " response printf "\033[m" # White. if [[ "$response" == 'y' ]]; then git branch --delete --force "$branch" else printf "%s\n" "Local branch deletion aborted." fi else printf "%s\n" "Local branch not found." fi } # Label: Git Branch Delete (merged) # Description: Delete remote and local merged branches. gbdm() { if [[ $(_git_branch_name) != "$(_git_branch_default)" ]]; then printf "%s\n" "ERROR: Whoa, switch to default branch first." return 1 fi # Remote git branch --remotes \ --merged \ | rg "origin" \ | rg --invert-match "$(_git_branch_default)" \ | sed 's/origin\///' \ | xargs -n 1 git push --delete origin # Local git branch --merged | rg --invert-match "\* $(_git_branch_default)" | xargs -n 1 git branch --delete --force } # Label: Git Branch Delete (remote) # Description: Delete remote branch. # Parameters: $1 (required): Branch name. gbdr() { local branch="$1" if [[ -n "$(git branch --remotes --list origin/$branch)" ]]; then printf "\033[31m" # Red. read -p "Delete \"$branch\" remote branch (y/n)?: " response printf "\033[m" # White. if [[ "$response" == 'y' ]]; then git push --delete origin "$branch" else printf "%s\n" "Remote branch deletion aborted." fi else printf "%s\n" "Remote branch not found." fi } # Label: Git Branch Facsimile # Description: Duplicate current branch with new name and switch to it. # Parameters: $1 (required): New branch name. gbf() { local new="$1" local old="$(_git_branch_name)" if [[ "$new" ]]; then git switch --create "$new" "$old" --track git commit --allow-empty --no-verify --message "----- End of $old work -----" else printf "%s\n" "ERROR: Branch name must be supplied." return 1 fi } # Label: Git Branch List # Description: List local and remote branch details. gbl() { local format="%(refname)|%(color:yellow)%(objectname)|%(color:reset)|%(color:blue bold)%(authorname)|%(color:green)|%(committerdate:relative)" git for-each-ref --sort="authordate:iso8601" \ --sort="authorname" \ --color \ --format="$format" \ refs/heads \ refs/remotes/origin \ | sed '/HEAD/d' \ | sed 's/refs\/heads\///g' \ | sed 's/refs\/remotes\/origin\///g' \ | uniq \ | sort \ | column -s '|' -t } # Label: Git Branch List (all) # Description: List current branch for projects in current directory. gbla() { while read -r project; do ( cd "$project" if [[ -d ".git" ]]; then local branch="$(_git_branch_name)" printf "\033[36m${project}\033[m: " # Output in cyan color. if [[ "$branch" == "$(_git_branch_default)" ]]; then printf "%s\n" "$branch" else printf "\033[31m$branch\033[m\n" # Output in red color. fi fi ) done < <(ls -A1) } # Label: Git Branch List (owner) # Description: List branches owned by current author or supplied author. # Parameters: $1 (optional): The author name. gblo() { local owner="${1:-$(git config get user.name)}" gbl | rg --color never "$owner" } # Label: Git Branch Number (all) # Description: Answer number of branches for projects in current directory. gbna() { while read -r project; do ( cd "$project" if [[ -d ".git" ]]; then local current_branch="$(_git_branch_name)" local number="$(gbl | rg --invert-match "$(_git_branch_default)" | wc -l | tr -d ' ')" if [[ $number -gt 0 ]]; then # Output project in cyan and number in white color. printf "\033[36m${project}\033[m: $number\n" fi fi ) done < <(ls -A1) } # Label: Git Branch Rename # Description: Rename current branch. # Parameters: $1 (required): Branch name. gbr() { local new_branch="$1" local old_branch="$(_git_branch_name)" git branch --move "$new_branch" if [[ -n "$(git branch --remotes --list origin/$old_branch)" ]]; then printf "\033[31m" # Red. read -p "Delete \"$old_branch\" remote branch and push \"$new_branch\" branch (y/n)?: " response printf "\033[m" # White. if [[ "$response" == 'y' ]]; then git push --delete origin "$old_branch" git push --set-upstream origin "$new_branch" fi fi } # Label: Git Branch Switch # Description: Switch between branches. gbs() { gbl | fzf | awk '{print $1}' | xargs git switch } # Label: Git Branch Switch (all) # Description: Switch to given branch for projects in current directory. # Parameters: $1 (required): The branch name. gbsa() { local branch="$1" if [[ -n "$branch" ]]; then while read -r project; do ( cd "$project" if [[ -d ".git" ]]; then local current_branch="$(_git_branch_name)" if [[ $(git rev-parse --quiet --verify "$branch") && "$current_branch" != "$branch" ]]; then git switch --quiet "$branch" printf "\033[36m${project}\033[m: $branch\n" # Output in cyan and branch in white color. fi fi ) done < <(ls -A1) else printf "%s\n" "ERROR: Branch name must be supplied." fi } # Label: Git Commit (all) # Description: Commit changes (unstaged and staged) for projects in current directory. gcaa() { local temp_file=$(mktemp -t git-commit) cp $HOME/.config/git/commit_message.txt $temp_file $EDITOR --wait $temp_file while read -r project; do ( cd "$project" if [[ -d ".git" ]]; then # Only process projects that have changes. if [[ "$(git status --short)" ]]; then printf "\033[36m${project}\033[m:\n" # Outputs in cyan color. git commit --all --cleanup strip --file $temp_file fi fi ) done < <(ls -A1) rm -f $temp_file } # Label: Git Commit and Push (all) # Description: Commit and push changes for projects in current directory. gcap() { local temp_file=$(mktemp -t git-commit) cp $HOME/.config/git/commit_message.txt $temp_file $EDITOR --wait $temp_file while read -r project; do ( cd "$project" if [[ -d ".git" ]]; then # Only process projects that have changes. if [[ "$(git status --short)" ]]; then printf "\033[36m${project}\033[m:\n" # Outputs in cyan color. git commit --all --cleanup strip --file $temp_file && gp fi fi ) done < <(ls -A1) rm -f $temp_file } # Label: Git Commit Breakpoint # Description: Create a breakpoint (empty) commit to denote related commits in a feature branch. # Parameters: $1 (optional): A custom label. Default: "Breakpoint" gcb() { local label="${1:-Breakpoint}" git commit --allow-empty --no-verify --message "----- $label -----" } # Label: Git Commit Fixup # Description: Create fixup commit with optional amend or reword support. # Parameters: $1 (required): SHA, $2 (optional): (a)mend or (r)eword. gcf() { local sha="$1" local kind="$2" if [[ -z "$sha" ]]; then printf "%s\n" "ERROR: SHA is missing." return fi case $kind in 'a') git commit --fixup=amend:"$sha";; 'r') git commit --fixup=reword:"$sha";; *) git commit --fixup "$sha";; esac } # Label: Git Commit Fix (file) # Description: Create commit fix for file (ignores previous fixups). gcff() { local file_path local file_sha file_path="$(git ls-files --modified | _fzf_preview_and_select)" if [[ -a "$file_path" ]]; then file_sha="$(git log --grep 'fixup!' --invert-grep --pretty=format:%h -1 "$file_path")" else return 0 fi if [[ "($(_git_branch_shas))" == *"$file_sha"* ]]; then git add "$file_path" && git commit --fixup "$file_sha" fi } # Label: Git Commit Fix (interactive) # Description: Select which commit to fix within current feature branch. # Parameters: $1 (optional): (a)mend or (r)eword. gcfi() { local kind="$1" selection=$( git log --color --pretty=format:"$(_git_log_enrich_format)" "$(_git_branch_range)" \ | _git_log_enrich \ | fzf --preview 'git show --color {1}' --preview-window=wrap \ | cut -d ' ' -f 1 ) if [[ -n "$selection" ]]; then gcf "$selection" "$kind" fi } # Label: Git Diff Files # Description: List all added/changed files on current branch. gdf() { git log --pretty="" --name-only "$(_git_branch_range)" \ | sort \ | uniq \ | _fzf_preview_and_select \ | xargs "$EDITOR" } # Label: Git Day # Description: Answer summarized list of current day activity for projects in current directory. gday() { gince "12am" } # Label: Git Reset Hard # Description: Reset to HEAD, destroying all untracked, staged, and unstaged changes. UNRECOVERABLE! # Parameters: $1 (optional): The number of commits to reset or a specific commit SHA. gesh() { local value="$1" local number_pattern="^[0-9]+$" local commit_pattern="^[a-f0-9]+$" git clean --force --quiet -d if [[ "$value" =~ $number_pattern ]]; then git reset --hard "HEAD~${value}" elif [[ "$value" =~ $commit_pattern ]]; then git reset --hard "${value}" else git reset --hard HEAD fi } # Label: Git Reset Hard (all) # Description: Destroy all untracked, staged, and unstaged changes for all projects in current directory. UNRECOVERABLE! # Parameters: $1 (optional): The number of commits to reset or a specific commit SHA. gesha() { while read -r project; do ( cd "$project" if [[ -d ".git" ]]; then printf "\n\033[36m${project}\033[m:\n" # Outputs in cyan color. gesh "$1" fi ) done < <(ls -A1) } # Label: Git Reset Soft # Description: Resets previous commit (default), resets back to number of commits, or resets to specific commit. # Parameters: $1 (optional): The number of commits to reset or a specific commit SHA. gess() { local value="$1" local number_pattern="^[0-9]+$" local commit_pattern="^[a-f0-9]+$" if [[ "$value" =~ $number_pattern ]]; then git reset --soft "HEAD~${value}" elif [[ "$value" =~ $commit_pattern ]]; then git reset --soft "${value}" else git reset --soft HEAD^ fi } # Label: Git Get Config Value (all) # Description: Answer key value for projects in current directory. # Parameters: $1 (required): The key name. ggeta() { if [[ "$1" ]]; then while read -r project; do ( cd "$project" if [[ -d ".git" ]]; then # Get Git config value for given key. local result=$(git config get "$1") # Print project (cyan). printf "\033[36m${project}\033[m: " # Print result. if [[ -n "$result" ]]; then printf "$1 = $result\n" # White else printf "\033[31mKey not found.\033[m\n" # Red fi fi ) done < <(ls -A1) else printf "%s\n" "ERROR: Key must be supplied." return 1 fi } # Label: Git Guise Add # Description: Adds Git configuration and associated profile. # Parameters: $1 (required): Label. gga() { local label="$1" local name="${label,,}" local path="$HOME/.config/git/profiles/${name,,}" if [[ -z "$label" ]]; then printf "%s\n" "ERROR: Guise label must be supplied." return fi git config set --global \ includeIf."gitdir:~/Engineering/Companies/$label/".path "$HOME/.config/git/profiles/$name" \ && touch "$path" \ && printf "%s\n" "Created: $path." } # Label: Git Guise Delete # Description: Deletes Git configuration and associated profile. # Parameters: $1 (required): Name. ggd() { local name="$1" local path="$HOME/.config/git/profiles/$name" if [[ -z "$name" ]]; then printf "%s\n" "ERROR: Guise name must be supplied." return fi rg --no-line-number --ignore-case --regexp "includeIf.+$name" "$GIT_CONFIG_GLOBAL" \ | sed 's/\[includeIf \"//g' \ | sed 's/\"\]//g' \ | xargs -I {} git config unset --global "includeIf.{}.path" \ && rm -f "$path" \ && printf "%s\n" "Deleted: $path." } # Label: Git Show # Description: Show commit details with optional diff support. # Parameters: $1 (optional): The commit to show. Default: , $2 (optional): Launch difftool. Default: false. ghow() { local commit="$1" local difftool="$2" if [[ -n "$commit" && -n "$difftool" ]]; then _git_show_details "$commit" git difftool "$commit^" "$commit" elif [[ -n "$commit" && -z "$difftool" ]]; then _git_show_details "$commit" else _git_show_details fi } # Label: Git Churn # Description: Answer commit churn for project files (sorted highest to lowest). ghurn() { git log --all \ --find-renames \ --find-copies \ --name-only \ --format='format:' "$@" \ | sort \ | grep --invert-match '^$' \ | uniq -c \ | sort \ | awk '{print $1 "\t" $2}' \ | sort --general-numeric-sort --reverse \ | more } # Label: Git Init (all) # Description: Initialize/re-initialize repositories in current directory. gia() { while read -r project; do ( cd "$project" if [[ -d ".git" ]]; then printf "\033[36m${project}\033[m: " # Print project (cyan) and message (white). git init fi ) done < <(ls -A1) } # Label: Git File # Description: Show file details for a specific commit (with optional diff support). # Parameters: $1 (required): The file, $2 (required): The commit, $3 (optional): Launch difftool. Default: false. gile() { local file="$1" local commit="$2" local diff="$3" if [[ -z "$file" ]]; then printf "%s\n" "ERROR: File is missing." return 1 fi if [[ -z "$commit" ]]; then printf "%s\n" "ERROR: Commit SHA is missing." return 1 fi git show --stat --pretty=format:"$(_git_log_details_format)" "$commit" -- "$file" if [[ -n "$diff" ]]; then gdt $commit^! -- "$file" fi } # Label: Git Import # Description: Import remote repository commits into current local branch. # Parameters: $1 (required): URL, $2 (optional): Branch, $3 (optional): Name. gim() { local url="$1" local branch="${2:-main}" local name="${3:-import}" local remote="$name/$branch" if [[ -z "$url" ]]; then printf "%s\n" "Remote repository URL must be supplied." return 1 fi git remote add "$name" "$url" git fetch "$name" git cherry-pick "$(git rev-list --max-parents=0 "$remote")".."$(git rev-list -1 "$remote")" git remote remove "$name" } # Label: Git Since # Description: Answer summarized list of activity since date/time for projects in current directory. # Parameters: $1 (required): The date/time since value, $2 (optional): The date/time until value, $3 (optional): The commit author. gince() { if [[ "$1" ]]; then while read -r project; do ( cd "$project" if [[ -d ".git" ]]; then # Capture git log activity. results=$(git log --reverse --color --format="$(_git_log_enrich_format)" --since "$1" --until "$2" --author "$3" | _git_log_enrich) # Print project name (cyan) and Git activity (white) only if Git activity was detected. if [[ -n "$results" ]]; then printf "\033[36m${project}:\033[m\n$results\n" fi fi ) done < <(ls -A1) else printf "%s\n" "ERROR: Date/time must be supplied." return 1 fi } # Label: Git Info # Description: Print repository overview information. ginfo() { printf "\n%s\n\n" "$(_print_black_on_white ' Local Configuration (.git/config) ')" git config list --local printf "\n%s\n\n" "$(_print_black_on_white ' Stashes ')" local stashes="$(gashl)" if [[ -n "$stashes" ]]; then printf "%s\n" "$stashes" else printf "%s\n" "None." fi printf "\n%s\n\n" "$(_print_black_on_white ' Branches ')" gbl printf "\n%s\n\n" "$(_print_black_on_white ' Remote URLs ')" git remote --verbose printf "\n%s\n\n" "$(_print_black_on_white ' File Churn (Top 25) ')" ghurn | head -n 25 printf "\n%s\n\n" "$(_print_black_on_white ' Commits by Author ')" guthors printf "\n%s\n\n" "$(_print_black_on_white ' Total Commits ')" gount printf "\n%s\n\n" "$(_print_black_on_white ' Last Tag ')" _git_tag_last_info printf "\n%s\n\n" "$(_print_black_on_white ' Last Commit ')" git show --decorate --stat printf "\n%s\n\n" "$(_print_black_on_white ' Current Status ')" git status --short --branch } # Label: Git File History # Description: View file commit history (with optional diff support). # Parameters: $1 (required): The file path. gistory() { if [[ -z "$1" ]]; then printf "%s\n" "ERROR: File must be supplied." return 1 fi local file="$1" local commits=($(git rev-list --use-bitmap-index --reverse HEAD -- "$file")) _git_file_commits commits[@] "$file" } # Label: Git Blame History # Description: View commit history for file and/or lines (with optional diff support). # Parameters: $1 (required): The file path, $2 (optional): The file lines (,). glameh() { if [[ -z "$1" ]]; then printf "%s\n" "ERROR: File must be supplied." return 1 fi local file="$1" local lines="$2" local commits=("$(git blame -s -M -C -L "$lines" "$file" | awk '{print $1}' | sort -u)") _git_file_commits commits[@] "$file" } # Label: Git Clean (all) # Description: Clean uncommitted files from all projects in current directory. gleana() { while read -r project; do ( cd "$project" if [[ -d ".git" ]]; then # Only process projects that have untracked changes. if [[ "$(git status --untracked-files --short)" ]]; then printf "\n\033[36m${project}\033[m:\n" # Outputs in cyan color. git clean -d --force fi fi ) done < <(ls -A1) } # Label: Git Clear # Description: Clear repository for packaging/shipping purposes. glear() { if [[ ! -d .git ]]; then printf "%s\n" "ERROR: Project is not a Git repository." return 1 fi read -p "Permanently delete/compact repository files? Continue (y/n)?: " response if [[ "$response" == "y" ]]; then printf "%s\n\n" "Verifying connectivity and validity of the objects in Git repository..." git fsck printf "%s\n\n" "Pruning rerere records of older conflicting merges..." git rerere gc printf "\n%s\n\n" "Aggressively pruning repository..." git gc --aggressive --prune=now printf "\n%s\n" "Clearing reflog..." git reflog expire --expire=now --all printf "\n%s\n" "Clearing commit message file..." echo > .git/COMMIT_EDITMSG printf "\n%s\n" "Clearing sample Git Hooks..." rm -rf .git/hooks/*.sample printf "\n%s\n" "Deleting code coverage reports..." rm -rf coverage printf "\n%s\n" "Deleting Rubocop cache..." copd printf "\n%s\n" "Deleting Node modules..." rm -rf node_modules printf "\n%s\n" "Deleting temp directory..." rm -rf tmp else printf "%s\n" "Git clear aborted." fi } # Label: Git Log Grep # Description: Grep Git log by query. # Parameters: $1 (required): Query. glg() { local query="$1" if [[ -z "$query" ]]; then printf "%s\n" "ERROR: Grep query is required." return 1 fi selection=$( git log --color --pretty=format:"$(_git_log_enrich_format)" --grep "$query" \ | _git_log_enrich \ | fzf --preview 'git show --color {1}' --preview-window=wrap \ | cut -d ' ' -f 1 ) if [[ -n "$selection" ]]; then ghow "$selection" fi } # Label: Git Log (interactive) # Description: List default or feature branch commits with commit show and/or diff support. gli() { selection=$( git log --color --pretty=format:"$(_git_log_enrich_format)" "$(_git_branch_range)" \ | _git_log_enrich \ | fzf --preview 'git show --color {1}' --preview-window=wrap \ | cut -d ' ' -f 1 ) if [[ -n "$selection" ]]; then ghow "$selection" fi } # Label: Git Log Search # Description: Search Git log by query. # Parameters: $1 (required): Query. gls() { local query="$1" if [[ -z "$query" ]]; then printf "%s\n" "ERROR: Search query is required." return 1 fi selection=$( git log --color --pretty=format:"$(_git_log_enrich_format)" -S "$query" \ | _git_log_enrich \ | fzf --preview 'git show --color {1}' --preview-window=wrap \ | cut -d ' ' -f 1 ) if [[ -n "$selection" ]]; then ghow "$selection" fi } # Label: Git Log Fuzzy # Description: Fuzzy find commits in the log. glz() { git log --color --pretty=format:"$(_git_log_line_format)" \ | fzf --no-sort --reverse --preview 'git show --color {1}' --preview-window=wrap } # Label: Git Merge # Description: Interactively select a branch to merge into the current branch and delete after. # Parameters: $1 (required): The branch to merge. gm() { branch="$(gbl | fzf | awk '{print $1}')" git merge "$branch" && git branch --delete --force "$branch" && git push --delete origin "$branch" } # Label: Git Merge (all) # Description: Merges, deletes, and pushes feature branch. # Parameters: $1 (required): Branch. gma() { local branch="$1" if [[ -z "$branch" ]]; then printf "%s\n" "ERROR: Branch must be supplied." return 1 fi while read -r project; do ( cd "$project" if [[ -d ".git" && "$(_git_branch_name)" == "$branch" ]]; then printf "\033[36m${project}\033[m: Merging, deleting, and pushing...\n" git switch "$(_git_branch_default)" \ && git merge "$branch" \ && git branch --delete --force "$branch" \ && git push --delete origin "$branch" \ && git push fi ) done < <(ls -A1) } # Label: Git Month # Description: Answer summarized list of current month activity for projects in current directory. gmonth() { gince "1 month 12am" } # Label: Git Amend Push (all) # Description: Amend all changes and force push with lease for projects in current directory. gmpa() { while read -r project; do ( cd "$project" if [[ -d ".git" ]]; then # Only process projects that have changes. if [[ "$(git status --short)" ]]; then printf "\033[36m${project}\033[m:\n" # Outputs in cyan color. git commit --amend --all --no-edit && git push --force-with-lease fi fi ) done < <(ls -A1) } # Label: Git Notes Add (interactive) # Description: Select which commit note to add for current feature branch. gnai() { mapfile -t shas < <(_git_branch_shas) _git_commit_options "${shas[*]}" printf "\n" read -p "Enter selection or quit (q): " response if [[ "$response" == 'q' ]]; then return fi local selection=${shas[$((response - 1))]} printf "%s\n" "Selected: $selection" gna "$selection" } # Label: Git Notes Edit (interactive) # Description: Select which commit note to edit for current feature branch. gnei() { mapfile -t shas < <(_git_branch_shas) _git_commit_options "${shas[*]}" printf "\n" read -p "Enter selection or quit (q): " response if [[ "$response" == 'q' ]]; then return fi local selection=${shas[$((response - 1))]} printf "%s\n" "Selected: $selection" gne "$selection" } # Label: Git Notes Remove (interactive) # Description: Select which commit note to remove for current feature branch. gndi() { mapfile -t shas < <(_git_branch_shas) _git_commit_options "${shas[*]}" printf "\n" read -p "Enter selection or quit (q): " response if [[ "$response" == 'q' ]]; then return fi local selection=${shas[$((response - 1))]} printf "%s\n" "Selected: $selection" gnd "$selection" } # Label: Git Notes Show (interactive) # Description: Select which commit note to show for current feature branch. gnri() { mapfile -t shas < <(_git_branch_shas) _git_commit_options "${shas[*]}" printf "\n" read -p "Enter selection or quit (q): " response if [[ "$response" == 'q' ]]; then return fi local selection=${shas[$((response - 1))]} printf "%s\n" "Selected: $selection" gns "$selection" } # Label: Git Commit Count # Description: Answer total number of commits for current project. gount() { printf "Commits: " git rev-list --use-bitmap-index --count HEAD } # Label: Git Push (all) # Description: Push changes for projects in current directory. gpa() { while read -r project; do ( cd "$project" if [[ -d ".git" ]]; then # Only process projects that have changes. if [[ "$(git status --short --branch)" == *"[ahead"*"]" ]]; then printf "\033[36m${project}\033[m:\n" # Outputs in cyan color. gp fi fi ) done < <(ls -A1) } # Label: Git Pull (all) # Description: Pull new changes from remote branch for projects in current directory. gpua() { while read -r project; do ( cd "$project" if [[ -d ".git" ]]; then # Capture current project status. local results=$(git pull | tail -1) # Print project name and Git activity only if Git activity was detected. printf "\033[36m${project}\033[m: " # Outputs in cyan color. if [[ -n "$results" && "$results" != "Already up-to-date." ]]; then printf "\n %s\n" "$results" else printf "✓\n" fi fi ) done < <(ls -A1) } # Label: Git Remote Add # Description: Add remote repository. # Parameters: $1 (required): The repository URL. gra() { local url="$1" name=$(echo "$url" | awk -F/ '{print $4}') if [[ -z "$url" ]]; then printf "%s\n" "ERROR: Repository URL must be supplied." return 1 fi git remote add --no-tags "$name" "$url" git -c fetch.pruneTags=false fetch "$name" } # Label: Git Remote Delete # Description: Delete local remote. grd() { selection="$(git remote | grep -v '^origin$' | fzf)" git remote remove "$selection" printf "%s\n" "Removed remote: $selection." } # Label: Git Rebase (interactive) # Description: Rebase commits, interactively. # Parameters: $1 (optional): The number of commits or label (i.e. branch/tag) to rebase to. grbi() { local number_pattern="^[0-9]+$" local label_pattern="^[0-9a-zA-Z\_-]+$" local parent_sha=$(git log --pretty=format:%h -n 1 "$(_git_branch_parent)" 2> /dev/null || :) local value="${1:-$parent_sha}" if [[ "$value" =~ $number_pattern ]]; then git rebase --keep-empty --interactive "@~${value}" elif [[ "$(_git_branch_name)" == "$(_git_branch_default)" ]]; then git rebase --keep-empty --interactive --root elif [[ "$value" =~ $label_pattern ]]; then git rebase --keep-empty --interactive "$value" else printf "%s\n" "Invalid SHA, branch, or tag for rebasing: $value." return 1 fi } # Label: Git Rebase (quick) # Description: Rebase commits, quickly. Identical to `grbi` function but skips editor. # Parameters: $1 (optional): The commit number or branch to rebase to. Default: upstream or root. grbq() { GIT_EDITOR=true grbi "$1" } # Label: Git Root # Description: Change to repository root directory regardless of current depth. groot() { cd "$(git rev-parse --show-toplevel)" } # Label: Git Set Config Value (all) # Description: Set key value for projects in current directory. # Parameters: $1 (required): The key name, $2 (required): The key value. gseta() { if [[ "$1" && "$2" ]]; then while read -r project; do ( cd "$project" if [[ -d ".git" ]]; then # Set key value for current project. git config set "$1" "$2" # Print project (cyan) and email (white). printf "\033[36m${project}\033[m: $1 = $2\n" fi ) done < <(ls -A1) else printf "%s\n" "ERROR: Key and value must be supplied." return 1 fi } # Label: Git Status (all) # Description: Answer status of projects with uncommited/unpushed changes. gsta() { while read -r project; do ( cd "$project" if [[ -d ".git" ]]; then # Capture current project status info as an array. local results=($(git status --short --branch)) local size=${#results[@]} # Print Git activity if Git activity detected (white). if [[ $size -gt 2 ]]; then # Remove first and second elements since they contain branch info. results=("${results[@]:1}") results=("${results[@]:1}") # Print project (cyan). printf "\033[36m${project}\033[m:\n" # Print results (white). for line in "${results[@]}"; do printf "%s" "$line " if [[ $newline == 1 ]]; then printf "\n" local newline=0 else local newline=1 fi done fi fi ) done < <(ls -A1) } # Label: Git Statistics # Description: Answer statistics for current project. gstats() { if [[ -d ".git" ]]; then gount printf "Branches: %s\n" "$(gbl | wc -l | tr -d ' ')" printf "Tags: %s\n" "$(git tag | wc -l | tr -d ' ')" printf "Stashes: %s\n" "$(_git_stash_count)" printf "Size: %s\n" "$(git count-objects --human-readable)" fi } # Label: Git Statistics (all) # Description: Answer statistics for all projects in current directory. gstatsa() { while read -r project; do ( cd "$project" printf "\033[36m${project}\033[m:\n" # Print project (cyan) and message (white). gstats ) done < <(ls -A1) } # Label: Git Standup # Description: Answer summarized list of activity since yesterday for projects in current directory. gsup() { gince "yesterday.midnight" "midnight" $(git config get user.name) } # Label: Git Tag Delete # Description: Delete local and remote tag (if found). # Parameters: $1 (required): The tag name. gtd() { if [[ -z "$1" ]]; then printf "%s\n" "ERROR: Tag name must be supplied." return 1 fi read -p "Delete '$1' tag from local and remote repositories. Continue (y/n)?: " response if [[ "$response" == 'y' ]]; then printf "%s " "Local:" if [[ -n "$(git tag --list $1)" ]]; then git tag --delete "$1" else printf "%s\n" "No tag found." fi printf "%s " "Remote:" if [[ $(git config get remote.origin.url) && -n "$(git ls-remote --tags origin | rg $1)" ]]; then git push --delete origin "$1" else printf "%s\n" "No tag found." fi else printf "%s\n" "Tag deletion aborted." fi } # Label: Git Tag List # Description: List tags in tabular form. gtl() { local format="\ %(color:yellow)%(refname:short)%(color:reset)|%(taggerdate:short)|\ %(color:brightblue)%(taggername)%(color:reset)|\ %(color:brightmagenta)%(trailers:key=Commits,separator=)%(color:reset)|\ %(color:brightmagenta)%(trailers:key=Files,separator=)%(color:reset)|\ %(color:green)%(trailers:key=Deletions,separator=)%(color:reset)|\ %(color:red)%(trailers:key=Insertions,separator=)%(color:reset)|\ %(color:brightmagenta)%(trailers:key=Duration,separator=)%(color:reset)" git tag --list --sort=taggerdate --color --format="$format" | column -s "|" -t } # Label: Git Tag Rebuild # Description: Rebuild a previous tag. WARNING: Use with caution, especially if previously published. # Parameters: $1 (required): Version, $2 (required): Release notes path, $3 (optional): Creation date/time. Default: current date/time. gtr() { local version="$1" local path="$2" local datetime="${3:-$(date '+%Y-%m-%d %H:%M:%S')}" GIT_COMMITTER_DATE="$datetime" git tag --force --sign --file "$path" "$version" } # Label: Git Tail # Description: Answer commit history since last tag for current project (copies results to clipboard). gtail() { if [[ ! -d ".git" ]]; then printf "%s\n" "ERROR: Not a Git repository." return 1 fi if [[ $(git tag) ]]; then git log --reverse \ --color \ --pretty=format:"$(_git_log_enrich_format)" "$(_git_tag_last)..HEAD" \ | _git_log_enrich printf "\n" else git log --reverse --color --pretty=format:"$(_git_log_enrich_format)" | _git_log_enrich printf "\n" fi } # Label: Git Tail (all) # Description: Answer commit history count since last tag for projects in current directory. gtaila() { # Iterate through root project directories. while read -r project; do ( cd "$project" if [[ -d ".git" ]]; then local info=$(_git_commit_count_since_last_tag "$project") if [[ ! "$info" == *": 0"* ]]; then printf "%s\n" "$info" fi fi ) done < <(ls -A1) } # Label: Git Upstream Commit Count (all) # Description: Answer upstream commit count since last pull for projects in current directory. gucca() { while read -r project; do ( cd "$project" if [[ -d ".git" ]]; then # Capture upstream project commit count. git fetch --quiet local count=$(git log ..@{upstream} --pretty=format:"%h" | wc -l | tr -d ' ') if [[ $count -gt '0' ]]; then # Print project (cyan) and commit count (white). printf "\033[36m${project}\033[m: $count\n" fi fi ) done < <(ls -A1) } # Label: Git Nuke # Description: Permanently destroy and erase a file from history. UNRECOVERABLE! # Parameters: $1 (optional): The file to destroy. guke() { local file="$1" if [[ -z "$file" ]]; then printf "%s\n" "ERROR: File to nuke must be supplied." return 1 fi printf "\033[31m" # Switch to red font. read -p "Permanently delete '$file' from the local repository. Continue (y/n)?: " response printf "\033[m" # Switch to white font. if [[ "$response" == 'y' ]]; then git-filter-repo --force --invert-paths --path "$file" else printf "%s\n" "Nuke aborted." fi } # Label: Git Garbage Collect # Description: Garbage collect dangling commits for projects in current directory. garb() { while read -r project; do ( cd "$project" if [[ -d ".git" ]]; then printf "\033[36m${project}\033[m\n" # Output in cyan and branch in white color. git reflog expire --expire-unreachable=now --all git gc --prune=now fi ) done < <(ls -A1) } # Label: Git Unset (all) # Description: Unset key value for projects in current directory. # Parameters: $1 (required): The key name. gunseta() { if [[ "$1" ]]; then while read -r project; do ( cd "$project" if [[ -d ".git" ]]; then # Unset key for current project with error output suppressed. git config unset "$1" &> /dev/null # Print project (cyan). printf "\033[36m${project}\033[m: \"$1\" key removed.\n" fi ) done < <(ls -A1) else printf "%s\n" "ERROR: Key must be supplied." return 1 fi } # Label: Git Update # Description: Fetch commits, prune untracked references, review each commit (optional, with diff), and pull (optional). gup() { git fetch --quiet commits=($(git log --reverse --no-merges --pretty=format:"%h" ..@{upstream})) if [[ ${#commits[@]} == 0 ]]; then printf "%s\n" "All is quiet, nothing to update." return 0 fi printf "%s\n" "Commit Summary:" hr '-' git log --reverse --no-merges --pretty=format:"$(_git_log_line_format)" ..@{upstream} hr '-' printf "%s\n" "Commit Review (↓${#commits[@]}):" local counter=1 for commit in "${commits[@]}"; do hr '-' printf "[$counter/${#commits[@]}] " counter=$((counter + 1)) _git_show_details $commit printf "\n" read -p "View Diff (y = yes, n = no, q = quit)? " response case $response in 'y') git difftool $commit^!;; 'n');; 'q');; *) printf "%s\n" "ERROR: Invalid option.";; esac break done hr '-' read -p "Commit Pull (y/n)? " response if [[ "$response" == 'y' ]]; then git pull fi } # Label: Git Author Contributions # Description: Answers total lines added/removed by author for repo (with emphasis on deletion). # Parameters: $1 (optional): Author name. Default: Current user. guthorc() { local author="${1:-$(git config get user.name)}" if [[ -z "$author" ]]; then printf "%s\n" "ERROR: Author name required." return 1 fi git log --author="$author" \ --pretty=tformat: --numstat \ | awk -v author="$author" \ 'BEGIN { initial_pattern = "\033[1;34m%s\033[0m: Added: \033[0;31m%s\033[0m, Removed: \033[0;32m%s\033[0m, " positive_pattern = initial_pattern "Total: \033[0;32m%s\033[0m.\n"; neutral_pattern = initial_pattern "Total: %s.\n"; negative_pattern = initial_pattern "Total: \033[0;31m%s\033[0m.\n"; } { added += $1; removed += $2; total += $1 - $2; } END { if (total > 0) printf negative_pattern, author, added, removed, total else if (total < 0) printf positive_pattern, author, added, removed, total else printf neutral_pattern, author, added, removed, total }' } # Label: Git Authors (all) # Description: Answer author commit activity per project (ranked highest to lowest). guthorsa() { while read -r project; do ( cd "$project" if [[ -d ".git" ]]; then # Print project (cyan) and message (white). printf "\033[36m${project}\033[m:\n" guthors fi ) done < <(ls -A1) } # Label: Git Verify and Clean # Description: Verify and clean objects for current project. gvac() { printf "%s\n\n" "Verifying connectivity and validity of the objects in Git repository..." git fsck printf "%s\n" "Packing unpacked objects into a single pack and removing redundant packs..." git repack -Ad printf "\n%s\n\n" "Cleaning unnecessary files and optimizing local Git repository..." git maintenance run --task=gc printf "%s\n\n" "Pruning rerere records of older conflicting merges..." git rerere gc } # Label: Git Verify and Clean (all) # Description: Verify and clean objects for projects in current directory. gvaca() { while read -r project; do ( cd "$project" if [[ -d ".git" ]]; then printf "\n\033[36m${project}\033[m:\n" # Outputs in cyan color. git fsck && git repack -Ad && git maintenance run --task=gc && git rerere gc fi ) done < <(ls -A1) } # Label: Git Worktree Add # Description: Add and switch to new worktree. # Parameters: $1 (required): Worktree/branch name, $2 (required): Option. gwa() { local name="$1" local option="$2" local project_name="$(basename $(pwd))" local worktree_path="../$project_name-$name" if [[ -z "$name" ]]; then printf "%s\n" "ERROR: Worktree name must be supplied." return 1 fi if [[ "$option" != "d" && -n $(git branch --list "$name") ]]; then printf "%s\n" "ERROR: Invalid worktree, local branch exists." return 1 fi case $option in 'd') git worktree add --detach "$worktree_path" HEAD;; 'r') git worktree add -b "$name" "$worktree_path" origin/"$name";; 'l') git worktree add -b "$name" "$worktree_path" "$(_git_branch_default)";; *) printf "%s\n" "ERROR: Invalid worktree option: Use: (d)etach, (r)emote, or (l)ocal." return 1;; esac printf "%s\n" "Syncing project files..." git ls-files --others | rsync --links --files-from - "$(pwd)/" "$worktree_path/" cd "$worktree_path" } # Label: Git Worktree Delete # Description: Deletes current Git worktree. gwd() { local project_name="$(basename $(git rev-parse --show-toplevel) | cut -d'-' -f1)" local worktree_dir="$(pwd)" local branch="$(_git_branch_name)" if [[ "$(git status --short)" ]]; then printf "%s\n" "ERROR: Git worktree has uncommitted changes." return 1 else cd ../$project_name read -p "Git worktree: $worktree_dir. Delete (y/n)?: " response if [[ "$response" == 'y' ]]; then rm -rf $worktree_dir git worktree prune gbdl "$branch" git branch --delete --force "$branch" fi fi } # Label: Git Week # Description: Answer summarized list of current week activity for projects in current directory. gweek() { gince "last Monday 12am" } # Label: Git Sync # Description: Syncs up remote changes and deletes pruned/merged branches. gync() { if [[ $(_git_branch_name) != "$(_git_branch_default)" ]]; then printf "%s\n" "ERROR: Whoa, switch to default branch first." return 1 fi git pull && gbdm } #--------------------------------------# # Section: https://github.com:[GitHub] # #--------------------------------------# # Label: GitHub # Description: View GitHub details for current project. # Parameters: $1 (optional): The option selection, $2 (optional): The option input. gh() { if [[ -d ".git" ]]; then while true; do if [[ $# == 0 ]]; then printf "\n%s\n" "Usage: gh OPTION" printf "\n%s\n" "GitHub Options (default browser):" printf "%s\n" " a: Open actions." printf "%s\n" " o: Open repository." printf "%s\n" " i: Open repository issues." printf "%s\n" " c: Open repository commits. Options:" printf "%s\n" " HASH: Open commit." printf "%s\n" " f: Copy repository file URL." printf "%s\n" " b: Open repository branches. Options:" printf "%s\n" " c: Open current branch." printf "%s\n" " d: Open diff for current branch." printf "%s\n" " r: Open pull request for current branch." printf "%s\n" " t: Open repository tags." printf "%s\n" " r: Open repository pull requests." printf "%s\n" " NUMBER: Open pull request." printf "%s\n" " l: List pull requests." printf "%s\n" " w: Open repository wiki." printf "%s\n" " p: Open repository pulse." printf "%s\n" " g: Open repository graphs." printf "%s\n" " s: Open repository settings." printf "%s\n" " u: Print and copy repository URL. Options:" printf "%s\n" " HASH: Print and copy commit URL." printf "%s\n" " l: Print and copy last commit URL." printf "%s\n\n" " q: Quit/Exit." read -p "Enter selection: " response printf "\n" _process_gh_option $response "$2" else _process_gh_option "$1" "$2" "$3" fi break done else printf "%s\n" "ERROR: Not a Git repository!" return 1 fi } # Label: GitHub Pull Request (all) # Description: Open pull requests for all projects in current directory (non-default branches only). ghpra() { while read -r project; do ( cd "$project" if [[ -d ".git" ]]; then if [[ "$(_git_branch_name)" != "$(_git_branch_default)" ]]; then gh b r fi fi ) done < <(ls -A1) } #-----------------------------------------------------------# # Section: https://en.wikipedia.org/wiki/Less_(Unix):[less] # #-----------------------------------------------------------# # Label: Less Interactive # Description: Inspect file, interactively. # Parameters: $1 (required): The file path. lessi() { if [[ "$1" ]]; then less +F --LONG-PROMPT --LINE-NUMBERS --RAW-CONTROL-CHARS --QUIET --quit-if-one-screen -i "$1" else printf "%s\n" "ERROR: File path must be supplied." printf "%s\n" "TIP: Use CONTROL+c to switch to VI mode, SHIFT+f to switch back, and CONTROL+c+q to exit." fi } #--------------------------------------------------------------------# # Section: https://github.com/pivotal/LicenseFinder:[License Finder] # #--------------------------------------------------------------------# # Label: License Finder (add) # Description: Adds library to global list. # Parameters: $1 (required): Library, $2 (required): Why. licensea() { local library="$1" local why="$2" if [[ -z "$library" ]]; then printf "%s\n" "ERROR: Must supply library." return 1 fi if [[ -z "$why" ]]; then printf "%s\n" "ERROR: Explain why the license is safe." return 1 fi license_finder approval add "$library" --who "$(git config get user.name)" --why "$why" } # Label: License Finder (include) # Description: Include license in global list. # Parameters: $1 (required): License, $2 (required): Why. licensei() { local license="$1" local why="$2" if [[ -z "$license" ]]; then printf "%s\n" "ERROR: Must supply license." return 1 fi if [[ -z "$why" ]]; then printf "%s\n" "ERROR: Explain why the license is safe." return 1 fi license_finder whitelist add "$license" --who "$(git config get user.name)" --why "$why" } #-------------------------------------------------# # Section: https://people.freebsd.org/~abe:[lsof] # #-------------------------------------------------# # Label: Port # Description: List file activity on given port. # Parameters: $1 (required): The port number. port() { if [[ "$1" ]]; then lsof -i :$1 +c0 else printf "%s\n" "ERROR: Port number must be supplied." fi } #--------------------------------------------# # Section: https://marked2app.com:[Marked 2] # #--------------------------------------------# # Label: Marked Open # Description: Opens Markdown file in Marked. # Parameters: $1 (optional): Path to Markdown file. Default: README.md. mo() { local path=${1:-README.md} open -a Marked\ 2 "$path" } #-----------------------------------------------------------------# # Section: https://alchemists.io/projects/milestoner:[Milestoner] # #-----------------------------------------------------------------# # Label: Milestoner (ASCII Doc) # Description: Build milestone(s) in ASCII Doc format. # Parameters: $1 (optional): Maximum. Default: 1. msa() { local max=${1:-1} local root="tmp/milestones" local selection="" rm -rf tmp/milestones milestoner build --max "$max" --format ascii_doc read -r selection < <(fd .adoc tmp/milestones | _fzf_preview_and_select) if [[ -n "$selection" ]]; then ado "$selection" fi } # Label: Milestoner (feed) # Description: Build milestone(s) in feed (atom) format. # Parameters: $1 (optional): Maximum. Default: 10. msf() { local max=${1:-10} local path="tmp/milestones/index.xml" rm -rf tmp/milestones milestoner build --max "$max" --format feed if [[ -f "$path" ]]; then open -a "Vivaldi" "tmp/milestones/index.xml" fi } # Label: Milestoner (Markdown) # Description: Build milestone(s) in Markdown format. # Parameters: $1 (optional): Maximum. Default: 1. msm() { local max=${1:-1} local path="tmp/milestones/index.md" local selection="" rm -rf tmp/milestones milestoner build --max "$max" --format markdown read -r selection < <(fd .md tmp/milestones | _fzf_preview_and_select) if [[ -n "$selection" ]]; then mo "$selection" fi } # Label: Milestoner (stream) # Description: Build milestone(s) in stream format. # Parameters: $1 (optional): Maximum. Default: 1. mss() { local max=${1:-1} milestoner build --max "$max" --format stream } # Label: Milestoner (web) # Description: Build milestone(s) in web format. # Parameters: $1 (optional): Maximum. Default: 1. msw() { local max=${1:-1} local root="tmp/milestones" local path="" rm -rf "$root" milestoner build --max "$max" --format web path="$(eza --oneline --all --only-dirs "$root" | tail -n 1)" if [[ -d "$root" ]]; then reb "$root" 3030 "$path" fi } #---------------------------------------------------------# # Section: https://jedisct1.github.io/minisign:[Minisign] # #---------------------------------------------------------# # Label: Minisign Sign File # Description: Sign a file. # Parameters: $1 (required): File path, $2 (optional): Comment. sigf() { local path="$1" local comment="$2" minisign -S -s "$HOME/.minisign/alchemists.key" -m "$path" -t "$comment" } # Label: Minisign Generate # Description: Generate private and public key pair. # Parameters: $1 (required): Key pair name. sigg() { local name="$1" minisign -G -s "$HOME/.minisign/$name.key" -p "$HOME/.minisign/$name.pub" } # Label: Minisign Verify File # Description: Verify signed file. # Parameters: $1 (required): File path. sigv() { local path="$1" minisign -V -p "$HOME/.minisign/alchemists.pub" -m "$path" } #-------------------------------------------------------------------# # Section: https://en.wikipedia.org/wiki/Network_Computer:[Network] # #-------------------------------------------------------------------# # Label: DNS Flush # Description: Flush DNS cache. dnsf() { sudo killall -HUP mDNSResponder \ && sudo killall mDNSResponderHelper \ && sudo dscacheutil -flushcache \ && printf 'DNS cache cleared.\n' } #----------------------------------------# # Section: https://openssl.org:[OpenSSL] # #----------------------------------------# # Label: SSL Certificate Creation # Description: Create SSL certificate. # Parameters: $1 (required): The domain name. sslc() { local name="$1" if [[ -z "$name" ]]; then printf "%s\n" "ERROR: Domain name for SSL certificate must be supplied." return 1 fi cat > "$name.cnf" <<-EOF [req] distinguished_name = req_distinguished_name x509_extensions = v3_req prompt = no [req_distinguished_name] CN = *."$name" [v3_req] keyUsage = keyEncipherment, dataEncipherment extendedKeyUsage = serverAuth subjectAltName = @alt_names [alt_names] DNS.1 = *."$name" DNS.2 = "$name" EOF openssl req -new \ -newkey rsa:2048 \ -sha256 \ -days 3650 \ -nodes \ -x509 \ -keyout "$name.key" \ -out "$name.crt" \ -config "$name.cnf" rm -f "$name.cnf" } #----------------------------------------------------------# # Section: https://github.com/DarthSim/overmind:[Overmind] # #----------------------------------------------------------# # Label: Overmind Connect # Description: Connect to running process. # Parameters: $1 (optional): Process. Default: "web". omc() { local process="${1:-web}" overmind connect "$process" } # Label: Overmind Restart # Description: Restart running process. # Parameters: $1 (optional): Process. Default: "web". omr() { local process="${1:-web}" overmind restart "$process" } # Label: Overmind Start # Description: Start processes. # Parameters: $1 (optional): Environment. Use: "p" for "production". Default: "". oms() { local environment="$1" if [[ "$environment" == "p" ]]; then overmind start --port-step 10 --can-die assets,migrate else overmind start --port-step 10 --procfile Procfile.dev --can-die assets,migrate fi } #--------------------------------------------------# # Section: https://github.com/theory/pgenv:[pgenv] # #--------------------------------------------------# # Label: PostgreSQL Install # Description: Install (build) specific version. # Parameters: $1 (required): Version. pgi() { local version="$1" pgenv build "$version" && noti --title "PostgreSQL $version installed!" } #--------------------------------------------------# # Section: https://www.postgresql.org:[PostgreSQL] # #--------------------------------------------------# # Label: PostgreSQL Template # Description: Edit PostgreSQL template. # Parameters: $1 (required): The username. pgt() { local user="$1" if [[ -n "$user" ]]; then psql -U "$user" template1 else printf "%s\n" "ERROR: PostgreSQL username must be supplied." return 1 fi } # Label: PostgreSQL User Create # Description: Create PostgreSQL user. # Parameters: $1 (required): The username. pguc() { local user="$1" if [[ -n "$user" ]]; then createuser --interactive "$user" -P else printf "%s\n" "ERROR: PostgreSQL username must be supplied." return 1 fi } # Label: PostgreSQL User Drop # Description: Drop PostgreSQL user. # Parameters: $1 (required): The username. pgud() { local user="$1" if [[ -n "$user" ]]; then dropuser --interactive "$user" else printf "%s\n" "ERROR: PostgreSQL username must be supplied." return 1 fi } #----------------------------------------------# # Section: https://github.com/ruby/rake:[Rake] # #----------------------------------------------# # Label: Rake (all) # Description: Run default Rake tasks for projects in current directory. rakea() { while read -r project; do ( cd "$project" if [[ -f "Gemfile.lock" && -f "Rakefile" ]]; then # Prints project (cyan). printf "\033[36m${project}\033[m: " rake > /dev/null printf "\n" fi ) done < <(ls -A1) } #-------------------------------------# # Section: https://rspec.info:[RSpec] # #-------------------------------------# # Label: RSpec (all) # Description: Run RSpec for projects in current directory. rsall() { while read -r project; do ( cd "$project" if [[ -f "Gemfile.lock" && -d "spec" ]]; then local json=$(rspec spec --format json) local examples=$(printf "%s" "$json" | jq ".summary.example_count" ) local failures=$(printf "%s" "$json" | jq ".summary.failure_count" ) local pending=$(printf "%s" "$json" | jq ".summary.pending_count" ) local duration=$(printf "%s" "$json" | jq ".summary.duration" ) # Prints project (cyan). printf "\033[36m${project}\033[m: " # Prints total examples (white). printf "$examples examples, " # Prints total failures (red). _toggle_total_color "$failures" "failures" "\033[31m" printf ", " # Prints total pending (yellow). _toggle_total_color "$pending" "pending" "\033[33m" printf ", " # Prints total duration (white). printf "%s\n" "$duration seconds." fi ) done < <(ls -A1) } # Label: RSpec Bisect # Description: Debug RSpec failure using bisect to automatically determine the root cause. # Parameters: $1 (optional): The seed. Default: 2112, $2 (optional): Debug verbosity. Default: "normal". rsb() { local seed=${1:-2112} local verbosity="${2:-normal}" rspec --seed $seed --bisect="$verbosity" spec } # Label: RSpec Debug # Description: Debug intermittent RSpec failure(s) by running spec(s) until failure is detected. # Parameters: $1 (optional): The spec to debug. Default: "spec". rsd() { local subject=${1:-spec} while [ $? == 0 ]; do rspec "$subject" done } # Label: RSpec Profile # Description: Runs RSpec specs with profiling enabled. # Parameters: $1 (optional): The number of top specs to profile. Default: 5. rsp() { local number=${1:-5} rspec --profile $number spec } #---------------------------------------------# # Section: https://docs.rubocop.org:[Rubocop] # #---------------------------------------------# # Label: Rubocop (all) # Description: Run Rubocop for all projects in current directory. copa() { while read -r project; do ( cd "$project" if [[ -f ".config/rubocop/config.yml" ]]; then printf "\n\033[36m${project^^}\033[m\n\n" # Outputs in cyan color. bundle exec rubocop --parallel --format progress fi ) done < <(ls -A1) } #-------------------------------------------# # Section: https://www.ruby-lang.org:[Ruby] # #-------------------------------------------# # Label: Ruby Install # Description: Install a specific version with safe defaults. # Parameters: $1 (required): Version. rbi() { local version="$1" frum install "$version" \ --with-openssl-dir="$(brew --prefix openssl)" \ --enable-shared \ --disable-silent-rules if [ $? -eq 0 ]; then noti --title "Ruby $version installed!" else noti --title "Ruby $version install failed!" fi } # Label: Ruby Web Server # Description: Serve web content via WEBrick. # Parameters: $1 (optional): Root. Default: . # $2 (optional): Port. Default: 3030 # $3 (optional): Path. Default: "". reb() { local root="${1:-.}" local port=${2:-3030} local path="${3:-}" ruby -run -e httpd "$root" --port "$port" & while ! nc -z localhost "$port"; do sleep 0.1 done open "http://localhost:$port/$path" fg } # Label: Ruby Which # Description: Locate path to current Ruby program. # Parameters: $1 (required): Program name. rbw() { local program="$(command -v $1)" printf "%s\n" "${program//$FRUM_MULTISHELL_PATH/$(readlink $FRUM_MULTISHELL_PATH)}" } # Label: Ruby Upgrade (all) # Description: Upgrade Ruby projects in current directory to new Ruby version. # Parameters: $1 (required): The new version to upgrade to. Example: 3.2.0. rbua() { local new_version="$1" local paths=(".ruby-version" "home_files/.ruby-version.tt") if [[ "$new_version" ]]; then while read -r project; do ( cd "$project" printf "\033[36m${project}\033[m\n" # Outputs in cyan color. for path in "${paths[@]}"; do if [[ -e "$path" ]]; then old_version="$(head -n 1 "$path")" if [[ "$old_version" != "$new_version" ]]; then printf "%s\n" "$new_version" > "$path" printf "%s\n" " $path: $old_version --> $new_version" fi fi done ) done < <(ls -A1) else printf "%s\n" "ERROR: Version must be supplied." return 1 fi } # Label: Ruby Version (all) # Description: Show current Ruby version for all projects in current directory. rbva() { while read -r project; do ( cd "$project" if [[ -e ".ruby-version" ]]; then local version=$(head -n 1 .ruby-version) # Outputs project as cyan and version as white color. printf "\033[36m${project}\033[m: $version\n" fi ) done < <(ls -A1) } #-------------------------------------------# # Section: https://rubygems.org:[Ruby Gems] # #-------------------------------------------# # Label: Gem Dependencies # Description: Answers dependencies for a gem. # Parameters: $1 (required): The gem name. gemd() { local name="$1" if [[ -z "$name" ]]; then printf "%s\n" "ERROR: Gem name must be supplied!" return 1 fi gem dependency "$1" --reverse-dependencies } # Label: Gem Dependency Search # Description: Finds a gem defined within a Gemfile or a gemspec. # Parameters: $1 (required): The gem name. gemdep() { local gem_name="$1" if [[ -z "$gem_name" ]]; then printf "%s\n" "ERROR: Gem name must be supplied!" return 1 fi rg --sort path "(add.*dependency \"$gem_name\"|add.*dependency '$gem_name'|gem \"$gem_name\"|gem '$gem_name')" . } #--------------------------------------------------# # Section: https://rubyonrails.org:[Ruby on Rails] # #--------------------------------------------------# # Label: Ruby on Rails New # Description: Create new Rails application from selected option. # Parameters: $1 (required): Application name, $2 (optional): Option. railsn() { if [[ "$1" ]]; then while true; do if [[ $2 ]]; then _process_rails_new_option "$1" "$2" else printf "%s\n" "\nUsage: railsn NAME TEMPLATE" printf "\n%s\n\n" "Select Ruby on Rails generation option:" printf "%s\n" " default: Rails Default" printf "%s\n" " api: Rails API" printf "%s\n" " slim: Rails Slim" printf "%s\n" " dummy: Rails Dummy" printf "\n" read -p "Please pick one (or type 'q' to quit): " response printf "\n" _process_rails_new_option "$1" $response fi break done else printf "%s\n" "ERROR: Rails application name must be supplied." return 1 fi } #-------------------------------------------------------------# # Section: https://github.com/colszowka/simplecov:[SimpleCov] # #-------------------------------------------------------------# # Label: RSpec (all) # Description: Run RSpec for projects in current directory. cova() { while read -r project; do ( cd "$project" if [[ -d "coverage" ]]; then open "coverage/index.html" fi ) done < <(ls -A1) } ================================================ FILE: lib/templates/.config/bash/prompt.sh.tt ================================================ #! /usr/bin/env bash # The following was inspired by the original Powerline port by Riobard Zhan (https://github.com/riobard/bash-powerline). _powerline() { # Unicode symbols readonly OS_DARWIN_SYMBOL='' readonly OS_LINUX_SYMBOL='$' readonly OS_OTHER_SYMBOL='%' readonly GIT_BRANCH_SYMBOL='⑂' readonly GIT_BRANCH_NORMAL_SYMBOL='✓' readonly GIT_BRANCH_CHANGED_SYMBOL='+' readonly GIT_STASH_SYMBOL="@" readonly GIT_PUSH_SYMBOL='↑' readonly GIT_PULL_SYMBOL='↓' # Determine OS case "$(uname)" in Darwin) readonly OS_SYMBOL=$OS_DARWIN_SYMBOL ;; Linux) readonly OS_SYMBOL=$OS_LINUX_SYMBOL ;; *) readonly OS_SYMBOL=$OS_OTHER_SYMBOL esac _update_history() { history -a # Append. history -n # Reload. } _update_iterm_label() { printf "\033]0;${PWD##*/}\007" } _git_branch_info() { # Get current branch name or short SHA1 hash for detached head. local branch="$(git symbolic-ref --short HEAD 2>/dev/null || git describe --tags --always 2>/dev/null)" [ -n "$branch" ] || return # Git branch not found. local marks=" $GIT_BRANCH_NORMAL_SYMBOL" # Check if branch is modified. [ -n "$(git status --porcelain)" ] && marks=" $GIT_BRANCH_CHANGED_SYMBOL" # Compute how many commits local branch is ahead/behind of remote branch. local stat="$(git status --porcelain --branch | grep '^##' | grep -o '\[.\+\]$')" local aheadN="$(echo $stat | grep -o 'ahead \d\+' | grep -o '\d\+')" local behindN="$(echo $stat | grep -o 'behind \d\+' | grep -o '\d\+')" [ -n "$aheadN" ] && marks+=" $GIT_PUSH_SYMBOL$aheadN" [ -n "$behindN" ] && marks+=" $GIT_PULL_SYMBOL$behindN" # Print the git branch segment without a trailing newline printf " $GIT_BRANCH_SYMBOL $branch$marks " } _git_stash_info() { local count=$(git stash list | wc -l | xargs -n 1) count="$count" if [[ $count -gt 0 ]]; then printf "$GIT_STASH_SYMBOL$count " fi } ps1() { # Check the exit code of the previous command and toggle background color accordingly. if [ $? -eq 0 ]; then local BG_EXIT="$GREEN_BACKGROUND" else local BG_EXIT="$RED_BACKGROUND" fi PS1="\[$BLACK\]\[$WHITE_BACKGROUND\] \u@\h \[$NORMAL\]" # User@host. PS1+="\[$BLACK\]\[$CYAN_BACKGROUND\] ${PWD##*/} \[$NORMAL\]" # Directory. if [[ -d .git ]]; then PS1+="\[$SLATE_BACKGROUND\] $(git config get user.email | egrep --only-matching '[^@]+$') \[$NORMAL\]" # Git Email Domain. PS1+="\[$BLUE_BACKGROUND\]$(_git_branch_info)\[$NORMAL\]" # Git Branch Info. PS1+="\[$YELLOW\]\[$BLUE_BACKGROUND\]$(_git_stash_info)\[$NORMAL\]" # Git Stash Info. fi _update_history _update_iterm_label PS1+="\[$BG_EXIT\] $OS_SYMBOL \[$NORMAL\] " } PROMPT_COMMAND=ps1 } _powerline unset _powerline ================================================ FILE: lib/templates/.config/duti/configuration.duti.tt ================================================ # Use `mdls -name kMDItemCFBundleIdentifier -r /Applications/.app` to identify applications. com.colliderli.iina .flac all com.colliderli.iina .mkv all com.colliderli.iina .mov all com.colliderli.iina .mp4 all com.colliderli.iina .webm all com.flyingmeat.Acorn8 .arw all com.flyingmeat.Acorn8 .avif all com.flyingmeat.Acorn8 .bmp all com.flyingmeat.Acorn8 .gif all com.flyingmeat.Acorn8 .heic all com.flyingmeat.Acorn8 .jpeg all com.flyingmeat.Acorn8 .jpg all com.flyingmeat.Acorn8 .png all com.flyingmeat.Acorn8 .svg all com.flyingmeat.Acorn8 .tiff all com.flyingmeat.Acorn8 .webp all com.rogueamoeba.Fission .m4a all com.sublimetext.4 .erb all com.sublimetext.4 .rb all ================================================ FILE: lib/templates/.config/git/attributes.tt ================================================ *.gemspec diff=ruby *.gif diff=exif *.ico diff=exif *.jpeg diff=exif *.jpg diff=exif *.mp4 diff=exif *.ogg diff=exif *.png diff=exif *.rake diff=ruby *.rb diff=ruby *.webm diff=exif config.ru diff=ruby config/credentials.yml.enc diff=rails_credentials config/credentials/*.yml.enc diff=rails_credentials Gemfile diff=ruby Gemfile.lock diff=ruby Guardfile diff=ruby Procfile diff=ruby Rakefile diff=ruby ================================================ FILE: lib/templates/.config/git/commit_message.txt.tt ================================================ Milestone: ? # Questions: # Why is this necessary? # Any side effects to be aware of? # Any links to add? # Trailers: # Co-authored-by: River Tam # Format: asciidoc # Issue: 123 # Milestone: patch # Reviewer: github # Signed-off-by: Malcolm Reynolds # Tracker: linear ================================================ FILE: lib/templates/.config/git/configuration.tt ================================================ [advice] detachedHead = false [branch] autoSetupRebase = always [commit] gpgSign = true template = ~/.config/git/commit_message.txt verbose = true [core] abbrev = 12 editor = "$EDITOR --wait" fsmonitor = false hooksPath = ~/.config/git/hooks pager = delta quotePath = false untrackedCache = true whitespace = fix,-indent-with-non-tab,trailing-space,cr-at-eol [color] pager = true ui = true [color "branch"] current = yellow reverse local = yellow remote = green [color "diff"] commit = 227 bold frag = magenta bold meta = 227 new = green bold old = red bold whitespace = red reverse [color "diff-highlight"] newHighlight = green bold 22 newNormal = green bold oldHighlight = red bold 52 oldNormal = red bold [color "status"] added = yellow changed = green untracked = cyan [credential] helper = cache --timeout=3600 [delta] commit-decoration-style = bold yellow box ul file-style = bold yellow ul hunk-header-decoration-style = yellow box line-numbers = true minus-color = "#340001" plus-color = "#012800" side-by-side = true whitespace-error-style = 22 reverse [diff] algorithm = histogram colorMoved = default dstPrefix = after indentHeuristic = true mnemonicPrefix = true renames = copies srcPrefix = before tool = difftastic [diff "exif"] textconv = exiftool [difftool] prompt = false [difftool "difftastic"] cmd = difft "$LOCAL" "$REMOTE" [feature] experimental = true [fetch] prune = true pruneTags = true writeCommitGraph = true [gpg "ssh"] allowedSignersFile = ~/.ssh/allowed_signers [grep] column = true fullname = true lineNumber = true [init] defaultBranch = main templateDir = ~/.config/git/template [interactive] diffFilter = delta --color-only singleKey = true [maintenance] auto = false strategy = incremental [merge] conflictStyle = zdiff3 ff = only tool = difftastic [mergetool] prompt = false [mergetool "difftastic"] cmd = difft "$LOCAL" "$REMOTE" trustExitCode = true [notes] rewriteRef = refs/notes/commits [pack] useBitmapBoundaryTraversal = true [pager] difftool = true [pull] rebase = merges [push] autoSetupRemote = true default = simple followTags = true useForceIfIncludes = true [rebase] abbreviateCommands = true autoSquash = true autoStash = true updateRefs = true [remote "origin"] fetch = refs/pull/*/head:refs/remotes/pull_requests/* fetch = refs/stashes/*:refs/remote/origin/stashes/* [rerere] autoUpdate = true enabled = true [revert] reference = true [stash] showIncludeUntracked = true showPatch = true showStat = false [status] showUntrackedFiles = all [tag] gpgSign = true sort = version:refname [transfer] fsckObjects = true [url "https://github.com/bkuhlmann/"] insteadOf = bk: [url "https://github.com/dry-rb/dry-"] insteadOf = dry: [url "https://github.com/"] insteadOf = gh: [url "https://github.com/hanami/"] insteadOf = hanami: [url "https://git.heroku.com"] insteadOf = heroku: [url "https://github.com/rom-rb/rom-"] insteadOf = rom: [url "https://github.com/ruby/"] insteadOf = rb: [user] email = name = signingKey = useConfigOnly = true [includeIf "gitdir:~/Engineering/Companies/Example/"] path = ~/.config/git/profiles/example ================================================ FILE: lib/templates/.config/git/hooks/applypatch-msg.tt ================================================ #! /usr/bin/env bash # Defines Git apply patch functionality. set -o nounset set -o errexit set -o pipefail IFS=$'\n\t' source "$HOME/.config/git/hooks/extensions/support.sh" ================================================ FILE: lib/templates/.config/git/hooks/commit-msg.tt ================================================ #! /usr/bin/env bash # Defines Git commit message functionality. set -o nounset set -o errexit set -o pipefail IFS=$'\n\t' source "$HOME/.config/git/hooks/extensions/support.sh" source "$HOME/.config/git/hooks/extensions/git.sh" git_trailer_cleaner "$1" git_lint_check ================================================ FILE: lib/templates/.config/git/hooks/extensions/brakeman.sh.tt ================================================ #! /usr/bin/env bash # Label: Brakeman Check # Description: Scan Rails project for security vulnerabilities. brakeman_check() { if _check_gem_dependencies "brakeman"; then printf "%s\n" "[brakeman]" bundle exec brakeman --summary --quiet fi } export -f brakeman_check ================================================ FILE: lib/templates/.config/git/hooks/extensions/bundler.sh.tt ================================================ #! /usr/bin/env bash # Label: Bundler Gemfile Path # Description: Detect gem path statements. bundler_gemfile_path() { _scan_code "[bundler]" "Gemfile path statement detected" 'Gemfile' '(path:|:path\s=>)' } export -f bundler_gemfile_path # Label: Bundler Audit Check # Description: Scans gem dependencies for security vulnerabilities. bundler_audit_check() { if _check_gem_dependencies "bundler-audit"; then printf "[bundler-audit]: " bundle exec bundler-audit fi } export -f bundler_audit_check ================================================ FILE: lib/templates/.config/git/hooks/extensions/comments.sh.tt ================================================ #! /usr/bin/env bash # Label: Comment Total # Description: Print project comment total. # Parameters: $1 (required): The comment prefix to search for. _comment_total() { local prefix="$1" local label="[comments]" local lines=("omit:0") # Ensures array is populated, with omitted total, in case Silver Searcher finds nothing. local total=0 if ! command -v rg > /dev/null; then printf "%s" "$label: Ripgrep not found. To install, run: brew install ripgrep." exit 1 fi lines+=($(rg --count --case-sensitive --iglob '!vendor' --regexp "^\s*?(#|--|//) $prefix" . || :)) for line in ${lines[*]}; do total=$((total + ${line#*:})) done if [[ $total -gt 0 ]]; then _print_warning "$label: $total $prefix" fi } export -f _comment_total # Label: Comment Totals # Description: Print project comment totals. comment_totals() { local prefixes=( "TODO" "FIX" "DUPLICATE" "shellcheck disable" ":reek:" "rubocop:disable" "rubocop:todo" ":nocov:" ) for prefix in ${prefixes[*]}; do _comment_total "$prefix" done } export -f comment_totals ================================================ FILE: lib/templates/.config/git/hooks/extensions/ctags.sh.tt ================================================ #! /usr/bin/env bash # Label: CTags Rebuild # Description: Rebuild project .tags file. ctags_rebuild() { local label="[ctags]" _build_ctags printf "%s\n" "$label: CTags rebuilt." } export -f ctags_rebuild ================================================ FILE: lib/templates/.config/git/hooks/extensions/dotenv.sh.tt ================================================ #! /usr/bin/env bash # Label: Dotenv Linter # Description: Scan environment files for consistent style and security issues. dotenv_check() { if command -v dotenv-linter > /dev/null; then printf "%s\n" "[dotenv-linter]:" dotenv-linter check . fi } export -f dotenv_check ================================================ FILE: lib/templates/.config/git/hooks/extensions/git.sh.tt ================================================ #! /usr/bin/env bash # Label: Git Lint Check # Description: Enforce consistent Git commits. git_lint_check() { if _check_gem_dependencies "git-lint"; then git-lint --hook "${BASH_ARGV[0]}" fi } export -f git_lint_check # Label: Git Trailer Cleaner # Description: Remove unused/empty Git commit body trailers. # Parameters: $1 (required): Commit message file path. git_trailer_cleaner() { local commit_message_path="$1" git interpret-trailers --in-place --trim-empty "$commit_message_path" } export -f git_trailer_cleaner # Label: Git Add Trailers # Description: Dynamically add trailers based on branch description. # Parameters: $1 (required): Commit message file path, $2 (required): The kind. git_add_trailers() { local commit_message_path="$1" local kind="$2" local branch="" local trailers="" branch="$(git branch --show-current | tr -d '\n')" trailers="$(git config get "branch.$branch.description" | git interpret-trailers --parse || :)" case "$kind" in message) printf "\n\n%s" "$trailers" >> "$commit_message_path";; template) sd --max-replacements 1 "\n#" "\n$trailers\n\n#" "$commit_message_path";; esac } export -f git_add_trailers ================================================ FILE: lib/templates/.config/git/hooks/extensions/hadolint.sh.tt ================================================ #! /usr/bin/env bash # Label: Haskell Dockerfile Linter # Description: Scan Dockerfile for vulnerabilities. hadolint_check() { if command -v hadolint > /dev/null && [[ -e "Dockerfile" ]]; then printf "%s\n" "[hadolint]:" hadolint Dockerfile fi } export -f hadolint_check ================================================ FILE: lib/templates/.config/git/hooks/extensions/java_script.sh.tt ================================================ #! /usr/bin/env bash # Label: Git Label # Description: Print Git label. _java_script_label() { printf "[java_script]" } export -f _java_script_label # Label: File Pattern # Description: Print file regular expression. _java_script_file_pattern() { printf '^((?!min).)+.(js|erb|slim)$' } export -f _java_script_file_pattern # Label: JavaScript Debugger # Description: Detect JavaScript debug statements. java_script_debugger() { local search_pattern='^(?:(?!(.*//.+|.*/\*.+)).*debugger;)' _scan_code "$(_java_script_label)" "Debug statements detected" $(_java_script_file_pattern) $search_pattern } export -f java_script_debugger # Label: JavaScript Console # Description: Detect JavaScript console statements. java_script_console() { local search_pattern='^(?:(?!(.*//.+|.*/\*.+)).*console.(count|dir|error|group.*|info|log|time.*|table|trace)\(.+\);)' _scan_code "$(_java_script_label)" "Console statements detected" $(_java_script_file_pattern) $search_pattern } export -f java_script_console # Label: JavaScript Alert # Description: Detect JavaScript alert statements. java_script_alert() { local search_pattern='^(?:(?!(.*//.+|.*/\*.+)).*alert\(.+\);)' _scan_code "$(_java_script_label)" "Alert statements detected" $(_java_script_file_pattern) $search_pattern } export -f java_script_alert ================================================ FILE: lib/templates/.config/git/hooks/extensions/license_finder.sh.tt ================================================ #! /usr/bin/env bash # Label: License Finder Check # Description: Scan project for valid licenses. license_finder_check() { if _check_gem_dependencies "license_finder"; then printf "%s\n" "[license_finder]:" bundle exec license_finder fi } export -f license_finder_check ================================================ FILE: lib/templates/.config/git/hooks/extensions/osv.sh.tt ================================================ #! /usr/bin/env bash # Label: Open Source Vulnerability (OSV) Check # Description: Scan Ruby dependencies for vulnerabilities. osv_check() { if command -v osv-scanner > /dev/null && [[ -e "Gemfile.lock" ]]; then printf "%s\n" "[osv]:" osv-scanner --lockfile Gemfile.lock fi } export -f osv_check ================================================ FILE: lib/templates/.config/git/hooks/extensions/reek.sh.tt ================================================ #! /usr/bin/env bash # Label: Reek Branch Check # Description: Scan Ruby code -- feature branch only -- for poor style choices. reek_branch_check() { if _check_gem_dependencies "reek"; then printf "%s\n" "[reek]:" bundle exec reek "$(_git_feature_files)" fi } export -f reek_branch_check # Label: Reek Stage Check # Description: Scan Ruby code -- staged files only -- for poor style choices. reek_stage_check() { if _check_gem_dependencies "reek"; then printf "%s\n" "[reek]:" bundle exec reek "$(_git_staged_files)" fi } export -f reek_stage_check ================================================ FILE: lib/templates/.config/git/hooks/extensions/rspec.sh.tt ================================================ #! /usr/bin/env bash # Label: RSpec Dotfile # Description: Detect RSpec dotfile. rspec_dotfile() { if command -v rg > /dev/null; then results=("$(rg --files --glob .rspec . || :)") if [[ ${#results[@]} -gt 0 && ${results[@]} != '' ]]; then _print_error "[rspec]: Dotfile detected." exit 1 fi else _print_error "[rspec]: Ripgrep not found. To install, run: brew install ripgrep." exit 1 fi } export -f rspec_dotfile # Label: RSpec Order # Description: Detect RSpec ordered specs. rspec_order() { _scan_code "[rspec]" "Order detected" '(_helper.rb$|spec.rb$)' '(order.*\=.*defined|,\sorder:.+defined)' } export -f rspec_order ================================================ FILE: lib/templates/.config/git/hooks/extensions/rubocop.sh.tt ================================================ #! /usr/bin/env bash # Label: RuboCop Branch Check # Description: Scan Ruby code -- feature branch only -- for poor style choices. rubocop_branch_check() { if _check_gem_dependencies "caliber" || _check_gem_dependencies "rubocop"; then printf "%s\n" "[rubocop]:" _git_feature_files | xargs | _run_rubocop fi } export -f rubocop_branch_check # Label: RuboCop Stage Check # Description: Scan Ruby code -- staged files only -- for poor style choices. rubocop_stage_check() { if _check_gem_dependencies "caliber" || _check_gem_dependencies "rubocop"; then printf "%s\n" "[rubocop]:" _git_staged_files | xargs | _run_rubocop fi } export -f rubocop_stage_check # Label: Run RuboCop # Description: Run RuboCop in a mode compatible for use in Git Hooks. _run_rubocop() { bundle exec rubocop --parallel \ --force-exclusion \ --display-cop-names \ --display-style-guide \ --only-recognized-file-types \ --format simple } export -f _run_rubocop ================================================ FILE: lib/templates/.config/git/hooks/extensions/support.sh.tt ================================================ #! /usr/bin/env bash # Label: Check Gem Dependencies # Description: Check Gemfile/gemspec dependencies for specified gem. # Parameters: $1 (required): The gem name. _check_gem_dependencies() { local gem="$1" rg "(add.*dependency \"$gem\"|add.*dependency '$gem'|gem \"$gem\"|gem '$gem')" --max-depth 1 . > /dev/null } export -f _check_gem_dependencies # Label: Builds CTags # Description: Build/rebuild CTags. _build_ctags() { rm -f ".tags" rm -f "tags" ctags } export -f _build_ctags # Label: Git Feature Files # Description: Answer feature branch files only. _git_feature_files() { git diff \ --diff-filter=d \ "$(git branch --show-current | tr -d '\n')".."$(git config get init.defaultBranch)" \ --name-only } export -f _git_feature_files # Label: Git Staged Files # Description: Answer staged files only. _git_staged_files() { git diff --diff-filter=d --name-only --cached } # Label: Print Warning. # Description: Print yellow warning message. # Parameters: $1 (required): Message. _print_warning() { local message="$1" printf "\033[33m" printf "%s\n" "$message" printf "\033[m" } export -f _print_warning # Label: Print Error. # Description: Print red error message. # Parameters: $1 (required): Message. _print_error() { local message="$1" printf "\033[31m" printf "%s\n" "$message" printf "\033[m" } export -f _print_error # Label: Scan Code # Description: Scan for invalid code. # Parameters: $1 (required): Label, $2 (required): Message, $3 (required): File regex, $4 (required): Search regex. _scan_code() { local label="$1" local message="$2" local file_pattern=$3 local search_pattern=$4 local ignore_pattern="vendor" if command -v ag > /dev/null; then results=("$(ag --file-search-regex $file_pattern $search_pattern --ignore $ignore_pattern . || :)") if [[ ${#results[@]} -gt 0 && ${results[@]} != '' ]]; then _print_error "$label: $message:" for line in ${results[@]}; do _print_error " $line" done exit 1 fi else _print_error "$label: Silver Surfer not found. To install, run: brew install the_silver_searcher." exit 1 fi } export -f _scan_code ================================================ FILE: lib/templates/.config/git/hooks/post-applypatch.tt ================================================ #! /usr/bin/env bash # Defines Git post-apply patch functionality. set -o nounset set -o errexit set -o pipefail IFS=$'\n\t' source "$HOME/.config/git/hooks/extensions/support.sh" ================================================ FILE: lib/templates/.config/git/hooks/post-checkout.tt ================================================ #! /usr/bin/env bash # Defines Git post-checkout functionality. set -o nounset set -o errexit set -o pipefail IFS=$'\n\t' source "$HOME/.config/git/hooks/extensions/support.sh" source "$HOME/.config/git/hooks/extensions/ctags.sh" ctags_rebuild ================================================ FILE: lib/templates/.config/git/hooks/post-commit.tt ================================================ #! /usr/bin/env bash # Defines Git post-commit functionality. set -o nounset set -o errexit set -o pipefail IFS=$'\n\t' source "$HOME/.config/git/hooks/extensions/support.sh" source "$HOME/.config/git/hooks/extensions/ctags.sh" ctags_rebuild ================================================ FILE: lib/templates/.config/git/hooks/post-merge.tt ================================================ #! /usr/bin/env bash # Defines Git post-merge functionality. set -o nounset set -o errexit set -o pipefail IFS=$'\n\t' source "$HOME/.config/git/hooks/extensions/support.sh" ================================================ FILE: lib/templates/.config/git/hooks/post-rewrite.tt ================================================ #! /usr/bin/env bash # Defines Git post-rewrite functionality. set -o nounset set -o errexit set -o pipefail IFS=$'\n\t' source "$HOME/.config/git/hooks/extensions/support.sh" source "$HOME/.config/git/hooks/extensions/ctags.sh" ctags_rebuild ================================================ FILE: lib/templates/.config/git/hooks/pre-applypatch.tt ================================================ #! /usr/bin/env bash # Defines Git pre-apply patch functionality. set -o nounset set -o errexit set -o pipefail IFS=$'\n\t' source "$HOME/.config/git/hooks/extensions/support.sh" ================================================ FILE: lib/templates/.config/git/hooks/pre-commit.tt ================================================ #! /usr/bin/env bash # Defines Git pre-commit functionality. set -o nounset set -o errexit set -o pipefail IFS=$'\n\t' source "$HOME/.config/git/hooks/extensions/support.sh" source "$HOME/.config/git/hooks/extensions/java_script.sh" source "$HOME/.config/git/hooks/extensions/reek.sh" source "$HOME/.config/git/hooks/extensions/rspec.sh" source "$HOME/.config/git/hooks/extensions/rubocop.sh" java_script_alert java_script_console java_script_debugger reek_stage_check rspec_dotfile rspec_order rubocop_stage_check ================================================ FILE: lib/templates/.config/git/hooks/pre-merge-commit.tt ================================================ #! /usr/bin/env bash # Defines Git pre-merge commit functionality. set -o nounset set -o errexit set -o pipefail IFS=$'\n\t' source "$HOME/.config/git/hooks/extensions/support.sh" ================================================ FILE: lib/templates/.config/git/hooks/pre-push.tt ================================================ #! /usr/bin/env bash # Defines Git pre-push functionality. set -o nounset set -o errexit set -o pipefail IFS=$'\n\t' source "$HOME/.config/git/hooks/extensions/support.sh" source "$HOME/.config/git/hooks/extensions/brakeman.sh" source "$HOME/.config/git/hooks/extensions/bundler.sh" source "$HOME/.config/git/hooks/extensions/comments.sh" source "$HOME/.config/git/hooks/extensions/dotenv.sh" source "$HOME/.config/git/hooks/extensions/hadolint.sh" source "$HOME/.config/git/hooks/extensions/license_finder.sh" source "$HOME/.config/git/hooks/extensions/osv.sh" source "$HOME/.config/git/hooks/extensions/reek.sh" source "$HOME/.config/git/hooks/extensions/rubocop.sh" push_command=$(ps -ocommand= -p $PPID) zeros=0000000000000000000000000000000000000000 # Ignore remote branch or tag deletes. if [[ "$push_command" == *"--delete"* || "$push_command" == *"--tags"* ]]; then exit 0 fi # Ignore unbuildable commits. if [[ $(git log --format=%B -1) == *"[ci skip]"* ]]; then exit 0 fi while read local_ref local_sha remote_ref remote_sha; do if [[ "$local_sha" != "$zeros" && "$remote_sha" != "$zeros" ]]; then parallel ::: comment_totals \ reek_branch_check \ rubocop_branch_check \ dotenv_check \ bundler_gemfile_path \ bundler_audit_check \ brakeman_check \ license_finder_check \ hadolint_check \ osv_check fi done exit 0 ================================================ FILE: lib/templates/.config/git/hooks/pre-rebase.tt ================================================ #! /usr/bin/env bash # Defines Git pre-rebase functionality. set -o nounset set -o errexit set -o pipefail IFS=$'\n\t' source "$HOME/.config/git/hooks/extensions/support.sh" ================================================ FILE: lib/templates/.config/git/hooks/prepare-commit-msg.tt ================================================ #! /usr/bin/env bash # Defines Git prepare commit message functionality. set -o nounset set -o errexit set -o pipefail IFS=$'\n\t' source "$HOME/.config/git/hooks/extensions/support.sh" source "$HOME/.config/git/hooks/extensions/git.sh" git_add_trailers "$1" "$2" ================================================ FILE: lib/templates/.config/git/ignore.tt ================================================ # Archives *.7z *.bzip *.dmg *.gz *.iso *.jar *.rar *.tar *.tar.gz *.zip # Bundler .bundle # CTags .tags .tags_sorted_by_file /tags # Databases *.dump # Docker compose.dev.yml # Environments *.env* !*.env*.tt # Logs *.log *.log.* # macOS .DS_Store # SimpleCov coverage # Processes Procfile.dev # Solargraph .solargraph.yml # Temp Directories tmp ================================================ FILE: lib/templates/.config/git/template/mkdir.command ================================================ # Special command for creating empty directories. # Delete if templates are added. ================================================ FILE: lib/templates/.config/irb/irbrc.tt ================================================ #! /usr/bin/env ruby # frozen_string_literal: true require "irb/completion" Reline::Face.config :completion_dialog do |config| config.define :default, foreground: :white, background: :black config.define :enhanced, foreground: :black, background: :green config.define :scrollbar, foreground: :bright_white, background: :black end begin require "amazing_print" AmazingPrint.irb! rescue LoadError => error puts "ERROR: #{error.message.capitalize}." end begin require "irb/kit" IRB::Kit.register_commands :all IRB::Kit.register_helpers :all IRB.conf[:PROMPT] ||= {} IRB.conf[:PROMPT][:ALCHEMISTS] = { PROMPT_I: "[#{IRB::Kit.prompt}]> ", PROMPT_N: "[#{IRB::Kit.prompt}]| ", PROMPT_C: "[#{IRB::Kit.prompt}]| ", PROMPT_S: "[#{IRB::Kit.prompt}]%l ", RETURN: "=> %s\n" } IRB.conf[:PROMPT_MODE] = :ALCHEMISTS rescue LoadError => error puts "ERROR: #{error.message.capitalize}." end IRB.conf[:EVAL_HISTORY] = 1_000 IRB.conf[:HISTORY_FILE] = "#{Dir.home}/.cache/irb/history.log" IRB.conf[:COMPLETOR] = :type IRB.conf[:SHOW_BANNER] = false IRB.conf[:COMMAND_ALIASES] .merge! b: :backtrace, c: :continue, e: :edit, h: :show_cmds, i: :info, l: :ls, n: :next, m: :measure, s: :step, w: :whereami ================================================ FILE: lib/templates/.config/pgenv/initialize.tt ================================================ #! /usr/bin/env bash set -o nounset set -o errexit set -o pipefail IFS=$'\n\t' psql --username postgres \ --command "CREATE ROLE $USER WITH SUPERUSER CREATEDB CREATEROLE LOGIN PASSWORD '';" psql --username postgres --command "CREATE DATABASE $USER;" ( cd "$HOME/.cache/pgenv/pgsql/data" if [[ ! -e "server.key" && ! -e "server.crt" ]]; then openssl req -new \ -x509 \ -days 365 \ -nodes \ -text \ -out server.crt \ -keyout server.key \ -subj "/CN=postgres" chmod 0600 server.key fi ) psql -c "ALTER SYSTEM SET timezone = 'UTC';" psql -c "ALTER SYSTEM SET ssl = 'on';" psql -c "ALTER SYSTEM SET ssl_cert_file = 'server.crt';" psql -c "ALTER SYSTEM SET ssl_key_file = 'server.key';" psql -c "ALTER SYSTEM SET ssl_min_protocol_version = 'TLSv1.3';" pgenv restart ================================================ FILE: lib/templates/.config/rubocop/config.yml.tt ================================================ inherit_gem: caliber: config/all.yml ================================================ FILE: lib/templates/.ctags.tt ================================================ --exclude=*.git* --exclude=*.min.js --exclude=*coverage* --exclude=*node_modules* --exclude=*packs* --exclude=.DS_Store --exclude=log --exclude=tmp --exclude=vendor --fields=+l --languages=-sql --recurse=yes --sort=yes --tag-relative=yes ================================================ FILE: lib/templates/.erdconfig.tt ================================================ attributes: - primary_keys - foreign_keys - content - inheritance - timestamps disconnected: true filename: tmp/erd inheritance: true notation: bachman ================================================ FILE: lib/templates/.hushlogin.tt ================================================ ================================================ FILE: lib/templates/.inputrc.tt ================================================ # READLINE SETTINGS (http://cnswww.cns.cwru.edu/php/chet/readline/readline.html#SEC13) # Sets bell style to visible instead of audible. set bell-style visible # Use VI edit commands instead of Emacs. set editing-mode vi # Use VI key mappings instead of Emacs. set keymap vi # Show all auto-complete results at once. set page-completions off # Use case insensitive tab auto-completion. set completion-ignore-case on # Show all possible auto-completion matches (even when some are ambiguous). set show-all-if-ambiguous on # Show all auto-completion results (by asking) when results are more than current limit. set completion-query-items 100 # Use intelligent auto-completion for text after the cursor relative to current command. set skip-completed-text on # Cycles backward through recent history for command completions. Use: ↑ "\e[A": history-search-backward # Cycles forward through recent history for command completions. Use: ↓ "\e[B": history-search-forward # Ensures backward line movement works. Use: ← "\e[D": backward-char # Ensures forward line movement works. Use: → "\e[C": forward-char # Changes tab completion default menu list to cycle through each matching command. Use: "\t": menu-complete ================================================ FILE: lib/templates/.npmrc.tt ================================================ init-author-name="Brooke Kuhlmann" init-license="Hippocratic-2.1" progress=false save-prefix="^" ================================================ FILE: lib/templates/.psqlrc.tt ================================================ -- %[...%] = Sets the default prompt bold black color. -- %M = The full host name (with domain) of database server, or [local] if the connection is a Unix domain socket. -- %n = The database user name. -- %/ = The database name. -- %x = The transaction state. See legend below: -- : Not in transaction. -- *: Inside a transaction. -- !: Inside a failed transaction and not rolled back. -- ?: State is unknown or there is no connection. -- %R = The connection info. See legend below: -- =: New command. -- –: Continuation of multiline query. -- ^: In single-line mode. -- @: Inside conditional logic branch. -- *: Inside unfinished comment block. -- ': Inside unfinished single quoted string. -- ": Inside unfinished double quoted string. -- $: Inside unfinished dollar quoted string. -- (: Inside unfinished parenthesis. -- !: Disconnected from database. -- %[...%] = Resets the color to non-bold black. -- %# = '#' if superuser, otherwise '>'. \set PROMPT1 '%[%033[1m%]%M %n@%/%x%R%[%033[0m%]%# ' -- Used when waiting for more input. \set PROMPT2 '[more] %x%R> ' -- Autocomplete keywords (like SELECT) in upper-case, even if you started typing them in lower case. \set COMP_KEYWORD_CASE upper -- Use a separate history file per-database. \set HISTFILE ~/.cache/psql/:DBNAME.log -- If a command is run more than once in a row, only store it once in the history. \set HISTCONTROL ignoredups -- Keep a decently sized history of previously used commands. \set HISTSIZE 1000 -- Enable verbose error reports. \set VERBOSITY verbose -- Use "\q" instead of CONTROL+D (unless pressed 5 times in a row) to quit. \set IGNOREEOF 5 -- Enables error fixing when entering statements via the prompt without starting over. \set ON_ERROR_ROLLBACK interactive -- Reduces typing so you can use `:vet` instead of `EXPLAIN ANALYZE` to check query performance. \set vet 'EXPLAIN ANALYZE' -- By default, NULL is an empty space. This makes NULL values visible. \pset null '[NULL]' -- Enable display of query execution times. \timing on -- Use table format (with headers) by default, but switch to expanded table format when there's a lot of data. \x auto -- Cache Hit \set ch 'SELECT ''index hit rate'' AS name, (sum(idx_blks_hit)) / nullif(sum(idx_blks_hit + idx_blks_read),0) AS ratio FROM pg_statio_user_indexes UNION ALL SELECT ''table hit rate'' AS name, sum(heap_blks_hit) / nullif(sum(heap_blks_hit) + sum(heap_blks_read),0) AS ratio FROM pg_statio_user_tables;' -- Long Running \set lr 'SELECT pid, now() - pg_stat_activity.xact_start AS duration, query, state FROM pg_stat_activity WHERE (now() - pg_stat_activity.xact_start) > interval ''5 minutes'' ORDER by 2 DESC;' -- Indexes (unused) \set iu 'SELECT schemaname || ''.'' || relname AS table, indexrelname AS index, pg_size_pretty(pg_relation_size(i.indexrelid)) AS index_size, idx_scan as index_scans FROM pg_stat_user_indexes ui JOIN pg_index i ON ui.indexrelid = i.indexrelid WHERE NOT indisunique AND idx_scan < 50 AND pg_relation_size(relid) > 5 * 8192 ORDER BY pg_relation_size(i.indexrelid) / nullif(idx_scan, 0) DESC NULLS FIRST, pg_relation_size(i.indexrelid) DESC;' -- Table Sizes \set ts 'SELECT c.relname AS name, pg_size_pretty(pg_table_size(c.oid)) AS size FROM pg_class c LEFT JOIN pg_namespace n ON (n.oid = c.relnamespace) WHERE n.nspname NOT IN (''pg_catalog'', ''information_schema'') AND n.nspname !~ ''^pg_toast'' AND c.relkind=''r'' ORDER BY pg_table_size(c.oid) DESC;' ================================================ FILE: lib/templates/.ruby-version.tt ================================================ 4.0.3 ================================================ FILE: lib/templates/.vimrc.tt ================================================ " VIM SETTINGS set history=1000 " Keep 1000 lines of history. set ruler " Always show the cursor position. set relativenumber " Show line numbers relative to cursor where cursor number is always zero. set expandtab " Use spaces instead of tabs when indenting. set smarttab " Indent instead of tabbing at the beginning of a line. set shiftwidth=2 " Indent by 2 spaces. set tabstop=2 " Hard tab stop. set softtabstop=2 " Soft tab stop. set incsearch " Incrementally highlight search pattern as it is updated. set hlsearch " Highlight search matches after entering search pattern. set ignorecase " Use case insensitive search pattern matching by default. set smartcase " Override 'ignorecase' setting if search pattern contains uppercase characters. set spell " Enable spell checking. set complete+=kspell " Enables use of CONTROL+N or CONTROL+P within Insert mode to complete words being typed. set winwidth=120 " Default window width. set winheight=10 " Default window height. set winminheight=10 " Minimum window height. set winheight=1000 " Reset window height. set tags=./.tags; " Use CTags as generated by Sublime Text. syntax on " Enable syntax highlighting. filetype plugin indent on " Enable file type specific indentation. " Leaders map i mmgg=G`m map cs :nohlsearch " Remappings nnoremap " Move up one window. nnoremap " Move right one window. nnoremap " Move down one window. nnoremap " Move left one window. " Auto-Commands autocmd FileType gitcommit setlocal spell " Enables spell checking for Git commits. autocmd FileType markdown setlocal spell " Enables spell checking for Markdown files. " Extensions execute pathogen#infect() runtime macros/matchit.vim ================================================ FILE: lib/utilities.sh ================================================ #! /usr/bin/env bash # DESCRIPTION # Defines general utility functions. # Shows managed files. show_files() { printf "%s\n" "Managed Dotfiles:" for file in $(home_files); do printf " %s\n" "$(base_dest_file $file)" done } export -f show_files # Installs all files. install_files() { printf "%s\n" "Installing dotfiles..." for file in $(home_files); do install_file $file done printf "%s\n" "Dotfiles install complete!" } export -f install_files # Installs a file. # Parameters: $1 (required): The file name. install_file() { local source_file="$1" local dest_file="$HOME/$(base_dest_file $source_file)" local dest_dir="$(dirname $dest_file)" if [[ "$(basename $source_file)" == "mkdir.command" ]]; then mkdir -p $dest_dir return fi if [[ ! -f "$dest_file" ]]; then mkdir -p "$dest_dir" cp "$source_file" "$dest_file" printf " + %s\n" "$dest_file" fi } export -f install_file # Links all files. link_files() { printf "%s\n" "Linking dotfiles..." for file in $(home_files); do link_file $file done printf "%s\n" "Dotfiles link complete!" } export -f link_files # Links a dotfile to this project. # Parameters: $1 (required): The file name. link_file() { local source_file="$PWD/$1" local dest_file="$HOME/$(base_dest_file $1)" local dest_dir="$(dirname $dest_file)" local excludes=".+(environment.sh.tt|git/configuration.tt)$" if [[ "$(basename $source_file)" == "mkdir.command" ]]; then mkdir -p $dest_dir return fi if [[ ! -h "$dest_file" && ! "$source_file" =~ $excludes ]]; then read -r -p " Link $dest_file -> $source_file (y/n)? " response if [[ $response == 'y' ]]; then mkdir -p "$dest_dir" ln -sf "$source_file" "$dest_file" fi fi } export -f link_file # Checks all files for changes. check_files() { printf "%s\n" "Dotfiles Changes:" for file in $(home_files); do check_file $file done printf "%s\n" "Dotfiles check complete!" } export -f check_files # Checks a file for changes. # Parameters: $1 (required): The file name. check_file() { local source_file="$1" local dest_file="$HOME/$(base_dest_file $1)" local excludes=".+command$" if [[ "$source_file" =~ $excludes ]]; then return elif [[ -e "$dest_file" || -h "$dest_file" ]]; then if [[ "$(diff $dest_file $source_file)" != '' ]]; then printf " * %s\n" "$dest_file" fi else printf " - %s\n" "$dest_file" fi } export -f check_file # Delete files. delete_files() { printf "%s\n" "Deleting dotfiles..." for file in $(home_files); do delete_file $file done printf "%s\n" "Dotfiles deletion complete!" } export -f delete_files # Delete file. # Parameters: $1 (required): The file name. delete_file() { local dest_file="$HOME/$(base_dest_file $1)" local excludes=".+(environment.sh|git/configuration)$" # Proceed only if file exists. if [[ -e "$dest_file" || -h "$dest_file" ]] && [[ ! "$dest_file" =~ $excludes ]]; then read -r -p " Delete $dest_file (y/n)? " response if [[ $response == 'y' ]]; then rm -f "$dest_file" fi fi } export -f delete_file # Label: Home Files # Description: Enumerate home file templates. home_files() { for file in $(find lib/templates -type f); do printf "%s\n" "$file" done } export -f home_files # Label: Base Destination Home File # Description: Compute destination file path for source path. # Parameters: $1 (required): The source path. base_dest_file() { local source_file="$1" printf "${source_file%.*}" | sed 's/lib\/templates\///g' } export -f base_dest_file