├── .github ├── no-response.yml └── stale.yml ├── .gitignore ├── .guardian.yml ├── .travis.yml ├── .version ├── .zunit.yml ├── .zvmrc ├── CODE-OF-CONDUCT.md ├── CONTRIBUTING.md ├── LICENSE ├── README.md ├── build.zsh ├── src ├── commands │ ├── alias.zsh │ ├── analytics.zsh │ ├── bundle.zsh │ ├── cdpath.zsh │ ├── compile.zsh │ ├── config.zsh │ ├── fpath.zsh │ ├── func.zsh │ ├── info.zsh │ ├── init.zsh │ ├── install.zsh │ ├── link.zsh │ ├── list.zsh │ ├── manpath.zsh │ ├── path.zsh │ ├── search.zsh │ ├── self-update.zsh │ ├── switch.zsh │ ├── sync.zsh │ ├── theme.zsh │ ├── uninstall.zsh │ ├── unlink.zsh │ ├── update.zsh │ ├── upgrade.zsh │ └── var.zsh ├── helpers.zsh └── zulu.zsh ├── tests ├── _output │ └── .gitkeep ├── _support │ ├── .gitkeep │ └── bootstrap └── commands │ ├── alias.zunit │ ├── bundle.zunit │ ├── cdpath.zunit │ ├── config.zunit │ ├── fpath.zunit │ ├── func.zunit │ ├── install.zunit │ ├── list.zunit │ ├── manpath.zunit │ ├── path.zunit │ ├── self-update.zunit │ ├── switch.zunit │ ├── theme.zunit │ ├── uninstall.zunit │ ├── update.zunit │ ├── upgrade.zunit │ └── var.zunit └── zulu.zsh-completion /.github/no-response.yml: -------------------------------------------------------------------------------- 1 | # Configuration for probot-no-response - https://github.com/probot/no-response 2 | 3 | # Number of days of inactivity before an Issue is closed for lack of response 4 | daysUntilClose: 14 5 | # Label requiring a response 6 | responseRequiredLabel: 'more information needed' 7 | # Comment to post when closing an Issue for lack of response. Set to `false` to disable 8 | closeComment: > 9 | This issue has been automatically closed because there has been no response 10 | to our request for more information from the original author. With only the 11 | information that is currently in the issue, we don't have enough information 12 | to take action. Please reach out if you have or find the answers we need so 13 | that we can investigate further. 14 | -------------------------------------------------------------------------------- /.github/stale.yml: -------------------------------------------------------------------------------- 1 | # Configuration for probot-stale - https://github.com/probot/stale 2 | 3 | # Number of days of inactivity before an Issue or Pull Request becomes stale 4 | daysUntilStale: 365 5 | # Number of days of inactivity before a stale Issue or Pull Request is closed 6 | daysUntilClose: 7 7 | # Issues or Pull Requests with these labels will never be considered stale 8 | exemptLabels: 9 | - future 10 | # Label to use when marking as stale 11 | staleLabel: stale 12 | # Comment to post when marking as stale. Set to `false` to disable 13 | markComment: > 14 | This issue has been automatically marked as stale because it has not had 15 | recent activity. It will be closed if no further activity occurs. Thank you 16 | for your contributions. 17 | # Comment to post when removing the stale label. Set to `false` to disable 18 | unmarkComment: false 19 | # Comment to post when closing a stale Issue or Pull Request. Set to `false` to disable 20 | closeComment: false 21 | # Limit to only `issues` or `pulls` 22 | # only: issues 23 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Ignore files generated by nested Zulu install 2 | tests/_support/.config/* 3 | tests/_support/.zulu/* 4 | tests/_support/zulu-install.zsh 5 | 6 | # Ignore output 7 | tests/_output/* 8 | !tests/_output/.gitkeep 9 | 10 | /zulu 11 | *.zwc 12 | -------------------------------------------------------------------------------- /.guardian.yml: -------------------------------------------------------------------------------- 1 | files: ./tests/commands/**/* 2 | run: zunit "%file%" 3 | --- 4 | files: ./src/**/*.zsh 5 | run: ./build.zsh 6 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | addons: 2 | apt: 3 | packages: 4 | - zsh 5 | - ncurses-dev 6 | - autoconf 7 | - yodl 8 | - man 9 | language: generic 10 | cache: 11 | apt: true 12 | directories: 13 | - "$HOME/.zvm" 14 | dist: trusty 15 | matrix: 16 | include: 17 | - env: ZVM_VERSION='5.0.8' 18 | - env: ZVM_VERSION='5.1.1' 19 | - env: ZVM_VERSION='5.2' 20 | - env: ZVM_VERSION='5.3.1' 21 | install: 22 | - if [[ $(ls "$HOME/.zvm" | wc -l) -eq 0 ]]; then rm -rf "$HOME/.zvm"; fi 23 | - mkdir .bin 24 | - curl -L https://raw.githubusercontent.com/molovo/revolver/master/revolver > .bin/revolver 25 | - curl -L https://raw.githubusercontent.com/molovo/color/master/color.zsh > .bin/color 26 | - curl -L https://raw.githubusercontent.com/molovo/zvm/master/zvm > .bin/zvm 27 | - curl -L https://github.com/molovo/zunit/releases/download/v0.8.0/zunit > .bin/zunit 28 | - chmod u+x .bin/{color,revolver,zunit,zvm} 29 | - export PATH="$HOME/.zvm/bin:$PWD/.bin:$PATH" 30 | before_script: 31 | - zvm use ${ZVM_VERSION} 32 | - "./build.zsh" 33 | script: zunit 34 | notifications: 35 | email: false 36 | slack: 37 | secure: odq7Bn+HU3VLl7g8ZY4r2ILsq9g7DnEh802zOporpmeayzU2Zd44L+R6QG8oR/rfeOSNpczmn6ERrwP1rhyPsG16ziU1SXSlxUGjvjCqoaFi7UZduyN/29FdziBCcfgP454EjMB696/JBUTwfKtsxqGSSrVuBUWeFlRO0Q8Une8LL+dyZ2wenCDKD14f7qxmUOxM/11DnvN1P9KNhJvX4jD8qLNB/QnY788KRGnsR1kruBT9xM1VUSuEj5wRqMqSpaQNGPNQxJUX2A/tWNXlZsnaGGVI7KTTDleylQwG+MebXdB4En2UPnW8iPIYmYNKUGFRyVq0PPAuq081heoiFj0f5otZb1JJcWobw3fkXWzukEyjqVaGU8WM90qvFNTn7hOuhN5v902n+v7H3QlRD2W+ac1+cGKoFyZxVOVH7mMxRrbGd85i2xr35OmqketOhvTep2snr8Oj4kLD6X6J7bvZPQVHSMkfgZi8XdU08yGJkEkH837kUD0VRZA89MZ7EWT8SstuxosAgUAyUqmkz8bOmTwGQksna5qj9zHiCGiYinrHzjFwhd8QnKW45CKflxxwGuW7Ve00Nef9QNWWrDYbvL5JJZJVGHhsTS+ArVUAsHDrMHg/OeITKSakDlDv0i+U1V0YyvOW1gFnE0xeA7ei7y0kL1GSywRFAZkOp24= 38 | -------------------------------------------------------------------------------- /.version: -------------------------------------------------------------------------------- 1 | 1.5.0 2 | -------------------------------------------------------------------------------- /.zunit.yml: -------------------------------------------------------------------------------- 1 | tap: false 2 | directories: 3 | tests: tests 4 | output: tests/_output 5 | support: tests/_support 6 | -------------------------------------------------------------------------------- /.zvmrc: -------------------------------------------------------------------------------- 1 | 5.1.1 2 | -------------------------------------------------------------------------------- /CODE-OF-CONDUCT.md: -------------------------------------------------------------------------------- 1 | # Contributor Covenant Code of Conduct 2 | 3 | ## Our Pledge 4 | 5 | In the interest of fostering an open and welcoming environment, we as 6 | contributors and maintainers pledge to making participation in our project and 7 | our community a harassment-free experience for everyone, regardless of age, body 8 | size, disability, ethnicity, gender identity and expression, level of experience, 9 | nationality, personal appearance, race, religion, or sexual identity and 10 | orientation. 11 | 12 | ## Our Standards 13 | 14 | Examples of behavior that contributes to creating a positive environment 15 | include: 16 | 17 | * Using welcoming and inclusive language 18 | * Being respectful of differing viewpoints and experiences 19 | * Gracefully accepting constructive criticism 20 | * Focusing on what is best for the community 21 | * Showing empathy towards other community members 22 | 23 | Examples of unacceptable behavior by participants include: 24 | 25 | * The use of sexualized language or imagery and unwelcome sexual attention or 26 | advances 27 | * Trolling, insulting/derogatory comments, and personal or political attacks 28 | * Public or private harassment 29 | * Publishing others' private information, such as a physical or electronic 30 | address, without explicit permission 31 | * Other conduct which could reasonably be considered inappropriate in a 32 | professional setting 33 | 34 | ## Our Responsibilities 35 | 36 | Project maintainers are responsible for clarifying the standards of acceptable 37 | behavior and are expected to take appropriate and fair corrective action in 38 | response to any instances of unacceptable behavior. 39 | 40 | Project maintainers have the right and responsibility to remove, edit, or 41 | reject comments, commits, code, wiki edits, issues, and other contributions 42 | that are not aligned to this Code of Conduct, or to ban temporarily or 43 | permanently any contributor for other behaviors that they deem inappropriate, 44 | threatening, offensive, or harmful. 45 | 46 | ## Scope 47 | 48 | This Code of Conduct applies both within project spaces and in public spaces 49 | when an individual is representing the project or its community. Examples of 50 | representing a project or community include using an official project e-mail 51 | address, posting via an official social media account, or acting as an appointed 52 | representative at an online or offline event. Representation of a project may be 53 | further defined and clarified by project maintainers. 54 | 55 | ## Enforcement 56 | 57 | Instances of abusive, harassing, or otherwise unacceptable behavior may be 58 | reported by contacting the project team at hi@molovo.co. All 59 | complaints will be reviewed and investigated and will result in a response that 60 | is deemed necessary and appropriate to the circumstances. The project team is 61 | obligated to maintain confidentiality with regard to the reporter of an incident. 62 | Further details of specific enforcement policies may be posted separately. 63 | 64 | Project maintainers who do not follow or enforce the Code of Conduct in good 65 | faith may face temporary or permanent repercussions as determined by other 66 | members of the project's leadership. 67 | 68 | ## Attribution 69 | 70 | This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4, 71 | available at [http://contributor-covenant.org/version/1/4][version] 72 | 73 | [homepage]: http://contributor-covenant.org 74 | [version]: http://contributor-covenant.org/version/1/4/ -------------------------------------------------------------------------------- /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | # Contributing to Zulu 2 | 3 | ✨ Thanks for contributing to Zulu! ✨ 4 | 5 | Please note that this project is released with a [Contributor Code of Conduct](code-of-conduct.md). By participating in this project you agree to abide by its terms. 6 | 7 | ## How can I contribute? 8 | 9 | ### Improve documentation 10 | 11 | As a user of Zulu you're the perfect candidate to help us improve our documentation. Typo corrections, error fixes, better explanations, more examples, etc. Open issues for things that could be improved. Anything. Even improvements to this document. 12 | 13 | Use the [`docs` label](https://github.com/zulu-zsh/zulu/labels/docs) to find suggestions for what we'd love to see more documentation on. 14 | 15 | ### Improve issues 16 | 17 | Some issues are created with missing information, not reproducible, or plain invalid. Help make them easier to resolve. Handling issues takes a lot of time that we could rather spend on fixing bugs and adding features. 18 | 19 | ### Give feedback on issues 20 | 21 | We're always looking for more opinions on discussions in the issue tracker. It's a good opportunity to influence the future direction of Zulu. 22 | 23 | The [`question` label](https://github.com/zulu-zsh/zulu/labels/question) is a good place to find ongoing discussions. 24 | 25 | ### Write code 26 | 27 | You can use issue labels to discover issues you could help out with: 28 | 29 | * [`blocked` issues](https://github.com/zulu-zsh/zulu/labels/blocked) need help getting unstuck 30 | * [`bug` issues](https://github.com/zulu-zsh/zulu/labels/bug) are known bugs we'd like to fix 31 | * [`enhancement` issues](https://github.com/zulu-zsh/zulu/labels/enhancement) are features we're open to including 32 | * [`performance` issues](https://github.com/zulu-zsh/zulu/labels/performance) track ideas on how to improve Zulu’s performance 33 | 34 | The [`help wanted`](https://github.com/zulu-zsh/zulu/labels/help%20wanted) and [`good for beginner`](https://github.com/zulu-zsh/zulu/labels/good%20for%20beginner) labels are especially useful. 35 | 36 | You may find an issue is assigned, or has the [`assigned` label](https://github.com/zulu-zsh/zulu/labels/assigned). Please double-check before starting on this issue because somebody else is likely already working on it. 37 | 38 | We'd like to fix [`priority` issues](https://github.com/zulu-zsh/zulu/labels/priority) first. We'd love to see progress on [`low-priority` issues](https://github.com/zulu-zsh/zulu/labels/low%20priority) too. [`future` issues](https://github.com/zulu-zsh/zulu/labels/future) are those that we'd like to get to, but not anytime soon. Please check before working on these since we may not yet want to take on the burden of supporting those features. 39 | 40 | ### Hang out in our chat 41 | 42 | We have a [chat](https://gitter.im/zulu-zsh/zulu). Jump in there and lurk, talk to us, and help others. 43 | 44 | ## Submitting an issue 45 | 46 | - The issue tracker is for issues. Use our [chat](https://gitter.im/zulu-zsh/zulu) for support. 47 | - Search the issue tracker before opening an issue. 48 | - Ensure you're using the latest version of Zulu. 49 | - Use a clear and descriptive title. 50 | - Include as much information as possible: Steps to reproduce the issue, error message, ZSH version, operating system, etc. 51 | - The more time you put into an issue, the more we will. 52 | - [The best issue report is a failing test proving it.](https://twitter.com/sindresorhus/status/579306280495357953) 53 | 54 | ## Submitting a pull request 55 | 56 | - Non-trivial changes are often best discussed in an issue first, to prevent you from doing unnecessary work. 57 | - For ambitious tasks, you should try to get your work in front of the community for feedback as soon as possible. Open a pull request as soon as you have done the minimum needed to demonstrate your idea. At this early stage, don't worry about making things perfect, or 100% complete. Add a [WIP] prefix to the title, and describe what you still need to do. This lets reviewers know not to nit-pick small details or point out improvements you already know you need to make. 58 | - New features should be accompanied with tests and documentation. 59 | - Don't include unrelated changes. 60 | - Make the pull request from a [topic branch](https://github.com/dchelimsky/rspec/wiki/Topic-Branches), not master. 61 | - Use a clear and descriptive title for the pull request and commits. 62 | - Write a convincing description of why we should land your pull request. It's your job to convince us. Answer "why" it's needed and provide use-cases. 63 | - You might be asked to do changes to your pull request. There's never a need to open another pull request. [Just update the existing one.](https://github.com/RichardLitt/docs/blob/master/amending-a-commit-guide.md) -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2016 James Dinsdale (molovo.co) 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 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Zulu 2 | 3 | Zulu: [![GitHub release](https://img.shields.io/github/release/zulu-zsh/zulu.svg)](https://github.com/zulu-zsh/zulu/releases/latest) [![Build Status](https://travis-ci.org/zulu-zsh/zulu.svg?branch=master)](https://travis-ci.org/zulu-zsh/zulu) | Index: [![Build Status](https://travis-ci.org/zulu-zsh/index.svg?branch=master)](https://travis-ci.org/zulu-zsh/index) | [![Join the chat at https://gitter.im/zulu-zsh/zulu](https://badges.gitter.im/zulu-zsh/zulu.svg)](https://gitter.im/zulu-zsh/zulu?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge) 4 | 5 | Thanks for using Zulu. Zulu is a environment manager for ZSH, which aims to make it easy to manage your shell without writing any code. 6 | 7 | ## Features 8 | 9 | * Easily manage your shell environment without editing files. 10 | * Create aliases, functions and environment variables, and have them available to you at the next shell startup. 11 | * Add and remove directories from `$path`, `$fpath` and `$cdpath` with simple commands. 12 | * Install packages, plugins and themes easily, and have them available to you immediately. 13 | 14 | ## Requirements 15 | 16 | * ZSH `5.0.2` or above 17 | * git `1.9.1` or above 18 | 19 | ## Installation 20 | 21 | Zulu comes with its own install script, which is the recommended method of install. 22 | 23 | ```sh 24 | curl -L https://zulu.molovo.co/install | zsh && zsh 25 | ``` 26 | 27 | If you'd rather not pipe a script into ZSH, take a look at the [manual installation process](https://zulu.molovo.co/docs/getting-started/manual-installation). 28 | 29 | ## Usage 30 | 31 | For detailed usage instructions, take a look at Zulu's [official documentation](https://zulu.molovo.co/docs) 32 | 33 | ## Contributing 34 | 35 | All contributions are welcome, and encouraged. Please read our [contribution guidelines](CONTRIBUTING.md) and [code of conduct](CODE-OF-CONDUCT.md) for more information. 36 | 37 | ## License 38 | 39 | Copyright (c) 2016 James Dinsdale (molovo.co) 40 | 41 | Zulu is licensed under The MIT License (MIT) 42 | 43 | Icon is [Shield](https://thenounproject.com/search/?q=zulu&i=163736) by Ivan Colic from The Noun Project 44 | 45 | ## Team 46 | 47 | * [James Dinsdale](http://molovo.co) 48 | -------------------------------------------------------------------------------- /build.zsh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env zsh 2 | 3 | # Clear the file to start with 4 | cat /dev/null > zulu 5 | 6 | # Start with the shebang 7 | echo "#!/usr/bin/env zsh\n" >> zulu 8 | 9 | # We need to do some fancy globbing 10 | setopt EXTENDED_GLOB 11 | 12 | # Print each of the source files into the target, removing any comments 13 | # from the compiled executable 14 | cat src/**/(^zulu).zsh | grep -v -E '^(\s*#.*[^"])$' >> zulu 15 | 16 | # Print the main command last 17 | cat src/zulu.zsh | grep -v -E '^(\s*#.*[^"])$' >> zulu 18 | 19 | # Make sure the file is executable 20 | chmod u+x zulu 21 | 22 | # Let the user know we're finished 23 | echo "\033[0;32m✔\033[0;m zulu built successfully" 24 | -------------------------------------------------------------------------------- /src/commands/alias.zsh: -------------------------------------------------------------------------------- 1 | ### 2 | # Output usage information 3 | ### 4 | function _zulu_alias_usage() { 5 | builtin echo $(_zulu_color yellow "Usage:") 6 | builtin echo " zulu alias [args]" 7 | builtin echo 8 | builtin echo $(_zulu_color yellow "Contexts:") 9 | builtin echo " add Add an alias" 10 | builtin echo " load Load all aliases from alias file" 11 | builtin echo " rm Remove an alias" 12 | } 13 | 14 | ### 15 | # Add an alias 16 | ### 17 | function _zulu_alias_add() { 18 | local existing alias cmd flag global 19 | 20 | builtin zparseopts -D \ 21 | g=global -global=global 22 | 23 | alias="$1" 24 | cmd="${(@)@:2}" 25 | 26 | existing=$(command cat $aliasfile | command grep -E -e "^alias(\ -g)?\ $alias=") 27 | if [[ $existing != "" ]]; then 28 | builtin echo $(_zulu_color red "Alias '$alias' already exists") 29 | return 1 30 | fi 31 | 32 | if [[ -n $global ]]; then 33 | flag=' -g' 34 | fi 35 | 36 | builtin echo "alias$flag $alias='$cmd'" >> $aliasfile 37 | 38 | zulu alias load 39 | builtin echo "$(_zulu_color green '✔') Alias '$alias' added" 40 | } 41 | 42 | ### 43 | # Remove an alias 44 | ### 45 | function _zulu_alias_rm() { 46 | local existing alias 47 | 48 | alias="$1" 49 | 50 | existing=$(command cat $aliasfile | command grep -E -e "^alias(\ -g)?\ $alias=") 51 | if [[ -z $existing ]]; then 52 | builtin echo $(_zulu_color red "Alias '$alias' does not exist") 53 | return 1 54 | fi 55 | 56 | builtin echo "$(command cat $aliasfile | command grep -E -ve "^alias(\ -g)?\ $alias=")" >! $aliasfile 57 | unalias $alias 58 | 59 | zulu alias load 60 | builtin echo "$(_zulu_color green '✔') Alias '$alias' removed" 61 | } 62 | 63 | ### 64 | # Load aliases 65 | ### 66 | function _zulu_alias_load() { 67 | builtin source $aliasfile 68 | } 69 | 70 | ### 71 | # Zulu command to handle path manipulation 72 | ### 73 | function _zulu_alias() { 74 | local ctx base aliasfile 75 | 76 | # Parse options 77 | builtin zparseopts -D h=help -help=help 78 | 79 | # Output help and return if requested 80 | if [[ -n $help ]]; then 81 | _zulu_alias_usage 82 | return 83 | fi 84 | 85 | # Set up some variables 86 | base=${ZULU_DIR:-"${ZDOTDIR:-$HOME}/.zulu"} 87 | config=${ZULU_CONFIG_DIR:-"${ZDOTDIR:-$HOME}/.config/zulu"} 88 | aliasfile="${config}/alias" 89 | 90 | # If no context is passed, output the contents of the aliasfile 91 | if [[ "$1" = "" ]]; then 92 | cat "$aliasfile" 93 | return 94 | fi 95 | 96 | # Get the context 97 | ctx="$1" 98 | 99 | # Call the relevant function 100 | _zulu_alias_${ctx} "${(@)@:2}" 101 | } 102 | -------------------------------------------------------------------------------- /src/commands/analytics.zsh: -------------------------------------------------------------------------------- 1 | ### 2 | # Get a unique hash which refers to the user 3 | ### 4 | function _zulu_analytics_user_key() { 5 | local -a hash_cmds; hash_cmds=(sha256sum gsha256sum) 6 | local cmd hash_cmd 7 | 8 | # If a user ID is already set in the config file. 9 | # we don't need to generate one 10 | if zulu config user_id >/dev/null 2>&1; then 11 | builtin echo $(zulu config user_id) 12 | return 13 | fi 14 | 15 | # Loop through each of the hashing commands 16 | for hash_cmd in $hash_cmds; do 17 | # Check if the command is installed 18 | if builtin type $hash_cmd >/dev/null 2>&1; then 19 | # It's installed, we'll set it to be used 20 | # and break the loop 21 | cmd=$hash_cmd 22 | break 23 | fi 24 | done 25 | 26 | # A hashing command could not be found, we'll just 27 | # skip hashing for this user 28 | if [[ -z $cmd ]]; then 29 | return 30 | fi 31 | 32 | # Create a hash from the user's username and hostname 33 | hash=$(builtin echo -n "$USER@$HOST" | $cmd) 34 | 35 | # Store the hash in the Zulu config file 36 | # and return it 37 | zulu config set user_id ${hash:0:$(( ${#hash} - 2 ))} 38 | } 39 | 40 | ### 41 | # Send the event data to Heap 42 | ### 43 | function _zulu_analytics_track() { 44 | if ! _zulu_analytics_enabled; then 45 | return 46 | fi 47 | 48 | local evt="$1" user="$(_zulu_analytics_user_key)" 49 | 50 | # Yes, you could run this command to post data 51 | # directly to our analytics provider, but please 52 | # don't. We collect this data to allow us to see 53 | # which of Zulu's features are most important to 54 | # you, the user, and find ways to improve Zulu. 55 | # If the data is inaccurate, it makes supporting 56 | # Zulu more difficult. Please don't be a dick. 57 | command curl \ 58 | -X POST \ 59 | -H "Content-Type: application/json" \ 60 | -d "{ 61 | \"app_id\": \"2918660738\", 62 | \"identity\": \"$user\", 63 | \"event\": \"$evt\" 64 | }" 'https://heapanalytics.com/api/track' >/dev/null 2>&1 65 | } 66 | 67 | function _zulu_analytics_enabled() { 68 | if ! zulu config analytics >/dev/null 2>&1; then 69 | # Turn on by default 70 | zulu config set analytics true >/dev/null 2>&1 71 | 72 | # Let the user know they can opt-out 73 | builtin echo 'Zulu collects anonymous usage data to allow the developers to see 74 | which of Zulu'\''s features are most important to you, the user, and to 75 | continue to improve Zulu for you. 76 | 77 | If you'\''d like to opt-out of sending this anonymous data, you can do so by 78 | running the following command 79 | 80 | zulu config set analytics false' 81 | fi 82 | 83 | # If the user has opted out, go no further 84 | if [[ $(zulu config analytics) != 'true' ]]; then 85 | return 1 86 | fi 87 | } 88 | -------------------------------------------------------------------------------- /src/commands/bundle.zsh: -------------------------------------------------------------------------------- 1 | ### 2 | # Print usage information 3 | ### 4 | function _zulu_bundle_usage() { 5 | builtin echo $(_zulu_color yellow "Usage:") 6 | builtin echo " zulu bundle [options]" 7 | builtin echo 8 | builtin echo $(_zulu_color yellow "Options:") 9 | builtin echo " -c, --cleanup Uninstall packages not in packagefile" 10 | builtin echo " -f, --file Specify a packagefile" 11 | builtin echo " -d, --dump Dump installed packages to packagefile" 12 | builtin echo " -h, --help Output this help text and exit" 13 | builtin echo " -x, --force Force writing of packages to an existing file" 14 | } 15 | 16 | ### 17 | # Dump installed packages to file 18 | ### 19 | function _zulu_bundle_dump() { 20 | local -a installed; installed=($(zulu list --installed --simple --branch --tag)) 21 | 22 | # Check if the packagefile exists 23 | if [[ -f $packagefile ]]; then 24 | # If the --force option was passed, overwrite it 25 | if [[ -n $force ]]; then 26 | builtin echo ${(@F)installed} >! $packagefile 27 | return 28 | fi 29 | 30 | # Throw an error 31 | builtin echo $(_zulu_color red "Packagefile at $packagefile already exists") 32 | builtin echo 'Use `zulu bundle --dump --force` to overwrite' 33 | return 1 34 | fi 35 | 36 | # Write to the packagefile 37 | builtin echo ${(@F)installed} > $packagefile 38 | return 39 | } 40 | 41 | ### 42 | # Uninstall packages not in packagefile 43 | ### 44 | function _zulu_bundle_cleanup() { 45 | local -a installed; installed=($(zulu list --installed --simple --branch --tag)) 46 | 47 | # Loop through each of the installed packages 48 | for package in "${installed[@]}"; do 49 | # Search the packagefile 50 | check=$(cat $packagefile | grep -e "^${package}$") 51 | 52 | # If not found, uninstall it 53 | if [[ -z $check ]]; then 54 | zulu uninstall $package 55 | fi 56 | done 57 | } 58 | 59 | ### 60 | # The zulu bundle command 61 | ### 62 | function _zulu_bundle() { 63 | local help file cleanup dump force base config packagefile packages 64 | 65 | # Parse options 66 | builtin zparseopts -D h=help -help=help \ 67 | f:=file -file:=file \ 68 | c=cleanup -cleanup=cleanup \ 69 | d=dump -dump=dump \ 70 | x=force -force=force 71 | 72 | # Output help and return if requested 73 | if [[ -n $help ]]; then 74 | _zulu_bundle_usage 75 | return 76 | fi 77 | 78 | # Set up some variables 79 | base=${ZULU_DIR:-"${ZDOTDIR:-$HOME}/.zulu"} 80 | config=${ZULU_CONFIG_DIR:-"${ZDOTDIR:-$HOME}/.config/zulu"} 81 | 82 | # Set the path for the default packagefile 83 | packagefile="$config/packages" 84 | 85 | # If a file is passed, use that as the packagefile 86 | if [[ -n $file ]]; then 87 | builtin shift file 88 | packagefile="$file" 89 | fi 90 | 91 | # Check for the dump option 92 | if [[ -n $dump ]]; then 93 | _zulu_bundle_dump 94 | return $? 95 | fi 96 | 97 | # Check that the packagefile exists, and throw an 98 | # error if it does not 99 | if [[ ! -f $packagefile ]]; then 100 | builtin echo $(_zulu_color red 'Packagefile cannot be found') 101 | return 1 102 | fi 103 | 104 | # Check for the cleanup option 105 | if [[ -n $cleanup ]]; then 106 | _zulu_bundle_cleanup 107 | return $? 108 | fi 109 | 110 | local oldIFS=$IFS 111 | IFS=$'\n' 112 | 113 | # Load the list of packages 114 | packages=($(cat $packagefile)) 115 | 116 | IFS=$oldIFS 117 | builtin unset oldIFS 118 | 119 | # Loop through the packages 120 | for package in "${packages[@]}"; do 121 | local package_name='' flag='' argument='' install_flags='' 122 | 123 | # Separate the package name from any meta information 124 | local -a parts meta 125 | parts=(${(ps/, /)package}) 126 | package_name="${parts[1]}" 127 | meta=(${(ps/: /)parts[2]}) 128 | 129 | # Skip the package if it is already installed 130 | if _zulu_info_is_installed $package_name; then 131 | continue 132 | fi 133 | 134 | # Separate the meta information into flags and arguments 135 | if [[ ${#meta} -gt 0 ]]; then 136 | flag="${meta[1]}" 137 | argument="${meta[2]}" 138 | 139 | # Create the correct install flags 140 | case ${flag} in 141 | branch ) 142 | install_flags="--branch $argument" 143 | ;; 144 | tag ) 145 | install_flags="--tag $argument" 146 | ;; 147 | esac 148 | fi 149 | 150 | # Install the package 151 | zulu install ${(ps/ /)install_flags} $package_name 152 | done 153 | } 154 | -------------------------------------------------------------------------------- /src/commands/cdpath.zsh: -------------------------------------------------------------------------------- 1 | ### 2 | # Output usage information 3 | ### 4 | function _zulu_cdpath_usage() { 5 | builtin echo $(_zulu_color yellow "Usage:") 6 | builtin echo " zulu cdpath " 7 | builtin echo 8 | builtin echo $(_zulu_color yellow "Context:") 9 | builtin echo " add Add a directory to \$cdpath" 10 | builtin echo " reset Replace the current session \$cdpath with the stored dirs" 11 | builtin echo " rm Remove a directory from \$cdpath" 12 | } 13 | 14 | ### 15 | # Check the existence of a directory when passed as an argument, 16 | # and convert relative paths to absolute 17 | ### 18 | function _zulu_cdpath_parse() { 19 | local dir="$1" check_existing="$2" 20 | 21 | if [[ -d "$PWD/$dir" ]]; then 22 | # If the directory exists in the current working directory 23 | # convert the relative path to absolute 24 | builtin echo "$PWD/$dir" 25 | elif [[ -d "$dir" ]]; then 26 | # If the directory exists as an absolute path, we can use it directly 27 | builtin echo "$dir" 28 | elif [[ "$check_existing" != "false" ]]; then 29 | # The directory could not be found 30 | builtin echo $dir 31 | return 1 32 | fi 33 | } 34 | 35 | ### 36 | # Add a directory to $cdpath 37 | ### 38 | function _zulu_cdpath_add() { 39 | local dir p 40 | local -a items paths; paths=($(cat $pathfile)) 41 | 42 | # Check that each of the passed directories exist, and convert relative 43 | # paths to absolute 44 | for dir in "$@"; do 45 | dir=$(_zulu_cdpath_parse "$dir") 46 | 47 | # If parsing returned with an error, output the error and return 48 | if [[ $? -eq 0 ]]; then 49 | # Add the directory to the array of items 50 | items+="$dir" 51 | 52 | builtin echo "$(_zulu_color green '✔') $dir added to \$cdpath" 53 | else 54 | builtin echo "$(_zulu_color red '✘') $dir cannot be found" 55 | fi 56 | 57 | done 58 | 59 | # Loop through each of the existing paths and add those to the array as well 60 | for p in "$paths[@]"; do 61 | items+="$p" 62 | done 63 | 64 | # Store the new paths in the pathfile, and override $cdpath 65 | _zulu_cdpath_store 66 | _zulu_cdpath_reset 67 | } 68 | 69 | ### 70 | # Remove a directory from $cdpath 71 | ### 72 | function _zulu_cdpath_rm() { 73 | local dir p 74 | local -a items paths; paths=($(cat $pathfile)) 75 | 76 | # Check that each of the passed directories exist, and convert relative 77 | # paths to absolute 78 | for dir in "$@"; do 79 | dir=$(_zulu_cdpath_parse "$dir" "false") 80 | 81 | # If parsing returned with an error, output the error and return 82 | if [[ ! $? -eq 0 ]]; then 83 | builtin echo $dir 84 | return 1 85 | fi 86 | 87 | # Loop through each of the paths, and if they are *not* an exact match, 88 | # we want to keep them 89 | for p in "$paths[@]"; do 90 | if [[ "$p" != "$dir" ]]; then 91 | items+="$p" 92 | fi 93 | done 94 | 95 | builtin echo "$(_zulu_color green '✔') $dir removed from \$cdpath" 96 | done 97 | 98 | # Store the new paths in the pathfile, and override $cdpath 99 | _zulu_cdpath_store 100 | _zulu_cdpath_reset 101 | } 102 | 103 | ### 104 | # Store an array of paths in the pathfile 105 | ### 106 | function _zulu_cdpath_store() { 107 | local separator out 108 | 109 | # Separate the array by newlines, and print the contents to the pathfile 110 | separator=$'\n' 111 | local oldIFS=$IFS 112 | IFS="$separator"; out="${items[*]/#/${separator}}" 113 | builtin echo ${out:${#separator}} >! $pathfile 114 | IFS=$oldIFS 115 | builtin unset oldIFS 116 | } 117 | 118 | ### 119 | # Override the $cdpath variable with the current contents of the pathfile 120 | ### 121 | function _zulu_cdpath_reset() { 122 | local separator out 123 | local -a paths; paths=($(cat $pathfile)) 124 | 125 | typeset -gUa cdpath; cdpath=() 126 | for p in "${paths[@]}"; do 127 | cdpath+="$p" 128 | done 129 | } 130 | 131 | ### 132 | # Zulu command to handle path manipulation 133 | ### 134 | function _zulu_cdpath() { 135 | local ctx base pathfile 136 | 137 | # Parse options 138 | builtin zparseopts -D h=help -help=help 139 | 140 | # Output help and return if requested 141 | if [[ -n $help ]]; then 142 | _zulu_cdpath_usage 143 | return 144 | fi 145 | 146 | # Set up some variables 147 | base=${ZULU_DIR:-"${ZDOTDIR:-$HOME}/.zulu"} 148 | config=${ZULU_CONFIG_DIR:-"${ZDOTDIR:-$HOME}/.config/zulu"} 149 | pathfile="${config}/cdpath" 150 | 151 | # If no context is passed, output the contents of the pathfile 152 | if [[ "$1" = "" ]]; then 153 | command cat "$pathfile" 154 | return 155 | fi 156 | 157 | # Get the context 158 | ctx="$1" 159 | 160 | # Call the relevant function 161 | _zulu_cdpath_${ctx} "${(@)@:2}" 162 | } 163 | -------------------------------------------------------------------------------- /src/commands/compile.zsh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env zsh 2 | 3 | ### 4 | # Output usage information and exit 5 | ### 6 | function _zulu_compile_usage() { 7 | builtin echo '\033[0;32mUsage:\033[0;m' 8 | builtin echo ' zulu_compile [options]' 9 | } 10 | 11 | ### 12 | # Resolve symbolic links to a file, a compare it's last-modified date 13 | # with the compiled version, recompiling if needed 14 | ### 15 | function _zulu_compile_if_needed() { 16 | local file="$1" follow_symlinks 17 | 18 | builtin zparseopts -D \ 19 | f=follow_symlinks -follow-symlinks=follow_symlinks 20 | 21 | # We can't compile files that do not exist 22 | [[ ! -e $file ]] && return 23 | 24 | # Resolve symlinks if necessary 25 | [[ -n $follow_symlinks && -L $file ]] && file=$(command readlink $file) 26 | 27 | # Check if the file is newer than it's compiled version, 28 | # and recompile if necessary 29 | if [[ -s ${file} && ( ! -s ${file}.zwc || ${file} -nt ${file}.zwc) ]]; then 30 | zcompile ${file} 31 | fi 32 | } 33 | 34 | ### 35 | # The main zulu_compile process 36 | ### 37 | (( $+functions[_zulu_compile] )) || function _zulu_compile() { 38 | local base=${ZULU_DIR:-"${ZDOTDIR:-$HOME}/.zulu"} 39 | local config=${ZULU_CONFIG_DIR:-"${ZDOTDIR:-$HOME}/.config/zulu"} 40 | local help version 41 | 42 | builtin zparseopts -D \ 43 | h=help -help=help 44 | 45 | if [[ -n $help ]]; then 46 | _zulu_compile_usage 47 | exit 48 | fi 49 | 50 | setopt EXTENDED_GLOB 51 | # A list of glob paths pointing to files to be compiled 52 | local -a compile_targets; compile_targets=( 53 | # Zulu's core 54 | ${base}/core/zulu 55 | 56 | # Files linked by packages 57 | ${base}/share/**/*^(*.zwc)(#q@) 58 | ${base}/bin/**/*^(*.zwc)(#q@) 59 | 60 | # Completion dump 61 | ${ZDOTDIR:-${HOME}}/.zcomp^(*.zwc)(.) 62 | 63 | # User env files 64 | ${ZDOTDIR:-${HOME}}/.zshenv 65 | ${ZDOTDIR:-${HOME}}/.zlogin 66 | ${ZDOTDIR:-${HOME}}/.zprofile 67 | ${ZDOTDIR:-${HOME}}/.zshrc 68 | ${ZDOTDIR:-${HOME}}/.zlogout 69 | ) 70 | 71 | # A second list of compile targets. These files have their symlinks resolved 72 | # before they are sourced, so we need to follow the symlink before compiling, 73 | # to ensure the compiled version is picked up 74 | local -a linked_compile_targets; linked_compile_targets=( 75 | # Initialisation scripts for packages 76 | ${base}/init/**/*^(*.zwc)(#q@) 77 | ) 78 | 79 | # Loop through each of the files marked for compilation, and compile 80 | # them if necessary 81 | for file in ${(@f)compile_targets}; do 82 | _zulu_compile_if_needed $file 83 | done 84 | 85 | # Loop through each of the files marked for compilation, follow their 86 | # symlinks, and compile them if necessary 87 | for file in ${(@f)linked_compile_targets}; do 88 | _zulu_compile_if_needed --follow-symlinks $file 89 | done 90 | } 91 | -------------------------------------------------------------------------------- /src/commands/config.zsh: -------------------------------------------------------------------------------- 1 | ### 2 | # Output usage information 3 | ### 4 | function _zulu_config_usage() { 5 | builtin echo $(_zulu_color yellow "Usage:") 6 | builtin echo " zulu config " 7 | builtin echo 8 | builtin echo $(_zulu_color yellow "Contexts:") 9 | builtin echo " list List all config values" 10 | builtin echo " get Get a config value" 11 | builtin echo " set Set a config value" 12 | } 13 | 14 | ### 15 | # Set a config value 16 | ### 17 | function _zulu_config_set() { 18 | local key="$1" value="${(@)@:2}" 19 | 20 | _zulu_config_load 21 | 22 | # Rewrite the config file, omitting the key 23 | # we're setting if it exists 24 | builtin echo "$(command cat $configfile | command grep -v -E "^$key:")" >! $configfile 25 | 26 | # Write the new value to the config file 27 | builtin echo "$key: $value" >> $configfile 28 | 29 | # Write the config file again, stripping out any blank lines 30 | builtin echo "$(command cat $configfile | command grep -v -E '^\s*$')" >! $configfile 31 | 32 | zulu config $key 33 | } 34 | 35 | ### 36 | # Get a config value 37 | ### 38 | function _zulu_config_get() { 39 | local key="$1" 40 | 41 | _zulu_config_load 42 | 43 | if (( ! $+zulu_config[$key] )); then 44 | return 1 45 | fi 46 | 47 | builtin echo "$zulu_config[$key]" 48 | } 49 | 50 | ### 51 | # Load the current config 52 | ### 53 | function _zulu_config_load { 54 | [[ ! -f $configfile ]] && touch $configfile 55 | builtin eval $(_zulu_config_parse_yaml) 56 | } 57 | 58 | ### 59 | # Parse the YAML config file 60 | # Based on https://gist.github.com/pkuczynski/8665367 61 | ### 62 | function _zulu_config_parse_yaml() { 63 | local s w fs prefix='zulu_config' 64 | s='[[:space:]]*' 65 | w='[a-zA-Z0-9_]*' 66 | fs="$(builtin echo @|tr @ '\034')" 67 | command sed -ne "s|^\(${s}\)\(${w}\)${s}:${s}\"\(.*\)\"${s}\$|\1${fs}\2${fs}\3|p" \ 68 | -e "s|^\(${s}\)\(${w}\)${s}[:-]${s}\(.*\)${s}\$|\1${fs}\2${fs}\3|p" "$configfile" | 69 | awk -F"${fs}" '{ 70 | indent = length($1)/2; 71 | vname[indent] = $2; 72 | for (i in vname) {if (i > indent) {delete vname[i]}} 73 | if (length($3) > 0) { 74 | vn=""; for (i=0; i " 7 | builtin echo 8 | builtin echo $(_zulu_color yellow "Context:") 9 | builtin echo " add Add a directory to \$fpath" 10 | builtin echo " reset Replace the current session \$fpath with the stored dirs" 11 | builtin echo " rm Remove a directory from \$fpath" 12 | } 13 | 14 | ### 15 | # Check the existence of a directory when passed as an argument, 16 | # and convert relative paths to absolute 17 | ### 18 | function _zulu_fpath_parse() { 19 | local dir="$1" check_existing="$2" 20 | 21 | if [[ -d "$PWD/$dir" ]]; then 22 | # If the directory exists in the current working directory 23 | # convert the relative path to absolute 24 | builtin echo "$PWD/$dir" 25 | elif [[ -d "$dir" ]]; then 26 | # If the directory exists as an absolute path, we can use it directly 27 | builtin echo "$dir" 28 | elif [[ "$check_existing" != "false" ]]; then 29 | # The directory could not be found 30 | builtin echo $dir 31 | return 1 32 | fi 33 | } 34 | 35 | ### 36 | # Add a directory to $fpath 37 | ### 38 | function _zulu_fpath_add() { 39 | local dir p 40 | local -a items paths; paths=($(command cat $pathfile)) 41 | 42 | # Check that each of the passed directories exist, and convert relative 43 | # paths to absolute 44 | for dir in "$@"; do 45 | dir=$(_zulu_fpath_parse "$dir") 46 | 47 | # If parsing returned with an error, output the error and return 48 | if [[ $? -eq 0 ]]; then 49 | # Add the directory to the array of items 50 | items+="$dir" 51 | 52 | builtin echo "$(_zulu_color green '✔') $dir added to \$fpath" 53 | else 54 | builtin echo "$(_zulu_color red '✘') $dir cannot be found" 55 | fi 56 | 57 | done 58 | 59 | # Loop through each of the existing paths and add those to the array as well 60 | for p in "$paths[@]"; do 61 | items+="$p" 62 | done 63 | 64 | # Store the new paths in the pathfile, and override $fpath 65 | _zulu_fpath_store 66 | _zulu_fpath_reset 67 | } 68 | 69 | ### 70 | # Remove a directory from $fpath 71 | ### 72 | function _zulu_fpath_rm() { 73 | local dir p 74 | local -a items paths; paths=($(command cat $pathfile)) 75 | 76 | # Check that each of the passed directories exist, and convert relative 77 | # paths to absolute 78 | for dir in "$@"; do 79 | dir=$(_zulu_fpath_parse "$dir" "false") 80 | 81 | # If parsing returned with an error, output the error and return 82 | if [[ ! $? -eq 0 ]]; then 83 | builtin echo $dir 84 | return 1 85 | fi 86 | 87 | # Loop through each of the paths, and if they are *not* an exact match, 88 | # we want to keep them 89 | for p in "$paths[@]"; do 90 | if [[ "$p" != "$dir" ]]; then 91 | items+="$p" 92 | fi 93 | done 94 | 95 | builtin echo "$(_zulu_color green '✔') $dir removed from \$fpath" 96 | done 97 | 98 | # Store the new paths in the pathfile, and override $fpath 99 | _zulu_fpath_store 100 | _zulu_fpath_reset 101 | } 102 | 103 | ### 104 | # Store an array of paths in the pathfile 105 | ### 106 | function _zulu_fpath_store() { 107 | local separator out 108 | 109 | # Separate the array by newlines, and print the contents to the pathfile 110 | separator=$'\n' 111 | local oldIFS=$IFS 112 | IFS="$separator"; out="${items[*]/#/${separator}}" 113 | builtin echo ${out:${#separator}} >! $pathfile 114 | IFS=$oldIFS 115 | builtin unset oldIFS 116 | } 117 | 118 | ### 119 | # Override the $fpath variable with the current contents of the pathfile 120 | ### 121 | function _zulu_fpath_reset() { 122 | local separator out 123 | local -a paths; paths=($(command cat $pathfile)) 124 | 125 | typeset -gUa fpath; fpath=() 126 | for p in "${paths[@]}"; do 127 | fpath+="$p" 128 | done 129 | } 130 | 131 | ### 132 | # Zulu command to handle path manipulation 133 | ### 134 | function _zulu_fpath() { 135 | local ctx base pathfile 136 | 137 | # Parse options 138 | builtin zparseopts -D h=help -help=help 139 | 140 | # Output help and return if requested 141 | if [[ -n $help ]]; then 142 | _zulu_fpath_usage 143 | return 144 | fi 145 | 146 | # Set up some variables 147 | base=${ZULU_DIR:-"${ZDOTDIR:-$HOME}/.zulu"} 148 | config=${ZULU_CONFIG_DIR:-"${ZDOTDIR:-$HOME}/.config/zulu"} 149 | pathfile="${config}/fpath" 150 | 151 | # If no context is passed, output the contents of the pathfile 152 | if [[ "$1" = "" ]]; then 153 | command cat "$pathfile" 154 | return 155 | fi 156 | 157 | # Get the context 158 | ctx="$1" 159 | 160 | # Call the relevant function 161 | _zulu_fpath_${ctx} "${(@)@:2}" 162 | } 163 | -------------------------------------------------------------------------------- /src/commands/func.zsh: -------------------------------------------------------------------------------- 1 | ### 2 | # Output usage information 3 | ### 4 | function _zulu_func_usage() { 5 | builtin echo $(_zulu_color yellow "Usage:") 6 | builtin echo " zulu func " 7 | builtin echo 8 | builtin echo $(_zulu_color yellow "Contexts:") 9 | builtin echo " add Add a function" 10 | builtin echo " edit Edit a function" 11 | builtin echo " load Load all functions from functions directory" 12 | builtin echo " rm Remove a function" 13 | } 14 | 15 | ### 16 | # Add a function 17 | ### 18 | _zulu_func_add() { 19 | local existing func cmd 20 | 21 | func="$1" 22 | 23 | if [[ -z $EDITOR ]]; then 24 | builtin echo $(_zulu_color red "The \$EDITOR environment variable must be set to use the func command in add or edit context") 25 | return 1 26 | fi 27 | 28 | if [[ -f "$funcdir/$func" ]]; then 29 | builtin echo $(_zulu_color red "Function '$func' already exists") 30 | return 1 31 | fi 32 | 33 | builtin echo "#!/usr/bin/env zsh 34 | 35 | (( \$+functions[$func] )) || function $func() { 36 | 37 | }" > "$funcdir/$func" 38 | 39 | ${=EDITOR} "$funcdir/$func" 40 | 41 | zulu func load 42 | return 43 | } 44 | 45 | ### 46 | # Add a function 47 | ### 48 | _zulu_func_edit() { 49 | local existing func cmd 50 | 51 | func="$1" 52 | 53 | if [[ -z $EDITOR ]]; then 54 | builtin echo $(_zulu_color red "The \$EDITOR environment variable must be set to use the func command in add or edit context") 55 | return 1 56 | fi 57 | 58 | if [[ ! -f "$funcdir/$func" ]]; then 59 | builtin echo $(_zulu_color red "Function '$func' does not exist") 60 | return 1 61 | fi 62 | 63 | ${=EDITOR} "$funcdir/$func" 64 | 65 | zulu func load 66 | return 67 | } 68 | 69 | ### 70 | # Remove a function 71 | ### 72 | _zulu_func_rm() { 73 | local existing func 74 | 75 | func="$1" 76 | 77 | if [[ ! -f "$funcdir/$func" ]]; then 78 | builtin echo $(_zulu_color red "Function '$alias' does not exist") 79 | return 1 80 | fi 81 | 82 | unfunction $func 83 | command rm "$funcdir/$func" 84 | zulu func load 85 | return 86 | } 87 | 88 | ### 89 | # Load aliases 90 | ### 91 | _zulu_func_load() { 92 | for f in $(ls $funcdir); do 93 | (( $+functions[$f] )) && unfunction $f 94 | builtin source "$funcdir/$f" 95 | done 96 | } 97 | 98 | ### 99 | # Zulu command to handle managing functions 100 | ### 101 | function _zulu_func() { 102 | local ctx base funcdir 103 | 104 | # Parse options 105 | builtin zparseopts -D h=help -help=help 106 | 107 | # Output help and return if requested 108 | if [[ -n $help ]]; then 109 | _zulu_func_usage 110 | return 111 | fi 112 | 113 | # Set up some variables 114 | base=${ZULU_DIR:-"${ZDOTDIR:-$HOME}/.zulu"} 115 | config=${ZULU_CONFIG_DIR:-"${ZDOTDIR:-$HOME}/.config/zulu"} 116 | funcdir="${config}/functions" 117 | 118 | # Check for and create the directory, since it will not 119 | # exist in older versions of Zulu 120 | if [[ ! -d "$funcdir" ]]; then 121 | command mkdir -p "$funcdir" 122 | fi 123 | 124 | # If no context is passed, output the contents of the aliasfile 125 | if [[ "$1" = "" ]]; then 126 | command ls "$funcdir" 127 | return 128 | fi 129 | 130 | # Get the context 131 | ctx="$1" 132 | 133 | # Call the relevant function 134 | _zulu_func_${ctx} "${(@)@:2}" 135 | } 136 | -------------------------------------------------------------------------------- /src/commands/info.zsh: -------------------------------------------------------------------------------- 1 | ### 2 | # Output usage information 3 | ### 4 | function _zulu_info_usage() { 5 | builtin echo $(_zulu_color yellow "Usage:") 6 | builtin echo " zulu info " 7 | } 8 | 9 | ### 10 | # Check if a package is installed 11 | ### 12 | function _zulu_info_is_installed() { 13 | local package="$1" base=${ZULU_DIR:-"${ZDOTDIR:-$HOME}/.zulu"} 14 | 15 | [[ -d "$base/packages/$package" ]] 16 | return $? 17 | } 18 | 19 | ### 20 | # Extract package information from the index entry 21 | ### 22 | function _zulu_info_package() { 23 | local json name description url author packagetype installed package=$1 24 | 25 | json=$(command cat "$index/$package") 26 | 27 | name=$(jsonval $json 'name') 28 | description=$(jsonval $json 'description') 29 | url=$(jsonval $json 'repository') 30 | author=$(jsonval $json 'author') 31 | packagetype=$(jsonval $json 'type') 32 | 33 | _zulu_info_is_installed $name && installed="$(_zulu_color green '✔ Installed')" 34 | 35 | builtin echo "$(_zulu_color white underline "$name") $installed" 36 | builtin echo $description 37 | builtin echo 38 | 39 | builtin echo "Type: $packagetype" 40 | builtin echo "URL: $url" 41 | builtin echo "Author: $author" 42 | } 43 | 44 | ### 45 | # Zulu command to output package information 46 | ### 47 | function _zulu_info() { 48 | local base index out package=$1 49 | 50 | # Parse options 51 | builtin zparseopts -D h=help -help=help 52 | 53 | # Output help and return if requested 54 | if [[ -n $help ]]; then 55 | _zulu_info_usage 56 | return 57 | fi 58 | 59 | # Set up some variables 60 | base=${ZULU_DIR:-"${ZDOTDIR:-$HOME}/.zulu"} 61 | config=${ZULU_CONFIG_DIR:-"${ZDOTDIR:-$HOME}/.config/zulu"} 62 | index="${base}/index/packages" 63 | 64 | if [[ ! -f "$index/$package" ]]; then 65 | builtin echo $(_zulu_color red "Package '$package' is not in the index") 66 | return 1 67 | fi 68 | 69 | _zulu_info_package $package 70 | } 71 | -------------------------------------------------------------------------------- /src/commands/init.zsh: -------------------------------------------------------------------------------- 1 | function _zulu_init_usage() { 2 | builtin echo $(_zulu_color yellow "Usage:") 3 | builtin echo " zulu init [options]" 4 | builtin echo 5 | builtin echo $(_zulu_color yellow "Options:") 6 | builtin echo " -c, --check-for-update Check for updates on startup" 7 | builtin echo " -h, --help Output this help text and exit" 8 | builtin echo " -n, --no-compile Skip compilation of scripts on startup" 9 | builtin echo " --dev Start Zulu in Development Mode" 10 | } 11 | 12 | function _zulu_init_setup_completion() { 13 | # 14 | # Sets completion options. 15 | # 16 | # Authors: 17 | # Robby Russell 18 | # Sorin Ionescu 19 | # 20 | 21 | # Return if requirements are not found. 22 | if [[ "$TERM" == 'dumb' ]]; then 23 | return 1 24 | fi 25 | 26 | # Load and initialize the completion system ignoring insecure directories. 27 | builtin autoload -Uz compinit && compinit -i 28 | 29 | # 30 | # Options 31 | # 32 | 33 | builtin setopt COMPLETE_IN_WORD # Complete from both ends of a word. 34 | builtin setopt ALWAYS_TO_END # Move cursor to the end of a completed word. 35 | builtin setopt PATH_DIRS # Perform path search even on command names with slashes. 36 | builtin setopt AUTO_MENU # Show completion menu on a successive tab press. 37 | builtin setopt AUTO_LIST # Automatically list choices on ambiguous completion. 38 | builtin setopt AUTO_PARAM_SLASH # If completed parameter is a directory, add a trailing slash. 39 | builtin unsetopt MENU_COMPLETE # Do not autoselect the first completion entry. 40 | builtin unsetopt FLOW_CONTROL # Disable start/stop characters in shell editor. 41 | 42 | # 43 | # Styles 44 | # 45 | 46 | # Use caching to make completion for commands such as dpkg and apt usable. 47 | builtin zstyle ':completion::complete:*' use-cache on 48 | builtin zstyle ':completion::complete:*' cache-path "${ZDOTDIR:-$HOME}/.zcompcache" 49 | 50 | # Disable case sensitivity 51 | builtin zstyle ':completion:*' matcher-list 'm:{a-zA-Z}={A-Za-z}' 'r:|[._-]=* r:|=*' 'l:|=* r:|=*' 52 | builtin unsetopt CASE_GLOB 53 | 54 | # Group matches and describe. 55 | builtin zstyle ':completion:*:*:*:*:*' menu select 56 | builtin zstyle ':completion:*:matches' group 'yes' 57 | builtin zstyle ':completion:*:options' description 'yes' 58 | builtin zstyle ':completion:*:options' auto-description '%d' 59 | builtin zstyle ':completion:*:corrections' format ' %F{green}-- %d (errors: %e) --%f' 60 | builtin zstyle ':completion:*:descriptions' format ' %F{yellow}-- %d --%f' 61 | builtin zstyle ':completion:*:messages' format ' %F{purple} -- %d --%f' 62 | builtin zstyle ':completion:*:warnings' format ' %F{red}-- no matches found --%f' 63 | builtin zstyle ':completion:*:default' list-prompt '%S%M matches%s' 64 | builtin zstyle ':completion:*' format ' %F{yellow}-- %d --%f' 65 | builtin zstyle ':completion:*' group-name '' 66 | builtin zstyle ':completion:*' verbose yes 67 | 68 | # Don't show already completed options in the list 69 | builtin zstyle ':completion:*:*:*:*:*' ignore-line 'yes' 70 | 71 | # Fuzzy match mistyped completions. 72 | builtin zstyle ':completion:*' completer _complete _match _approximate 73 | builtin zstyle ':completion:*:match:*' original only 74 | builtin zstyle ':completion:*:approximate:*' max-errors 1 numeric 75 | 76 | # Increase the number of errors based on the length of the typed word. 77 | builtin zstyle -e ':completion:*:approximate:*' max-errors 'reply=($((($#PREFIX+$#SUFFIX)/3))numeric)' 78 | 79 | # Don't complete unavailable commands. 80 | builtin zstyle ':completion:*:functions' ignored-patterns '(_*|pre(cmd|exec))' 81 | 82 | # Array completion element sorting. 83 | builtin zstyle ':completion:*:*:-subscript-:*' tag-order indexes parameters 84 | 85 | # Directories 86 | builtin zstyle ':completion:*:default' list-colors ${(s.:.)LS_COLORS} 87 | builtin zstyle ':completion:*:*:cd:*' tag-order local-directories directory-stack path-directories 88 | builtin zstyle ':completion:*:*:cd:*:directory-stack' menu yes select 89 | builtin zstyle ':completion:*:-tilde-:*' group-order 'named-directories' 'path-directories' 'users' 'expand' 90 | builtin zstyle ':completion:*' squeeze-slashes true 91 | 92 | # History 93 | builtin zstyle ':completion:*:history-words' stop yes 94 | builtin zstyle ':completion:*:history-words' remove-all-dups yes 95 | builtin zstyle ':completion:*:history-words' list false 96 | builtin zstyle ':completion:*:history-words' menu yes 97 | 98 | # Environmental Variables 99 | builtin zstyle ':completion::*:(-command-|export):*' fake-parameters ${${${_comps[(I)-value-*]#*,}%%,*}:#-*-} 100 | 101 | # Populate hostname completion. 102 | builtin zstyle -e ':completion:*:hosts' hosts 'reply=( 103 | ${=${=${=${${(f)"$(cat {/etc/ssh_,~/.ssh/known_}hosts(|2)(N) 2>/dev/null)"}%%[#| ]*}//\]:[0-9]*/ }//,/ }//\[/ } 104 | ${=${(f)"$(cat /etc/hosts(|)(N) <<(ypcat hosts 2>/dev/null))"}%%\#*} 105 | ${=${${${${(@M)${(f)"$(cat ~/.ssh/config 2>/dev/null)"}:#Host *}#Host }:#*\**}:#*\?*}} 106 | )' 107 | 108 | # Don't complete uninteresting users... 109 | builtin zstyle ':completion:*:*:*:users' ignored-patterns \ 110 | adm amanda apache avahi beaglidx bin cacti canna clamav daemon \ 111 | dbus distcache dovecot fax ftp games gdm gkrellmd gopher \ 112 | hacluster haldaemon halt hsqldb ident junkbust ldap lp mail \ 113 | mailman mailnull mldonkey mysql nagios \ 114 | named netdump news nfsnobody nobody nscd ntp nut nx openvpn \ 115 | operator pcap postfix postgres privoxy pulse pvm quagga radvd \ 116 | rpc rpcuser rpm shutdown squid sshd sync uucp vcsa xfs '_*' 117 | 118 | # ... unless we really want to. 119 | builtin zstyle '*' single-ignored show 120 | 121 | # Ignore multiple entries. 122 | builtin zstyle ':completion:*:(rm|kill|diff):*' ignore-line other 123 | builtin zstyle ':completion:*:rm:*' file-patterns '*:all-files' 124 | 125 | # Kill 126 | builtin zstyle ':completion:*:*:*:*:processes' command 'ps -u $LOGNAME -o pid,user,command -w' 127 | builtin zstyle ':completion:*:*:kill:*:processes' list-colors '=(#b) #([0-9]#) ([0-9a-z-]#)*=01;36=0=01' 128 | builtin zstyle ':completion:*:*:kill:*' menu yes select 129 | builtin zstyle ':completion:*:*:kill:*' force-list always 130 | builtin zstyle ':completion:*:*:kill:*' insert-ids single 131 | 132 | # Man 133 | builtin zstyle ':completion:*:manuals' separate-sections true 134 | builtin zstyle ':completion:*:manuals.(^1*)' insert-sections true 135 | 136 | # Media Players 137 | builtin zstyle ':completion:*:*:mpg123:*' file-patterns '*.(mp3|MP3):mp3\ files *(-/):directories' 138 | builtin zstyle ':completion:*:*:mpg321:*' file-patterns '*.(mp3|MP3):mp3\ files *(-/):directories' 139 | builtin zstyle ':completion:*:*:ogg123:*' file-patterns '*.(ogg|OGG|flac):ogg\ files *(-/):directories' 140 | builtin zstyle ':completion:*:*:mocp:*' file-patterns '*.(wav|WAV|mp3|MP3|ogg|OGG|flac):ogg\ files *(-/):directories' 141 | 142 | # Mutt 143 | if [[ -s "$HOME/.mutt/aliases" ]]; then 144 | builtin zstyle ':completion:*:*:mutt:*' menu yes select 145 | builtin zstyle ':completion:*:mutt:*' users ${${${(f)"$(<"$HOME/.mutt/aliases")"}#alias[[:space:]]}%%[[:space:]]*} 146 | fi 147 | 148 | # SSH/SCP/RSYNC 149 | builtin zstyle ':completion:*:(scp|rsync):*' tag-order 'hosts:-host:host hosts:-domain:domain hosts:-ipaddr:ip\ address *' 150 | builtin zstyle ':completion:*:(scp|rsync):*' group-order users files all-files hosts-domain hosts-host hosts-ipaddr 151 | builtin zstyle ':completion:*:ssh:*' tag-order 'hosts:-host:host hosts:-domain:domain hosts:-ipaddr:ip\ address *' 152 | builtin zstyle ':completion:*:ssh:*' group-order users hosts-domain hosts-host users hosts-ipaddr 153 | builtin zstyle ':completion:*:(ssh|scp|rsync):*:hosts-host' ignored-patterns '*(.|:)*' loopback ip6-loopback localhost ip6-localhost broadcasthost 154 | builtin zstyle ':completion:*:(ssh|scp|rsync):*:hosts-domain' ignored-patterns '<->.<->.<->.<->' '^[-[:alnum:]]##(.[-[:alnum:]]##)##' '*@*' 155 | builtin zstyle ':completion:*:(ssh|scp|rsync):*:hosts-ipaddr' ignored-patterns '^(<->.<->.<->.<->|(|::)([[:xdigit:].]##:(#c,2))##(|%*))' '127.0.0.<->' '255.255.255.255' '::1' 'fe80::*' 156 | } 157 | 158 | function _zulu_init_setup_history() { 159 | # 160 | # Variables 161 | # 162 | 163 | HISTFILE="${ZDOTDIR:-$HOME}/.zhistory" # The path to the history file. 164 | HISTSIZE=10000 # The maximum number of events to save in the internal history. 165 | SAVEHIST=10000 # The maximum number of events to save in the history file. 166 | 167 | # 168 | # Options 169 | # 170 | 171 | builtin setopt BANG_HIST # Treat the '!' character specially during expansion. 172 | builtin setopt EXTENDED_HISTORY # Write the history file in the ':start:elapsed;command' format. 173 | builtin setopt INC_APPEND_HISTORY # Write to the history file immediately, not when the shell exits. 174 | builtin setopt SHARE_HISTORY # Share history between all sessions. 175 | builtin setopt HIST_EXPIRE_DUPS_FIRST # Expire a duplicate event first when trimming history. 176 | builtin setopt HIST_IGNORE_DUPS # Do not record an event that was just recorded again. 177 | builtin setopt HIST_IGNORE_ALL_DUPS # Delete an old recorded event if a new event is a duplicate. 178 | builtin setopt HIST_FIND_NO_DUPS # Do not display a previously found event. 179 | builtin setopt HIST_IGNORE_SPACE # Do not record an event starting with a space. 180 | builtin setopt HIST_SAVE_NO_DUPS # Do not write a duplicate event to the history file. 181 | builtin setopt HIST_VERIFY # Do not execute immediately upon history expansion. 182 | builtin setopt HIST_BEEP # Beep when accessing non-existent history. 183 | 184 | if (( $+widgets[history-substring-search-up] )); then 185 | # 186 | # Integrates history-substring-search into Prezto. 187 | # 188 | # Authors: 189 | # Suraj N. Kurapati 190 | # Sorin Ionescu 191 | # 192 | 193 | # Source module files. 194 | [[ -f "$base/init/zsh-history-substring-search.zsh" ]] || return 1 195 | 196 | builtin zle -N history-substring-search-up 197 | builtin zle -N history-substring-search-down 198 | 199 | # 200 | # Search 201 | # 202 | 203 | HISTORY_SUBSTRING_SEARCH_HIGHLIGHT_FOUND='bg=magenta,fg=white,bold' 204 | HISTORY_SUBSTRING_SEARCH_HIGHLIGHT_NOT_FOUND='bg=red,fg=white,bold' 205 | HISTORY_SUBSTRING_SEARCH_GLOBBING_FLAGS='i' 206 | HISTORY_SUBSTRING_SEARCH_GLOBBING_FLAGS="${HISTORY_SUBSTRING_SEARCH_GLOBBING_FLAGS//i}" 207 | 208 | # 209 | # Key Bindings 210 | # 211 | 212 | if [[ -n "$key_info" ]]; then 213 | # Emacs 214 | builtin bindkey -M emacs "$key_info[Control]P" history-substring-search-up 215 | builtin bindkey -M emacs "$key_info[Control]N" history-substring-search-down 216 | 217 | # Vi 218 | builtin bindkey -M vicmd "k" history-substring-search-up 219 | builtin bindkey -M vicmd "j" history-substring-search-down 220 | 221 | # Emacs and Vi 222 | for keymap in 'emacs' 'viins'; do 223 | builtin bindkey -M "$keymap" "$key_info[Up]" history-substring-search-up 224 | builtin bindkey -M "$keymap" "$key_info[Down]" history-substring-search-down 225 | done 226 | fi 227 | fi 228 | } 229 | 230 | function _zulu_init_setup_key_bindings() { 231 | # 232 | # Sets key bindings. 233 | # 234 | # Authors: 235 | # Sorin Ionescu 236 | # 237 | 238 | # Return if requirements are not found. 239 | if [[ "$TERM" == 'dumb' ]]; then 240 | return 1 241 | fi 242 | 243 | # 244 | # Options 245 | # 246 | 247 | # Beep on error in line editor. 248 | builtin setopt BEEP 249 | 250 | # 251 | # Variables 252 | # 253 | 254 | # Treat these characters as part of a word. 255 | WORDCHARS='*?_-.[]~&;!#$%^(){}<>' 256 | 257 | # Use human-friendly identifiers. 258 | builtin zmodload zsh/terminfo 259 | typeset -gA key_info 260 | key_info=( 261 | 'Control' '\C-' 262 | 'ControlLeft' '\e[1;5D \e[5D \e\e[D \eOd' 263 | 'ControlRight' '\e[1;5C \e[5C \e\e[C \eOc' 264 | 'Escape' '\e' 265 | 'Meta' '\M-' 266 | 'Backspace' "^?" 267 | 'Delete' "^[[3~" 268 | 'F1' "$terminfo[kf1]" 269 | 'F2' "$terminfo[kf2]" 270 | 'F3' "$terminfo[kf3]" 271 | 'F4' "$terminfo[kf4]" 272 | 'F5' "$terminfo[kf5]" 273 | 'F6' "$terminfo[kf6]" 274 | 'F7' "$terminfo[kf7]" 275 | 'F8' "$terminfo[kf8]" 276 | 'F9' "$terminfo[kf9]" 277 | 'F10' "$terminfo[kf10]" 278 | 'F11' "$terminfo[kf11]" 279 | 'F12' "$terminfo[kf12]" 280 | 'Insert' "$terminfo[kich1]" 281 | 'Home' "$terminfo[khome]" 282 | 'PageUp' "$terminfo[kpp]" 283 | 'End' "$terminfo[kend]" 284 | 'PageDown' "$terminfo[knp]" 285 | 'Up' "^[[A" 286 | 'Left' "^[[D" 287 | 'Down' "^[[B" 288 | 'Right' "^[[C" 289 | 'BackTab' "$terminfo[kcbt]" 290 | ) 291 | 292 | # Set empty $key_info values to an invalid UTF-8 sequence to induce silent 293 | # bindkey failure. 294 | for key in "${(k)key_info[@]}"; do 295 | if [[ -z "$key_info[$key]" ]]; then 296 | key_info[$key]='�' 297 | fi 298 | done 299 | 300 | # 301 | # External Editor 302 | # 303 | 304 | # Allow command line editing in an external editor. 305 | builtin autoload -Uz edit-command-line 306 | builtin zle -N edit-command-line 307 | 308 | # 309 | # Functions 310 | # 311 | 312 | # Exposes information about the Zsh Line Editor via the $editor_info associative 313 | # array. 314 | function editor-info { 315 | builtin zle reset-prompt 316 | builtin zle -R 317 | } 318 | builtin zle -N editor-info 319 | 320 | # Updates editor information when the keymap changes. 321 | function zle-keymap-select { 322 | builtin zle editor-info 323 | } 324 | builtin zle -N zle-keymap-select 325 | 326 | # Enables terminal application mode and updates editor information. 327 | function zle-line-init { 328 | # The terminal must be in application mode when ZLE is active for $terminfo 329 | # values to be valid. 330 | if (( $+terminfo[smkx] )); then 331 | # Enable terminal application mode. 332 | echoti smkx 333 | fi 334 | 335 | # Update editor information. 336 | builtin zle editor-info 337 | } 338 | builtin zle -N zle-line-init 339 | 340 | # Disables terminal application mode and updates editor information. 341 | function zle-line-finish { 342 | # The terminal must be in application mode when ZLE is active for $terminfo 343 | # values to be valid. 344 | if (( $+terminfo[rmkx] )); then 345 | # Disable terminal application mode. 346 | echoti rmkx 347 | fi 348 | 349 | # Update editor information. 350 | builtin zle editor-info 351 | } 352 | builtin zle -N zle-line-finish 353 | 354 | # Toggles emacs overwrite mode and updates editor information. 355 | function overwrite-mode { 356 | builtin zle .overwrite-mode 357 | builtin zle editor-info 358 | } 359 | builtin zle -N overwrite-mode 360 | 361 | # Enters vi insert mode and updates editor information. 362 | function vi-insert { 363 | builtin zle .vi-insert 364 | builtin zle editor-info 365 | } 366 | builtin zle -N vi-insert 367 | 368 | # Moves to the first non-blank character then enters vi insert mode and updates 369 | # editor information. 370 | function vi-insert-bol { 371 | builtin zle .vi-insert-bol 372 | builtin zle editor-info 373 | } 374 | builtin zle -N vi-insert-bol 375 | 376 | # Enters vi replace mode and updates editor information. 377 | function vi-replace { 378 | builtin zle .vi-replace 379 | builtin zle editor-info 380 | } 381 | builtin zle -N vi-replace 382 | 383 | # Expands .... to ../.. 384 | function expand-dot-to-parent-directory-path { 385 | if [[ $LBUFFER = *.. ]]; then 386 | LBUFFER+='/..' 387 | else 388 | LBUFFER+='.' 389 | fi 390 | } 391 | builtin zle -N expand-dot-to-parent-directory-path 392 | 393 | # Displays an indicator when completing. 394 | function expand-or-complete-with-indicator { 395 | local indicator="→" 396 | print -Pn "$indicator" 397 | builtin zle expand-or-complete 398 | builtin zle redisplay 399 | } 400 | builtin zle -N expand-or-complete-with-indicator 401 | 402 | # Inserts 'sudo ' at the beginning of the line. 403 | function prepend-sudo { 404 | if [[ "$BUFFER" != su(do|)\ * ]]; then 405 | BUFFER="sudo $BUFFER" 406 | (( CURSOR += 5 )) 407 | fi 408 | } 409 | builtin zle -N prepend-sudo 410 | 411 | # Reset to default key bindings. 412 | builtin bindkey -d 413 | 414 | # 415 | # Emacs Key Bindings 416 | # 417 | 418 | for key in "$key_info[Escape]"{B,b} "${(s: :)key_info[ControlLeft]}" 419 | builtin bindkey -M emacs "$key" emacs-backward-word 420 | for key in "$key_info[Escape]"{F,f} "${(s: :)key_info[ControlRight]}" 421 | builtin bindkey -M emacs "$key" emacs-forward-word 422 | 423 | # Kill to the beginning of the line. 424 | for key in "$key_info[Escape]"{K,k} 425 | builtin bindkey -M emacs "$key" backward-kill-line 426 | 427 | # Redo. 428 | builtin bindkey -M emacs "$key_info[Escape]_" redo 429 | 430 | # Search previous character. 431 | builtin bindkey -M emacs "$key_info[Control]X$key_info[Control]B" vi-find-prev-char 432 | 433 | # Match bracket. 434 | builtin bindkey -M emacs "$key_info[Control]X$key_info[Control]]" vi-match-bracket 435 | 436 | # Edit command in an external editor. 437 | builtin bindkey -M emacs "$key_info[Control]X$key_info[Control]E" edit-command-line 438 | 439 | if (( $+widgets[history-incremental-pattern-search-backward] )); then 440 | builtin bindkey -M emacs "$key_info[Control]R" \ 441 | history-incremental-pattern-search-backward 442 | builtin bindkey -M emacs "$key_info[Control]S" \ 443 | history-incremental-pattern-search-forward 444 | fi 445 | 446 | # 447 | # Vi Key Bindings 448 | # 449 | 450 | # Edit command in an external editor. 451 | builtin bindkey -M vicmd "v" edit-command-line 452 | 453 | # Undo/Redo 454 | builtin bindkey -M vicmd "u" undo 455 | builtin bindkey -M vicmd "$key_info[Control]R" redo 456 | 457 | if (( $+widgets[history-incremental-pattern-search-backward] )); then 458 | builtin bindkey -M vicmd "?" history-incremental-pattern-search-backward 459 | builtin bindkey -M vicmd "/" history-incremental-pattern-search-forward 460 | else 461 | builtin bindkey -M vicmd "?" history-incremental-search-backward 462 | builtin bindkey -M vicmd "/" history-incremental-search-forward 463 | fi 464 | 465 | # 466 | # Emacs and Vi Key Bindings 467 | # 468 | 469 | for keymap in 'emacs' 'viins'; do 470 | builtin bindkey -M "$keymap" "$key_info[Home]" beginning-of-line 471 | builtin bindkey -M "$keymap" "$key_info[End]" end-of-line 472 | 473 | builtin bindkey -M "$keymap" "$key_info[Insert]" overwrite-mode 474 | builtin bindkey -M "$keymap" "$key_info[Delete]" delete-char 475 | builtin bindkey -M "$keymap" "$key_info[Backspace]" backward-delete-char 476 | 477 | builtin bindkey -M "$keymap" "$key_info[Left]" backward-char 478 | builtin bindkey -M "$keymap" "$key_info[Right]" forward-char 479 | 480 | # Expand history on space. 481 | builtin bindkey -M "$keymap" ' ' magic-space 482 | 483 | # Clear screen. 484 | builtin bindkey -M "$keymap" "$key_info[Control]L" clear-screen 485 | 486 | # Expand command name to full path. 487 | for key in "$key_info[Escape]"{E,e} 488 | builtin bindkey -M "$keymap" "$key" expand-cmd-path 489 | 490 | # Duplicate the previous word. 491 | for key in "$key_info[Escape]"{M,m} 492 | builtin bindkey -M "$keymap" "$key" copy-prev-shell-word 493 | 494 | # Use a more flexible push-line. 495 | for key in "$key_info[Control]Q" "$key_info[Escape]"{q,Q} 496 | builtin bindkey -M "$keymap" "$key" push-line-or-edit 497 | 498 | # Bind Shift + Tab to go to the previous menu item. 499 | builtin bindkey -M "$keymap" "$key_info[BackTab]" reverse-menu-complete 500 | 501 | # Complete in the middle of word. 502 | builtin bindkey -M "$keymap" "$key_info[Control]I" expand-or-complete 503 | 504 | # Expand .... to ../.. 505 | builtin bindkey -M "$keymap" "." expand-dot-to-parent-directory-path 506 | 507 | # Display an indicator when completing. 508 | builtin bindkey -M "$keymap" "$key_info[Control]I" \ 509 | expand-or-complete-with-indicator 510 | 511 | # Insert 'sudo ' at the beginning of the line. 512 | builtin bindkey -M "$keymap" "$key_info[Control]X$key_info[Control]S" prepend-sudo 513 | done 514 | 515 | builtin unset key{,map,bindings} 516 | } 517 | 518 | ### 519 | # Check for updates 520 | ### 521 | function _zulu_check_for_update() { 522 | local out 523 | local -a commands pids 524 | 525 | commands=( 526 | '_zulu_self-update_check_for_update' 527 | '_zulu_update_check_for_update' 528 | '_zulu_upgrade --check' 529 | ) 530 | 531 | # If the ZSH version we are using supports it, 532 | # perform update checks asynchronously 533 | if is-at-least '5.1'; then 534 | pids=() 535 | 536 | for command in $commands; do 537 | { 538 | out=$(${=command}) 539 | if [[ $? -eq 0 ]]; then 540 | builtin echo $out 541 | fi 542 | } &! 543 | pids+=$! 544 | done 545 | 546 | for pid in $pids; do 547 | while builtin kill -0 $pid >/dev/null 2>&1; do 548 | done 549 | done 550 | else 551 | for command in $commands; do 552 | out=$(${=command}) 553 | if [[ $? -eq 0 ]]; then 554 | builtin echo $out 555 | fi 556 | done 557 | fi 558 | } 559 | 560 | ### 561 | # Source init scripts for installed packages 562 | ### 563 | function _zulu_load_packages() { 564 | # Source files in the init directory 565 | builtin setopt EXTENDED_GLOB 566 | for f in ${base}/init/**/*^(*.zwc)(#q@N); do 567 | if [[ -L $f ]]; then 568 | builtin source $(command readlink $f) 569 | else 570 | builtin source $f 571 | fi 572 | done 573 | } 574 | 575 | ### 576 | # Use Zulu next 577 | ### 578 | function _zulu_init_switch_branch() { 579 | local oldPWD=$PWD branch="$1" 580 | builtin cd $base/core 581 | 582 | local current=$(command git status --short --branch -uno --ignore-submodules=all | command head -1 | command awk '{print $2}' 2>/dev/null) 583 | 584 | if [[ ${current:0:${#branch}} != $branch ]]; then 585 | if command git reset --hard 2>&1; then 586 | echo $(_zulu_color red 'Failed to reset Zulu repository') 587 | return 1 588 | fi 589 | 590 | if command git checkout $branch 2>&1; then 591 | echo $(_zulu_color red "Failed to checkout branch $branch") 592 | return 1 593 | fi 594 | 595 | if ./build.zsh 2>&1; then 596 | echo $(_zulu_color red "Failed to compile Zulu") 597 | return 1 598 | fi 599 | 600 | builtin source ./zulu 601 | fi 602 | 603 | builtin cd $oldPWD 604 | builtin unset oldPWD 605 | } 606 | 607 | ### 608 | # Display a message to next users 609 | ### 610 | function _zulu_init_next_message() { 611 | builtin echo 612 | builtin echo '\033[0;33mThanks for using Zulu next\033[0;m' 613 | builtin echo 'We rely on people like you testing new versions to keep Zulu as useful' 614 | builtin echo 'and as stable as possible. If you do run into any errors, please do' 615 | builtin echo 'report them so that they can be fixed before the next release.' 616 | builtin echo 617 | builtin echo 'Github Issues: https://github.com/zulu-zsh/zulu/issues' 618 | builtin echo 'Gitter Chat: https://gitter.im/zulu-zsh/zulu' 619 | } 620 | 621 | ### 622 | # Set up the zulu environment 623 | ### 624 | function _zulu_init() { 625 | local base=${ZULU_DIR:-"${ZDOTDIR:-$HOME}/.zulu"} 626 | local config=${ZULU_CONFIG_DIR:-"${ZDOTDIR:-$HOME}/.config/zulu"} 627 | local help check_for_update no_compile next dev bare branch 628 | 629 | # Parse CLI options 630 | builtin zparseopts -D \ 631 | h=help -help=help \ 632 | c=check_for_update -check-for-update=check_for_update \ 633 | n=no_compile -no-compile=no_compile \ 634 | -bare=bare \ 635 | -next=next \ 636 | -dev=dev 637 | 638 | if [[ -n $help ]]; then 639 | _zulu_init_usage 640 | return 641 | fi 642 | 643 | # Check for the --dev flag and turn dev mode on or off 644 | if [[ -n $dev ]]; then 645 | export ZULU_DEV_MODE=1 646 | else 647 | export ZULU_DEV_MODE=0 648 | fi 649 | 650 | # Check for the --next flag unless in dev mode 651 | if [[ $ZULU_DEV_MODE -ne 1 ]]; then 652 | if [[ -n $next ]]; then 653 | branch='next' 654 | else 655 | branch='master' 656 | fi 657 | 658 | output=$(_zulu_init_switch_branch $branch) 659 | if [[ $? -eq 0 ]]; then 660 | builtin echo "\033[0;32m✔\033[0;m Switched to Zulu $branch" 661 | else 662 | builtin echo $output 663 | return 1 664 | fi 665 | fi 666 | 667 | # Populate paths 668 | zulu path reset 669 | zulu fpath reset 670 | zulu cdpath reset 671 | zulu manpath reset 672 | 673 | # Set up the environment 674 | _zulu_init_setup_key_bindings 675 | _zulu_init_setup_completion 676 | 677 | # Load installed packages 678 | if [[ -z $bare ]]; then 679 | _zulu_load_packages 680 | fi 681 | 682 | # Set up history 683 | _zulu_init_setup_history 684 | 685 | # Load aliases, functions and environment variables 686 | if [[ -z $bare ]]; then 687 | zulu alias load 688 | zulu func load 689 | zulu var load 690 | fi 691 | 692 | # Autoload zsh theme 693 | if [[ -z $bare && -f "$config/theme" ]]; then 694 | builtin autoload -U promptinit && promptinit 695 | local theme=$(cat "$config/theme") 696 | prompt $theme 697 | fi 698 | 699 | if [[ -z $no_compile ]]; then 700 | { 701 | zulu compile 702 | } >/dev/null 2>&1 &! 703 | fi 704 | 705 | [[ -n $check_for_update ]] && _zulu_check_for_update 706 | 707 | # If Zulu next is enabled, show a message to the user 708 | if [[ -n $next ]]; then 709 | _zulu_init_next_message 710 | fi 711 | 712 | return 713 | } 714 | -------------------------------------------------------------------------------- /src/commands/install.zsh: -------------------------------------------------------------------------------- 1 | ### 2 | # Output usage information 3 | ### 4 | function _zulu_install_usage() { 5 | builtin echo $(_zulu_color yellow "Usage:") 6 | builtin echo " zulu install " 7 | builtin echo 8 | builtin echo $(_zulu_color yellow "Options:") 9 | builtin echo " --no-autoselect-themes Don't autoselect themes after installing" 10 | builtin echo " --ignore-dependencies Don't automatically install dependencies" 11 | builtin echo " -b, --branch Specify a branch to install" 12 | builtin echo " -t, --tag Specify a tag to install" 13 | } 14 | 15 | ### 16 | # Install a package 17 | ### 18 | function _zulu_install_package() { 19 | local package ref json repo dir file link packagetype 20 | local -a dependencies 21 | 22 | package="$1" 23 | ref="$2" 24 | 25 | # Check if the package is already installed 26 | root="$base/packages/$package" 27 | if [[ -d "$root" ]]; then 28 | builtin echo $(_zulu_color red "Package '$package' is already installed") >&2 29 | return 1 30 | fi 31 | 32 | # Get the JSON from the index 33 | json=$(command cat "$index/$package") 34 | if [[ $? -ne 0 ]]; then 35 | builtin echo 'Could not find package in index' >&2 36 | return 1 37 | fi 38 | 39 | # Get the repository URL from the JSON 40 | repo=$(jsonval $json 'repository') 41 | 42 | if [[ $? -ne 0 || -z $repo ]]; then 43 | builtin echo 'Could not find repository URL' >&2 44 | return 1 45 | fi 46 | 47 | local -a warnings 48 | warnings=($(builtin echo $(jsonval $json 'collision_warnings') | tr "," "\n")) 49 | 50 | if [[ ${#warnings} -gt 0 ]]; then 51 | builtin echo $(_zulu_color yellow underline "Warnings from $package package:") >&2 52 | for warning in "${(@F)warnings}"; do 53 | local -a parts; parts=(${(s/:/)warning}) 54 | if _zulu_info_is_installed $parts[1]; then 55 | builtin echo $(_zulu_color yellow "Collides with ${warning}") >&2 56 | fi 57 | done 58 | builtin echo 59 | fi 60 | 61 | # Clone the repository 62 | builtin cd "$base/packages" 63 | 64 | local -a args 65 | if [[ -n $ref ]]; then 66 | args=(--branch $ref) 67 | fi 68 | command git clone --recursive $args $repo $package 2>&1 69 | if [[ $? -ne 0 ]]; then 70 | builtin echo 'Failed to clone repository' >&2 71 | return 1 72 | fi 73 | 74 | return 75 | } 76 | 77 | ### 78 | # Zulu command to handle package installation 79 | ### 80 | function _zulu_install() { 81 | local base index packages out help no_autoselect_themes ignore_dependencies \ 82 | branch tag ref 83 | 84 | # Parse options 85 | builtin zparseopts -D h=help -help=help \ 86 | -no-autoselect-themes=no_autoselect_themes \ 87 | -ignore-dependencies=ignore_dependencies \ 88 | b:=branch -branch:=branch \ 89 | t:=tag -tag:=tag 90 | 91 | # Output help and return if requested 92 | if [[ -n $help ]]; then 93 | _zulu_install_usage 94 | return 95 | fi 96 | 97 | if [[ -n $branch && -n $tag ]]; then 98 | builtin echo $(_zulu_color red 'You must only specify one of branch or tag') 99 | return 1 100 | fi 101 | 102 | # Set up some variables 103 | base=${ZULU_DIR:-"${ZDOTDIR:-$HOME}/.zulu"} 104 | config=${ZULU_CONFIG_DIR:-"${ZDOTDIR:-$HOME}/.config/zulu"} 105 | index="${base}/index/packages" 106 | 107 | packages=($@) 108 | packagefile="$config/packages" 109 | 110 | if [[ ! -f $packagefile ]]; then 111 | command touch $packagefile 112 | fi 113 | 114 | # If no package name is passed, throw an error 115 | if [[ ${#packages} -eq 0 ]]; then 116 | builtin echo $(_zulu_color red "Please specify a package name") 117 | builtin echo 118 | _zulu_install_usage 119 | return 1 120 | fi 121 | 122 | # Do a first loop, to ensure all packages exist 123 | for package in "$packages[@]"; do 124 | if [[ ! -f "$index/$package" ]]; then 125 | builtin echo $(_zulu_color red "Package '$package' is not in the index") 126 | return 1 127 | fi 128 | done 129 | 130 | local error=0 131 | 132 | # Do a second loop, to do the actual install 133 | for package in "$packages[@]"; do 134 | # Get the JSON from the index 135 | json=$(cat "$index/$package") 136 | 137 | if [[ -z $ignore_dependencies ]]; then 138 | # Get the list of dependencies from the index 139 | dependencies=($(builtin echo $(jsonval $json 'dependencies') | command tr "," "\n" | command sed 's/\[//g' | command sed 's/\]//g')) 140 | 141 | # If there are dependencies in the list 142 | if [[ ${#dependencies} -ne 0 ]]; then 143 | # Loop through each of the dependencies 144 | for dependency in "$dependencies[@]"; do 145 | # Check that the dependency is not already installed 146 | if [[ ! -d "$base/packages/$dependency" ]]; then 147 | _zulu_revolver start "Installing dependency $dependency..." 148 | out=$(_zulu_install_package "$dependency" 2>&1) 149 | state=$? 150 | _zulu_revolver stop 151 | 152 | if [ $state -eq 0 ]; then 153 | builtin echo "$(_zulu_color green '✔') Finished installing dependency $dependency" 154 | zulu link $dependency 155 | else 156 | builtin echo "$(_zulu_color red '✘') Error installing dependency $dependency" 157 | builtin echo "$out" 158 | fi 159 | fi 160 | done 161 | fi 162 | fi 163 | 164 | local ref='' 165 | if [[ -n $branch ]]; then 166 | builtin shift branch 167 | ref=$branch 168 | fi 169 | 170 | if [[ -n $tag ]]; then 171 | builtin shift tag 172 | ref=$tag 173 | fi 174 | 175 | _zulu_revolver start "Installing $package..." 176 | out=$(_zulu_install_package "$package" "$ref") 177 | state=$? 178 | _zulu_revolver stop 179 | 180 | if [ $state -eq 0 ]; then 181 | local -a link_flags; link_flags=() 182 | 183 | if [[ -n $no_autoselect_themes ]]; then 184 | link_flags=($link_flags '--no-autoselect-themes') 185 | fi 186 | 187 | builtin echo "$(_zulu_color green '✔') Finished installing $package" 188 | zulu link $link_flags $package 189 | else 190 | builtin echo "$(_zulu_color red '✘') Error installing $package" 191 | builtin echo "$out" 192 | error=1 193 | fi 194 | done 195 | 196 | # Write the new packagefile contents 197 | zulu bundle --dump --force 198 | 199 | if [[ $error -ne 0 ]]; then 200 | return 1 201 | fi 202 | } 203 | -------------------------------------------------------------------------------- /src/commands/link.zsh: -------------------------------------------------------------------------------- 1 | ### 2 | # Print usage information 3 | ### 4 | function _zulu_link_usage() { 5 | builtin echo $(_zulu_color yellow "Usage:") 6 | builtin echo " zulu link " 7 | builtin echo 8 | builtin echo $(_zulu_color yellow "Options:") 9 | builtin echo " --no-autoselect-themes Don't autoselect themes after installing" 10 | } 11 | 12 | ### 13 | # The zulu link function 14 | ### 15 | function _zulu_link() { 16 | local help package json dir file link base index no_autoselect_themes 17 | local -a dirs 18 | 19 | builtin zparseopts -D h=help -help=help \ 20 | -no-autoselect-themes=no_autoselect_themes 21 | 22 | if [[ -n $help ]]; then 23 | _zulu_link_usage 24 | return 25 | fi 26 | 27 | base=${ZULU_DIR:-"${ZDOTDIR:-$HOME}/.zulu"} 28 | config=${ZULU_CONFIG_DIR:-"${ZDOTDIR:-$HOME}/.config/zulu"} 29 | index="$base/index/packages" 30 | 31 | package="$1" 32 | 33 | # Check if the package is already installed 34 | root="$base/packages/$package" 35 | if [[ ! -d "$root" ]]; then 36 | builtin echo $(_zulu_color red "Package '$package' is not installed") 37 | return 1 38 | fi 39 | 40 | _zulu_revolver start "Linking $package..." 41 | 42 | # Get the JSON from the index 43 | json=$(command cat "$index/$package") 44 | 45 | # See if the package has a post_install script 46 | post_install=$(jsonval $json 'post_install') 47 | if [[ -n $post_install ]]; then 48 | # Change to the package directory 49 | oldPWD=$PWD 50 | builtin cd $root 51 | 52 | # Eval the post_install script 53 | output=$(builtin eval "$post_install") 54 | if [[ $? -ne 0 ]]; then 55 | builtin echo $(_zulu_color red "Post install step for $package failed") 56 | builtin echo "$output" 57 | builtin cd $oldPWD 58 | return 1 59 | fi 60 | 61 | builtin cd $oldPWD 62 | fi 63 | 64 | # Loop through the 'bin' and 'share' objects 65 | dirs=('bin' 'init' 'share') 66 | for dir in $dirs[@]; do 67 | # Reset $IFS, just in case 68 | local oldIFS=$IFS 69 | IFS=$' ' 70 | 71 | # Convert the bin/share object into an associative array 72 | typeset -A files; files=($(builtin echo $(jsonval $json $dir) | tr "," "\n" | tr ":" " ")) 73 | 74 | IFS=$oldIFS 75 | 76 | # Continue on to the next directory if no files exist 77 | [[ ${#files} -eq 0 ]] && continue 78 | 79 | # Loop through each of the values in the array, the key is a file within 80 | # the package, the value is the name of a symlink to create in the directory 81 | for file link in "${(@kv)files}"; do 82 | # Create a symlink to the file, filtering out .zwc files 83 | ln -s $root/${~file} $base/$dir/$link 84 | 85 | # Make sure that commands to be included in bin are executable 86 | if [[ "$dir" = "bin" ]]; then 87 | command chmod u+x "$root/$file" 88 | fi 89 | 90 | # Source init scripts 91 | if [[ "$dir" = "init" ]]; then 92 | builtin source $(command readlink "$base/init/$link") 93 | fi 94 | done 95 | done 96 | 97 | package_type=$(jsonval $json 'type') 98 | if [[ -z $no_autoselect_themes ]]; then 99 | if [[ $package_type = 'theme' ]]; then 100 | zulu theme $package 101 | fi 102 | fi 103 | 104 | _zulu_revolver stop 105 | builtin echo "$(_zulu_color green '✔') Finished linking $package" 106 | } 107 | -------------------------------------------------------------------------------- /src/commands/list.zsh: -------------------------------------------------------------------------------- 1 | ### 2 | # Print usage information 3 | ### 4 | function _zulu_list_usage() { 5 | builtin echo $(_zulu_color yellow "Usage:") 6 | builtin echo " zulu list [options]" 7 | builtin echo 8 | builtin echo $(_zulu_color yellow "Options:") 9 | builtin echo " -a, --all List all packages in the index" 10 | builtin echo " -d, --describe Include package description in output" 11 | builtin echo " -h, --help Output this help text and exit" 12 | builtin echo " -i, --installed List only installed packages (default)" 13 | builtin echo " -n, --not-installed List non-installed packages" 14 | builtin echo " -s, --simple Hide the 'package installed' indicator" 15 | builtin echo " -t, --type Limit results to packages of " 16 | builtin echo " --branch Print the current branch (if one is checked out)" 17 | builtin echo " --tag Print the current tag (if one is checked out)" 18 | } 19 | 20 | ### 21 | # Output a list of packages 22 | ### 23 | function _zulu_list_packages() { 24 | local base index files json packages package type name description pad lim 25 | 26 | base=${ZULU_DIR:-"${ZDOTDIR:-$HOME}/.zulu"} 27 | config=${ZULU_CONFIG_DIR:-"${ZDOTDIR:-$HOME}/.config/zulu"} 28 | index="$base/index/packages" 29 | 30 | for package in $(command ls $index); do 31 | # If --installed is passed but the package is not installed, 32 | # then skip past it 33 | if [[ -n $installed ]] && ! _zulu_info_is_installed $package; then 34 | continue 35 | fi 36 | 37 | # If --not-installed is passed but the package is installed, 38 | # then skip past it 39 | if [[ -n $not_installed ]] && _zulu_info_is_installed $package; then 40 | continue 41 | fi 42 | 43 | # We only need to read the package's index file if 44 | # the --type or --describe options are passed 45 | if [[ -n $package_type || -n $describe ]]; then 46 | json="$(command cat $index/$package)" 47 | fi 48 | 49 | # If --type is passed but the package is not of the 50 | # requested type, then skip past it 51 | if [[ -n $package_type ]]; then 52 | type=$(jsonval $json 'type') 53 | 54 | if [[ $type != $package_type ]]; then 55 | continue 56 | fi 57 | fi 58 | 59 | # Prevent ZVM from changing the ZSH version 60 | local old_ZVM_AUTO_USE=$ZVM_AUTO_USE 61 | builtin unset ZVM_AUTO_USE 62 | 63 | local suffix='' 64 | 65 | # If --branch is specified, get the current checked-out branch 66 | # for the package and print it alongside the name 67 | if [[ -n $branch ]] && _zulu_info_is_installed $package; then 68 | local oldPWD=$PWD 69 | builtin cd "$base/packages/$package" 70 | 71 | local current=$(command git status --short --branch -uno --ignore-submodules=all | command head -1 | command awk '{print $2}' 2>/dev/null) 72 | current=${current%...*} 73 | 74 | if [[ $current != 'HEAD' && $current != 'master' ]]; then 75 | suffix+=", branch: $current" 76 | fi 77 | 78 | builtin cd $oldPWD 79 | builtin unset oldPWD 80 | fi 81 | 82 | # If --tag is specified, get the current checked-out tag 83 | # for the package and print it alongside the name 84 | if [[ -n $tag ]] && _zulu_info_is_installed $package; then 85 | local oldPWD=$PWD 86 | builtin cd "$base/packages/$package" 87 | 88 | local commit=$(command git status HEAD -uno --ignore-submodules=all | command head -1 | command awk '{print $4}' 2>/dev/null) 89 | 90 | if [[ -n $commit ]]; then 91 | suffix+=", tag: $commit" 92 | fi 93 | 94 | builtin cd $oldPWD 95 | builtin unset oldPWD 96 | fi 97 | 98 | # Restore the previous ZVM_AUTO_USE setting 99 | export ZVM_AUTO_USE=$old_ZVM_AUTO_USE 100 | builtin unset old_ZVM_AUTO_USE 101 | 102 | # Print out the name of the package, and the installed flag 103 | # unless --simple is passed 104 | if [[ -n $simple ]]; then 105 | name="$package$suffix" 106 | lim=30 107 | else 108 | if _zulu_info_is_installed $package; then 109 | name="$(_zulu_color green '✔') $package$suffix" 110 | lim=42 111 | else 112 | name=" $package$suffix" 113 | lim=30 114 | fi 115 | fi 116 | 117 | # If --describe is specified, print the description 118 | if [[ -n $describe ]]; then 119 | description=$(jsonval $json 'description') 120 | builtin printf '%s' "$name" 121 | builtin printf '%*.*s' 0 $(($lim - ${#name} )) "$(builtin printf '%0.1s' " "{1..60})" 122 | builtin printf '%s\n' "$description" 123 | else 124 | builtin echo $name 125 | fi 126 | done 127 | 128 | return 129 | } 130 | 131 | ### 132 | # The main zulu list function 133 | ### 134 | function _zulu_list() { 135 | local help all installed not_installed describe simple package_type branch tag 136 | 137 | # If no arguments are passed, just print a simple list 138 | # of all installed packages 139 | if [[ $# -eq 0 ]]; then 140 | installed=true 141 | simple=true 142 | _zulu_list_packages 143 | return 144 | fi 145 | 146 | # Parse options 147 | builtin zparseopts -D \ 148 | h=help -help=help \ 149 | i=installed -installed=installed \ 150 | n=not_installed -not-installed=not_installed \ 151 | a=all -all=all \ 152 | d=describe -describe=describe \ 153 | s=simple -simple=simple \ 154 | t:=package_type -type:=package_type \ 155 | -branch=branch \ 156 | -tag=tag 157 | 158 | # Output help and return if requested 159 | if [[ -n $help ]]; then 160 | _zulu_list_usage 161 | return 162 | fi 163 | 164 | # Check if the --type option is passed and shift the argument 165 | if [[ -n $package_type ]]; then 166 | builtin shift package_type 167 | fi 168 | 169 | # List the packages 170 | _zulu_list_packages 171 | } 172 | -------------------------------------------------------------------------------- /src/commands/manpath.zsh: -------------------------------------------------------------------------------- 1 | ### 2 | # Output usage information 3 | ### 4 | function _zulu_manpath_usage() { 5 | builtin echo $(_zulu_color yellow "Usage:") 6 | builtin echo " zulu manpath " 7 | builtin echo 8 | builtin echo $(_zulu_color yellow "Context:") 9 | builtin echo " add Add a directory to \$manpath" 10 | builtin echo " reset Replace the current session \$manpath with the stored dirs" 11 | builtin echo " rm Remove a directory from \$manpath" 12 | } 13 | 14 | ### 15 | # Check the existence of a directory when passed as an argument, 16 | # and convert relative paths to absolute 17 | ### 18 | function _zulu_manpath_parse() { 19 | local dir="$1" check_existing="$2" 20 | 21 | if [[ -d "$PWD/$dir" ]]; then 22 | # If the directory exists in the current working directory 23 | # convert the relative path to absolute 24 | builtin echo "$PWD/$dir" 25 | elif [[ -d "$dir" ]]; then 26 | # If the directory exists as an absolute path, we can use it directly 27 | builtin echo "$dir" 28 | elif [[ "$check_existing" != "false" ]]; then 29 | # The directory could not be found 30 | builtin echo $dir 31 | return 1 32 | fi 33 | } 34 | 35 | ### 36 | # Add a directory to $manpath 37 | ### 38 | function _zulu_manpath_add() { 39 | local dir p 40 | local -a items paths; paths=($(command cat $pathfile)) 41 | 42 | # Check that each of the passed directories exist, and convert relative 43 | # paths to absolute 44 | for dir in "$@"; do 45 | dir=$(_zulu_manpath_parse "$dir") 46 | 47 | # If parsing returned with an error, output the error and return 48 | if [[ $? -eq 0 ]]; then 49 | # Add the directory to the array of items 50 | items+="$dir" 51 | 52 | builtin echo "$(_zulu_color green '✔') $dir added to \$manpath" 53 | else 54 | builtin echo "$(_zulu_color red '✘') $dir cannot be found" 55 | fi 56 | 57 | done 58 | 59 | # Loop through each of the existing paths and add those to the array as well 60 | for p in "$paths[@]"; do 61 | items+="$p" 62 | done 63 | 64 | # Store the new paths in the pathfile, and override $manpath 65 | _zulu_manpath_store 66 | _zulu_manpath_reset 67 | } 68 | 69 | ### 70 | # Remove a directory from $manpath 71 | ### 72 | function _zulu_manpath_rm() { 73 | local dir p 74 | local -a items paths; paths=($(command cat $pathfile)) 75 | 76 | # Check that each of the passed directories exist, and convert relative 77 | # paths to absolute 78 | for dir in "$@"; do 79 | dir=$(_zulu_manpath_parse "$dir" "false") 80 | 81 | # If parsing returned with an error, output the error and return 82 | if [[ ! $? -eq 0 ]]; then 83 | builtin echo $dir 84 | return 1 85 | fi 86 | 87 | # Loop through each of the paths, and if they are *not* an exact match, 88 | # we want to keep them 89 | for p in "$paths[@]"; do 90 | if [[ "$p" != "$dir" ]]; then 91 | items+="$p" 92 | fi 93 | done 94 | 95 | builtin echo "$(_zulu_color green '✔') $dir removed from \$manpath" 96 | done 97 | 98 | # Store the new paths in the pathfile, and override $manpath 99 | _zulu_manpath_store 100 | _zulu_manpath_reset 101 | } 102 | 103 | ### 104 | # Store an array of paths in the pathfile 105 | ### 106 | function _zulu_manpath_store() { 107 | local separator out 108 | 109 | # Separate the array by newlines, and print the contents to the pathfile 110 | separator=$'\n' 111 | local oldIFS=$IFS 112 | IFS="$separator"; out="${items[*]/#/${separator}}" 113 | builtin echo ${out:${#separator}} >! $pathfile 114 | IFS=$oldIFS 115 | builtin unset oldIFS 116 | } 117 | 118 | ### 119 | # Override the $manpath variable with the current contents of the pathfile 120 | ### 121 | function _zulu_manpath_reset() { 122 | local separator out 123 | local -a paths; paths=($(command cat $pathfile)) 124 | 125 | typeset -gUa manpath; manpath=() 126 | for p in "${paths[@]}"; do 127 | manpath+="$p" 128 | done 129 | } 130 | 131 | ### 132 | # Zulu command to handle path manipulation 133 | ### 134 | function _zulu_manpath() { 135 | local ctx base pathfile 136 | 137 | # Parse options 138 | builtin zparseopts -D h=help -help=help 139 | 140 | # Output help and return if requested 141 | if [[ -n $help ]]; then 142 | _zulu_manpath_usage 143 | return 144 | fi 145 | 146 | # Set up some variables 147 | base=${ZULU_DIR:-"${ZDOTDIR:-$HOME}/.zulu"} 148 | config=${ZULU_CONFIG_DIR:-"${ZDOTDIR:-$HOME}/.config/zulu"} 149 | pathfile="${config}/manpath" 150 | 151 | if [[ ! -f "$pathfile" ]]; then 152 | touch $pathfile 153 | fi 154 | 155 | # If no context is passed, output the contents of the pathfile 156 | if [[ "$1" = "" ]]; then 157 | command cat "$pathfile" 158 | return 159 | fi 160 | 161 | # Get the context 162 | ctx="$1" 163 | 164 | # Call the relevant function 165 | _zulu_manpath_${ctx} "${(@)@:2}" 166 | } 167 | -------------------------------------------------------------------------------- /src/commands/path.zsh: -------------------------------------------------------------------------------- 1 | ### 2 | # Output usage information 3 | ### 4 | function _zulu_path_usage() { 5 | builtin echo $(_zulu_color yellow "Usage:") 6 | builtin echo " zulu path " 7 | builtin echo 8 | builtin echo $(_zulu_color yellow "Context:") 9 | builtin echo " add Add a directory to \$path" 10 | builtin echo " reset Replace the current session \$path with the stored dirs" 11 | builtin echo " rm Remove a directory from \$path" 12 | } 13 | 14 | ### 15 | # Check the existence of a directory when passed as an argument, 16 | # and convert relative paths to absolute 17 | ### 18 | function _zulu_path_parse() { 19 | local dir="$1" check_existing="$2" 20 | 21 | if [[ -d "$PWD/$dir" ]]; then 22 | # If the directory exists in the current working directory 23 | # convert the relative path to absolute 24 | builtin echo "$PWD/$dir" 25 | elif [[ -d "$dir" ]]; then 26 | # If the directory exists as an absolute path, we can use it directly 27 | builtin echo "$dir" 28 | elif [[ "$check_existing" != "false" ]]; then 29 | # The directory could not be found 30 | builtin echo $dir 31 | return 1 32 | fi 33 | } 34 | 35 | ### 36 | # Add a directory to $path 37 | ### 38 | function _zulu_path_add() { 39 | local dir p 40 | local -a items paths; paths=($(command cat $pathfile)) 41 | 42 | # Check that each of the passed directories exist, and convert relative 43 | # paths to absolute 44 | for dir in "$@"; do 45 | dir=$(_zulu_path_parse "$dir") 46 | 47 | # If parsing returned with an error, output the error and return 48 | if [[ $? -eq 0 ]]; then 49 | # Add the directory to the array of items 50 | items+="$dir" 51 | 52 | builtin echo "$(_zulu_color green '✔') $dir added to \$path" 53 | else 54 | builtin echo "$(_zulu_color red '✘') $dir cannot be found" 55 | fi 56 | 57 | done 58 | 59 | # Loop through each of the existing paths and add those to the array as well 60 | for p in "$paths[@]"; do 61 | items+="$p" 62 | done 63 | 64 | # Store the new paths in the pathfile, and override $path 65 | _zulu_path_store 66 | _zulu_path_reset 67 | } 68 | 69 | ### 70 | # Remove a directory from $path 71 | ### 72 | function _zulu_path_rm() { 73 | local dir p 74 | local -a items paths; paths=($(command cat $pathfile)) 75 | 76 | # Check that each of the passed directories exist, and convert relative 77 | # paths to absolute 78 | for dir in "$@"; do 79 | dir=$(_zulu_path_parse "$dir" "false") 80 | 81 | # If parsing returned with an error, output the error and return 82 | if [[ ! $? -eq 0 ]]; then 83 | builtin echo $dir 84 | return 1 85 | fi 86 | 87 | # Loop through each of the paths, and if they are *not* an exact match, 88 | # we want to keep them 89 | for p in "$paths[@]"; do 90 | if [[ "$p" != "$dir" ]]; then 91 | items+="$p" 92 | fi 93 | done 94 | 95 | builtin echo "$(_zulu_color green '✔') $dir removed from \$path" 96 | done 97 | 98 | # Store the new paths in the pathfile, and override $path 99 | _zulu_path_store 100 | _zulu_path_reset 101 | } 102 | 103 | ### 104 | # Store an array of paths in the pathfile 105 | ### 106 | function _zulu_path_store() { 107 | local separator out 108 | 109 | # Separate the array by newlines, and print the contents to the pathfile 110 | separator=$'\n' 111 | local oldIFS=$IFS 112 | IFS="$separator"; out="${items[*]/#/${separator}}" 113 | builtin echo ${out:${#separator}} >! $pathfile 114 | IFS=$oldIFS 115 | builtin unset oldIFS 116 | } 117 | 118 | ### 119 | # Override the $path variable with the current contents of the pathfile 120 | ### 121 | function _zulu_path_reset() { 122 | local separator out 123 | local -a paths; paths=($(command cat $pathfile)) 124 | 125 | typeset -gUa path; path=() 126 | for p in "${paths[@]}"; do 127 | path+="$p" 128 | done 129 | } 130 | 131 | ### 132 | # Zulu command to handle path manipulation 133 | ### 134 | function _zulu_path() { 135 | local ctx base pathfile 136 | 137 | # Parse options 138 | builtin zparseopts -D h=help -help=help 139 | 140 | # Output help and return if requested 141 | if [[ -n $help ]]; then 142 | _zulu_path_usage 143 | return 144 | fi 145 | 146 | # Set up some variables 147 | base=${ZULU_DIR:-"${ZDOTDIR:-$HOME}/.zulu"} 148 | config=${ZULU_CONFIG_DIR:-"${ZDOTDIR:-$HOME}/.config/zulu"} 149 | pathfile="${config}/path" 150 | 151 | # If no context is passed, output the contents of the pathfile 152 | if [[ "$1" = "" ]]; then 153 | command cat "$pathfile" 154 | return 155 | fi 156 | 157 | # Get the context 158 | ctx="$1" 159 | 160 | # Call the relevant function 161 | _zulu_path_${ctx} "${(@)@:2}" 162 | } 163 | -------------------------------------------------------------------------------- /src/commands/search.zsh: -------------------------------------------------------------------------------- 1 | ### 2 | # Output usage information 3 | ### 4 | function _zulu_search_usage() { 5 | builtin echo $(_zulu_color yellow "Usage:") 6 | builtin echo " zulu search " 7 | } 8 | 9 | ### 10 | # Zulu command to search the package index 11 | ### 12 | function _zulu_search() { 13 | local base index out results term=$1 14 | 15 | # Parse options 16 | builtin zparseopts -D h=help -help=help 17 | 18 | # Output help and return if requested 19 | if [[ -n $help ]]; then 20 | _zulu_search_usage 21 | return 22 | fi 23 | 24 | # Set up some variables 25 | base=${ZULU_DIR:-"${ZDOTDIR:-$HOME}/.zulu"} 26 | config=${ZULU_CONFIG_DIR:-"${ZDOTDIR:-$HOME}/.config/zulu"} 27 | index="${base}/index/packages" 28 | 29 | results="$(zulu list --all | command grep -i $term)" 30 | builtin echo "$results" 31 | } 32 | -------------------------------------------------------------------------------- /src/commands/self-update.zsh: -------------------------------------------------------------------------------- 1 | ### 2 | # Print usage information 3 | ### 4 | function _zulu_self-update_usage() { 5 | builtin echo $(_zulu_color yellow "Usage:") 6 | builtin echo " zulu self-update [options]" 7 | builtin echo 8 | builtin echo $(_zulu_color yellow "Options:") 9 | builtin echo " -c, --check Check if an update is available" 10 | builtin echo " -h, --help Output this help text and exit" 11 | } 12 | 13 | ### 14 | # Update the zulu core 15 | ### 16 | function _zulu_self-update_core() { 17 | local old="$(pwd)" 18 | 19 | builtin cd $core 20 | command git rebase -p --autostash FETCH_HEAD 21 | 22 | if [[ $? -eq 0 ]]; then 23 | builtin echo "$(_zulu_color red '✗') Zulu core failed to update" 24 | fi 25 | 26 | [[ -f build.zsh ]] && ./build.zsh 27 | builtin source zulu 28 | _zulu_init 29 | builtin cd $old 30 | } 31 | 32 | function _zulu_self-update_check_for_update() { 33 | local old="$(pwd)" 34 | 35 | builtin cd "$base/core" 36 | 37 | command git fetch origin &>/dev/null 38 | 39 | if command git rev-parse --abbrev-ref @'{u}' &>/dev/null; then 40 | count="$(command git rev-list --left-right --count HEAD...@'{u}' 2>/dev/null)" 41 | 42 | down="$count[(w)2]" 43 | 44 | if [[ $down -gt 0 ]]; then 45 | builtin echo "$(_zulu_color green "New Zulu version available") Run zulu self-update to upgrade" 46 | builtin cd $old 47 | return 48 | fi 49 | fi 50 | 51 | builtin echo $(_zulu_color green 'No update available') 52 | builtin cd $old 53 | return 1 54 | } 55 | 56 | ### 57 | # Update the zulu core 58 | ### 59 | function _zulu_self-update() { 60 | local help base core check 61 | 62 | base=${ZULU_DIR:-"${ZDOTDIR:-$HOME}/.zulu"} 63 | core="${base}/core" 64 | 65 | # Parse options 66 | builtin zparseopts -D h=help -help=help c=check -check=check 67 | 68 | # Output help and return if requested 69 | if [[ -n $help ]]; then 70 | _zulu_self-update_usage 71 | return 72 | fi 73 | 74 | if [[ -n $check ]]; then 75 | _zulu_revolver start "Checking for updates..." 76 | _zulu_self-update_check_for_update 77 | _zulu_revolver stop 78 | return 79 | fi 80 | 81 | _zulu_revolver start "Checking for updates..." 82 | if _zulu_self-update_check_for_update > /dev/null; then 83 | _zulu_revolver update "Updating zulu core..." 84 | out=$(_zulu_self-update_core 2>&1) 85 | _zulu_revolver stop 86 | 87 | if [ $? -eq 0 ]; then 88 | builtin echo "$(_zulu_color green '✔') Zulu core updated" 89 | else 90 | builtin echo "$(_zulu_color red '✘') Error updating zulu core" 91 | builtin echo "$out" 92 | 93 | return 1 94 | fi 95 | 96 | return 97 | fi 98 | 99 | _zulu_revolver stop 100 | builtin echo "$(_zulu_color green "No update available")" 101 | } 102 | -------------------------------------------------------------------------------- /src/commands/switch.zsh: -------------------------------------------------------------------------------- 1 | ### 2 | # Output usage information 3 | ### 4 | function _zulu_switch_usage() { 5 | builtin echo $(_zulu_color yellow "Usage:") 6 | builtin echo " zulu switch " 7 | builtin echo 8 | builtin echo $(_zulu_color yellow "Options:") 9 | builtin echo " -b, --branch Checkout the specified branch" 10 | builtin echo " -t, --tag Checkout the specified tag or commit" 11 | } 12 | 13 | ### 14 | # Checkout the provided tag or branch in the package repository 15 | ### 16 | function _zulu_switch_checkout() { 17 | local package="$1" ref="$2" 18 | local base=${ZULU_DIR:-"${ZDOTDIR:-$HOME}/.zulu"} 19 | 20 | if ! _zulu_info_is_installed $package; then 21 | builtin echo $(_zulu_color red "Package $package is not installed") 22 | fi 23 | 24 | local oldPWD=$PWD 25 | builtin cd "$base/packages/$package" 26 | 27 | command git fetch origin >/dev/null 2>&1 28 | output=$(command git checkout -qf $ref 2>&1) 29 | state=$? 30 | 31 | builtin cd $oldPWD 32 | builtin unset oldPWD 33 | 34 | if [[ $state -ne 0 ]]; then 35 | builtin echo $(_zulu_color red "Failed to checkout $ref of package $package") 36 | builtin echo $output 37 | 38 | return 1 39 | fi 40 | 41 | builtin echo "$(_zulu_color green '✔') Successfully switched $package to $ref" 42 | } 43 | 44 | ### 45 | # Zulu command to handle path manipulation 46 | ### 47 | function _zulu_switch() { 48 | local ctx base help branch tag ref 49 | 50 | # Parse options 51 | builtin zparseopts -D h=help -help=help \ 52 | b:=branch -branch:=branch \ 53 | t:=tag -tag:=tag 54 | 55 | # Output help and return if requested 56 | if [[ -n $help ]]; then 57 | _zulu_switch_usage 58 | return 59 | fi 60 | 61 | if [[ -z $branch && -z $tag ]]; then 62 | builtin echo $(_zulu_color red 'You must specify a branch or tag') 63 | return 1 64 | fi 65 | 66 | if [[ -n $branch && -n $tag ]]; then 67 | builtin echo $(_zulu_color red 'You must only specify one of branch or tag') 68 | return 1 69 | fi 70 | 71 | if [[ -n $branch ]]; then 72 | builtin shift branch 73 | ref=$branch 74 | fi 75 | 76 | if [[ -n $tag ]]; then 77 | builtin shift tag 78 | ref=$tag 79 | fi 80 | 81 | # Set up some variables 82 | base=${ZULU_DIR:-"${ZDOTDIR:-$HOME}/.zulu"} 83 | package="$1" 84 | 85 | # Call the relevant function 86 | _zulu_switch_checkout $package $ref 87 | } 88 | -------------------------------------------------------------------------------- /src/commands/sync.zsh: -------------------------------------------------------------------------------- 1 | ### 2 | # Output usage information 3 | ### 4 | function _zulu_sync_usage() { 5 | builtin echo $(_zulu_color yellow 'Usage:') 6 | builtin echo ' zulu sync' 7 | builtin echo 8 | builtin echo $(_zulu_color yellow 'Commands:') 9 | builtin echo ' pull Pull changes from remote repository' 10 | builtin echo ' push Push local changes to remote repository' 11 | } 12 | 13 | ### 14 | # Pull changes from the remote repository 15 | ### 16 | function _zulu_sync_pull_changes() { 17 | local oldPWD=$PWD 18 | builtin cd $config_dir 19 | 20 | # Start the progress spinner 21 | _zulu_revolver start 'Syncing...' 22 | 23 | # Fetch from the remote 24 | command git fetch origin >/dev/null 2>&1 25 | 26 | # Check if any updates are available 27 | count="$(command git rev-list --left-right --count HEAD...@'{u}' 2>/dev/null)" 28 | down="$count[(w)2]" 29 | 30 | # If no updates are available, stop and tell the user 31 | if [[ $down -eq 0 ]]; then 32 | builtin cd $oldPWD 33 | builtin unset oldPWD 34 | 35 | _zulu_revolver stop 36 | builtin echo $(_zulu_color green 'No updates found') 37 | return 38 | fi 39 | 40 | # Rebase master over the updates 41 | command git rebase -p --autostash origin/master >/dev/null 2>&1 42 | if [[ $? -ne 0 ]]; then 43 | builtin cd $oldPWD 44 | builtin unset oldPWD 45 | 46 | _zulu_revolver stop 47 | builtin echo $(_zulu_color red 'Failed to merge changes from remote') 48 | return 1 49 | fi 50 | 51 | zulu bundle 52 | zulu init 53 | 54 | # Success! Tell the user 55 | _zulu_revolver stop 56 | builtin echo "$(_zulu_color green '✔') Remote changes synced" 57 | 58 | builtin cd $oldPWD 59 | builtin unset oldPWD 60 | } 61 | 62 | function _zulu_sync_push_changes() { 63 | local oldPWD=$PWD 64 | builtin cd $config_dir 65 | 66 | # Start the progress spinner 67 | _zulu_revolver start 'Syncing...' 68 | 69 | # Fetch from the remote 70 | command git fetch origin >/dev/null 2>&1 71 | 72 | # Check if any updates are available 73 | count="$(command git rev-list --left-right --count HEAD...@'{u}' 2>/dev/null)" 74 | down="$count[(w)2]" 75 | 76 | # If no updates are available, stop and tell the user 77 | if [[ $down -gt 0 ]]; then 78 | builtin cd $oldPWD 79 | builtin unset oldPWD 80 | 81 | _zulu_revolver stop 82 | builtin echo $(_zulu_color red 'Remote has been updated. Pull changes first') 83 | return 1 84 | fi 85 | 86 | dirty="$(command git diff --ignore-submodules=all HEAD 2>/dev/null)" 87 | if [[ -z $dirty ]]; then 88 | builtin cd $oldPWD 89 | builtin unset oldPWD 90 | 91 | _zulu_revolver stop 92 | builtin echo $(_zulu_color green 'Nothing to sync') 93 | return 1 94 | fi 95 | 96 | command git add . >/dev/null 2>&1 97 | command git commit -m "Sync config from $HOST" >/dev/null 2>&1 98 | command git push -u origin master >/dev/null 2>&1 99 | 100 | _zulu_revolver stop 101 | builtin echo "$(_zulu_color green '✔') Local changes uploaded" 102 | 103 | builtin cd $oldPWD 104 | builtin unset oldPWD 105 | } 106 | 107 | ### 108 | # Check if the sync repository has already been set up 109 | ### 110 | function _zulu_sync_repository_exists() { 111 | local oldPWD=$PWD 112 | builtin cd $config_dir 113 | 114 | # Check if the config directory is already within a git repository 115 | if command git rev-parse --is-inside-work-tree &>/dev/null; then 116 | # If it is, check if the config directory is the git root. 117 | # If it's not, we'll exit, since syncing is probably already 118 | # being handled outside of Zulu 119 | git_dir=$(command git rev-parse --git-dir) 120 | if [[ $git_dir = ".git" ]]; then 121 | builtin cd $oldPWD 122 | builtin unset oldPWD 123 | 124 | return 0 125 | fi 126 | fi 127 | 128 | builtin cd $oldPWD 129 | builtin unset oldPWD 130 | 131 | return 1 132 | } 133 | 134 | ### 135 | # Setup a new environment ready for syncing 136 | ### 137 | function _zulu_sync_setup() { 138 | # Change into the config directory 139 | local oldPWD=$PWD 140 | builtin cd $config_dir 141 | 142 | # Check if the config directory is already within a git repository 143 | if command git rev-parse --is-inside-work-tree &>/dev/null; then 144 | # If it is, check if the config directory is the git root. 145 | # If it's not, we'll exit, since syncing is probably already 146 | # being handled outside of Zulu 147 | git_dir=$(command git rev-parse --git-dir) 148 | if [[ $git_dir != ".git" ]]; then 149 | builtin cd $oldPWD 150 | builtin unset oldPWD 151 | 152 | builtin echo $(_zulu_color red "It looks like $config_dir is already within a git repository at $git_dir") 153 | return 1 154 | fi 155 | 156 | return 157 | fi 158 | 159 | # Create a new git repository in the config directory 160 | if ! command git init >/dev/null 2>&1; then 161 | builtin cd $oldPWD 162 | builtin unset oldPWD 163 | 164 | builtin echo $(_zulu_color red 'Failed to initialise empty repository') 165 | exit 1 166 | fi 167 | 168 | # Ask the user for the remote repository URL 169 | builtin echo $(_zulu_color yellow 'Sync has not been set up yet') 170 | builtin echo 'If you haven'\''t already, create a repository using' 171 | builtin echo 'a remote service such as github.com' 172 | builtin echo 173 | vared -p "$(_zulu_color yellow 'Please enter your repository URL: ')" -c repo_url 174 | 175 | # If a URL was not provided, exit 176 | if [[ -z $repo_url ]]; then 177 | builtin cd $oldPWD 178 | builtin unset oldPWD 179 | 180 | builtin echo $(_zulu_color red 'Repository URL not provided') 181 | return 1 182 | fi 183 | 184 | # Set the repository's origin to the remote 185 | command git remote add origin $repo_url 186 | command git fetch origin >/dev/null 2>&1 187 | 188 | # Create a .gitignore if one does not exist, to ensure 189 | # private configuration is not synced 190 | if [[ ! -f .gitignore ]]; then 191 | builtin echo ".backup 192 | *.private" > .gitignore 193 | fi 194 | 195 | remotes=$(command git rev-parse --remotes) 196 | if [[ -n $remotes ]]; then 197 | # The repository provided already has a HEAD 198 | # Present the user with some options 199 | vared -p " 200 | $(_zulu_color yellow "It looks like there's already some code in that repository") 201 | Please choose from one of the following options: 202 | 203 | p) Push local changes, and overwrite the remote 204 | b) Back up local changes, and pull from remote 205 | *) Cancel and exit 206 | 207 | Your choice: " -c choice 208 | 209 | case $choice in 210 | # Force push the empty repository to the remote, 211 | # overwriting any existing remote config 212 | ( p|P ) 213 | _zulu_revolver start 'Overwriting remote config...' 214 | # Commit changes 215 | command git add . >/dev/null 2>&1 216 | command git commit -m "Sync config from $HOST" >/dev/null 2>&1 217 | 218 | # Force push to overwrite remote config 219 | command git push --force --set-upstream origin master >/dev/null 2>&1 220 | 221 | _zulu_revolver stop 222 | builtin echo 223 | builtin echo "$(_zulu_color green '✔') Sync setup complete" 224 | 225 | # Return to the previous directory 226 | builtin cd $oldPWD 227 | builtin unset oldPWD 228 | ;; 229 | 230 | # Back up the existing config to $ZULU_CONFIG_DIR/.backup 231 | # and create a fresh clone of the remote repository in $ZULU_CONFIG_DIR 232 | ( b|B ) 233 | _zulu_revolver start 'Backing up and downloading from remote...' 234 | 235 | # Return to the previous directory so we can move 236 | # the current directory 237 | builtin cd $oldPWD 238 | builtin unset oldPWD 239 | 240 | # Move existing config directory into tmp 241 | command mv "$ZULU_CONFIG_DIR" "/tmp/zulu-config.bkp" 242 | 243 | # Since we have no local branch we can't pull 244 | # a remote branch into the local repository, 245 | # so we create a fresh clone instead 246 | command git clone $repo_url $ZULU_CONFIG_DIR >/dev/null 2>&1 247 | 248 | # Move the temporary backup back into the repository 249 | # so that it's easy to find. It will be ignored by git 250 | command mv "/tmp/zulu-config.bkp" "$ZULU_CONFIG_DIR/.backup" 251 | 252 | _zulu_revolver stop 253 | builtin echo 254 | builtin echo "$(_zulu_color green '✔') Sync setup complete" 255 | builtin echo "Old config backed up to $ZULU_CONFIG_DIR/.backup" 256 | builtin echo 257 | 258 | zulu bundle 259 | zulu init 260 | 261 | builtin echo "$(_zulu_color green '✔') Remote changes synced" 262 | ;; 263 | 264 | # Something else was entered, exit 265 | ( * ) 266 | # Return to the previous directory 267 | builtin cd $oldPWD 268 | builtin unset oldPWD 269 | 270 | return 1 271 | ;; 272 | esac 273 | fi 274 | } 275 | 276 | ### 277 | # The main sync command 278 | ### 279 | function _zulu_sync() { 280 | local ctx config_dir 281 | 282 | # Parse options 283 | builtin zparseopts -D h=help -help=help 284 | 285 | # Output help and return if requested 286 | if [[ -n $help ]]; then 287 | _zulu_sync_usage 288 | return 289 | fi 290 | 291 | # The path to the config directory 292 | config_dir="${ZULU_CONFIG_DIR:-"${ZDOTDIR:-$HOME}/.config/zulu"}" 293 | 294 | # Check if the repository exists 295 | if ! _zulu_sync_repository_exists; then 296 | # It doesn't. Create it 297 | _zulu_sync_setup 298 | return $? 299 | fi 300 | 301 | ctx="$1" 302 | 303 | if [[ -z $ctx ]]; then 304 | # Sync changes both ways 305 | _zulu_sync_pull_changes && _zulu_sync_push_changes 306 | return $? 307 | fi 308 | 309 | case $ctx in 310 | push ) 311 | _zulu_sync_push_changes 312 | ;; 313 | pull ) 314 | _zulu_sync_pull_changes 315 | ;; 316 | * ) 317 | builtin echo $(_zulu_color red "Unrecognized command $ctx") 318 | return 1 319 | esac 320 | } 321 | -------------------------------------------------------------------------------- /src/commands/theme.zsh: -------------------------------------------------------------------------------- 1 | ### 2 | # Output usage information 3 | ### 4 | function _zulu_theme_usage() { 5 | builtin echo $(_zulu_color yellow "Usage:") 6 | builtin echo " zulu theme " 7 | } 8 | 9 | _zulu_theme() { 10 | local base theme config config_dir 11 | 12 | theme="$1" 13 | 14 | # Parse options 15 | builtin zparseopts -D h=help -help=help 16 | 17 | # Output help and return if requested 18 | if [[ -n $help ]]; then 19 | _zulu_theme_usage 20 | return 21 | fi 22 | 23 | # Set up some variables 24 | base=${ZULU_DIR:-"${ZDOTDIR:-$HOME}/.zulu"} 25 | config_dir=${ZULU_CONFIG_DIR:-"${ZDOTDIR:-$HOME}/.config/zulu"} 26 | config="${config_dir}/theme" 27 | 28 | # If no argument is passed, print the current theme 29 | if [[ -z $theme ]]; then 30 | echo "$(cat $config)" 31 | return 32 | fi 33 | 34 | # Ensure promptinit is loaded 35 | autoload -U promptinit && promptinit 36 | 37 | # Test if theme prompt function exists. 38 | # If not, print a pretty warn message. 39 | if builtin which prompt_${theme}_setup >/dev/null 2>&1; then 40 | prompt ${theme} 41 | if [[ $? -eq 0 ]]; then 42 | builtin echo "$theme" >! $config 43 | builtin echo "$(_zulu_color green '✔') Theme set to $theme" 44 | return 45 | fi 46 | fi 47 | 48 | builtin echo $(_zulu_color red "Failed to load theme '${theme}'") 49 | builtin echo "Please ensure your theme is in \$fpath and is called prompt_${theme}_setup" 50 | return 1 51 | } 52 | -------------------------------------------------------------------------------- /src/commands/uninstall.zsh: -------------------------------------------------------------------------------- 1 | ### 2 | # Output usage information 3 | ### 4 | function _zulu_uninstall_usage() { 5 | builtin echo $(_zulu_color yellow "Usage:") 6 | builtin echo " zulu uninstall " 7 | } 8 | 9 | ### 10 | # Install a package 11 | ### 12 | function _zulu_uninstall_package() { 13 | local package root 14 | 15 | package="$1" 16 | 17 | # Double check that the package name has been passed 18 | if [[ -z $package ]]; then 19 | builtin echo $(_zulu_color red "Please specify a package name") 20 | builtin echo 21 | _zulu_uninstall_usage 22 | return 1 23 | fi 24 | 25 | # Check if the package is already uninstalled 26 | root="$base/packages/$package" 27 | 28 | # Remove the package source 29 | # 30 | # TODO: Obviously, this works, but would really like to find a pure-zsh 31 | # way of doing this safely *just in case* the root variable doesn't 32 | # get populated for some reason 33 | command rm -rf "$root" 34 | 35 | return $? 36 | } 37 | 38 | ### 39 | # Zulu command to handle package installation 40 | ### 41 | function _zulu_uninstall() { 42 | local base index packages out 43 | 44 | # Parse options 45 | builtin zparseopts -D h=help -help=help 46 | 47 | # Output help and return if requested 48 | if [[ -n $help ]]; then 49 | _zulu_uninstall_usage 50 | return 51 | fi 52 | 53 | # Set up some variables 54 | base=${ZULU_DIR:-"${ZDOTDIR:-$HOME}/.zulu"} 55 | config_dir=${ZULU_CONFIG_DIR:-"${ZDOTDIR:-$HOME}/.config/zulu"} 56 | index="${base}/index/packages" 57 | 58 | # If no context is passed, output the contents of the pathfile 59 | if [[ "$1" = "" ]]; then 60 | builtin echo $(_zulu_color red "Please specify a package name") 61 | builtin echo 62 | _zulu_uninstall_usage 63 | return 1 64 | fi 65 | 66 | # Do a first loop, to ensure all packages exist 67 | for package in "$@"; do 68 | if [[ ! -f "$index/$package" ]]; then 69 | builtin echo $(_zulu_color red "Package '$package' is not in the index") 70 | return 1 71 | fi 72 | 73 | if [[ ! -d "$base/packages/$package" ]]; then 74 | builtin echo $(_zulu_color red "Package '$package' is not installed") 75 | return 1 76 | fi 77 | done 78 | 79 | # Do a second loop, to do the actual install 80 | for package in "$@"; do 81 | zulu unlink $package 82 | [ $? -ne 0 ] && return 1 83 | 84 | _zulu_revolver start "Uninstalling $package..." 85 | out=$(_zulu_uninstall_package "$package" 2>&1) 86 | state=$? 87 | _zulu_revolver stop 88 | 89 | if [ $state -eq 0 ]; then 90 | builtin echo "$(_zulu_color green '✔') Finished uninstalling $package" 91 | else 92 | builtin echo "$(_zulu_color red '✘') Error uninstalling $package" 93 | builtin echo "$out" 94 | fi 95 | done 96 | 97 | zulu bundle --dump --force 98 | } 99 | -------------------------------------------------------------------------------- /src/commands/unlink.zsh: -------------------------------------------------------------------------------- 1 | ### 2 | # Print usage information 3 | ### 4 | function _zulu_unlink_usage() { 5 | builtin echo $(_zulu_color yellow "Usage:") 6 | builtin echo " zulu unlink " 7 | } 8 | 9 | ### 10 | # The zulu unlink function 11 | ### 12 | function _zulu_unlink() { 13 | local help package json dir file link base 14 | local -a dirs 15 | 16 | builtin zparseopts -D h=help -help=help 17 | 18 | if [[ -n $help ]]; then 19 | _zulu_unlink_usage 20 | return 21 | fi 22 | 23 | base=${ZULU_DIR:-"${ZDOTDIR:-$HOME}/.zulu"} 24 | config_dir=${ZULU_CONFIG_DIR:-"${ZDOTDIR:-$HOME}/.config/zulu"} 25 | index="$base/index/packages" 26 | 27 | package="$1" 28 | 29 | # Check if the package is already installed 30 | root="$base/packages/$package" 31 | if [[ ! -d "$root" ]]; then 32 | builtin echo $(_zulu_color red "Package '$package' is not installed") 33 | return 1 34 | fi 35 | 36 | _zulu_revolver start "Unlinking $package..." 37 | 38 | # Get the JSON from the index 39 | json=$(command cat "$index/$package") 40 | 41 | # Loop through the 'bin' and 'share' objects 42 | dirs=('bin' 'init' 'share') 43 | local oldPWD=$PWD 44 | local flags 45 | 46 | case $OSTYPE in 47 | darwin* ) 48 | flags='' 49 | ;; 50 | linux* ) 51 | flags='-r' 52 | ;; 53 | esac 54 | 55 | for dir in $dirs[@]; do 56 | builtin cd "$base/$dir" 57 | # Unlink any file in $dir which points to the package's source 58 | command ls -la | \ 59 | command grep "$base/packages/$package/" | \ 60 | command awk '{print $9}' | \ 61 | command xargs $flags /bin/rm 62 | done 63 | 64 | builtin cd $oldPWD 65 | 66 | _zulu_revolver stop 67 | builtin echo "$(_zulu_color green '✔') Finished unlinking $package" 68 | } 69 | -------------------------------------------------------------------------------- /src/commands/update.zsh: -------------------------------------------------------------------------------- 1 | ### 2 | # Print usage information 3 | ### 4 | function _zulu_update_usage() { 5 | builtin echo $(_zulu_color yellow "Usage:") 6 | builtin echo " zulu update [options]" 7 | builtin echo 8 | builtin echo $(_zulu_color yellow "Options:") 9 | builtin echo " -c, --check Check if an update is available" 10 | builtin echo " -h, --help Output this help text and exit" 11 | } 12 | 13 | ### 14 | # Update the zulu package index 15 | ### 16 | function _zulu_update_index() { 17 | local old="$(pwd)" 18 | local stub="packages/" 19 | typeset -A files 20 | typeset -a changed; changed=() 21 | typeset -a new; new=() 22 | typeset -a removed; removed=() 23 | 24 | builtin cd $index 25 | 26 | # Get the list of changed files 27 | files=($(command git diff --name-status HEAD...@'{u}' 2>&1)) 28 | 29 | # Sort files into arrays for changed, new and removed packages 30 | for type file in "${(@kv)files}"; do 31 | if [[ $type == 'M' ]]; then 32 | changed=($changed ${file//${stub}/}) 33 | fi 34 | 35 | if [[ $type == 'A' ]]; then 36 | new=($new ${file//${stub}/}) 37 | fi 38 | 39 | if [[ $type == 'D' ]]; then 40 | removed=($removed ${file//${stub}/}) 41 | fi 42 | done 43 | 44 | # Update the index 45 | local out=$(command git rebase -p --autostash FETCH_HEAD >/dev/null 2>&1) 46 | if [ $? -ne 0 ]; then 47 | builtin echo $(color red $out) 48 | return 1 49 | fi 50 | 51 | # Print the updated packages 52 | if [ ${#changed} -gt 0 ]; then 53 | builtin echo $(color yellow 'Updated packages') 54 | builtin echo " $changed" 55 | fi 56 | 57 | if [ ${#new} -gt 0 ]; then 58 | builtin echo $(color yellow 'New packages') 59 | builtin echo " $new" 60 | fi 61 | 62 | if [ ${#removed} -gt 0 ]; then 63 | builtin echo $(color yellow 'Deleted packages') 64 | builtin echo " $removed" 65 | fi 66 | 67 | builtin cd $old 68 | } 69 | 70 | function _zulu_update_check_for_update() { 71 | local old="$(pwd)" 72 | 73 | builtin cd "$base/index" 74 | 75 | command git fetch origin &>/dev/null 76 | 77 | if command git rev-parse --abbrev-ref @'{u}' &>/dev/null; then 78 | count="$(command git rev-list --left-right --count HEAD...@'{u}' 2>/dev/null)" 79 | 80 | down="$count[(w)2]" 81 | 82 | if [[ $down -gt 0 ]]; then 83 | builtin echo "$(_zulu_color green "Zulu index updates available") Run zulu update to update the index" 84 | builtin cd $old 85 | return 86 | fi 87 | fi 88 | 89 | builtin echo "$(_zulu_color green "No update available")" 90 | builtin cd $old 91 | return 1 92 | } 93 | 94 | ### 95 | # Update the zulu package index 96 | ### 97 | function _zulu_update() { 98 | local help base index check 99 | 100 | base=${ZULU_DIR:-"${ZDOTDIR:-$HOME}/.zulu"} 101 | index="${base}/index" 102 | 103 | # Parse options 104 | builtin zparseopts -D h=help -help=help c=check -check=check 105 | 106 | # Output help and return if requested 107 | if [[ -n $help ]]; then 108 | _zulu_update_usage 109 | return 110 | fi 111 | 112 | if [[ -n $check ]]; then 113 | _zulu_revolver start "Checking for updates..." 114 | _zulu_update_check_for_update 115 | _zulu_revolver stop 116 | return 117 | fi 118 | 119 | _zulu_revolver start "Checking for updates..." 120 | if _zulu_update_check_for_update > /dev/null; then 121 | _zulu_revolver update "Updating package index..." 122 | out=$(_zulu_update_index 2>&1) 123 | _zulu_revolver stop 124 | 125 | if [ $? -eq 0 ]; then 126 | builtin echo "$out" 127 | builtin echo "$(_zulu_color green '✔') Package index updated" 128 | else 129 | builtin echo "$(_zulu_color red '✘') Error updating package index" 130 | builtin echo "$out" 131 | fi 132 | 133 | return 134 | fi 135 | 136 | _zulu_revolver stop 137 | builtin echo "$(_zulu_color green "No update available")" 138 | } 139 | -------------------------------------------------------------------------------- /src/commands/upgrade.zsh: -------------------------------------------------------------------------------- 1 | ### 2 | # Output usage information 3 | ### 4 | function _zulu_upgrade_usage() { 5 | builtin echo $(_zulu_color yellow "Usage:") 6 | builtin echo " zulu upgrade []" 7 | builtin echo 8 | builtin echo $(_zulu_color yellow "Options:") 9 | builtin echo " -c, --check Check if upgrades are available" 10 | builtin echo " -h, --help Output this help text and exit" 11 | builtin echo " -y, --no-confirmation Do not ask for confirmation before upgrading" 12 | } 13 | 14 | ### 15 | # Upgrade a package 16 | ### 17 | function _zulu_upgrade_package() { 18 | local package json repo dir file link oldpwd=$(pwd) 19 | 20 | package="$1" 21 | 22 | # Don't let zvm change the ZSH version for use while we're checking 23 | local old_ZVM_AUTO_USE=${ZVM_AUTO_USE} 24 | unset ZVM_AUTO_USE 25 | 26 | # Pull from the repository 27 | cd "$base/packages/$package" 28 | 29 | git rebase -p --autostash FETCH_HEAD && git submodule update --init --recursive 30 | 31 | cd $oldpwd 32 | 33 | # Restore the ZVM_AUTO_USE setting 34 | export ZVM_AUTO_USE=${old_ZVM_AUTO_USE} 35 | } 36 | 37 | ### 38 | # Zulu command to handle package upgrades 39 | ### 40 | function _zulu_upgrade() { 41 | local base index out count down oldpwd i input no_confirmation 42 | local -a packages to_update 43 | local -A _pids 44 | 45 | # Parse options 46 | builtin zparseopts -D h=help -help=help \ 47 | c=check -check=check \ 48 | y=no_confirmation -no-confirmation=no_confirmation 49 | 50 | # Output help and return if requested 51 | if [[ -n $help ]]; then 52 | _zulu_upgrade_usage 53 | return 54 | fi 55 | 56 | # Don't let zvm change the ZSH version for use while we're checking 57 | local old_ZVM_AUTO_USE=${ZVM_AUTO_USE} 58 | unset ZVM_AUTO_USE 59 | 60 | # Set up some variables 61 | base=${ZULU_DIR:-"${ZDOTDIR:-$HOME}/.zulu"} 62 | config=${ZULU_CONFIG_DIR:-"${ZDOTDIR:-$HOME}/.config/zulu"} 63 | index="${base}/index/packages" 64 | 65 | _zulu_revolver start "Checking for updates..." 66 | 67 | packages=($@) 68 | packagefile="$config/packages" 69 | 70 | if [[ ! -f $packagefile ]]; then 71 | touch $packagefile 72 | fi 73 | 74 | # If no context is passed, upgrade the contents of the packagefile 75 | if [[ ${#packages} -eq 0 ]]; then 76 | packages=($(/bin/ls "$base/packages")) 77 | fi 78 | 79 | oldpwd=$(pwd) 80 | 81 | # If the ZSH version we are using supports it, 82 | # perform update checks asynchronously 83 | if is-at-least '5.1'; then 84 | _pids=() 85 | # Do a first loop, to kick off a fetch asynchronously 86 | for package in "$packages[@]"; do 87 | cd "$base/packages/$package" 88 | 89 | { 90 | git fetch origin >/dev/null 2>&1 91 | } &! 92 | _pids[${package}]=$! 93 | done 94 | 95 | # Do a second loop, to wait until all subprocesses have finished 96 | for package pid in "${(@kv)_pids}"; do 97 | while kill -0 $pid >/dev/null 2>&1; do 98 | done 99 | done 100 | else 101 | for package in "$packages[@]"; do 102 | cd "$base/packages/$package" 103 | git fetch origin >/dev/null 2>&1 104 | done 105 | fi 106 | 107 | # Do a third loop, to check if updates are available 108 | i=1 109 | for package in "$packages[@]"; do 110 | cd "$base/packages/$package" 111 | 112 | if command git rev-parse --abbrev-ref @'{u}' &>/dev/null; then 113 | count="$(command git rev-list --left-right --count HEAD...@'{u}' 2>/dev/null)" 114 | 115 | down="$count[(w)2]" 116 | 117 | if [[ $down -gt 0 ]]; then 118 | to_update[$i]="$package" 119 | i=$(( i + 1 )) 120 | fi 121 | fi 122 | done 123 | 124 | cd $oldpwd 125 | 126 | # Restore the ZVM_AUTO_USE setting 127 | export ZVM_AUTO_USE=${old_ZVM_AUTO_USE} 128 | 129 | _zulu_revolver stop 130 | 131 | if [[ ${#to_update} -eq 0 ]]; then 132 | builtin echo "$(_zulu_color green "Nothing to upgrade")" 133 | return 1 134 | fi 135 | 136 | if [[ -n $check ]]; then 137 | builtin echo "$(_zulu_color green 'Package upgrades available') Run zulu upgrade to upgrade" 138 | return 0 139 | fi 140 | 141 | builtin echo $(_zulu_color yellow 'The following packages will be upgraded') 142 | builtin echo "$to_update[@]" 143 | 144 | if [[ -z $no_confirmation ]]; then 145 | builtin echo $(_zulu_color yellow bold 'Continue (y|N)') 146 | builtin read -rs -k 1 input 147 | else 148 | input='y' 149 | fi 150 | 151 | case $input in 152 | y) 153 | for package in "$to_update[@]"; do 154 | if [[ -z $package ]]; then 155 | continue 156 | fi 157 | # Unlink package first 158 | zulu unlink $package 159 | 160 | # Upgrade the package 161 | _zulu_revolver start "Upgrading $package..." 162 | out=$(_zulu_upgrade_package "$package" 2>&1) 163 | _zulu_revolver stop 164 | 165 | if [ $? -eq 0 ]; then 166 | builtin echo "$(_zulu_color green '✔') Finished upgrading $package" 167 | zulu link --no-autoselect-themes $package 168 | else 169 | builtin echo "$(_zulu_color red '✘') Error upgrading $package" 170 | builtin echo "$out" 171 | fi 172 | done 173 | ;; 174 | *) 175 | builtin echo $(_zulu_color red 'Upgrade cancelled') 176 | return 1 177 | ;; 178 | esac 179 | } 180 | -------------------------------------------------------------------------------- /src/commands/var.zsh: -------------------------------------------------------------------------------- 1 | ### 2 | # Output usage information 3 | ### 4 | function _zulu_var_usage() { 5 | builtin echo $(_zulu_color yellow "Usage:") 6 | builtin echo " zulu var [args]" 7 | builtin echo 8 | builtin echo $(_zulu_color yellow "Contexts:") 9 | builtin echo " add Add an environment variable" 10 | builtin echo " load Load all environment variables from env file" 11 | builtin echo " rm Remove an environment variable" 12 | } 13 | 14 | ### 15 | # Add an var 16 | ### 17 | _zulu_var_add() { 18 | local existing var cmd private 19 | 20 | builtin zparseopts -D \ 21 | p=private -private=private 22 | 23 | var="$1" 24 | cmd="${(@)@:2}" 25 | 26 | # Loop through each of the envfiles 27 | for file in $envfile $envfile.private; do 28 | # Search for the variable in the file 29 | existing=$(command cat $file | command grep "export $var=") 30 | 31 | # If the variable already exists in either file, 32 | # throw an error 33 | if [[ $existing != "" ]]; then 34 | builtin echo $(_zulu_color red "Environment variable '$var' already exists") 35 | return 1 36 | fi 37 | done 38 | 39 | # If the variable is private, set the correct envfile to use 40 | if [[ -n $private ]]; then 41 | envfile="$envfile.private" 42 | fi 43 | 44 | # Save the variable to the envfile 45 | builtin echo "export $var='$cmd'" >> $envfile 46 | 47 | # Strip any blank lines for neatness 48 | builtin echo "$(command cat $envfile | command grep -vE '^\s*$')" >! $envfile 49 | 50 | # Reload variables 51 | zulu var load 52 | return 53 | } 54 | 55 | ### 56 | # Remove an var 57 | ### 58 | _zulu_var_rm() { 59 | local existing var 60 | 61 | var="$1" 62 | 63 | # Loop through each of the envfiles 64 | for file in $envfile $envfile.private; do 65 | # Search for the variable in the file 66 | existing=$(command cat $file | command grep "export $var=") 67 | 68 | # If we haven't found it, skip to the next file 69 | [[ $existing = "" ]] && continue 70 | 71 | # If we get here, we've found the variable, so we rewrite the file, 72 | # stripping out the definition to remove 73 | builtin echo "$(command cat $file | command grep -v "export $var=" | command grep -vE '^\s*$')" >! $file 74 | break 75 | done 76 | 77 | # The variable wasn't found in either of the envfiles, so throw an error 78 | if [[ $existing = "" ]]; then 79 | builtin echo $(_zulu_color red "Environment variable '$var' does not exist") 80 | return 1 81 | fi 82 | 83 | unset $var 84 | zulu var load 85 | return 86 | } 87 | 88 | ### 89 | # Load vares 90 | ### 91 | _zulu_var_load() { 92 | builtin source $envfile 93 | builtin source $envfile.private 94 | } 95 | 96 | ### 97 | # Zulu command to handle path manipulation 98 | ### 99 | function _zulu_var() { 100 | local ctx base envfile private 101 | 102 | # Parse options 103 | builtin zparseopts -D h=help -help=help \ 104 | p=private -private=private 105 | 106 | # Output help and return if requested 107 | if [[ -n $help ]]; then 108 | _zulu_var_usage 109 | return 110 | fi 111 | 112 | # Set up some variables 113 | base=${ZULU_DIR:-"${ZDOTDIR:-$HOME}/.zulu"} 114 | config=${ZULU_CONFIG_DIR:-"${ZDOTDIR:-$HOME}/.config/zulu"} 115 | envfile="${config}/env" 116 | 117 | # Check if the envfiles exist, and if not create them 118 | [[ -f $envfile ]] || command touch $envfile 119 | [[ -f "$envfile.private" ]] || command touch "$envfile.private" 120 | 121 | # If no context is passed, output the contents of the envfiles 122 | if [[ "$1" = "" ]]; then 123 | command cat "$envfile" 124 | builtin echo 125 | builtin echo $(_zulu_color yellow 'Private:') 126 | command cat "$envfile.private" 127 | return 128 | fi 129 | 130 | # Get the context 131 | ctx="$1" 132 | builtin shift 133 | 134 | # Call the relevant function 135 | _zulu_var_${ctx} ${private:+'--private'} "$@" 136 | } 137 | -------------------------------------------------------------------------------- /src/helpers.zsh: -------------------------------------------------------------------------------- 1 | ### 2 | # Get the value for a key in a JSON object 3 | # 4 | # IMPORTANT: There must be no newlines within nested objects 5 | ### 6 | function jsonval { 7 | local temp json=$1 key=$2 8 | local oldIFS=$IFS 9 | IFS=$' \t\n' 10 | 11 | temp=$(builtin echo $json | command sed 's/\\\\\//\//g' | \ 12 | command sed 's/[{}]//g' | \ 13 | command sed 's/\"\:\"/\|/g' | \ 14 | command sed 's/[\,]/ /g' | \ 15 | command sed 's/\"//g' | \ 16 | command grep -w $key | \ 17 | command cut -d":" -f2-9999999 | \ 18 | command sed -e 's/^ *//g' -e 's/ *$//g' 19 | ) 20 | builtin echo ${temp##*|} 21 | 22 | IFS=$oldIFS 23 | builtin unset oldIFS 24 | } 25 | 26 | ### 27 | # If the revolver command is not installed, create a simple polyfill 28 | # function to prevent COMMAND_NOT_FOUND errors 29 | ### 30 | function _zulu_color { 31 | $(builtin type -p color 2>&1 > /dev/null) 32 | if [[ $? -ne 0 && ! -x ${ZULU_DIR:-"${ZDOTDIR:-$HOME}/bin/color"} ]]; then 33 | local color=$1 style=$2 b=0 34 | 35 | builtin shift 36 | 37 | case $style in 38 | bold|b) b=1; builtin shift ;; 39 | italic|i) b=2; builtin shift ;; 40 | underline|u) b=4; builtin shift ;; 41 | inverse|in) b=7; builtin shift ;; 42 | strikethrough|s) b=9; builtin shift ;; 43 | esac 44 | 45 | case $color in 46 | black|b) builtin echo "\033[${b};30m${@}\033[0;m" ;; 47 | red|r) builtin echo "\033[${b};31m${@}\033[0;m" ;; 48 | green|g) builtin echo "\033[${b};32m${@}\033[0;m" ;; 49 | yellow|y) builtin echo "\033[${b};33m${@}\033[0;m" ;; 50 | blue|bl) builtin echo "\033[${b};34m${@}\033[0;m" ;; 51 | magenta|m) builtin echo "\033[${b};35m${@}\033[0;m" ;; 52 | cyan|c) builtin echo "\033[${b};36m${@}\033[0;m" ;; 53 | white|w) builtin echo "\033[${b};37m${@}\033[0;m" ;; 54 | esac 55 | 56 | return 57 | fi 58 | 59 | command color "$@" 60 | } 61 | 62 | ### 63 | # If the revolver command is not installed, create an empty 64 | # function to prevent COMMAND_NOT_FOUND errors 65 | ### 66 | function _zulu_revolver { 67 | if [[ $ZULU_NO_PROGRESS -eq 1 ]]; then 68 | return 69 | fi 70 | 71 | $(builtin type -p revolver 2>&1 > /dev/null) 72 | if [[ $? -ne 0 && ! -x ${ZULU_DIR:-"${ZDOTDIR:-$HOME}/bin/revolver"} ]]; then 73 | # Check for a revolver process file, and remove it if it exists. 74 | # Revolver will handle the missing state and kill any orphaned process. 75 | if [[ -f "${ZDOTDIR:-$HOME}/.revolver/${$}" ]]; then 76 | command rm "${ZDOTDIR:-$HOME}/.revolver/${$}" 77 | fi 78 | return 79 | fi 80 | 81 | command revolver "$@" 82 | } 83 | -------------------------------------------------------------------------------- /src/zulu.zsh: -------------------------------------------------------------------------------- 1 | ### 2 | # Print usage information 3 | ### 4 | function _zulu_usage() { 5 | builtin echo $(_zulu_color yellow "Usage:") 6 | builtin echo " zulu [options] " 7 | builtin echo 8 | builtin echo $(_zulu_color yellow "Options:") 9 | builtin echo " -h, --help Output this help text and exit" 10 | builtin echo " -v, --version Output version information and exit" 11 | builtin echo 12 | builtin echo $(_zulu_color yellow "Commands:") 13 | builtin echo " alias Functions for adding/removing aliases" 14 | builtin echo " bundle Install all packages from packagefile" 15 | builtin echo " cdpath Functions for adding/removing dirs from \$cdpath" 16 | builtin echo " fpath Functions for adding/removing dirs from \$fpath" 17 | builtin echo " func Functions for adding/removing functions" 18 | builtin echo " info Show information for a package" 19 | builtin echo " install Install a package" 20 | builtin echo " link Create symlinks for a package" 21 | builtin echo " list List packages" 22 | builtin echo " manpath Functions for adding/removing dirs from \$manpath" 23 | builtin echo " path Functions for adding/removing dirs from \$path" 24 | builtin echo " theme Select a prompt theme" 25 | builtin echo " search Search the package index" 26 | builtin echo " self-update Update zulu" 27 | builtin echo " switch Switch to a different version of a package" 28 | builtin echo " sync Sync your Zulu environment to a remote repository" 29 | builtin echo " uninstall Uninstall a package" 30 | builtin echo " unlink Remove symlinks for a package" 31 | builtin echo " update Update the package index" 32 | builtin echo " upgrade Upgrade a package" 33 | builtin echo " var Functions for adding/removing environment variables" 34 | } 35 | 36 | function _zulu_version() { 37 | command cat "$base/core/.version" 38 | } 39 | 40 | ### 41 | # The main zulu command. Loads and executes all other commands 42 | ### 43 | function zulu() { 44 | local cmd base help version 45 | 46 | autoload -Uz is-at-least 47 | 48 | # Set up some source paths 49 | base=${ZULU_DIR:-"${ZDOTDIR:-$HOME}/.zulu"} 50 | config=${ZULU_CONFIG_DIR:-"${ZDOTDIR:-$HOME}/.config/zulu"} 51 | 52 | # Parse CLI options 53 | builtin zparseopts -D h=help -help=help v=version -version=version 54 | 55 | # Print help 56 | if [[ -n $help ]]; then 57 | _zulu_usage 58 | return 59 | fi 60 | 61 | if [[ -n $version ]]; then 62 | _zulu_version 63 | return 64 | fi 65 | 66 | cmd="$1" 67 | 68 | if [[ -z $cmd ]]; then 69 | builtin echo " _____ ___" 70 | builtin echo "/__ / __ __/ /_ __" 71 | builtin echo " / / / / / / / / / /" 72 | builtin echo " / /__/ /_/ / / /_/ /" 73 | builtin echo "/____/\\____/__/\\____/" 74 | builtin echo 75 | builtin echo "Version $(zulu --version)" 76 | builtin echo 77 | _zulu_usage 78 | return 79 | fi 80 | 81 | # If we're in dev mode, re-source the command now 82 | if (( $+functions[_zulu_${cmd}] )) && [[ $ZULU_DEV_MODE -eq 1 ]]; then 83 | builtin source "$base/core/src/commands/$cmd.zsh" 84 | fi 85 | 86 | # Check if the requested command exists 87 | if (( ! $+functions[_zulu_${cmd}] )); then 88 | # If it doesn't, print usage information and exit 89 | builtin echo $(_zulu_color red "Command '$cmd' can not be found.") 90 | builtin echo 91 | _zulu_usage 92 | return 1 93 | fi 94 | 95 | 96 | # If the user initiated this call, then track it 97 | if [[ $ZULU_DEV_MODE -ne 1 && "${${(s/:/)funcfiletrace[1]}[1]}" != "$base/core/zulu" ]]; then 98 | { 99 | _zulu_analytics_track "Ran command: $cmd $2" 100 | } &! 101 | fi 102 | 103 | # Execute the requested command 104 | _zulu_${cmd} "${(@)@:2}" 105 | } 106 | -------------------------------------------------------------------------------- /tests/_output/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zulu-zsh/zulu/0c22ab852df4705fe0af2197f5828dada36910a8/tests/_output/.gitkeep -------------------------------------------------------------------------------- /tests/_support/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zulu-zsh/zulu/0c22ab852df4705fe0af2197f5828dada36910a8/tests/_support/.gitkeep -------------------------------------------------------------------------------- /tests/_support/bootstrap: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env zsh 2 | 3 | # Set Zulu directories 4 | export ZULU_DIR="$PWD/tests/_support/.zulu" 5 | export ZULU_CONFIG_DIR="$PWD/tests/_support/.config/zulu" 6 | export ZULU_INSTALL_SCRIPT="$PWD/tests/_support/zulu-install.zsh" 7 | 8 | # Store the value of $IFS before we do anything 9 | oldIFS=$IFS 10 | 11 | # We're going to create a fresh install of Zulu in tests/_support so 12 | # that the environment is fully configured, and then remove the core, 13 | # replacing it with a symlink to this repository 14 | 15 | # Check if Zulu is already installed in the support directory 16 | if [[ ! -d "$ZULU_DIR" ]]; then 17 | # Check if the Zulu install script has already been downloaded 18 | if [[ ! -f "$ZULU_INSTALL_SCRIPT" ]]; then 19 | curl -L https://zulu.molovo.co/install > $ZULU_INSTALL_SCRIPT 20 | fi 21 | 22 | # Source the Zulu install script 23 | source "$PWD/tests/_support/zulu-install.zsh" 24 | fi 25 | 26 | # If the core directory is still present, remove it and 27 | # create a symlink to the current directory so that we 28 | # can test the Zulu version in this repository 29 | if [[ ! -L "$ZULU_DIR/core" ]]; then 30 | if [[ -d "$ZULU_DIR/core" ]]; then 31 | rm -rf "$ZULU_DIR/core" 32 | fi 33 | 34 | ln -s "$PWD" "$ZULU_DIR/core" 35 | fi 36 | 37 | # Check that Zulu has already been built, and if it 38 | # hasn't, do it now 39 | if [[ ! -f "$PWD/zulu" ]]; then 40 | ./build.zsh 41 | fi 42 | 43 | # Check if an upstream is configured for this branch, and if 44 | # it isn't, set it now 45 | if ! command git rev-parse --abbrev-ref @'{u}' &>/dev/null; then 46 | # If $TRAVIS_BRANCH is set, then we can use that for the upstream 47 | if [[ -n $TRAVIS_BRANCH ]]; then 48 | git branch -u origin/$TRAVIS_BRANCH 49 | fi 50 | fi 51 | 52 | # Disable analytics whilst testing 53 | echo "analytics: false" >! "$ZULU_CONFIG_DIR/config.yml" 54 | 55 | # Ensure the progress indicator is hidden, so that we can 56 | # perform assertions against the output from commands 57 | export ZULU_NO_PROGRESS=1 58 | 59 | # Ensure IFS is reset 60 | export IFS=$oldIFS 61 | unset oldIFS 62 | 63 | # Source the embedded Zulu installation 64 | source "$PWD/tests/_support/.zulu/core/zulu" 65 | zulu init --dev 66 | -------------------------------------------------------------------------------- /tests/commands/alias.zunit: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env zunit 2 | 3 | @test 'Test "zulu alias add" creates an alias' { 4 | run zulu alias add an_alias 'echo "It worked"' 5 | 6 | assert $state equals 0 7 | assert "$output" same_as "\033[0;32m✔\033[0;m Alias 'an_alias' added" 8 | 9 | run grep -E -e '^alias an_alias=' tests/_support/.config/zulu/alias 10 | 11 | assert $state equals 0 12 | assert "$output" same_as "alias an_alias='echo \"It worked\"'" 13 | } 14 | 15 | @test 'Test "zulu alias rm" removes an alias' { 16 | zulu alias load 17 | 18 | run zulu alias rm an_alias 19 | 20 | assert $state equals 0 21 | assert "$output" same_as "\033[0;32m✔\033[0;m Alias 'an_alias' removed" 22 | 23 | local -a output 24 | run grep -E -e '^alias an_alias=' tests/_support/.config/zulu/alias 25 | 26 | assert $state equals 1 27 | assert "$output" is_empty 28 | } 29 | 30 | @test 'Test "zulu alias add -g" creates a global alias' { 31 | run zulu alias add -g a_global_alias ' | cat -vte' 32 | 33 | assert $state equals 0 34 | assert "$output" same_as "\033[0;32m✔\033[0;m Alias 'a_global_alias' added" 35 | 36 | run grep -E -e '^alias -g a_global_alias=' tests/_support/.config/zulu/alias 37 | 38 | assert $state equals 0 39 | assert "$output" same_as "alias -g a_global_alias=' | cat -vte'" 40 | } 41 | 42 | @test 'Test "zulu alias rm" removes a global alias' { 43 | zulu alias load 44 | 45 | run zulu alias rm 'a_global_alias' 46 | 47 | assert $state equals 0 48 | assert "$output" same_as "\033[0;32m✔\033[0;m Alias 'a_global_alias' removed" 49 | 50 | local -a output 51 | run grep -E -e '^alias -g a_global_alias=' tests/_support/.config/zulu/alias 52 | 53 | assert $state equals 1 54 | assert "$output" is_empty 55 | } 56 | 57 | @test 'Test "zulu alias add" does not allow overlapping standard and global aliases' { 58 | run zulu alias add a_new_alias 'echo "It worked"' 59 | 60 | assert $state equals 0 61 | assert "$output" same_as "\033[0;32m✔\033[0;m Alias 'a_new_alias' added" 62 | 63 | zulu alias load 64 | 65 | run zulu alias add -g a_new_alias ' | cat -vte' 66 | 67 | assert $state equals 1 68 | assert "$output" same_as "\033[0;31mAlias 'a_new_alias' already exists\033[0;m" 69 | } -------------------------------------------------------------------------------- /tests/commands/bundle.zunit: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env zunit 2 | 3 | @setup { 4 | if _zulu_info_is_installed dummy; then 5 | zulu uninstall dummy 6 | fi 7 | } 8 | 9 | @teardown { 10 | if _zulu_info_is_installed dummy; then 11 | zulu uninstall dummy 12 | fi 13 | } 14 | 15 | @test 'Test "zulu bundle" installs package' { 16 | # Add an extra package to the packagefile 17 | echo 'dummy' >> "$PWD/tests/_support/.config/zulu/packages" 18 | 19 | run zulu bundle 20 | 21 | assert $state equals 0 22 | assert "${lines[${#lines}]}" same_as "\033[0;32m✔\033[0;m Finished linking dummy" 23 | assert "$PWD/tests/_support/.zulu/packages/dummy" is_dir 24 | } 25 | -------------------------------------------------------------------------------- /tests/commands/cdpath.zunit: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env zunit 2 | 3 | @test 'Test "zulu cdpath" returns correct contents' { 4 | run zulu cdpath 5 | 6 | assert $state equals 0 7 | assert "${output//\n/ }" same_as "$cdpath" 8 | } 9 | 10 | @test 'Tests "zulu cdpath reset" reloads from cdpathfile' { 11 | assert "$PWD" not_in "${cdpath[@]}" 12 | 13 | cdpath+=$PWD 14 | 15 | assert "$PWD" in "${cdpath[@]}" 16 | 17 | zulu cdpath reset 18 | 19 | assert "$PWD" not_in "${cdpath[@]}" 20 | } 21 | 22 | @test 'Test "zulu cdpath add" allows directories to be entered' { 23 | mkdir -p tests/_support/a_test_directory 24 | 25 | run builtin cd a_test_directory 26 | 27 | assert $state equals 1 28 | assert "$output" matches 'run:cd:[0-9]+: no such file or directory: a_test_directory' 29 | 30 | zulu cdpath add tests/_support 31 | 32 | run builtin cd a_test_directory 33 | 34 | assert $state equals 0 35 | 36 | zulu cdpath rm tests/_support 37 | rm -r tests/_support/a_test_directory 38 | } 39 | -------------------------------------------------------------------------------- /tests/commands/config.zunit: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env zunit 2 | 3 | @teardown { 4 | echo "analytics: false" >! tests/_support/.config/zulu/config.yml 5 | } 6 | 7 | @test 'Test "zulu config list" returns contents of config.yml' { 8 | echo "testing: true" >> tests/_support/.config/zulu/config.yml 9 | 10 | run zulu config list 11 | 12 | assert $state equals 0 13 | assert "$lines[${#lines}]" same_as "testing: true" 14 | } 15 | 16 | @test 'Test "zulu config" returns correct value' { 17 | echo "testing: true" >> tests/_support/.config/zulu/config.yml 18 | 19 | run zulu config testing 20 | 21 | assert $state equals 0 22 | assert "$lines[${#lines}]" same_as "true" 23 | } 24 | 25 | @test 'Test "zulu config set" sets value' { 26 | run zulu config set rainbows unicorns 27 | 28 | assert $state equals 0 29 | assert "$output" same_as "unicorns" 30 | 31 | run zulu config list 32 | 33 | assert $state equals 0 34 | assert "$lines[${#lines}]" same_as "rainbows: unicorns" 35 | 36 | run zulu config rainbows 37 | 38 | assert $state equals 0 39 | assert "$output" same_as "unicorns" 40 | } 41 | 42 | @test 'Test "zulu config set" overwrites existing value' { 43 | run zulu config set rainbows unicorns 44 | 45 | assert $state equals 0 46 | assert "$output" same_as "unicorns" 47 | 48 | run zulu config list 49 | 50 | assert $state equals 0 51 | assert "$lines[${#lines}]" same_as "rainbows: unicorns" 52 | 53 | run zulu config set rainbows pixies 54 | 55 | assert $state equals 0 56 | assert "$output" same_as "pixies" 57 | 58 | run zulu config list 59 | 60 | assert $state equals 0 61 | assert "$lines[${#lines}]" same_as "rainbows: pixies" 62 | 63 | run zulu config rainbows 64 | 65 | assert $state equals 0 66 | assert "$output" same_as "pixies" 67 | } 68 | -------------------------------------------------------------------------------- /tests/commands/fpath.zunit: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env zunit 2 | 3 | @test 'Test "zulu fpath" returns correct contents' { 4 | run zulu fpath 5 | 6 | assert $state equals 0 7 | assert "${output//\n/ }" same_as "$fpath" 8 | } 9 | 10 | @test 'Tests "zulu fpath reset" reloads from fpathfile' { 11 | assert "$PWD" not_in "$fpath[@]" 12 | 13 | fpath+=$PWD 14 | 15 | assert "$PWD" in "$fpath[@]" 16 | 17 | zulu fpath reset 18 | 19 | assert "$PWD" not_in "$fpath[@]" 20 | } 21 | 22 | @test 'Test "zulu fpath add" allows scripts to be autoloaded' { 23 | echo "#!/usr/bin/env zsh 24 | 25 | function _a_test_function() { 26 | echo 'It worked' 27 | } 28 | 29 | _a_test_function" > tests/_support/a_test_function 30 | chmod u+x tests/_support/a_test_function 31 | 32 | autoload -Uz a_test_function 33 | run a_test_function 34 | 35 | assert $state equals 1 36 | assert "$output" matches 'run:[0-9]+: a_test_function: function definition file not found' 37 | 38 | zulu fpath add tests/_support 39 | 40 | run a_test_function 41 | 42 | assert $state equals 0 43 | assert "$output" same_as 'It worked' 44 | 45 | zulu fpath rm tests/_support 46 | rm tests/_support/a_test_function 47 | } 48 | -------------------------------------------------------------------------------- /tests/commands/func.zunit: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env zunit 2 | 3 | @test 'Test "zulu func add" creates empty definition' { 4 | # zulu func opens the created definition in $EDITOR. 5 | # By changing $EDITOR to 'cat', we can capture the output 6 | # immediately, rather than having an actual editor lock 7 | # up the shell waiting for user input 8 | EDITOR='cat -e' 9 | run zulu func add unicorn_generator 10 | 11 | func="#!/usr/bin/env zsh\$ 12 | $ 13 | (( \$+functions[unicorn_generator] )) || function unicorn_generator() {\$ 14 | $ 15 | }\$" 16 | 17 | assert $state equals 0 18 | assert "${output//\n/ }" same_as "${func//\n/ }" 19 | } 20 | 21 | @test 'Test "zulu func edit" opens function definition' { 22 | # zulu func opens the created definition in $EDITOR. 23 | # By changing $EDITOR to 'cat', we can capture the output 24 | # immediately, rather than having an actual editor lock 25 | # up the shell waiting for user input 26 | EDITOR='cat -e' 27 | run zulu func edit unicorn_generator 28 | 29 | func="#!/usr/bin/env zsh\$ 30 | $ 31 | (( \$+functions[unicorn_generator] )) || function unicorn_generator() {\$ 32 | $ 33 | }\$" 34 | 35 | assert $state equals 0 36 | assert "${output//\n/ }" same_as "${func//\n/ }" 37 | } 38 | 39 | @test 'Test "zulu func rm" removes function definition' { 40 | # Ensure the function is loaded into the environment first 41 | zulu func load 42 | 43 | run zulu func rm unicorn_generator 44 | 45 | assert $state equals 0 46 | assert "$output" is_empty 47 | 48 | run assert 'tests/_support/.config/zulu/functions/unicorn_generator' is_file 49 | 50 | assert $state equals 1 51 | } 52 | -------------------------------------------------------------------------------- /tests/commands/install.zunit: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env zunit 2 | 3 | @setup { 4 | if _zulu_info_is_installed dummy; then 5 | zulu uninstall dummy 6 | fi 7 | } 8 | 9 | @teardown { 10 | if _zulu_info_is_installed dummy; then 11 | zulu uninstall dummy 12 | fi 13 | } 14 | 15 | @test 'Test "zulu install" installs package' { 16 | # Install the dummy package 17 | run zulu install --no-autoselect-themes --ignore-dependencies dummy 18 | 19 | # Assert that the package installed successfully 20 | assert $state equals 0 21 | assert "${lines[${#lines}]}" same_as "\033[0;32m✔\033[0;m Finished linking dummy" 22 | assert "$PWD/tests/_support/.zulu/packages/dummy" is_dir 23 | } 24 | 25 | @test 'Test "zulu install" fails for installed package' { 26 | # Install the dummy package 27 | run zulu install --no-autoselect-themes --ignore-dependencies dummy 28 | 29 | # Assert that the package installed successfully 30 | assert $state equals 0 31 | assert "${lines[${#lines}]}" same_as "\033[0;32m✔\033[0;m Finished linking dummy" 32 | assert "$PWD/tests/_support/.zulu/packages/dummy" is_dir 33 | 34 | # Install the package again and record the output 35 | run zulu install --no-autoselect-themes --ignore-dependencies dummy 36 | 37 | # Assert that the package failed to install 38 | assert $state equals 1 39 | assert "${lines[${#lines}]}" same_as "\033[0;31m✘\033[0;m Error installing dummy" 40 | } 41 | 42 | @test 'Test "zulu install" fails for non-existent package' { 43 | run zulu install --no-autoselect-themes --ignore-dependencies not-a-package 44 | 45 | assert $state equals 1 46 | assert "${lines[${#lines}]}" same_as "\033[0;31mPackage 'not-a-package' is not in the index\033[0;m" 47 | } 48 | 49 | @test 'Test "zulu install" fails with no argument' { 50 | run zulu install --no-autoselect-themes --ignore-dependencies 51 | 52 | assert $state equals 1 53 | assert "${lines[1]}" same_as "\033[0;31mPlease specify a package name\033[0;m" 54 | } 55 | 56 | @test 'Test "zulu install --branch" checks out correct branch' { 57 | # Install the 'testing' branch of the dummy package 58 | run zulu install --no-autoselect-themes --ignore-dependencies --branch testing dummy 59 | 60 | # Assert that the package installed successfully 61 | assert $state equals 0 62 | assert "${lines[${#lines}]}" same_as "\033[0;32m✔\033[0;m Finished linking dummy" 63 | 64 | # Change to the package directory and check the checked out branch 65 | local oldPWD=$PWD 66 | cd "${ZULU_DIR:-"${ZDOTDIR:-$HOME}/.zulu"}/packages/dummy" 67 | 68 | local branch=$(git status --short --branch -uno --ignore-submodules=all | head -1 | awk '{print $2}' 2>/dev/null) 69 | 70 | assert "${branch%...*}" same_as 'testing' 71 | 72 | cd $oldPWD 73 | unset oldPWD 74 | } 75 | -------------------------------------------------------------------------------- /tests/commands/list.zunit: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env zunit 2 | 3 | @test 'Test "zulu list" lists installed packages' { 4 | run zulu list 5 | 6 | local -a packages; packages=($(ls tests/_support/.zulu/packages)) 7 | 8 | assert $state equals 0 9 | assert "${output//\n/ }" same_as "$packages" 10 | } 11 | 12 | @test 'Test "zulu list --all --simple" lists all packages' { 13 | run zulu list --all --simple 14 | 15 | local -a packages; packages=($(ls tests/_support/.zulu/index/packages)) 16 | 17 | assert $state equals 0 18 | assert "${output//\n/ }" same_as "$packages" 19 | } 20 | -------------------------------------------------------------------------------- /tests/commands/manpath.zunit: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env zunit 2 | 3 | @test 'Test "zulu manpath" returns correct contents' { 4 | run zulu manpath 5 | 6 | assert $state equals 0 7 | assert "${output//\n/ }" same_as "$manpath" 8 | } 9 | 10 | @test 'Tests "zulu manpath reset" reloads from manpathfile' { 11 | assert "$PWD" not_in "${manpath[@]}" 12 | 13 | manpath+=$PWD 14 | 15 | assert "$PWD" in "${manpath[@]}" 16 | 17 | zulu manpath reset 18 | 19 | assert "$PWD" not_in "${manpath[@]}" 20 | } 21 | 22 | @test 'Test "zulu manpath add" allows directories to be entered' { 23 | if [[ $OSTYPE =~ 'darwin.*' ]]; then 24 | skip 'Manpath is set at shell startup in OSX, so we cannot affect it here' 25 | fi 26 | 27 | mkdir -p tests/_support/man1 28 | echo '.TH Testing' > tests/_support/man1/a_test_command.1 29 | 30 | run man a_test_command 31 | 32 | # BSD man and GNU man give different exit codes 33 | case $OSTYPE in 34 | darwin* ) 35 | assert $state equals 1 36 | ;; 37 | * ) 38 | assert $state equals 16 39 | ;; 40 | esac 41 | assert "$output" same_as 'No manual entry for a_test_command' 42 | 43 | zulu manpath add tests/_support 44 | 45 | run man a_test_command 46 | 47 | assert $state equals 0 48 | assert "$output" matches '^Testing\(\).*' 49 | 50 | zulu manpath rm tests/_support 51 | rm -r tests/_support/man1 52 | } 53 | -------------------------------------------------------------------------------- /tests/commands/path.zunit: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env zunit 2 | 3 | @test 'Test "zulu path" returns correct contents' { 4 | run zulu path 5 | 6 | assert $state equals 0 7 | assert "${output//\n/ }" same_as "$path" 8 | } 9 | 10 | @test 'Tests "zulu path reset" reloads from pathfile' { 11 | assert "$PWD" not_in "${path[@]}" 12 | 13 | path+=$PWD 14 | 15 | assert "$PWD" in "${path[@]}" 16 | 17 | zulu path reset 18 | 19 | assert "$PWD" not_in "${path[@]}" 20 | } 21 | 22 | @test 'Test "zulu path add" allows scripts to be executed' { 23 | echo "#!/usr/bin/env zsh 24 | 25 | echo 'It worked'" > tests/_support/a_test_script 26 | chmod u+x tests/_support/a_test_script 27 | 28 | run a_test_script 29 | 30 | assert $state equals 127 31 | assert "$output" matches 'run:[0-9]+: command not found: a_test_script' 32 | 33 | zulu path add tests/_support 34 | 35 | run a_test_script 36 | 37 | assert $state equals 0 38 | assert "$output" same_as 'It worked' 39 | 40 | zulu path rm tests/_support 41 | rm tests/_support/a_test_script 42 | } 43 | -------------------------------------------------------------------------------- /tests/commands/self-update.zunit: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env zunit 2 | 3 | @test 'Test "zulu self-update --check" finds updates' { 4 | oldPWD=$PWD 5 | cd tests/_support/.zulu/core 6 | 7 | if ! command git rev-parse --abbrev-ref @'{u}' &>/dev/null; then 8 | cd $oldPWD 9 | unset oldPWD 10 | skip 'Cannot test self-update without an upstream' 11 | fi 12 | 13 | # Stash any uncommitted changes and rewind one commit to ensure 14 | # updates are available 15 | git stash 2>&1 16 | git reset --hard HEAD~1 2>&1 17 | 18 | cd $oldPWD 19 | unset oldPWD 20 | 21 | # Check for updates 22 | run zulu self-update --check 23 | 24 | # Assert that updates were found 25 | assert $state equals 0 26 | assert "$output" same_as '\033[0;32mNew Zulu version available\033[0;m Run zulu self-update to upgrade' 27 | } 28 | 29 | @test 'Test "zulu self-update" updates repository' { 30 | oldPWD=$PWD 31 | cd tests/_support/.zulu/core 32 | 33 | if ! command git rev-parse --abbrev-ref @'{u}' &>/dev/null; then 34 | cd $oldPWD 35 | unset oldPWD 36 | skip 'Cannot test self-update without an upstream' 37 | fi 38 | 39 | cd $oldPWD 40 | unset oldPWD 41 | 42 | run zulu self-update 43 | 44 | assert $state equals 0 45 | assert "${output%"${output##*[![:space:]]}"}" same_as '\033[0;32m✔\033[0;m Zulu core updated' 46 | } 47 | 48 | @test 'Test "zulu self-update" preserves local changes' { 49 | oldPWD=$PWD 50 | cd tests/_support/.zulu/core 51 | 52 | if ! command git rev-parse --abbrev-ref @'{u}' &>/dev/null; then 53 | cd $oldPWD 54 | unset oldPWD 55 | skip 'Cannot test self-update without an upstream' 56 | fi 57 | 58 | # Stash any uncommitted changes and rewind one commit to ensure 59 | # updates are available 60 | git stash 2>&1 61 | git reset --hard HEAD~1 2>&1 62 | 63 | # Add a test line to the end of a source file 64 | echo 'thisisatest' >> README.md 65 | 66 | # Run the update 67 | run zulu self-update 68 | 69 | # Assert the update was successful 70 | assert $state equals 0 71 | assert "${output%"${output##*[![:space:]]}"}" same_as '\033[0;32m✔\033[0;m Zulu core updated' 72 | 73 | # Assert the additional line still exists in the file 74 | assert "$(tail -1 README.md)" same_as 'thisisatest' 75 | 76 | # Remove the additional line from the file 77 | cp README.md README.md.tmp 78 | sed '$ d' README.md.tmp >! README.md 79 | rm README.md.tmp 80 | 81 | cd $oldPWD 82 | unset oldPWD 83 | } 84 | -------------------------------------------------------------------------------- /tests/commands/switch.zunit: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env zunit 2 | 3 | @setup { 4 | if ! _zulu_info_is_installed dummy; then 5 | zulu install dummy 6 | fi 7 | } 8 | 9 | @teardown { 10 | if _zulu_info_is_installed dummy; then 11 | zulu uninstall dummy 12 | fi 13 | } 14 | 15 | @test 'Test "zulu switch --tag" checks out correct tag' { 16 | run zulu switch --tag v1.0.0 dummy 17 | 18 | assert $state equals 0 19 | assert "${lines[${#lines}]}" same_as "\033[0;32m✔\033[0;m Successfully switched dummy to v1.0.0" 20 | } 21 | 22 | @test 'Test "zulu switch --branch" checks out correct branch' { 23 | run zulu switch --branch testing dummy 24 | 25 | assert $state equals 0 26 | assert "${lines[${#lines}]}" same_as "\033[0;32m✔\033[0;m Successfully switched dummy to testing" 27 | } 28 | -------------------------------------------------------------------------------- /tests/commands/theme.zunit: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env zunit 2 | 3 | @teardown { 4 | # Always revert back to default theme after changing it 5 | zulu theme zulu-theme 6 | } 7 | 8 | @test 'Test "zulu theme" outputs current theme' { 9 | run zulu theme adam1 10 | 11 | assert $state equals 0 12 | assert "$output" same_as "\033[0;32m✔\033[0;m Theme set to adam1" 13 | 14 | run zulu theme 15 | 16 | assert $state equals 0 17 | assert "$output" same_as "adam1" 18 | } 19 | 20 | @test 'Test "zulu theme" sets theme' { 21 | run zulu theme adam1 22 | 23 | assert $state equals 0 24 | assert "$output" same_as "\033[0;32m✔\033[0;m Theme set to adam1" 25 | } 26 | 27 | @test 'Test "zulu theme" returns error for missing theme' { 28 | run zulu theme notatheme 29 | 30 | assert $state equals 1 31 | assert "${lines[1]}" same_as "\033[0;31mFailed to load theme 'notatheme'\033[0;m" 32 | assert "${lines[2]}" same_as "Please ensure your theme is in \$fpath and is called prompt_notatheme_setup" 33 | } 34 | -------------------------------------------------------------------------------- /tests/commands/uninstall.zunit: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env zunit 2 | 3 | @setup { 4 | if ! _zulu_info_is_installed dummy; then 5 | zulu install --no-autoselect-themes --ignore-dependencies dummy 6 | fi 7 | } 8 | 9 | @teardown { 10 | if _zulu_info_is_installed dummy; then 11 | zulu uninstall dummy 12 | fi 13 | } 14 | 15 | @test 'Test "zulu uninstall" uninstalls package' { 16 | run zulu uninstall dummy 17 | 18 | assert $state equals 0 19 | assert "${lines[${#lines}]}" same_as "\033[0;32m✔\033[0;m Finished uninstalling dummy" 20 | } 21 | 22 | @test 'Test "zulu uninstall" fails for not-installed package' { 23 | # Uninstall the package once 24 | run zulu uninstall dummy 25 | 26 | assert $state equals 0 27 | assert "${lines[${#lines}]}" same_as "\033[0;32m✔\033[0;m Finished uninstalling dummy" 28 | 29 | # Run the uninstall again, this time it should fail 30 | run zulu uninstall dummy 31 | 32 | assert $state equals 1 33 | assert "${lines[${#lines}]}" same_as "\033[0;31mPackage 'dummy' is not installed\033[0;m" 34 | } 35 | 36 | @test 'Test "zulu uninstall" fails for non-existent package' { 37 | run zulu uninstall not-a-package 38 | 39 | assert $state equals 1 40 | assert "${lines[${#lines}]}" same_as "\033[0;31mPackage 'not-a-package' is not in the index\033[0;m" 41 | } 42 | 43 | @test 'Test "zulu uninstall" fails with no argument' { 44 | run zulu uninstall 45 | 46 | assert $state equals 1 47 | assert "${lines[1]}" same_as "\033[0;31mPlease specify a package name\033[0;m" 48 | } 49 | -------------------------------------------------------------------------------- /tests/commands/update.zunit: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env zunit 2 | 3 | @test 'Test "zulu update --check" finds updates' { 4 | oldPWD=$PWD 5 | cd tests/_support/.zulu/index 6 | 7 | if ! command git rev-parse --abbrev-ref @'{u}' &>/dev/null; then 8 | cd $oldPWD 9 | unset oldPWD 10 | skip 'Cannot test update without an upstream' 11 | fi 12 | 13 | # Stash any uncommitted changes and rewind one commit to ensure 14 | # updates are available 15 | git stash >/dev/null 2>&1 16 | git reset --hard HEAD~1 >/dev/null 2>&1 17 | 18 | cd $oldPWD 19 | unset oldPWD 20 | 21 | # Check for updates 22 | run zulu update --check 23 | 24 | # Assert that updates were found 25 | assert $state equals 0 26 | assert "$output" same_as '\033[0;32mZulu index updates available\033[0;m Run zulu update to update the index' 27 | } 28 | 29 | @test 'Test "zulu update" updates repository' { 30 | oldPWD=$PWD 31 | cd tests/_support/.zulu/index 32 | 33 | if ! command git rev-parse --abbrev-ref @'{u}' &>/dev/null; then 34 | cd $oldPWD 35 | unset oldPWD 36 | skip 'Cannot test update without an upstream' 37 | fi 38 | 39 | cd $oldPWD 40 | unset oldPWD 41 | 42 | run zulu update 43 | 44 | assert $state equals 0 45 | assert "${lines[${#lines}]}" same_as '\033[0;32m✔\033[0;m Package index updated' 46 | } 47 | 48 | @test 'Test "zulu update" preserves local changes' { 49 | oldPWD=$PWD 50 | cd tests/_support/.zulu/index 51 | 52 | if ! command git rev-parse --abbrev-ref @'{u}' &>/dev/null; then 53 | cd $oldPWD 54 | unset oldPWD 55 | skip 'Cannot test update without an upstream' 56 | fi 57 | 58 | # Stash any uncommitted changes and rewind one commit to ensure 59 | # updates are available 60 | git stash >/dev/null 2>&1 61 | git reset --hard HEAD~1 >/dev/null 2>&1 62 | 63 | # Add a test line to the end of a source file 64 | echo 'thisisatest' >> readme.md 65 | 66 | # Run the update 67 | run zulu update 68 | 69 | # Assert the update was successful 70 | assert $state equals 0 71 | assert "${lines[${#lines}]}" same_as '\033[0;32m✔\033[0;m Package index updated' 72 | 73 | # Assert the additional line still exists in the file 74 | assert "$(tail -1 readme.md)" same_as 'thisisatest' 75 | 76 | # Remove the additional line from the file 77 | cp readme.md readme.md.tmp 78 | sed '$ d' readme.md.tmp >! readme.md 79 | rm readme.md.tmp 80 | 81 | cd $oldPWD 82 | unset oldPWD 83 | } 84 | -------------------------------------------------------------------------------- /tests/commands/upgrade.zunit: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env zunit 2 | 3 | @setup { 4 | if ! _zulu_info_is_installed dummy; then 5 | zulu install dummy 6 | fi 7 | } 8 | 9 | @teardown { 10 | if _zulu_info_is_installed dummy; then 11 | zulu uninstall dummy 12 | fi 13 | } 14 | 15 | @test 'Test "zulu upgrade --check" finds package updates' { 16 | oldPWD=$PWD 17 | cd tests/_support/.zulu/packages/dummy 18 | 19 | if ! command git rev-parse --abbrev-ref @'{u}' &>/dev/null; then 20 | cd $oldPWD 21 | unset oldPWD 22 | skip 'Cannot test upgrade without an upstream' 23 | fi 24 | 25 | # Stash any uncommitted changes and 26 | git stash 2>&1 27 | 28 | # Rewind one commit to ensure updates are available 29 | git reset --hard HEAD~1 2>&1 30 | 31 | cd $oldPWD 32 | unset oldPWD 33 | 34 | # Check for updates 35 | run zulu upgrade --check 36 | 37 | # Assert that updates were found 38 | assert $state equals 0 39 | assert "$output" same_as '\033[0;32mPackage upgrades available\033[0;m Run zulu upgrade to upgrade' 40 | } 41 | 42 | @test 'Test "zulu upgrade" updates package repository' { 43 | oldPWD=$PWD 44 | cd tests/_support/.zulu/packages/dummy 45 | 46 | if ! command git rev-parse --abbrev-ref @'{u}' &>/dev/null; then 47 | cd $oldPWD 48 | unset oldPWD 49 | skip 'Cannot test upgrade without an upstream' 50 | fi 51 | 52 | # Stash any uncommitted changes and 53 | git stash 2>&1 54 | 55 | # Rewind one commit to ensure updates are available 56 | git reset --hard HEAD~1 2>&1 57 | 58 | cd $oldPWD 59 | unset oldPWD 60 | 61 | run zulu upgrade -y 62 | 63 | assert $state equals 0 64 | assert "${lines[${#lines}]}" same_as "\033[0;32m✔\033[0;m Finished linking dummy" 65 | } 66 | 67 | @test 'Test "zulu upgrade" preserves local changes in package repository' { 68 | oldPWD=$PWD 69 | cd tests/_support/.zulu/packages/dummy 70 | 71 | if ! command git rev-parse --abbrev-ref @'{u}' &>/dev/null; then 72 | cd $oldPWD 73 | unset oldPWD 74 | skip 'Cannot test self-update without an upstream' 75 | fi 76 | 77 | # Stash any uncommitted changes and rewind one commit to ensure 78 | # updates are available 79 | git stash 2>&1 80 | git reset --hard HEAD~1 2>&1 81 | 82 | # Add a test line to the end of a source file 83 | echo 'thisisatest' >> README.md 84 | 85 | # Run the update 86 | run zulu upgrade -y 87 | 88 | # Assert the update was successful 89 | assert $state equals 0 90 | assert "${lines[${#lines}]}" same_as "\033[0;32m✔\033[0;m Finished linking dummy" 91 | 92 | # Assert the additional line still exists in the file 93 | assert "$(tail -1 README.md)" same_as 'thisisatest' 94 | 95 | # Remove the additional line from the file 96 | cp README.md README.md.tmp 97 | sed '$ d' README.md.tmp >! README.md 98 | rm README.md.tmp 99 | 100 | cd $oldPWD 101 | unset oldPWD 102 | } 103 | -------------------------------------------------------------------------------- /tests/commands/var.zunit: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env zunit 2 | 3 | @test 'Test "zulu var add" creates a variable' { 4 | run zulu var add A_TEST_VAR 1 5 | 6 | assert $state equals 0 7 | assert "$output" is_empty 8 | 9 | run grep -E '^export A_TEST_VAR=' tests/_support/.config/zulu/env 10 | 11 | assert $state equals 0 12 | assert "$output" same_as "export A_TEST_VAR='1'" 13 | 14 | run grep -E '^export A_TEST_VAR=' tests/_support/.config/zulu/env.private 15 | 16 | assert $state equals 1 17 | assert "$output" is_empty 18 | } 19 | 20 | @test 'Test "zulu var rm" removes an variable' { 21 | run zulu var rm A_TEST_VAR 22 | 23 | assert $state equals 0 24 | assert "$output" is_empty 25 | 26 | local -a output 27 | run grep -E '^export A_TEST_VAR=' tests/_support/.config/zulu/env 28 | 29 | assert $state equals 1 30 | assert "$output" is_empty 31 | } 32 | 33 | @test 'Test "zulu var add --private" creates a variable' { 34 | run zulu var add --private A_TEST_VAR 1 35 | 36 | assert $state equals 0 37 | assert "$output" is_empty 38 | 39 | run grep -E '^export A_TEST_VAR=' tests/_support/.config/zulu/env 40 | 41 | assert $state equals 1 42 | assert "$output" is_empty 43 | 44 | run grep -E '^export A_TEST_VAR=' tests/_support/.config/zulu/env.private 45 | 46 | assert $state equals 0 47 | assert "$output" same_as "export A_TEST_VAR='1'" 48 | } 49 | 50 | @test 'Test "zulu var rm" removes a private variable' { 51 | run zulu var rm A_TEST_VAR 52 | 53 | assert $state equals 0 54 | assert "$output" is_empty 55 | 56 | local -a output 57 | run grep -E '^export A_TEST_VAR=' tests/_support/.config/zulu/env.private 58 | 59 | assert $state equals 1 60 | assert "$output" is_empty 61 | } 62 | -------------------------------------------------------------------------------- /zulu.zsh-completion: -------------------------------------------------------------------------------- 1 | #compdef zulu 2 | 3 | ### 4 | # List of Commands 5 | ### 6 | _zulu_commands=( 7 | 'install:Install a package' 8 | 'uninstall:Uninstall a package' 9 | 'bundle:Manage packagefile' 10 | 'upgrade:Upgrade a package' 11 | 'update:Update the package index' 12 | 'self-update:Update the zulu core framework' 13 | 'link:Create symbolic links to enable a package' 14 | 'unlink:Remove symbolic links to disable a package' 15 | 'list:List packages' 16 | 'info:Show information for a package' 17 | 'search:Search the package index' 18 | 'theme:Change the theme' 19 | 'init:Reload zulu configuration' 20 | 'alias:Functions for adding/removing aliases' 21 | 'func:Functions for adding/removing functions' 22 | 'var:Functions for adding/removing environment variables' 23 | 'path:Functions for adding/removing directories from \$path' 24 | 'manpath:Functions for adding/removing directories from \$manpath' 25 | 'cdpath:Functions for adding/removing directories from \$cdpath' 26 | 'fpath:Functions for adding/removing directories from \$fpath' 27 | 'config:Functions for getting/setting configuration values' 28 | 'sync:Sync zulu environment to a remote repository' 29 | 'switch:Checkout a different version of a package' 30 | ) 31 | 32 | ### 33 | # Commands in the path context 34 | ### 35 | _zulu_path_commands=( 36 | 'add:Add a directory to $path' 37 | 'rm:Remove a directory from $path' 38 | 'reset:Restore $path from pathfile' 39 | ) 40 | 41 | ### 42 | # Commands in the fpath context 43 | ### 44 | _zulu_fpath_commands=( 45 | 'add:Add a directory to $fpath' 46 | 'rm:Remove a directory from $fpath' 47 | 'reset:Restore $fpath from pathfile' 48 | ) 49 | 50 | ### 51 | # Commands in the cdpath context 52 | ### 53 | _zulu_cdpath_commands=( 54 | 'add:Add a directory to $cdpath' 55 | 'rm:Remove a directory from $cdpath' 56 | 'reset:Restore $cdpath from pathfile' 57 | ) 58 | 59 | ### 60 | # Commands in the manpath context 61 | ### 62 | _zulu_manpath_commands=( 63 | 'add:Add a directory to $manpath' 64 | 'rm:Remove a directory from $manpath' 65 | 'reset:Restore $cdpath from pathfile' 66 | ) 67 | 68 | ### 69 | # Commands in the alias context 70 | ### 71 | _zulu_alias_commands=( 72 | 'add:Add a new alias' 73 | 'rm:Remove an existing alias' 74 | 'load:Reload all aliases' 75 | ) 76 | 77 | ### 78 | # Commands in the func context 79 | ### 80 | _zulu_func_commands=( 81 | 'add:Add a new function' 82 | 'edit:Edit an existing function' 83 | 'rm:Remove an existing function' 84 | 'load:Reload all functions' 85 | ) 86 | 87 | ### 88 | # Commands in the var context 89 | ### 90 | _zulu_var_commands=( 91 | 'add:Add a new environment variable' 92 | 'rm:Remove an existing environment variable' 93 | 'load:Reload all environment variables' 94 | ) 95 | 96 | ### 97 | # Commands in the config context 98 | ### 99 | _zulu_config_commands=( 100 | 'list:List all config values' 101 | 'get:Get a config value' 102 | 'set:Set a config value' 103 | ) 104 | 105 | ### 106 | # Commands in the config context 107 | ### 108 | _zulu_sync_commands=( 109 | 'push:Upload local changes' 110 | 'pull:Download remote changes' 111 | ) 112 | 113 | ### 114 | # Locating the package file 115 | ### 116 | local base config 117 | 118 | base=${ZULU_DIR:-"${ZDOTDIR:-$HOME}/.zulu"} 119 | config=${ZULU_CONFIG_DIR:-"${ZDOTDIR:-$HOME}/.config/zulu"} 120 | 121 | _zulu_package_file="$config/packages" 122 | _zulu_index="$base/index" 123 | 124 | ### 125 | # Define a default caching policy for zulu: we rebuild the cache 126 | # if the cache file is older than zulu's package index. 127 | ### 128 | local cache_policy 129 | zstyle -s ":completion::complete:zulu:*" cache-policy cache_policy 130 | if [[ -z "$cache_policy" ]]; then 131 | zstyle ":completion::complete:zulu:*" cache-policy _zulu_caching_policy 132 | fi 133 | 134 | _zulu_caching_policy() { 135 | [[ "$_zulu_package_file" -nt "$1" || "$_zulu_index" -nt "$1" ]] && return 0 136 | return 1 137 | } 138 | 139 | # ~~~ CACHING ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 140 | # Using the cache mechanism of zsh to store packages 141 | (( $+functions[_zulu_get_packages] )) || 142 | _zulu_get_packages() { 143 | local package_list cacheid='ZULU_PACKAGE_LIST' 144 | if ( [[ ${+_zulu_package_list} -eq 0 ]] || _cache_invalid $cacheid ) \ 145 | && ! _retrieve_cache $cacheid; 146 | then 147 | _zulu_package_list=() 148 | IFS=$'\n' package_list=($(zulu list --all --describe --simple)) 149 | 150 | for i in "$package_list[@]"; do 151 | _zulu_package_list+=("$(echo $i | cut -c 1-30 | tr -d " "):$(echo $i | cut -c 31-)") 152 | done 153 | 154 | _store_cache $cacheid _zulu_package_list 155 | fi; 156 | } 157 | 158 | # ~~~ CACHING ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 159 | # Using the cache mechanism of zsh to store packages 160 | (( $+functions[_zulu_get_installed_packages] )) || 161 | _zulu_get_installed_packages() { 162 | local package_list cacheid='ZULU_INSTALLED_PACKAGE_LIST' 163 | if ( [[ ${+_zulu_installed_package_list} -eq 0 ]] || _cache_invalid $cacheid ) \ 164 | && ! _retrieve_cache $cacheid; 165 | then 166 | _zulu_installed_package_list=() 167 | IFS=$'\n' package_list=($(zulu list --installed --describe --simple)) 168 | 169 | for i in "$package_list[@]"; do 170 | _zulu_installed_package_list+=("$(echo $i | cut -c 1-30 | tr -d " "):$(echo $i | cut -c 31-)") 171 | done 172 | 173 | _store_cache $cacheid _zulu_installed_package_list 174 | fi; 175 | } 176 | 177 | # ~~~ CACHING ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 178 | # Using the cache mechanism of zsh to store themes 179 | (( $+functions[_zulu_get_installed_themes] )) || 180 | _zulu_get_installed_themes() { 181 | local theme_list cacheid='ZULU_INSTALLED_THEME_LIST' 182 | if ( [[ ${+_zulu_installed_theme_list} -eq 0 ]] || _cache_invalid $cacheid ) \ 183 | && ! _retrieve_cache $cacheid; 184 | then 185 | _zulu_installed_theme_list=() 186 | IFS=$'\n' theme_list=($(zulu list --installed --describe --simple --type theme)) 187 | 188 | for i in "$theme_list[@]"; do 189 | _zulu_installed_theme_list+=("$(echo $i | cut -c 1-30 | tr -d " "):$(echo $i | cut -c 31-)") 190 | done 191 | 192 | _store_cache $cacheid _zulu_installed_theme_list 193 | fi; 194 | } 195 | 196 | # ~~~ CACHING ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 197 | # Using the cache mechanism of zsh to store packages 198 | (( $+functions[_zulu_get_not_installed_packages] )) || 199 | _zulu_get_not_installed_packages() { 200 | local package_list cacheid='ZULU_NOT_INSTALLED_PACKAGE_LIST' 201 | if ( [[ ${+_zulu_not_installed_package_list} -eq 0 ]] || _cache_invalid $cacheid ) \ 202 | && ! _retrieve_cache $cacheid; 203 | then 204 | _zulu_not_installed_package_list=() 205 | IFS=$'\n' package_list=($(zulu list --not-installed --describe --simple)) 206 | 207 | for i in "$package_list[@]"; do 208 | _zulu_not_installed_package_list+=("$(echo $i | cut -c 1-30 | tr -d " "):$(echo $i | cut -c 31-)") 209 | done 210 | 211 | _store_cache $cacheid _zulu_not_installed_package_list 212 | fi; 213 | } 214 | 215 | _zulu() { 216 | typeset -A opt_args 217 | local context state line curcontext="$curcontext" 218 | 219 | _arguments -A \ 220 | '(-h --help)'{-h,--help}'[show help text and exit]' \ 221 | '(-v --version)'{-v,--version}'[show version information and exit]' 222 | 223 | _arguments \ 224 | '1: :_zulu_cmds' \ 225 | '*::arg:->args' 226 | 227 | case "$state" in 228 | (args) 229 | case "$words[1]" in 230 | (theme) 231 | _arguments \ 232 | '*: :_zulu_installed_themes' 233 | ;; 234 | (install) 235 | _arguments -A \ 236 | '(-h --help)'{-h,--help}'[show help text and exit]' \ 237 | '--ignore-dependencies[Don'\''t automatically install dependencies]' \ 238 | '--no-autoselect-themes[Don'\''t autoselect themes after installing]' \ 239 | '(-b --branch)'{-b,--branch}'[specify a branch to install]' \ 240 | '(-t --tag)'{-t,--tag}'[specify a tag or commit to install]' 241 | 242 | _arguments \ 243 | '*: :_zulu_not_installed_packages' 244 | ;; 245 | (switch) 246 | _arguments -A \ 247 | '(-b --branch)'{-b,--branch}'[specify a branch to install]' \ 248 | '(-t --tag)'{-t,--tag}'[specify a tag or commit to install]' 249 | 250 | _arguments \ 251 | '*: :_zulu_installed_packages' 252 | ;; 253 | (info) 254 | _arguments \ 255 | '*: :_zulu_packages' 256 | ;; 257 | (alias) 258 | _arguments \ 259 | '1: :_zulu_alias_cmds' 260 | ;; 261 | (func) 262 | _arguments \ 263 | '1: :_zulu_func_cmds' 264 | ;; 265 | (var) 266 | _arguments \ 267 | '1: :_zulu_var_cmds' 268 | ;; 269 | (config) 270 | _arguments \ 271 | '1: :_zulu_config_cmds' 272 | ;; 273 | (sync) 274 | _arguments \ 275 | '1: :_zulu_sync_cmds' 276 | ;; 277 | (fpath) 278 | _arguments \ 279 | '1: :_zulu_fpath_cmds' 280 | 281 | case "$words[2]" in 282 | (add|rm) 283 | _arguments \ 284 | '*:directory:_files -/' 285 | ;; 286 | esac 287 | ;; 288 | (cdpath) 289 | _arguments \ 290 | '1: :_zulu_cdpath_cmds' 291 | 292 | case "$words[2]" in 293 | (add|rm) 294 | _arguments \ 295 | '*:directory:_files -/' 296 | ;; 297 | esac 298 | ;; 299 | (path) 300 | _arguments \ 301 | '1: :_zulu_path_cmds' 302 | 303 | case "$words[2]" in 304 | (add|rm) 305 | _arguments \ 306 | '*:directory:_files -/' 307 | ;; 308 | esac 309 | ;; 310 | (manpath) 311 | _arguments \ 312 | '1: :_zulu_manpath_cmds' 313 | 314 | case "$words[2]" in 315 | (add|rm) 316 | _arguments \ 317 | '*:directory:_files -/' 318 | ;; 319 | esac 320 | ;; 321 | (link) 322 | _arguments -A \ 323 | '(-h --help)'{-h,--help}'[show help text and exit]' \ 324 | '--no-autoselect-themes[Don'\''t autoselect themes after installing]' 325 | 326 | _arguments \ 327 | '*: :_zulu_installed_packages' 328 | ;; 329 | (uninstall|unlink) 330 | _arguments \ 331 | '*: :_zulu_installed_packages' 332 | ;; 333 | (update|self-update) 334 | _arguments -A \ 335 | '(-h --help)'{-h,--help}'[show help text and exit]' \ 336 | '(-c --check)'{-c,--check}'[check if an update is available]' 337 | ;; 338 | (upgrade) 339 | _arguments \ 340 | '*: :_zulu_installed_packages' 341 | 342 | _arguments -A \ 343 | '(-h --help)'{-h,--help}'[show help text and exit]' \ 344 | '(-c --check)'{-c,--check}'[check if upgrades are available]' \ 345 | '(-y --no-confirmation)'{-y,--no-confirmation}'[do not ask for confirmation before upgrading]' 346 | ;; 347 | (list) 348 | _arguments -A \ 349 | '(-h --help)'{-h,--help}'[show help text and exit]' \ 350 | '(-i --installed)'{-i,--installed}'[list only installed packages]' \ 351 | '(-n --not-installed)'{-n,--not-installed}'[list only packages which have not been installed]' \ 352 | '(-a --all)'{-a,--all}'[list all packages]' \ 353 | '(-s --simple)'{-s,--simple}'[do not show installed indicators]' \ 354 | '(-d --describe)'{-d,--describe}'[show package descriptions]' 355 | ;; 356 | (bundle) 357 | _arguments -A \ 358 | '(-h --help)'{-h,--help}'[show help text and exit]' \ 359 | '(-f --file)'{-f,--file}'[specify a packagefile]' \ 360 | '(-c --cleanup)'{-c,--cleanup}'[uninstall packages not present in packagefile]' \ 361 | '(-d --dump)'{-d,--dump}'[dump installed packages to packagefile]' \ 362 | '(-x --force)'{-x,--force}'[force writing of packages to an existing file]' 363 | ;; 364 | (init) 365 | _arguments -A \ 366 | '(-h --help)'{-h,--help}'[show help text and exit]' \ 367 | '(-c --check-for-update)'{-c,--check-for-update}'[check if updates are available]' 368 | ;; 369 | esac 370 | ;; 371 | esac 372 | } 373 | 374 | (( $+functions[_zulu_packages] )) || _zulu_packages() { 375 | _zulu_get_packages 376 | local expl 377 | _describe -t packages 'packages' _zulu_package_list "$@" 378 | } 379 | 380 | (( $+functions[_zulu_installed_packages] )) || _zulu_installed_packages() { 381 | _zulu_get_installed_packages 382 | local expl 383 | _describe -t packages 'packages' _zulu_installed_package_list "$@" 384 | } 385 | 386 | (( $+functions[_zulu_installed_themes] )) || _zulu_installed_themes() { 387 | _zulu_get_installed_themes 388 | local expl 389 | _describe -t themes 'themes' _zulu_installed_theme_list "$@" 390 | } 391 | 392 | (( $+functions[_zulu_not_installed_packages] )) || _zulu_not_installed_packages() { 393 | _zulu_get_not_installed_packages 394 | local expl 395 | _describe -t packages 'packages' _zulu_not_installed_package_list "$@" 396 | } 397 | 398 | (( $+functions[_zulu_path_cmds] )) || _zulu_path_cmds() { 399 | _describe -t commands 'commands' _zulu_path_commands "$@" 400 | } 401 | 402 | (( $+functions[_zulu_fpath_cmds] )) || _zulu_fpath_cmds() { 403 | _describe -t commands 'commands' _zulu_fpath_commands "$@" 404 | } 405 | 406 | (( $+functions[_zulu_cdpath_cmds] )) || _zulu_cdpath_cmds() { 407 | _describe -t commands 'commands' _zulu_cdpath_commands "$@" 408 | } 409 | 410 | (( $+functions[_zulu_manpath_cmds] )) || _zulu_manpath_cmds() { 411 | _describe -t commands 'commands' _zulu_manpath_commands "$@" 412 | } 413 | 414 | (( $+functions[_zulu_alias_cmds] )) || _zulu_alias_cmds() { 415 | _describe -t commands 'commands' _zulu_alias_commands "$@" 416 | } 417 | 418 | (( $+functions[_zulu_func_cmds] )) || _zulu_func_cmds() { 419 | _describe -t commands 'commands' _zulu_func_commands "$@" 420 | } 421 | 422 | (( $+functions[_zulu_var_cmds] )) || _zulu_var_cmds() { 423 | _describe -t commands 'commands' _zulu_var_commands "$@" 424 | } 425 | 426 | (( $+functions[_zulu_config_cmds] )) || _zulu_config_cmds() { 427 | _describe -t commands 'commands' _zulu_config_commands "$@" 428 | } 429 | 430 | (( $+functions[_zulu_sync_cmds] )) || _zulu_sync_cmds() { 431 | _describe -t commands 'commands' _zulu_sync_commands "$@" 432 | } 433 | 434 | (( $+functions[_zulu_cmds] )) || _zulu_cmds() { 435 | _describe -t commands 'commands' _zulu_commands "$@" 436 | } 437 | 438 | _zulu "$@" 439 | --------------------------------------------------------------------------------