mirror of https://github.com/jorgebucaran/fisher
Compare commits
220 Commits
Author | SHA1 | Date |
---|---|---|
|
2efd33ccd0 | 10 months ago |
|
4c95fd94c6 | 10 months ago |
|
59228d6215 | 12 months ago |
|
ed7c28ea78 | 1 year ago |
|
dc543b2a65 | 1 year ago |
|
2440ef4ebd | 1 year ago |
|
67bec738db | 1 year ago |
|
5841ec0091 | 1 year ago |
|
4cd902e63f | 1 year ago |
|
4199657495 | 1 year ago |
|
2e8a24614b | 1 year ago |
|
36810b3940 | 2 years ago |
|
53c06c9d2f | 2 years ago |
|
d431f45abc | 2 years ago |
|
c05a169187 | 2 years ago |
|
67a543ef60 | 2 years ago |
|
d92d62457f | 2 years ago |
|
626afefcb0 | 2 years ago |
|
2ef758ec27 | 2 years ago |
|
de3eee489f | 2 years ago |
|
3ae4b29137 | 2 years ago |
|
7c4024da66 | 2 years ago |
|
357d682b10 | 2 years ago |
|
1662b799eb | 2 years ago |
|
604f8ff1ea | 2 years ago |
|
475505312c | 2 years ago |
|
daddbadb79 | 2 years ago |
|
bad0471c4b | 2 years ago |
|
79b1cf17ca | 2 years ago |
|
01af91773f | 2 years ago |
|
7fdb083c60 | 2 years ago |
|
36c1930aa7 | 2 years ago |
|
507c9cc425 | 2 years ago |
|
5622dd660f | 2 years ago |
|
cf4c6cc561 | 2 years ago |
|
b3c5336480 | 2 years ago |
|
a4e74bd6f1 | 2 years ago |
|
164628b696 | 2 years ago |
|
74dabc5d5a | 2 years ago |
|
354c8fccec | 2 years ago |
|
0a0c48993a | 2 years ago |
|
93dafd242b | 3 years ago |
|
1f080b0457 | 3 years ago |
|
885129b7d3 | 3 years ago |
|
b2c317a2ae | 3 years ago |
|
dc7ada7a78 | 3 years ago |
|
c220662604 | 3 years ago |
|
7bd5bfcac1 | 3 years ago |
|
28bb0e172c | 3 years ago |
|
b9b1eda07a | 3 years ago |
|
247b58e0d9 | 3 years ago |
|
e7a538239b | 3 years ago |
|
b222175fc8 | 3 years ago |
|
48c414fa09 | 3 years ago |
|
00f130ed90 | 3 years ago |
|
a0a68de919 | 3 years ago |
|
6cc13ada7e | 3 years ago |
|
8ae139dc9e | 3 years ago |
|
56c629a3a9 | 3 years ago |
|
3f0851c5cb | 3 years ago |
|
94e934d49e | 3 years ago |
|
746ec1a504 | 3 years ago |
|
3e7c4015ab | 3 years ago |
|
a8a8a96287 | 3 years ago |
|
32ed213b4a | 3 years ago |
|
0b8daa2b8f | 3 years ago |
|
9cc7d9582f | 3 years ago |
|
d0c3d1840a | 3 years ago |
|
f4739a8c7d | 3 years ago |
|
57ed19f945 | 3 years ago |
|
7ed1de7e56 | 3 years ago |
|
3e5b263785 | 3 years ago |
|
b9f222c52e | 3 years ago |
|
70c9a59b53 | 3 years ago |
|
09fc107734 | 3 years ago |
|
48a61924ad | 3 years ago |
|
a2e3d5463f | 3 years ago |
|
8f84ee6144 | 3 years ago |
|
b2501f620d | 3 years ago |
|
d1a9ae0f7f | 3 years ago |
|
c8091b3dee | 3 years ago |
|
7a47e294b9 | 3 years ago |
|
aa4e1caca5 | 3 years ago |
|
0e2227019e | 3 years ago |
|
8fde904564 | 3 years ago |
|
da228c9f70 | 3 years ago |
|
c3659bed01 | 3 years ago |
|
3edac36e38 | 4 years ago |
|
72a40f13ce | 4 years ago |
|
fbc117df2d | 4 years ago |
|
6dc9e1237d | 4 years ago |
|
b5650d3ef6 | 4 years ago |
|
fca10da157 | 4 years ago |
|
f24bb10edb | 4 years ago |
|
c9decadc16 | 4 years ago |
|
7d6bd9f9b3 | 4 years ago |
|
ed32770424 | 4 years ago |
|
f5b6254833 | 4 years ago |
|
b4c2fcc68a | 4 years ago |
|
ae423be725 | 4 years ago |
|
285fc352b7 | 4 years ago |
|
f6f2b5d149 | 4 years ago |
|
1644724ef1 | 4 years ago |
|
721ac3f707 | 4 years ago |
|
fb16985935 | 4 years ago |
|
db6801f565 | 4 years ago |
|
6b1a886c58 | 4 years ago |
|
d0c30d9723 | 4 years ago |
|
cd9d69209e | 4 years ago |
|
4ff6128860 | 4 years ago |
|
2bbc06a965 | 4 years ago |
|
eab5c67f0b | 4 years ago |
|
861cd38133 | 4 years ago |
|
cc06470da1 | 4 years ago |
|
f4b32b3419 | 4 years ago |
|
dc63a83c78 | 4 years ago |
|
f26e1d121f | 4 years ago |
|
5368e72863 | 4 years ago |
|
f091c22c60 | 4 years ago |
|
f7c347b5d0 | 4 years ago |
|
3f8552e200 | 4 years ago |
|
ac1b49b43b | 4 years ago |
|
5a81014f22 | 4 years ago |
|
ce6072f907 | 4 years ago |
|
67aa8ed7c7 | 4 years ago |
|
b808e7318a | 4 years ago |
|
210db6a46b | 4 years ago |
|
f5ae081036 | 4 years ago |
|
32781c42dc | 4 years ago |
|
e5d10e0fe6 | 4 years ago |
|
6e3b9d8023 | 4 years ago |
|
dcbf55956e | 4 years ago |
|
f9b91779f3 | 4 years ago |
|
5e454f63bf | 4 years ago |
|
47ba393569 | 4 years ago |
|
e8c48262e1 | 4 years ago |
|
3f0138c097 | 4 years ago |
|
479bb3cd36 | 4 years ago |
|
07b7fc79d7 | 4 years ago |
|
fa598b1ed6 | 4 years ago |
|
83608c228a | 4 years ago |
|
f97dc3b47d | 4 years ago |
|
3077649891 | 4 years ago |
|
882e839110 | 4 years ago |
|
e3ae2ed66a | 4 years ago |
|
bd7b69d47b | 4 years ago |
|
4f2bc7bf01 | 4 years ago |
|
d69311a911 | 4 years ago |
|
08bdf7ed0d | 4 years ago |
|
168004cf1e | 4 years ago |
|
dbf07b1709 | 4 years ago |
|
c2c091f33e | 4 years ago |
|
c84294b06f | 4 years ago |
|
429b99696f | 4 years ago |
|
e2374589ff | 4 years ago |
|
297c6b77c7 | 4 years ago |
|
b9c5b48513 | 4 years ago |
|
fcef567fba | 4 years ago |
|
6cdfadc41e | 4 years ago |
|
d7035f3f4e | 4 years ago |
|
c20d1b3ec3 | 4 years ago |
|
c9393460cf | 4 years ago |
|
9a0679c9ae | 4 years ago |
|
510e6254ee | 4 years ago |
|
994506e594 | 4 years ago |
|
3badc25962 | 4 years ago |
|
d847b79b63 | 4 years ago |
|
c19e4e7d16 | 4 years ago |
|
3decc8e468 | 4 years ago |
|
c2b3ab0171 | 4 years ago |
|
3e4ae4b960 | 4 years ago |
|
c22526cc5a | 4 years ago |
|
3f1d3d7db7 | 4 years ago |
|
a8357adbdc | 4 years ago |
|
df72aa0443 | 4 years ago |
|
017046abf3 | 4 years ago |
|
44405ca9c4 | 4 years ago |
|
47229c1429 | 4 years ago |
|
c142f61e51 | 5 years ago |
|
25ae8be214 | 5 years ago |
|
6d2d4107b4 | 5 years ago |
|
f3e87cf5f6 | 5 years ago |
|
24b4aaa55b | 5 years ago |
|
fe5638d107 | 5 years ago |
|
1e6e80c0c1 | 5 years ago |
|
9bdd1d5e61 | 5 years ago |
|
ae37295f81 | 5 years ago |
|
8b5a422999 | 5 years ago |
|
0b1f270361 | 5 years ago |
|
c66a1db768 | 5 years ago |
|
7b4705f810 | 5 years ago |
|
d3469cfa33 | 5 years ago |
|
b2cd7aee3a | 5 years ago |
|
6ef9c5029c | 5 years ago |
|
05486e8767 | 5 years ago |
|
c7472b2961 | 5 years ago |
|
ae878a8e9c | 6 years ago |
|
9a23976473 | 6 years ago |
|
ee330a8cf1 | 6 years ago |
|
49c3eabf9f | 6 years ago |
|
37a6cd28e3 | 6 years ago |
|
e11cd69f17 | 6 years ago |
|
5ddafed654 | 6 years ago |
|
91417201f4 | 6 years ago |
|
db82938731 | 6 years ago |
|
12ee3cb33e | 6 years ago |
|
972eed7aa8 | 6 years ago |
|
632917c7d2 | 6 years ago |
|
8a99865be5 | 6 years ago |
|
3a13ba9d68 | 6 years ago |
|
975aa989c9 | 6 years ago |
|
fe1cc9805c | 6 years ago |
|
8cb6692785 | 6 years ago |
|
61f679e6a3 | 6 years ago |
|
6401d18504 | 6 years ago |
|
9fc0779339 | 6 years ago |
|
1211e0bafa | 6 years ago |
|
f1890a54d2 | 6 years ago |
|
f1766dcfa0 | 6 years ago |
|
81f03702e6 | 6 years ago |
@ -0,0 +1,22 @@
|
||||
name: CI
|
||||
|
||||
on: push
|
||||
|
||||
jobs:
|
||||
test:
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- name: Install Fish
|
||||
run: |
|
||||
sudo apt-add-repository -yn ppa:fish-shell/release-3
|
||||
sudo apt-get update
|
||||
sudo apt-get install -y fish
|
||||
|
||||
- name: Install Tools
|
||||
run: |
|
||||
source $GITHUB_WORKSPACE/functions/fisher.fish
|
||||
fisher install $GITHUB_WORKSPACE jorgebucaran/fishtape
|
||||
fishtape tests/*.fish
|
||||
shell: fish {0}
|
@ -1,10 +0,0 @@
|
||||
sudo: required
|
||||
before_install:
|
||||
- sudo add-apt-repository -y ppa:fish-shell/nightly-master
|
||||
- sudo apt-get update
|
||||
- sudo apt-get -y install fish
|
||||
script:
|
||||
- curl https://git.io/fisher --create-dirs -sLo ~/.config/fish/functions/fisher.fish
|
||||
- fish -c "fisher version; and fisher help"
|
||||
notifications:
|
||||
email: false
|
@ -1,19 +1,7 @@
|
||||
Copyright © 2016-present [Jorge Bucaran](https://github.com/jorgebucaran)
|
||||
Copyright © Jorge Bucaran <<https://jorgebucaran.com>>
|
||||
|
||||
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:
|
||||
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 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.
|
||||
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.
|
||||
|
@ -1,286 +1,193 @@
|
||||
> ###### ✋ Psst! Migrating from V2 to V3? We got you. Check our [**migration guide**](https://github.com/jorgebucaran/fisher/issues/450) and happy upgrading!
|
||||
|
||||
# Fisher
|
||||
|
||||
[![Build Status](https://img.shields.io/travis/jorgebucaran/fisher.svg)](https://travis-ci.org/jorgebucaran/fisher)
|
||||
[![Releases](https://img.shields.io/github/release/jorgebucaran/fisher.svg?label=latest)](https://github.com/jorgebucaran/fisher/releases)
|
||||
|
||||
Fisher is a package manager for the [fish shell](https://fishshell.com). It defines a common interface for package authors to build and distribute their shell scripts in a portable way. You can use it to extend your shell capabilities, change the look of your prompt and create repeatable configurations across different systems effortlessly.
|
||||
> A plugin manager for [Fish](https://fishshell.com)—your friendly interactive shell. [Snag fresh plugins!](https://github.com/jorgebucaran/awsm.fish#readme)
|
||||
|
||||
Looking for packages? Check the [awesome fish shell](https://github.com/jorgebucaran/awesome-fish-shell) repository to get started.
|
||||
Take control of functions, completions, bindings, and snippets from the command line. Unleash your shell's true potential, perfect your prompt, and craft repeatable configurations across different systems effortlessly. Fisher's zero impact on shell startup keeps your shell zippy and responsive. No gimmicks, just smooth sailing!
|
||||
|
||||
## Features
|
||||
- Fisher is 100% pure-Fish, making it easy to contribute or modify
|
||||
- Scorching fast concurrent plugin downloads that'll make you question reality
|
||||
- Zero configuration needed—we're not kidding!
|
||||
- Oh My Fish! plugins supported too
|
||||
|
||||
- Zero configuration
|
||||
- Oh My Fish package support
|
||||
- High-speed concurrent package downloads⌁!
|
||||
- If you've installed a package before, you can install it again offline
|
||||
- Add, update and remove functions, completions, key bindings and configuration snippets from a variety of sources using the command line, editing your [fishfile](#using-the-fishfile) or both
|
||||
> #### ☝️ [Upgrading from Fisher `3.x` or older? Strap in and read this!](https://github.com/jorgebucaran/fisher/issues/652)
|
||||
|
||||
## Installation
|
||||
|
||||
Download `fisher` to your fish functions directory or any directory in the fish function path.
|
||||
|
||||
```sh
|
||||
curl https://git.io/fisher --create-dirs -sLo ~/.config/fish/functions/fisher.fish
|
||||
```console
|
||||
curl -sL https://raw.githubusercontent.com/jorgebucaran/fisher/main/functions/fisher.fish | source && fisher install jorgebucaran/fisher
|
||||
```
|
||||
|
||||
Your shell can take a few seconds before refreshing the function path. If `fisher` is not immediately available after the download is complete, you can launch a new session, or [replace the current session](https://fishshell.com/docs/current/commands.html#exec) with a new one.
|
||||
|
||||
> **Note:** If the [`XDG_CONFIG_HOME`](https://specifications.freedesktop.org/basedir-spec/basedir-spec-latest.html#variables) environment variable is defined on your system, use `$XDG_CONFIG_HOME/fish` to find the path to your fish configuration directory.
|
||||
|
||||
### Dependencies
|
||||
## Quickstart
|
||||
|
||||
- [fish](https://github.com/fish-shell/fish-shell) 2.2+
|
||||
- [curl](https://github.com/curl/curl) 7.10.3+
|
||||
- [git](https://github.com/git/git) 1.7.12+
|
||||
Fisher lets you install, update, and remove plugins like a boss. Revel in Fish's [tab completion](https://fishshell.com/docs/current/index.html#completion) and rich syntax highlighting while you're at it.
|
||||
|
||||
Stuck in fish 2.0 and can't upgrade your shell? Check our [legacy fish support guide](https://github.com/jorgebucaran/fisher/issues/510) and good luck!
|
||||
### Installing plugins
|
||||
|
||||
### Bootstrap installation
|
||||
To install plugins, use the `install` command and point it to the GitHub repository.
|
||||
|
||||
To automate installing Fisher and the packages listed in your [fishfile](#using-the-fishfile) on a new system, add the following code to your fish configuration file.
|
||||
|
||||
```fish
|
||||
if not functions -q fisher
|
||||
set -q XDG_CONFIG_HOME; or set XDG_CONFIG_HOME ~/.config
|
||||
curl https://git.io/fisher --create-dirs -sLo $XDG_CONFIG_HOME/fish/functions/fisher.fish
|
||||
fish -c fisher
|
||||
end
|
||||
```console
|
||||
fisher install jorgebucaran/nvm.fish
|
||||
```
|
||||
|
||||
### Changing the installation prefix
|
||||
> Wanna install from GitLab? No problemo—just prepend `gitlab.com/` to the plugin path.
|
||||
|
||||
Use the `$fisher_path` environment variable to change the location where functions, completions, and [configuration snippets](#configuration-snippets) will be copied to when a package is installed. The default location will be your fish configuration directory.
|
||||
|
||||
```fish
|
||||
set -g fisher_path /path/to/another/location
|
||||
You can also snag a specific version of a plugin by adding an `@` symbol after the plugin name, followed by a tag, branch, or [commit](https://git-scm.com/docs/gitglossary#Documentation/gitglossary.txt-aiddefcommit-ishacommit-ishalsocommittish).
|
||||
|
||||
set fish_function_path $fish_function_path[1] $fisher_path/functions $fish_function_path[2..-1]
|
||||
set fish_complete_path $fish_complete_path[1] $fisher_path/completions $fish_complete_path[2..-1]
|
||||
|
||||
for file in $fisher_path/conf.d/*.fish
|
||||
builtin source $file 2> /dev/null
|
||||
end
|
||||
```console
|
||||
fisher install IlanCosman/tide@v5
|
||||
```
|
||||
|
||||
Do I need this? It depends. If you want to keep your own functions, completions, and configuration snippets separate from packages installed with Fisher, you can customize the installation prefix. If you prefer to keep everything in the same place, you can skip this.
|
||||
|
||||
## Usage
|
||||
|
||||
You've found an interesting utility you'd like to try out. Or perhaps you've [created a package](#creating-your-own-package) yourself. How do you install it on your system? Now you want to update or remove it. How do you do that?
|
||||
|
||||
You can use Fisher to add, update, and remove packages interactively, taking advantage of fish [tab completion](https://fishshell.com/docs/current/index.html#completion) and syntax highlighting. Or [edit your fishfile](#using-the-fishfile) and commit your changes. Do you prefer a CLI-centered approach, text-based approach, or a mix of both?
|
||||
|
||||
### Adding packages
|
||||
|
||||
Add packages using the `add` command followed by the path to the repository on GitHub.
|
||||
And hey, you can install plugins from a local directory too!
|
||||
|
||||
```
|
||||
fisher add jethrokuan/z rafaelrinaldi/pure
|
||||
```console
|
||||
fisher install ~/path/to/plugin
|
||||
```
|
||||
|
||||
To add a package from anywhere other than GitHub, use the address of the server and the path to the repository. HTTPS is always assumed so you don't need to specify the protocol.
|
||||
> Heads up! Fisher expands plugins into your Fish configuration directory by default, overwriting existing files. If that's not your jam, set `$fisher_path` to your preferred location and put it in your function path ([#640](https://github.com/jorgebucaran/fisher/issues/640)).
|
||||
|
||||
```
|
||||
fisher add gitlab.com/jorgebucaran/mermaid
|
||||
```
|
||||
### Listing plugins
|
||||
|
||||
To add a package from a private repository set the `fisher_user_api_token` variable to your username followed by a colon and your authorization token or password.
|
||||
Use the `list` command to see all your shiny installed plugins.
|
||||
|
||||
```fish
|
||||
set -g fisher_user_api_token jorgebucaran:ce04da9bd93ddb5e729cfff4a58c226322c8d142
|
||||
```console
|
||||
$ fisher list
|
||||
jorgebucaran/fisher
|
||||
ilancosman/tide@v5
|
||||
jorgebucaran/nvm.fish
|
||||
/home/jb/path/to/plugin
|
||||
```
|
||||
|
||||
For a specific version of a package add an `@` symbol after the package name followed by the tag, branch or [commit-ish](https://git-scm.com/docs/gitglossary#gitglossary-aiddefcommit-ishacommit-ishalsocommittish) you want. Only one package version can be installed at any given time.
|
||||
The `list` command also plays nice with regular expressions for filtering the output.
|
||||
|
||||
```
|
||||
fisher add edc/bass@20f73ef jethrokuan/z@pre27
|
||||
```console
|
||||
$ fisher list \^/
|
||||
/home/jb/path/to/plugin
|
||||
```
|
||||
|
||||
You can add packages from a local directory too. Local packages will be copied as [symbolic links](https://en.wikipedia.org/wiki/Symbolic_link) so changes in the original files will be reflected in future shell sessions without having to run `fisher` again.
|
||||
### Updating plugins
|
||||
|
||||
```
|
||||
fisher add ~/path/to/local/pkg
|
||||
```
|
||||
|
||||
### Listing packages
|
||||
|
||||
List all the packages that are currently installed using the `ls` command. This includes packages you didn't install yourself but were installed on your system as a dependency of another package.
|
||||
`update` command to the rescue! It updates one or more plugins to their latest and greatest version.
|
||||
|
||||
```console
|
||||
fisher update jorgebucaran/fisher
|
||||
```
|
||||
fisher ls
|
||||
jethrokuan/z
|
||||
rafaelrinaldi/pure
|
||||
gitlab.com/jorgebucaran/mermaid
|
||||
edc/bass
|
||||
~/path/to/myfish/pkg
|
||||
```
|
||||
|
||||
### Removing packages
|
||||
|
||||
Remove packages using the `rm` command. If a package has dependencies, they too will be removed. If any dependencies are still shared by other packages, they will remain installed.
|
||||
> Just type `fisher update` to update everything in one fell swoop.
|
||||
|
||||
```
|
||||
fisher rm rafaelrinaldi/pure
|
||||
```
|
||||
### Removing plugins
|
||||
|
||||
You can remove everything that is currently installed in one sweep using the following pipeline.
|
||||
Say goodbye to installed plugins with the `remove` command.
|
||||
|
||||
```sh
|
||||
fisher ls | fisher rm
|
||||
```console
|
||||
fisher remove jorgebucaran/nvm.fish
|
||||
```
|
||||
|
||||
### Updating packages
|
||||
|
||||
Run `fisher` to update everything you've installed. There is no dedicated update command. Using the command line to add and remove packages is a facade for modifying and committing changes to your fishfile in a single step.
|
||||
Feeling destructive? Wipe out everything, including Fisher itself.
|
||||
|
||||
Looking for a way to update fisher itself? Use the `self-update` command.
|
||||
|
||||
```
|
||||
fisher self-update
|
||||
```console
|
||||
fisher list | fisher remove
|
||||
```
|
||||
|
||||
### Other commands
|
||||
## Using your `fish_plugins` file
|
||||
|
||||
Use the `help` command to display usage help on the command line.
|
||||
Whenever you install or remove a plugin from the command line, Fisher jots down all the installed plugins in `$__fish_config_dir/fish_plugins`. Add this file to your dotfiles or version control to easily share your configuration across different systems.
|
||||
|
||||
```
|
||||
fisher help
|
||||
```
|
||||
You can also edit this file and run `fisher update` to commit changes like a pro:
|
||||
|
||||
Last but not least, use the `version` command to display the current version of fisher.
|
||||
|
||||
```
|
||||
fisher version
|
||||
```
|
||||
|
||||
### Using the fishfile
|
||||
|
||||
Whenever you add or remove a package from the command line we'll write to a text file in `~/.config/fish/fishfile`. This is your fishfile. It lists every package that is currently installed on your system. You should add this file to your dotfiles or version control if you want to reproduce your configuration on a different system.
|
||||
|
||||
You can edit this file to add or remove packages and run `fisher` to commit your changes. Only the packages listed in this file will be installed after `fisher` returns. If a package is already installed, it will be updated. Everything after a `#` symbol (comments) will be ignored.
|
||||
|
||||
```fish
|
||||
vi ~/.config/fish/fishfile
|
||||
```console
|
||||
$EDITOR $__fish_config_dir/fish_plugins
|
||||
```
|
||||
|
||||
```diff
|
||||
- rafaelrinaldi/pure
|
||||
- jethrokuan/z@pre27
|
||||
gitlab.com/jorgebucaran/mermaid
|
||||
edc/bass
|
||||
+ FabioAntunes/fish-nvm
|
||||
~/path/to/myfish/pkg
|
||||
```
|
||||
|
||||
```
|
||||
fisher
|
||||
jorgebucaran/fisher
|
||||
ilancosman/tide@v5
|
||||
jorgebucaran/nvm.fish
|
||||
+ PatrickF1/fzf.fish
|
||||
- /home/jb/path/to/plugin
|
||||
```
|
||||
|
||||
That will remove **rafaelrinaldi/pure** and **jethrokuan/z**, add **FabioAntunes/fish-nvm** and update the rest.
|
||||
|
||||
## Packages
|
||||
|
||||
Packages help you organize shell scripts into reusable, independent components that can be shared through a git URL or the path to a local directory. Even if your package is not meant to be shared with others, you can benefit from composition and the ability to depend on other packages.
|
||||
|
||||
The structure of a package can be adopted from the fictional project described below. These are the files that fisher looks for when installing or uninstalling a package. Of course, you can elaborate on this to add tests, documentation, and other files such as README and LICENSE files. The name of the root directory can be anything you like.
|
||||
|
||||
```
|
||||
fish-kraken
|
||||
├── fishfile
|
||||
├── functions
|
||||
│ └── kraken.fish
|
||||
├── completions
|
||||
│ └── kraken.fish
|
||||
└── conf.d
|
||||
└── kraken.fish
|
||||
```console
|
||||
fisher update
|
||||
```
|
||||
|
||||
If your project depends on other packages, it should list them as dependencies in a fishfile. There is no need for a fishfile otherwise. The rules concerning the usage of the fishfile are the same rules we've already covered in [using the fishfile](#using-the-fishfile).
|
||||
This will install **PatrickF1**/**fzf.fish**, remove /**home**/**jb**/**path**/**to**/**plugin**, and update everything else.
|
||||
|
||||
While some packages contain every kind of file, some packages contain only functions or configuration snippets. You are not limited to a single file per directory either. There can be as many files as you need or only one as in the next example.
|
||||
## Creating a plugin
|
||||
|
||||
```
|
||||
fish-kraken
|
||||
└── kraken.fish
|
||||
```
|
||||
Plugins can include any number of files in `functions`, `conf.d`, and `completions` directories. Most plugins are just a single function or a [configuration snippet](https://fishshell.com/docs/current/index.html#configuration). Behold the anatomy of a typical plugin:
|
||||
|
||||
The lack of private function scope in fish causes all package functions to share the same namespace. A good rule of thumb is to prefix functions intended for private use with the name of your package to reduce the possibility of conflicts.
|
||||
<pre>
|
||||
<b>flipper</b>
|
||||
├── <b>completions</b>
|
||||
│ └── flipper.fish
|
||||
├── <b>conf.d</b>
|
||||
│ └── flipper.fish
|
||||
└── <b>functions</b>
|
||||
└── flipper.fish
|
||||
</pre>
|
||||
|
||||
### Creating your own package
|
||||
Non `.fish` files and directories inside these locations will be copied to `$fisher_path` under `functions`, `conf.d`, or `completions` respectively.
|
||||
|
||||
The best way to show you how to create your own package is by building one together. Our first example will be a function that prints the raw non-rendered markdown source of a README file from GitHub to standard output. Its inputs will be the name of the owner, repository, and branch. If no branch is specified, we'll use the master branch.
|
||||
### Event system
|
||||
|
||||
Create the following directory structure and function file. Make sure the function name matches the file name, otherwise fish won't be able to autoload it the first time you try to use it.
|
||||
Fish [events](https://fishshell.com/docs/current/cmds/emit.html) notify plugins when they're being installed, updated, or removed.
|
||||
|
||||
```
|
||||
fish-readme
|
||||
└── readme.fish
|
||||
```
|
||||
> Keep in mind, `--on-event` functions must be loaded when their event is emitted. So, place your event handlers in the `conf.d` directory.
|
||||
|
||||
```fish
|
||||
function readme -a owner repo branch
|
||||
if test -z "$branch"
|
||||
set branch master
|
||||
end
|
||||
curl -s https://raw.githubusercontent.com/$owner/$repo/$branch/README.md
|
||||
# Defined in flipper/conf.d/flipper.fish
|
||||
|
||||
function _flipper_install --on-event flipper_install
|
||||
# Set universal variables, create bindings, and other initialization logic.
|
||||
end
|
||||
```
|
||||
|
||||
You can install it with the `add` command followed by the path to the directory.
|
||||
function _flipper_update --on-event flipper_update
|
||||
# Migrate resources, print warnings, and other update logic.
|
||||
end
|
||||
|
||||
```
|
||||
fisher add /absolute/path/to/fish-readme
|
||||
function _flipper_uninstall --on-event flipper_uninstall
|
||||
# Erase "private" functions, variables, bindings, and other uninstall logic.
|
||||
end
|
||||
```
|
||||
|
||||
The next logical step is to share it with others. How do you do that? Fisher is not a package registry. Its function is to fetch fish scripts and put them in place so that your shell can find them. To publish a package put your code online. You can use GitHub, GitLab or BitBucket or anywhere you like.
|
||||
## Creating a theme
|
||||
|
||||
Now let's install the package again, this time from its new location. Open your [fishfile](#using-the-fishfile) and replace the local version of the package we previously added with the URL of the remote repository. Save your changes and run `fisher`.
|
||||
A theme is like any other Fish plugin, but with a `.theme` file in the `themes` directory. Themes were introduced in [Fish `3.4`](https://github.com/fish-shell/fish-shell/releases/tag/3.4.0) and work with the `fish_config` builtin. A theme can also have files in `functions`, `conf.d`, or `completions` if necessary. Check out what a typical theme plugin looks like:
|
||||
|
||||
```diff
|
||||
- /absolute/path/to/fish-readme
|
||||
+ jorgebucaran/fish-readme
|
||||
```
|
||||
|
||||
```
|
||||
fisher
|
||||
```
|
||||
<pre>
|
||||
<b>gills</b>
|
||||
├── <b>conf.d</b>
|
||||
│ └── gills.fish
|
||||
└── <b>themes</b>
|
||||
└── gills.theme
|
||||
</pre>
|
||||
|
||||
You can leave off the github.com part of the URL when adding or removing packages hosted on GitHub. If your package is hosted anywhere else, the address of the server is required.
|
||||
### Using `$fisher_path` with themes
|
||||
|
||||
### Configuration snippets
|
||||
If you customize `$fisher_path` to use a directory other than `$__fish_config_dir`, your themes won't be available via `fish_config`. That's because Fish expects your themes to be in `$__fish_config_dir/themes`, not `$fisher_path/themes`. This isn't configurable in Fish yet, but there's [a request to add that feature](https://github.com/fish-shell/fish-shell/issues/9456).
|
||||
|
||||
Configuration snippets consist of all the fish files inside your `~/.config/fish/conf.d` directory. They are evaluated on [shell startup](http://fishshell.com/docs/current/index.html#initialization) and generally used to set environment variables, add new key bindings, etc.
|
||||
Fear not! You can easily solve this by symlinking Fisher's `themes` directory into your Fish config. First, backup any existing themes directory.
|
||||
|
||||
Unlike functions or completions which can be erased programmatically, we can't undo a fish file that has been sourced without creating a new shell session. For this reason, packages that use configuration snippets provide custom uninstall logic through an uninstall [event handler](https://fishshell.com/docs/current/#event).
|
||||
```console
|
||||
mv $__fish_config_dir/themes $__fish_config_dir/themes.bak
|
||||
```
|
||||
|
||||
Let's walk through an example that uses this feature to add a new key binding for the Control-G sequence that opens your fishfile in the `vi` editor. When you install the package, `fishfile_quick_edit_key_bindings.fish` will be sourced, adding the specified key binding and loading the event handler function. When you uninstall it, we'll emit an uninstall event where the key binding will be erased.
|
||||
Next, create a symlink for Fisher's themes directory.
|
||||
|
||||
```
|
||||
fish-fishfile-quick-edit
|
||||
└── conf.d
|
||||
└── fishfile_quick_edit_key_bindings.fish
|
||||
```console
|
||||
ln -s $fisher_path/themes $__fish_config_dir/themes
|
||||
```
|
||||
|
||||
```fish
|
||||
bind \cg "vi ~/.config/fish/fishfile"
|
||||
Want to use theme plugins and maintain your own local themes? You can do that too ([#708](https://github.com/jorgebucaran/fisher/issues/708)).
|
||||
|
||||
set -l name (basename (status -f) .fish){_uninstall}
|
||||
## Discoverability
|
||||
|
||||
function $name --event $name
|
||||
bind -e \cg
|
||||
end
|
||||
```
|
||||
|
||||
## Uninstalling
|
||||
While Fisher doesn't rely on a central plugin repository, discovering new plugins doesn't have to feel like navigating uncharted waters. To boost your plugin's visibility and make it easier for users to find, [add relevant topics to your repository](https://docs.github.com/en/repositories/managing-your-repositorys-settings-and-features/customizing-your-repository/classifying-your-repository-with-topics#adding-topics-to-your-repository) using [`fish-plugin`](https://github.com/topics/fish-plugin). By doing so, you're not only contributing to the Fisher community but also enabling users to explore new plugins and enhance their Fish shell experience. Don't let plugin discovery be a fishy business, tag your plugins today!
|
||||
|
||||
You want to know how to uninstall Fisher and everything you've installed with it from your system. This command will purge all packages, cache, configuration and related files—all in the same session.
|
||||
## Acknowledgments
|
||||
|
||||
```fish
|
||||
fisher self-uninstall
|
||||
```
|
||||
Fisher started its journey in 2016 by [@jorgebucaran](https://github.com/jorgebucaran) as a shell configuration manager for Fish. Along the way, many helped shape it into what it is today. [Oh My Fish](https://github.com/oh-my-fish/oh-my-fish) paved the way as the first popular Fish framework. [@jethrokuan](https://github.com/jethrokuan) provided crucial support during the early years. [@PatrickF1](https://github.com/PatrickF1)'s candid feedback proved invaluable time and again. Bootstrapping Fisher was originally [@IlanCosman](https://github.com/IlanCosman)'s brilliant idea. Thank you to all our contributors! <3
|
||||
|
||||
## License
|
||||
|
||||
Fisher is MIT licensed. See the [LICENSE](LICENSE.md) for details.
|
||||
[MIT](LICENSE.md)
|
||||
|
@ -0,0 +1,7 @@
|
||||
complete --command fisher --exclusive --long help --description "Print help"
|
||||
complete --command fisher --exclusive --long version --description "Print version"
|
||||
complete --command fisher --exclusive --condition __fish_use_subcommand --arguments install --description "Install plugins"
|
||||
complete --command fisher --exclusive --condition __fish_use_subcommand --arguments update --description "Update installed plugins"
|
||||
complete --command fisher --exclusive --condition __fish_use_subcommand --arguments remove --description "Remove installed plugins"
|
||||
complete --command fisher --exclusive --condition __fish_use_subcommand --arguments list --description "List installed plugins matching regex"
|
||||
complete --command fisher --exclusive --condition "__fish_seen_subcommand_from update remove" --arguments "(fisher list)"
|
@ -1,496 +0,0 @@
|
||||
set -g fisher_version 3.2.4
|
||||
|
||||
function fisher -a cmd -d "fish package manager"
|
||||
set -q XDG_CACHE_HOME; or set XDG_CACHE_HOME ~/.cache
|
||||
set -q XDG_CONFIG_HOME; or set XDG_CONFIG_HOME ~/.config
|
||||
|
||||
set -g fish_config $XDG_CONFIG_HOME/fish
|
||||
set -g fisher_cache $XDG_CACHE_HOME/fisher
|
||||
set -g fisher_config $XDG_CONFIG_HOME/fisher
|
||||
|
||||
set -q fisher_path; or set -g fisher_path $fish_config
|
||||
|
||||
for path in {$fish_config,$fisher_path}/{functions,completions,conf.d} $fisher_cache
|
||||
if test ! -d $path
|
||||
command mkdir -p $path
|
||||
end
|
||||
end
|
||||
|
||||
if test ! -e $fisher_path/completions/fisher.fish
|
||||
echo "fisher self-complete" >$fisher_path/completions/fisher.fish
|
||||
_fisher_self_complete
|
||||
end
|
||||
|
||||
if test -e $fisher_path/conf.d/fisher.fish
|
||||
switch "$version"
|
||||
case \*-\*
|
||||
command rm -f $fisher_path/conf.d/fisher.fish
|
||||
case 2\*
|
||||
case \*
|
||||
command rm -f $fisher_path/conf.d/fisher.fish
|
||||
end
|
||||
else
|
||||
switch "$version"
|
||||
case \*-\*
|
||||
case 2\*
|
||||
echo "fisher copy-user-key-bindings" >$fisher_path/conf.d/fisher.fish
|
||||
end
|
||||
end
|
||||
|
||||
switch "$cmd"
|
||||
case self-complete
|
||||
_fisher_self_complete
|
||||
case copy-user-key-bindings
|
||||
_fisher_copy_user_key_bindings
|
||||
case ls
|
||||
set -e argv[1]
|
||||
_fisher_ls | _fisher_fmt | _fisher_filter | command awk "/$argv[1]/"
|
||||
case self-update
|
||||
_fisher_self_update (status -f)
|
||||
case self-uninstall
|
||||
_fisher_self_uninstall
|
||||
case -v {,--}version
|
||||
_fisher_version (status -f)
|
||||
case -h {,--}help
|
||||
_fisher_help
|
||||
case ""
|
||||
_fisher_commit --
|
||||
case add rm
|
||||
if not isatty
|
||||
while read -l arg
|
||||
set argv $argv $arg
|
||||
end
|
||||
end
|
||||
|
||||
if test (count $argv) = 1
|
||||
echo "invalid number of arguments" >&2
|
||||
_fisher_help >&2
|
||||
return 1
|
||||
end
|
||||
|
||||
_fisher_commit $argv
|
||||
case \*
|
||||
echo "unknown flag or command \"$cmd\"" >&2
|
||||
_fisher_help >&2
|
||||
return 1
|
||||
end
|
||||
end
|
||||
|
||||
function _fisher_self_complete
|
||||
complete -ec fisher
|
||||
complete -xc fisher -n __fish_use_subcommand -a add -d "Add packages"
|
||||
complete -xc fisher -n __fish_use_subcommand -a rm -d "Remove packages"
|
||||
complete -xc fisher -n __fish_use_subcommand -a ls -d "List installed packages"
|
||||
complete -xc fisher -n __fish_use_subcommand -a help -d "Show usage help"
|
||||
complete -xc fisher -n __fish_use_subcommand -a version -d "$fisher_version"
|
||||
complete -xc fisher -n __fish_use_subcommand -a self-update -d "Update to the latest version"
|
||||
for pkg in (_fisher_ls | _fisher_fmt | _fisher_filter)
|
||||
complete -xc fisher -n "__fish_seen_subcommand_from rm" -a $pkg
|
||||
end
|
||||
end
|
||||
|
||||
function _fisher_copy_user_key_bindings
|
||||
if functions -q fish_user_key_bindings
|
||||
functions -c fish_user_key_bindings fish_user_key_bindings_copy
|
||||
end
|
||||
function fish_user_key_bindings
|
||||
for file in $fisher_path/conf.d/*_key_bindings.fish
|
||||
source $file >/dev/null 2>/dev/null
|
||||
end
|
||||
if functions -q fish_user_key_bindings_copy
|
||||
fish_user_key_bindings_copy
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
function _fisher_ls
|
||||
for pkg in $fisher_config/*/*/*
|
||||
command readlink $pkg; or echo $pkg
|
||||
end
|
||||
end
|
||||
|
||||
function _fisher_fmt
|
||||
command sed "s|^[[:space:]]*||;s|^$fisher_config/||;s|^$HOME|~|;s|^\.\/|$PWD/|;s|^github\.com/||;s|^https*://||;s|/*\$||"
|
||||
end
|
||||
|
||||
function _fisher_file -a file
|
||||
set -e argv[1]
|
||||
_fisher_fmt < $file | _fisher_read $argv
|
||||
end
|
||||
|
||||
function _fisher_filter
|
||||
set -l file (_fisher_file $fisher_path/fishfile)
|
||||
command awk -v FILE="$file" '
|
||||
BEGIN {
|
||||
n = split(FILE, file, " ")
|
||||
for (i = 1; i <= n; i++) found[file[i]] = i
|
||||
}
|
||||
found[$0]
|
||||
'
|
||||
end
|
||||
|
||||
function _fisher_version -a file
|
||||
echo "fisher version $fisher_version $file" | command sed "s|$HOME|~|"
|
||||
end
|
||||
|
||||
function _fisher_help
|
||||
echo "usage:"
|
||||
echo " fisher add <PACKAGES> Add packages"
|
||||
echo " fisher rm <PACKAGES> Remove packages"
|
||||
echo " fisher Update all packages"
|
||||
echo " fisher ls [REGEX] List installed packages matching REGEX"
|
||||
echo " fisher help Show this help"
|
||||
echo " fisher version Show the current version"
|
||||
echo " fisher self-update Update to the latest version"
|
||||
echo " fisher self-uninstall Uninstall from your system"
|
||||
echo
|
||||
echo "examples:"
|
||||
echo " fisher add jethrokuan/z rafaelrinaldi/pure"
|
||||
echo " fisher add gitlab.com/foo/bar@v2"
|
||||
echo " fisher add ~/path/to/local/pkg"
|
||||
echo " fisher add < bundle"
|
||||
echo " fisher rm rafaelrinaldi/pure"
|
||||
echo " fisher rm rafaelrinaldi/pure"
|
||||
echo " fisher ls | fisher rm"
|
||||
echo " fisher ls fish-\*"
|
||||
end
|
||||
|
||||
function _fisher_self_update -a file
|
||||
set -l url "https://raw.githubusercontent.com/jorgebucaran/fisher/master/fisher.fish"
|
||||
echo "fetching $url" >&2
|
||||
command curl -s "$url?nocache" >$file.
|
||||
|
||||
set -l next_version (command awk 'NR == 1 { print $4 }' < $file.)
|
||||
switch "$next_version"
|
||||
case "" $fisher_version
|
||||
command rm -f $file.
|
||||
if test -z "$next_version"
|
||||
echo "cannot update fisher -- are you offline?" >&2
|
||||
return 1
|
||||
end
|
||||
echo "fisher is already up-to-date" >&2
|
||||
case \*
|
||||
echo "linking $file" | command sed "s|$HOME|~|" >&2
|
||||
command mv -f $file. $file
|
||||
source $file
|
||||
echo "updated to $fisher_version -- hooray!" >&2
|
||||
_fisher_self_complete
|
||||
end
|
||||
end
|
||||
|
||||
function _fisher_self_uninstall
|
||||
for pkg in (_fisher_ls)
|
||||
_fisher_rm $pkg
|
||||
end
|
||||
|
||||
for file in $fisher_cache $fisher_config $fisher_path/{functions,completions,conf.d}/fisher.fish $fisher_path/fishfile
|
||||
echo "removing $file"
|
||||
command rm -Rf $file 2>/dev/null
|
||||
end | command sed "s|$HOME|~|" >&2
|
||||
|
||||
set -e fisher_cache
|
||||
set -e fisher_config
|
||||
set -e fisher_path
|
||||
set -e fisher_version
|
||||
|
||||
complete -c fisher --erase
|
||||
functions -e (functions -a | command awk '/^_fisher/') fisher
|
||||
|
||||
echo "done -- see you again!" >&2
|
||||
end
|
||||
|
||||
function _fisher_commit -a cmd
|
||||
set -e argv[1]
|
||||
set -l elapsed (_fisher_now)
|
||||
set -l fishfile $fisher_path/fishfile
|
||||
|
||||
if test ! -e "$fishfile"
|
||||
command touch $fishfile
|
||||
echo "created new fishfile in $fishfile" | command sed "s|$HOME|~|" >&2
|
||||
end
|
||||
|
||||
set -l rm_pkgs (_fisher_ls | _fisher_fmt)
|
||||
for pkg in (_fisher_ls)
|
||||
_fisher_rm $pkg
|
||||
end
|
||||
command rm -Rf $fisher_config
|
||||
command mkdir -p $fisher_config
|
||||
|
||||
set -l next_pkgs (_fisher_file $fishfile $cmd (printf "%s\n" $argv | _fisher_fmt))
|
||||
set -l new_pkgs (_fisher_fetch $next_pkgs)
|
||||
set -l old_pkgs
|
||||
for pkg in $rm_pkgs
|
||||
if contains -- $pkg $new_pkgs
|
||||
set old_pkgs $old_pkgs $pkg
|
||||
end
|
||||
end
|
||||
|
||||
if test -z "$new_pkgs$old_pkgs$rm_pkgs$next_pkgs"
|
||||
echo "nothing to commit -- try adding some packages" >&2
|
||||
return 1
|
||||
end
|
||||
|
||||
set -l actual_pkgs
|
||||
if test "$cmd" = "rm"
|
||||
set actual_pkgs $next_pkgs
|
||||
else
|
||||
for pkg in $next_pkgs
|
||||
if contains -- (echo $pkg | command sed "s|@.*||") $new_pkgs
|
||||
set actual_pkgs $actual_pkgs $pkg
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
_fisher_fmt <$fishfile | _fisher_write $cmd $actual_pkgs >$fishfile.
|
||||
command mv -f $fishfile. $fishfile
|
||||
|
||||
_fisher_self_complete
|
||||
|
||||
command awk -v N=(count $new_pkgs) -v O=(count $old_pkgs) -v R=(count $rm_pkgs) -v E=(_fisher_now $elapsed) '
|
||||
BEGIN {
|
||||
if (N = N - O) res = msg(res, "added", N)
|
||||
if (O) res = msg(res, "updated", O)
|
||||
if (R = R - O) res = msg(res, "removed", R)
|
||||
printf((res ? res : "done") " in %.2fs\n", E / 1000)
|
||||
}
|
||||
function msg(res, str, n) {
|
||||
return (res ? res ", " : "") str " " n " package" (n > 1 ? "s" : "")
|
||||
}
|
||||
' >&2
|
||||
end
|
||||
|
||||
function _fisher_read -a cmd
|
||||
set -e argv[1]
|
||||
command awk -v FS="[[:space:]]*#" -v CMD="$cmd" -v ARGS="$argv" '
|
||||
BEGIN {
|
||||
split(ARGS, args, " ")
|
||||
for (i in args) {
|
||||
if (!((k = getkey(args[i])) in pkgs)) {
|
||||
pkgs[k] = args[i]
|
||||
if (CMD == "add") out[n++] = args[i]
|
||||
}
|
||||
}
|
||||
}
|
||||
!/^#/ && NF {
|
||||
if (!file[k = getkey($1)]++ && !(k in pkgs)) out[n++] = $1
|
||||
}
|
||||
END {
|
||||
for (i = 0; i < n; i++) print out[i]
|
||||
if (CMD == "rm") {
|
||||
for (pkg in pkgs) {
|
||||
if (!(pkg in file)) {
|
||||
print "cannot remove \""pkg"\" -- package not listed in fishfile" > "/dev/stderr"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
function getkey(s) {
|
||||
return (split(s, a, /@+|:/) > 2) ? a[2]"/"a[1]"/"a[3] : a[1]
|
||||
}
|
||||
'
|
||||
end
|
||||
|
||||
function _fisher_write -a cmd
|
||||
set -e argv[1]
|
||||
command awk -v CMD="$cmd" -v ARGS="$argv" '
|
||||
BEGIN {
|
||||
split(ARGS, args, " ")
|
||||
for (i in args) pkgs[getkey(args[i])] = args[i]
|
||||
}
|
||||
{
|
||||
if (/^#/ || !NF) print $0
|
||||
else {
|
||||
k = getkey($0)
|
||||
if (out = pkgs[k] != 0 ? pkgs[k] : CMD != "rm" ? $0 : "") print out
|
||||
pkgs[k] = 0
|
||||
}
|
||||
}
|
||||
END {
|
||||
for (k in pkgs) if (pkgs[k]) print pkgs[k]
|
||||
}
|
||||
function getkey(s) {
|
||||
return (split(s, a, /@+|:/) > 2) ? a[2]"/"a[1]"/"a[3] : a[1]
|
||||
}
|
||||
'
|
||||
end
|
||||
|
||||
function _fisher_fetch
|
||||
set -l pkg_jobs
|
||||
set -l next_pkgs
|
||||
set -l local_pkgs
|
||||
set -l actual_pkgs
|
||||
set -q fisher_user_api_token; and set -l user_info -u $fisher_user_api_token
|
||||
|
||||
for i in $argv
|
||||
switch $i
|
||||
case \~\* /\*
|
||||
set -l path (echo "$i" | command sed "s|~|$HOME|")
|
||||
if test -e "$path"
|
||||
set local_pkgs $local_pkgs $path
|
||||
else
|
||||
echo "cannot add \"$i\" -- is this a valid file?" >&2
|
||||
end
|
||||
continue
|
||||
end
|
||||
|
||||
command awk -v NAME=$i -v FS=/ '
|
||||
BEGIN {
|
||||
if (split(NAME, tmp, /@+|:/) > 2) {
|
||||
if (tmp[4]) sub("@"tmp[4], "", NAME)
|
||||
print NAME "\t" tmp[2]"/"tmp[1]"/"tmp[3] "\t" (tmp[4] ? tmp[4] : "master")
|
||||
} else {
|
||||
pkg = split(NAME, _, "/") <= 2 ? "github.com/"tmp[1] : tmp[1]
|
||||
tag = tmp[2] ? tmp[2] : "master"
|
||||
print (\
|
||||
pkg ~ /^github/ ? "https://codeload."pkg"/tar.gz/"tag : \
|
||||
pkg ~ /^gitlab/ ? "https://"pkg"/-/archive/"tag"/"tmp[split(pkg, tmp, "/")]"-"tag".tar.gz" : \
|
||||
pkg ~ /^bitbucket/ ? "https://"pkg"/get/"tag".tar.gz" : pkg \
|
||||
) "\t" pkg
|
||||
}
|
||||
}
|
||||
' | read -l url pkg branch
|
||||
|
||||
if test ! -d "$fisher_config/$pkg"
|
||||
fish -c "
|
||||
echo fetching $url >&2
|
||||
command mkdir -p $fisher_config/$pkg $fisher_cache/(dirname $pkg)
|
||||
if test ! -z \"$branch\"
|
||||
command git clone $url $fisher_config/$pkg --branch $branch --depth 1 2>/dev/null
|
||||
or echo cannot clone \"$url\" -- is this a valid url\? >&2
|
||||
else if command curl $user_info -Ss $url 2>&1 | command tar -xzf- -C $fisher_config/$pkg 2>/dev/null
|
||||
command rm -Rf $fisher_cache/$pkg
|
||||
command mv -f $fisher_config/$pkg/* $fisher_cache/$pkg
|
||||
command rm -Rf $fisher_config/$pkg
|
||||
command cp -Rf {$fisher_cache,$fisher_config}/$pkg
|
||||
else if test -d \"$fisher_cache/$pkg\"
|
||||
echo cannot connect to server -- searching in \"$fisher_cache/$pkg\" | command sed 's|$HOME|~|' >&2
|
||||
command cp -Rf $fisher_cache/$pkg $fisher_config/$pkg/..
|
||||
else
|
||||
command rm -Rf $fisher_config/$pkg
|
||||
echo cannot add \"$pkg\" -- is this a valid package\? >&2
|
||||
end
|
||||
" >/dev/null &
|
||||
|
||||
set pkg_jobs $pkg_jobs (_fisher_jobs --last)
|
||||
set next_pkgs $next_pkgs "$fisher_config/$pkg"
|
||||
end
|
||||
end
|
||||
|
||||
if test ! -z "$pkg_jobs"
|
||||
_fisher_wait $pkg_jobs
|
||||
for pkg in $next_pkgs
|
||||
if test -d "$pkg"
|
||||
set actual_pkgs $actual_pkgs $pkg
|
||||
_fisher_add $pkg
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
set -l local_path $fisher_config/local/$USER
|
||||
for src in $local_pkgs
|
||||
command mkdir -p $local_path
|
||||
command ln -sf $src $local_path/(command basename $src)
|
||||
set actual_pkgs $actual_pkgs $src
|
||||
_fisher_add $src --link
|
||||
end
|
||||
|
||||
if test ! -z "$actual_pkgs"
|
||||
_fisher_fetch (_fisher_deps $actual_pkgs | command awk '!seen[$0]++')
|
||||
printf "%s\n" $actual_pkgs | _fisher_fmt
|
||||
end
|
||||
end
|
||||
|
||||
function _fisher_deps
|
||||
for pkg in $argv
|
||||
if test ! -d "$pkg"
|
||||
echo $pkg
|
||||
else if test -s "$pkg/fishfile"
|
||||
_fisher_deps (_fisher_fmt < $pkg/fishfile | _fisher_read)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
function _fisher_add -a pkg opts
|
||||
set -l name (command basename $pkg)
|
||||
set -l files $pkg/{functions,completions,conf.d}/**.* $pkg/*.fish
|
||||
for src in $files
|
||||
set -l target (command basename $src)
|
||||
switch $src
|
||||
case $pkg/conf.d\*
|
||||
set target $fisher_path/conf.d/$target
|
||||
case $pkg/completions\*
|
||||
set target $fisher_path/completions/$target
|
||||
case $pkg/{functions,}\*
|
||||
switch $target
|
||||
case uninstall.fish
|
||||
continue
|
||||
case init.fish key_bindings.fish
|
||||
set target $fisher_path/conf.d/$name\_$target
|
||||
case \*
|
||||
set target $fisher_path/functions/$target
|
||||
end
|
||||
end
|
||||
echo "linking $target" | command sed "s|$HOME|~|" >&2
|
||||
if test -z "$opts"
|
||||
command cp -f $src $target
|
||||
else
|
||||
command ln -sf $src $target
|
||||
end
|
||||
switch $target
|
||||
case \*.fish
|
||||
source $target >/dev/null 2>/dev/null
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
function _fisher_rm -a pkg
|
||||
set -l name (command basename $pkg)
|
||||
set -l files $pkg/{conf.d,completions,functions}/**.* $pkg/*.fish
|
||||
for src in $files
|
||||
set -l target (command basename $src)
|
||||
set -l filename (command basename $target .fish)
|
||||
switch $src
|
||||
case $pkg/conf.d\*
|
||||
test "$filename.fish" = "$target"; and emit "$filename"_uninstall
|
||||
set target conf.d/$target
|
||||
case $pkg/completions\*
|
||||
test "$filename.fish" = "$target"; and complete -ec $filename
|
||||
set target completions/$target
|
||||
case $pkg/{,functions}\*
|
||||
test "$filename.fish" = "$target"; and functions -e $filename
|
||||
switch $target
|
||||
case uninstall.fish
|
||||
source $src
|
||||
continue
|
||||
case init.fish key_bindings.fish
|
||||
set target conf.d/$name\_$target
|
||||
case \*
|
||||
set target functions/$target
|
||||
end
|
||||
end
|
||||
command rm -f $fisher_path/$target
|
||||
end
|
||||
if not functions -q fish_prompt
|
||||
source "$__fish_datadir$__fish_data_dir/functions/fish_prompt.fish"
|
||||
end
|
||||
end
|
||||
|
||||
function _fisher_jobs
|
||||
jobs $argv | command awk '/^[0-9]+\t/ { print $1 }'
|
||||
end
|
||||
|
||||
function _fisher_wait
|
||||
while for job in $argv
|
||||
contains -- $job (_fisher_jobs); and break
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
function _fisher_now -a elapsed
|
||||
switch (command uname)
|
||||
case Darwin \*BSD
|
||||
command perl -MTime::HiRes -e 'printf("%.0f\n", (Time::HiRes::time() * 1000) - $ARGV[0])' $elapsed
|
||||
case \*
|
||||
math (command date "+%s%3N") - "0$elapsed"
|
||||
end
|
||||
end
|
@ -0,0 +1,240 @@
|
||||
function fisher --argument-names cmd --description "A plugin manager for Fish"
|
||||
set --query fisher_path || set --local fisher_path $__fish_config_dir
|
||||
set --local fisher_version 4.4.4
|
||||
set --local fish_plugins $__fish_config_dir/fish_plugins
|
||||
|
||||
switch "$cmd"
|
||||
case -v --version
|
||||
echo "fisher, version $fisher_version"
|
||||
case "" -h --help
|
||||
echo "Usage: fisher install <plugins...> Install plugins"
|
||||
echo " fisher remove <plugins...> Remove installed plugins"
|
||||
echo " fisher update <plugins...> Update installed plugins"
|
||||
echo " fisher update Update all installed plugins"
|
||||
echo " fisher list [<regex>] List installed plugins matching regex"
|
||||
echo "Options:"
|
||||
echo " -v, --version Print version"
|
||||
echo " -h, --help Print this help message"
|
||||
echo "Variables:"
|
||||
echo " \$fisher_path Plugin installation path. Default: $__fish_config_dir" | string replace --regex -- $HOME \~
|
||||
case ls list
|
||||
string match --entire --regex -- "$argv[2]" $_fisher_plugins
|
||||
case install update remove
|
||||
isatty || read --local --null --array stdin && set --append argv $stdin
|
||||
|
||||
set --local install_plugins
|
||||
set --local update_plugins
|
||||
set --local remove_plugins
|
||||
set --local arg_plugins $argv[2..-1]
|
||||
set --local old_plugins $_fisher_plugins
|
||||
set --local new_plugins
|
||||
|
||||
test -e $fish_plugins && set --local file_plugins (string match --regex -- '^[^\s]+$' <$fish_plugins)
|
||||
|
||||
if ! set --query argv[2]
|
||||
if test "$cmd" != update
|
||||
echo "fisher: Not enough arguments for command: \"$cmd\"" >&2 && return 1
|
||||
else if ! set --query file_plugins
|
||||
echo "fisher: \"$fish_plugins\" file not found: \"$cmd\"" >&2 && return 1
|
||||
end
|
||||
set arg_plugins $file_plugins
|
||||
end
|
||||
|
||||
for plugin in $arg_plugins
|
||||
set plugin (test -e "$plugin" && realpath $plugin || string lower -- $plugin)
|
||||
contains -- "$plugin" $new_plugins || set --append new_plugins $plugin
|
||||
end
|
||||
|
||||
if set --query argv[2]
|
||||
for plugin in $new_plugins
|
||||
if contains -- "$plugin" $old_plugins
|
||||
test "$cmd" = remove &&
|
||||
set --append remove_plugins $plugin ||
|
||||
set --append update_plugins $plugin
|
||||
else if test "$cmd" = install
|
||||
set --append install_plugins $plugin
|
||||
else
|
||||
echo "fisher: Plugin not installed: \"$plugin\"" >&2 && return 1
|
||||
end
|
||||
end
|
||||
else
|
||||
for plugin in $new_plugins
|
||||
contains -- "$plugin" $old_plugins &&
|
||||
set --append update_plugins $plugin ||
|
||||
set --append install_plugins $plugin
|
||||
end
|
||||
|
||||
for plugin in $old_plugins
|
||||
contains -- "$plugin" $new_plugins || set --append remove_plugins $plugin
|
||||
end
|
||||
end
|
||||
|
||||
set --local pid_list
|
||||
set --local source_plugins
|
||||
set --local fetch_plugins $update_plugins $install_plugins
|
||||
set --local fish_path (status fish-path)
|
||||
|
||||
echo (set_color --bold)fisher $cmd version $fisher_version(set_color normal)
|
||||
|
||||
for plugin in $fetch_plugins
|
||||
set --local source (command mktemp -d)
|
||||
set --append source_plugins $source
|
||||
|
||||
command mkdir -p $source/{completions,conf.d,themes,functions}
|
||||
|
||||
$fish_path --command "
|
||||
if test -e $plugin
|
||||
command cp -Rf $plugin/* $source
|
||||
else
|
||||
set temp (command mktemp -d)
|
||||
set repo (string split -- \@ $plugin) || set repo[2] HEAD
|
||||
|
||||
if set path (string replace --regex -- '^(https://)?gitlab.com/' '' \$repo[1])
|
||||
set name (string split -- / \$path)[-1]
|
||||
set url https://gitlab.com/\$path/-/archive/\$repo[2]/\$name-\$repo[2].tar.gz
|
||||
else
|
||||
set url https://api.github.com/repos/\$repo[1]/tarball/\$repo[2]
|
||||
end
|
||||
|
||||
echo Fetching (set_color --underline)\$url(set_color normal)
|
||||
|
||||
if command curl -q --silent -L \$url | command tar -xzC \$temp -f - 2>/dev/null
|
||||
command cp -Rf \$temp/*/* $source
|
||||
else
|
||||
echo fisher: Invalid plugin name or host unavailable: \\\"$plugin\\\" >&2
|
||||
command rm -rf $source
|
||||
end
|
||||
|
||||
command rm -rf \$temp
|
||||
end
|
||||
|
||||
set files $source/* && string match --quiet --regex -- .+\.fish\\\$ \$files
|
||||
" &
|
||||
|
||||
set --append pid_list (jobs --last --pid)
|
||||
end
|
||||
|
||||
wait $pid_list 2>/dev/null
|
||||
|
||||
for plugin in $fetch_plugins
|
||||
if set --local source $source_plugins[(contains --index -- "$plugin" $fetch_plugins)] && test ! -e $source
|
||||
if set --local index (contains --index -- "$plugin" $install_plugins)
|
||||
set --erase install_plugins[$index]
|
||||
else
|
||||
set --erase update_plugins[(contains --index -- "$plugin" $update_plugins)]
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
for plugin in $update_plugins $remove_plugins
|
||||
if set --local index (contains --index -- "$plugin" $_fisher_plugins)
|
||||
set --local plugin_files_var _fisher_(string escape --style=var -- $plugin)_files
|
||||
|
||||
if contains -- "$plugin" $remove_plugins
|
||||
for name in (string replace --filter --regex -- '.+/conf\.d/([^/]+)\.fish$' '$1' $$plugin_files_var)
|
||||
emit {$name}_uninstall
|
||||
end
|
||||
printf "%s\n" Removing\ (set_color red --bold)$plugin(set_color normal) " "$$plugin_files_var | string replace -- \~ ~
|
||||
set --erase _fisher_plugins[$index]
|
||||
end
|
||||
|
||||
command rm -rf (string replace -- \~ ~ $$plugin_files_var)
|
||||
|
||||
functions --erase (string replace --filter --regex -- '.+/functions/([^/]+)\.fish$' '$1' $$plugin_files_var)
|
||||
|
||||
for name in (string replace --filter --regex -- '.+/completions/([^/]+)\.fish$' '$1' $$plugin_files_var)
|
||||
complete --erase --command $name
|
||||
end
|
||||
|
||||
set --erase $plugin_files_var
|
||||
end
|
||||
end
|
||||
|
||||
if set --query update_plugins[1] || set --query install_plugins[1]
|
||||
command mkdir -p $fisher_path/{functions,themes,conf.d,completions}
|
||||
end
|
||||
|
||||
for plugin in $update_plugins $install_plugins
|
||||
set --local source $source_plugins[(contains --index -- "$plugin" $fetch_plugins)]
|
||||
set --local files $source/{functions,themes,conf.d,completions}/*
|
||||
|
||||
if set --local index (contains --index -- $plugin $install_plugins)
|
||||
set --local user_files $fisher_path/{functions,themes,conf.d,completions}/*
|
||||
set --local conflict_files
|
||||
|
||||
for file in (string replace -- $source/ $fisher_path/ $files)
|
||||
contains -- $file $user_files && set --append conflict_files $file
|
||||
end
|
||||
|
||||
if set --query conflict_files[1] && set --erase install_plugins[$index]
|
||||
echo -s "fisher: Cannot install \"$plugin\": please remove or move conflicting files first:" \n" "$conflict_files >&2
|
||||
continue
|
||||
end
|
||||
end
|
||||
|
||||
for file in (string replace -- $source/ "" $files)
|
||||
command cp -RLf $source/$file $fisher_path/$file
|
||||
end
|
||||
|
||||
set --local plugin_files_var _fisher_(string escape --style=var -- $plugin)_files
|
||||
|
||||
set --query files[1] && set --universal $plugin_files_var (string replace -- $source $fisher_path $files | string replace -- ~ \~)
|
||||
|
||||
contains -- $plugin $_fisher_plugins || set --universal --append _fisher_plugins $plugin
|
||||
contains -- $plugin $install_plugins && set --local event install || set --local event update
|
||||
|
||||
printf "%s\n" Installing\ (set_color --bold)$plugin(set_color normal) " "$$plugin_files_var | string replace -- \~ ~
|
||||
|
||||
for file in (string match --regex -- '.+/[^/]+\.fish$' $$plugin_files_var | string replace -- \~ ~)
|
||||
source $file
|
||||
if set --local name (string replace --regex -- '.+conf\.d/([^/]+)\.fish$' '$1' $file)
|
||||
emit {$name}_$event
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
command rm -rf $source_plugins
|
||||
|
||||
if set --query _fisher_plugins[1]
|
||||
set --local commit_plugins
|
||||
|
||||
for plugin in $file_plugins
|
||||
contains -- (string lower -- $plugin) (string lower -- $_fisher_plugins) && set --append commit_plugins $plugin
|
||||
end
|
||||
|
||||
for plugin in $_fisher_plugins
|
||||
contains -- (string lower -- $plugin) (string lower -- $commit_plugins) || set --append commit_plugins $plugin
|
||||
end
|
||||
|
||||
printf "%s\n" $commit_plugins >$fish_plugins
|
||||
else
|
||||
set --erase _fisher_plugins
|
||||
command rm -f $fish_plugins
|
||||
end
|
||||
|
||||
set --local total (count $install_plugins) (count $update_plugins) (count $remove_plugins)
|
||||
|
||||
test "$total" != "0 0 0" && echo (string join ", " (
|
||||
test $total[1] = 0 || echo "Installed $total[1]") (
|
||||
test $total[2] = 0 || echo "Updated $total[2]") (
|
||||
test $total[3] = 0 || echo "Removed $total[3]")
|
||||
) plugin/s
|
||||
case \*
|
||||
echo "fisher: Unknown command: \"$cmd\"" >&2 && return 1
|
||||
end
|
||||
end
|
||||
|
||||
if ! set --query _fisher_upgraded_to_4_4
|
||||
set --universal _fisher_upgraded_to_4_4
|
||||
if functions --query _fisher_list
|
||||
set --query XDG_DATA_HOME[1] || set --local XDG_DATA_HOME ~/.local/share
|
||||
command rm -rf $XDG_DATA_HOME/fisher
|
||||
functions --erase _fisher_{list,plugin_parse}
|
||||
fisher update >/dev/null 2>/dev/null
|
||||
else
|
||||
for var in (set --names | string match --entire --regex '^_fisher_.+_files$')
|
||||
set $var (string replace -- ~ \~ $$var)
|
||||
end
|
||||
functions --erase _fisher_fish_postexec
|
||||
end
|
||||
end
|
@ -0,0 +1,33 @@
|
||||
set --local BASENAME --regex -- '[^/]+$'
|
||||
|
||||
@echo (fisher --version)
|
||||
|
||||
@test "fisher install" (
|
||||
fisher install tests/ponyo >/dev/null
|
||||
) "$ponyo" = "pyon pyon"
|
||||
|
||||
@test "fisher list" (
|
||||
fisher list | string match $BASENAME | string join " "
|
||||
) = "fisher fishtape ponyo"
|
||||
|
||||
@test "fisher list regex" (
|
||||
fisher list ponyo | string match $BASENAME
|
||||
) = ponyo
|
||||
|
||||
@test "pyon pyon" (fish --command ponyo | string join " ") = "pyon pyon ponyo"
|
||||
|
||||
@test "fisher update" (
|
||||
fisher update tests/ponyo >/dev/null
|
||||
) "$ponyo" = "pyon pyon pyon"
|
||||
|
||||
@test "fisher remove" (
|
||||
fisher remove tests/ponyo >/dev/null
|
||||
) "$ponyo" = ""
|
||||
|
||||
@test "has state" -n (
|
||||
set --names | string match \*fisher\* | string collect
|
||||
)
|
||||
|
||||
@test fish_plugins (
|
||||
fisher list | string collect
|
||||
) = (read --null <$__fish_config_dir/fish_plugins | string collect)
|
@ -0,0 +1,13 @@
|
||||
echo pyon pyon
|
||||
|
||||
function ponyo_install --on-event ponyo_install
|
||||
set --global ponyo pyon pyon
|
||||
end
|
||||
|
||||
function ponyo_update --on-event ponyo_update
|
||||
set --global --append ponyo pyon
|
||||
end
|
||||
|
||||
function ponyo_uninstall --on-event ponyo_uninstall
|
||||
set --erase ponyo
|
||||
end
|
@ -0,0 +1,3 @@
|
||||
function ponyo
|
||||
echo ponyo
|
||||
end
|
Loading…
Reference in New Issue