├── .env ├── .github └── workflows │ ├── build.yml │ ├── publish.yml │ └── test.yml ├── .gitignore ├── Dockerfile ├── Gemfile ├── Gemfile.lock ├── LICENSE.md ├── Makefile ├── README.md ├── bin ├── homer ├── homer-alias ├── homer-grep ├── homer-help ├── homer-init ├── homer-plugin ├── homer-save ├── homer-script ├── homer-update └── homer-version ├── docs ├── _config.yml ├── homer-thinking.gif ├── index.md ├── install.sh └── manual │ ├── edit.1.html │ ├── homer.1.html │ ├── index.md │ └── page.1.html ├── package.json ├── share ├── doc │ ├── homer │ │ ├── USAGE.txt │ │ ├── alias.txt │ │ ├── grep.txt │ │ ├── init.txt │ │ ├── plugin.txt │ │ ├── save.txt │ │ ├── script.txt │ │ ├── update.txt │ │ └── version.txt │ └── man │ │ ├── edit.1.md │ │ ├── homer.1.md │ │ └── page.1.md ├── homer.zsh └── homer │ ├── VERSION │ ├── cli.zsh │ ├── command │ ├── bin.sh │ ├── doc.txt │ └── test.bats │ ├── profile.d │ ├── editing.zsh │ ├── paths.zsh │ ├── shell.zsh │ ├── terminal.zsh │ └── vcsinfo.zsh │ └── template │ ├── .gitignore │ ├── .zshenv │ ├── .zshrc │ ├── README.md │ ├── bin │ └── .keep │ └── etc │ ├── aliases.zsh │ ├── plugins.zsh │ └── profile.d │ └── .keep └── test ├── homer-alias-test.bats ├── homer-grep-test.bats ├── homer-help-test.bats ├── homer-init-test.bats ├── homer-install-test.bats ├── homer-plugin-test.bats ├── homer-save-test.bats ├── homer-script-test.bats ├── homer-test.bats ├── homer-update-test.bats ├── homer-version-test.bats └── test_helper.bash /.env: -------------------------------------------------------------------------------- 1 | # Development configuration for Homer. This configuration is 2 | # automatically run with the dotenv shell extension, and will add the 3 | # paths in $PWD/bin and the bundle's bin directory to your $PATH for 4 | # easy command execution. Any commands executed within this directory 5 | # will be looked for in the current directory bin, always ensuring 6 | # you're using the commands that you're editing. 7 | 8 | export HOMER_PATH=$PWD 9 | export PATH=$PWD/bin:$PWD/vendor/bundle/bin:$PATH 10 | -------------------------------------------------------------------------------- /.github/workflows/build.yml: -------------------------------------------------------------------------------- 1 | name: Build 2 | on: 3 | push: 4 | branches: [master] 5 | jobs: 6 | build: 7 | name: Build Signed Package 8 | runs-on: ubuntu-latest 9 | steps: 10 | - name: Checkout Source Code 11 | uses: actions/checkout@v1 12 | - name: Setup Ruby 13 | uses: actions/setup-ruby@v1 14 | - name: Install Dependencies 15 | run: | 16 | sudo apt-get update -qq 17 | sudo apt-get install -qqyy zsh 18 | gem install bundler 19 | - name: Configure GPG 20 | run: | 21 | echo "${{ secrets.gpg_public_key }}" | gpg --import 22 | echo "${{ secrets.gpg_private_key }}" | gpg --import 23 | - name: Find Current Version 24 | id: get_version 25 | run: echo ::set-output name=VERSION::$(echo $GITHUB_REF | cut -d / -f 3) 26 | - name: Build Project 27 | run: make 28 | env: 29 | BUNDLE_PATH: vendor/bundle 30 | - name: Upload Tarball 31 | uses: actions/upload-artifact@v1 32 | with: 33 | path: dist/homer-${{ steps.get_version.outputs.VERSION }}.tar.gz 34 | name: homer-${{ steps.get_version.outputs.VERSION }}.tar.gz 35 | - name: Upload Signature 36 | uses: actions/upload-artifact@v1 37 | with: 38 | path: dist/homer-${{ steps.get_version.outputs.VERSION }}.tar.gz.asc 39 | name: homer-${{ steps.get_version.outputs.VERSION }}.tar.gz.asc 40 | -------------------------------------------------------------------------------- /.github/workflows/publish.yml: -------------------------------------------------------------------------------- 1 | name: Publish 2 | on: 3 | push: 4 | tags: [v*] 5 | jobs: 6 | build: 7 | name: Build Signed Package 8 | runs-on: ubuntu-latest 9 | steps: 10 | - name: Checkout Source Code 11 | uses: actions/checkout@v1 12 | - name: Setup Ruby 13 | uses: actions/setup-ruby@v1 14 | - name: Install Dependencies 15 | run: | 16 | sudo apt-get update -qq 17 | sudo apt-get install -qqyy zsh 18 | gem install bundler 19 | - name: Configure GPG 20 | run: | 21 | echo "${{ secrets.gpg_public_key }}" | gpg --import 22 | echo "${{ secrets.gpg_private_key }}" | gpg --import 23 | - name: Find Current Version 24 | id: get_version 25 | run: echo ::set-output name=VERSION::$(echo $GITHUB_REF | cut -d / -f 3) 26 | - name: Build Project 27 | run: make 28 | env: 29 | BUNDLE_PATH: vendor/bundle 30 | - name: Upload Artifacts 31 | uses: actions/upload-artifact@v1 32 | with: 33 | path: dist 34 | name: homer-${{ steps.get_version.outputs.VERSION }} 35 | release: 36 | name: Create New Release 37 | runs-on: ubuntu-latest 38 | needs: build 39 | steps: 40 | - name: Find Current Version 41 | id: get_version 42 | run: echo ::set-output name=VERSION::$(echo $GITHUB_REF | cut -d / -f 3) 43 | - name: Download Artifacts 44 | uses: actions/download-artifact@v1 45 | with: 46 | name: homer-${{ steps.get_version.outputs.VERSION }} 47 | - name: Create GitHub Release 48 | id: create_release 49 | uses: actions/create-release@v1.0.0 50 | env: 51 | GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} 52 | with: 53 | tag_name: ${{ steps.get_version.outputs.VERSION }} 54 | release_name: Release ${{ steps.get_version.outputs.VERSION }} 55 | draft: false 56 | prerelease: false 57 | - name: Publish Tarball 58 | uses: actions/upload-release-asset@v1.0.1 59 | env: 60 | GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} 61 | with: 62 | upload_url: ${{ steps.create_release.outputs.upload_url }} 63 | asset_path: ./homer-${{ steps.get_version.outputs.VERSION }}/homer-${{ steps.get_version.outputs.VERSION }}.tar.gz 64 | asset_name: homer-${{ steps.get_version.outputs.VERSION }}.tar.gz 65 | asset_content_type: application/tar+gzip 66 | - name: Publish Signature 67 | uses: actions/upload-release-asset@v1.0.1 68 | env: 69 | GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} 70 | with: 71 | upload_url: ${{ steps.create_release.outputs.upload_url }} 72 | asset_path: ./homer-${{ steps.get_version.outputs.VERSION }}/homer-${{ steps.get_version.outputs.VERSION }}.tar.gz.asc 73 | asset_name: homer-${{ steps.get_version.outputs.VERSION }}.asc 74 | asset_content_type: text/plain 75 | -------------------------------------------------------------------------------- /.github/workflows/test.yml: -------------------------------------------------------------------------------- 1 | name: Tests 2 | on: [push] 3 | jobs: 4 | test: 5 | name: Run Automated Tests 6 | runs-on: ubuntu-latest 7 | steps: 8 | - name: Checkout Source Code 9 | uses: actions/checkout@v1 10 | - name: Setup NodeJS 11 | uses: actions/setup-node@v1 12 | - name: Install Dependencies 13 | run: | 14 | sudo apt-get update -qq 15 | sudo apt-get install -qqyy zsh 16 | - name: Configure Git 17 | run: | 18 | git config --global user.email "test@example.com" 19 | git config --global user.name "Lester Tester" 20 | - name: Run BATS 21 | run: make check 22 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | /.bundle/ 2 | tags 3 | /vendor 4 | docs/_site 5 | node_modules 6 | yarn.lock 7 | /dist 8 | /share/man/man1 9 | /.wiki 10 | -------------------------------------------------------------------------------- /Dockerfile: -------------------------------------------------------------------------------- 1 | # 2 | # Docker image that comes with Homer pre-installed. This is used for 3 | # "integration" tests of the installer script to make sure it will 4 | # automatically install everything correctly without having to blow away 5 | # an existing install on a machine. 6 | # 7 | 8 | # Use the latest version of Ubuntu 9 | FROM ubuntu:latest 10 | 11 | # Build dependencies 12 | RUN apt-get update -qq && apt-get install build-essential sudo curl zsh git -yy 13 | 14 | # Ensure the $PATH has /usr/local at the beginning 15 | ENV PATH=/usr/local/bin:$PATH PREFIX=/usr/local 16 | 17 | # Configure Git 18 | RUN git config --global user.email "test@example.com" 19 | RUN git config --global user.name "Lester Tester" 20 | 21 | # Install Homer 22 | COPY docs/install.sh install.sh 23 | RUN bash install.sh 24 | -------------------------------------------------------------------------------- /Gemfile: -------------------------------------------------------------------------------- 1 | source 'https://rubygems.org' 2 | 3 | # Use Kramdown to generate Man pages. 4 | gem 'kramdown-man' 5 | 6 | # Use ronn to convert Man pages into HTML 7 | gem 'ronn' 8 | 9 | # Use Jekyll and GitHub Pages for the documentation site. 10 | gem 'jekyll' 11 | gem 'jekyll-theme-hacker', group: :jekyll_plugins 12 | gem 'github-pages', group: :jekyll_plugins 13 | -------------------------------------------------------------------------------- /Gemfile.lock: -------------------------------------------------------------------------------- 1 | GEM 2 | remote: https://rubygems.org/ 3 | specs: 4 | activesupport (4.2.11.1) 5 | i18n (~> 0.7) 6 | minitest (~> 5.1) 7 | thread_safe (~> 0.3, >= 0.3.4) 8 | tzinfo (~> 1.1) 9 | addressable (2.7.0) 10 | public_suffix (>= 2.0.2, < 5.0) 11 | coffee-script (2.4.1) 12 | coffee-script-source 13 | execjs 14 | coffee-script-source (1.11.1) 15 | colorator (1.1.0) 16 | commonmarker (0.17.13) 17 | ruby-enum (~> 0.5) 18 | concurrent-ruby (1.1.5) 19 | dnsruby (1.61.3) 20 | addressable (~> 2.5) 21 | em-websocket (0.5.1) 22 | eventmachine (>= 0.12.9) 23 | http_parser.rb (~> 0.6.0) 24 | ethon (0.12.0) 25 | ffi (>= 1.3.0) 26 | eventmachine (1.2.7) 27 | execjs (2.7.0) 28 | faraday (0.15.4) 29 | multipart-post (>= 1.2, < 3) 30 | ffi (1.11.1) 31 | forwardable-extended (2.6.0) 32 | gemoji (3.0.1) 33 | github-pages (198) 34 | activesupport (= 4.2.11.1) 35 | github-pages-health-check (= 1.16.1) 36 | jekyll (= 3.8.5) 37 | jekyll-avatar (= 0.6.0) 38 | jekyll-coffeescript (= 1.1.1) 39 | jekyll-commonmark-ghpages (= 0.1.5) 40 | jekyll-default-layout (= 0.1.4) 41 | jekyll-feed (= 0.11.0) 42 | jekyll-gist (= 1.5.0) 43 | jekyll-github-metadata (= 2.12.1) 44 | jekyll-mentions (= 1.4.1) 45 | jekyll-optional-front-matter (= 0.3.0) 46 | jekyll-paginate (= 1.1.0) 47 | jekyll-readme-index (= 0.2.0) 48 | jekyll-redirect-from (= 0.14.0) 49 | jekyll-relative-links (= 0.6.0) 50 | jekyll-remote-theme (= 0.3.1) 51 | jekyll-sass-converter (= 1.5.2) 52 | jekyll-seo-tag (= 2.5.0) 53 | jekyll-sitemap (= 1.2.0) 54 | jekyll-swiss (= 0.4.0) 55 | jekyll-theme-architect (= 0.1.1) 56 | jekyll-theme-cayman (= 0.1.1) 57 | jekyll-theme-dinky (= 0.1.1) 58 | jekyll-theme-hacker (= 0.1.1) 59 | jekyll-theme-leap-day (= 0.1.1) 60 | jekyll-theme-merlot (= 0.1.1) 61 | jekyll-theme-midnight (= 0.1.1) 62 | jekyll-theme-minimal (= 0.1.1) 63 | jekyll-theme-modernist (= 0.1.1) 64 | jekyll-theme-primer (= 0.5.3) 65 | jekyll-theme-slate (= 0.1.1) 66 | jekyll-theme-tactile (= 0.1.1) 67 | jekyll-theme-time-machine (= 0.1.1) 68 | jekyll-titles-from-headings (= 0.5.1) 69 | jemoji (= 0.10.2) 70 | kramdown (= 1.17.0) 71 | liquid (= 4.0.0) 72 | listen (= 3.1.5) 73 | mercenary (~> 0.3) 74 | minima (= 2.5.0) 75 | nokogiri (>= 1.8.5, < 2.0) 76 | rouge (= 2.2.1) 77 | terminal-table (~> 1.4) 78 | github-pages-health-check (1.16.1) 79 | addressable (~> 2.3) 80 | dnsruby (~> 1.60) 81 | octokit (~> 4.0) 82 | public_suffix (~> 3.0) 83 | typhoeus (~> 1.3) 84 | hpricot (0.8.6) 85 | html-pipeline (2.12.0) 86 | activesupport (>= 2) 87 | nokogiri (>= 1.4) 88 | http_parser.rb (0.6.0) 89 | i18n (0.9.5) 90 | concurrent-ruby (~> 1.0) 91 | jekyll (3.8.5) 92 | addressable (~> 2.4) 93 | colorator (~> 1.0) 94 | em-websocket (~> 0.5) 95 | i18n (~> 0.7) 96 | jekyll-sass-converter (~> 1.0) 97 | jekyll-watch (~> 2.0) 98 | kramdown (~> 1.14) 99 | liquid (~> 4.0) 100 | mercenary (~> 0.3.3) 101 | pathutil (~> 0.9) 102 | rouge (>= 1.7, < 4) 103 | safe_yaml (~> 1.0) 104 | jekyll-avatar (0.6.0) 105 | jekyll (~> 3.0) 106 | jekyll-coffeescript (1.1.1) 107 | coffee-script (~> 2.2) 108 | coffee-script-source (~> 1.11.1) 109 | jekyll-commonmark (1.3.1) 110 | commonmarker (~> 0.14) 111 | jekyll (>= 3.7, < 5.0) 112 | jekyll-commonmark-ghpages (0.1.5) 113 | commonmarker (~> 0.17.6) 114 | jekyll-commonmark (~> 1) 115 | rouge (~> 2) 116 | jekyll-default-layout (0.1.4) 117 | jekyll (~> 3.0) 118 | jekyll-feed (0.11.0) 119 | jekyll (~> 3.3) 120 | jekyll-gist (1.5.0) 121 | octokit (~> 4.2) 122 | jekyll-github-metadata (2.12.1) 123 | jekyll (~> 3.4) 124 | octokit (~> 4.0, != 4.4.0) 125 | jekyll-mentions (1.4.1) 126 | html-pipeline (~> 2.3) 127 | jekyll (~> 3.0) 128 | jekyll-optional-front-matter (0.3.0) 129 | jekyll (~> 3.0) 130 | jekyll-paginate (1.1.0) 131 | jekyll-readme-index (0.2.0) 132 | jekyll (~> 3.0) 133 | jekyll-redirect-from (0.14.0) 134 | jekyll (~> 3.3) 135 | jekyll-relative-links (0.6.0) 136 | jekyll (~> 3.3) 137 | jekyll-remote-theme (0.3.1) 138 | jekyll (~> 3.5) 139 | rubyzip (>= 1.2.1, < 3.0) 140 | jekyll-sass-converter (1.5.2) 141 | sass (~> 3.4) 142 | jekyll-seo-tag (2.5.0) 143 | jekyll (~> 3.3) 144 | jekyll-sitemap (1.2.0) 145 | jekyll (~> 3.3) 146 | jekyll-swiss (0.4.0) 147 | jekyll-theme-architect (0.1.1) 148 | jekyll (~> 3.5) 149 | jekyll-seo-tag (~> 2.0) 150 | jekyll-theme-cayman (0.1.1) 151 | jekyll (~> 3.5) 152 | jekyll-seo-tag (~> 2.0) 153 | jekyll-theme-dinky (0.1.1) 154 | jekyll (~> 3.5) 155 | jekyll-seo-tag (~> 2.0) 156 | jekyll-theme-hacker (0.1.1) 157 | jekyll (~> 3.5) 158 | jekyll-seo-tag (~> 2.0) 159 | jekyll-theme-leap-day (0.1.1) 160 | jekyll (~> 3.5) 161 | jekyll-seo-tag (~> 2.0) 162 | jekyll-theme-merlot (0.1.1) 163 | jekyll (~> 3.5) 164 | jekyll-seo-tag (~> 2.0) 165 | jekyll-theme-midnight (0.1.1) 166 | jekyll (~> 3.5) 167 | jekyll-seo-tag (~> 2.0) 168 | jekyll-theme-minimal (0.1.1) 169 | jekyll (~> 3.5) 170 | jekyll-seo-tag (~> 2.0) 171 | jekyll-theme-modernist (0.1.1) 172 | jekyll (~> 3.5) 173 | jekyll-seo-tag (~> 2.0) 174 | jekyll-theme-primer (0.5.3) 175 | jekyll (~> 3.5) 176 | jekyll-github-metadata (~> 2.9) 177 | jekyll-seo-tag (~> 2.0) 178 | jekyll-theme-slate (0.1.1) 179 | jekyll (~> 3.5) 180 | jekyll-seo-tag (~> 2.0) 181 | jekyll-theme-tactile (0.1.1) 182 | jekyll (~> 3.5) 183 | jekyll-seo-tag (~> 2.0) 184 | jekyll-theme-time-machine (0.1.1) 185 | jekyll (~> 3.5) 186 | jekyll-seo-tag (~> 2.0) 187 | jekyll-titles-from-headings (0.5.1) 188 | jekyll (~> 3.3) 189 | jekyll-watch (2.2.1) 190 | listen (~> 3.0) 191 | jemoji (0.10.2) 192 | gemoji (~> 3.0) 193 | html-pipeline (~> 2.2) 194 | jekyll (~> 3.0) 195 | kramdown (1.17.0) 196 | kramdown-man (0.1.6) 197 | kramdown (~> 1.0) 198 | liquid (4.0.0) 199 | listen (3.1.5) 200 | rb-fsevent (~> 0.9, >= 0.9.4) 201 | rb-inotify (~> 0.9, >= 0.9.7) 202 | ruby_dep (~> 1.2) 203 | mercenary (0.3.6) 204 | mini_portile2 (2.4.0) 205 | minima (2.5.0) 206 | jekyll (~> 3.5) 207 | jekyll-feed (~> 0.9) 208 | jekyll-seo-tag (~> 2.1) 209 | minitest (5.11.3) 210 | multipart-post (2.1.1) 211 | mustache (1.1.0) 212 | nokogiri (1.10.8) 213 | mini_portile2 (~> 2.4.0) 214 | octokit (4.14.0) 215 | sawyer (~> 0.8.0, >= 0.5.3) 216 | pathutil (0.16.2) 217 | forwardable-extended (~> 2.6) 218 | public_suffix (3.1.1) 219 | rb-fsevent (0.10.3) 220 | rb-inotify (0.10.0) 221 | ffi (~> 1.0) 222 | rdiscount (2.2.0.1) 223 | ronn (0.7.3) 224 | hpricot (>= 0.8.2) 225 | mustache (>= 0.7.0) 226 | rdiscount (>= 1.5.8) 227 | rouge (2.2.1) 228 | ruby-enum (0.7.2) 229 | i18n 230 | ruby_dep (1.5.0) 231 | rubyzip (2.0.0) 232 | safe_yaml (1.0.5) 233 | sass (3.7.4) 234 | sass-listen (~> 4.0.0) 235 | sass-listen (4.0.0) 236 | rb-fsevent (~> 0.9, >= 0.9.4) 237 | rb-inotify (~> 0.9, >= 0.9.7) 238 | sawyer (0.8.2) 239 | addressable (>= 2.3.5) 240 | faraday (> 0.8, < 2.0) 241 | terminal-table (1.8.0) 242 | unicode-display_width (~> 1.1, >= 1.1.1) 243 | thread_safe (0.3.6) 244 | typhoeus (1.3.1) 245 | ethon (>= 0.9.0) 246 | tzinfo (1.2.5) 247 | thread_safe (~> 0.1) 248 | unicode-display_width (1.6.0) 249 | 250 | PLATFORMS 251 | ruby 252 | 253 | DEPENDENCIES 254 | github-pages 255 | jekyll 256 | jekyll-theme-hacker 257 | kramdown-man 258 | ronn 259 | 260 | BUNDLED WITH 261 | 2.1.0 262 | -------------------------------------------------------------------------------- /LICENSE.md: -------------------------------------------------------------------------------- 1 | # The MIT License (MIT) 2 | 3 | Copyright (c) 2014 Tom Scott 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in 13 | all copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 21 | THE SOFTWARE. 22 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | # Build scripts for Homer. These tasks will generate documentation, 2 | # commands, and of course install the Homer scripts themselves to an 3 | # executable location. 4 | # 5 | # Shoutouts to @postmodern and @isaacs, I lifted most of their ideas to 6 | # make this... 7 | 8 | .PHONY: all build test check install uninstall clean command release verify 9 | 10 | PROGRAM=homer 11 | SHELL=/usr/bin/env zsh 12 | PREFIX?=$(DESTDIR)/usr/local 13 | HOMER_PATH?=$(PWD) 14 | SOURCE_PATH=$(PWD) 15 | DIRS=bin share 16 | INSTALL_DIRS=`find $(DIRS) -type d` 17 | INSTALL_FILES=`find $(DIRS) -type f` 18 | GITHUB_REF?=$(shell git show-ref $(git branch | grep '*') | head -n 1 | awk '{ print $2 }') 19 | VERSION?=$(shell echo $(GITHUB_REF) | cut -d / -f 3) 20 | DOCS=$(shell find share/doc/man/*.md -type f | sed 's/doc\/man/man\/man1/g' | sed 's/\.md//g') 21 | 22 | PKG_DIR=dist 23 | PKG_NAME=$(PROGRAM)-$(VERSION) 24 | PKG=$(PKG_DIR)/$(PKG_NAME).tar.gz 25 | TAG=.git/refs/tags/$(VERSION) 26 | SIG=$(PKG).asc 27 | 28 | # Build the documentation and tarball, then sign the package with GPG 29 | all: $(DOCS) $(PKG) $(SIG) 30 | build: all 31 | 32 | # Install manpages generator 33 | vendor/bundle: 34 | @bundle check || bundle install 35 | 36 | # Remove all generated files 37 | clean: 38 | @rm -rf tmp share/man/man1 dist 39 | 40 | # Install the testing framework 41 | node_modules: 42 | @yarn 43 | 44 | # Run all tests 45 | check: node_modules 46 | @node_modules/.bin/bats test 47 | test: check 48 | 49 | # Generate man pages from markdown 50 | share/man/man1: 51 | @mkdir -p share/man/man1 52 | docs/manual: 53 | @mkdir -p docs/manual 54 | share/man/man1/%.1: vendor/bundle share/man/man1 docs/manual 55 | @bundle exec ronn --date="2014-11-01" --manual="User Manual" --organization="$(PROGRAM)" --style=dark share/doc/man/$(@F).md 56 | @mv share/doc/man/$(@F) share/man/man1/$(@F) 57 | @mv share/doc/man/$(@F).html docs/manual/$(@F).html 58 | 59 | # Move scripts to /usr/local. Typically requires `sudo` access. 60 | install: 61 | @for dir in $(INSTALL_DIRS); do mkdir -p $(DESTDIR)$(PREFIX)/$$dir; done 62 | @for file in $(INSTALL_FILES); do cp $$file $(DESTDIR)$(PREFIX)/$$file; done 63 | 64 | # Remove scripts from /usr/local. Typically requires `sudo` access. 65 | uninstall: 66 | @for file in $(INSTALL_FILES); do echo $$file; done 67 | 68 | # Generate a new command 69 | command: 70 | @cp share/homer/command/bin.sh bin/homer-${NAME} 71 | @cp share/homer/command/doc.txt share/doc/homer/${NAME}.txt 72 | @cp share/homer/command/test.bats test/homer-${NAME}-test.bats 73 | @chmod +x bin/homer-${NAME} 74 | 75 | # Tag the current state of the codebase as a released version 76 | $(TAG): 77 | @git tag $(VERSION) -m "Release $(VERSION)" 78 | 79 | # Generate ctags 80 | tags: 81 | @ctags -R . 82 | 83 | # Create a package for the current version of the codebase. This 84 | # omits developer-centric files like tests and build manifests for the 85 | # released version of the package. 86 | $(PKG_DIR): 87 | @mkdir -p $(PKG_DIR) 88 | $(PKG): $(PKG_DIR) 89 | @git archive --output=$(PKG) --prefix=$(PKG_NAME)/ HEAD $(DIRS) ./Makefile 90 | 91 | # Cryptographically sign the package so its contents can be verified at 92 | # a later date 93 | $(SIG): $(PKG) 94 | @gpg --batch --sign --detach-sign --armor $(PKG) 95 | 96 | # Release the latest version of Homer to GitHub. 97 | release: $(TAG) 98 | @git push origin --tags 99 | @git push origin master 100 | 101 | # Verify the contents of a package 102 | verify: $(PKG) $(SIG) 103 | @gpg --verify $(SIG) $(PKG) 104 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Homer 2 | 3 | [![Test Status](https://github.com/tubbo/homer/workflows/Tests/badge.svg)][ci] 4 | [![Build Status](https://github.com/tubbo/homer/workflows/Build/badge.svg)][ci] 5 | [![Publish Status](https://github.com/tubbo/homer/workflows/Publish/badge.svg)][ci] 6 | 7 | ![Homer Thinking](https://github.com/tubbo/homer/raw/master/docs/homer-thinking.gif) 8 | 9 | Homer is a home directory manager for your shell. Using [Git][git], it 10 | tracks changes in your home directory configuration from anywhere on 11 | your machine. Its goal is to uncover the IDE-like possibilities of the 12 | shell and make such features more approachable to newer users, while 13 | still retaining its usefulness to power users. 14 | 15 | Homer is an opinionated, but minimal, framework. While most of what 16 | it assumes about your environment is strongly enforced across the 17 | framework, it attempts to assume little about your system, instead 18 | allowing you to customize your shell the way you see fit. Homer's main 19 | philosophy is that having a stellar shell configuration should be 20 | much easier than it is today. 21 | 22 | ## How It Works 23 | 24 | Homer is effectively a Git repo and shell extension manager that is accessible 25 | from anywhere on the machine. It's written entirely in [ZSH][] shell 26 | script, but you don't have to use ZSH to gain its benefits. Homer is actually 27 | nothing more than a set of conventions, some shell scripts to make 28 | complex tasks easier, and some useful/sane defaults for ZSH. Homer's 29 | components are tools that wrap a Git repository and your ZSH 30 | configuration. 31 | 32 | Homer is comparable with tools like [GNU Stow][stow], its main 33 | difference is that instead of keeping a directory separate from 34 | `$HOME` and symlinking the necessary files over from some 35 | version-controlled directory when asked, Homer uses the home 36 | directory as a Git repository and ignores any files it doesn't explicitly 37 | track. It also provides ZSH-specific alias and plugin management, which 38 | Stow as a more generalized system does not do. Homer is essentially a tool for 39 | managing any file in your home directory you wish to keep with Git. 40 | 41 | ## Features 42 | 43 | - Syncs home directory configuration with a Git repository 44 | - Manages shell aliases and custom shell scripts 45 | - Manages OS packages and custom package repositories 46 | - Exposes useful attributes and contains a small CLI plugin API that 47 | allows for hooking into Homer and adding your own commands. 48 | 49 | ## Installation 50 | 51 | The easiest way to install Homer is with the one-liner install script: 52 | 53 | ```bash 54 | $ curl -o- -L https://homer.psychedeli.ca/install.sh | bash 55 | ``` 56 | 57 | It's a good practice to always [view the source code][installer] before 58 | running a command like this, but if you're busy, here's a short 59 | description of what the installer script does: 60 | 61 | 1. Downloads the latest `.tar.gz` release of Homer 62 | 2. Extracts the source code to a directory in `/tmp` 63 | 3. Runs `sudo make` in the source code directory, this will require you 64 | to type in your root password 65 | 4. Removes all files in the `/tmp` directory created by the installer. 66 | 67 | ### From a Package Manager 68 | 69 | As a package, Homer is available on [Homebrew][brew]: 70 | 71 | ```bash 72 | $ brew tap tubbo/homebrew-tap 73 | $ brew install homer 74 | ``` 75 | 76 | You can also install the edge version of Homer, which is the latest 77 | commit of 'master' branch, by applying the **--HEAD** switch: 78 | 79 | ```bash 80 | $ brew install homer --HEAD 81 | ``` 82 | 83 | ### From Source 84 | 85 | Before installing from source, make sure you have the following hard 86 | dependencies installed: 87 | 88 | - zsh 89 | - antigen 90 | - keychain 91 | - bats (if you're developing on the project) 92 | 93 | Once they're all installed, run the following commands to install to 94 | `/usr/local`... 95 | 96 | ```bash 97 | $ git clone https://github.com/tubbo/homer.git 98 | $ cd homer 99 | $ make && sudo make install 100 | ``` 101 | 102 | When its installed, run the setup command: 103 | 104 | ```bash 105 | $ homer init 106 | ``` 107 | 108 | This will create a Git repo in your home directory, add 109 | a `~/.gitignore` file to control it, and some 110 | default ZSH configuration. 111 | 112 | If you already have a home directory repo that was initialized using 113 | Homer, you can copy it down to your machine with the following command: 114 | 115 | ```bash 116 | $ homer init https://url.to/your/home/directory/repo.git 117 | ``` 118 | 119 | This will clone the Git repo at the URL provided to `/tmp/homer` without 120 | actually checking out a working copy. After copying the `.git` directory 121 | (the actual data contents of the repo) to your home directory, it will 122 | run `git reset --hard HEAD` to "rehydrate" all the files of the working 123 | copy in the home directory rather than in the place it was checked out. 124 | This is to ensure that any overwritten files will have a diff to show 125 | you what changed, and none of your files that currently exist in the 126 | home directory will be accidentally deleted. 127 | 128 | ## Usage 129 | 130 | Homer is primarily used to track files which are located in your home 131 | directory to your Git repository. You can add files that are currently 132 | untracked with the `homer save` command: 133 | 134 | ```bash 135 | $ homer save .vimrc -m "Removed vim-rails" 136 | ``` 137 | 138 | This will begin tracking the file at `~/.vimrc` in your home directory 139 | repo. A commit will be added using the message in `-m`, and you can run 140 | `homer update` to sync with the remote at any time. 141 | 142 | If you wish to stop tracking a given configuration file, run `homer 143 | save` with the `-r` flag: 144 | 145 | ```bash 146 | $ homer save -r .vimrc 147 | ``` 148 | 149 | This removes the `~/.vimrc` file from your repo (but retains it in your 150 | home directory) and stops tracking it. When no `-m` is given for a 151 | message, the message is derived from the action, command, and filename. 152 | 153 | ### Idempotency 154 | 155 | Homer is designed to keep your local machine's configuration in sync 156 | with the configuration that may be stored on a remote Git repository. 157 | This could have changes that are not yet on your machine, and Homer 158 | can pull those changes down, cleanly, without affecting any files that 159 | you may have locally edited. 160 | 161 | To update the current home directory with the remote: 162 | 163 | ```bash 164 | $ homer update 165 | ``` 166 | 167 | You can also update Homer itself, which is basically re-running the 168 | installer script. To do so, run: 169 | 170 | ```bash 171 | $ homer upgrade 172 | ``` 173 | 174 | ### Plugins 175 | 176 | Homer provides an easy way to manage ZSH plugins with [Antigen][]. 177 | These plugins are automatically installed when you `init` your home 178 | directory on a new machine. Antigen is installed automatically upon 179 | initialization if it's not already installed. The plugin manifest can be 180 | found in `~/etc/plugins.zsh`. 181 | 182 | To install a new plugin: 183 | 184 | ```bash 185 | $ homer plugin zsh-users/zsh-syntax-highlighting 186 | ``` 187 | 188 | As well as remove them. 189 | 190 | ```bash 191 | $ homer plugin zsh-users/zsh-syntax-highlighting -r 192 | ``` 193 | 194 | ### Aliases 195 | 196 | Homer can add aliases and save them for later use. These aliases are 197 | stored in `~/etc/aliases.zsh`, and tracked by Git so they can be shared 198 | in your home directory repository. 199 | 200 | To add a new alias: 201 | 202 | ```bash 203 | $ homer alias gc 'git commit' 204 | ``` 205 | 206 | Reload your shell, and you can now use `gc` as an alias to `git commit`: 207 | 208 | ```bash 209 | $ gc -m "wow this is cool" 210 | ``` 211 | 212 | To delete an alias: 213 | 214 | ```bash 215 | $ homer alias -d gc 216 | ``` 217 | 218 | ### User Scripts 219 | 220 | If you write a useful shell script or executable, Homer can copy this 221 | file to a directory in your `$PATH`. Homer uses the `~/bin` directory 222 | for this purpose, and keeps files in this directory checked in to Git so 223 | you can share them in your home directory repo. Upon initialization, 224 | Homer will also `chmod +x` this entire directory to ensure that files 225 | created within it will default to be executable by the current user. 226 | 227 | ```bash 228 | $ homer script bin/find-and-replace-in-project 229 | $ find-and-replace-in-project 230 | ``` 231 | 232 | You can also remove commands from this directory: 233 | 234 | ```bash 235 | $ homer script bin/find-and-replace-in-project -r 236 | ``` 237 | 238 | ### Text Editing and Paging 239 | 240 | Homer uses the `$EDITOR` and `$PAGER` variables as the backbone for the 241 | `edit` and `page` (or `e` and `v`) commands used to edit and view text 242 | files, respectively. Text editing and viewing files with a page are two 243 | of the most common tasks performed within the shell, and Homer helps 244 | integrate whatever editor you choose to use seamlessly within your shell 245 | environment. 246 | 247 | To edit text with your `$EDITOR`, run: 248 | 249 | ```bash 250 | $ edit some/file.txt 251 | ``` 252 | 253 | You can also view files with the `$PAGER` by running: 254 | 255 | ```bash 256 | $ page /var/log/system.log 257 | ``` 258 | 259 | The `$EDITOR` is set to `vi` by default, and the `$PAGER` is set to 260 | `less`, but you can change these values in your **~/.zshenv**: 261 | 262 | ```bash 263 | export EDITOR='vim' 264 | export PAGER='less -r' 265 | ``` 266 | 267 | ### Conventions 268 | 269 | Homer establishes useful conventions on your home directory. It 270 | uses the **~/bin/** directory to store user-made scripts which are 271 | available in the `$PATH`. It creates an **~/etc/** directory and uses that to 272 | store files such as **~/etc/plugins.zsh** for defining shell plugins and 273 | **~/etc/aliases.zsh** for storing shell aliases you wish to recall later. 274 | Note that you should not edit the manifest files mentioned above manually, the 275 | `homer alias` and `homer plugin` tools should manage the files for 276 | you. Place any ZSH code you wish to load when the shell launches 277 | in "initializer" files within **~/etc/profile.d**, keeping **~/.zshrc** and 278 | **~/.zshenv** clear. 279 | 280 | As well as creating these initial files, it also runs `git init` in your 281 | home directory, effectively making the entire thing a Git repository. In order 282 | to prevent massive repo sizes and checking in unsafe credentials, 283 | Homer does not initially add any files to this repo, except for the ones 284 | it generates. One of these generated files is a `.gitignore`, which ignores all 285 | files in the home directory by default. To add files to the repo, you need to use 286 | `homer save` or run `git add -f` in your home directory. 287 | 288 | ## Development 289 | 290 | Homer is written entirely in [ZSH][] shell script. It uses [BATS][bats] to 291 | run its tests, and a Makefile is provided to run the tests as well as 292 | build/install the project. 293 | 294 | To run tests: 295 | 296 | ```bash 297 | $ make test 298 | ``` 299 | 300 | You can also use the Makefile to generate a new command: 301 | 302 | ```bash 303 | $ make command NAME=foo 304 | ``` 305 | 306 | This will generate `bin/homer-foo`, `share/doc/homer/foo.txt`, and 307 | `test/homer-foo-test.bats` with given templates. 308 | 309 | The Makefile is also used to create releases, which are mostly handled 310 | by [GitHub Actions][ci]. To create a new release, generate its tag by running: 311 | 312 | ```bash 313 | $ make release VERSION=foo 314 | ``` 315 | 316 | This will create a new tag and push it to GitHub, where the package will 317 | be built, signed, and uploaded as an artifact to a new [GitHub Release][] 318 | 319 | ### License 320 | 321 | Homer uses the MIT License, as described below: 322 | 323 | ``` 324 | The MIT License (MIT) 325 | 326 | Copyright (c) 2014-2019 Tom Scott 327 | 328 | Permission is hereby granted, free of charge, to any person obtaining a copy 329 | of this software and associated documentation files (the "Software"), to deal 330 | in the Software without restriction, including without limitation the rights 331 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 332 | copies of the Software, and to permit persons to whom the Software is 333 | furnished to do so, subject to the following conditions: 334 | 335 | The above copyright notice and this permission notice shall be included in 336 | all copies or substantial portions of the Software. 337 | 338 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 339 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 340 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 341 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 342 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 343 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 344 | THE SOFTWARE. 345 | ``` 346 | 347 | [git]: http://git-scm.com 348 | [brew]: http://brew.sh 349 | [bats]: https://github.com/sstephenson/bats 350 | [stow]: http://www.gnu.org/software/stow/ 351 | [ci]: https://github.com/tubbo/homer/actions 352 | [Antigen]: https://github.com/zsh-users/antigen 353 | [ZSH]: http://zsh.sourceforge.net/ 354 | [installer]: https://github.com/tubbo/homer/blob/master/docs/install.sh 355 | [GitHub Release]: https://github.com/tubbo/homer/releases 356 | -------------------------------------------------------------------------------- /bin/homer: -------------------------------------------------------------------------------- 1 | #!/bin/zsh 2 | # 3 | # Executes Homer commands 4 | 5 | # All variables are based off this single key, which is the location of 6 | # this particular file. 7 | case $0 in 8 | /*) HOMER_SCRIPT_FILE=$0;; 9 | *) HOMER_SCRIPT_FILE=$PWD/$0;; 10 | esac 11 | 12 | # Load global configuration 13 | export HOMER_SCRIPT_PATH=$(dirname $HOMER_SCRIPT_FILE) 14 | export HOMER_PATH=$(dirname $HOMER_SCRIPT_PATH) 15 | export HOMER_COMMAND=$1 16 | export HOMER_EXECUTABLE=$HOMER_SCRIPT_PATH/homer-$HOMER_COMMAND 17 | 18 | if [ -z $HOMER_HOME ]; then 19 | export HOMER_HOME=$HOME 20 | fi 21 | 22 | pushd $HOMER_PATH 23 | export HOMER_PREFIX=$PWD 24 | popd 25 | 26 | # Execute the command or run `homer help` if not found. 27 | if [[ -e $HOMER_EXECUTABLE ]]; then 28 | source "$HOMER_EXECUTABLE" 29 | else 30 | source "$HOMER_SCRIPT_PATH/homer-help" 31 | fi 32 | -------------------------------------------------------------------------------- /bin/homer-alias: -------------------------------------------------------------------------------- 1 | #!/bin/zsh 2 | # 3 | # Add an alias to future shell sessions. 4 | 5 | source "$HOMER_PATH/share/homer/cli.zsh" 6 | 7 | name=$2 8 | cmd=$3 9 | 10 | if [[ -z $name || -z $cmd ]]; then 11 | homer_error "You must enter a name and command." 12 | exit 1 13 | fi 14 | 15 | zparseopts -D -E -- r=remove m:=message 16 | 17 | if [[ "$remove" == "-r" ]]; then 18 | action='Remove' 19 | else 20 | action='Add' 21 | fi 22 | 23 | if [[ -z $message ]]; then 24 | message="${action} alias ${name}" 25 | fi 26 | 27 | case "$action" in 28 | Add) 29 | line="alias ${name}='${cmd}'" 30 | echo "${line}" >> $HOMER_HOME/etc/aliases.zsh 31 | homer_add $HOMER_HOME/etc/aliases.zsh $message 32 | ;; 33 | Remove) 34 | sed "s/alias ${line}=.*$//" $HOMER_HOME/etc/aliases.zsh > /tmp/aliases 35 | mv /tmp/aliases $HOMER_HOME/aliases.zsh 36 | homer_add $HOMER_HOME/etc/aliases.zsh $message 37 | ;; 38 | esac 39 | -------------------------------------------------------------------------------- /bin/homer-grep: -------------------------------------------------------------------------------- 1 | #!/bin/zsh 2 | # 3 | # Run `git grep` on your home directory repo and Homer shared scripts 4 | # simultaneously. 5 | 6 | shift 7 | 8 | pushd $HOMER_HOME 9 | results=$(git grep --color='always' $*) 10 | popd 11 | 12 | for file in $(find $HOMER_PATH/share/homer/**/*.zsh); do 13 | results+=$(grep --color='always' -I $* $file /dev/null) 14 | done 15 | 16 | echo $results | less -r 17 | -------------------------------------------------------------------------------- /bin/homer-help: -------------------------------------------------------------------------------- 1 | #!/bin/zsh 2 | # 3 | # Show usage information or help with a particular command. 4 | 5 | # Set up the path at which we look for txt files describing each 6 | # command. 7 | HOMER_DOC_PATH=$HOMER_PREFIX/share/doc/homer 8 | 9 | # Determine the command to look up, defaults to USAGE if unspecified or 10 | # not found. 11 | if [[ -e $HOMER_DOC_PATH/$2.txt ]]; then 12 | docfile=$2 13 | else 14 | docfile="USAGE" 15 | fi 16 | 17 | echo "" 18 | cat $HOMER_DOC_PATH/$docfile.txt 19 | echo "" 20 | -------------------------------------------------------------------------------- /bin/homer-init: -------------------------------------------------------------------------------- 1 | #!/bin/zsh 2 | # 3 | # Copy home directory template files to the user's home directory and 4 | # initialize it as a Git repository. 5 | 6 | source "$HOMER_PATH/share/homer/cli.zsh" 7 | 8 | if [[ -e "$HOMER_HOME/.git" ]]; then 9 | homer_error "There is already an existing Git repository in $HOMER_HOME." 10 | exit 1 11 | fi 12 | 13 | zparseopts -K -- m:=message 14 | 15 | if [ -z "$message[2]" ]; then 16 | message="Initialize home directory." 17 | else 18 | message=$message[2] 19 | fi 20 | 21 | if [ ! -z "$2" ]; then 22 | repository=$2 23 | git clone --no-checkout $repository /tmp/homer 24 | pushd $HOMER_HOME 25 | mv /tmp/homer/.git .git 26 | git reset --hard HEAD 27 | popd 28 | else 29 | git init $HOMER_HOME 30 | cp -a $HOMER_PREFIX/share/homer/template/** $HOMER_HOME 31 | cp -a $HOMER_PREFIX/share/homer/template/.* $HOMER_HOME 32 | homer_add_all $message 33 | fi 34 | -------------------------------------------------------------------------------- /bin/homer-plugin: -------------------------------------------------------------------------------- 1 | #!zsh 2 | # 3 | # Install a shell plugin with Antigen, and save it in the 4 | # ~/etc/plugins file. 5 | 6 | plugin=$2 7 | file=$HOMER_HOME/etc/plugins.zsh 8 | 9 | source "$HOMER_PATH/share/homer/cli.zsh" 10 | 11 | if [[ -z $plugin ]]; then 12 | homer_error "You must specify a plugin." 13 | exit 1 14 | fi 15 | 16 | zparseopts -K -- m:=message r:=remove 17 | 18 | if [ -n "${remove+x}" ]; then 19 | action='Remove' 20 | else 21 | action='Add' 22 | fi 23 | 24 | if [[ -z $message ]]; then 25 | message="${action} ZSH plugin ${plugin}" 26 | fi 27 | 28 | case "$action" in 29 | Add) 30 | antigen bundle $plugin 31 | echo "antigen bundle $plugin" >> $file 32 | homer_add $file $message 33 | ;; 34 | Remove) 35 | sed "/antigen bundle $plugin/,/" $file 36 | source $file 37 | homer_remove $file $message 38 | ;; 39 | esac 40 | -------------------------------------------------------------------------------- /bin/homer-save: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env zsh 2 | # 3 | # Save a dotfile, either adding it for the first time or updating its 4 | # contents. 5 | 6 | file=$2 7 | 8 | source "$HOMER_PATH/share/homer/cli.zsh" 9 | 10 | zparseopts -E -- m:=message r=remove 11 | 12 | if [ $remove ]; then 13 | homer_remove $file $message[2] 14 | else 15 | homer_add $file $message[2] 16 | fi 17 | -------------------------------------------------------------------------------- /bin/homer-script: -------------------------------------------------------------------------------- 1 | #!/bin/zsh 2 | # 3 | # Copy a script to an executable $PATH 4 | 5 | source "$HOMER_PATH/share/homer/cli.zsh" 6 | 7 | script=$2 8 | 9 | zparseopts -D -E -- r=remove m:=message 10 | 11 | if [[ $remove == "-r" ]]; then 12 | action='Remove' 13 | else 14 | action='Add' 15 | fi 16 | 17 | if [[ -z $script ]]; then 18 | homer_error "You must enter the path to a script" 19 | exit 1 20 | fi 21 | 22 | name=$(basename $script) 23 | 24 | echo "msg: $message[2]" 25 | 26 | if [[ -z $message ]]; then 27 | message="${action} script ${name}" 28 | fi 29 | 30 | case "$action" in 31 | Add) 32 | cp $script $HOMER_HOME/bin/$name 33 | chmod +x $HOMER_HOME/bin/$name 34 | homer_add bin/$name $message 35 | ;; 36 | Remove) 37 | homer_remove bin/$name $message 38 | ;; 39 | esac 40 | -------------------------------------------------------------------------------- /bin/homer-update: -------------------------------------------------------------------------------- 1 | #!/bin/zsh 2 | # 3 | # Save a dotfile, either adding it for the first time or updating its 4 | # contents. 5 | 6 | source "$HOMER_PATH/share/homer/cli.zsh" 7 | 8 | homer_update_repo 9 | 10 | echo "Updated home directory $HOMER_HOME with the latest changes." 11 | -------------------------------------------------------------------------------- /bin/homer-version: -------------------------------------------------------------------------------- 1 | #!/bin/zsh 2 | # 3 | # Print the current version of Homer 4 | 5 | cat $HOMER_PATH/share/homer/VERSION 6 | -------------------------------------------------------------------------------- /docs/_config.yml: -------------------------------------------------------------------------------- 1 | --- 2 | theme: jekyll-theme-hacker 3 | title: homer 4 | description: the home directory manager for zsh 5 | -------------------------------------------------------------------------------- /docs/homer-thinking.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tubbo/homer/c6b5826ece60b192cbc616927d8030d864afbd6f/docs/homer-thinking.gif -------------------------------------------------------------------------------- /docs/index.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: homer 3 | layout: default 4 | --- 5 | 6 | Homer is a home directory manager for your shell. Using Git, it 7 | tracks changes in your home directory configuration from anywhere on 8 | your machine. Its goal is to uncover the IDE-like possibilities of the 9 | shell and make such features more approachable to newer users, while 10 | still retaining its usefulness to power users. 11 | 12 | Homer is an opinionated, but minimal, framework. While most of what 13 | it assumes about your environment is strongly enforced across the 14 | framework, it attempts to assume little about your system, instead 15 | allowing you to customize your shell the way you see fit. Homer's main 16 | philosophy is that having a stellar shell configuration should be 17 | much easier. 18 | 19 | The only requirement to run Homer is that you have the [Z Shell][zsh] 20 | installed. Homer is written entirely in ZSH shell script, and works best 21 | in a ZSH environment since it takes advantage of a number of its 22 | features. 23 | 24 | ## Features 25 | 26 | - **Conventional Directories:** Homer establishes a number of 27 | directories in your home directory, like `~/bin` and `~/etc`, for 28 | storing executable scripts and shell configuration. Drop new `.zsh` files in 29 | `~/etc/profile.d` to have them apply automatically when your shell is 30 | loaded. Homer ensures that `~/bin` is in your `$PATH` so the 31 | executable scripts in that directory are always available as extra 32 | commands in your shell. 33 | - **Dotfiles:** Save your configuration files directly where they need 34 | to be in your home directory from anywhere on the system. No need to 35 | mess around with symlink. 36 | - **Aliases:** Remembering long commands can be tough, and shell aliases 37 | are a built-in solution to that problem. Homer makes it easier to 38 | manage aliases from the `~/etc/aliases.zsh` directory, loaded in your 39 | shell automatically. 40 | - **ZSH Plugins:** One benefit to using ZSH is the vast amount of 41 | plugins that can be installed using Antigen, but managing these 42 | plugins can be somewhat difficult. Homer comes bundled with Antigen 43 | and manages the plugins you wish to install from your `~/etc/plugins.zsh` 44 | manifest file. 45 | - **Idempotency:** Homer can self-update, sync with a remote repository, 46 | and cleanly rehydrate the contents of a cloned repository into your home 47 | directory upon new installations. 48 | 49 | ## Installation 50 | 51 | Install with our handy-dandy script: 52 | 53 | ```bash 54 | $ curl -o- -L https://tubbo.github.io/homer/install.sh | bash 55 | ``` 56 | 57 | If you're on macOS, you can also install with Homebrew: 58 | 59 | ```bash 60 | $ brew tap tubbo/homebrew-tap 61 | $ brew install homer 62 | ``` 63 | 64 | ## Setup 65 | 66 | Once Homer is installed, you can use it to either create a new 67 | repository for persisting your configuration, or you can pull down an 68 | existing repository and extract it on top of the existing home directory 69 | on your machine. 70 | 71 | To create a new home directory repo: 72 | 73 | ```bash 74 | $ homer init 75 | ``` 76 | 77 | Otherwise, provide the URL to your existing home directory repo: 78 | 79 | ```bash 80 | $ homer init https://github.com/your/home-dir.git 81 | ``` 82 | 83 | After these commands are run, your home directory will be set up for use 84 | with Homer! 85 | 86 | ## Usage 87 | 88 | To learn how to use Homer, check out the [README][], run `man homer` 89 | to view command-line documentation, or view the manpages online: 90 | 91 | - [homer(1)][] 92 | - [edit(1)][] 93 | - [page(1)][] 94 | 95 | [README]: https://github.com/tubbo/homer#homer 96 | [homer(1)]: manual/homer.1.html 97 | [edit(1)]: manual/edit.1.html 98 | [page(1)]: manual/page.1.html 99 | -------------------------------------------------------------------------------- /docs/install.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # 3 | # Install Homer on the system. Note that this is _not_ a ZSH script, 4 | # because ZSH may not actually be on the system yet. We can be pretty 5 | # sure that Bash will be there, though, so that's why this script is 6 | # written in Bash instead of ZSH. 7 | 8 | # Find latest released version from GitHub API 9 | repo="https://api.github.com/repos/tubbo/homer/releases/latest" 10 | version=$(curl --silent "$repo" | grep '"tag_name":' | sed -E 's/.*"([^"]+)".*/\1/') 11 | tmpdir=$(mktemp -d) 12 | sourcedir="homer-${version:1}" 13 | filename="homer-$version.tar.gz" 14 | 15 | pushd "$tmpdir" > /dev/null 2>&1 16 | 17 | # Ensure source code is in place 18 | echo "Downloading Homer $version from GitHub..." 19 | curl -sL "https://github.com/tubbo/homer/archive/$version.tar.gz" -o "$filename" 20 | 21 | # Extract source code from tarball 22 | tar -zxf "$filename" 23 | 24 | # Install homer from source to /usr/local and capture exit code 25 | pushd "$sourcedir" > /dev/null 2>&1 26 | echo "Installing Homer..." 27 | make install 28 | code=$? 29 | 30 | # Print whether Homer was installed or not 31 | if [[ "$code" == 0 ]]; then 32 | echo "Homer $version has been installed!" 33 | echo "Get started by running \`homer init [REPO]\`" 34 | echo "Or, run \`homer\` to see the full list of commands" 35 | else 36 | echo "Error installing Homer" 37 | fi 38 | 39 | # Clean up the source directory 40 | popd > /dev/null 2>&1 41 | popd > /dev/null 2>&1 42 | rm -rf "$tmpdir" 43 | 44 | exit $code 45 | -------------------------------------------------------------------------------- /docs/manual/edit.1.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | edit(1) - Open files for editing and manipulating 7 | 44 | 55 | 56 | 63 | 64 |
65 | 66 | 76 | 77 |
    78 |
  1. edit(1)
  2. 79 |
  3. User Manual
  4. 80 |
  5. edit(1)
  6. 81 |
82 | 83 |

NAME

84 |

85 | edit - Open files for editing and manipulating 86 |

87 | 88 |

SYNOPSIS

89 | 90 |

edit ARGUMENTS

91 | 92 |

DESCRIPTION

93 | 94 |

The edit utility is used to open and edit files using your 95 | configured editor. It's a quick time-saver that uses the configured 96 | $EDITOR in your shell for editing files. All arguments passed into 97 | this utility will be passed onward to the configured shell editor 98 | program.

99 | 100 |

edit is provided by homer. For more information, check out:

101 | 102 |

https://github.com/tubbo/homer#readme

103 | 104 |

ARGUMENTS

105 | 106 |

ARGUMENTS 107 | Arguments passed to the editor.

108 | 109 |

EXAMPLES

110 | 111 |

Open a file with your editor:

112 | 113 |
edit path/to/my/file.txt
114 | 
115 | 116 |

CONFIGURATION

117 | 118 |

To configure which program is opened when the edit command is run, set 119 | the $EDITOR variable in your shell like so:

120 | 121 |
export EDITOR=vim
122 | 
123 | 124 |

(Homer will do this for you in ~/.zshenv)

125 | 126 |

AUTHOR

127 | 128 |

Tom Scott http://psychedeli.ca

129 | 130 |

SEE ALSO

131 | 132 |

homer(1) 133 | page(1)

134 | 135 | 136 |
    137 |
  1. homer
  2. 138 |
  3. November 2014
  4. 139 |
  5. edit(1)
  6. 140 |
141 | 142 |
143 | 144 | 145 | -------------------------------------------------------------------------------- /docs/manual/homer.1.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | homer(1) - your home directory manager 7 | 44 | 55 | 56 | 63 | 64 |
65 | 66 | 76 | 77 |
    78 |
  1. homer(1)
  2. 79 |
  3. User Manual
  4. 80 |
  5. homer(1)
  6. 81 |
82 | 83 |

NAME

84 |

85 | homer - your home directory manager 86 |

87 | 88 |

SYNOPSIS

89 | 90 |

homer COMMAND ARGUMENTS

91 | 92 |

DESCRIPTION

93 | 94 |

Homer is a command-line utility to manage your shell's home directory. 95 | It turns your entire home directory into a Git repo so you can 96 | version control non-sensitive configuration and data and synchronize 97 | them across machines. It also includes provisions for installing custom 98 | shell scripts, aliases and hooks for package management tooling. Homer 99 | is designed around the Unix philosophy, and stays out of your way as 100 | much as possible. It is written entirely in ZSH shell script.

101 | 102 |

For more information, check out:

103 | 104 |

https://github.com/tubbo/homer#readme

105 | 106 |

ARGUMENTS

107 | 108 |

COMMAND 109 | The command you wish to run.

110 | 111 |

ARGUMENTS 112 | Arguments for said command.

113 | 114 |

EXAMPLES

115 | 116 |

Initialize your home directory as a new repo:

117 | 118 |
homer init
119 | 
120 | 121 |

Or, clone an existing home directory repo:

122 | 123 |
homer init -c https://github.com/me/home.git
124 | 
125 | 126 |

You can now save dotfiles to the repo:

127 | 128 |
homer save .vimrc -m "Removed vim-rails"
129 | 
130 | 131 |

Or, sync with your Git repo if you made changes elsewhere:

132 | 133 |
homer update
134 | 
135 | 136 |

Homer can even upgrade itself using the latest GitHub release:

137 | 138 |
homer upgrade
139 | 
140 | 141 |

Shell Plugins

142 | 143 |

Homer also provides an easy way to manage ZSH plugins with Antigen. 144 | These plugins are automatically installed when you init your home 145 | directory on a new machine.

146 | 147 |
homer plugin zsh-users/zsh-syntax-highlighting
148 | 
149 | 150 |

You can also remove shell plugins from the manifest:

151 | 152 |
homer plugin zsh-users/zsh-syntax-highlighting -r
153 | 
154 | 155 |

Homer manages an ~/etc/aliases file that includes your shell aliases. 156 | To add one, run the following command:

157 | 158 |
homer alias gc 'git commit'
159 | 
160 | 161 |

Or, forget an alias:

162 | 163 |
homer alias gc -r
164 | 
165 | 166 |

NOTE: The shell will need to be reloaded in order for alias changes 167 | to take effect.

168 | 169 |

User Scripts

170 | 171 |

Homer establishes a ~/bin directory for useful scripts that you might 172 | need access to as commands. This directory is added to $PATH so that 173 | its executable contents can be used as commands across the system.

174 | 175 |

Adding a new command

176 | 177 |
homer script path/to/your/script/find-and-replace-in-project
178 | 
179 | 180 |

You can now use the script as if it was a command:

181 | 182 |
find-and-replace-in-project
183 | 
184 | 185 |

To remove the script from ~/bin:

186 | 187 |
homer script find-and-replace-in-project -r
188 | 
189 | 190 |

GENERATED FILES

191 | 192 |

The following files are generated when you run the homer init 193 | command...

194 | 195 |

~/bin: User scripts directory. Added to your $PATH automatically.

196 | 197 |

~/etc/profile.d/: User configs directory

198 | 199 |

~/etc/plugins.zsh: Plugins configuration

200 | 201 |

~/etc/aliases.zsh: User aliases configuration

202 | 203 |

AUTHOR

204 | 205 |

Tom Scott http://psychedeli.ca

206 | 207 |

SEE ALSO

208 | 209 |

antigen(1) 210 | zsh(1) 211 | git(1)

212 | 213 | 214 |
    215 |
  1. homer
  2. 216 |
  3. November 2014
  4. 217 |
  5. homer(1)
  6. 218 |
219 | 220 |
221 | 222 | 223 | -------------------------------------------------------------------------------- /docs/manual/index.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: homer - manual 3 | layout: default 4 | --- 5 | 6 | - [homer][] 7 | - [edit][] 8 | - [page][] 9 | 10 | [homer]: manual/homer.1.html 11 | [edit]: manual/edit.1.html 12 | [page]: manual/page.1.html 13 | -------------------------------------------------------------------------------- /docs/manual/page.1.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | page(1) - Open files for viewing and reading in realtime 7 | 44 | 55 | 56 | 63 | 64 |
65 | 66 | 76 | 77 |
    78 |
  1. page(1)
  2. 79 |
  3. User Manual
  4. 80 |
  5. page(1)
  6. 81 |
82 | 83 |

NAME

84 |

85 | page - Open files for viewing and reading in realtime 86 |

87 | 88 |

SYNOPSIS

89 | 90 |

page ARGUMENTS

91 | 92 |

DESCRIPTION

93 | 94 |

The page command is used to open files for viewing using your 95 | configured pager program, such as less. It's a quick time-saver that 96 | uses the $PAGER variable in your shell for viewing files quickly, or 97 | in real-time as they are updated. All arguments passed into this utility 98 | will be passed onward to the configured shell pager program.

99 | 100 |

page is provided by homer. For more information, check out:

101 | 102 |

https://github.com/tubbo/homer#readme

103 | 104 |

ARGUMENTS

105 | 106 |

ARGUMENTS 107 | Arguments passed to the pager.

108 | 109 |

EXAMPLES

110 | 111 |

Open a file with your pager:

112 | 113 |
page /var/log/system.log
114 | 
115 | 116 |

CONFIGURATION

117 | 118 |

To configure which program is opened when the page command is run, set 119 | the $PAGER variable in your shell like so:

120 | 121 |
export PAGER="less -r"
122 | 
123 | 124 |

(Homer will do this for you in ~/.zshenv)

125 | 126 |

AUTHOR

127 | 128 |

Tom Scott http://psychedeli.ca

129 | 130 |

SEE ALSO

131 | 132 |

homer(1) 133 | edit(1)

134 | 135 | 136 |
    137 |
  1. homer
  2. 138 |
  3. November 2014
  4. 139 |
  5. page(1)
  6. 140 |
141 | 142 |
143 | 144 | 145 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "homer", 3 | "version": "0.1.1", 4 | "description": "The home directory manager and ZSH framework", 5 | "install": "make install", 6 | "dependencies": { 7 | "bats": "^1.1.0", 8 | "bats-assert": "https://github.com/ztombol/bats-assert", 9 | "bats-file": "https://github.com/ztombol/bats-file", 10 | "bats-support": "https://github.com/ztombol/bats-support" 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /share/doc/homer/USAGE.txt: -------------------------------------------------------------------------------- 1 | Usage: homer COMMAND [ARGUMENTS] 2 | 3 | Homer is your home directory manager. It helps manage things like 4 | plugins, aliases, and dotfiles. For more information on this software, 5 | type `man homer`. 6 | 7 | Commands: 8 | 9 | - alias Save an alias in ~/etc/aliases.zsh. 10 | - grep Search Homer shared source and your own configs simultaneously 11 | - help View this and other command help. 12 | - init Initialize a home directory. Use -c to clone an existing 13 | home directory repo. 14 | - plugin Install a plugin with Antigen to ~/etc/plugins.zsh. 15 | - save Commit changes to the repo and push to origin. 16 | - script Save a bin script to the repo. 17 | - update Update the repo and stash current changes. 18 | - version Print the current version of Homer 19 | 20 | Type `homer help COMMAND` to get help on a particular command. 21 | -------------------------------------------------------------------------------- /share/doc/homer/alias.txt: -------------------------------------------------------------------------------- 1 | homer alias NAME [COMMAND] [options] 2 | 3 | Saves an alias to ~/etc/aliases.zsh for future shell sessions. Has the 4 | option of removing the file and customizing the commit message. 5 | 6 | OPTIONS: 7 | 8 | -r Removes the alias (by name) from ~/etc/aliases.zsh 9 | 10 | -m MESSAGE an optional message to pass to the Git commit 11 | -------------------------------------------------------------------------------- /share/doc/homer/grep.txt: -------------------------------------------------------------------------------- 1 | homer grep [OPTIONS] PATTERN [FILES] 2 | 3 | Searches your home directory repo with `git grep` and the Homer shared 4 | ZSH source with `grep`, then combines search results together. This 5 | command passes all options and arguments to `git grep` and `grep`. 6 | -------------------------------------------------------------------------------- /share/doc/homer/init.txt: -------------------------------------------------------------------------------- 1 | homer init [REPOSITORY] [options] 2 | 3 | Sets up your home directory for use with Homer. By default, it 4 | initializes a new Git repo in $HOME and copies in the base template 5 | files/directories, but you can optionally pass in a remote Git repo URL 6 | to form the base for your home directory configuration. This is useful 7 | if you maintain a "dotfiles" repo and want to copy your configuration 8 | between machines. 9 | 10 | OPTIONS: 11 | 12 | -m MESSAGE Customize the initial message when committing to Git. 13 | -------------------------------------------------------------------------------- /share/doc/homer/plugin.txt: -------------------------------------------------------------------------------- 1 | homer plugin NAME [options] 2 | 3 | Installs (or uninstalls) plugins for ZSH. Essentially a 4 | lightweight command-line interface for Antigen, this command manages its 5 | dependencies in your ~/etc/plugins.zsh file and can remove dependencies 6 | as well. 7 | 8 | OPTIONS: 9 | 10 | -r Remove this plugin from ~/etc/aliases.zsh instead of adding it. 11 | 12 | -m MESSAGE Customize the Git message for this action. 13 | -------------------------------------------------------------------------------- /share/doc/homer/save.txt: -------------------------------------------------------------------------------- 1 | homer save FILE [options] 2 | 3 | Save a file in your home directory to the Git repo. By default, all 4 | files in your home directory are ignored, allowing you to "whitelist" 5 | the files you which to store in Git, and the `homer save` command makes 6 | it easy to add or commit files to the repo. 7 | 8 | OPTIONS: 9 | 10 | -m MESSAGE MESSAGE Add a short commit message describing the change. 11 | -r Remove this file from the repo. 12 | -------------------------------------------------------------------------------- /share/doc/homer/script.txt: -------------------------------------------------------------------------------- 1 | homer script FILE [options] 2 | 3 | Copy a script from the given file path to ~/bin in your home directory, 4 | and add the script to Git using `homer save`. You can also remove 5 | scripts. 6 | 7 | OPTIONS: 8 | 9 | -r Remove a script 10 | -m MESSAGE MESSAGE Add a short message to be passed to `homer save`. 11 | -------------------------------------------------------------------------------- /share/doc/homer/update.txt: -------------------------------------------------------------------------------- 1 | homer update 2 | 3 | Synchronizes your home directory repo with its 'origin' remote. Stashes 4 | any unsaved changes, pulls (with rebase) from 'origin/master', then pops 5 | the changes saved in stash out so they can be committed if necessary. 6 | -------------------------------------------------------------------------------- /share/doc/homer/version.txt: -------------------------------------------------------------------------------- 1 | homer version 2 | 3 | Print the current version of Homer. 4 | -------------------------------------------------------------------------------- /share/doc/man/edit.1.md: -------------------------------------------------------------------------------- 1 | edit(1) - Open files for editing and manipulating 2 | ================================================= 3 | 4 | ## SYNOPSIS 5 | 6 | `edit` [ARGUMENTS] 7 | 8 | ## DESCRIPTION 9 | 10 | The **edit** utility is used to open and edit files using your 11 | configured editor. It's a quick time-saver that uses the configured 12 | **$EDITOR** in your shell for editing files. All arguments passed into 13 | this utility will be passed onward to the configured shell editor 14 | program. 15 | 16 | **edit** is provided by **homer**. For more information, check out: 17 | 18 | https://github.com/tubbo/homer#readme 19 | 20 | ## ARGUMENTS 21 | 22 | *ARGUMENTS* 23 | Arguments passed to the editor. 24 | 25 | ## EXAMPLES 26 | 27 | Open a file with your editor: 28 | 29 | ``` 30 | edit path/to/my/file.txt 31 | ``` 32 | 33 | ## CONFIGURATION 34 | 35 | To configure which program is opened when the `edit` command is run, set 36 | the **$EDITOR** variable in your shell like so: 37 | 38 | ``` 39 | export EDITOR=vim 40 | ``` 41 | 42 | (Homer will do this for you in `~/.zshenv`) 43 | 44 | ## AUTHOR 45 | 46 | Tom Scott 47 | 48 | ## SEE ALSO 49 | 50 | homer(1) 51 | page(1) 52 | -------------------------------------------------------------------------------- /share/doc/man/homer.1.md: -------------------------------------------------------------------------------- 1 | homer(1) - your home directory manager 2 | ====================================== 3 | 4 | ## SYNOPSIS 5 | 6 | `homer` COMMAND [ARGUMENTS] 7 | 8 | ## DESCRIPTION 9 | 10 | Homer is a command-line utility to manage your shell's home directory. 11 | It turns your entire home directory into a Git repo so you can 12 | version control non-sensitive configuration and data and synchronize 13 | them across machines. It also includes provisions for installing custom 14 | shell scripts, aliases and hooks for package management tooling. Homer 15 | is designed around the Unix philosophy, and stays out of your way as 16 | much as possible. It is written entirely in ZSH shell script. 17 | 18 | For more information, check out: 19 | 20 | https://github.com/tubbo/homer#readme 21 | 22 | ## ARGUMENTS 23 | 24 | *COMMAND* 25 | The command you wish to run. 26 | 27 | *ARGUMENTS* 28 | Arguments for said command. 29 | 30 | ## EXAMPLES 31 | 32 | Initialize your home directory as a new repo: 33 | 34 | ``` 35 | homer init 36 | ``` 37 | 38 | Or, clone an existing home directory repo: 39 | 40 | 41 | ``` 42 | homer init -c https://github.com/me/home.git 43 | ``` 44 | 45 | You can now save dotfiles to the repo: 46 | 47 | ``` 48 | homer save .vimrc -m "Removed vim-rails" 49 | ``` 50 | 51 | Or, sync with your Git repo if you made changes elsewhere: 52 | 53 | ``` 54 | homer update 55 | ``` 56 | 57 | Homer can even upgrade itself using the latest GitHub release: 58 | 59 | ``` 60 | homer upgrade 61 | ``` 62 | 63 | ### Shell Plugins 64 | 65 | Homer also provides an easy way to manage ZSH plugins with Antigen. 66 | These plugins are automatically installed when you `init` your home 67 | directory on a new machine. 68 | 69 | ``` 70 | homer plugin zsh-users/zsh-syntax-highlighting 71 | ``` 72 | 73 | You can also remove shell plugins from the manifest: 74 | 75 | ``` 76 | homer plugin zsh-users/zsh-syntax-highlighting -r 77 | ``` 78 | 79 | Homer manages an `~/etc/aliases` file that includes your shell aliases. 80 | To add one, run the following command: 81 | 82 | ``` 83 | homer alias gc 'git commit' 84 | ``` 85 | 86 | Or, forget an alias: 87 | 88 | ``` 89 | homer alias gc -r 90 | ``` 91 | 92 | **NOTE:** The shell will need to be reloaded in order for alias changes 93 | to take effect. 94 | 95 | ### User Scripts 96 | 97 | Homer establishes a `~/bin` directory for useful scripts that you might 98 | need access to as commands. This directory is added to `$PATH` so that 99 | its executable contents can be used as commands across the system. 100 | 101 | Adding a new command 102 | 103 | ``` 104 | homer script path/to/your/script/find-and-replace-in-project 105 | ``` 106 | 107 | You can now use the script as if it was a command: 108 | 109 | ``` 110 | find-and-replace-in-project 111 | ``` 112 | 113 | To remove the script from `~/bin`: 114 | 115 | ``` 116 | homer script find-and-replace-in-project -r 117 | ``` 118 | 119 | ## GENERATED FILES 120 | 121 | The following files are generated when you run the `homer init` 122 | command... 123 | 124 | *~/bin:* User scripts directory. Added to your `$PATH` automatically. 125 | 126 | *~/etc/profile.d/:* User configs directory 127 | 128 | *~/etc/plugins.zsh:* Plugins configuration 129 | 130 | *~/etc/aliases.zsh:* User aliases configuration 131 | 132 | 133 | ## AUTHOR 134 | 135 | Tom Scott 136 | 137 | ## SEE ALSO 138 | 139 | antigen(1) 140 | zsh(1) 141 | git(1) 142 | -------------------------------------------------------------------------------- /share/doc/man/page.1.md: -------------------------------------------------------------------------------- 1 | page(1) - Open files for viewing and reading in realtime 2 | ======================================================== 3 | 4 | ## SYNOPSIS 5 | 6 | `page` [ARGUMENTS] 7 | 8 | ## DESCRIPTION 9 | 10 | The **page** command is used to open files for viewing using your 11 | configured pager program, such as `less`. It's a quick time-saver that 12 | uses the **$PAGER** variable in your shell for viewing files quickly, or 13 | in real-time as they are updated. All arguments passed into this utility 14 | will be passed onward to the configured shell pager program. 15 | 16 | **page** is provided by **homer**. For more information, check out: 17 | 18 | https://github.com/tubbo/homer#readme 19 | 20 | ## ARGUMENTS 21 | 22 | *ARGUMENTS* 23 | Arguments passed to the pager. 24 | 25 | ## EXAMPLES 26 | 27 | Open a file with your pager: 28 | 29 | ``` 30 | page /var/log/system.log 31 | ``` 32 | 33 | ## CONFIGURATION 34 | 35 | To configure which program is opened when the `page` command is run, set 36 | the **$PAGER** variable in your shell like so: 37 | 38 | ``` 39 | export PAGER="less -r" 40 | ``` 41 | 42 | (Homer will do this for you in `~/.zshenv`) 43 | 44 | ## AUTHOR 45 | 46 | Tom Scott 47 | 48 | ## SEE ALSO 49 | 50 | homer(1) 51 | edit(1) 52 | -------------------------------------------------------------------------------- /share/homer.zsh: -------------------------------------------------------------------------------- 1 | #!/bin/zsh 2 | # 3 | # Set up the Homer shell framework. 4 | 5 | # Remember the path to homer's code 6 | if [ -z $HOMER_PREFIX ]; then 7 | export HOMER_PREFIX="/usr/local" 8 | fi 9 | 10 | # Use a copy of the $HOME alias if no home path defined 11 | if [ -z $HOMER_HOME ]; then 12 | export HOMER_HOME=$HOME 13 | fi 14 | 15 | # Configure a basic prompt string 16 | export PROMPT="♬ " 17 | 18 | # Add user path on top so ~/bin files override the main $PATHs. 19 | export PATH=$HOME/bin:$PATH 20 | export HOMER_PATH=$HOMER_PREFIX/share/homer 21 | 22 | # Load the framework 23 | for filepath in `find $HOMER_PATH/profile.d -type f`; do 24 | source "$filepath" 25 | done 26 | 27 | # Load user plugins 28 | source "$HOMER_HOME/etc/plugins.zsh" 29 | 30 | # Load user aliases 31 | source "$HOMER_HOME/etc/aliases.zsh" 32 | 33 | # Load user profile configuration 34 | for file in `ls $HOMER_HOME/etc/profile.d`; do 35 | source "$HOMER_HOME/etc/profile.d/$file" 36 | done 37 | -------------------------------------------------------------------------------- /share/homer/VERSION: -------------------------------------------------------------------------------- 1 | v0.1.1 2 | -------------------------------------------------------------------------------- /share/homer/cli.zsh: -------------------------------------------------------------------------------- 1 | #!/bin/zsh 2 | # 3 | # Commands that help support Homer's CLI. 4 | 5 | # Render an error. 6 | homer_error() { 7 | message=$1 8 | echo "ERROR: $message" 9 | } 10 | 11 | # Save a file to Git. 12 | homer_add() { 13 | file=$1 14 | message=$2 15 | 16 | if [[ -z $message ]]; then 17 | echo "You must enter a message." 18 | exit 1 19 | fi 20 | 21 | pushd $HOMER_HOME 22 | git add -f $file && git commit $file -m "${message}" 23 | popd 24 | } 25 | 26 | # Remove a file from Git. 27 | homer_remove() { 28 | file=$1 29 | message=$2 30 | 31 | if [[ -z $message ]]; then 32 | echo "You must enter a message." 33 | exit 1 34 | fi 35 | 36 | pushd $HOMER_HOME 37 | git rm -rf $file && git commit -m "${message}" 38 | popd 39 | } 40 | 41 | # Commit all untracked files to Git. 42 | homer_add_all() { 43 | message=$1 44 | pushd $HOMER_HOME 45 | git add -f . && git commit -m "${message}" 46 | popd 47 | } 48 | 49 | # Update the git repo in the home directory with the latest changes from 50 | # GitHub. 51 | homer_update_repo() { 52 | pushd $HOMER_HOME 53 | git stash save 54 | git pull --rebase origin master 55 | git push origin master 56 | git stash pop 57 | popd 58 | } 59 | -------------------------------------------------------------------------------- /share/homer/command/bin.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env homer 2 | # 3 | # Short description of the command 4 | 5 | name=$1 6 | 7 | if [[ -z $name ]]; then 8 | echo "You must enter a name" 9 | exit 1 10 | fi 11 | 12 | zparseopts -K -- r:=remove m:=message 13 | 14 | if [ -n "${remove+x}" ]; then 15 | action='Remove' 16 | else 17 | action='Add' 18 | fi 19 | 20 | if [[ -z $message ]]; then 21 | message="${action} COMMAND ${name}" 22 | fi 23 | 24 | case "$action" in 25 | Add) 26 | ;; 27 | Remove) 28 | ;; 29 | esac 30 | -------------------------------------------------------------------------------- /share/homer/command/doc.txt: -------------------------------------------------------------------------------- 1 | homer COMMAND [options] 2 | 3 | Short description of the command. 4 | 5 | OPTIONS: 6 | 7 | -r Remove 8 | -m (optional) A short message for the commit. 9 | -------------------------------------------------------------------------------- /share/homer/command/test.bats: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bats 2 | 3 | load test_helper 4 | 5 | test "your new command" { 6 | assert [ "it works" ] 7 | } 8 | -------------------------------------------------------------------------------- /share/homer/profile.d/editing.zsh: -------------------------------------------------------------------------------- 1 | #!/bin/zsh 2 | # 3 | # Configuration for text editing. 4 | 5 | if [ -n "${EDITOR+x}" ]; then 6 | # do nothing, var is set 7 | else 8 | EDITOR='vi' 9 | fi 10 | 11 | if [ -n "${PAGER+x}" ]; then 12 | # do nothing, var is set 13 | else 14 | # use the posix-compliant variant 15 | PAGER='less' 16 | fi 17 | 18 | # Execute as the configured editor. 19 | edit() { 20 | if [ -z "$*" ]; then 21 | $EDITOR . 22 | else 23 | $EDITOR $* 24 | fi 25 | } 26 | alias e=edit 27 | 28 | # Execute as the configured pager. 29 | page() { 30 | $PAGER $* 31 | } 32 | alias v=page 33 | 34 | # Print a given string. 35 | alias p=echo 36 | 37 | # Clear the screen 38 | alias c=clear 39 | -------------------------------------------------------------------------------- /share/homer/profile.d/paths.zsh: -------------------------------------------------------------------------------- 1 | #!/bin/zsh 2 | 3 | # Cache the path laid out in this file and `reset_path` if the shell 4 | # gets confused. 5 | export DEFAULT_PATH=$PATH 6 | alias reset_path='export PATH=$DEFAULT_PATH' 7 | -------------------------------------------------------------------------------- /share/homer/profile.d/shell.zsh: -------------------------------------------------------------------------------- 1 | #!/bin/zsh 2 | # 3 | # Configuration for ZSH, the underlying shell 4 | 5 | # Use ZSH online help 6 | unalias run-help 7 | autoload run-help 8 | HELPDIR=/usr/local/share/zsh/helpfiles 9 | 10 | # Enable vi mode 11 | bindkey -v 12 | 13 | # Re-bind history search actions so that the text already typed into 14 | # the prompt is used to filter results. When typing "rake" into the 15 | # prompt and hitting the up arrow, only results that match /^rake/ 16 | # will be returned. 17 | bindkey '^R' history-incremental-search-backward 18 | bindkey '\e[A' history-beginning-search-backward 19 | bindkey '\e[B' history-beginning-search-forward 20 | 21 | # SSH agent forwarding 22 | zstyle :omz:plugins:ssh-agent agent-forwarding on 23 | -------------------------------------------------------------------------------- /share/homer/profile.d/terminal.zsh: -------------------------------------------------------------------------------- 1 | #!/bin/zsh 2 | # 3 | # Configuration for the terminal emulator using this shell. 4 | 5 | # Force 256 color terminals 6 | TERM=screen-256color 7 | 8 | # Don't set iTerm/Terminal's title automatically. 9 | DISABLE_AUTO_TITLE="true" 10 | 11 | # Display red dots when ZSH is hanging. 12 | COMPLETION_WAITING_DOTS="true" 13 | 14 | # Set the title of the current terminal session 15 | title() { 16 | print -Pn "\033];$1\007"; 17 | } 18 | alias t=title 19 | -------------------------------------------------------------------------------- /share/homer/profile.d/vcsinfo.zsh: -------------------------------------------------------------------------------- 1 | #!/bin/zsh 2 | # 3 | # Git commands for the prompt. 4 | 5 | # get the name of the branch we are on 6 | function git_prompt_info() { 7 | if [[ "$(command git config --get oh-my-zsh.hide-status 2>/dev/null)" != "1" ]]; then 8 | ref=$(command git symbolic-ref HEAD 2> /dev/null) || \ 9 | ref=$(command git rev-parse --short HEAD 2> /dev/null) || return 0 10 | echo "$ZSH_THEME_GIT_PROMPT_PREFIX${ref#refs/heads/}$(parse_git_dirty)$ZSH_THEME_GIT_PROMPT_SUFFIX" 11 | fi 12 | } 13 | 14 | 15 | # Checks if working tree is dirty 16 | parse_git_dirty() { 17 | local STATUS='' 18 | local FLAGS 19 | FLAGS=('--porcelain') 20 | if [[ "$(command git config --get oh-my-zsh.hide-dirty)" != "1" ]]; then 21 | if [[ $POST_1_7_2_GIT -gt 0 ]]; then 22 | FLAGS+='--ignore-submodules=dirty' 23 | fi 24 | if [[ "$DISABLE_UNTRACKED_FILES_DIRTY" == "true" ]]; then 25 | FLAGS+='--untracked-files=no' 26 | fi 27 | STATUS=$(command git status ${FLAGS} 2> /dev/null | tail -n1) 28 | fi 29 | if [[ -n $STATUS ]]; then 30 | echo "$ZSH_THEME_GIT_PROMPT_DIRTY" 31 | else 32 | echo "$ZSH_THEME_GIT_PROMPT_CLEAN" 33 | fi 34 | } 35 | 36 | # get the difference between the local and remote branches 37 | git_remote_status() { 38 | remote=${$(command git rev-parse --verify ${hook_com[branch]}@{upstream} --symbolic-full-name 2>/dev/null)/refs\/remotes\/} 39 | if [[ -n ${remote} ]] ; then 40 | ahead=$(command git rev-list ${hook_com[branch]}@{upstream}..HEAD 2>/dev/null | wc -l) 41 | behind=$(command git rev-list HEAD..${hook_com[branch]}@{upstream} 2>/dev/null | wc -l) 42 | 43 | if [ $ahead -eq 0 ] && [ $behind -gt 0 ] 44 | then 45 | echo "$ZSH_THEME_GIT_PROMPT_BEHIND_REMOTE" 46 | elif [ $ahead -gt 0 ] && [ $behind -eq 0 ] 47 | then 48 | echo "$ZSH_THEME_GIT_PROMPT_AHEAD_REMOTE" 49 | elif [ $ahead -gt 0 ] && [ $behind -gt 0 ] 50 | then 51 | echo "$ZSH_THEME_GIT_PROMPT_DIVERGED_REMOTE" 52 | fi 53 | fi 54 | } 55 | 56 | # Checks if there are commits ahead from remote 57 | function git_prompt_ahead() { 58 | if $(echo "$(command git log @{upstream}..HEAD 2> /dev/null)" | grep '^commit' &> /dev/null); then 59 | echo "$ZSH_THEME_GIT_PROMPT_AHEAD" 60 | fi 61 | } 62 | 63 | # Gets the number of commits ahead from remote 64 | function git_commits_ahead() { 65 | if $(echo "$(command git log @{upstream}..HEAD 2> /dev/null)" | grep '^commit' &> /dev/null); then 66 | COMMITS=$(command git log @{upstream}..HEAD | grep '^commit' | wc -l | tr -d ' ') 67 | echo "$ZSH_THEME_GIT_COMMITS_AHEAD_PREFIX$COMMITS$ZSH_THEME_GIT_COMMITS_AHEAD_SUFFIX" 68 | fi 69 | } 70 | 71 | # Formats prompt string for current git commit short SHA 72 | function git_prompt_short_sha() { 73 | SHA=$(command git rev-parse --short HEAD 2> /dev/null) && echo "$ZSH_THEME_GIT_PROMPT_SHA_BEFORE$SHA$ZSH_THEME_GIT_PROMPT_SHA_AFTER" 74 | } 75 | 76 | # Formats prompt string for current git commit long SHA 77 | function git_prompt_long_sha() { 78 | SHA=$(command git rev-parse HEAD 2> /dev/null) && echo "$ZSH_THEME_GIT_PROMPT_SHA_BEFORE$SHA$ZSH_THEME_GIT_PROMPT_SHA_AFTER" 79 | } 80 | 81 | # Get the status of the working tree 82 | git_prompt_status() { 83 | INDEX=$(command git status --porcelain -b 2> /dev/null) 84 | STATUS="" 85 | if $(echo "$INDEX" | command grep -E '^\?\? ' &> /dev/null); then 86 | STATUS="$ZSH_THEME_GIT_PROMPT_UNTRACKED$STATUS" 87 | fi 88 | if $(echo "$INDEX" | grep '^A ' &> /dev/null); then 89 | STATUS="$ZSH_THEME_GIT_PROMPT_ADDED$STATUS" 90 | elif $(echo "$INDEX" | grep '^M ' &> /dev/null); then 91 | STATUS="$ZSH_THEME_GIT_PROMPT_ADDED$STATUS" 92 | fi 93 | if $(echo "$INDEX" | grep '^ M ' &> /dev/null); then 94 | STATUS="$ZSH_THEME_GIT_PROMPT_MODIFIED$STATUS" 95 | elif $(echo "$INDEX" | grep '^AM ' &> /dev/null); then 96 | STATUS="$ZSH_THEME_GIT_PROMPT_MODIFIED$STATUS" 97 | elif $(echo "$INDEX" | grep '^ T ' &> /dev/null); then 98 | STATUS="$ZSH_THEME_GIT_PROMPT_MODIFIED$STATUS" 99 | fi 100 | if $(echo "$INDEX" | grep '^R ' &> /dev/null); then 101 | STATUS="$ZSH_THEME_GIT_PROMPT_RENAMED$STATUS" 102 | fi 103 | if $(echo "$INDEX" | grep '^ D ' &> /dev/null); then 104 | STATUS="$ZSH_THEME_GIT_PROMPT_DELETED$STATUS" 105 | elif $(echo "$INDEX" | grep '^D ' &> /dev/null); then 106 | STATUS="$ZSH_THEME_GIT_PROMPT_DELETED$STATUS" 107 | elif $(echo "$INDEX" | grep '^AD ' &> /dev/null); then 108 | STATUS="$ZSH_THEME_GIT_PROMPT_DELETED$STATUS" 109 | fi 110 | if $(command git rev-parse --verify refs/stash >/dev/null 2>&1); then 111 | STATUS="$ZSH_THEME_GIT_PROMPT_STASHED$STATUS" 112 | fi 113 | if $(echo "$INDEX" | grep '^UU ' &> /dev/null); then 114 | STATUS="$ZSH_THEME_GIT_PROMPT_UNMERGED$STATUS" 115 | fi 116 | if $(echo "$INDEX" | grep '^## .*ahead' &> /dev/null); then 117 | STATUS="$ZSH_THEME_GIT_PROMPT_AHEAD$STATUS" 118 | fi 119 | if $(echo "$INDEX" | grep '^## .*behind' &> /dev/null); then 120 | STATUS="$ZSH_THEME_GIT_PROMPT_BEHIND$STATUS" 121 | fi 122 | if $(echo "$INDEX" | grep '^## .*diverged' &> /dev/null); then 123 | STATUS="$ZSH_THEME_GIT_PROMPT_DIVERGED$STATUS" 124 | fi 125 | echo $STATUS 126 | } 127 | 128 | #compare the provided version of git to the version installed and on path 129 | #prints 1 if input version <= installed version 130 | #prints -1 otherwise 131 | function git_compare_version() { 132 | local INPUT_GIT_VERSION=$1; 133 | local INSTALLED_GIT_VERSION 134 | INPUT_GIT_VERSION=(${(s/./)INPUT_GIT_VERSION}); 135 | INSTALLED_GIT_VERSION=($(command git --version 2>/dev/null)); 136 | INSTALLED_GIT_VERSION=(${(s/./)INSTALLED_GIT_VERSION[3]}); 137 | 138 | for i in {1..3}; do 139 | if [[ $INSTALLED_GIT_VERSION[$i] -gt $INPUT_GIT_VERSION[$i] ]]; then 140 | echo 1 141 | return 0 142 | fi 143 | if [[ $INSTALLED_GIT_VERSION[$i] -lt $INPUT_GIT_VERSION[$i] ]]; then 144 | echo -1 145 | return 0 146 | fi 147 | done 148 | echo 0 149 | } 150 | 151 | #this is unlikely to change so make it all statically assigned 152 | POST_1_7_2_GIT=$(git_compare_version "1.7.2") 153 | 154 | #clean up the namespace slightly by removing the checker function 155 | unset -f git_compare_version 156 | -------------------------------------------------------------------------------- /share/homer/template/.gitignore: -------------------------------------------------------------------------------- 1 | # This gitignore is for files that should always be ignored from every 2 | # Git repo on the machine. It is *not* for time-savers that one might 3 | # generate for every gitignore on a given type of project. 4 | 5 | # OS X garbage 6 | .DS_Store 7 | .AppleDouble 8 | .LSOverride 9 | Icon 10 | .Spotlight-V100 11 | .Trashes 12 | 13 | # Vim temporary files 14 | .*.sw[a-z] 15 | *.un~ 16 | Session.vim 17 | .netrwhist 18 | 19 | # Mercurial repos 20 | /.hg/* 21 | */.hg/* 22 | .hgignore 23 | 24 | # Local Bundler settings 25 | .bundle 26 | /vendor/gems 27 | /vendor/bundle 28 | 29 | # Environment configuration 30 | .env 31 | 32 | # CTags 33 | tags 34 | 35 | # Archives and packages 36 | *.7z 37 | *.jar 38 | *.rar 39 | *.zip 40 | *.gz 41 | *.bzip 42 | *.bz2 43 | *.xz 44 | *.lzma 45 | *.iso 46 | *.tar 47 | *.dmg 48 | *.xpi 49 | *.gem 50 | *.egg 51 | *.deb 52 | *.rpm 53 | 54 | # CTags 55 | tags 56 | 57 | # Directory info 58 | .info 59 | -------------------------------------------------------------------------------- /share/homer/template/.zshenv: -------------------------------------------------------------------------------- 1 | #!/zsh 2 | 3 | source "/usr/local/share/homer.zsh" 4 | -------------------------------------------------------------------------------- /share/homer/template/.zshrc: -------------------------------------------------------------------------------- 1 | #!/bin/zsh 2 | # 3 | # ZSH master shell configuration. 4 | 5 | ## Load the Homer shell framework 6 | homer load 7 | 8 | ## Configuration 9 | 10 | # Text editing and paging 11 | EDITOR='vim' 12 | PAGER='less -R' 13 | -------------------------------------------------------------------------------- /share/homer/template/README.md: -------------------------------------------------------------------------------- 1 | # ~ 2 | 3 | This is my home directory. It's managed by [Homer][homer]. 4 | 5 | [homer]: http://github.com/tubbo/homer 6 | -------------------------------------------------------------------------------- /share/homer/template/bin/.keep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tubbo/homer/c6b5826ece60b192cbc616927d8030d864afbd6f/share/homer/template/bin/.keep -------------------------------------------------------------------------------- /share/homer/template/etc/aliases.zsh: -------------------------------------------------------------------------------- 1 | #!/bin/zsh 2 | # 3 | # This is where you keep your aliases. PLEASE DO NOT EDIT THIS FILE BY 4 | # HAND! 5 | 6 | 7 | -------------------------------------------------------------------------------- /share/homer/template/etc/plugins.zsh: -------------------------------------------------------------------------------- 1 | #!/bin/zsh 2 | # 3 | # This is your plugins file. PLEASE DO NOT EDIT IT BY HAND! It is 4 | # managed by the `homer plugin` tool. 5 | 6 | source "/usr/local/share/antigen.zsh" 7 | -------------------------------------------------------------------------------- /share/homer/template/etc/profile.d/.keep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tubbo/homer/c6b5826ece60b192cbc616927d8030d864afbd6f/share/homer/template/etc/profile.d/.keep -------------------------------------------------------------------------------- /test/homer-alias-test.bats: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bats 2 | 3 | load test_helper 4 | 5 | alias_string="alias hello-world='echo hello world'" 6 | 7 | @test "add an alias" { 8 | $HOMER init 9 | run $HOMER alias hello-world 'echo "hello world"' 10 | 11 | assert_success 12 | assert_output --partial "Add alias hello-world" 13 | } 14 | 15 | @test "remove an alias" { 16 | $HOMER init 17 | echo $alias_string >> $HOMER_HOME/etc/aliases.zsh 18 | 19 | run $HOMER alias hello-world -r 20 | 21 | assert_success 22 | assert_output --partial "Remove alias hello-world" 23 | } 24 | -------------------------------------------------------------------------------- /test/homer-grep-test.bats: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bats 2 | 3 | load test_helper 4 | 5 | @test "search the home directory repo" { 6 | $HOMER init > /dev/null 2>&1 7 | echo page > $HOMER_HOME/.dotfile 8 | pushd $HOMER_HOME 9 | git add -f .dotfile 10 | git commit .dotfile -m "created dotfile" 11 | popd 12 | 13 | run $HOMER grep page 14 | 15 | assert_success 16 | assert_output --partial ".dotfile" 17 | assert_output --partial "share/homer/profile.d/editing.zsh" 18 | } 19 | -------------------------------------------------------------------------------- /test/homer-help-test.bats: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bats 2 | 3 | load test_helper 4 | 5 | @test "show usage information" { 6 | run $HOMER help 7 | 8 | assert_success 9 | assert_output --partial "Usage: homer COMMAND [ARGUMENTS]" 10 | } 11 | 12 | @test "show information on command" { 13 | run $HOMER help init 14 | 15 | assert_success 16 | assert_output --partial "Sets up your home directory for use with Homer." 17 | } 18 | -------------------------------------------------------------------------------- /test/homer-init-test.bats: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bats 2 | 3 | load test_helper 4 | 5 | assert_error() { 6 | assert_output "ERROR: $1" 7 | } 8 | 9 | if [ -z "$HOMER_TEST_REPO_URL" ]; then 10 | HOMER_TEST_REPO_URL=https://github.com/tubbo/homer-example.git 11 | fi 12 | 13 | @test "initialize a git repo as the home dir" { 14 | run $HOMER init 15 | 16 | assert_success 17 | assert_file_exist $HOMER_HOME/etc/aliases.zsh 18 | assert_file_exist $HOMER_HOME/etc/plugins.zsh 19 | assert_file_exist $HOMER_HOME/bin/.keep 20 | } 21 | 22 | @test "clone an existing git repo into the home dir" { 23 | run $HOMER init $HOMER_TEST_REPO_URL 24 | 25 | assert_success 26 | assert_file_exist $HOMER_HOME/etc/aliases.zsh 27 | assert_file_exist $HOMER_HOME/etc/plugins.zsh 28 | assert_file_exist $HOMER_HOME/bin/.keep 29 | } 30 | 31 | @test "print an error and exit if git repo already exists" { 32 | mkdir -p $HOMER_HOME/.git 33 | run $HOMER init 34 | 35 | assert_failure 36 | assert_error "There is already an existing Git repository in $HOMER_HOME." 37 | } 38 | -------------------------------------------------------------------------------- /test/homer-install-test.bats: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bats 2 | 3 | load test_helper 4 | 5 | setup() { 6 | if [ ! -z "$(command -v docker)" ]; then 7 | docker build -t homer:latest . 8 | fi 9 | } 10 | 11 | teardown() { 12 | if [ ! -z "$(command -v docker)" ]; then 13 | docker image rm homer:latest 14 | fi 15 | } 16 | 17 | @test "install the latest version with the installer script" { 18 | if [ -z "$(command -v docker)" ]; then 19 | skip "Install Docker to run integration tests" 20 | fi 21 | 22 | run docker run --rm homer:latest homer 23 | 24 | assert_success 25 | assert_line --partial "Usage: homer COMMAND [ARGUMENTS]" 26 | } 27 | -------------------------------------------------------------------------------- /test/homer-plugin-test.bats: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bats 2 | 3 | load test_helper 4 | 5 | @test "add a plugin to the manifest" { 6 | run $HOMER plugin zsh-users/zsh-syntax-highlighting 7 | 8 | assert_success 9 | } 10 | 11 | @test "remove a plugin from the manifest" { 12 | } 13 | -------------------------------------------------------------------------------- /test/homer-save-test.bats: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bats 2 | 3 | load test_helper 4 | 5 | @test "save a dotfile to the home dir" { 6 | $HOMER init 7 | touch $HOMER_HOME/.dotfile 8 | run $HOMER save .dotfile -m "Added dotfile" 9 | 10 | assert_success 11 | assert_line --partial "Added dotfile" 12 | } 13 | 14 | @test "remove a dotfile from the home dir" { 15 | $HOMER init 16 | run $HOMER save README.md -r -m "Removed README" 17 | 18 | assert_success 19 | assert_line --partial "Removed README" 20 | } 21 | 22 | @test "prevent saving dotfile without a commit message" { 23 | $HOMER init 24 | touch $HOMER_HOME/.dotfile 25 | run $HOMER save .dotfile 26 | 27 | assert_failure 28 | assert_output "You must enter a message." 29 | } 30 | -------------------------------------------------------------------------------- /test/homer-script-test.bats: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bats 2 | 3 | load test_helper 4 | 5 | @test "save an executable script to bin/" { 6 | $HOMER init 7 | 8 | echo 'echo hello world' > $BATS_TMPDIR/foo 9 | 10 | run $HOMER script $BATS_TMPDIR/foo 11 | 12 | assert_success 13 | assert_output --partial "Add script foo" 14 | } 15 | 16 | @test "save an executable script to bin/ with custom msg" { 17 | $HOMER init 18 | 19 | echo 'echo hello world' > $BATS_TMPDIR/foo 20 | 21 | run $HOMER script $BATS_TMPDIR/foo -m "Add foo" 22 | 23 | assert_success 24 | assert_output --partial "Add foo" 25 | } 26 | 27 | 28 | 29 | @test "remove an executable script from bin/" { 30 | $HOMER init 31 | pushd $HOMER_HOME 32 | echo 'echo hello world' > bin/foo 33 | git add -f bin/foo 34 | git commit -m "Add script foo" 35 | popd 36 | 37 | run $HOMER script $BATS_TMPDIR/foo -r 38 | 39 | assert_success 40 | assert_output --partial "Remove script foo" 41 | } 42 | -------------------------------------------------------------------------------- /test/homer-test.bats: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bats 2 | 3 | @test "runs an executable when given a proper command" { 4 | ./bin/homer help 5 | } 6 | 7 | @test "shows usage information when command not found" { 8 | ./bin/homer not-a-command 9 | } 10 | -------------------------------------------------------------------------------- /test/homer-update-test.bats: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bats 2 | 3 | load test_helper 4 | 5 | @test "sync with remote repository" { 6 | $HOMER init 7 | git init $BATS_TMPDIR/remote --bare 8 | pushd $HOMER_HOME 9 | git remote add origin $BATS_TMPDIR/remote 10 | git push origin master 11 | popd 12 | 13 | run $HOMER update 14 | 15 | assert_success 16 | assert_output --partial "Updated home directory $HOMER_HOME with the latest changes." 17 | } 18 | -------------------------------------------------------------------------------- /test/homer-version-test.bats: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bats 2 | 3 | load test_helper 4 | 5 | @test "print current version" { 6 | run $HOMER version 7 | 8 | assert_success 9 | assert_output "$(cat $PWD/share/homer/VERSION)" 10 | } 11 | -------------------------------------------------------------------------------- /test/test_helper.bash: -------------------------------------------------------------------------------- 1 | #!/usr/local/bin/bash 2 | 3 | # Load BATS plugins 4 | VENDOR_PATH=../node_modules 5 | 6 | load "${VENDOR_PATH}/bats-support/load" 7 | load "${VENDOR_PATH}/bats-assert/load" 8 | load "${VENDOR_PATH}/bats-file/load" 9 | 10 | export SOURCE_DIR="$(dirname $BATS_TEST_DIRNAME)" 11 | export HOMER=$BATS_TEST_DIRNAME/../bin/homer 12 | 13 | setup() { 14 | export HOMER_HOME="$BATS_TMPDIR/home" 15 | mkdir -p $HOMER_HOME 16 | } 17 | 18 | teardown() { 19 | rm -rf $HOMER_HOME $BATS_TMPDIR/remote $BATS_TMPDIR/repo $BATS_TMPDIR/foo 20 | } 21 | --------------------------------------------------------------------------------