Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add hooks system for packages #286

Merged
merged 1 commit into from
Jul 18, 2016
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
60 changes: 46 additions & 14 deletions docs/en-US/Packages.md
Original file line number Diff line number Diff line change
Expand Up @@ -53,42 +53,73 @@ Bear in mind that fish lacks a private scope, so if you need to split your packa

# Hooks

Oh My Fish package API offer some lifecycle hooks, which are completely optional. When using `omf new` command some of them are created with sample code.
Oh My Fish provides a "hooks" system that allows you to write scripts for your package that run when other interesting events occur. Packages can use these hooks to provide advanced installation, custom resource management, etc. Hooks are ordinary Fish scripts named after the event they are triggered by. Most hooks reside in a `hooks` directory inside a package's project directory.

>Hooks that are called at startup time (`init.fish` and `key_bindings.fish`) can slow down shell startup. Be sure to avoid slow code at startup time! Also, if your package doesn't need a hook file, be sure to remove it.

## Initialization
The working directory inside a hook is always set to the root directory of the package. The hooks Oh My Fish currently supports are listed below:

If you want code to be executed when the package loads, you can add code to `init.fish` file at package's root directory:
## `init`

The `init` hook is run once when the shell first loads. Scripts to handle this hook should be located at `init.fish` at package's root directory.

Inside this hook, you can access three package-related variables:

* `$package`: Package name
* `$path`: Package installation path
* `$dependencies`: Package dependencies

For example, with an `init.fish` script containing the following code:

```fish
echo "hello_world initialized"
```

Inside this hook runs you can access three package-related variables:
you will see the line `hello_world initialized` at the top of the terminal when it is first opened.

Use this hook to modify the environment, load resources, autoload functions, etc. If your package does not export any function, you can still use this event to add functionality to your package, or dynamically create functions.

## `key_bindings`

If your package or theme need to use key bindings, be sure to set them up in the `key_bindings` hook. Key binding scripts must be located at `key_bindings.fish` at package's root directory. In this hook you can freely use the [`bind`][fish-bind] command to define custom key bindings.

>Themes can define key bindings too! Oh My Fish will reload key bindings when you switch themes.

## `install`

The `install` hook is triggered when a package is first installed. Scripts for this hook must be located at `hooks/install.fish`.

Inside this hook, you can access two package-related variables:

* `$package`: Package name
* `$path`: Package installation path
* `$dependencies` : Package dependencies

Use this hook to modify the environment, load resources, autoload functions, etc. If your package does not export any function, you can still use this event to add functionality to your package, or dynamically create functions.
This hook is useful for downloading additional resources, setting up Git submodules, or installing third-party dependencies like Bash scripts.

## Key Bindings
## `update`

If your package or theme need to use key bindings, be sure to set them up in `key_bindings.fish`.
As you might have guessed, the `update` hook is triggered for a package after it is updated. Scripts for this hook must be located at `hooks/update.fish`.

>Themes can define key bindings too! Oh My Fish will reload key bindings when you switch themes.
Inside this hook, you can access two package-related variables:

## Uninstall
* `$package`: Package name
* `$path`: Package installation path

This hook is useful for updating Git submodules or checking for new versions of third-party dependencies.

Code inside `uninstall.fish` hook will be called before a package is removed via `omf remove <pkg>`.
## `uninstall`

>Packages can use this hook to clean up custom resources, etc.
The `uninstall` hook will be triggered before a package is removed via `omf remove <pkg>`. Scripts for this hook must be located at `hooks/uninstall.fish`.

Inside this hook you can access one package-related variable:
Inside this hook, you can access two package-related variables:

* `$package`: Package name
* `$path`: Package installation path

Packages can use this hook to clean up custom resources, etc.

>Note: for backwards-compatibility, uninstall hooks will also be run if they are located at `uninstall.fish` in the package root.

# Make it public

Oh My Fish keeps a registry of public packages under `$OMF_PATH/db/`.
Expand All @@ -108,4 +139,5 @@ This will add a new entry to your local copy of the registry. Now you just need
>When sending pull requests with package URL under Oh My Fish organization (https://github.com/oh-my-fish) we will allocate a repository inside the organization so you can push your work and join the community! :tada:


[omf-pulls-link]: https://github.com/oh-my-fish/oh-my-fish/pulls
[fish-bind]: http://fishshell.com/docs/current/commands.html#bind
[omf-pulls-link]: https://github.com/oh-my-fish/oh-my-fish/pulls
7 changes: 7 additions & 0 deletions pkg/omf/functions/packages/omf.packages.install.fish
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,13 @@ function omf.packages.install -a name_or_url
if omf.repo.clone $url $OMF_PATH/$parent_path/$name
omf.bundle.install $OMF_PATH/$parent_path/$name/bundle
omf.bundle.add $install_type $name_or_url

# Run the install hook.
if not omf.packages.run_hook $OMF_PATH/$parent_path/$name install
__omf.packages.install.error "$install_type $name"
return $OMF_UNKNOWN_ERR
end

__omf.packages.install.success "$install_type $name"

if test "$install_type" = theme
Expand Down
2 changes: 2 additions & 0 deletions pkg/omf/functions/packages/omf.packages.remove.fish
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,8 @@ function omf.packages.remove -a pkg
and set found;
or continue

# Run uninstall hook first.
omf.packages.run_hook $path uninstall
source $path/uninstall.fish ^/dev/null;
and emit uninstall_$pkg

Expand Down
13 changes: 13 additions & 0 deletions pkg/omf/functions/packages/omf.packages.run_hook.fish
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
function omf.packages.run_hook -a path hook
set -l hook_script "$path/hooks/$hook.fish"
set package (basename $path)

if test -e "$hook_script"
pushd $path
source "$hook_script"
set -l code $status
popd

return $code
end
end
32 changes: 19 additions & 13 deletions pkg/omf/functions/packages/omf.packages.update.fish
Original file line number Diff line number Diff line change
Expand Up @@ -4,21 +4,27 @@ function omf.packages.update -a name
return 1
end

# Skip packages outside version control
not test -e $target_path/.git;
and return 0
# Only pull packages in version control
if test -e $target_path/.git
omf.repo.pull $target_path
switch $status
case 0
omf.bundle.install $target_path/bundle
set result (omf::em)"$name successfully updated."(omf::off)
case 1
echo (omf::err)"Could not update $name."(omf::off) 1>&2
return 1
case 2
set result (omf::dim)"$name is already up-to-date."(omf::off)
end
end

omf.repo.pull $target_path
switch $status
case 0
omf.bundle.install $target_path/bundle
echo (omf::em)"$name successfully updated."(omf::off)
case 1
echo (omf::err)"Could not update $name."(omf::off) 1>&2
return 1
case 2
echo (omf::dim)"$name is already up-to-date."(omf::off)
# Run update hook.
if not omf.packages.run_hook $target_path update
echo (omf::err)"Could not update $name."(omf::off) 1^&2
return 1
end

echo $result
return 0
end