diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..88c9438 --- /dev/null +++ b/.gitignore @@ -0,0 +1,10 @@ +# Running tests creates this completion dump file. +tests/.zcompdump + +# Test failure reports +tests/*.t.err + +# If the $ADOTDIR is the same as the antigen's clone directory itself, the +# following would be shown as untracked. +repos/ +revert-info diff --git a/.travis.yml b/.travis.yml new file mode 100644 index 0000000..e1032a6 --- /dev/null +++ b/.travis.yml @@ -0,0 +1,35 @@ +# Using python for running the tests, using the `cram` test framework. +language: python + +# Python version to run tests with. +python: + - "2.7" + +env: + # Default zsh + - PPA="none" + # zsh 5 PPA + - PPA="ppa:brainpower/testing" + +before_script: + + # Show the git version being used to test. + - "git --version" + + # Show the zsh version being used to test. + - "zsh --version" + + # Test config for git. + - "git config --global user.name test" + - "git config --global user.email test@test.test" + +install: + # Add PPA if needed + - "./travis-ppa.sh" + # Install python requirements. + - "pip install -r requirements.txt --use-mirrors" + # Install zsh. + - "sudo apt-get install zsh" + +# Run the tests. +script: "make tests PYENV=" diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..342d213 --- /dev/null +++ b/Makefile @@ -0,0 +1,10 @@ +.PHONY: itests tests + +PYENV ?= . .pyenv/bin/activate && +TESTS ?= tests + +itests: + ${MAKE} tests CRAM_OPTS=-i + +tests: + ${PYENV} ZDOTDIR="${PWD}/tests" cram ${CRAM_OPTS} --shell=zsh ${TESTS} diff --git a/README.mkd b/README.mkd new file mode 100644 index 0000000..b9d1ac6 --- /dev/null +++ b/README.mkd @@ -0,0 +1,616 @@ +# Antigen v1 + +[![Build Status](https://secure.travis-ci.org/zsh-users/antigen.png)](http://travis-ci.org/zsh-users/antigen) + +Antigen is a small set of functions that help you easily manage your shell (zsh) +plugins, called bundles. The concept is pretty much the same as bundles in a +typical vim+pathogen setup. Antigen is to zsh, what [Vundle][] is to vim. + +> [Donate to Antigen](https://gum.co/antigen) + +Antigen has reached a certain level of stability and has been used in the wild +for around a couple of years. If you face any problems, please open an issue. + +Note: Please read the commit comments of the changesets when you pull a new +version of antigen. + +## Show off + +> Enough talk. Let's fight! +> -- Po, Kung-fu Panda. + +You're going to experience antigen right in your open shell. No `.zshrc` +tweaking and reading the rest of this documentation. Kinda like an ice-cream +sample, if you will. + +Get and load antigen. + + curl -L https://raw.githubusercontent.com/zsh-users/antigen/master/antigen.zsh > antigen.zsh + source antigen.zsh + +There. You now have all the antigen goodies. Let's try install some plugins. How +about some color to start with. Get the [syntax highlighting plugin][] by +running + + antigen bundle zsh-users/zsh-syntax-highlighting + +Now let it do its thing and once you're back at your prompt, try and type a +command. See that? Colors! + +So, you do git? ruby? git and ruby? There are lots of awesome plugins over at +oh-my-zsh. Treat yourself to some. + + antigen bundle robbyrussell/oh-my-zsh plugins/ruby + # Or for the lazy, + antigen bundle git + +There are lots of plugins out there in the wild and people are writing zsh +utilities as small scripts all the time. Antigen is compatible with all of them. +The plugins and scripts don't need any special handling to be compatible with +antigen. + +Another example, [kennethreitz's autoenv][autoenv] (or [my fork][f-autoenv] of +it). Just a bundle command away. + + antigen bundle sharat87/autoenv + +And boom! you have all the autoenv goodness. Just remember how you used to do +these before antigen, clone it, modify your zshrc to source it, load a new +terminal, all just to test it out. Duh! + +A subtle aspect of this is that you can tell antigen to grab just about anything +from anyone's `dotfiles` repo, as long as it is in a directory under any repo on +github. + +And themes? How would you like a fancy new prompt for yourself? + + antigen theme funky + +No? Not your taste? There are many themes available to you, check out the +oh-my-zsh's [page on themes][]. + +You can install themes from unofficial repos too! + + antigen theme XsErG/zsh-themes themes/lazyuser + +See? It's easy! To see how that works, refer to [the section on the +`antigen theme` command further down](#antigen-theme). + +Note: Many of those plugins and especially themes, assume you have the core +library of oh-my-zsh loaded. So, if you want to experiment further, issue a + + antigen use oh-my-zsh + +and continue until you're tired. At which point you can come back to this page +;) + +## Usage + +So, now that you're here, I suppose you are convinced and want antigen running +your shell all the time. Sweet. Let's do it. + +First, clone this repo, probably as a submodule if you have your dotfiles in a +git repo, + + git clone https://github.com/zsh-users/antigen.git + +The usage should be very familiar to you if you use Vundle. A typical `.zshrc` +might look like this + + source /path-to-antigen-clone/antigen.zsh + + # Load the oh-my-zsh's library. + antigen use oh-my-zsh + + # Bundles from the default repo (robbyrussell's oh-my-zsh). + antigen bundle git + antigen bundle heroku + antigen bundle pip + antigen bundle lein + antigen bundle command-not-found + + # Syntax highlighting bundle. + antigen bundle zsh-users/zsh-syntax-highlighting + + # Load the theme. + antigen theme robbyrussell + + # Tell antigen that you're done. + antigen apply + +Open your zsh with this zshrc and you should see all the bundles you defined +here, getting installed. Once its done, you are ready to roll. The complete +syntax for the `antigen bundle` command is discussed further down on this page. + +You can find more examples in the wiki: [Antigen in the wild][wild]. + +## Motivation + +If you use zsh and [oh-my-zsh][], you know that having many different plugins +that are developed by many different authors in a single (sub)repo is not very +easy to maintain. There are some really fantastic plugins and utilities in +oh-my-zsh, but having them all in a single repo doesn't really scale well. And I +admire robbyrussell's efforts for reviewing and merging the gigantic number of +pull requests the project gets. We need a better way of plugin management. + +This was discussed on [a][1] [few][2] [issues][3], but it doesn't look like +there was any progress made. So, I'm trying to start this off with antigen, +hoping to better this situation. Please note that I'm by no means a zsh or any +shell script expert (far from it). + +[1]: https://github.com/robbyrussell/oh-my-zsh/issues/465 +[2]: https://github.com/robbyrussell/oh-my-zsh/issues/377 +[3]: https://github.com/robbyrussell/oh-my-zsh/issues/1014 + +Inspired by vundle, antigen can pull oh-my-zsh style plugins from various github +repositories. You are not limited to use plugins from the oh-my-zsh repository +only and you don't need to maintain your own fork and pull from upstream every +now and then. I actually encourage you to grab plugins and scripts from various +sources, straight from the authors, before they even submit it to oh-my-zsh as a +pull request. + +Antigen also lets you switch the prompt theme with one command, just like that + + antigen theme candy + +and your prompt is changed, just for this session of course (unless you put this +line in your `.zshrc`). + +## Commands + +### antigen bundle + +This command tells antigen to install (if not already installed) and load the +given plugin. The simplest usage follows the following syntax. + + antigen bundle + +This will install and load the `plugins/` directory from [robbyrussell's +oh-my-zsh][oh-my-zsh] (can be changed by setting `ANTIGEN_DEFAULT_REPO_URL`). + +However, the above is just syntax sugar for the extended syntax of the +`antigen bundle` command. + + antigen bundle [ []] + +where `` is the repository url and it defaults to [robbyrussell's +oh-my-zsh][oh-my-zsh] repo (can be changed by setting `ANTIGEN_DEFAULT_REPO_URL` +discussed further down). `` is the path under this repository which has the +zsh plugin. This is typically the directory that contains a `*.plugin.zsh` file, +but it could contain a completion file or just many `*.zsh` files to be sourced, +or it could simply be a file (with any extension) that you want to source. +`` defaults to `/`, which indicates the repository itself is a plugin. + +An example invocation would be + + # The following is the same as `antigen bundle ant`. But for demonstration + # purposes, we use the extended syntax here. + antigen bundle https://github.com/robbyrussell/oh-my-zsh.git plugins/ant + +This would install the ant plugin from robbyrussell's oh-my-zsh repo. Of course, +github url's can be shortened. + + antigen bundle robbyrussell/oh-my-zsh plugins/ant + +And since this repo is the default, even that isn't necessary. But we can't +specify the `loc` without giving the first argument. + +For this and a few other reasons, `antigen bundle` also supports a simple +keyword argument syntax, using which we can rewrite the above as + + antigen bundle --loc=plugins/ant + +Which picks up the default for the `url` argument, and uses the `loc` given to +it. + +*Note* that you can mix and match positional and keyword arguments. But you +can't have positional arguments after keyword arguments. + + antigen bundle robbyrussell/oh-my-zsh --loc=plugins/ant + +And keyword arguments don't care about the order in which the arguments are +specified. The following is perfectly valid. + + antigen bundle --loc=plugins/ant --url=robbyrussell/oh-my-zsh + +You can also specify a local directory on your file system as a bundle. In this +case, make sure the path you give is the absolute path (i.e., starts with a +`/`). Relative paths are not supported. If the repo you gave is a local +directory path, then it is not necessary that this path is a git repo. Please +refer to the notes on `--no-local-clone` below. + +This command can also be used from your shell environment. This allows you to +install plugins on the fly and try them out. Of course if you want a bundle to +be available every time you open a shell, put it in your `.zshrc`. + +Other keyword-only arguments accepted: + +`--branch={git-branch-name}` — Specify the branch of the git repo to be +used for this bundle (without the braces of course). The default is whatever +branch the clone comes with, which is usually `master`. For example, + + antigen bundle github-user/repo --branch=develop + +This will get the plugin as in the branch `develop`. + +Note that if you specify two plugins to be loaded from the same git repo, but +different branches, then two separate clones of this repo will be maintained. +This is a small implementation detail and shouldn't influence you in any way. + +`--no-local-clone` — This command can be useful if you are developing a +plugin and already have a clone on your local file system. If this argument is +not given, even if the given repo url is a local path, a clone is made in the +`$ADOTDIR/repos`, and the plugin is loaded from that clone. But, if you give +this argument, the plugin is sourced straight from the repo location, without +creating a clone. For example, + + antigen bundle /absolute/path/to/the/plugin --no-local-clone + +Note that if the repo url is *not* an absolute local path or a branch has been +specified with the `--branch` option, this argument has no effect. That is, +for this option to have any affect, the repo url must be an absolute local path +and no `--branch` should be specified. + +Also, if the local path given as the url is not a git repo, then this +argument is forced as it doesn't makes sense to *clone* something that's not a +git repo. This property can be used to load any utility scripts you have in your +dotfiles repo. For example, + + antigen bundle $HOME/dotfiles/oh-my-zsh/custom + +In addition to the above discussed arguments, `antigen bundle` also takes a +`btype` keyword-only argument, that is used internally. You shouldn't be +concerned with this argument, its only used internally and will probably go away +in the future. It indicates whether the bundle is a theme or a simple plugin. + +### antigen bundles + +If you have a fair number of bundles, using the `antigen bundle` command can +look cumbersome. You can use the `antigen bundles` command to *bulk* define +bundles instead of individual calls to `antigen bundle`. + +Usage is pretty straightforward. Just pipe the bundle specifications, just as +you would give to the `antigen bundle` command, one per line, into the +`antigen bundles` command. The easiest way to do this, is using the heredoc +syntax. + + antigen bundles <α + +Reverts the state of all your plugins to how they were before the last +`antigen update`. This command is currently experimental, so don't rely too much +on it. There is a test for it, and it passes, so it should work fine though. + +Takes no options. + +Insider detail: The information for reverting is stored in +`$ADOTDIR/revert-info` file. If its not present, reverting is not possible. + +### antigen list + +Use this command to list out the currently *loaded* plugins. Keep in mind that +this includes any bundles installed on-the-fly. + +Takes no arguments. Gives out four entries per line of output, denoting the +following fields of each bundle. + + + +The `btype` field is an internal detail, that specifies if the bundle is a +`plugin` or a `theme`. + +The final field is `true` or `false` reflecting whether there is a local clone +for this bundle. + +### antigen cleanup + +Used to clean up the clones of repos which are not used by any plugins currently +loaded. It takes no arguments. When run, it lists out the repo-clones that are +available but are not used by any plugin *currently loaded*. + +This command, by default asks for confirmation before deleting the unused +clones. If the `--force` argument is given, then this confirmation is not asked. +It straight away deletes all the unused clones. This option makes this command +usable in a non-interactive fashion. + +### antigen use + +This command lets you load any (supported) zsh pre-packaged framework, like +oh-my-zsh. Usage is + + antigen use oh-my-zsh + +Additional arguments may be present depending on the framework you are +`use`-ing. Here are the supported frameworks. + +#### oh-my-zsh + +This is (almost) the same as + + antigen bundle --loc=lib + +So, it basically installs the oh-my-zsh's library as a bundle. + +One other thing it does is that some oh-my-zsh plugins expect a `$ZSH` set to +the full path of the oh-my-zsh clone being used. This is also set to the +correct path, if not already set to something else. + +Please note that this assumes that the `ANTIGEN_DEFAULT_REPO_URL` is set to the +oh-my-zsh repo or a fork of that repo. If you want to specify the `url` too, +then you can't use the `antigen use oh-my-zsh` short cut. You have to do that +directly with the `antigen bundle` command. + +Use + + antigen use oh-my-zsh + +in your `.zshrc`, before any `antigen bundle` declarations. It takes no further +arguments. + +#### prezto + +This is (almost, but not quite) the same as doing, + + antigen bundle sorin-ionescu/prezto + +That is, initializes the canonical repo of the prezto framework. Please note +that prezto support is very new and experimental in antigen. If you find any +bugs, please report over on github issues. + +Takes no further arguments. + +### antigen theme + +Used for switching the prompt theme. Invoke it with the name of the theme you +want to use. + + antigen theme fox + +This will get the theme file located at `themes/fox.zsh-theme` in the repo +specified by `ANTIGEN_DEFAULT_REPO_URL`. + +To pull themes from other repositories, use `antigen theme` just like +`antigen bundle`. Exactly the same, just make sure the `url` and `loc` +combination point to a theme file, having a `.zsh-theme` extension. + +For example, + + antigen theme robbyrussell/oh-my-zsh themes/apple + +Will pull the apple theme from the canonical oh-my-zsh repo. Also, note that the +`.zsh-theme` extension is not present. It can be given, its optional. + +To get themes from arbitrary git repos (such as gists) use, + + antigen theme https://gist.github.com/3750104.git agnoster + +in which case there is a file called `agnoster.zsh-theme` present in the gist at +https://gist.github.com/3750104. + +You can use this command to change your theme on the fly in your shell. Go on, +try out a few themes in your shell before you set it in your `.zshrc`. + +**Note**: Some themes use functions that are loaded by `antigen use oh-my-zsh`. +So, to avoid any trouble, run `antigen use oh-my-zsh` if you haven't already +before experimenting with themes. If you have `antigen use oh-my-zsh` in your +`.zshrc`, you're covered. + +**Note**: Do *not* provide the `--btype` argument to `antigen theme`. Its an +internal argument. + +*For the interested, you can read more details on the purpose & workings of the +`theme` command on the comments of issue #78.* + +### antigen apply + +You have to add this command after defining all bundles you need, in your zshrc. +The completions defined by your bundles will be loaded at this step. + +It is possible to load completions as and when a bundle is specified with the +bundle command, in which case this command would not be necessary. But loading +the completions is a time-consuming process, so if the completions were loaded +at every call to `antigen bundle`, your shell will start noticeably slow when +you have a good number of bundle specifications. + +However, if you can suggest a way so that this would not be necessary, I am very +interested in discussing it. Please open up an issue with your details. Thanks. + +### antigen snapshot α + +Creates a snapshot of all the clones you currently have *active* including the +git version hash they are at and save it to a snapshot file. *Active* means, the +clones for those listed by `antigen cleanup` are not included in the snapshot. + +Takes one optional argument, the file name in which the snapshot is to be saved. +Defaults to `antigen snapshot`. + +**Note**: The snapshot currently *only* contains the details of those bundles +that have a clone. That is, bundles that have `--no-local-clone` set or are +directly sourced from your file system (without a git repo), are not recorded +in the snapshot file. + +### antigen restore α + +Restore the bundles state as specified in the snapshot. Takes one required +argument, the snapshot file name to read. + +Although it restores the clones of the repos specified in the snapshot file, any +other clones present in your environment are not touched. This behavior may +change in the future. + +### antigen selfupdate + +Use this command to update your copy of antigen. It basically does a `git pull` +on your antigen's clone, *if* it is a git clone. Otherwise, it doesn't do +anything. + +Takes no options. + +### antigen help + +This exists so that there can be some help right in the command line. Currently +it doesn't provide much help other than redirecting you to the project page for +documentation. It is intended to provide more meaning and sub-command specific +help in the future. + +I could use some help here as I'm not that good at writing documentation that +looks good as output on the command line. + +## Configuration + +The following environment variables can be set to customize the behavior of +antigen. Make sure you set them *before* source-ing `antigen.zsh`. + +`ANTIGEN_DEFAULT_REPO_URL` — This is the default repository url that is +used for `bundle` commands. The default value is robbyrussell's oh-my-zsh repo, +but you can set this to the fork url of your own fork. + +`ADOTDIR` — This directory is used to store all the repo clones, your +bundles, themes, caches and everything else antigen requires to run smoothly. +Defaults to `$HOME/.antigen`. + +**Note**: `ANTIGEN_REPO_CACHE` & `ANTIGEN_BUNDLE_DIR` — These variables +were used previously but are now removed. Please use `ADOTDIR` instead, as +mentioned above. + +## Running the tests + +All the tests are in the `tests` folder and are run using the [cram][] test +system. The latest version on that website, as of today is v0.5, which does not +have the `--shell` argument which is required to run our tests. So, to get the +correct version of cram, run + + pip install -r requirements.txt + +With that, once you have cram installed, you can run the tests as + + make + +If you are making a feature addition, I'd really appreciate if you can add a +test for your feature. Even if you can add a test for an existing feature, that +would be great as the tests are currently seriously lagging behind the full +functionality of antigen. + +## Notes on writing plugins + +Most shell utilities/plugins are made up of just one file. For a plugin called +`awesomeness`, create a `awesomeness.plugin.zsh` and code away. + +That said, even if you write a single file as a `.sh` file with the goodness you +want to create, antigen will work just fine with it. The `*.plugin.zsh` way is +recommended by antigen, because it is widely used because of the [oh-my-zsh][] +project. + +If you want to know how antigen loads the plugins, do continue. + +Firstly, antigen looks for a `*.plugin.zsh` file in the plugin directory. If +present, it will source *only* this script. Nothing else is sourced. This is for +oh-my-zsh style plugins. + +Secondly, it looks for a `init.zsh` file in the plugin directory. If present, it +will source *only* this script. Nothing else is sourced. This is for prezto +style modules. + +Otherwise, it looks for `*.zsh` files and if there are any, *all* of them are +sourced. The order in which they are sourced is not currently defined. Please +don't rely on this order. Nothing else is sourced after all the `*.zsh` scripts. + +If no `*.zsh` files are present, it finally looks for any `*.sh` files and +sources *all* of them. Again, the order in which they are sourced in not +currently defined. + +No matter which (or none) of the above happen to be sourced, this plugin +directory is added to the zsh's function path (`$fpath`) so that any completions +in it are loaded. + +One exception to this rule is that if this plugin is a theme. In which case the +theme script is just sourced and nothing else is done. Not even adding to +`$fpath`. + +## A note on external zsh plugins + +Antigen downloads zsh scripts and sources them, according to your +specifications. As such, these scripts are capable of doing some *real* damage +to your system. If you are only downloading scripts from oh-my-zsh and/or +prezto, you're probably fine, since there is a second level of manual checking +before a script gets into the framework. + +But, if you are adding a script from any other source, please check the source +code of the plugin to see its not doing anything malicious, before adding it to +your `.zshrc`. + +## Meta + +### Helping out + +Antigen is licensed with the [MIT License][license]. + +To contribute, please read the [contributing wiki page][contributing] before +sending pull requests. If its a long/complicated change, please consider opening +an [issue][] first so we can discuss it out. Thanks! + +You may also wish to [donate to the project](https://gum.co/antigen). Thank you +so much! + +### Feedback please + +Any comments/suggestions/feedback welcome. Please say hello to me +([@sharat87][twitter]) on twitter. Or open an issue to discuss something +(anything!) about the project ;). + +### Alternatives to antigen + + * [antigen-hs] - An antigen-inspired zsh plugin manager that tries to do work statically and only on manual invocation, minimizing the zsh startup time. Antigen-hs is much more minimalistic and convention over configuration than antigen. + + +[Vundle]: https://github.com/gmarik/vundle +[page on themes]: https://github.com/robbyrussell/oh-my-zsh/wiki/Themes +[wild]: https://github.com/zsh-users/antigen/wiki/In-the-wild +[syntax highlighting plugin]: https://github.com/zsh-users/zsh-syntax-highlighting +[autoenv]: https://github.com/kennethreitz/autoenv +[f-autoenv]: https://github.com/sharat87/autoenv +[oh-my-zsh]: https://github.com/robbyrussell/oh-my-zsh +[cram]: https://bitheap.org/cram/ +[issue]: https://github.com/zsh-users/antigen/issues +[license]: http://mit.sharats.me +[contributing]: https://github.com/zsh-users/antigen/wiki/Contributing +[twitter]: http://twitter.com/sharat87 +[antigen-hs]: https://github.com/Tarrasch/antigen-hs diff --git a/antigen.zsh b/antigen.zsh new file mode 100644 index 0000000..ceacad8 --- /dev/null +++ b/antigen.zsh @@ -0,0 +1,753 @@ +# Antigen: A simple plugin manager for zsh +# Authors: Shrikant Sharat Kandula +# and Contributors +# Homepage: http://antigen.sharats.me +# License: MIT License + +# Each line in this string has the following entries separated by a space +# character. +# , , , +# FIXME: Is not kept local by zsh! +local _ANTIGEN_BUNDLE_RECORD="" +local _ANTIGEN_INSTALL_DIR="$(cd "$(dirname "$0")" && pwd)" + +# Used to defer compinit/compdef +typeset -a __deferred_compdefs +compdef () { __deferred_compdefs=($__deferred_compdefs "$*") } + +# Syntaxes +# antigen-bundle [=/] +# Keyword only arguments: +# branch - The branch of the repo to use for this bundle. +antigen-bundle () { + + # Bundle spec arguments' default values. + local url="$ANTIGEN_DEFAULT_REPO_URL" + local loc=/ + local branch= + local no_local_clone=false + local btype=plugin + + # Parse the given arguments. (Will overwrite the above values). + eval "$(-antigen-parse-args \ + 'url?, loc? ; branch:?, no-local-clone?, btype:?' \ + "$@")" + + # Check if url is just the plugin name. Super short syntax. + if [[ "$url" != */* ]]; then + loc="plugins/$url" + url="$ANTIGEN_DEFAULT_REPO_URL" + fi + + # Resolve the url. + url="$(-antigen-resolve-bundle-url "$url")" + + # Add the branch information to the url. + if [[ ! -z $branch ]]; then + url="$url|$branch" + fi + + # The `make_local_clone` variable better represents whether there should be + # a local clone made. For cloning to be avoided, firstly, the `$url` should + # be an absolute local path and `$branch` should be empty. In addition to + # these two conditions, either the `--no-local-clone` option should be + # given, or `$url` should not a git repo. + local make_local_clone=true + if [[ $url == /* && -z $branch && + ( $no_local_clone == true || ! -d $url/.git ) ]]; then + make_local_clone=false + fi + + # Add the theme extension to `loc`, if this is a theme. + if [[ $btype == theme && $loc != *.zsh-theme ]]; then + loc="$loc.zsh-theme" + fi + + # Add it to the record. + _ANTIGEN_BUNDLE_RECORD="$_ANTIGEN_BUNDLE_RECORD\n$url $loc $btype" + _ANTIGEN_BUNDLE_RECORD="$_ANTIGEN_BUNDLE_RECORD $make_local_clone" + + # Ensure a clone exists for this repo, if needed. + if $make_local_clone; then + -antigen-ensure-repo "$url" + fi + + # Load the plugin. + -antigen-load "$url" "$loc" "$make_local_clone" + +} + +-antigen-resolve-bundle-url () { + # Given an acceptable short/full form of a bundle's repo url, this function + # echoes the full form of the repo's clone url. + + local url="$1" + + # Expand short github url syntax: `username/reponame`. + if [[ $url != git://* && + $url != https://* && + $url != http://* && + $url != ssh://* && + $url != /* && + $url != git@github.com:*/* + ]]; then + url="https://github.com/${url%.git}.git" + fi + + echo "$url" +} + +antigen-bundles () { + # Bulk add many bundles at one go. Empty lines and lines starting with a `#` + # are ignored. Everything else is given to `antigen-bundle` as is, no + # quoting rules applied. + + local line + + grep '^[[:space:]]*[^[:space:]#]' | while read line; do + # Using `eval` so that we can use the shell-style quoting in each line + # piped to `antigen-bundles`. + eval "antigen-bundle $line" + done +} + +antigen-update () { + # Update your bundles, i.e., `git pull` in all the plugin repos. + + date > $ADOTDIR/revert-info + + -antigen-echo-record | + awk '$4 == "true" {print $1}' | + sort -u | + while read url; do + echo "**** Pulling $url" + + local clone_dir="$(-antigen-get-clone-dir "$url")" + if [[ -d "$clone_dir" ]]; then + (echo -n "$clone_dir:" + cd "$clone_dir" + git rev-parse HEAD) >> $ADOTDIR/revert-info + fi + + -antigen-ensure-repo "$url" --update --verbose + + echo + done +} + +antigen-revert () { + if [[ -f $ADOTDIR/revert-info ]]; then + cat $ADOTDIR/revert-info | sed '1!p' | while read line; do + dir="$(echo "$line" | cut -d: -f1)" + git --git-dir="$dir/.git" --work-tree="$dir" \ + checkout "$(echo "$line" | cut -d: -f2)" 2> /dev/null + + done + + echo "Reverted to state before running -update on $( + cat $ADOTDIR/revert-info | sed -n 1p)." + + else + echo 'No revert information available. Cannot revert.' >&2 + fi + + +} + +-antigen-get-clone-dir () { + # Takes a repo url and gives out the path that this url needs to be cloned + # to. Doesn't actually clone anything. + echo -n $ADOTDIR/repos/ + + if [[ "$1" == "https://github.com/sorin-ionescu/prezto.git" ]]; then + # Prezto's directory *has* to be `.zprezto`. + echo .zprezto + + else + echo "$1" | sed \ + -e 's./.-SLASH-.g' \ + -e 's.:.-COLON-.g' \ + -e 's.|.-PIPE-.g' + + fi +} + +-antigen-get-clone-url () { + # Takes a repo's clone dir and gives out the repo's original url that was + # used to create the given directory path. + + if [[ "$1" == ".zprezto" ]]; then + # Prezto's (in `.zprezto`), is assumed to be from `sorin-ionescu`'s + # remote. + echo https://github.com/sorin-ionescu/prezto.git + + else + echo "$1" | sed \ + -e "s:^$ADOTDIR/repos/::" \ + -e 's.-SLASH-./.g' \ + -e 's.-COLON-.:.g' \ + -e 's.-PIPE-.|.g' + + fi +} + +-antigen-ensure-repo () { + + # Ensure that a clone exists for the given repo url and branch. If the first + # argument is `--update` and if a clone already exists for the given repo + # and branch, it is pull-ed, i.e., updated. + + # Argument defaults. + # The url. No sane default for this, so just empty. + local url= + # Check if we have to update. + local update=false + # Verbose output. + local verbose=false + + eval "$(-antigen-parse-args 'url ; update?, verbose?' "$@")" + shift $# + + # Get the clone's directory as per the given repo url and branch. + local clone_dir="$(-antigen-get-clone-dir $url)" + + # A temporary function wrapping the `git` command with repeated arguments. + --plugin-git () { + (cd "$clone_dir" && git --no-pager "$@") + } + + # Clone if it doesn't already exist. + if [[ ! -d $clone_dir ]]; then + git clone --recursive "${url%|*}" "$clone_dir" + elif $update; then + # Save current revision. + local old_rev="$(--plugin-git rev-parse HEAD)" + # Pull changes if update requested. + --plugin-git pull + # Update submodules. + --plugin-git submodule update --recursive + # Get the new revision. + local new_rev="$(--plugin-git rev-parse HEAD)" + fi + + # If its a specific branch that we want, checkout that branch. + if [[ $url == *\|* ]]; then + local current_branch=${$(--plugin-git symbolic-ref HEAD)##refs/heads/} + local requested_branch="${url#*|}" + # Only do the checkout when we are not already on the branch. + [[ $requested_branch != $current_branch ]] && + --plugin-git checkout $requested_branch + fi + + if [[ -n $old_rev && $old_rev != $new_rev ]]; then + echo Updated from ${old_rev:0:7} to ${new_rev:0:7}. + if $verbose; then + --plugin-git log --oneline --reverse --no-merges --stat '@{1}..' + fi + fi + + # Remove the temporary git wrapper function. + unfunction -- --plugin-git + +} + +-antigen-load () { + + local url="$1" + local loc="$2" + local make_local_clone="$3" + + # The full location where the plugin is located. + local location + if $make_local_clone; then + location="$(-antigen-get-clone-dir "$url")/$loc" + else + location="$url/$loc" + fi + + if [[ -f "$location" ]]; then + source "$location" + + else + + # Source the plugin script. + # FIXME: I don't know. Looks very very ugly. Needs a better + # implementation once tests are ready. + local script_loc="$(ls "$location" | grep '\.plugin\.zsh$' | head -n1)" + + if [[ -f $location/$script_loc ]]; then + # If we have a `*.plugin.zsh`, source it. + source "$location/$script_loc" + + elif [[ -f $location/init.zsh ]]; then + # If we have a `init.zsh` + if (( $+functions[pmodload] )); then + # If pmodload is defined pmodload the module. Remove `modules/` + # from loc to find module name. + pmodload "${loc#modules/}" + else + # Otherwise source it. + source "$location/init.zsh" + fi + + elif ls "$location" | grep -l '\.zsh$' &> /dev/null; then + # If there is no `*.plugin.zsh` file, source *all* the `*.zsh` + # files. + for script ($location/*.zsh(N)) source "$script" + + elif ls "$location" | grep -l '\.sh$' &> /dev/null; then + # If there are no `*.zsh` files either, we look for and source any + # `*.sh` files instead. + for script ($location/*.sh(N)) source "$script" + + fi + + # Add to $fpath, for completion(s). + fpath=($location $fpath) + + fi + +} + +# Update (with `git pull`) antigen itself. +# TODO: Once update is finished, show a summary of the new commits, as a kind of +# "what's new" message. +antigen-selfupdate () { + ( cd $_ANTIGEN_INSTALL_DIR + if [[ ! ( -d .git || -f .git ) ]]; then + echo "Your copy of antigen doesn't appear to be a git clone. " \ + "The 'selfupdate' command cannot work in this case." + return 1 + fi + local head="$(git rev-parse --abbrev-ref HEAD)" + if [[ $head == "HEAD" ]]; then + # If current head is detached HEAD, checkout to master branch. + git checkout master + fi + git pull + ) +} + +antigen-cleanup () { + + # Cleanup unused repositories. + + local force=false + if [[ $1 == --force ]]; then + force=true + fi + + if [[ ! -d "$ADOTDIR/repos" || -z "$(ls "$ADOTDIR/repos/")" ]]; then + echo "You don't have any bundles." + return 0 + fi + + # Find directores in ADOTDIR/repos, that are not in the bundles record. + local unused_clones="$(comm -13 \ + <(-antigen-echo-record | + awk '$4 == "true" {print $1}' | + while read line; do + -antigen-get-clone-dir "$line" + done | + sort -u) \ + <(ls -d "$ADOTDIR/repos/"* | sort -u))" + + if [[ -z $unused_clones ]]; then + echo "You don't have any unidentified bundles." + return 0 + fi + + echo 'You have clones for the following repos, but are not used.' + echo "$unused_clones" | + while read line; do + -antigen-get-clone-url "$line" + done | + sed -e 's/^/ /' -e 's/|/, branch /' + + if $force || (echo -n '\nDelete them all? [y/N] '; read -q); then + echo + echo + echo "$unused_clones" | while read line; do + echo -n "Deleting clone for $(-antigen-get-clone-url "$line")..." + rm -rf "$line" + echo ' done.' + done + else + echo + echo Nothing deleted. + fi +} + +antigen-use () { + if [[ $1 == oh-my-zsh ]]; then + -antigen-use-oh-my-zsh + elif [[ $1 == prezto ]]; then + -antigen-use-prezto + else + echo 'Usage: antigen-use ' >&2 + echo 'Where is any one of the following:' >&2 + echo ' * oh-my-zsh' >&2 + echo ' * prezto' >&2 + return 1 + fi +} + +-antigen-use-oh-my-zsh () { + if [[ -z "$ZSH" ]]; then + export ZSH="$(-antigen-get-clone-dir "$ANTIGEN_DEFAULT_REPO_URL")" + fi + antigen-bundle --loc=lib +} + +-antigen-use-prezto () { + antigen-bundle sorin-ionescu/prezto + export ZDOTDIR=$ADOTDIR/repos/ +} + +# For backwards compatibility. +antigen-lib () { + -antigen-use-oh-my-zsh + echo '`antigen-lib` is deprecated and will soon be removed.' + echo 'Use `antigen-use oh-my-zsh` instead.' +} + +# For backwards compatibility. +antigen-prezto-lib () { + -antigen-use-prezto + echo '`antigen-prezto-lib` is deprecated and will soon be removed.' + echo 'Use `antigen-use prezto` instead.' +} + +antigen-theme () { + + if [[ "$1" != */* && "$1" != --* ]]; then + # The first argument is just a name of the plugin, to be picked up from + # the default repo. + local name="${1:-robbyrussell}" + antigen-bundle --loc=themes/$name --btype=theme + + else + antigen-bundle "$@" --btype=theme + + fi + +} + +antigen-apply () { + + # Initialize completion. + local cdef + + # Load the compinit module. This will readefine the `compdef` function to + # the one that actually initializes completions. + autoload -U compinit + compinit -i + + # Apply all `compinit`s that have been deferred. + eval "$(for cdef in $__deferred_compdefs; do + echo compdef $cdef + done)" + + unset __deferred_compdefs + +} + +antigen-list () { + # List all currently installed bundles. + if [[ -z "$_ANTIGEN_BUNDLE_RECORD" ]]; then + echo "You don't have any bundles." >&2 + return 1 + else + -antigen-echo-record | sort -u + fi +} + +antigen-snapshot () { + + local snapshot_file="${1:-antigen-shapshot}" + + # The snapshot content lines are pairs of repo-url and git version hash, in + # the form: + # + local snapshot_content="$(-antigen-echo-record | + grep 'true$' | + sed 's/ .*$//' | + sort -u | + while read url; do + local dir="$(-antigen-get-clone-dir "$url")" + local version_hash="$(cd "$dir" && git rev-parse HEAD)" + echo "$version_hash $url" + done)" + + { + # The first line in the snapshot file is for metadata, in the form: + # key='value'; key='value'; key='value'; + # Where `key`s are valid shell variable names. + + # Snapshot version. Has no relation to antigen version. If the snapshot + # file format changes, this number can be incremented. + echo -n "version='1';" + + # Snapshot creation date+time. + echo -n " created_on='$(date)';" + + # Add a checksum with the md5 checksum of all the snapshot lines. + chksum() { (md5sum; test $? = 127 && md5) 2>/dev/null | cut -d' ' -f1 } + local checksum="$(echo "$snapshot_content" | chksum)" + unset -f chksum; + echo -n " checksum='${checksum%% *}';" + + # A newline after the metadata and then the snapshot lines. + echo "\n$snapshot_content" + + } > "$snapshot_file" + +} + +antigen-restore () { + + if [[ $# == 0 ]]; then + echo 'Please provide a snapshot file to restore from.' >&2 + return 1 + fi + + local snapshot_file="$1" + + # TODO: Before doing anything with the snapshot file, verify its checksum. + # If it fails, notify this to the user and confirm if restore should + # proceed. + + echo -n "Restoring from $snapshot_file..." + + sed -n '1!p' "$snapshot_file" | + while read line; do + + local version_hash="${line%% *}" + local url="${line##* }" + local clone_dir="$(-antigen-get-clone-dir "$url")" + + if [[ ! -d $clone_dir ]]; then + git clone "$url" "$clone_dir" &> /dev/null + fi + + (cd "$clone_dir" && git checkout $version_hash) &> /dev/null + + done + + echo ' done.' + echo 'Please open a new shell to get the restored changes.' +} + +antigen-help () { + cat <&2 + return 1 + fi + shift + + if functions "antigen-$cmd" > /dev/null; then + "antigen-$cmd" "$@" + else + echo "Antigen: Unknown command: $cmd" >&2 + fi +} + +-antigen-parse-args () { + # An argument parsing functionality to parse arguments the *antigen* way :). + # Takes one first argument (called spec), which dictates how to parse and + # the rest of the arguments are parsed. Outputs a piece of valid shell code + # that can be passed to `eval` inside a function which creates the arguments + # and their values as local variables. Suggested use is to set the defaults + # to all arguments first and then eval the output of this function. + + # Spec: Only long argument supported. No support for parsing short options. + # The spec must have two sections, separated by a `;`. + # ';' + # Positional arguments are passed as just values, like `command a b`. + # Keyword arguments are passed as a `--name=value` pair, like `command + # --arg1=a --arg2=b`. + + # Each argument in the spec is separated by a `,`. Each keyword argument can + # end in a `:` to specifiy that this argument wants a value, otherwise it + # doesn't take a value. (The value in the output when the keyword argument + # doesn't have a `:` is `true`). + + # Arguments in either section can end with a `?` (should come after `:`, if + # both are present), means optional. FIXME: Not yet implemented. + + # See the test file, tests/arg-parser.t for (working) examples. + + local spec="$1" + shift + + # Sanitize the spec + spec="$(echo "$spec" | tr '\n' ' ' | sed 's/[[:space:]]//g')" + + local code='' + + --add-var () { + test -z "$code" || code="$code\n" + code="${code}local $1='$2'" + } + + local positional_args="$(echo "$spec" | cut -d\; -f1)" + local positional_args_count="$(echo $positional_args | + awk -F, '{print NF}')" + + # Set spec values based on the positional arguments. + local i=1 + while [[ -n $1 && $1 != --* ]]; do + + if (( $i > $positional_args_count )); then + echo "Only $positional_args_count positional arguments allowed." >&2 + echo "Found at least one more: '$1'" >&2 + return + fi + + local name_spec="$(echo "$positional_args" | cut -d, -f$i)" + local name="${${name_spec%\?}%:}" + local value="$1" + + if echo "$code" | grep -l "^local $name=" &> /dev/null; then + echo "Argument '$name' repeated with the value '$value'". >&2 + return + fi + + --add-var $name "$value" + + shift + i=$(($i + 1)) + done + + local keyword_args="$( + # Positional arguments can double up as keyword arguments too. + echo "$positional_args" | tr , '\n' | + while read line; do + if [[ $line == *\? ]]; then + echo "${line%?}:?" + else + echo "$line:" + fi + done + + # Specified keyword arguments. + echo "$spec" | cut -d\; -f2 | tr , '\n' + )" + local keyword_args_count="$(echo $keyword_args | awk -F, '{print NF}')" + + # Set spec values from keyword arguments, if any. The remaining arguments + # are all assumed to be keyword arguments. + while [[ $1 == --* ]]; do + # Remove the `--` at the start. + local arg="${1#--}" + + # Get the argument name and value. + if [[ $arg != *=* ]]; then + local name="$arg" + local value='' + else + local name="${arg%\=*}" + local value="${arg#*=}" + fi + + if echo "$code" | grep -l "^local $name=" &> /dev/null; then + echo "Argument '$name' repeated with the value '$value'". >&2 + return + fi + + # The specification for this argument, used for validations. + local arg_line="$(echo "$keyword_args" | + egrep "^$name:?\??" | head -n1)" + + # Validate argument and value. + if [[ -z $arg_line ]]; then + # This argument is not known to us. + echo "Unknown argument '$name'." >&2 + return + + elif (echo "$arg_line" | grep -l ':' &> /dev/null) && + [[ -z $value ]]; then + # This argument needs a value, but is not provided. + echo "Required argument for '$name' not provided." >&2 + return + + elif (echo "$arg_line" | grep -vl ':' &> /dev/null) && + [[ -n $value ]]; then + # This argument doesn't need a value, but is provided. + echo "No argument required for '$name', but provided '$value'." >&2 + return + + fi + + if [[ -z $value ]]; then + value=true + fi + + --add-var "${name//-/_}" "$value" + shift + done + + echo "$code" + + unfunction -- --add-var + +} + +# Echo the bundle specs as in the record. The first line is not echoed since it +# is a blank line. +-antigen-echo-record () { + echo "$_ANTIGEN_BUNDLE_RECORD" | sed -n '1!p' +} + +-antigen-env-setup () { + + # Helper function: Same as `export $1=$2`, but will only happen if the name + # specified by `$1` is not already set. + -set-default () { + local arg_name="$1" + local arg_value="$2" + eval "test -z \"\$$arg_name\" && export $arg_name='$arg_value'" + } + + # Pre-startup initializations. + -set-default ANTIGEN_DEFAULT_REPO_URL \ + https://github.com/robbyrussell/oh-my-zsh.git + -set-default ADOTDIR $HOME/.antigen + + # Setup antigen's own completion. + compdef _antigen antigen + + # Remove private functions. + unfunction -- -set-default +} + +# Setup antigen's autocompletion +_antigen () { + compadd \ + bundle \ + bundles \ + update \ + revert \ + list \ + cleanup \ + use \ + selfupdate \ + theme \ + apply \ + snapshot \ + restore \ + help +} + +-antigen-env-setup diff --git a/requirements.txt b/requirements.txt new file mode 100644 index 0000000..61c8e0e --- /dev/null +++ b/requirements.txt @@ -0,0 +1 @@ +cram==0.6 diff --git a/tests/.zshenv b/tests/.zshenv new file mode 100644 index 0000000..c3af528 --- /dev/null +++ b/tests/.zshenv @@ -0,0 +1,43 @@ +# zshrc file written for antigen's tests. Might not be a good one for daily use. + +# See cram's documentation for some of the variables used below. + +export ADOTDIR="$PWD/dot-antigen" + +test -f "$TESTDIR/.zcompdump" && rm "$TESTDIR/.zcompdump" + +source "$TESTDIR/../antigen.zsh" + +# A test plugin repository to test out antigen with. + +export PLUGIN_DIR="$PWD/test-plugin" +mkdir "$PLUGIN_DIR" + +# A wrapper function over `git` to work with the test plugin repo. +alias pg='git --git-dir "$PLUGIN_DIR/.git" --work-tree "$PLUGIN_DIR"' + +echo 'alias hehe="echo hehe"' > "$PLUGIN_DIR"/aliases.zsh +echo 'export PS1="prompt>"' > "$PLUGIN_DIR"/silly.zsh-theme + +{ + pg init + pg add . + pg commit -m 'Initial commit' +} > /dev/null + +# Another test plugin. + +export PLUGIN_DIR2="$PWD/test-plugin2" +mkdir "$PLUGIN_DIR2" + +# A wrapper function over `git` to work with the test plugin repo. +alias pg2='git --git-dir "$PLUGIN_DIR2/.git" --work-tree "$PLUGIN_DIR2"' + +echo 'alias hehe2="echo hehe2"' > "$PLUGIN_DIR2"/init.zsh +echo 'alias unsourced-alias="echo unsourced-alias"' > "$PLUGIN_DIR2"/aliases.zsh + +{ + pg2 init + pg2 add . + pg2 commit -m 'Initial commit' +} > /dev/null diff --git a/tests/antigen-wrapper.t b/tests/antigen-wrapper.t new file mode 100644 index 0000000..a88f59f --- /dev/null +++ b/tests/antigen-wrapper.t @@ -0,0 +1,21 @@ +Create a dummy antigen command. + + $ antigen-dummy () { + > echo me dummy + > } + +Check the normal way of calling it + + $ antigen-dummy + me dummy + +Call with the wrapper syntax. + + $ antigen dummy + me dummy + +Call with an alias + + $ alias a=antigen + $ a dummy + me dummy diff --git a/tests/arg-parser.t b/tests/arg-parser.t new file mode 100644 index 0000000..b1f58e5 --- /dev/null +++ b/tests/arg-parser.t @@ -0,0 +1,64 @@ +Helper alias. + + $ alias parse='-antigen-parse-args "url?, loc?; + > btype:?, no-local-clone?"' + +No arguments (since all are specified as optional). + + $ parse + (glob) + +One positional argument. + + $ parse name + local url='name' + +Two arguments. + + $ parse url location + local url='url' + local loc='location' + +Three arguments. + + $ parse url location crap + Only 2 positional arguments allowed. + Found at least one more: 'crap' + +Keywordo magic. + + $ parse url location --btype=1 --no-local-clone + local url='url' + local loc='location' + local btype='1' + local no_local_clone='true' + +Unknown keyword argument. + + $ parse --me=genius + Unknown argument 'me'. + +Missed value for keyword argument. + + $ parse --btype + Required argument for 'btype' not provided. + +Provide value for keyword argument, that shouldn't be there. + + $ parse --no-local-clone=yes + No argument required for 'no-local-clone', but provided 'yes'. + +Positional argument as a keyword argument. + + $ parse --url=some-url + local url='some-url' + +Repeated keyword arguments. + + $ parse --url=url1 --url=url2 + Argument 'url' repeated with the value 'url2'. + +Repeated, once as positional and once more as keyword. + + $ parse url1 --url=url2 + Argument 'url' repeated with the value 'url2'. diff --git a/tests/branch-bundle.t b/tests/branch-bundle.t new file mode 100644 index 0000000..12deca1 --- /dev/null +++ b/tests/branch-bundle.t @@ -0,0 +1,32 @@ +Branch b1. + + $ pg branch b1 + $ pg checkout b1 + Switched to branch 'b1' + $ cat > $PLUGIN_DIR/aliases.zsh < alias hehe='echo hehe from b1' + > EOF + $ pg commit -am 'Change for b1' + \[b1 [a-f0-9]{7}\] Change for b1 (re) + 1 file changed, 1 insertion(+), 1 deletion(-) + +Go back to master. + + $ pg checkout master + Switched to branch 'master' + +Load plugin from b1. + + $ antigen-bundle $PLUGIN_DIR --branch=b1 &> /dev/null + $ hehe + hehe from b1 + +Does not say 'Already on b1' on each session startup. + + $ antigen-bundle $PLUGIN_DIR --branch=b1 + +Load plugin from master. + + $ antigen-bundle $PLUGIN_DIR &> /dev/null + $ hehe + hehe diff --git a/tests/bundle-syntaxes.t b/tests/bundle-syntaxes.t new file mode 100644 index 0000000..983e692 --- /dev/null +++ b/tests/bundle-syntaxes.t @@ -0,0 +1,94 @@ +Test helper and mock functions. + + $ ANTIGEN_DEFAULT_REPO_URL=gh-user/repo + + $ b () { + > antigen-bundle "$@" + > } + + $ -antigen-ensure-repo () {} + + $ -antigen-load () { + > echo "url: $1" + > echo "dir: $2" + > echo "clone?: $3" + > } + +Short and sweet. + + $ b lol + url: https://github.com/gh-user/repo.git + dir: plugins/lol + clone?: true + +Short repo url. + + $ b github-username/repo-name + url: https://github.com/github-username/repo-name.git + dir: / + clone?: true + +Short repo url with `.git` suffix. + + $ b github-username/repo-name.git + url: https://github.com/github-username/repo-name.git + dir: / + clone?: true + +Long repo url. + + $ b https://github.com/user/repo.git + url: https://github.com/user/repo.git + dir: / + clone?: true + +Long repo url with missing `.git` suffix (should'nt add the suffix). + + $ b https://github.com/user/repo + url: https://github.com/user/repo + dir: / + clone?: true + +Short repo with location. + + $ b user/plugin path/to/plugin + url: https://github.com/user/plugin.git + dir: path/to/plugin + clone?: true + +Keyword arguments, in respective places. + + $ b --url=user/repo --loc=path/of/plugin + url: https://github.com/user/repo.git + dir: path/of/plugin + clone?: true + +Keyword arguments, in respective places, with full repo url. + + $ b --url=https://github.com/user/repo.git --loc=plugin/path + url: https://github.com/user/repo.git + dir: plugin/path + clone?: true + +Keyword arguments, in reversed order. + + $ b --loc=path/of/plugin --url=user/repo + url: https://github.com/user/repo.git + dir: path/of/plugin + clone?: true + +Mixed positional and keyword arguments, and skip `loc`. + + $ b user/repo --loc=plugin/loc + url: https://github.com/user/repo.git + dir: plugin/loc + clone?: true + +Just `loc`, using keyword arguments. + + $ b --loc=plugin/path + url: https://github.com/gh-user/repo.git + dir: plugin/path + clone?: true + +TODO: Error reporting with erroneous arguments or usage with incorrect syntax. diff --git a/tests/bundle.t b/tests/bundle.t new file mode 100644 index 0000000..3a69b95 --- /dev/null +++ b/tests/bundle.t @@ -0,0 +1,29 @@ +Load plugin from master. + + $ antigen-bundle $PLUGIN_DIR &> /dev/null + $ hehe + hehe + +Load the plugin again. Just to see nothing happens. + + $ antigen-bundle $PLUGIN_DIR + $ hehe + hehe + +Confirm there is still only one repository. + + $ ls $ADOTDIR/repos | wc -l + 1 + +Load a prezto style module. Should only source the `init.zsh` present in the +module. + + $ antigen-bundle $PLUGIN_DIR2 &> /dev/null + $ hehe2 + hehe2 + +The alias defined in the other zsh file should not be available. + + $ unsourced-alias + zsh: command not found: unsourced-alias + [127] diff --git a/tests/bundles.t b/tests/bundles.t new file mode 100644 index 0000000..696cc6f --- /dev/null +++ b/tests/bundles.t @@ -0,0 +1,26 @@ +Add multiple bundles. + + $ echo "$PLUGIN_DIR\n$PLUGIN_DIR2" | antigen-bundles &> /dev/null + +Check if they are both applied. + + $ hehe + hehe + $ hehe2 + hehe2 + +Clean it all up. + + $ export _ANTIGEN_BUNDLE_RECORD="" + $ antigen-cleanup --force &> /dev/null + +Specify with indentation. + + $ echo " $PLUGIN_DIR\n $PLUGIN_DIR2" | antigen-bundles &> /dev/null + +Again, check if they are both applied. + + $ hehe + hehe + $ hehe2 + hehe2 diff --git a/tests/cleanup.t b/tests/cleanup.t new file mode 100644 index 0000000..d53dc7a --- /dev/null +++ b/tests/cleanup.t @@ -0,0 +1,57 @@ +Firstly, no plugins, nothing to cleanup. + + $ antigen-cleanup --force + You don't have any bundles. + +Load the plugins. + + $ antigen-bundle $PLUGIN_DIR &> /dev/null + $ antigen-bundle $PLUGIN_DIR2 &> /dev/null + +Check the listing. + + $ antigen-list + */test-plugin / plugin true (glob) + */test-plugin2 / plugin true (glob) + +Nothing should be available for cleanup. + + $ antigen-cleanup --force + You don't have any unidentified bundles. + +Clear out the bundles record. + + $ _ANTIGEN_BUNDLE_RECORD="" + +Check the listing, after clearing the record. + + $ antigen-list + You don't have any bundles. + [1] + +Confirm the plugin directory exists. + + $ ls dot-antigen/repos | wc -l + 2 + +Do the cleanup. + + $ antigen-cleanup --force + You have clones for the following repos, but are not used. + */test-plugin (glob) + */test-plugin2 (glob) + + + Deleting clone for */test-plugin... done. (glob) + Deleting clone for */test-plugin2... done. (glob) + +Check the listing, after cleanup. + + $ antigen-list + You don't have any bundles. + [1] + +Confirm the plugin directory does not exist after cleanup. + + $ ls dot-antigen/repos | wc -l + 0 diff --git a/tests/list.t b/tests/list.t new file mode 100644 index 0000000..7b8af1e --- /dev/null +++ b/tests/list.t @@ -0,0 +1,24 @@ +Empty initial listing. + + $ antigen-list + You don't have any bundles. + [1] + +Add a bundle. + + $ antigen-bundle $PLUGIN_DIR &> /dev/null + $ antigen-list + */test-plugin / plugin true (glob) + +Add same bundle and check uniqueness. + + $ antigen-bundle $PLUGIN_DIR + $ antigen-list + */test-plugin / plugin true (glob) + +Add another bundle. + + $ antigen-bundle $PLUGIN_DIR2 &> /dev/null + $ antigen-list + */test-plugin / plugin true (glob) + */test-plugin2 / plugin true (glob) diff --git a/tests/no_local_clone.t b/tests/no_local_clone.t new file mode 100644 index 0000000..8ec41d8 --- /dev/null +++ b/tests/no_local_clone.t @@ -0,0 +1,34 @@ +Load the plugin with no local clone. + + $ antigen-bundle $PLUGIN_DIR --no-local-clone + +Check if the plugin is loaded correctly. + + $ hehe + hehe + +Confirm no clone is made. + + $ test -d dot-antigen + [1] + +Load the plugin with a clone. + + $ antigen-bundle $PLUGIN_DIR &> /dev/null + +Empty the record. + + $ _ANTIGEN_BUNDLE_RECORD= + +Load the plugin again with no local clone. + + $ antigen-bundle $PLUGIN_DIR --no-local-clone + +The cleanup should list the bundle's clone. + + $ antigen-cleanup --force + You have clones for the following repos, but are not used. + */test-plugin (glob) + + + Deleting clone for */test-plugin... done. (glob) diff --git a/tests/revert-update.t b/tests/revert-update.t new file mode 100644 index 0000000..f4763bc --- /dev/null +++ b/tests/revert-update.t @@ -0,0 +1,59 @@ +Load and test plugin. + + $ antigen-bundle $PLUGIN_DIR &> /dev/null + $ hehe + hehe + +Save the current HEAD of the plugin. + + $ old_version="$(pg rev-parse HEAD)" + +Modify the plugin. + + $ cat > $PLUGIN_DIR/aliases.zsh < alias hehe='echo hehe, updated' + > EOF + $ pg commit -am 'Updated message' + \[master [a-f0-9]{7}\] Updated message (re) + 1 file changed, 1 insertion(+), 1 deletion(-) + +Save the new HEAD of the plugin. + + $ new_version="$(pg rev-parse HEAD)" + +Define a convenience function to get the current version. + + $ current-version () {(cd dot-antigen/repos/* && git rev-parse HEAD)} + +Confirm we currently have the old version. + + $ [[ $(current-version) == $old_version ]] + +Run antigen's update. + + $ antigen-update + **** Pulling */test-plugin (glob) + From */test-plugin (glob) + ???????..??????? master -> origin/master (glob) + Updating ???????..??????? (glob) + Fast-forward + aliases.zsh |\s+2 \+- (re) + 1 file changed, 1 insertion(+), 1 deletion(-) + Updated from ??????? to ???????. (glob) + ??????? Updated message (glob) + aliases.zsh |\s+2 +- (re) + 1 file changed, 1 insertion(+), 1 deletion(-) + + +Confirm we have the new version. + + $ [[ $(current-version) == $new_version ]] + +Run update again, with no changes in the origin repo. + + $ antigen-revert + Reverted to state before running -update on *. (glob) + +Confirm we have the old version again. + + $ [[ $(current-version) == $old_version ]] diff --git a/tests/selfupdate.t b/tests/selfupdate.t new file mode 100644 index 0000000..b8fc970 --- /dev/null +++ b/tests/selfupdate.t @@ -0,0 +1,69 @@ +Set environment variables for this test case + + $ export TEST_DIR=$PWD + $ export TEST_HOST=$TEST_DIR/host + $ export TEST_NORMAL=$TEST_DIR/client + $ export TEST_SUBMODULE=$TEST_DIR/submodule + +Create fake host repository + + $ mkdir -p $TEST_HOST + $ cd $TEST_HOST + $ git init + Initialized empty Git repository in * (glob) + $ echo 1 > ver + $ git add ver + $ git commit -m "1" + [master (root-commit) ???????] 1 (glob) + 1 file changed, 1 insertion(+) + create mode 100644 ver + +Create a normal repository cloning from host + + $ git clone $TEST_HOST $TEST_NORMAL &> /dev/null + +Create a submodule repository cloning from host + + $ mkdir -p $TEST_SUBMODULE + $ cd $TEST_SUBMODULE + $ git init + Initialized empty Git repository in * (glob) + $ git submodule add $TEST_HOST antigen &> /dev/null + $ git commit -m "1" + [master (root-commit) ???????] 1 (glob) + 2 files changed, 4 insertions(+) + create mode 100644 .gitmodules + create mode 160000 antigen + +Update host repository + + $ cd $TEST_HOST + $ echo 2 > ver + $ git add ver + $ git commit -m "2" + [master ???????] 2 (glob) + 1 file changed, 1 insertion(+), 1 deletion(-) + +Use selfupdate from normal repository + + $ _ANTIGEN_INSTALL_DIR=$TEST_NORMAL antigen-selfupdate + From * (glob) + ???????..??????? master -> origin/master (glob) + Updating ???????..??????? (glob) + Fast-forward + ver | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + $ _ANTIGEN_INSTALL_DIR=$TEST_NORMAL antigen-selfupdate + Already up-to-date. + +Use selfupdate from submodule repository + + $ _ANTIGEN_INSTALL_DIR=$TEST_SUBMODULE/antigen antigen-selfupdate + From * (glob) + ???????..??????? master -> origin/master (glob) + Updating ???????..??????? (glob) + Fast-forward + ver | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + $ _ANTIGEN_INSTALL_DIR=$TEST_SUBMODULE/antigen antigen-selfupdate + Already up-to-date. diff --git a/tests/snapshots.t b/tests/snapshots.t new file mode 100644 index 0000000..2bb066b --- /dev/null +++ b/tests/snapshots.t @@ -0,0 +1,34 @@ +Load a couple of plugins. + + $ antigen-bundle $PLUGIN_DIR &> /dev/null + $ antigen-bundle $PLUGIN_DIR2 &> /dev/null + +Create a snapshot file. + + $ test -f snapshot-file + [1] + $ antigen-snapshot snapshot-file + $ test -f snapshot-file + +See the contents of the snapshot file. + + $ cat snapshot-file + version='1'; created_on='*'; checksum='*'; (glob) + .{40} .*/test-plugin (re) + .{40} .*/test-plugin2 (re) + +Reset the antigen's bundle record and run cleanup. + + $ unset _ANTIGEN_BUNDLE_RECORD + $ antigen-cleanup --force | grep '^Deleting' | wc -l + 2 + +Restore from the snapshot. + + $ ls dot-antigen/repos | wc -l + 0 + $ antigen-restore snapshot-file + Restoring from snapshot-file... done. + Please open a new shell to get the restored changes. + $ ls dot-antigen/repos | wc -l + 2 diff --git a/tests/theme.t b/tests/theme.t new file mode 100644 index 0000000..dfdc6d2 --- /dev/null +++ b/tests/theme.t @@ -0,0 +1,5 @@ +Load the theme explicitly. + + $ antigen-theme $PLUGIN_DIR silly &> /dev/null + $ echo "$PS1" + prompt> diff --git a/tests/update.t b/tests/update.t new file mode 100644 index 0000000..df94b04 --- /dev/null +++ b/tests/update.t @@ -0,0 +1,47 @@ +Load plugin. + + $ antigen-bundle $PLUGIN_DIR &> /dev/null + $ hehe + hehe + +Update the plugin. + + $ cat > $PLUGIN_DIR/aliases.zsh < alias hehe='echo hehe, updated' + > EOF + $ pg commit -am 'Updated message' + \[master [a-f0-9]{7}\] Updated message (re) + 1 file changed, 1 insertion(+), 1 deletion(-) + +Run antigen's update. + + $ antigen-update + **** Pulling */test-plugin (glob) + From */test-plugin (glob) + ???????..??????? master -> origin/master (glob) + Updating ???????..??????? (glob) + Fast-forward + aliases.zsh |\s+2 \+- (re) + 1 file changed, 1 insertion(+), 1 deletion(-) + Updated from ??????? to ???????. (glob) + ??????? Updated message (glob) + aliases.zsh |\s+2 \+- (re) + 1 file changed, 1 insertion(+), 1 deletion(-) + + +Confirm there is still only one repository. + + $ ls $ADOTDIR/repos | wc -l + 1 + +The new alias should not activate. + + $ hehe + hehe + +Run update again, with no changes in the origin repo. + + $ antigen-update + **** Pulling */test-plugin (glob) + Already up-to-date. + diff --git a/tests/url-resolver.t b/tests/url-resolver.t new file mode 100644 index 0000000..a4f4436 --- /dev/null +++ b/tests/url-resolver.t @@ -0,0 +1,33 @@ +Helper alias. + + $ alias resolve=-antigen-resolve-bundle-url + +Complete urls. + + $ resolve https://github.com/zsh-users/antigen.git + https://github.com/zsh-users/antigen.git + $ resolve git://github.com/zsh-users/antigen.git + git://github.com/zsh-users/antigen.git + $ resolve git@github.com:zsh-users/antigen.git + git@github.com:zsh-users/antigen.git + +Complete github urls, missing the `.git` suffix. + + $ resolve https://github.com/zsh-users/antigen + https://github.com/zsh-users/antigen + $ resolve git://github.com/zsh-users/antigen + git://github.com/zsh-users/antigen + $ resolve git@github.com:zsh-users/antigen + git@github.com:zsh-users/antigen + +Just username and repo name. + + $ resolve zsh-users/antigen + https://github.com/zsh-users/antigen.git + $ resolve zsh-users/antigen.git + https://github.com/zsh-users/antigen.git + +Local absolute file path. + + $ resolve /path/to/a/local/git/repo + /path/to/a/local/git/repo diff --git a/tests/use.t b/tests/use.t new file mode 100644 index 0000000..2231e8c --- /dev/null +++ b/tests/use.t @@ -0,0 +1,35 @@ +Use unknown library. + + $ antigen-use unknown + Usage: antigen-use + Where is any one of the following: + * oh-my-zsh + * prezto + [1] + +Missing argument. + + $ antigen-use + Usage: antigen-use + Where is any one of the following: + * oh-my-zsh + * prezto + [1] + +Mock out the library loading functions. + + $ -antigen-use-oh-my-zsh () { echo Using oh-my-zsh. } + $ -antigen-use-prezto () { echo Using prezto. } + +Note: We lack tests for these internal functions. I'm not sure how feasible +testing them is given they most certainly use the network. + +Use oh-my-zsh library. + + $ antigen-use oh-my-zsh + Using oh-my-zsh. + +Use prezto library. + + $ antigen-use prezto + Using prezto. diff --git a/travis-ppa.sh b/travis-ppa.sh new file mode 100755 index 0000000..bc34d70 --- /dev/null +++ b/travis-ppa.sh @@ -0,0 +1,5 @@ +#! /bin/sh +if [ $PPA != 'none' ];then + sudo apt-add-repository -y $PPA; + sudo apt-get update -qq; +fi