Commit 2693a2fd authored by Jorge Bucaran's avatar Jorge Bucaran

%%% United States of the Fish → Wahoo + OMF %%%

parent 4d628d5f
# EditorConfig is awesome: http://EditorConfig.org
# top-most EditorConfig file
# http://editorconfig.org
root = true
# Two-space indent, Unix-style newlines, and a newline ending every file
[*]
end_of_line = lf
insert_final_newline = true
indent_style = space
indent_size = 2
indent_style = space
insert_final_newline = true
trim_trailing_whitespace = true
custom/*
plugins/*
themes/*
pkg/**
!pkg/omf
!pkg/omf/**
.DS_Store
*.pyc
*~
*.sw?
plugins/ta/data/*
themes/**
!themes/default/*
# Track oh-my-fish plugin
!plugins/omf/
.DS_Store
**/.DS_Store
language: c
os:
- linux
- osx
env:
- FISH_PPA=nightly-master BREW_OPTIONS=--HEAD
before_install:
- script/bootstrap.sh
script: script/run-tests.fish
notifications:
email:
on_success: never
on_failure: change
webhooks:
urls:
- https://webhooks.gitter.im/e/16e8638d3a0deeaf317d
on_success: change
on_failure: always
on_start: false
sudo: false
addons:
apt:
packages:
- tree
- fish
before_script: pwd; tree -h
script: /bin/sh bin/install
after_script:
- cd ~/.config/fish; tree -h; find . -type f | xargs cat
<div align="center">
<a href="http://github.com/fish-shell/omf">
<img width=120px src="https://cloud.githubusercontent.com/assets/8317250/8510172/f006f0a4-230f-11e5-98b6-5c2e3c87088f.png">
</a>
</div>
<br>
<p align="center">
<b><a href="#issues">Issues</a></b>
|
<b><a href="#package-repositories">Packages</a></b>
|
<b><a href="#commit-messages">Commit Messages</a></b>
|
<b><a href="#code-style">Code Style</a></b>
</p>
# Contributing
We love pull requests. Here's a quick guide.
Thanks for taking the time to read this guide and please _do_ contribute to Oh My Fish. This is an open initiative and _everyone_ is welcome. :metal:
## Issues
Please [open an issue](https://github.com/fish-shell/omf/issues) for bug reports / patches. Include your OS version, code examples, stack traces and everything you can to help you debug your problem.
If you have a new feature or large change in mind, please open a new issue with your suggestion to discuss the idea together.
## Package Repositories
This is the repository for the core Oh My Fish framework and bootstrap installer.
If your issue is related to a specific package, we still may be able to help, but consider visiting that package's issue tracker first.
## Commit Messages
+ Use the [present tense](https://simple.wikipedia.org/wiki/Present_tense) ("add awesome-package" not "added ...")
+ Less than 72 characters or less for the first line of your commit.
+ Use of [emoji](http://www.emoji-cheat-sheet.com/) is definitely encouraged. :lollipop:
## Code Style
> These rules are not set in stone. Feel free to open an issue with suggestions and/or feedback.
### Control Flow
Using `if..else..end` blocks is preferred.
```fish
if not set -q ENV_VARIABLE
set -g ENV_VARIABLE 42
end
```
The following syntax is more concise, but arguably less transparent.
> You still may use `and` / `or` statements if you consider `if..else..then` to be overkill.
```fish
set -q VAR; set -g VAR 42
```
### Functions
Use named arguments `-a`:
```fish
function greet -a message
echo "$message"
end
```
Use `-d` description fields:
Fork and make your change. Make sure the tests pass:
```fish
function greet -a message -d "Display a greeting message"
echo "$message"
end
```
./script/run-tests.fish -v
`fish` does not have private functions, so in order to avoid polluting the global namespace, use a prefix based in the scope of your code. For example, if you are writing a `ninja` plugin using `__ninja_function_name`.
Push to your fork and [submit a pull request][pr].
If you are writing a function inside another function, prefix the inner one with the parent's name.
At this point you're waiting on us. We usually comment on pull requests within a few hours. We may suggest some changes or improvements or alternatives.
```fish
function parent
function parent_child
end
end
```
Some things that will increase the chance that your pull request is accepted:
Note that it's still possible to mimic private functions in `fish` by deleting the function before returning using `functions -e function_name`
* Write tests.
* Follow our [style guide][style].
* Write a [good commit message][commit].
```fish
function public_func
function private_func
# ...
functions -e private_func
end
end
```
## Style Guide
### Blocks
* Indentation should follow the "2-space convention".
* Keep line length to a maximum of 100 characters.
Blocks allow you to write code resembling macro expressions composed of smaller blocks without relying on variables.
### Plugins
Compare the following _without_ blocks:
If your plugin is complex, make sure to include tests, we suggest using [fish-spec][].
```fish
set -l colors green1 green2 green3
if test $error -ne 0
set colors red1 red2 red3
end
### Themes
for color in $colors
printf "%s"(set_color $color)">"
end
```
Make sure to include a screenshot in your pull request, but don't commit the file to git. A nifty way is to post a comment with the image and link directly to it.
and _using_ blocks:
```fish
for color in (begin
if test $error -ne 0
and printf "%s\n" red1 red2 red3
or printf "%s\n" green1 green2 green3
end)
printf "%s"(set_color $color)">"
end
```
[pr]: https://github.com/oh-my-fish/oh-my-fish/compare/
[fish-spec]: https://github.com/oh-my-fish/oh-my-fish/tree/master/plugins/fish-spec
[commit]: http://tbaggery.com/2008/04/19/a-note-about-git-commit-messages.html
[style]: #style-guide
The second example does not use a `colors` variable.
FROM ubuntu:latest
# Install dependencies
RUN apt-get -y install curl git software-properties-common
# Set bootstrap script environment variables
ENV FISH_PPA=nightly-master \
TRAVIS_OS_NAME=linux TRAVIS_REPO_SLUG=oh-my-fish/oh-my-fish TRAVIS_BRANCH=master
# Cache script folder
ADD script /src/script
# Install fish and oh-my-fish
RUN /src/script/bootstrap.sh
WORKDIR /root/.oh-my-fish
CMD ["fish", "./script/run-tests.fish", "--verbose"]
<div align="center">
<a href="http://github.com/fish-shell/omf">
<img width=120px src="https://cloud.githubusercontent.com/assets/8317250/8510172/f006f0a4-230f-11e5-98b6-5c2e3c87088f.png">
</a>
</div>
<br>
# FAQ
Thanks for taking the time to read this FAQ. Feel free to create a new issue if your question is not answered here.
## What is Oh My Fish and why do I want it?
Oh My Fish is a _framework_ for the [fishshell](https://fishshell.org). It helps you manage your configuration, themes and packages.
## What do I need to know to use Oh My Fish?
_Nothing_. You can install Oh My Fish and keep using Fish as usual. When you are ready to learn more just type `wa help`.
## What are Oh My Fish packages?
Oh My Fish packages are themes or plugins written in fish that extend the shell core functionality, run code during initialization, add auto completion for known utilities, etc.
## What kind of Oh My Fish packages are there?
There are roughly 3 kinds of packages:
1. Configuration utilities. For example [`pkg-pyenv`](https://github.com/oh-my-fish/pkg-pyenv) checks whether `pyenv` exists in your system and runs `(pyenv init - | psub)` for you during startup.
2. Themes. Check our [theme gallery](https://github.com/oh-my-fish).
3. Traditional shell utilities. For example [`pkg-copy`](https://github.com/oh-my-fish/pkg-copy), a clipboard utility compatible across Linux and OSX.
## What does Oh My Fish do exactly?
+ Autoload installed packages and themes under `$OMF_PATH/`.
+ Autoload your custom path. `$OMF_PATH/custom` by default, but configurable via `$OMF_CUSTOM`.
+ Autoload any `functions` directory under `$OMF_PATH` and `$OMF_CUSTOM`
+ Run `$OMF_CUSTOM/init.fish` if available.
## How can I upgrade from an existing Oh My Fish installation?
> :warning: Remember to backup your dotfiles and other sensitive data first.
```
rm -rf "$fish_path"
curl -L git.io/omf | sh
```
## I changed my prompt with `fish_config` and now I can't get my Oh My Fish theme's prompt back, what do I do?
`fish_config` persists the prompt to `~/.config/fish/functions/fish_prompt.fish`. That file gets loaded _after_ the Oh My Fish theme, therefore it takes precedence over the Oh My Fish theme's prompt. To restore your Oh My Fish theme prompt, simply remove that file by running:
```
rm ~/.config/fish/functions/fish_prompt.fish
```
## How do I use fish as my default shell?
Add Fish to `/etc/shells`:
```sh
echo "/usr/local/bin/fish" | sudo tee -a /etc/shells
```
Make Fish your default shell:
```sh
chsh -s /usr/local/bin/fish
```
To switch your default shell back:
> Substitute `/bin/bash` with `/bin/tcsh` or `/bin/zsh` as appropriate.
```sh
chsh -s /bin/bash
```
The MIT License (MIT)
Copyright (c) 2014 Bruno Ferreira Pinto
Copyright (c) 2015, Oh My Fish!
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
......
> The [Fishshell][fishshell] Framework
[![Fish Version][fish-badge]][fishshell]
[![Build Status][travis-badge]][travis-url]
[![License][license-badge]](#LICENSE)
<a name="omf"></a>
<br>
<p align="center">
<a href="https://github.com/oh-my-fish/oh-my-fish">
<img width=20% src="https://cloud.githubusercontent.com/assets/958723/6883431/9beb62b0-d58b-11e4-902c-2f716859a7ad.png">
</a>
<a href="https://github.com/fish-shell/omf/blob/master/README.md">
<img width="200px" src="https://cloud.githubusercontent.com/assets/8317250/8510172/f006f0a4-230f-11e5-98b6-5c2e3c87088f.png">
</a>
</p>
<a name="omf"></a>
<br>
<p align="center">
<b><a href="#about">About</a></b>
|
<b><a href="#install">Install</a></b>
|
<b><a href="#getting-started">Getting Started</a></b>
|
<b><a href="#advanced">Advanced</a></b>
|
<b><a href="https://github.com/fish-shell/omf/wiki/Screencasts">Screencasts</a></b>
|
<b><a href="/CONTRIBUTING.md">Contributing</a></b>
|
<b><a href="/FAQ.md">FAQ</a></b>
<p align="center">
<a href="https://gitter.im/fish-shell/omf?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge">
<img src="https://badges.gitter.im/Join%20Chat.svg">
</a>
</p>
</p>
[![Build Status](https://travis-ci.org/oh-my-fish/oh-my-fish.svg?branch=master)](https://travis-ci.org/oh-my-fish/oh-my-fish) [![](https://img.shields.io/badge/Framework-Oh My Fish-blue.svg?style=flat)](https://github.com/oh-my-fish/oh-my-fish) ![](https://img.shields.io/cocoapods/l/AFNetworking.svg) [![Join the chat at https://gitter.im/oh-my-fish/oh-my-fish](https://badges.gitter.im/Join%20Chat.svg)](https://gitter.im/oh-my-fish/oh-my-fish?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)
<br>
# About
# Oh My Fish!
> :warning: You need [git](https://git-scm.com/book/en/v2/Getting-Started-Installing-Git)
and [Fish][fishshell] to install Oh My Fish!.
### Why?
Developing on a shell should be a pleasure. Our goal is to help developers that do not want to spend time configuring their own computer to spend time doing what they want.
Oh My Fish is an all-purpose framework for the [fishshell][Fishshell]. It looks after your configuration, themes and packages. It's lightining fast and easy to use.
### How?
With the power of our community, we take the already awesome [fish shell][fish] to another level by creating simple-to-use plugins and themes.
We love contributions, [fork and send us a PR](https://github.com/fish-shell/omf/fork).
[fish]: http://fishshell.com/
# Install
### What?
Oh-my-fish is a user-friendly framework for managing your fish-shell configuration. It includes optional plugins (brew, git-flow, rails, python, node, etc) and themes.
```sh
curl -L git.io/omf | sh
omf help
```
<br>
## Installation
Or _download_ and run it yourself:
```sh
curl -L git.io/omf > install
chmod +x install
./install
```
# :beginner: Getting Started
Oh My Fish includes a small utility `omf` to fetch and install new packages and themes.
## `omf update`
Update framework and installed packages.
## `omf get` _`<package> ...`_
Install one _or more_ themes or packages. To list available packages type `omf use`.
> You can fetch packages by URL as well via `omf get URL`
## `omf list`
List installed packages.
> To list packages available for download use `omf get`.
## `omf use` _`<theme>`_
Apply a theme. To list available themes type `omf use`.
## `omf remove` _`<name>`_
Remove a theme or package.
> Packages subscribed to `uninstall_<pkg>` events are notified before the package is removed to allow custom cleanup of resources. See [Uninstall](#uninstall).
## `omf new pkg | theme` _`<name>`_
Scaffold out a new package or theme.
> This creates a new directory under `$OMF_CUSTOM/{pkg | themes}/` with a template.
## `omf submit` _`pkg/<name>`_ _`[<url>]`_
Add a new package. To add a theme use `omf submit` _`themes/<name>`_ _`<url>`_.
Make sure to [send us a PR][omf-pulls-link] to update the registry.
## `omf query` _`<variable name>`_
Use to inspect all session variables. Useful to dump _path_ variables like `$fish_function_path`, `$fish_complete_path`, `$PATH`, etc.
## `omf destroy`
Uninstall Oh My Fish. See [uninstall](#uninstall) for more information.
# :triangular_flag_on_post: Advanced
+ [Bootstrap](#bootstrap)
+ [Startup](#startup)
+ [Core Library](#core-library)
+ [Packages](#packages)
+ [Creating](#creating)
+ [Submitting](#submitting)
+ [Initialization](#initialization)
+ [Uninstall](#uninstall)
+ [Ignoring](#ignoring)
## Bootstrap
Oh My Fish's bootstrap script will install `git` and `fish` if not available, switch your default shell and modify `$HOME/.config/fish/config.fish` to source Oh My Fish's `init.fish` script.
## Startup
This script runs each time a new session begins, autoloading packages, themes and your _custom_ path (dotfiles) in that order.
The _custom_ path (`$HOME/.dotfiles` by default) is defined by `$OMF_CUSTOM` in `$HOME/.config/fish/config.fish`. Modify this to load your own dotfiles if you have any.
## Core Library
The core library is a minimum set of basic utility functions that extend your shell.
+ [See the documentation](/lib/README.md).
## Packages
### Creating
> A package name may only contain lowercase letters and hyphens to separate words.
To scaffold out a new package:
```fish
$ omf new pkg my_package
my_package/
README.md
my_package.fish
completions/my_package.fish
```
> Use `omf new theme my_theme` for themes.
Please provide [auto completion](http://fishshell.com/docs/current/commands.html#complete) for your utilities if applicable and describe how your package works in the `README.md`.
`my_package.fish` defines a single function:
```fish
function my_package -d "My package"
end
```
> Bear in mind that fish lacks a private scope so consider the following options to avoid polluting the global namespace:
+ Prefix functions: `my_package_my_func`.
+ Using [blocks](http://fishshell.com/docs/current/commands.html#block).
### Submitting
Oh My Fish keeps a registry of packages under `$OMF_PATH/db/`.
To create a new entry run:
```fish
curl -L https://github.com/oh-my-fish/oh-my-fish/raw/master/tools/install.fish | fish
omf submit pkg/my_package .../my_package.git
```
**NOTE**: The installation script renames your existing `config.fish` to `config.orig`, and replaces it with [the default oh-my-fish config](https://github.com/oh-my-fish/oh-my-fish/blob/master/templates/config.fish). If you have existing customizations to your fish config, you will need to manually include those customizations after the install.
Similarly for themes use:
If you want to install it manually, [click here](https://github.com/oh-my-fish/oh-my-fish/wiki/Manual-Installation).
```fish
omf submit theme/my_theme .../my_theme.git
```
## Usage
This will add a new entry to your local copy of the registry. Please [send us a PR][omf-pulls-link] to update the global registry.
Open your fish configuration file `~/.config/fish/config.fish` and specify the theme and the plugins you want to use. And then run `omf install` on your terminal to install them.
Before setting down on a theme, you might want to have a go with all themes using our quick [theme switcher](https://github.com/oh-my-fish/plugin-theme) by typing `theme --help` on your shell.
### Initialization
## Upgrading from previous version
If you want to be [notified](http://fishshell.com/docs/current/commands.html#emit) when your package is loads, declare the following function in your `my_package.fish`:
[![asciicast](https://asciinema.org/a/20802.png)](https://asciinema.org/a/20802)
```fish
function init -a path --on-event init_mypkg
end
```
Use this event to modify the environment, load resources, autoload functions, etc. If your package does not export any functions, you can still use this event to add functionality to your package.
### Uninstall
Oh My Fish emits `uninstall_<pkg>` events before a package is removed via `omf remove <pkg>`. Subscribers can use the event to clean up custom resources, etc.
```fish
function uninstall --on-event uninstall_pkg
end
```
### Ignoring
## Customization
Remove any packages you wish to turn off using `omf remove <package name>`. Alternatively, you can set a global env variable `$OMF_IGNORE` in your `~/.config/fish/config.fish` with the packages you wish to ignore. For example:
If you have many functions which go well together, you can create custom plugin in the `custom/plugins/PLUGIN_NAME` directory and add to it as many functions as you want.
```fish
set -g OMF_IGNORE skip this that ...
```
If you would like to use your custom theme, move it with the same name in the `custom/themes/` directory and it will override the original theme in `themes/`.
If you just want to override any of the default behavior or add some environment variables, just add a new file (ending in .load) into the `custom/` directory.
# License
## Contributing
MIT © [Oh My Fish][contributors] :metal:
Create an [issue](https://github.com/oh-my-fish/oh-my-fish/issues) linking to your repository and we will move it to the [oh-my-fish](https://github.com/oh-my-fish) organization.
[fishshell]: http://fishshell.com
## Uninstall
[contributors]: https://github.com/fish-shell/omf/graphs/contributors
rm -rf ~/.oh-my-fish
[travis-badge]: http://img.shields.io/travis/fish-shell/omf.svg?style=flat-square
[travis-url]: https://travis-ci.org/fish-shell/omf
## License
[fish-badge]: https://img.shields.io/badge/fish-v2.2.0-007EC7.svg?style=flat-square
[MIT](http://mit-license.org) © [Contributors](https://github.com/oh-my-fish/oh-my-fish/graphs/contributors)
[license-badge]: https://img.shields.io/badge/license-MIT-007EC7.svg?style=flat-square
[Logo](https://cloud.githubusercontent.com/assets/958723/6847746/8d1b95b0-d3a7-11e4-866a-6bdc1eea0fe6.png) by [marcker](https://github.com/marcker):small_blue_diamond: [Attribution CC 4.0](http://creativecommons.org/licenses/by/4.0/)
[omf-pulls-link]: https://github.com/fish-shell/omf/pulls
#!/bin/sh
#
# USAGE
# #1: curl -L git.io/omf | sh
# #2: curl -L git.io/omf > install && chmod +x install && ./install
# #3: OMF_CUSTOM=~/.dotfiles curl -L git.io/omf | sh
#
# ENV
# XDG_DATA_HOME Base directory (~/.local/share)
# XDG_CONFIG_HOME Base configuration directory (~/.config)
#
# ↑ See XDG Base Directory Specification
# → https://standards.freedesktop.org/basedir-spec/basedir-spec-latest.html
#
# OMF_PATH Oh My Fish directory
# OMF_CONFIG Oh My Fish configuration
# OMF_CUSTOM Custom dotfiles directory
#
# OMF_REPO_URI Source git repository
# OMF_REPO_BRANCH Source repository default branch (master)
#
# FUNCTIONS
# die
# is_installed
# omf_create_fish_config <path/to/fish.config>
# omf_install
test -z ${XDG_DATA_HOME+_} && XDG_DATA_HOME="${HOME}/.local/share"
test -z ${XDG_CONFIG_HOME+_} && XDG_CONFIG_HOME="${HOME}/.config"
test -z ${OMF_PATH+_} && OMF_PATH="${XDG_DATA_HOME}/omf"
test -z ${OMF_CUSTOM+_} && OMF_CUSTOM="${HOME}/.dotfiles"
test -z ${OMF_CONFIG+_} && OMF_CONFIG="${XDG_CONFIG_HOME}/omf"
test -z ${OMF_REPO_URI+_} && OMF_REPO_URI="https://github.com/fish-shell/omf"
test -z ${OMF_REPO_BRANCH+_} && OMF_REPO_BRANCH="master"
die() {
echo "$1" && exit 1
}
is_installed() {
type "$1" >/dev/null 2>&1
}
omf_create_fish_config() {
local fish_config_file=$1
mkdir -p $(dirname "${fish_config_file}")
touch "${fish_config_file}"
}
omf_install() {
echo "Resolving Oh My Fish path → ${OMF_PATH}"
test -d "${OMF_PATH}" && die "Existing installation detected, aborting"
local git_uri="$(echo ${OMF_REPO_URI} | sed 's/\.git//').git"
echo "Cloning Oh My Fish → ${git_uri}"
if ! git clone -q --depth 1 -b "${OMF_REPO_BRANCH}" "${git_uri}" "${OMF_PATH}"; then
echo "Is 'git' installed?"
die "Could not clone the repository → ${OMF_PATH}:${OMF_REPO_BRANCH}"
fi
pushd ${OMF_PATH} >/dev/null 2>&1
local git_rev=$(git rev-parse HEAD) >/dev/null 2>&1
local git_upstream=$(git config remote.upstream.url)
if [ -z "${git_upstream}" ]; then
git remote add upstream ${git_uri}
else
git remote set-url upstream ${git_uri}
fi
echo "Oh My Fish revision id → ${git_rev}"
popd >/dev/null 2>&1
test -z ${FISH_CONFIG+_} && FISH_CONFIG="${XDG_CONFIG_HOME}/fish"
local fish_config_file="${FISH_CONFIG}/config.fish"
if [ -e "${FISH_CONFIG}/config.fish" ]; then
local timestamp=$(date +%s)
local fish_config_bk="${FISH_CONFIG}/config.${timestamp}.copy"
echo "Found existing 'fish' configuration → ${fish_config_file}"
echo "Writing back-up copy → ${fish_config_bk}"
cp "${fish_config_file}" "${fish_config_bk}" >/dev/null 2>&1
test $? -ne 0 && die "Writing back-up copy failed, error code → ${?}"
else
omf_create_fish_config $fish_config_file
fi
echo "Adding Oh My Fish bootstrap → ${fish_config_file}"
touch ${fish_config_file} >/dev/null 2>&1
test ! -w ${fish_config_file} && die "Fish configuration file is not writable, aborting."
echo "set -g OMF_PATH $(echo "${OMF_PATH}" | sed -e "s|$HOME|\$HOME|")" > ${fish_config_file}
echo "set -g OMF_CUSTOM $(echo "${OMF_CUSTOM}" | sed -e "s|$HOME|\$HOME|")" >> ${fish_config_file}
echo "set -g OMF_CONFIG $(echo "${OMF_CONFIG}" | sed -e "s|$HOME|\$HOME|")" >> ${fish_config_file}
echo "source \$OMF_PATH/init.fish" >> ${fish_config_file}
if [ ! -d "${OMF_CONFIG}" ]; then
echo "Writing Oh My Fish configuration → ${OMF_CONFIG}"
mkdir -p "${OMF_CONFIG}"
test -f "${OMF_CONFIG}/theme" || echo default > "${OMF_CONFIG}/theme"
test -f "${OMF_CONFIG}/revision" || echo ${git_rev} > "${OMF_CONFIG}/revision"
fi
}
echo "Installing Oh My Fish..."
! is_installed "fish" && die "Please install fish to continue → http://fishshell.com/"
if omf_install; then
echo "Oh My Fish successfully installed."
cd $HOME
# Do not swap process if running in a CI environment.
[ -z ${CI+_} ] || exit 0 && exec "fish" < /dev/tty
else
die "Oh My Fish couldn't install, but you can complain here → git.io/omf-issues"
fi
# Add yourself some shortcuts to projects you often work on
# Example:
#
# set oh-my-fish /Users/bpinto/.oh-my-fish
#
# Optionally add completions for your plugin here.
# complete -f -c my_command -a some_arg -d 'Description here'
# Add your own custom plugins in the custom/plugins directory. Plugins placed
# here will override ones with the same name in the main plugins directory.
https://github.com/wa/pkg-ansible
https://github.com/wa/pkg-battery
https://github.com/wa/pkg-copy
https://github.com/wa/pkg-direnv
https://github.com/cap10morgan/wa-emacs
https://github.com/wa/pkg-extract
https://github.com/wa/pkg-fasd
https://github.com/wa/pkg-gi
https://github.com/wa/pkg-hub
https://github.com/wa/pkg-keychain
https://github.com/wa/pkg-limap
https://github.com/wa/pkg-osx_manpath
https://github.com/wa/pkg-peco
https://github.com/wa/pkg-pyenv
https://github.com/wa/pkg-rbenv
https://github.com/wa/pkg-set_color
https://github.com/wa/pkg-stamp
https://github.com/wa/pkg-thefuck
https://github.com/wa/pkg-tiny
https://github.com/wa/theme-agnoster
https://github.com/oh-my-fish/theme-agnoster
https://github.com/oh-my-fish/theme-agnoster-mercurial
https://github.com/wa/theme-batman
https://github.com/oh-my-fish/theme-beloglazov
https://github.com/oh-my-fish/theme-bira
https://github.com/oh-my-fish/theme-bobthefish
https://github.com/oh-my-fish/theme-budspencer
https://github.com/oh-my-fish/theme-cbjohnson
https://github.com/oh-my-fish/theme-clearance
https://github.com/oh-my-fish/theme-cmorrell
https://github.com/oh-my-fish/theme-coffeeandcode
https://github.com/oh-my-fish/theme-cor
https://github.com/oh-my-fish/theme-dangerous
https://github.com/oh-my-fish/theme-eclm
https://github.com/oh-my-fish/theme-edan
https://github.com/oh-my-fish/theme-fishface
https://github.com/oh-my-fish/theme-fishy-drupal
https://github.com/oh-my-fish/theme-fisk
https://github.com/wa/theme-flash
https://github.com/oh-my-fish/theme-fox
https://github.com/oh-my-fish/theme-gianu
https://github.com/oh-my-fish/theme-gitstatus
https://github.com/oh-my-fish/theme-gnuykeaj
https://github.com/oh-my-fish/theme-godfather
https://github.com/wa/theme-hogan
https://github.com/wa/theme-hulk
https://github.com/oh-my-fish/theme-idan
https://github.com/oh-my-fish/theme-integral
https://github.com/oh-my-fish/theme-jacaetevha
https://github.com/oh-my-fish/theme-krisleech
https://github.com/oh-my-fish/theme-l
https://github.com/wa/theme-led
https://github.com/oh-my-fish/theme-mtahmed
https://github.com/oh-my-fish/theme-nai
https://github.com/oh-my-fish/theme-numist
https://github.com/oh-my-fish/theme-ocean
https://github.com/oh-my-fish/theme-perryh
https://github.com/oh-my-fish/theme-red-snapper
https://github.com/oh-my-fish/theme-robbyrussell
https://github.com/wa/theme-russell
https://github.com/oh-my-fish/theme-scorphish
https://github.com/oh-my-fish/theme-simplevi
https://github.com/oh-my-fish/theme-syl20bnr
https://github.com/oh-my-fish/theme-taktoa
https://github.com/oh-my-fish/theme-technopagan
https://github.com/oh-my-fish/theme-toaster
https://github.com/daveyarwood/tomita
https://github.com/oh-my-fish/theme-trout
https://github.com/oh-my-fish/theme-uggedal
https://github.com/oh-my-fish/theme-will
https://github.com/oh-my-fish/theme-yimmy
https://github.com/oh-my-fish/theme-zish
function Plugin --argument-names name
set -g fish_plugins $fish_plugins $name
if [ -e $fish_path/plugins/$name -o -e $fish_custom/plugins/$name ]
import plugins/$name
else
set_color red
echo "Plugin '$name' is not installed. Run 'omf install' to download and install it."
set_color normal
end
end
function Theme --argument-names name
set -g fish_theme $name
if [ -e $fish_path/themes/$name -o -e $fish_custom/themes/$name ]
import themes/$name
else
set_color red
echo "Theme '$name' is not installed. Run 'omf install' to download and install it."
set_color normal
end
end
# NAME
# _prepend_path - adds a path to a list
#
# SYNOPSIS
# _prepend_path [-d --destination <destination path>] <path>
#
# DESCRIPTION
# Adds a path to a list.
# If no list specified, defaults to $PATH
#
# OPTIONS
# <path>
# Required. Specify the path to add to the list.
# OPERATORS
# -d <DESTINATION PATH>
# Should appear at the end if used. Specifies the name of the
# list to prepend the paths to.
# If not used, $PATH is assumed by default.
#
# EXAMPLES
# _prepend_path $path
# Add $path to $PATH
#
# _prepend_path $path -d $fish_function_path
# Add $path to $fish_function_path
#/
function _prepend_path
# $PATH is the default destination path
set -l destination_path PATH
set -l path $argv
if test (count $argv) -gt 2
switch $path[-2]
case -d --destination
set destination_path $path[-1]
set path $path[1..-3]
end
end
for path in $path
if test -d $path
if not contains $path $$destination_path
set $destination_path $path $$destination_path
end
end
end
end
# NAME
# _prepend_tree - add a dependency tree to fish_function_path
#
# SYNOPSIS
# _prepend_tree [-v --verbose] <path> [<glob>..]
#
# DESCRIPTION
# Search a path tree and prepend directories with fish files. Use a glob
# list to include or exclude other file extensions. Use -v --verbose to
# output directories to be added to the path.
#
# OPTIONS
# [-v --verbose]
# Optional. Print directories that match the glob. Must be the
# first argument if used.
#
# <path>
# Required. Specify the path to search for glob patterns.
#
# [<glob> [<operator> <glob>..]]
# Glob pattern to match when traversing the path path.
#
# OPERATORS
# [! -not glob]
# Negates the following glob.
#
# [<glob> -o -or <glob>..]
# Default. Must meet at least one listed criteria.
#
# [<glob> [-a -and <glob>..]]
# Must meet *all* listed criteria.
#
# EXAMPLES
# _prepend_tree $path
# Match directories in $path containing `.fish` files.
#
# _prepend_tree $path \*.fish \*.sh
# Match directories in $path with either `.fish` OR `.sh` files.
#
# _prepend_tree $path \*.fish -a ! _\*.\*
# Match directories with `.fish` files that do not start with `_`.
#
# AUTHORS
# Jorge Bucaran <jbucaran@me.com>
#
# SEE ALSO
# .oh-my-fish/functions/_prepend_path.fish
#
# v.0.2.0
#/
function _prepend_tree -d "Add a dependency tree to the Fish path."
# Match directories with .fish files always.
set -l glob -name \*.fish
set -l verbose ""
# Retrieve first argument, either the path or the -v option.
set -l path $argv[1]
if contains -- $path -v --verbose
set verbose -v
# Option first, path should be next.
set path $argv[2]
end
# Parse glob options to create the main glob pattern.
if [ (count $argv) -gt 2 ]
set -l operator -o
for option in $argv[3..-1]
switch $option
case ! -not
set operator $operator !
case -o -or
set operator -o
case -a -and
set operator -a
case "*"
if [ operator = ! ]
set glob $operator $glob
else
set glob $glob $operator
end
set glob $glob -name $option
set operator -o # Default
end
end
end
# Traverse $path prepending only directories with matches. Excludes completions folder.
test -d $path
and for dir in (find $path ! -name "completions" ! -path "*.git*" -type d)
# Use head to retrieve at least one match. Skip not found errors
# for directories that do not exist.
if [ -z (find "$dir" $glob -maxdepth 1 ^/dev/null | head -1) ]
continue
end
# Print matched directories if the -v option is set.
if not [ -z $verbose ]
printf "%s\n" $dir
end
# Prepend matched directory to the the global fish function path.
# Note path duplicates are already handled by _prepend_path.
_prepend_path $dir -d fish_function_path
end
end
# NAME
# import - load libraries, plugins, themes, etc.
#
# SYNOPSIS
# import <path/library>[<path/library>..]
#
# DESCRIPTION
# Import libraries, plugins, themes, completions. Prepend existing
# user custom/<library> directories to the path to allow users to
# override specific functions in themes/plugins.
#
# NOTES
# $fish_path and $fish_custom point to oh-my-fish home and the user
# dotfiles folder respectively. Both globals are usually configured
# in ~/.config/fish/config.fish. Also, import is clever enough to
# skip directories with *.spec.fish files.
#
# EXAMPLES
# import plugins/<plugin>
# import plugins/{dpaste,cask} themes/bobthefish
#
# AUTHORS
# Jorge Bucaran <jbucaran@me.com>
#
# SEE ALSO
# functions/_prepend_path.fish
# functions/_prepend_tree.fish
#
# v.0.1.1
#/
function import -d "Load libraries, plugins, themes, etc."
# Do not add spec files to function path.
set -l skip_spec \*.fish -a ! \*.spec.fish
for library in $argv
# Prepend plugins, themes and completions, traversing library
# trees and prepending directories with fish code.
_prepend_tree $fish_path/$library $skip_spec
_prepend_tree $fish_custom/$library $skip_spec
_prepend_path $fish_path/$library/completions -d fish_complete_path
_prepend_path $fish_custom/$library/completions -d fish_complete_path
# Set path to load files.
set -l path $library/(basename $library).load
# Source each plugin, theme, etc., configuration load file.
for load in $fish_path/$path $fish_custom/$path
if [ -e $load ]
. $load
end
end
end
end
function restore_original_fish_colors
# Regular syntax highlighting colors
set fish_color_normal normal
set fish_color_command 005fd7 purple
set fish_color_param 00afff cyan
set fish_color_redirection normal
set fish_color_comment red
set fish_color_error red --bold
set fish_color_escape cyan
set fish_color_operator cyan
set fish_color_quote brown
set fish_color_autosuggestion 555 yellow
set fish_color_valid_path --underline
set fish_color_cwd green
set fish_color_cwd_root red
# Background color for matching quotes and parenthesis
set fish_color_match cyan
# Background color for search matches
set fish_color_search_match --background=purple
# Pager colors
set fish_pager_color_prefix cyan
set fish_pager_color_completion normal
set fish_pager_color_description 555 yellow
set fish_pager_color_progress cyan
end
# Cloned from https://github.com/fish-shell/fish-shell/issues/522
function source_script --description 'Source sh/csh file'
set -l ext
set -l type
while true
switch $argv[1]
case '--sh'
set type sh
case '--csh'
set type csh
case '--bash'
set type bash
case '--ext'
set ext 1
case '*'
break
end
set -e argv[1]
end
if not test "$type"
for f in $argv
switch $f
case '*.sh'
set type bash
break
case '*.csh' '*.tcsh'
set type csh
break
end
end
end
set -l exe
set -l source
switch "$type"
case bash
set exe /bin/bash
set source .
case sh
set exe /bin/sh
set source .
case csh
set exe /bin/tcsh
set source source
case '*'
echo Unknown source type for "'$argv'"
end
if test "$ext"
eval "exec $exe -c '$source $argv; exec fish'"
else
set -l f1 (command mktemp -t tmp.XXXXXXXXXX)
set -l f2 (command mktemp -t tmp.XXXXXXXXXX)
eval $exe -c "'env | sort > $f1; $source $argv; env | sort > $f2'"
set -l filter "(^[^\+-]|^\+\+\+|^---|^[\+-]_|^[\+-]PIPESTATUS|^[\+-]COLUMNS)"
set -l pattern 's/[:]\{0,1\}\([^:]\+\)/"\1" /g'
set -l IFS '='
set -l diffopts --old-line-format '-=%L' --new-line-format '+=%L' --unchanged-line-format ''
command diff $diffopts $f1 $f2 | command grep -vE $filter | while read -l state var value
switch $state$var
case -PATH
continue
case +PATH
eval set value (echo $value | tr : ' ')
for pt in $value
contains $pt $PATH; and continue
if not test -d $pt
echo "Unable to add '$pt' to \$PATH. Check existance."
continue
end
set -gx PATH $PATH $pt > /dev/null
end
case '-*'
set -e $var
case '+*'
eval set -gx $var (echo $value | command sed $pattern)
case '*'
echo Source error! Invalid case "'$state$var'"
end
end
command rm $f1 $f2 > /dev/null
end
end
# SYNOPSIS
# Initialize Oh My Fish.
#
# ENV
# OSTYPE Operating system.
# RESET_PATH Original $PATH preseved across Oh My Fish refreshes.
# OMF_PATH Set in ~/.config/fish/config.fish
# OMF_IGNORE List of packages to ignore.
# OMF_CUSTOM Same as OMF_PATH. ~/.dotfiles by default.
#
# OVERVIEW
# + Autoload Oh My Fish packages, themes and custom path
# + For each <pkg> inside {$OMF_PATH,$OMF_CUSTOM}
# + Autoload <pkg> directory
# + Source <pkg>.fish
# + Emit init_<pkg> event
#
# + Autoload {$OMF_PATH,$OMF_CUSTOM}/functions
# + Source {$OMF_PATH,$OMF_CUSTOM} → fish-shell/fish-shell/issues/845
# + Source $OMF_CUSTOM/init.fish
if set -q RESET_PATH
set PATH $RESET_PATH
else
set -gx RESET_PATH $PATH
end
set -q OSTYPE; or set -g OSTYPE (uname)
# Save the head of function path and autoload Oh My Fish core functions
set -l user_function_path $fish_function_path[1]
set fish_function_path[1] $OMF_PATH/lib
set -l theme {$OMF_PATH,$OMF_CUSTOM}/themes/(cat $OMF_CONFIG/theme)
set -l paths $OMF_PATH/pkg/*
set -l custom $OMF_CUSTOM/pkg/*
set -l ignore $OMF_IGNORE
for path in $paths
set custom $OMF_CUSTOM/(basename $path) $custom
end
for path in $OMF_PATH/lib $OMF_PATH/lib/git $paths $theme $custom
contains -- (basename $path) $ignore; and continue
autoload $path $path/completions
source $path/(basename $path).fish
and emit init_(basename $path) $path
end
autoload $OMF_CUSTOM/functions
autoload $user_function_path
source {$OMF_PATH,$OMF_CUSTOM}/events.fish
source $OMF_CUSTOM/init.fish
<p align="center">
<a href="https://github.com/fish-shell/omf/blob/master/README.md">
<img width="100px" src="https://cloud.githubusercontent.com/assets/8317250/8510172/f006f0a4-230f-11e5-98b6-5c2e3c87088f.png">
</a>
</p>
# Core Library
## Basic Functions
#### `autoload` _`<path [path...]>`_
Autoload a function or completion path. Add the specified list of directories to `$fish_function_path`.
Any `completions` directories are correctly added to the `$fish_complete_path`.
```fish
autoload $mypath $mypath/completions
```
#### `available` _`<name>`_
Check if a program is available to run. Sets `$status` to `0` if the program is available.
Use this function to check if a plugin is available before using it:
```fish
if available battery
battery
end
```
#### `basename` _`<path> ...`_
Wrap basename so it can handle multiple arguments.
#### `refresh`
Extract the root (top-most parent directory), dirname and basename from [`fish_prompt`](http://fishshell.com/docs/current/faq.html#faq-prompt).
#### `prompt_segments`
Replace the running instance of fishshell with a new one causing Oh My Fish to reload as well.
## Git Functions
#### `git_ahead`
Echo a character that represents whether the current repo is ahead, behind or has diverged from its upstream.
##### Default values:
+ ahead: `+`
+ behind: `-`
+ diverged: `±`
+ none: ` `
#### `git_is_repo`
Set `$status` to `0` if the current working directory belongs to a git repo.
#### `git_branch_name`
Echo the currently checked out branch name of the current repo.
#### `git_is_dirty`
Set `$status` to `0` if there are any changes to files already being tracked in the repo.
#### `git_is_staged`
Set `$status` to `0` if there [staged](http://programmers.stackexchange.com/questions/119782/what-does-stage-mean-in-git) changes.
#### `git_is_stashed`
Set `$status` to `0` if there are items in the [stash](https://git-scm.com/book/en/v1/Git-Tools-Stashing).
#### `git_is_touched`
Set `$status` to `0` if the repo has any changes whatsoever, including [tracked or untracked](http://stackoverflow.com/questions/9663507/what-is-tracked-files-and-untracked-files-in-the-context-of-git) files.
#### `git_untracked`
Echo a `\n` separated list of untracked files.
# SYNOPSIS
# autoload <path [path...]>
#
# OVERVIEW
# Autoload a function or completion path. Add the specified list of
# directories to $fish_function_path. Any `completions` directories
# are correctly added to the $fish_complete_path.
function autoload -d "autoload a function or completion path"
for path in $argv
if test -d "$path"
set -l dest fish_function_path
if test (basename "$path") = "completions"
set dest fish_complete_path
end
contains "$path" $$dest; or set $dest "$path" $$dest
end
end
end
# SYNOPSIS
# available [name]
#
# OVERVIEW
# Check if a program is available.
function available -a program -d "check if a program is available."
type "$program" ^/dev/null >&2
end
# SYNOPSIS
# basename <string> [suffix]
# basename [-s suffix] <string> [string...]
#
# OVERVIEW
# osx style variable arguments basename
function basename -d "get the filename or directory part of a path"
if test (uname) = "Darwin"
command basename $argv
else
if set -q argv[1]
set -l ext ""
switch $argv[1]
case -s
if test (count $argv) -gt 2
set ext $argv[2]
set argv $argv[3..-1]
else
echo "basename: Invalid number of arguments"
return 1
end
end
for path in $argv
command basename "$path" "$ext"
end
end
end
end
function git_ahead -a ahead behind diverged none
git_is_repo; and begin
test -z "$ahead"; and set ahead "+"
test -z "behind"; and set behind "-"
test -z "diverged"; and set diverged "±"
test -z "none"; and set none ""
command git rev-list --left-right "@{upstream}...HEAD" ^/dev/null \
| awk "/>/ {a += 1} /</ {b += 1} \
{if (a > 0) nextfile} END \
{if (a > 0 && b > 0) print \"$diverged\"; \
else if (a > 0) print \"$ahead\"; \
else if (b > 0) print \"$behind\";
else printf \"$none\"}"
end
end
function git_branch_name -d "Get current branch name"
git_is_repo; and begin
command git symbolic-ref --short HEAD
end
end
function git_is_dirty -d "Check if there are changes to tracked files"
git_is_repo; and not command git diff --no-ext-diff --quiet --exit-code
end
function git_is_repo -d "Check if directory is a repository"
test -d .git; or command git rev-parse --git-dir >/dev/null ^/dev/null
end
function git_is_staged -d "Check if repo has staged changes"
git_is_repo; and begin
not command git diff --cached --no-ext-diff --quiet --exit-code
end
end
function git_is_stashed -d "Check if repo has stashed contents"
git_is_repo; and begin
command git rev-parse --verify --quiet refs/stash >/dev/null
end
end
function git_is_touched -d "Check if repo has any changes"
git_is_repo; and begin
test -n (echo (command git status --porcelain))
end
end
function git_untracked -d "Print list of untracked files"
git_is_repo; and begin
command git ls-files --other --exclude-standard
end
end
# SYNOPSIS
# set -l segs (prompt_segments) # root dir base
#
# OVERVIEW
# Extract the root (top-most parent directory), dirname and basename
# from fish_prompt
function prompt_segments -d "extract root, dir and base from fish_prompt"
set -l root (prompt_pwd | cut -d "/" -f1)
if test -z "$root"
echo "/"
else
echo "$root"
end
set -l path (prompt_pwd | cut -d "/" -f2-)
set -l dir (dirname $path)
if test $dir != "."
echo $dir
end
set -l base (basename $path)
if test -n "$base" -a "$base" != "~"
echo $base
end
end
# SYNOPSIS
# refresh
#
# OVERVIEW
# Refresh (reload) the current fish session.
function refresh -d "refresh the fish session"
exec fish < /dev/tty
end
# Set fish_custom to the path where your custom config files
# and plugins exist, or use the default custom instead.
if not set -q fish_custom
set -g fish_custom $fish_path/custom
end
# Add functions defined in oh-my-fish/functions to the path.
if not contains $fish_path/functions/ $fish_function_path
set fish_function_path $fish_path/functions/ $fish_function_path
end
if not set -q __omf_loaded
if set -q fish_plugins
set_color red
echo '$fish_plugins usage has been deprecated; please use the \'Plugin\' command.'
set_color normal
end
if set -q fish_theme
set_color red
echo '$fish_theme usage has been deprecated; please use the \'Theme\' command.'
set_color normal
end
if set -q fish_plugins; or set -q fish_theme
set_color yellow
echo 'See https://asciinema.org/a/20802 for info on updating config.fish.'
set_color normal
end
set -g __omf_loaded "true"
end
# Add imported plugins, completions and themes. Customize imported
# commands via the $fish_path/custom directory, for example create
# a directory under $fish_path/custom/themes with the same name as
# the theme and override any functions/variables there. Rinse and
# repeat for plugins.
import plugins/$fish_plugins themes/$fish_theme
# Always load oh-my-fish plugin
import plugins/omf
# Source all files inside custom directory.
for load in $fish_custom/*.load
. $load
end
# Make sure to exit with $status of 1 when reloading the framework.
or true
function omf_destroy -d "Remove Oh My Fish"
echo (omf::dim)"Removing Oh My Fish..."(omf::off)
omf_remove_package (basename $OMF_PATH/pkg/*) >/dev/null ^&1
if test -e "$HOME/.config/fish/config.copy"
mv "$HOME/.config/fish/config".{copy,fish}
end
if test (basename "$OMF_CONFIG") = "omf"
rm -rf "$OMF_CONFIG"
end
if test "$OMF_PATH" != "$HOME"
rm -rf "$OMF_PATH"
end
exec fish < /dev/tty
end
function omf_help
echo \n"\
"(omf::dim)"Usage"(omf::off)"
omf "(omf::em)"action"(omf::off)" [options]
"(omf::dim)"Actions"(omf::off)"
"(omf::em)"l"(omf::off)"ist List local packages.
"(omf::em)"g"(omf::off)"et Install one or more packages.
"(omf::em)"u"(omf::off)"se List / Apply themes.
"(omf::em)"r"(omf::off)"emove Remove a theme or package.
u"(omf::em)"p"(omf::off)"date Update Oh My Fish.
"(omf::em)"n"(omf::off)"ew Create a new package from a template.
"(omf::em)"s"(omf::off)"ubmit Submit a package to the registry.
"(omf::em)"q"(omf::off)"uery Query environment variables.
"(omf::em)"h"(omf::off)"elp Display this help.
"(omf::em)"v"(omf::off)"ersion Display version.
"(omf::em)"destroy"(omf::off)" Uninstall Oh My Fish.
For more information visit → "(omf::em)"git.io/oh-my-fish"(omf::off)\n
end
# List all packages available to install from the registry.
function omf_list_db_packages
for item in (basename $OMF_PATH/db/pkg/*)
contains $item (basename {$OMF_PATH,$OMF_CUSTOM}/pkg/*); or echo $item
end
end
# List all packages installed from the registry.
function omf_list_installed_packages
for item in (basename $OMF_PATH/pkg/*)
test $item = wa; or echo $item
end
end
function omf_list_installed_themes
for item in (basename $OMF_PATH/themes/*)
test $item = default; or echo $item
end
end
\ No newline at end of file
# List all custom packages and packages installed from the registry.
function omf_list_local_packages
for item in (basename {$OMF_PATH,$OMF_CUSTOM}/pkg/*)
test $item = wa; or echo $item
end
end
function omf_list_themes
set -l seen ""
for theme in (basename $OMF_PATH/db/themes/*) \
(basename {$OMF_PATH,$OMF_CUSTOM}/themes/*)
contains $theme $seen; or echo $theme
set seen $seen $theme
end
end
function omf_new -a option name
switch $option
case "p" "pkg" "pack" "packg" "package"
set option "pkg"
case "t" "th" "the" "thm" "theme" "themes"
set option "themes"
case "*"
echo (omf::err)"$option is not a valid option."(omf::off) 1^&2
return $OMF_INVALID_ARG
end
if not omf_util_valid_package "$name"
echo (omf::err)"$name is not a valid package/theme name"(omf::off) 1^&2
return $OMF_INVALID_ARG
end
if set -l dir (omf_util_mkdir "$option/$name")
cd $dir
set -l github (git config github.user)
test -z "$github"; and set github "{{USERNAME}}"
set -l user (git config user.name)
test -z "$user"; and set user "{{USERNAME}}"
omf_new_from_template "$OMF_PATH/pkg/wa/templates/$option" \
$github $user $name
echo (omf::em)"Switched to $dir"(omf::off)
else
echo (omf::err)"\$OMF_CUSTOM and/or \$OMF_PATH undefined."(omf::off) 1^&2
exit $OMF_UNKNOWN_ERR
end
end
function omf_new_from_template -a path github user name
for file in $path/*
if test -d $file
mkdir (basename $file)
pushd (basename $file)
omf_new_from_template $file $github $user $name
else
set -l target (begin
if test (basename $file) = "{{NAME}}.fish"
echo "$name.fish"
else
echo (basename "$file")
end
end)
sed "s/{{USER_NAME}}/$user/;s/{{GITHUB_USER}}/$github/;s/{{NAME}}/$name/" \
$file > $target
echo (omf::em)" create "(omf::off)" "(begin
if test (basename $PWD) = $name
echo ""
else
echo (basename "$PWD")"/"
end
end)$target
end
end
popd >/dev/null ^&2
end
function omf_get_package
for search in $argv
if test -e $OMF_PATH/db/pkg/$search
set target pkg/$search
else if test -e $OMF_PATH/db/themes/$search
set target themes/$search
else
set -l pkg (basename $search)
if test -e $OMF_PATH/pkg/$pkg
echo (omf::err)"Error: $pkg already installed."(omf::off) 1^&2
else
echo (omf::dim)"Trying to clone from URL..."(omf::err)
git clone -q $search $OMF_PATH/pkg/$pkg
and echo (omf::em)"✔ $pkg succesfully installed."(omf::off)
or echo (omf::err)"$pkg is not a valid package/theme."(omf::off) 1^&2
end
continue
end
if test -e $OMF_PATH/$target
echo (omf::dim)"Updating $search..."(omf::off)
pushd $OMF_PATH/$target
omf_util_sync "origin" >/dev/null ^&1
popd
echo (omf::em)"✔ $search up to date."(omf::off)
else
echo (omf::dim)"Installing $search..."(omf::off)
git clone (cat $OMF_PATH/db/$target) $OMF_PATH/$target >/dev/null ^&1
and echo (omf::em)"✔ $search succesfully installed."(omf::off)
or echo (omf::err)"Could not install package."(omf::off) 1^&2
end
end
refresh
end
function omf_query_env
function __omf_print_pretty_path -a path
printf "%s\n" $path \
| sed "s|$HOME|"(omf::em)"~"(omf::off)"|g" \
| sed "s|/|"(omf::em)"/"(omf::off)"|g"
end
if not set -q argv[1]
for var in (set)
echo (omf::dim)(echo $var | awk '{ printf $1"\n"; }')(omf::off)
echo (omf::em)(__omf_print_pretty_path (echo $var | awk '{$1=""; print $0}'))(omf::off)
end
else
for key in $$argv[1]
__omf_print_pretty_path $key
end
end
end
function omf_remove_package
for pkg in $argv
if not omf_util_valid_package $pkg
if test $pkg = "wa"
echo (omf::err)"You can't remove wa"(omf::off) 1^&2
else
echo (omf::err)"$pkg is not a valid package/theme name"(omf::off) 1^&2
end
return $OMF_INVALID_ARG
end
if test -d $OMF_PATH/pkg/$pkg
emit uninstall_$pkg
rm -rf $OMF_PATH/pkg/$pkg
else if test -d $OMF_PATH/themes/$pkg
if test $pkg = default
echo (omf::err)"You can't remove the default theme"(omf::off) 1^&2
return $OMF_INVALID_ARG
end
if test $pkg = (cat $OMF_CONFIG/theme)
omf_use "default"
end
rm -rf $OMF_PATH/themes/$pkg
end
if test $status -eq 0
echo (omf::em)"$pkg succesfully removed."(omf::off)
else
echo (omf::err)"$pkg could not be found"(omf::off) 1^&2
end
end
refresh
end
\ No newline at end of file
# SYNOPSIS
# Submit a package to the registry
#
# OPTIONS
# name Name of the package.
# [url] URL to the package repository.
function omf_submit -a name url -d "Submit a package to the registry"
switch (dirname $name)
case pkg
case themes
case "*"
echo (omf::err)"Missing directory name: pkg/ or themes/"(omf::off) 1^&2
return $OMF_INVALID_ARG
end
set -l pkg (basename $name)
if not omf_util_valid_package $pkg
echo (omf::err)"$pkg is not a valid package/theme name"(omf::off) 1^&2
return $OMF_INVALID_ARG
end
if test -z "$url"
echo (omf::em)"URL not specified, looking for a remote origin..."(omf::off) 1^&2
set url (git config --get remote.origin.url)
if test -z "$url"
echo (omf::em)"$pkg remote URL not found"(omf::off) 1^&2
echo "Try: git remote add <URL> or see Docs#Submitting" 1^&2
return $OMF_INVALID_ARG
end
else
if test -e "$OMF_PATH/db/$name"
echo (omf::err)"Error: $pkg already exists in the registry!"(omf::off) 1^&2
return $OMF_INVALID_ARG
else
echo "$url" > $OMF_PATH/db/$name
echo (omf::em)"$pkg added to the local "(dirname $name)" registry."(omf::off)
echo "Want to contribute? Send us a PR → github.com/fish-shell/omf"
return 0
end
end
end
function omf_update
set -l repo "upstream"
test -z (git config --get remote.upstream.url)
and set -l repo "origin"
if git diff-index --quiet HEAD -- >/dev/null ^&1
git pull $repo master >/dev/null ^&1
else
git stash >/dev/null ^&1
if git pull --rebase $repo master >/dev/null ^&1
git stash apply >/dev/null ^&1
else
omf_util_sync "origin"
end
end
end
\ No newline at end of file
function omf_use
if not test -e $OMF_CUSTOM/themes/$argv[1]
if not test -e $OMF_PATH/themes/$argv[1]
set -l theme $OMF_PATH/db/themes/$argv[1]
if test -e $theme
echo (omf::dim)"Downloading $argv[1] theme..."(omf::off)
git clone (cat $theme) $OMF_PATH/themes/$argv[1] >/dev/null ^&1
and echo (omf::em)"$argv[1] theme downloaded."(omf::off)
or return $OMF_UNKNOWN_ERR
else
echo (omf::err)"$argv[1] is not a valid theme"(omf::off) 1^&2
return $OMF_INVALID_ARG
end
end
end
echo "$argv[1]" > $OMF_CONFIG/theme
refresh
end
function omf_version
echo "Oh My Fish! $OMF_VERSION"
end
# SYNOPSIS
# Completions for Oh My Fish CLI
function __omf_is_single_opt
test (count (commandline -opc)) -le 1
end
function __omf_opt_is
set -l cmd (commandline -opc)
test (count $cmd) -gt 1; and contains -- $cmd[2] $argv
end
complete --no-files -c omf -d "Oh My Fish"
complete -c omf -n "__omf_opt_is q query" -a (printf "%s " (set | awk '{ printf $1"\n"; }'))
complete -c omf -n "__omf_opt_is r rm remove" -a (printf "%s " (omf_list_local_packages) (omf_list_installed_themes))
complete -c omf -n "__omf_opt_is g get" -a (printf "%s " (omf_list_db_packages))
complete -c omf -n "__omf_opt_is u use" -a (printf "%s " (omf_list_themes))
complete -c omf -a list -n "__omf_is_single_opt" -d "List local packages"
complete -c omf -a get -n "__omf_is_single_opt" -d "Install one or more packages"
complete -c omf -a use -n "__omf_is_single_opt" -d "List / Apply themes"
complete -c omf -a remove -n "__omf_is_single_opt" -d "Remove a theme or package"
complete -c omf -a update -n "__omf_is_single_opt" -d "Update Oh My Fish"
complete -c omf -a new -n "__omf_is_single_opt" -d "Create a new package from a template"
complete -c omf -a submit -n "__omf_is_single_opt" -d "Submit a package to the registry"
complete -c omf -a query -n "__omf_is_single_opt" -d "Query environment variables"
complete -c omf -a help -n "__omf_is_single_opt" -d "Display this help"
complete -c omf -a version -n "__omf_is_single_opt" -d "Display version"
complete -c omf -a destroy -n "__omf_is_single_opt" -d "Remove Oh My Fish"
# SYNOPSIS
# Oh My Fish CLI
#
# ENV
# OMF_VERSION Version
# OMF_CONFIG Oh My Fish configuration
#
# OVERVIEW
# Provides options to list, download and remove packages, update
# the framework, create / submit a new package, etc.
set -g OMF_MISSING_ARG 1
set -g OMF_UNKNOWN_OPT 2
set -g OMF_INVALID_ARG 3
set -g OMF_UNKNOWN_ERR 4
set -g OMF_VERSION "1.0.0"
function omf::em; set_color -o yellow ; end
function omf::dim; set_color -o 888 ; end
function omf::err; set_color -o red ; end
function omf::off; set_color normal ; end
function init -a path --on-event init_omf
autoload $path/cli $path/util
end
function omf -d "Oh My Fish"
if test (count $argv) -eq 0
omf_help; and return 0
end
switch $argv[1]
case "v" "ver" "version"
omf_version
case "q" "query"
switch (count $argv)
case 1
omf_query_env
case 2
omf_query_env "$argv[2]"
case "*"
echo (omf::err)"Invalid number of arguments"(omf::off) 1^&2
echo "Usage: $_ "(omf::em)"$argv[1]"(omf::off)" [<variable name>]" 1^&2
return $OMF_INVALID_ARG
end
case "h" "help"
omf_help
case "l" "li" "lis" "lst" "list"
omf_list_local_packages | column
case "g" "ge" "get" "install"
if test (count $argv) -eq 1
omf_list_db_packages | column
else
omf_get_package $argv[2..-1]
end
case "u" "use"
if test (count $argv) -eq 1
set -l theme (cat $OMF_CONFIG/theme)
set -l regex "[[:<:]]($theme)[[:>:]]"
test "$OSTYPE" != "Darwin"; and set regex "\b($theme)\b"
omf_list_themes | column | sed -E "s/$regex/"(omf::em)"\1"(omf::off)"/"
omf::off
else if test (count $argv) -eq 2
omf_use $argv[2]
else
echo (omf::err)"Invalid number of arguments"(omf::off) 1^&2
echo "Usage: $_ "(omf::em)"$argv[1]"(omf::off)" [<theme name>]" 1^&2
return $OMF_INVALID_ARG
end
case "r" "rm" "remove" "uninstall"
if test (count $argv) -ne 2
echo (omf::err)"Invalid number of arguments"(omf::off) 1^&2
echo "Usage: $_ "(omf::em)"$argv[1]"(omf::off)" <[package|theme] name>" 1^&2
return $OMF_INVALID_ARG
end
omf_remove_package $argv[2..-1]
case "p" "up" "upd" "update"
pushd $OMF_PATH
echo (omf::em)"Updating Oh My Fish..."(omf::off)
if omf_update
echo (omf::em)"Oh My Fish is up to date."(omf::off)
else
echo (omf::err)"Oh My Fish failed to update."(omf::off)
echo "Please open a new issue here → "(omf::em)"git.io/omf-issues"(omf::off)
end
omf_use (cat $OMF_CONFIG/theme)
omf_get_package (omf_list_installed_packages)
popd
refresh
case "s" "su" "sub" "submit"
switch (count $argv)
case 3
omf_submit $argv[2] $argv[3]
case "*"
echo (omf::err)"Argument missing"(omf::off) 1^&2
echo "Usage: $_ "(omf::em)"$argv[1]"(omf::off)" "(omf::em)"pkg|themes"(omf::off)"/<name> <url>" 1^&2
return $OMF_MISSING_ARG
end
case "n" "nw" "new"
if test (count $argv) -ne 3
echo (omf::err)"Package type or name missing"(omf::off) 1^&2
echo "Usage: $_ "(omf::em)"$argv[1]"(omf::off)" "(omf::em)"pkg|theme"(omf::off)" <name>" 1^&2
return $OMF_MISSING_ARG
end
omf_new $argv[2..-1]
case "destroy"
omf_destroy
case "*"
echo (omf::err)"$argv[1] option not recognized"(omf::off) 1^&2
return $OMF_UNKNOWN_OPT
end
end
language: c
os:
- linux
# - osx # currently not supported
sudo: false
addons:
apt:
packages:
- tree
- fish
before_script:
- pwd; tree -h
- curl -L git.io/omf | sh
script:
- omf g {{NAME}}
- cat $OMF_PATH/pkg/{{NAME}}/test/{{NAME}}.fish
The MIT License (MIT)
Copyright (c) 2015 {{USER}}
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
<div align="center">
<a href="http://github.com/fish-shell/omf">
<img width=90px src="https://cloud.githubusercontent.com/assets/8317250/8510172/f006f0a4-230f-11e5-98b6-5c2e3c87088f.png">
</a>
</div>
<br>
> {{NAME}} for [Oh My Fish][omf-link].
[![][travis-badge]][travis-link]
![][license-badge]
## Install
```fish
$ omf g {{NAME}}
```
## Usage
```fish
$ {{NAME}}
```
# License
[MIT][mit] © [{{USER}}][author] et [al][contributors]
[mit]: http://opensource.org/licenses/MIT
[author]: http://github.com/{{USER}}
[contributors]: https://github.com/{{USER}}/{{NAME}}/graphs/contributors
[omf-link]: https://www.github.com/fish-shell/omf
[license-badge]: https://img.shields.io/badge/license-MIT-007EC7.svg?style=flat-square
[travis-badge]: http://img.shields.io/travis/{{USER}}/{{NAME}}.svg?style=flat-square
[travis-link]: https://travis-ci.org/{{USER}}/{{NAME}}
# See → fishshell.com/docs/current/commands.html#complete
# SYNOPSIS
# {{NAME}} [options]
#
# USAGE
# Options
#
function init -a path --on-event init_{{NAME}}
end
function {{NAME}} -d "My package"
end
function uninstall --on-event uninstall_{{NAME}}
end
The MIT License (MIT)
Copyright (c) 2015 {{USER_NAME}}
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
<div align="center">
<a href="http://github.com/fish-shell/omf">
<img width=90px src="https://cloud.githubusercontent.com/assets/8317250/8510172/f006f0a4-230f-11e5-98b6-5c2e3c87088f.png">
</a>
</div>
<br>
> {{NAME}} theme for [Oh My Fish][omf-link].
## Install
```fish
$ omf u {{NAME}}
```
## Features
* Lorem ipsum dolor sit amet.
* Consectetur adipisicing elit.
## Screenshot
<p align="center">
<img src="{{SCREENSHOT_URL}}">
</p>
# License
[MIT][mit] © [{{USER}}][author] et [al][contributors]
[mit]: http://opensource.org/licenses/MIT
[author]: http://github.com/{{USER}}
[contributors]: https://github.com/{{USER}}/{{NAME}}/graphs/contributors
[omf-link]: https://www.github.com/fish-shell/omf
[license-badge]: https://img.shields.io/badge/license-MIT-007EC7.svg?style=flat-square
[travis-badge]: http://img.shields.io/travis/{{USER}}/{{NAME}}.svg?style=flat-square
[travis-link]: https://travis-ci.org/{{USER}}/{{NAME}}
# Set global color styles, for example:
#
# function {{NAME}}_error
# set_color -o red
# end
#
# function {{NAME}}_normal
# set_color normal
#
function fish_greeting
end
function fish_prompt
set -l code $status
prompt_pwd
end
function fish_right_prompt
set -l code $status
end
function fish_title
# Customize the title bar of the terminal window.
end
function omf_util_fork_repo -a user repo
curl -u "$user" --fail --silent https://api.github.com/repos/$repo/forks \
-d "{\"user\":\"$user\"}" >/dev/null ^&1
end
\ No newline at end of file
function omf_util_mkdir -a name
set -l name "$argv[1]"
if test -d "$OMF_CUSTOM"
set name "$OMF_CUSTOM/$name"
else if test -d "$OMF_PATH"
set name "$OMF_PATH/$name"
end
mkdir -p "$name"
echo $name
end
\ No newline at end of file
function omf_util_sync -a remote
set -l repo $remote
set -q argv[1]; and set repo $argv[1]
git fetch origin master
git reset --hard FETCH_HEAD
git clean -df
end
\ No newline at end of file
function omf_util_valid_package -a package
test (echo "$package" | tr "[:upper:]" "[:lower:]") = "omf"; and return 10
switch $package
case {a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p,q,r,s,t,u,v,w,x,y,z}\*
switch $package
case "*/*" "* *" "*&*" "*\"*" "*!*" "*&*" "*%*" "*#*"
return 10
case "*"
return 0
end
case "*"
return 10
end
end
# Plugins
* [__android-sdk__](https://github.com/oh-my-fish/plugin-android-sdk)[Android SDK](http://developer.android.com/sdk/index.html) integration.
* [__archlinux__](https://github.com/oh-my-fish/plugin-archlinux) – Provides a number of plugins to make using Arch Linux easier.
* [__better-alias__](https://github.com/oh-my-fish/plugin-balias) - Provide alias with auto completion.
* [__brew__](https://github.com/oh-my-fish/plugin-brew)[Homebrew](http://brew.sh/) integration.
* [__bundler__](https://github.com/oh-my-fish/plugin-bundler) – Use Ruby's [Bundler](http://bundler.io/) automatically for some commands.
* [__ccache__](https://github.com/oh-my-fish/plugin-ccache) – Enable [ccache](http://ccache.samba.org/) to speed up compilation.
* [__django__](https://github.com/oh-my-fish/plugin-django) – Helper for Django Unit tests. Cleans the cached modules as well.
* [__ec2__](https://github.com/oh-my-fish/plugin-ec2) – Exports env variables for Amazon's EC2 management.
* [__emacs__](https://github.com/oh-my-fish/plugin-emacs) – Wrapper for [daemon](http://www.emacswiki.org/emacs/EmacsAsDaemon) functionality of [Emacs](https://www.gnu.org/software/emacs/).
* [__emoji-clock__](https://github.com/oh-my-fish/plugin-emoji-clock) – The current time with half hour accuracy as an emoji symbol.
* [__extract__](https://github.com/oh-my-fish/plugin-extract) – Plugin to expand or extract bundled & compressed files.
* [__fish-spec__](https://github.com/oh-my-fish/plugin-fish-spec) - Unit testing as simple as fish. See the [README](fish-spec/README.markdown) for usage instructions.
* [__foreign-env__](https://github.com/oh-my-fish/plugin-foreign-env) – Run foreign applications (like nvm) and capture environment variable changes.
* [__fry__](https://github.com/oh-my-fish/plugin-fry) – Starts [fry](https://github.com/terlar/fry), a simple Ruby version manager for fish.
* [__gem__](https://github.com/oh-my-fish/plugin-gem) – Ruby gem integration.
* [__getopts__](https://github.com/oh-my-fish/plugin-getopts) [(issues)](https://github.com/bucaran/getopts) - A [Unix compliant](http://pubs.opengroup.org/onlinepubs/7908799/xbd/utilconv.html) implementation of [`getopts`](http://en.wikipedia.org/wiki/Getopts) for fish.
* [__gi__](https://github.com/oh-my-fish/plugin-gi)[gitignore.io](http://gitignore.io) CLI for fish.
* [__git-flow__](https://github.com/oh-my-fish/plugin-git-flow)[git-flow](https://github.com/nvie/gitflow) Completion support for git-flow.
* [__grc__](https://github.com/oh-my-fish/plugin-grc)[grc](http://kassiopeia.juls.savba.sk/~garabik/software/grc.html) Colourizer for some commands.
* [__jump__](https://github.com/oh-my-fish/plugin-jump) – A port of [Jeroen Janssens’ “jump” utility](http://jeroenjanssens.com/2013/08/16/quickly-navigate-your-filesystem-from-the-command-line.html).
* [__local-config__](https://github.com/oh-my-fish/plugin-local-config) – Support per-user, per-host and per-platform custom config files.
* [__localhost__](https://github.com/oh-my-fish/plugin-localhost) – Opens `http://localhost:3000` (and other ports) in the default browser.
* [__mc__](https://github.com/oh-my-fish/plugin-mc) – Plugin to start mc with a shell compliant (Bash).
* [__msg__](https://github.com/oh-my-fish/plugin-msg) - A technicolor message printer. A colorful alternative to echo.
* [__ndenv__](https://github.com/oh-my-fish/plugin-ndenv) – Helpers for [another node.js version manager](https://github.com/riywo/ndenv).
* [__node__](https://github.com/oh-my-fish/plugin-node) – Adds locally installed NodeJS `npm` binary executable modules to the path.
* [__pbcopy__](https://github.com/oh-my-fish/plugin-pbcopy) – OSX's pbcopy and pbpaste for Linux.
* [__percol__](https://github.com/oh-my-fish/plugin-percol) – Browse your fish history with [percol](https://github.com/mooz/percol).
* [__peco__](https://github.com/oh-my-fish/plugin-peco) – Browse your fish history with [peco](https://github.com/peco/peco).
* [__osx__](https://github.com/oh-my-fish/plugin-osx) - Integration with Finder and iTunes.
* [__php__](https://github.com/oh-my-fish/plugin-php) – Manage phphttp server.
* [__plenv__](https://github.com/oh-my-fish/plugin-plenv)[plenv](https://github.com/tokuhirom/plenv) Perl binary manager integration.
* [__pyenv__](https://github.com/oh-my-fish/plugin-pyenv)[Simple Python Version Management](https://github.com/yyuu/pyenv) integration.
* [__python__](https://github.com/oh-my-fish/plugin-python) – Set of shortcuts to Python based utilities (pybeatifyjson – clean JSON files, pyclean – remove old `.pyc`, pyhttp & pysmtp – simple HTTP & SMTP servers)
* [__rails__](https://github.com/oh-my-fish/plugin-rails) – Alias for executing database migrations.
* [__rbenv__](https://github.com/oh-my-fish/plugin-rbenv)[rbenv](https://github.com/sstephenson/rbenv) Ruby environment/version manager.
* [__replace__](https://github.com/oh-my-fish/plugin-replace) – A port of [replace](https://github.com/thoughtbot/dotfiles/blob/master/bin/replace).
* [__rvm__](https://github.com/oh-my-fish/plugin-rvm)[RVM](http://rvm.io) Ruby version manager.
* [__ssh__](https://github.com/oh-my-fish/plugin-ssh) – ssh conservative $TERM value helper.
* [__sublime__](https://github.com/oh-my-fish/plugin-sublime) – Creates `subl` command line shortcut to launch [Sublime Text editor](http://sublimetext.com/).
* [__tab__](https://github.com/oh-my-fish/plugin-tab) – Open the current directory (or any other directory) in a new tab.
* [__theme__](https://github.com/oh-my-fish/plugin-theme) – Quick theme switcher.
* [__tiny__](https://github.com/oh-my-fish/plugin-tiny) - tap into github's git.io URL shortener.
* [__title__](https://github.com/oh-my-fish/plugin-title) – Change your terminal title!
* [__tmux__](https://github.com/oh-my-fish/plugin-tmux) – Plugin to start tmux with support for 256 colours.
* [__vi-mode__](https://github.com/oh-my-fish/plugin-vi-mode) – Basic vi key bindings emulation for fish.
* [__xdg__](https://github.com/oh-my-fish/plugin-xdg) – Setup [xdg](http://standards.freedesktop.org/basedir-spec/basedir-spec-latest.html) environment on Linux.
* [__z__](https://github.com/oh-my-fish/plugin-z) – Integration with [z](https://github.com/rupa/z) (autojump alternative).
# fish-spec
> Unit testing as simple as fish.
The following guide describes how to use the `fish-spec` plugin bundled with Oh-My-Fish.
## Install
Before you can use `fish-spec`, you need to install [Oh-My-Fish](https://github.com/oh-my-fish/oh-my-fish).
## Usage
Import the library into your fish file via [import](https://github.com/oh-my-fish/oh-my-fish/blob/master/functions/import.fish).
Inside your project's directory create a new `spec` folder and add all your _spec_ files inside. _Spec_ files are regular fish files that shall look like `*.spec.fish` and contain your tests.
You can have multiple `spec.fish` files to organize your tests in a per module basis, or you can squash everything into a single file and use describe blocks to separate groups of tests.
A `spec.file` usually looks like this:
```fish
import plugins/fish-spec
import plugins/the-library
# Use -d to enter a friendly description (optional)
function describe_library -d "the grand library"
function before_all
# Optional. Runs only once before all the tests.
end
function after_all
# Optional. Runs only once after all the tests.
end
function before_each
# Optional. Runs once before each test.
end
function after_each
# Optional. Runs once after each test.
end
function it_does_this
# ...
expect $what_I_got --to-equal $what_I_wanted
end
function it_does_that
# ...
expect $a_list --to-contain-all $expected_items
end
# ...
end
# Run tests when this file is sourced.
spec.run $argv
```
## API
As of now, there is only one method you should be aware of, [expect](https://github.com/oh-my-fish/oh-my-fish/blob/master/plugins/fish-spec/expect.fish):
> Assert a list of expected values match an actual value/s.
Under the hood, _expect_ checks an _actual_ value, usually a relevant result from your test unit, is equal to, not equal to, etc., to an _expected_ value, as determined by your test. Below are the list of conditions available to use with `expect`:
* __--to-equal__
`<actual>` value equals the `<expected>` value. For example:
```fish
expect $my_value --to-equal 5
```
* __--to-not-equal__
`<actual>` value does not equal the `<expected>` value
```fish
expect $my_string --to-not-equal "oh-the-fish"
```
* __--to-contain-all__ all `<actual>` values exist in the `<expected>` list
```fish
expect $elements --to-contain-all "earth" "fire" "water" "air"
```
* __--to-not-contain-all__ no `<actual>` values exist in `<expected>` list
```fish
expect $our_planets --to-not-contain-all "golomo" "borg prime" "rigel" "terra"
```
* __--to-be-true__ the exit status should be _truthy_
```fish
__my_plugin_improve_workflow
expect $status --to-be-true
```
* __--to-be-false__ the exit status should be _falsy_
```fish
__my_plugin_erase_drive
expect $status --to-be-false
```
## FAQ
1. __How to use `fish-spec` without Oh-My-Fish?__
`fish-spec` is currently only available bundled with Oh-My-Fish. As the library matures and grows, however, a future guide describing how to export `fish-spec` may be written.
## Authors
+ [Bruno Pinto](https://github.com/bpinto)
+ [Jorge Bucaran](https://bucaran.me)
## License
[MIT](http://opensource.org/licenses/MIT)
function eval -S -d "Evaluate parameters as a command"
# keep a copy of the previous $status and use restore_status
# to preserve the status in case the block that is evaluated
# does not modify the status itself.
set -l status_copy $status
function -S restore_status
return $status_copy
end
if not set -q argv[2]
# like most builtins, we only check for -h/--help
# if we only have a single argument
switch "$argv[1]"
case -h --help
__fish_print_help eval
return 0
end
end
# If we are in an interactive shell, eval should enable full
# job control since it should behave like the real code was
# executed. If we don't do this, commands that expect to be
# used interactively, like less, wont work using eval.
set -l mode
if status --is-interactive-job-control
set mode interactive
else
if status --is-full-job-control
set mode full
else
set mode none
end
end
if status --is-interactive
status --job-control full
end
# rfish: To eval 'foo', we construct a block "begin ; foo; end <&3 3<&-"
# The 'eval2_inner' is a param to 'begin' itself; I believe it does nothing.
# Note the redirections are also within the quotes.
#
# We then pipe this to 'source 3<&0' which dup2's 3 to stdin.
#
# You might expect that the dup2(3, stdin) should overwrite stdin,
# and therefore prevent 'source' from reading the piped-in block. This doesn't
# happen because when you pipe to a builtin, we don't overwrite stdin with the
# read end of the block; instead we set a separate fd in a variable 'builtin_stdin',
# which is what it reads from. So builtins are magic in that, in pipes, their stdin
# is not fd 0.
restore_status
echo "begin; $argv "\n" ;end eval2_inner <&3 3<&-" | source 3<&0
set -l res $status
status --job-control $mode
functions -e restore_status
return $res
end
# NAME
# expect - assert a list of expected values match an actual value
#
# SYNOPSIS
# expect <expected> <condition> <actual>
# OPTIONS
# <expected>...
# <condition>
# --to-equal <actual> value equals <expected> value
# --to-not-equal <actual> value does not equals <expected> value
#
# --to-contain-all all <actual> values exist in <expected> list
# --to-not-contain-all all <actual> values does not exist in <expected> list
# --to-be-true exit status should be truthy
# --to-be-false exit status should be falsy
# <actual>...
#
# EXAMPLE
# import plugins/fish-spec
#
# function describe_my_test
# function it_does_my_task
# set -l result (my_task $data)
# expect $result --to-equal 0
# end
# end
# spec.run
#
# AUTHORS
# Bruno Pinto <@pfbruno>
# Jorge Bucaran <@bucaran>
#/
function expect
set -l result 0
# Parse expected / actual lists
set -l actual ""
set -l expected ""
set -l condition ""
for index in (seq (count $argv))
switch $argv[$index]
# --condition found, split expected/actual lists
case --\*
set expected $argv[1..(math $index-1)]
set condition $argv[$index]
# No comparison required e.g. --to-be-true
if [ $index -lt (count $argv) ]
set actual $argv[(math $index+1)..-1]
end
break
end
end
# Test conditions
switch $condition
case --to-be-false
eval "$expected"
test $status -ne 0
case --to-be-true
eval "$expected"
test $status -eq 0
case --to-contain-all
set result 0
for item in $actual
contains -- "$item" $expected
or set result $status
end
test $result -eq 0
case --to-not-contain-all
set result 0
for item in $actual
contains -- "$item" $expected
or set result $status
end
test $result -ne 0
case --to-equal
test "$expected" = "$actual"
case --to-not-equal
test "$expected" != "$actual"
case \*
test true = false
end
set result $status
if [ $result -eq 0 ]
# Return a non-empty string to indicate success.
set -g _spec_current_test_ouput (printf "$result")
else
# Return error information separated by \t and tested condition.
set -g _spec_current_test_ouput (printf "%s\n" $expected \t $condition $actual)
end
return $result
end
# NAME
# list.erase - erase any items from one or more lists
#
# SYNOPSIS
# <item> [<item>...] [--from] <list>
# <item> [<item>...] --from <list1> [<list2>...]
#
# DESCRIPTION
# Erase any number of items from any number of lists. If more than one
# list is specified it must be separated from the items with --from.
#
# NOTES
# While items are basically any valid sequence of symbols, lists refer
# to any global variable or local variable in the scope of the calling
# function by name.
#
# AUTHORS
# Jorge Bucaran <@bucaran>
#/
function -S list.erase
# Assume no items were erased.
set -l result 1
# At least one list should be at the last index.
set -l items $argv[1..-2]
set -l lists $argv[-1]
if set -l index (contains -i -- --from $argv)
# <items to erase> --from <lists>
set items $argv[1..(math $index-1)]
set lists $argv[(math $index+1)..-1]
end
for item in $items
for list in $lists
if set -l index (contains -i -- $item $$list)
set -e $list[1][$index]
# Function succeeds if at least an item is erased.
set result 0
end
end
end
return $result
end
# NAME
# spec.eval - eval a test function
#
# SYNOPSIS
# spec.eval <function> [OPTIONS...]
#
# OPTIONS
# See spec.report
#
# AUTHORS
# Bruno Pinto <@pfbruno>
# Jorge Bucaran <@bucaran>
#/
import plugins/msg
function spec.eval
set -l result $status
set -l test $argv[1]
set -e argv[1]
if functions -q $test
# Erase previous test output
set -e _spec_current_test_ouput
# Run the test yielding control to the user defined spec.
eval $test
set result $status
# Display test results.
spec.view $test $result $argv -- $_spec_current_test_ouput
end
return $result
end
# NAME
# spec.functions - return functions in the global scope that match ^key
#
# SYNOPSIS
# spec.functions [OPTIONS] <key>
#
# OPTIONS
# -b --backup <key> <prefix>
# Create new backup functions for all functions by <key> with a <prefix>
#
# -r --restore <prefix>
# Create new functions without <prefix>.
#
# -q --quiet
# Quiet mode. No output. Return 1 if no functions are found.
#
# -e --erase <key>
# Erase the matched functions.
#
# EXAMPLES
# 1) spec.functions "describe_"
# 2) spec.functions -q "before_"
#
# 3) spec.functions -be "describe_" "it_" -- bak_
# Backup all describe_* and it_* functions to bak_describe_* and
# bak_it_* and erases the original describe_* and it_*
#
# 4) spec.functions -r bak_
# Find all bak_* functions and copies them without the prefix bak_.
#
# AUTHORS
# Jorge Bucaran <@bucaran>
#/
function spec.functions
# Parse custom options
set -l backup
set -l prefix
set -l restore
set -l quiet
set -l erase
set -l keys
for index in (seq (count $argv))
switch $argv[$index]
case -q --quiet
set quiet -q
# N-switch-fallthrough pattern in fish.
case -b\* -r\* -e\*
switch $argv[$index]
case -b -be -eb --backup
set backup -b
if set -l separator (contains -i -- "--" $argv[$index..-1])
set prefix $argv[(math $separator + 1)]
else
set prefix $argv[(math $index + 2)]
end
end
switch $argv[$index]
case -e -be -eb --erase -re -er
set erase -e
end
switch $argv[$index]
case -r -re -er --restore
# Using restore takes only one argument, <prefix>
set restore -r
set prefix $argv[(math $index + 1)]
end
case \*
set keys $keys $argv[$index]
end
end
# Skip empty strings to avoid fetching all global functions.
if [ -n "$keys" ]
if [ -n "$restore" -a -n "$prefix" ]
set keys $prefix
end
set -l list
for key in $keys
set list $list (functions -n | grep \^"$key")
end
if [ -n "$list" ]
if [ -n "$erase" -o -n "$prefix" ]
for item in $list
if [ -n "$backup" -a "$prefix" ]
functions -c $item $prefix$item
end
if [ -n "$restore" -a "$prefix" ]
# Cut prefix from function and create a new copy.
functions -c $item (echo $item | \
cut -c (echo $prefix | awk '{ print length + 1 }')-)
end
if [ -n "$erase" ]
functions -e $item
end
end
else if [ -z "$quiet" ]
printf "%s\n" $list
end
return 0
end
end
end
# NAME
# spec.run - run a suite of tests
#
# SYNOPSIS
# spec.run [OPTIONS]
#
# OPTIONS
# -v --verbose
# Print full test output.
#
# DESCRIPTION
# In order to run tests create the test file, import plugins/spec at
# before adding any of the functions described above and call spec.run.
#
# FUNCTIONS
# function before_all Run before any tests are run.
# function before_each Run before each test.
# function describe_* Use to organize different specs.
# function it_* Use to test your library/plugin.
# function after_each Run after each test.
# function after_all Run after all tests are finished.
#
# NOTES
# After each test is evaluated, the function is erased from the scope by
# spec.eval to guarantee that subsequent describe blocks will not end up
# calling the previous describe's batch of tests.
#
# The fish-spec library is no different from other Oh-My-Fish plugins.
# Use `import plugins/fish-spec` at the top of your spec file and call
#
# spec.run $argv
#
# After your suite of tests.
#
# EXAMPLES
# import plugins/fish-spec
# function describe_erase
# function before_each
# set -g nums 1 2 3
# end
# function it_erases_one_item -d "It should erase an item from a list."
# erase 1 --from nums
# expect $nums --to-not-contain 1
# end
# end
# spec.run --verbose
#
# AUTHORS
# Bruno Pinto <@pfbruno>
# Jorge Bucaran <@bucaran>
#/
function spec.run
set -l result 0
set -l tests ""
set -l describes (spec.functions describe_)
# Load this suite unique set of tests.
for describe in $describes
spec.eval $describe --header $argv
spec.eval before_all $argv
set tests (spec.functions it_)
set -l failed 0
for test in $tests
spec.eval before_each $argv
if not spec.eval $test --tab 1 $argv
set result 1 # Flunk!
set failed (math 1+$failed)
end
spec.eval after_each $argv
end
spec.eval after_all $argv
if contains -- $argv[1] -v --verbose
spec.view --report (count $tests) $failed
end
# Clean up methods after all tests are finished.
spec.functions -e it_ before_ after_
end
if [ -z "$describes" -o -z "$tests" ]
echo "No tests found."
return 1
end
spec.functions -e describe_
return $result
end
# NAME
# spec.view - print test output
#
# SYNOPSIS
# spec.view <test> <result> [OPTIONS] -- <output>
# spec.view -r --report <test count> <failed tests>
#
# OPTIONS
# -r --report
# Print a passed / failed diagnostics report. Verbose assumed.
#
# -v --verbose
# Print test full output.
#
# -h --header
#
# -t --tab
# Use to specify the tab indentation of nested tests inside suites.
#
# AUTHORS
# Jorge Bucaran <@bucaran>
#/
function spec.view
# Redefine these colors to customize the report.
set -l _color_default @white
set -l _color_pass @springgreen
set -l _color_info @lgray
set -l _color_fail @red
set -l _color_fail_info @black:yellow
set -l _color_dump 555
set -l verbose ""
if contains -- $argv[1] -r --report
set -l total_tests $argv[2]
set -l failed_tests $argv[3]
set -l passed_tests (math $total_tests - $failed_tests)
test $passed_tests -gt 0
and msg \n $_color_pass "$passed_tests passing"
test $failed_tests -gt 0
and msg $_color_fail "$failed_tests failing"
echo # Blank link
return 0
end
# Use test name or -d description field if available.
set -l info (type $argv[1] \
| head -n 2 \
| tail -n 1 \
| cut -d" " -f4- \
| sed "s/^\'//g" \
| sed "s/\'\$//g")
if [ -z "$info" ]
set info (echo $argv[1] | tr "_" " ")
end
set -l result $argv[2]
set -l output
# Parse format options.
set -l tab 1
set -l header ""
if set -q argv[3]
for index in (seq 3 (count $argv))
switch "$argv[$index]"
case -v --verbose
set verbose -v
case -h --header
set header $info
case -t --tab
set tab $argv[(math $index + 1)]
case --
if [ $index -lt (count $argv) ]
set output $argv[(math $index + 1)..-1]
end
break
end
end
end
# Print a header if available.
if [ -n "$header" -a "$verbose" ]
msg $_color_default _$header\_
end
# Process test functions with output. Typically it_ tests using `expect`.
if [ -n "$output" ]
set tab (printf " %.0s" (seq $tab))
# Process succesful tests.
if [ $result -eq 0 ]
if [ -n "$verbose" ]
msg $tab $_color_pass ✔ $_color_info $info
else
echo -n (set_color 00FF7F).
end
else
msg $tab $_color_fail ✖ $_color_fail_info $info
# Error dump parser, split output by \t.
set -l index (contains -i -- \t $output)
# Transform condition string to TitleCase
set condition (echo $output[(math $index+1)] \
| tr "-" " " \
| cut -c 3- \
| awk '{for(j=1;j<=NF;j++){ $j=toupper(substr($j,1,1)) substr($j,2) }}1')
msg $tab __Expected__
printf (set_color $_color_dump)"$tab %s\n" $output[1..(math $index-1)]
msg $tab $condition
printf (set_color $_color_dump)"$tab %s\n" $output[(math $index+2)..-1]
end
end
end
import plugins/fish-spec
function describe_expect
function before_each
set -e result
end
function it_is_false_when_comparison_does_not_exist
echo (expect true --invalid-comparison; set result $status) >/dev/null
expect $result --to-equal 1
end
end
spec.run $argv
import plugins/fish-spec
function describe_expect_to_be_false
function it_returns_1_when_evaluated_value_is_0
expect true --to-be-false
expect $status --to-equal 1
end
function it_returns_0_when_evaluated_value_is_1
expect false --to-be-false
expect $status --to-equal 0
end
function it_returns_1_when_evaluated_function_returns_0
expect "eval true" --to-be-false
expect $status --to-equal 1
end
function it_returns_0_when_evaluated_function_returns_1
expect "eval false" --to-be-false
expect $status --to-equal 0
end
end
spec.run $argv
import plugins/fish-spec
function describe_expect_to_be_true
function it_returns_0_when_evaluated_value_returns_0
expect true --to-be-true
expect $status --to-equal 0
end
function it_returns_1_when_evaluated_value_returns_1
expect false --to-be-true
expect $status --to-equal 1
end
function it_returns_0_when_evaluated_function_returns_0
expect "eval true" --to-be-true
expect $status --to-equal 0
end
function it_returns_1_when_evaluated_function_returns_1
expect "eval false" --to-be-true
expect $status --to-equal 1
end
end
spec.run $argv
import plugins/fish-spec
function describe_expect_to_contain_all
function it_returns_0_when_lists_are_the_same
expect 1 2 --to-contain-all 1 2
expect $status --to-equal 0
end
function it_returns_1_when_lists_are_different
expect 1 2 --to-contain-all 8 9
expect $status --to-equal 1
end
function it_returns_0_when_lists_have_the_same_item_but_in_different_order
expect 1 2 --to-contain-all 2 1
expect $status --to-equal 0
end
function it_returns_0_when_expected_list_contains_the_item
expect 1 2 --to-contain-all 1
expect $status --to-equal 0
end
function it_returns_1_when_expected_list_does_not_contain_the_item
expect 1 2 --to-contain-all 9
expect $status --to-equal 1
end
function it_returns_0_when_expected_list_contains_all_items
expect 1 2 3 --to-contain-all 1 2
expect $status --to-equal 0
end
function it_returns_1_when_expected_list_does_not_contain_all_items
expect 1 2 3 --to-contain-all 1 2 9
expect $status --to-equal 1
end
function it_returns_1_when_expected_list_contains_less_items
expect 1 2 --to-contain-all 1 2 9
expect $status --to-equal 1
end
end
spec.run $argv
import plugins/fish-spec
function describe_expect_to_equal
function it_returns_0_when_compared_values_are_the_same
expect 'equal' --to-equal 'equal'
expect $status --to-equal 0
end
function it_returns_1_when_compared_values_are_different
expect 'equal' --to-equal 'different'
expect $status --to-equal 1
end
function it_returns_0_when_list_items_are_in_the_same_order
expect 1 2 --to-equal 1 2
expect $status --to-equal 0
end
function it_returns_1_when_list_items_are_in_different_order
expect 1 2 --to-equal 2 1
expect $status --to-equal 1
end
end
spec.run $argv
import plugins/fish-spec
function describe_expect_to_not_contain_all
function it_is_false_when_lists_are_the_same
expect 1 2 --to-not-contain-all 1 2
expect $status --to-equal 1
end
function it_is_true_when_lists_are_different
expect 1 2 --to-not-contain-all 8 9
expect $status --to-equal 0
end
function it_is_false_when_lists_have_the_same_items_but_in_different_order
expect 1 2 --to-not-contain-all 2 1
expect $status --to-equal 1
end
function it_is_false_when_expected_list_contains_an_item
expect 1 2 --to-not-contain-all 1
expect $status --to-equal 1
end
function it_is_true_when_expected_list_does_not_contain_an_item
expect 1 2 --to-not-contain-all 9
expect $status --to-equal 0
end
function it_is_false_when_expected_list_contains_all_items
expect 1 2 3 --to-not-contain-all 1 2
expect $status --to-equal 1
end
function it_is_true_when_expected_array_does_not_contain_any_items
expect 1 2 3 --to-not-contain-all 8 9
expect $status --to-equal 0
end
function it_is_true_when_expected_array_contains_less_items
expect 1 2 --to-not-contain-all 1 2 9
expect $status --to-equal 0
end
end
spec.run $argv
import plugins/fish-spec
function describe_list.erase
function before_each
set -g nums_until_10 1 2 3 4 5 6 7 8 9 10
set -g odds_until_10 1 3 5 7 9
end
function it_erases_one_element
list.erase 1 nums_until_10
expect $nums_until_10 --to-not-contain-all 1
end
function it_erases_one_element_without_from_option
list.erase 1 --from nums_until_10
expect $nums_until_10 --to-not-contain-all 1
end
function it_erases_one_element_from_multiple_lists
list.erase 1 --from nums_until_10 odds_until_10
expect $nums_until_10 --to-not-contain-all 1
and expect $odds_until_10 --to-not-contain-all 1
end
function it_erases_one_element_from_multiple_lists_when_only_one_has_the_element
list.erase 2 --from nums_until_10 odds_until_10
expect $nums_until_10 --to-not-contain-all 2
end
function it_erases_multiple_elements
list.erase 1 2 nums_until_10
expect $nums_until_10 --to-not-contain-all 1
and expect $nums_until_10 --to-not-contain-all 2
end
function it_erases_multiple_elements_with_from_syntax
list.erase 1 2 --from nums_until_10
expect $nums_until_10 --to-not-contain-all 1
and expect $nums_until_10 --to-not-contain-all 2
end
function it_erases_multiple_elements_from_multiple_lists
list.erase 1 2 --from nums_until_10 odds_until_10
expect $nums_until_10 --to-not-contain-all 1
and expect $nums_until_10 --to-not-contain-all 2
and expect $odds_until_10 --to-not-contain-all 1
end
function it_returns_0_if_any_items_are_erased
list.erase 10 --from nums_until_10
expect $status --to-equal 0
end
function it_returns_1_if_no_items_are_erased
list.erase 100 200 300 --from nums_until_10
expect $status --to-equal 1
end
function it_returns_1_if_no_items_are_erased_from_any_lists
list.erase 100 200 300 --from nums_until_10 odds_until_10
expect $status --to-equal 1
end
function it_returns_0_if_items_are_erased_from_some_but_not_all_lists
list.erase 1 2 3 --from nums_until_10 odds_until_10
expect $status --to-equal 0
end
end
spec.run $argv
import plugins/fish-spec
function describe_fish-spec
function it_has_an_output_if_suite_is_blank
set -l suite "
import plugins/fish-spec
spec.run
"
expect (run_nested_suite $suite) --to-equal "No tests found."
end
function it_has_an_output_if_there_are_no_tests
set -l suite "
import plugins/fish-spec
function describe_blank_suite
end
spec.run
"
expect (run_nested_suite $suite) --to-equal "No tests found."
end
function it_runs_all_describe_blocks
set -l suite "
import plugins/fish-spec
function describe_blank_suite
echo 'first describe'
end
function describe_another_blank_suite
echo 'second describe'
end
spec.run
"
expect (run_nested_suite $suite) --to-contain-all 'first describe' 'second describe'
end
function it_runs_all_it_blocks
set -l suite "
import plugins/fish-spec
function describe_suite
function it_a_test
echo 'first test'
end
end
function describe_another_suite
function it_another_test
echo 'second test'
end
end
spec.run
"
expect (run_nested_suite $suite) --to-contain-all 'first test' 'second test'
end
function it_adds_a_dot_for_a_successful_expectation
set -l suite "
import plugins/fish-spec
function describe_suite
function it_is_executed
expect 'success' --to-equal 'success'
end
end
spec.run
"
expect (run_nested_suite $suite) --to-equal (dot)
end
function it_adds_a_dot_for_each_successful_test
set -l suite "
import plugins/fish-spec
function describe_suite
function it_is_executed
expect 'success' --to-equal 'success'
end
function it_is_executed_again
expect 'success' --to-equal 'success'
end
end
spec.run
"
expect (run_nested_suite $suite) --to-equal (dot)(dot)
end
function it_only_adds_a_dot_once_for_each_successful_test
set -l suite "
import plugins/fish-spec
function describe_suite
function it_is_executed
expect 'success' --to-equal 'success'
expect 'success' --to-equal 'success'
end
end
spec.run
"
expect (run_nested_suite $suite) --to-equal (dot)
end
function it_allows_debugging_messages_to_be_echoed_inside_a_test
set -l suite "
import plugins/fish-spec
function describe_suite
function it_is_executed
echo 'I can see this'
end
end
spec.run
"
set -l output (run_nested_suite $suite)
expect "$output" --to-contain-all 'I can see this'
end
end
function run_nested_suite -a suite
# Erase and backup original suite functions to avoid an infinite loop.
spec.functions -eb it_ describe_ -- "backup."
# Run nested suite
eval $suite
set -l result $status
# Erase functions created by the nested suite
spec.functions -e it_ describe_
# Restore original suite functions
spec.functions -re backup.
return $result
end
function dot
echo -ne (set_color 00FF7F).
end
spec.run $argv
# NAME
# omf - Oh My Fish helper
#
# DESCRIPTION
# Extend fish binary to support plugins and themes installation
#
function omf -d "Oh My Fish helper"
if test (count $argv) -gt 0
switch $argv[1]
case 'install'
omf.packages --install
case 'update'
omf.packages --update
case 'list' 'ls'
omf.packages --list
case 'self-update'
omf.git --update $fish_path
if [ $status -eq 0 ]
omf.log 'green' 'Oh My Fish has been successfully updated.'
end
case 'plugins'
omf.packages --plugins
case 'themes'
omf.packages --themes
case '*'
omf.helper
end
else
omf.helper
end
end
function omf.git
switch $argv[1]
case '--clone'
set -l repo_url $argv[2]
set -l path $argv[3]
git clone --quiet $repo_url $path ^ /tmp/oh-my-fish.clone.log
case '--update'
set -l path $argv[2]
return (pushd $path; and git pull --quiet --rebase > /dev/null
echo $status
popd > /dev/null)
case '*'
omf.log red 'Unknown option'
end
end
# NAME
# omf.helper - Prints Oh My Fish help
#
# DESCRIPTION
# Prints all functions supported by Oh My Fish helper
#
function omf.helper -d 'Prints all functions supported by Oh My Fish helper'
omf.log normal 'Oh My Fish is a package manager for fish shell. This is a'
omf.log normal 'basic help message containing pointers to more information.'
omf.log normal ''
omf.log normal ' Examples:'
omf.log normal ' omf install'
omf.log normal ' omf update'
omf.log normal ' omf list'
omf.log normal ' omf self-update'
omf.log normal ' omf plugins'
omf.log normal ' omf themes'
end
# NAME
# omf.log - simple log with color
#
# SYNOPSIS
# <string> [<string>...]
#
# DESCRIPTION
# Simply log a message with a specified color.
#
function omf.log -d "Simple log with color"
switch $argv[1]
case '-*'
echo $argv[1] (set_color $argv[2])$argv[3..-1](set_color normal)
case '*'
echo -e (set_color $argv[1])$argv[2..-1](set_color normal)
end
end
# NAME
# omf.packages - Manage all plugins and themes
#
# SYNOPSIS
# omf.packages [OPTIONS]
#
# OPTIONS
# --install
# Install all packages
# --install --plugin|--theme NAME
# Install one theme/plugin
# --update
# Update all packages
# --list
# List all active packages
# --plugins
# List all plugins available from the oh-my-fish Github repository
# --themes
# List all themes available from the oh-my-fish Github repository
#
# DESCRIPTION
# Manage all plugins and themes specified on the $fish_plugins
# and $fish_theme variables
#
function omf.packages --argument-names options arg1 arg2 -d 'Manage all plugins and themes'
set -g __omf_packages_modified 0
switch $options
case '--install'
switch "$arg1"
case '--plugin'
omf.packages.install --plugin $arg2
case '--theme'
omf.packages.install --theme $arg2
case ""
for plugin in $fish_plugins
omf.packages.install --plugin $plugin
end
omf.packages.install --theme $fish_theme
if [ $__omf_packages_modified -eq 0 ]
omf.log green 'All packages were already installed.'
end
end
case '--update'
for plugin in $fish_plugins
omf.packages.update --plugin $plugin
end
omf.packages.update --theme $fish_theme
if [ $__omf_packages_modified -eq 0 ]
omf.log green 'All packages were already updated'
end
case '--list'
omf.log yellow 'Plugins: '
if test -n "$fish_plugins"
omf.log normal $fish_plugins
end
omf.log normal ''
omf.log yellow 'Theme: '
if test -n "$fish_theme"
omf.log normal $fish_theme
end
case '--plugins'
omf.remote --plugins
case '--themes'
omf.remote --themes
case '*'
omf.log red 'Unknown option'
end
end
function omf.packages.report.installing -e omf_package_installing
omf.log -n white "Installing $argv... "
end
function omf.packages.report.updating -e omf_package_updating
omf.log -n white "Updating $argv... "
end
function omf.packages.report.failed -e omf_package_install_failed -e omf_package_update_failed
omf.log red "✖"
set_color yellow
cat /tmp/oh-my-fish.clone.log
echo -e ''
set_color normal
set __omf_packages_modified (expr $__omf_packages_modified + 1)
end
function omf.packages.report.finished -e omf_package_installed -e omf_package_updated
omf.log green "✔"
set __omf_packages_modified (expr $__omf_packages_modified + 1)
end
# NAME
# omf.packages.install - Install a plugin or theme
#
# SYNOPSIS
# --plugin <plugin_name>
# --theme <theme_name>
#
# DESCRIPTION
# Install a plugin or theme
#
function omf.packages.install --argument-names type name -d "Install a plugin or theme"
switch $type
case '--plugin'
if [ -e $fish_path/plugins/$name -o -e $fish_custom/plugins/$name ]
# Plugin is already installed. Skipping.
else
emit omf_package_installing $name
omf.git --clone "https://github.com/oh-my-fish/plugin-$name" $fish_path/plugins/$name
if [ $status -eq 0 ]
emit omf_package_installed $name
else
emit omf_package_install_failed $name
end
end
case '--theme'
if [ -e $fish_path/themes/$name -o -e $fish_custom/themes/$name ]
# Theme is already installed. Skipping.
else
emit omf_package_installing $name
omf.git --clone "https://github.com/oh-my-fish/theme-$name" $fish_path/themes/$name
if [ $status -eq 0 ]
emit omf_package_installed $name
else
emit omf_package_install_failed $name
end
end
case '*'
omf.log red 'Unknown option'
end
end
# NAME
# omf.packages.update - Update a plugin or theme
#
# SYNOPSIS
# --plugin <plugin_name>
# --theme <theme_name>
#
# DESCRIPTION
# Update a plugin or theme
#
function omf.packages.update --argument-names type name -d "Update a plugin or theme"
pushd # Save current dir
switch $type
case '--plugin'
if [ -e $fish_path/plugins/$name -a -e $fish_path/plugins/$name/.git ]
emit omf_package_updating $name
omf.git --update $fish_path/plugins/$name
emit omf_package_updated $name
else
if [ -e $fish_custom/plugins/$name -a -e $fish_custom/plugins/$name/.git ]
emit omf_package_updating $name
omf.git --update $fish_path/plugins/$name
emit omf_package_updated $name
else
# Plugin is not installed or not a git repo. Skipping.
end
end
case '--theme'
if [ -e $fish_path/themes/$name -a -e $fish_path/themes/$name/.git ]
emit omf_package_updating $name
omf.git --update $fish_path/themes/$name
emit omf_package_updated $name
else
if [ -e $fish_custom/themes/$name -a -e $fish_custom/themes/$name/.git ]
emit omf_package_updating $name
omf.git --update $fish_custom/themes/$name
emit omf_package_updated $name
else
# Theme is not installed or not a git repo. Skipping.
end
end
case '*'
omf.log red 'Unknown option'
end
popd # Restore current dir
end
# NAME
# omf.remote - List remote plugins and themes
#
# SYNOPSIS
# omf.remote [OPTIONS]
#
# OPTIONS
# --plugins
# List all available plugins
# --themes
# List all available themes
#
# DESCRIPTION
# List remote plugins and themes from the oh-my-fish Github repository
#
function omf.remote --argument-names options -d 'List remote plugins and themes'
set url "https://api.github.com/orgs/oh-my-fish/repos"
set page_count (curl -sI "$url?page=1&per_page=100" | grep "^Link" | sed 's/Link:.*page=\([0-9]*\)&per_page=100>; rel="last".*/\1/')
if echo $page_count | grep -vE '^[0-9]+$'
echo "Could not access Github API" >&2
return 1
end
set repos ""
for i in (seq $page_count)
set answer (curl -s "$url?page=$i&per_page=100" | grep '"name"' | tr '":' " " | awk '{print $2}')
set repos "$answer $repos"
end
switch $options
case '--plugins'
echo $repos | tr ' ' "\\n" | grep "plugin-" | cut -d "-" -f 2- | sort | paste -sd " " -
case '--themes'
echo $repos | tr ' ' "\\n" | grep "theme-" | cut -d "-" -f 2- | sort | paste -sd " " -
case '*'
omf.log red 'Unknown option'
end
end
#!/usr/bin/env bash
if [ "$TRAVIS_OS_NAME" = "linux" ]; then
ppa=ppa:fish-shell/$FISH_PPA
sudo add-apt-repository -y $ppa
sudo apt-get update
sudo apt-get -y install fish
else
brew install fish $BREW_OPTIONS
fi
curl -L https://github.com/$TRAVIS_REPO_SLUG/raw/$TRAVIS_BRANCH/tools/install.fish | fish
#!/usr/bin/env fish
set -l result 0
for test in (find $fish_path -type f -print | grep "spec.fish")
fish $test $argv
or set result 1
end
exit $result
import plugins/fish-spec
function describe_import
function before_all
set -g fish_function_path_bak $fish_function_path
list.erase "$fish_path/plugins/archlinux" --from fish_function_path
list.erase "$fish_path/plugins/git-flow" --from fish_function_path
list.erase "$fish_path/plugins/tiny" --from fish_function_path
end
function after_all
set fish_function_path $fish_function_path_bak
end
function it_imports_all_fish_files
import plugins/tiny
expect $fish_function_path --to-contain-all $fish_path/plugins/tiny
end
function it_imports_all_fish_files_recursively
import plugins/archlinux
expect $fish_function_path --to-contain-all $fish_path/plugins/archlinux/pacman
end
function it_does_not_import_test_files
import plugins/tiny
expect $fish_function_path --to-not-contain-all $fish_path/plugins/spec
end
function it_does_not_import_completion_files
import plugins/git-flow
expect $fish_function_path --to-not-contain-all $fish_path/plugins/git-flow/completions/
end
function it_adds_completion_files_to_completion_path
import plugins/git-flow
expect $fish_complete_path --to-contain-all $fish_path/plugins/git-flow/completions
end
function it_adds_completion_files_for_custom_plugins_to_completion_path
import plugins/example
expect $fish_complete_path --to-contain-all $fish_custom/plugins/example/completions
end
end
spec.run $argv
import plugins/fish-spec
function describe_oh_my_fish
function before_all
set -g fish_custom_bak $fish_custom
set -g fish_plugins_bak $fish_plugins
set -g fish_function_path_bak $fish_function_path
end
function after_all
set fish_custom $fish_custom_bak
set fish_plugins $fish_plugins_bak
set fish_function_path $fish_function_path_bak
end
function it_has_a_default_custom_directory
set -e fish_custom
load_oh_my_fish
expect $fish_custom --to-equal "$HOME/.oh-my-fish/custom"
end
function it_allows_the_custom_folder_location_to_be_customized
set -g fish_custom /tmp
load_oh_my_fish
expect $fish_custom --to-equal '/tmp'
end
function it_loads_all_custom_files
set -g fish_custom /tmp
echo 'set -gx TEST_LOAD_CUSTOM_FILE file_loaded' > $fish_custom/test.load
load_oh_my_fish
expect $TEST_LOAD_CUSTOM_FILE --to-equal 'file_loaded'
end
function it_loads_all_oh_my_fish_functions
list.erase "$fish_path/functions/" --from fish_function_path
load_oh_my_fish
expect $fish_function_path --to-contain-all $fish_path/functions/
end
function it_loads_all_selected_plugins
list.erase "$fish_path/plugins/bak" \
"$fish_path/plugins/z" --from fish_function_path
set -g fish_plugins bak z
load_oh_my_fish
expect $fish_function_path --to-contain-all $fish_path/plugins/bak
expect $fish_function_path --to-contain-all $fish_path/plugins/z
end
function it_loads_the_selected_theme
list.erase "$fish_path/themes/l" --from fish_function_path
set fish_theme l
load_oh_my_fish
expect $fish_function_path --to-contain-all $fish_path/themes/l
end
function it_reloads_with_status_of_0
load_oh_my_fish
expect $status --to-equal 0
end
end
function load_oh_my_fish
. $fish_path/oh-my-fish.fish
end
spec.run $argv
# Path to your oh-my-fish.
set fish_path $HOME/.oh-my-fish
# Path to your custom folder (default path is ~/.oh-my-fish/custom)
#set fish_custom $HOME/dotfiles/oh-my-fish
# Load oh-my-fish configuration.
. $fish_path/oh-my-fish.fish
# Custom plugins and themes may be added to ~/.oh-my-fish/custom
# Plugins and themes can be found at https://github.com/oh-my-fish/
Theme 'robbyrussell'
Plugin 'theme'
#!/usr/bin/env fish
#
# Oh-my-fish is a user-friendly framework for managing your fish-shell
# configuration. It includes optional plugins (brew, git, rails, python,
# node, etc) and themes.
#
# Get the party started with:
#
# curl -L https://github.com/oh-my-fish/oh-my-fish/raw/master/tools/install.fish \
# | fish
#
# Oh-My-Fish currently supports
#
# - Fish 2.0+ [fishshell.com] [github.com/fish-shell/fish-shell]
#
# The installation process is split up in the following steps:
#
# 1. Resolve source repository to default or get from environment variable.
# This allows installers curl -L ..install.fish | TRAVIS_REPO_SLUG=<fork> fish in
# order to test forks of the framework.
#
# 2. Check for already installed copies of Oh-My-Fish. Do not reinstall.
#
# 3. Attempt to pull repository via git clone, if git is not available,
# curl a HTTP GET request directly from github.
#
# 4. Backup original configuration file if there is one and copy new
# configuration file from templates/.
#
# 5. Print fish logo.
#
# 6. Start prompt if the terminal is interactive
#/
set fish_path ~/.oh-my-fish
set config_path ~/.config/fish
# Log a color message.
# log <color> <string>...
function log
echo -e (set_color $argv[1])$argv[2..-1](set_color normal)
end
log white "Installing Oh My Fish..."
# Allow installers to specify the source repository.
if not set -q TRAVIS_REPO_SLUG
set TRAVIS_REPO_SLUG oh-my-fish/oh-my-fish
set TRAVIS_BRANCH master
end
# Abort installation if oh-my-fish is already installed.
if test -d $fish_path
log yellow "You already have Oh My Fish installed."
log white "Remove $fish_path if you want to reinstall it."
exit 1
end
# Either git clone or curl GET repository.
log blue "Cloning Oh My Fish from remote repository..."
if type git >/dev/null
git clone -b $TRAVIS_BRANCH "https://github.com/$TRAVIS_REPO_SLUG.git" $fish_path
else
log yellow "Install git to pull Oh-My-Fish updates"
log white "Downloading remote zip from Github..."
if curl -sLo $fish_path.zip "https://github.com/$TRAVIS_REPO_SLUG/archive/master.zip"
unzip -q $fish_path.zip
mv "oh-my-fish-master" $fish_path
and log green "Oh-My-Fish succesfully downloaded and extracted to $fish_path"
rm -f $fish_path.zip
else
log red "Oh-My-Fish could not be downloaded."
log white "Report an issue → github.com/oh-my-fish/oh-my-fish/issues"
exit 1
end
end
# Check any existing config.fish files, backup and add custom template.
log blue "Looking for an existing fish config..."
if test -f $config_path/config.fish
log green "Found $config_path/config.fish."
log green "Backing up to $config_path/config.orig"
mv $config_path/config.{fish,orig}
end
log blue "Adding default configuration file to $config_path/config.fish"
cp $fish_path/templates/config.fish $config_path/config.fish
# Print nice fish logo with colors.
log green \
" _
| |
___ | |__ _ __ ___ _ _
/ _ \| _ \ | _ ` _ \| | | |
| (_) | | | | | | | | | | |_| |
\___/|_| |_| |_| |_| |_|\__, |
__/ |
|___/
"
echo " "(set_color F00)"___
___======____="(set_color FF7F00)"-"(set_color FF0)"-"(set_color FF7F00)"-="(set_color F00)")
/T \_"(set_color FF0)"--="(set_color FF7F00)"=="(set_color F00)")
[ \ "(set_color FF7F00)"("(set_color FF0)"0"(set_color FF7F00)") "(set_color F00)"\~ \_"(set_color FF0)"-="(set_color FF7F00)"="(set_color F00)")
\ / )J"(set_color FF7F00)"~~ \\"(set_color FF0)"-="(set_color F00)")
\\\\___/ )JJ"(set_color FF7F00)"~"(set_color FF0)"~~ "(set_color F00)"\)
\_____/JJJ"(set_color FF7F00)"~~"(set_color FF0)"~~ "(set_color F00)"\\
"(set_color FF7F00)"/ "(set_color FF0)"\ "(set_color FF0)", \\"(set_color F00)"J"(set_color FF7F00)"~~~"(set_color FF0)"~~ "(set_color FF7F00)"\\
(-"(set_color FF0)"\)"(set_color F00)"\="(set_color FF7F00)"|"(set_color FF0)"\\\\\\"(set_color FF7F00)"~~"(set_color FF0)"~~ "(set_color FF7F00)"L_"(set_color FF0)"_
"(set_color FF7F00)"("(set_color F00)"\\"(set_color FF7F00)"\\) ("(set_color FF0)"\\"(set_color FF7F00)"\\\)"(set_color F00)"_ "(set_color FF0)"\=="(set_color FF7F00)"__
"(set_color F00)"\V "(set_color FF7F00)"\\\\"(set_color F00)"\) =="(set_color FF7F00)"=_____ "(set_color FF0)"\\\\\\\\"(set_color FF7F00)"\\\\
"(set_color F00)"\V) \_) "(set_color FF7F00)"\\\\"(set_color FF0)"\\\\JJ\\"(set_color FF7F00)"J\)
"(set_color F00)"/"(set_color FF7F00)"J"(set_color FF0)"\\"(set_color FF7F00)"J"(set_color F00)"T\\"(set_color FF7F00)"JJJ"(set_color F00)"J)
(J"(set_color FF7F00)"JJ"(set_color F00)"| \UUU)\\
(UU)"(set_color normal)\n\n
log green "...is now installed."
# Launch fish after installation, loading Oh My Fish for the first time.
# Safeguard for non-interactive terminals, automated installers, etc.
if status --is-interactive
exec fish < /dev/tty
end
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment