├── test ├── fixtures │ └── foo │ │ ├── with_init │ │ ├── foo.fish │ │ ├── completions │ │ │ └── mycommand.fish │ │ ├── functions │ │ │ └── my_plugin_function.fish │ │ └── init.fish │ │ ├── without_init │ │ └── no_init.fish │ │ ├── subfolder │ │ └── plugin │ │ │ ├── completions │ │ │ └── my_subfolder_command.fish │ │ │ └── functions │ │ │ └── my_subfolder_plugin_function.fish │ │ └── with_dependency │ │ └── init.fish ├── __fundle_commit_sha_test.fish ├── with_repo.fish ├── __fundle_rev_parse_test.fish ├── __fundle_install_plugin_test.fish ├── __fundle_list_test.fish ├── __fundle_update_plugin_test.fish ├── __fundle_clean_test.fish ├── fundle_test.fish ├── __fundle_install_test.fish ├── helper.fish ├── utils_test.fish ├── __fundle_plugin_test.fish └── __fundle_init_test.fish ├── run-tests.fish ├── install-fishtape.sh ├── install-fundle.fish ├── Makefile ├── .travis.yml ├── LICENSE ├── completions └── fundle.fish ├── README.md └── functions └── fundle.fish /test/fixtures/foo/with_init/foo.fish: -------------------------------------------------------------------------------- 1 | 2 | set -g i_should_be_empty 'not_empty' 3 | -------------------------------------------------------------------------------- /test/fixtures/foo/with_init/completions/mycommand.fish: -------------------------------------------------------------------------------- 1 | complete -c mycommand -a foo -d "foo" 2 | -------------------------------------------------------------------------------- /test/fixtures/foo/without_init/no_init.fish: -------------------------------------------------------------------------------- 1 | function no_init 2 | echo "not_empty" 3 | end 4 | -------------------------------------------------------------------------------- /test/fixtures/foo/with_init/functions/my_plugin_function.fish: -------------------------------------------------------------------------------- 1 | function my_plugin_function 2 | end 3 | -------------------------------------------------------------------------------- /test/fixtures/foo/subfolder/plugin/completions/my_subfolder_command.fish: -------------------------------------------------------------------------------- 1 | complete -c my_subfolder_command -a foo -d "foo" 2 | -------------------------------------------------------------------------------- /test/fixtures/foo/subfolder/plugin/functions/my_subfolder_plugin_function.fish: -------------------------------------------------------------------------------- 1 | function my_subfolder_plugin_function 2 | end 3 | -------------------------------------------------------------------------------- /test/fixtures/foo/with_dependency/init.fish: -------------------------------------------------------------------------------- 1 | fundle plugin 'foo/with_init' (dirname (status -f))/../../../fixtures/foo/with_init 2 | -------------------------------------------------------------------------------- /run-tests.fish: -------------------------------------------------------------------------------- 1 | set failure 0 2 | for file in test/*_test.fish 3 | fishtape $file 4 | or set failure 1 5 | end 6 | exit $failure 7 | -------------------------------------------------------------------------------- /test/fixtures/foo/with_init/init.fish: -------------------------------------------------------------------------------- 1 | function init_with_init -a path --on-event init_with_init 2 | set -g i_have_init_file 'not empty' 3 | end 4 | -------------------------------------------------------------------------------- /install-fishtape.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | [ -z "$XDG_CONFIG_HOME" ] && XDG_CONFIG_HOME="$HOME/.config" 3 | mkdir -p $XDG_CONFIG_HOME/fish/functions 4 | curl -L https://raw.githubusercontent.com/jorgebucaran/fishtape/main/functions/fishtape.fish > $XDG_CONFIG_HOME/fish/functions/fishtape.fish 5 | -------------------------------------------------------------------------------- /install-fundle.fish: -------------------------------------------------------------------------------- 1 | echo "[Downloading fundle ...]"; 2 | test -z "$XDG_CONFIG_HOME"; and set XDG_CONFIG_HOME ~/.config; 3 | mkdir -p $XDG_CONFIG_HOME/fish/functions; 4 | curl -sfL https://git.io/fundle > $XDG_CONFIG_HOME/fish/functions/fundle.fish; and fish -c "fundle install"; and exec fish; 5 | # leave the semicolons at the end of the lines, they are needed by eval 6 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | export XDG_CONFIG_HOME ?= $(HOME)/.config 2 | 3 | FISHTAPE = $(XDG_CONFIG_HOME)/fish/functions/fishtape.fish 4 | 5 | # XXX: tests are reusing same tmp directory so run sequentially for now 6 | test: $(FISHTAPE) 7 | fish -c 'for file in test/*_test.fish; fishtape $$file; end' 8 | 9 | $(FISHTAPE): 10 | ./install-fishtape.sh 11 | 12 | .PHONY: test 13 | -------------------------------------------------------------------------------- /test/__fundle_commit_sha_test.fish: -------------------------------------------------------------------------------- 1 | source (string join '/' (dirname (realpath (status -f))) "helper.fish") 2 | source $current_dirname/with_repo.fish 3 | 4 | @test "$TESTNAME: works with valid git repositories" ( 5 | __fundle_commit_sha $repo main > /dev/null 6 | ) 0 -eq $status 7 | 8 | @test "$TESTNAME: returns a valid sha" ( 9 | __fundle_commit_sha $repo main | wc -m 10 | ) -eq 40 11 | -------------------------------------------------------------------------------- /test/with_repo.fish: -------------------------------------------------------------------------------- 1 | source (string join '/' (dirname (realpath (status -f))) "helper.fish") 2 | 3 | function setup 4 | __fundle_common_setup 5 | set -g plugin 'foo/with_init' 6 | set -g repo $current_dirname/fixtures/$plugin 7 | __fundle_gitify $repo 8 | end 9 | 10 | function teardown --on-process-exit %self 11 | __fundle_clean_gitify $repo 12 | __fundle_clean_tmp_dir 13 | end 14 | 15 | setup 16 | -------------------------------------------------------------------------------- /test/__fundle_rev_parse_test.fish: -------------------------------------------------------------------------------- 1 | source (string join '/' (dirname (realpath (status -f))) "helper.fish") 2 | source $current_dirname/with_repo.fish 3 | 4 | 5 | @test "$TESTNAME: works with valid git repositories" ( 6 | __fundle_rev_parse "$repo/.git" main > /dev/null 7 | ) $status -eq 0 8 | 9 | @test "$TESTNAME: returns a valid sha" ( 10 | __fundle_rev_parse "$repo/.git" main | wc -m 11 | ) -eq 40 12 | -------------------------------------------------------------------------------- /test/__fundle_install_plugin_test.fish: -------------------------------------------------------------------------------- 1 | source (string join '/' (dirname (realpath (status -f))) "helper.fish") 2 | source $current_dirname/with_repo.fish 3 | 4 | @test "$TESTNAME: fails when plugin cannot be fetched" ( 5 | __fundle_install_plugin $plugin /bad/path > /dev/null 2>&1 6 | ) $status -eq 1 7 | 8 | @test "$TESTNAME: succeeds when plugin can be fetched" ( 9 | __fundle_install_plugin $plugin $repo > /dev/null 2>&1 10 | ) $status -eq 0 11 | -------------------------------------------------------------------------------- /test/__fundle_list_test.fish: -------------------------------------------------------------------------------- 1 | source (string join '/' (dirname (realpath (status -f))) "helper.fish") 2 | 3 | function setup 4 | __fundle_cleanup_plugins 5 | __fundle_plugin 'foo/with_init' --url '/foo/bar' 6 | echo (__fundle_list) 7 | end 8 | 9 | setup 10 | 11 | @test "$TESTNAME: returns all registered plugins" (count (__fundle_list -s)) -eq 1 12 | 13 | @test "$TESTNAME: returns plugin name and url" ( 14 | __fundle_list | string collect 15 | ) = ( 16 | echo -e "foo/with_init\n\t/foo/bar" | string collect 17 | ) 18 | -------------------------------------------------------------------------------- /test/__fundle_update_plugin_test.fish: -------------------------------------------------------------------------------- 1 | source (string join '/' (dirname (realpath (status -f))) "helper.fish") 2 | source $current_dirname/with_repo.fish 3 | 4 | @test "$TESTNAME: fails when plugin is not present" ( 5 | __fundle_update_plugin $plugin $repo > /dev/null 2>&1 6 | ) 0 -ne $status 7 | 8 | 9 | @test "$TESTNAME: succeeds when plugin is present" ( 10 | __fundle_install_plugin $plugin $repo > /dev/null 2>&1; 11 | and set -l git_dir $fundle_plugins_dir/$plugin/.git; 12 | and __fundle_update_plugin $plugin $repo > /dev/null 2>&1 13 | ) 0 -eq $status 14 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: shell 2 | 3 | git: 4 | depth: 1 5 | 6 | os: linux 7 | 8 | dist: focal 9 | 10 | env: 11 | - FISH_PPA=nightly-master 12 | - FISH_PPA=release-3 13 | 14 | jobs: 15 | include: 16 | - os: osx 17 | osx_image: xcode12.2 18 | before_install: 19 | - brew update 20 | - brew install fish 21 | 22 | before_install: 23 | - sudo add-apt-repository -y "ppa:fish-shell/$FISH_PPA" 24 | - sudo apt-get update 25 | - sudo apt-get -y install fish 26 | 27 | before_script: 28 | - git config --global user.email "tuvistavie+fundle@gmail.com" 29 | - git config --global user.name "Fundle" 30 | - fish --version 31 | - ./install-fishtape.sh 32 | 33 | script: fish ./run-tests.fish 34 | -------------------------------------------------------------------------------- /test/__fundle_clean_test.fish: -------------------------------------------------------------------------------- 1 | source (string join '/' (dirname (realpath (status -f))) "helper.fish") 2 | 3 | function setup 4 | __fundle_common_setup 5 | mkdir -p $current_dirname/fundle/foo 6 | cp -r $current_dirname/fixtures/foo/with_init $current_dirname/fundle/foo/with_init 7 | cp -r $current_dirname/fixtures/foo/without_init $current_dirname/fundle/foo/without_init 8 | __fundle_plugin 'foo/with_init' 9 | __fundle_init 10 | set -g output (__fundle_clean) 11 | set -g code $status 12 | end 13 | 14 | function teardown --on-process-exit %self 15 | __fundle_clean_tmp_dir 16 | end 17 | 18 | setup 19 | 20 | @test "$TESTNAME: exits with status 0" 0 -eq $code 21 | 22 | @test "$TESTNAME: outputs info about removed plugins" 'Removing foo/without_init' = $output 23 | 24 | @test "$TESTNAME: removes unused plugins" 'without_init' != (ls $current_dirname/fundle/foo) 25 | -------------------------------------------------------------------------------- /test/fundle_test.fish: -------------------------------------------------------------------------------- 1 | source (string join '/' (dirname (realpath (status -f))) "helper.fish") 2 | source $current_dirname/with_repo.fish 3 | 4 | @test "$TESTNAME plugin: adds the repository to __fundle_plugin_names" ( 5 | fundle plugin 'foo/with_init' $current_dirname/fixtures/foo/with_init; 6 | and echo $__fundle_plugin_names[1] 7 | ) = 'foo/with_init' 8 | 9 | @test "$TESTNAME install: installs registered plugins" -d ( 10 | fundle plugin 'foo/with_init' $current_dirname/fixtures/foo/with_init; 11 | and fundle install > /dev/null 2>&1; 12 | and echo $fundle_plugins_dir/foo/with_init 13 | ) 14 | 15 | @test "$TESTNAME init: loads registered plugin" -n ( 16 | mkdir -p $current_dirname/fundle/foo; 17 | and cp -r $current_dirname/fixtures/foo/without_init $current_dirname/fundle/foo/without_init; 18 | and fundle plugin 'foo/without_init'; 19 | and fundle init; 20 | and no_init 21 | ) 22 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2015 Daniel Perez 2 | 3 | Permission is hereby granted, free of charge, to any person obtaining a copy 4 | of this software and associated documentation files (the "Software"), to deal 5 | in the Software without restriction, including without limitation the rights 6 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 | copies of the Software, and to permit persons to whom the Software is 8 | furnished to do so, subject to the following conditions: 9 | 10 | The above copyright notice and this permission notice shall be included in 11 | all copies or substantial portions of the Software. 12 | 13 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 19 | THE SOFTWARE. 20 | -------------------------------------------------------------------------------- /test/__fundle_install_test.fish: -------------------------------------------------------------------------------- 1 | source (string join '/' (dirname (realpath (status -f))) "helper.fish") 2 | 3 | function setup 4 | __fundle_common_setup 5 | __fundle_gitify $current_dirname/fixtures/foo/with_dependency 6 | __fundle_gitify $current_dirname/fixtures/foo/with_init 7 | __fundle_plugin 'foo/with_dependency' $current_dirname/fixtures/foo/with_dependency 8 | set output (__fundle_install) 9 | set -g code $status 10 | end 11 | 12 | function teardown --on-process-exit %self 13 | __fundle_clean_tmp_dir 14 | __fundle_clean_gitify $current_dirname/fixtures/foo/with_dependency 15 | __fundle_clean_gitify $current_dirname/fixtures/foo/with_init 16 | end 17 | 18 | setup 19 | 20 | @test "$TESTNAME: succeeds when all plugins exist" ( 21 | __fundle_cleanup_plugins; 22 | and __fundle_plugin 'foo/with_init' $current_dirname/fixtures/foo/with_init; 23 | and __fundle_install > /dev/null 24 | ) $status -eq 0 25 | 26 | @test "$TESTNAME: succeeds when when plugins have dependencies" $code -eq 0 27 | 28 | @test "$TESTNAME: installs registered plugins" -d $fundle_plugins_dir/foo/with_dependency 29 | 30 | @test "$TESTNAME: installs registered plugins dependencies" -d $fundle_plugins_dir/foo/with_init 31 | -------------------------------------------------------------------------------- /completions/fundle.fish: -------------------------------------------------------------------------------- 1 | complete -f -c fundle -n '__fish_prog_needs_command' -a init -d "load all plugins" 2 | complete -f -c fundle -n '__fish_prog_needs_command' -a plugin -d "add a plugin" 3 | complete -f -c fundle -n '__fish_prog_needs_command' -a list -d "list plugins" 4 | complete -f -c fundle -n '__fish_prog_needs_command' -a install -d "install all plugins" 5 | complete -f -c fundle -n '__fish_prog_needs_command' -a update -d "update existing plugins" 6 | complete -f -c fundle -n '__fish_prog_needs_command' -a clean -d "cleans unused plugins" 7 | complete -f -c fundle -n '__fish_prog_needs_command' -a self-update -d "update fundle" 8 | complete -f -c fundle -n '__fish_prog_needs_command' -a version -d "display fundle version" 9 | complete -f -c fundle -n '__fish_prog_needs_command' -a help -d "display helps" 10 | 11 | complete -f -c fundle -n '__fish_prog_using_command install' -s u -l update -d "update existing plugins (deprecated)" 12 | 13 | complete -f -c fundle -n '__fish_prog_using_command list' -s s -l short -d "show a short list with plugin names only" 14 | 15 | complete -f -c fundle -n '__fish_prog_using_command init' -s p -l profile -d "profile time for loading each plugin" 16 | 17 | complete -f -c fundle -n '__fish_prog_using_command plugin' -l url -d "set the plugin URL" 18 | complete -f -c fundle -n '__fish_prog_using_command plugin' -l path -d "set the plugin load path" 19 | -------------------------------------------------------------------------------- /test/helper.fish: -------------------------------------------------------------------------------- 1 | if test -z "$current_dirname" 2 | set current_dirname (dirname (realpath (status -f))) 3 | end 4 | source "$current_dirname/../functions/fundle.fish" 5 | 6 | set TESTNAME ( 7 | basename -s '.fish' ( 8 | status -t \ 9 | | string match -r '\w+.fish' \ 10 | | string match -v -r '(helper|with_repo)\.fish')[1] 11 | ) 12 | 13 | function __fundle_common_setup 14 | __fundle_cleanup_plugins 15 | __fundle_set_tmpdir 16 | mkdir -p $current_dirname/fundle 17 | end 18 | 19 | function __fundle_set_tmpdir 20 | set -g fundle_plugins_dir $current_dirname/fundle 21 | end 22 | 23 | function __fundle_cleanup_plugins 24 | set -e __fundle_plugin_names 25 | set -e __fundle_plugin_urls 26 | set -e __fundle_plugin_name_paths 27 | set -e __fundle_loaded_plugins 28 | return 0 29 | end 30 | 31 | function __fundle_clean_tmp_dir 32 | rm -rf $current_dirname/fundle 33 | end 34 | 35 | function __fundle_gitify -a git_dir 36 | cd $git_dir 37 | git init -b main > /dev/null 38 | git config user.name 'Daniel Perez' > /dev/null 39 | git config user.email 'tuvistavie@gmail.com' > /dev/null 40 | git config commit.gpgsign 'false' > /dev/null 41 | git add . > /dev/null 42 | git commit -m "Initial commit" > /dev/null 43 | cd $current_dirname/fundle 44 | end 45 | 46 | function __fundle_clean_gitify -a git_dir 47 | rm -rf $git_dir/.git 48 | end 49 | -------------------------------------------------------------------------------- /test/utils_test.fish: -------------------------------------------------------------------------------- 1 | source (string join '/' (dirname (realpath (status -f))) "helper.fish") 2 | if test -z "$XDG_CONFIG_HOME" 3 | set XDG_CONFIG_HOME $HOME/.config 4 | end 5 | 6 | function setup 7 | set -g remote 'https://github.com/tuvistavie/fundle.git' 8 | set -g revision "foobar" 9 | end 10 | 11 | setup 12 | 13 | @test "__fundle_plugins_dir: returns a default value when fundle_plugins_dir is not set" ( 14 | set -e fundle_plugins_dir; __fundle_plugins_dir 15 | ) = "$XDG_CONFIG_HOME/fish/fundle" 16 | 17 | @test "__fundle_plugins_dir: returns fundle_plugins_dir when set" ( 18 | set -g fundle_plugins_dir $current_dirname/fundle; and __fundle_plugins_dir 19 | ) = "$current_dirname/fundle" 20 | 21 | @test "__fundle_no_git: returns 1 when git is on the path" (__fundle_no_git) 1 -eq $status 22 | 23 | @test "__fundle_get_url: defaults to github url" "https://github.com/foo/with_init.git" = (__fundle_get_url 'foo/with_init') 24 | 25 | @test "__fundle_url_rev: defaults to HEAD" 'HEAD' = (__fundle_url_rev $remote) 26 | 27 | @test "__fundle_url_rev: parses revision" $revision = (__fundle_url_rev "$remote#$revision") 28 | 29 | @test "__fundle_remote_url: keeps remote without revision intact" $remote = (__fundle_remote_url $remote) 30 | 31 | @test "__fundle_remote_url: strips the revision from the URL" $remote = (__fundle_remote_url "$remote#$revision") 32 | 33 | @test "__fundle_compare_versions: compares using semver" (printf "%s " "lt" "gt" "eq" "gt" "lt" "gt" "eq" "lt") = (printf "%s " \ 34 | (__fundle_compare_versions 0.1.0 0.1.1) \ 35 | (__fundle_compare_versions 0.1.2 0.1.1) \ 36 | (__fundle_compare_versions 0.1.2 0.1.2) \ 37 | (__fundle_compare_versions 0.10.0 0.2.2) \ 38 | (__fundle_compare_versions 0.10.0 1.2.2) \ 39 | (__fundle_compare_versions 1.0.0 1.0.0.beta0) \ 40 | (__fundle_compare_versions 1.0.0.beta0 1.0.0.beta0) \ 41 | (__fundle_compare_versions 1.0.0.beta0 1.0.0.beta1) 42 | ) 43 | -------------------------------------------------------------------------------- /test/__fundle_plugin_test.fish: -------------------------------------------------------------------------------- 1 | source (string join '/' (dirname (realpath (status -f))) "helper.fish") 2 | source $current_dirname/helper.fish 3 | 4 | function setup 5 | __fundle_cleanup_plugins 6 | __fundle_plugin 'foo/bar' 7 | __fundle_plugin 'foo/baz' '/url/for/baz' 8 | __fundle_plugin 'foo/url-flag' --url '/url/for/url-flag' 9 | __fundle_plugin 'foo/path-flag' --path 'path4' 10 | __fundle_plugin 'foo/url-path-flag' '/url/for/url-path-flag' --path 'path5' 11 | __fundle_plugin 'foo/url-flag-path-flag' --url '/url/for/url-flag-path-flag' --path 'path6' 12 | __fundle_plugin 'foo/path-flag-url-flag' --path 'path7' --url '/url/for/path-flag-url-flag' 13 | end 14 | 15 | setup 16 | 17 | @test "$TESTNAME: adds plugins names" 7 -eq (count $__fundle_plugin_names) 18 | 19 | @test "$TESTNAME: adds plugins urls" 7 -eq (count $__fundle_plugin_urls) 20 | 21 | @test "$TESTNAME: adds plugins paths" 7 -eq (count $__fundle_plugin_name_paths) 22 | 23 | @test "$TESTNAME: adds names in order" 'foo/bar foo/baz foo/url-flag foo/path-flag foo/url-path-flag foo/url-flag-path-flag foo/path-flag-url-flag' = "$__fundle_plugin_names" 24 | 25 | @test "$TESTNAME: uses default url when not given" ( 26 | string join ' ' -- (__fundle_get_url 'foo/bar'; __fundle_get_url 'foo/path-flag') 27 | ) = "$__fundle_plugin_urls[1] $__fundle_plugin_urls[4]" 28 | 29 | @test "$TESTNAME: uses given url" ( 30 | string join ' ' -- \ 31 | '/url/for/baz' \ 32 | '/url/for/url-flag' \ 33 | '/url/for/url-path-flag' \ 34 | '/url/for/url-flag-path-flag' \ 35 | '/url/for/path-flag-url-flag' 36 | ) = "$__fundle_plugin_urls[2..3] $__fundle_plugin_urls[5..7]" 37 | 38 | @test "$TESTNAME: uses given path flag" ( 39 | string join ' ' -- \ 40 | 'foo/path-flag:path4' \ 41 | 'foo/url-path-flag:path5' \ 42 | 'foo/url-flag-path-flag:path6' \ 43 | 'foo/path-flag-url-flag:path7' 44 | ) = "$__fundle_plugin_name_paths[4..7]" 45 | -------------------------------------------------------------------------------- /test/__fundle_init_test.fish: -------------------------------------------------------------------------------- 1 | source (string join '/' (dirname (realpath (status -f))) "helper.fish") 2 | 3 | function setup 4 | __fundle_common_setup 5 | cp -r $current_dirname/fixtures/foo $current_dirname/fundle/foo 6 | __fundle_plugin 'foo/with_dependency' # this should recursively load 'foo/with_init' 7 | __fundle_plugin 'foo/without_init' 8 | __fundle_plugin 'foo/subfolder' --path 'plugin' 9 | set -g output (__fundle_init) 10 | set -g code $status 11 | end 12 | 13 | function teardown --on-process-exit %self 14 | __fundle_clean_tmp_dir 15 | end 16 | 17 | setup 18 | 19 | @test "$TESTNAME: fails when no plugin registered" ( 20 | __fundle_cleanup_plugins; and __fundle_init > /dev/null 2>&1 21 | ) 1 -eq $status 22 | 23 | @test "$TESTNAME: does not fail when plugin not installed" 0 -eq $code 24 | 25 | @test "$TESTNAME: outputs a warning when plugin not installed" -n ( 26 | __fundle_plugin 'foo/i_dont_exit' > /dev/null 2>&1; __fundle_init | string collect 27 | ) 28 | 29 | @test "$TESTNAME: does not output anything when all plugin are present" -z "$output" 30 | 31 | @test "$TESTNAME: loads init.fish when present" -n "$i_have_init_file" 32 | 33 | @test "$TESTNAME: does not load other .fish files when init.fish present" -z "$i_should_be_empty" 34 | 35 | @test "$TESTNAME treats package as function folder when init.fish not present" -n (no_init) 36 | 37 | @test "$TESTNAME adds functions directory to fish_function_path" ( 38 | contains "$current_dirname/fundle/foo/with_init/functions" $fish_function_path; and \ 39 | contains "$current_dirname/fundle/foo/subfolder/plugin/functions" $fish_function_path 40 | ) $status -eq 0 41 | 42 | @test "$TESTNAME adds completions directory to fish_complete_path" ( 43 | contains "$current_dirname/fundle/foo/with_init/completions" $fish_complete_path; and \ 44 | contains "$current_dirname/fundle/foo/subfolder/plugin/completions" $fish_complete_path 45 | ) $status -eq 0 46 | 47 | @test "$TESTNAME loads plugin functions" (functions -q my_plugin_function my_subfolder_plugin_function) 0 -eq $status 48 | 49 | @test "$TESTNAME with profile outputs profiling info" (__fundle_init --profile | grep 'us' > /dev/null) 0 -eq $status 50 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # fundle [![Build Status](https://travis-ci.org/danhper/fundle.svg?branch=master)](https://travis-ci.org/danhper/fundle) 2 | 3 | A minimalist package manager for [fish](http://fishshell.com/) inspired by [Vundle](https://github.com/VundleVim/Vundle.vim). 4 | 5 | 6 | All plugins are installed/updated using git, so the only requirement is to have 7 | git installed and on the path (and well, fish, obviously). 8 | 9 | This package manager is compatible with [oh-my-fish plugins](https://github.com/oh-my-fish). 10 | If you need the core functions of [oh-my-fish](https://github.com/oh-my-fish), 11 | you can use the [danhper/oh-my-fish-core](https://github.com/danhper/oh-my-fish-core) plugin. 12 | 13 | ## Installation 14 | 15 | You can use the installer: 16 | 17 | ```sh 18 | curl -sfL https://git.io/fundle-install | fish 19 | ``` 20 | 21 | Or if you don't like to pipe to a shell, just drop [fundle.fish](functions/fundle.fish) 22 | in your `~/.config/fish/functions` directory and you are done. 23 | 24 | ```sh 25 | mkdir -p ~/.config/fish/functions 26 | wget https://git.io/fundle -O ~/.config/fish/functions/fundle.fish 27 | ``` 28 | 29 | ### Automatic install 30 | 31 | If you want to automatically install fundle when it is not present, you can add 32 | the following at the top of your `~/.config/fish/config.fish`. 33 | 34 | ```fish 35 | if not functions -q fundle; eval (curl -sfL https://git.io/fundle-install); end 36 | ``` 37 | 38 | ### ArchLinux 39 | 40 | fundle is available on the AUR, so you can install it system wide with 41 | 42 | ``` 43 | yaourt -S fundle-git 44 | ``` 45 | 46 | ### Updating 47 | 48 | From fundle 0.2.0 and onwards, you can use `fundle self-update` to update fundle. 49 | 50 | ## Usage 51 | 52 | ### Sample `config.fish` 53 | 54 | 55 | Add this to your `~/.config/fish/config.fish` or any file that you use to load fundle's plugins (in `/etc/fish` for example): 56 | 57 | ``` 58 | fundle plugin 'edc/bass' 59 | fundle plugin 'oh-my-fish/plugin-php' 60 | fundle plugin 'danhper/fish-fastdir' 61 | fundle plugin 'danhper/fish-theme-afowler' 62 | 63 | fundle init 64 | ``` 65 | 66 | This will source the four plugins listed and load all the functions and completions found. 67 | 68 | *Note that the `fundle init` is required on each file loading a plugin, so if you load plugins in multiple .fish files, you have to add `fundle init` to each one of them.* 69 | 70 | After editing `config.fish`: 71 | 72 | 1. Reload your shell (you can run `exec fish` for example) 73 | 2. Run `fundle install` 74 | 3. That's it! The plugins have been installed in `~/.config/fish/fundle` 75 | 76 | ### In depth 77 | 78 | To add a plugin, you simply need to open `~/.config/fish/config.fish` and add: 79 | 80 | ``` 81 | fundle plugin 'repo_owner/repo_name' 82 | ``` 83 | 84 | For example: 85 | 86 | ``` 87 | fundle plugin 'danhper/fish-fastdir' 88 | ``` 89 | 90 | will install the repository at https://github.com/danhper/fish-fastdir. 91 | 92 | To pick a specific version of the plugins, you can append @ followed by a tag from the repo: 93 | ``` 94 | fundle plugin 'joseluisq/gitnow@2.7.0' 95 | ``` 96 | will install Gitnow release 2.7.0 at https://github.com/joseluisq/gitnow/releases/tag/2.7.0. 97 | 98 | If you need to change the repository, you can pass it with `--url` and 99 | it will be passed directly to `git clone`: 100 | 101 | ``` 102 | fundle plugin 'danhper/fish-fastdir' --url 'git@github.com:danhper/fish-fastdir.git' 103 | ``` 104 | Keep in mind that this option overrides any tag set with '@'. 105 | 106 | It also works with other repository hosts: 107 | 108 | ``` 109 | fundle plugin 'username/reponame' --url 'git@gitlab.com:username/reponame.git' 110 | ``` 111 | 112 | And it works with https remote as well (in case you have "the authenticity of host github can't be established"): 113 | 114 | ``` 115 | fundle plugin 'username/reponame' --url 'https://gitlab.com/username/reponame.git' 116 | ``` 117 | 118 | You can also use a branch, tag or any [commit-ish](https://www.kernel.org/pub/software/scm/git/docs/gitrevisions.html#_specifying_revisions) by appending `#commit-ish` to the URL. For example: 119 | 120 | ``` 121 | fundle plugin 'danhper/fish-fastdir' --url 'git@github.com:danhper/fish-fastdir.git#my-branch' 122 | ``` 123 | 124 | will use `my-branch`. If no commit-ish is passed, it will default to `master`. 125 | 126 | If the fish functions or completions are in a subdirectory of the repository, you can use 127 | `--path` to choose the path to load. 128 | 129 | ``` 130 | fundle plugin 'tmuxnator/tmuxinator' --path 'completion' 131 | ``` 132 | 133 | After having made all the calls to `fundle plugin`, you need to add 134 | 135 | ``` 136 | fundle init 137 | ``` 138 | 139 | in your configuration file for the plugins to be loaded. 140 | 141 | IMPORTANT: When you add new plugins, you must restart your shell *before* running `fundle install`. 142 | The simplest way to do this is probably to run `exec fish` in the running shell. 143 | 144 | You can then run 145 | 146 | ``` 147 | fundle install 148 | ``` 149 | 150 | for fundle to download them. 151 | 152 | You can also use 153 | 154 | ``` 155 | fundle update 156 | ``` 157 | 158 | to update the plugins. 159 | 160 | ## Commands 161 | 162 | * `fundle init`: Initialize fundle, loading all the available plugins 163 | * `fundle install`: Install all plugins 164 | * `fundle update`: Update all plugins (deprecates: `fundle install -u`) 165 | * `fundle plugin PLUGIN [--url PLUGIN_URL] [--path PATH]`: Add a plugin to fundle. 166 | * `--url` set the URL to clone the plugin. 167 | * `--path` set the plugin path (relative to the repository root) 168 | * `fundle list [-s]`: List the currently installed plugins, including dependencies (-s gives a shorter version) 169 | * `fundle clean`: Cleans unused plugins 170 | * `fundle self-update`: Updates fundle to the latest version 171 | * `fundle version`: Displays the current version of fundle 172 | * `fundle help`: Displays available commands 173 | 174 | Completions are available in the [completions/fundle.fish](./completions/fundle.fish). 175 | Note that you will need to install [fish-completion-helpers](https://github.com/danhper/fish-completion-helpers) 176 | to use them. 177 | 178 | ## Plugin structure 179 | 180 | A plugin basically has the following structure. 181 | 182 | ``` 183 | . 184 | ├── completions 185 | │   └── my_command.fish 186 | ├── functions 187 | │   ├── __plugin_namespace_my_function.fish 188 | │   └── my_public_function.fish 189 | ├── init.fish 190 | └── README.md 191 | ``` 192 | 193 | * `init.fish` will be sourced directly, so it should not do anything that takes too long 194 | to avoid slowing down the shell startup. It is a good place to put aliases, for example. 195 | * `functions` is the directory containing the plugin functions. This directory will 196 | be added to `fish_function_path`, and will therefore be auto loaded. I suggest you 197 | prefix your functions with `__plugin_name` if the user will not be using them explicitly. 198 | * `completions` is the directory containing the plugin completions. This directory will 199 | be added to `fish_complete_path`. 200 | 201 | NOTE: if no `init.fish` file is found, the root folder of the plugin is treated 202 | as a functions directory. This is to make the plugins compatible with 203 | [oh-my-fish plugins](https://github.com/oh-my-fish) themes. 204 | 205 | ## Managing dependencies 206 | 207 | fundle can manage dependencies for you very easily. 208 | You just have to add 209 | 210 | ``` 211 | fundle plugin 'my/dependency' 212 | ``` 213 | 214 | in your plugin `init.fish` and fundle will automatically fetch and install the 215 | missing dependencies when installing the plugin. 216 | 217 | I created a minimal example in [fish-nvm](https://github.com/danhper/fish-nvm), 218 | which depends on [edc/bass](https://github.com/edc/bass). 219 | 220 | ## Profiling 221 | 222 | Obviously, adding plugins makes the shell startup slower. It should usually be short enough, 223 | but if you feel your shell is becoming to slow, fundle has a very basic profiling 224 | mode to help you. 225 | 226 | All you need to do is to change 227 | 228 | ``` 229 | fundle init 230 | ``` 231 | 232 | to 233 | 234 | ``` 235 | fundle init --profile 236 | ``` 237 | 238 | in your `config.fish` and fundle will print the time it took to load each plugin. 239 | 240 | NOTE: 241 | * You will need the `gdate` command on OSX. You can install it with `brew install coreutils`. 242 | * This functionality simply uses the `date` command, so it prints the real time, 243 | not the CPU time, but it should usually be enough to detect if something is wrong. 244 | * When a plugin include dependencies, the load time for each dependency is added to the 245 | parent plugin load time. 246 | 247 | ## Compatible plugins 248 | 249 | Most [oh-my-fish plugins](https://github.com/oh-my-fish) should work out of the box 250 | or with [danhper/oh-my-fish-core](https://github.com/danhper/oh-my-fish-core) installed. 251 | 252 | Please feel free to edit the [wiki](https://github.com/danhper/fundle/wiki) and add 253 | your plugins, or plugins you know work with fundle. 254 | 255 | ## Contributing 256 | 257 | Contributions are very appreciated. Please open an issue or create a PR if you 258 | want to contribute. 259 | 260 | If you created a package compatible with fundle, feel free to [add it to the Wiki](https://github.com/danhper/fundle/wiki/Home/_edit). 261 | 262 | ## Motivations 263 | 264 | I know that [oh-my-fish](https://github.com/oh-my-fish/oh-my-fish) has a utility to 265 | install packages, but I wanted the simplest tool possible, not a whole framework. 266 | 267 | ## Changelog 268 | 269 | * 2016-04-06 (v0.5.1): Fix `fundle help` to show `clean` command. 270 | * 2016-04-06 (v0.5.0): Add `fundle clean`. Deprecate `fundle install -u` and add `fundle update` thanks to @enricobacis. 271 | * 2015-12-22 (v0.4.0): Add `--path` option, thanks to @Perlence. 272 | * 2015-12-16 (v0.3.2): Fix profiling in OSX. 273 | * 2015-12-14 (v0.3.1): Fix incompatibility with oh-my-fish. Rename `plugins` to `list`. 274 | * 2015-12-14 (v0.3.0): Fix dependency load order. Add profiling mode. 275 | * 2015-12-14 (v0.2.2): Emit plugin initialization event 276 | * 2015-12-07 (v0.2.1): Use `curl` instead of `wget` for `self-update` 277 | * 2015-12-07 (v0.2.0): Add `self-update` command 278 | * 2015-12-07 (v0.1.0): Fix bug with dependency loading in `fundle init` 279 | * 2015-11-24: Allow the use of `#commit-ish` when using plugin repo. Checkout repository `commit-ish` instead of using master branch. 280 | -------------------------------------------------------------------------------- /functions/fundle.fish: -------------------------------------------------------------------------------- 1 | set __fundle_current_version '0.7.1' 2 | 3 | function __fundle_seq -a upto 4 | seq 1 1 $upto 2>/dev/null 5 | end 6 | 7 | function __fundle_next_arg -a index 8 | set -l args $argv[2..-1] 9 | set -l arg_index (math $index + 1) 10 | if test (count $args) -lt $arg_index 11 | echo "missing argument for $args[$index]" 12 | return 1 13 | end 14 | set -l arg $args[$arg_index] 15 | switch $arg 16 | case '--*' 17 | echo "expected argument for $args[$index], got $arg"; and return 1 18 | case '*' 19 | echo $arg; and return 0 20 | end 21 | end 22 | 23 | function __fundle_compare_versions -a version1 -a version2 24 | for i in (__fundle_seq 4) 25 | set -l v1 (echo $version1 | cut -d '.' -f $i | sed -Ee 's/[a-z]+//g') 26 | set -l v2 (echo $version2 | cut -d '.' -f $i | sed -Ee 's/[a-z]+//g') 27 | if test \( -n $v1 -a -z $v2 \) -o \( -n $v1 -a -n $v2 -a $v1 -lt $v2 \) 28 | echo -n "lt"; and return 0 29 | else if test \( -z $v1 -a -n $v2 \) -o \( -n $v1 -a -n $v2 -a $v1 -gt $v2 \) 30 | echo -n "gt"; and return 0 31 | end 32 | end 33 | echo -n "eq"; and return 0 34 | end 35 | 36 | function __fundle_date -d "returns a date" 37 | set -l d (date +%s%N) 38 | if echo $d | string match -rvq 'N' 39 | echo $d 40 | else 41 | gdate +%s%N 42 | end 43 | return 0 44 | end 45 | 46 | function __fundle_self_update -d "updates fundle" 47 | set -l fundle_repo_url "https://github.com/tuvistavie/fundle.git" 48 | # This `sed` stays for now since doing it easily with `string` requires "--filter", which is only in 2.6.0 49 | set -l latest (command git ls-remote --tags $fundle_repo_url | sed -n -e 's|.*refs/tags/v\(.*\)|\1|p' | tail -n 1) 50 | if test (__fundle_compare_versions $latest (__fundle_version)) != "gt" 51 | echo "fundle is already up to date"; and return 0 52 | else 53 | set -l file_url_template 'https://raw.githubusercontent.com/tuvistavie/fundle/VERSION/functions/fundle.fish' 54 | set -l file_url (string replace 'VERSION' -- "v$latest" $file_url_template) 55 | set -l tmp_file (mktemp /tmp/fundle.XXX) 56 | set -l update_message "fundle has been updated to version $latest" 57 | curl -Ls $file_url > $tmp_file; and mv $tmp_file (status -f); and echo $update_message; and return 0 58 | end 59 | end 60 | 61 | function __fundle_url_rev -d "prints the revision from the url" -a git_url 62 | set -l rev (echo $git_url | cut -d '#' -f 2 -s) 63 | if test -n "$rev" 64 | echo $rev 65 | else 66 | echo HEAD 67 | end 68 | end 69 | 70 | function __fundle_remote_url -d "prints the remote url from the full git url" -a git_url 71 | echo $git_url | cut -d '#' -f 1 72 | end 73 | 74 | function __fundle_rev_parse -d "prints the revision if any" -a dir -a commitish 75 | set -l sha (command git --git-dir $dir rev-parse -q --verify $commitish 2>/dev/null) 76 | if test $status -eq 0 77 | echo -n $sha 78 | return 0 79 | end 80 | return 1 81 | end 82 | 83 | function __fundle_commit_sha -d "returns sha of the commit-ish" -a dir -a commitish 84 | if test -d "$dir/.git" 85 | set dir "$dir/.git" 86 | end 87 | if __fundle_rev_parse $dir "origin/$commitish" 88 | return 0 89 | end 90 | __fundle_rev_parse $dir $commitish 91 | end 92 | 93 | function __fundle_plugins_dir -d "returns fundle directory" 94 | if test -z "$fundle_plugins_dir" 95 | if test -n "$XDG_CONFIG_HOME" 96 | echo $XDG_CONFIG_HOME/fish/fundle 97 | else 98 | echo $HOME/.config/fish/fundle 99 | end 100 | else 101 | echo $fundle_plugins_dir 102 | end 103 | end 104 | 105 | function __fundle_no_git -d "check if git is installed" 106 | # `command -q` is >= 2.5.0 107 | if not command -s git > /dev/null 2>&1 108 | echo "git needs to be installed and in the path" 109 | return 0 110 | end 111 | return 1 112 | end 113 | 114 | function __fundle_check_date -d "check date" 115 | if date +%s%N | string match -rvq 'N' 116 | return 0 117 | end 118 | if command -s gdate > /dev/null 2>&1 119 | return 0 120 | end 121 | echo "You need to have a GNU date compliant date installed to use profiling. Use 'brew install coreutils' on OSX" 122 | return 1 123 | end 124 | 125 | function __fundle_get_url -d "returns the url for the given plugin" -a repo 126 | set split (string split @ $repo) 127 | set repo $split[1] 128 | set tag $split[2] 129 | set url "https://github.com/$repo.git" 130 | 131 | test ! -z "$tag"; and set url (string join "#tags/" "$url" "$tag") 132 | echo "$url" 133 | end 134 | 135 | 136 | function __fundle_plugin_index -d "returns the index of the plugin" -a plugin 137 | for i in (__fundle_seq (count $__fundle_plugin_names)) 138 | if test "$__fundle_plugin_names[$i]" = "$plugin" 139 | return $i 140 | end 141 | end 142 | # NOTE: should never reach this point 143 | echo "could not find plugin: $plugin" 144 | exit 1 145 | end 146 | 147 | function __fundle_checkout_revision -a plugin -a git_url 148 | set -l plugin_dir (__fundle_plugins_dir)/$plugin 149 | set -l git_dir $plugin_dir/.git 150 | 151 | set -l sha (__fundle_commit_sha $git_dir (__fundle_url_rev $git_url)) 152 | if test $status -eq 0 153 | command git --git-dir="$git_dir" --work-tree="$plugin_dir" checkout -q -f $sha 154 | else 155 | echo "Could not checkout $plugin revision $sha" 156 | return 1 157 | end 158 | end 159 | 160 | function __fundle_update_plugin -d "update the given plugin" -a plugin -a git_url 161 | echo "Updating $plugin" 162 | 163 | set -l remote_url (__fundle_remote_url $git_url) 164 | set -l git_dir (__fundle_plugins_dir)/$plugin/.git 165 | 166 | command git --git-dir=$git_dir remote set-url origin $remote_url 2>/dev/null 167 | command git --git-dir=$git_dir fetch -q 2>/dev/null 168 | 169 | __fundle_checkout_revision $plugin $git_url 170 | end 171 | 172 | function __fundle_install_plugin -d "install the given plugin" -a plugin -a git_url 173 | if __fundle_no_git 174 | return 1 175 | end 176 | 177 | set -l plugin_dir (__fundle_plugins_dir)/$plugin 178 | set -l git_dir $plugin_dir/.git 179 | set -l remote_url (__fundle_remote_url $git_url) 180 | 181 | if test -d $plugin_dir 182 | echo "$argv[1] installed in $plugin_dir" 183 | return 0 184 | else 185 | echo "Installing $plugin" 186 | command git clone -q $remote_url $plugin_dir 187 | __fundle_checkout_revision $plugin $git_url 188 | end 189 | end 190 | 191 | function __fundle_update -d "update the given plugin, or all if unspecified" -a plugin 192 | if test -n "$plugin"; and test ! -d (__fundle_plugins_dir)/$plugin/.git 193 | echo "$plugin not installed. You may need to run 'fundle install'" 194 | return 1 195 | end 196 | 197 | if test -n "$plugin" 198 | set -l index (__fundle_plugin_index $plugin) 199 | __fundle_update_plugin "$plugin" $__fundle_plugin_urls[$index] 200 | else 201 | for i in (__fundle_seq (count $__fundle_plugin_names)) 202 | __fundle_update_plugin $__fundle_plugin_names[$i] $__fundle_plugin_urls[$i] 203 | end 204 | end 205 | end 206 | 207 | function __fundle_show_doc_msg -d "show a link to fundle docs" 208 | if test (count $argv) -ge 1 209 | echo $argv 210 | end 211 | echo "See the docs for more info. https://github.com/tuvistavie/fundle" 212 | end 213 | 214 | function __fundle_load_plugin -a plugin -a path -a fundle_dir -a profile -d "load a plugin" 215 | if begin; set -q __fundle_loaded_plugins; and contains $plugin $__fundle_loaded_plugins; end 216 | return 0 217 | end 218 | 219 | set -l plugin_dir (string replace -r '/.$' '' -- "$fundle_dir/$plugin/$path") 220 | 221 | if not test -d $plugin_dir 222 | __fundle_show_doc_msg "$plugin not installed. You may need to run 'fundle install'" 223 | return 1 224 | end 225 | 226 | # Take everything but "plugin-" from the last path component 227 | set -l plugin_name (string replace -r '.*/(plugin-)?(.*)$' '$2' -- $plugin) 228 | set -l init_file "$plugin_dir/init.fish" 229 | set -l conf_dir "$plugin_dir/conf.d" 230 | set -l bindings_file "$plugin_dir/key_bindings.fish" 231 | set -l functions_dir "$plugin_dir/functions" 232 | set -l completions_dir "$plugin_dir/completions" 233 | set -l plugin_paths $__fundle_plugin_name_paths 234 | 235 | if begin; test -d $functions_dir; and not contains $functions_dir $fish_function_path; end 236 | set fish_function_path $fish_function_path[1] $functions_dir $fish_function_path[2..-1] 237 | end 238 | 239 | if begin; test -d $completions_dir; and not contains $completions_dir $fish_complete_path; end 240 | set fish_complete_path $fish_complete_path[1] $completions_dir $fish_complete_path[2..-1] 241 | end 242 | 243 | if test -f $init_file 244 | source $init_file 245 | else if test -d $conf_dir 246 | # read all *.fish files in conf.d 247 | for f in $conf_dir/*.fish 248 | source $f 249 | end 250 | else 251 | # For compatibility with oh-my-fish themes, if there is no `init.fish` file in the plugin, 252 | # which is the case with themses, the root directory of the plugin is trerated as a functions 253 | # folder, so we include it in the `fish_function_path` variable. 254 | if not contains $plugin_dir $fish_function_path 255 | set fish_function_path $fish_function_path[1] $plugin_dir $fish_function_path[2..-1] 256 | end 257 | end 258 | 259 | if test -f $bindings_file 260 | set -g __fundle_binding_paths $bindings_file $__fundle_binding_paths 261 | end 262 | 263 | set -g __fundle_loaded_plugins $plugin $__fundle_loaded_plugins 264 | 265 | set -l dependencies (printf '%s\n' $plugin_paths $__fundle_plugin_name_paths | sort | uniq -u) 266 | for dependency in $dependencies 267 | set -l name_path (string split : -- $dependency) 268 | if test "$profile" -eq 1 269 | set -l start_time (__fundle_date +%s%N) 270 | __fundle_load_plugin $name_path[1] $name_path[2] $fundle_dir $profile 271 | set -l ellapsed_time (math \((__fundle_date +%s%N) - $start_time\) / 1000) 272 | echo "$name_path[1]": {$ellapsed_time}us 273 | else 274 | __fundle_load_plugin $name_path[1] $name_path[2] $fundle_dir $profile 275 | end 276 | end 277 | 278 | emit "init_$plugin_name" $plugin_dir 279 | end 280 | 281 | function __fundle_bind -d "set up bindings" 282 | if functions -q fish_user_key_bindings; and not functions -q __fish_user_key_bindings 283 | functions -c fish_user_key_bindings __fish_user_key_bindings 284 | end 285 | 286 | function fish_user_key_bindings 287 | for bindings in $__fundle_binding_paths 288 | source $bindings 289 | end 290 | if functions -q __fish_user_key_bindings 291 | __fish_user_key_bindings 292 | end 293 | end 294 | end 295 | 296 | function __fundle_init -d "initialize fundle" 297 | set -l fundle_dir (__fundle_plugins_dir) 298 | 299 | if test (count $__fundle_plugin_names) -eq 0 300 | __fundle_show_doc_msg "No plugin registered. You need to call 'fundle plugin NAME' before using 'fundle init'. \ 301 | 302 | Try reloading your shell if you just edited your configuration." 303 | return 1 304 | end 305 | 306 | set -l profile 0 307 | if begin; contains -- -p $argv; or contains -- --profile $argv; and __fundle_check_date; end 308 | set profile 1 309 | end 310 | 311 | set -l has_uninstalled_plugins 0 312 | for name_path in $__fundle_plugin_name_paths 313 | set -l name_path (string split : -- $name_path) 314 | if test "$profile" -eq 1 315 | set -l start_time (__fundle_date +%s%N) 316 | __fundle_load_plugin $name_path[1] $name_path[2] $fundle_dir $profile 317 | set -l ellapsed_time (math \((__fundle_date +%s%N) - $start_time\) / 1000) 318 | echo "$name_path[1]": {$ellapsed_time}us 319 | else 320 | __fundle_load_plugin $name_path[1] $name_path[2] $fundle_dir $profile || set has_uninstalled_plugins 1 321 | end 322 | end 323 | 324 | __fundle_bind 325 | return $has_uninstalled_plugins 326 | end 327 | 328 | function __fundle_install -d "install plugin" 329 | if test (count $__fundle_plugin_names) -eq 0 330 | __fundle_show_doc_msg "No plugin registered. You need to call 'fundle plugin NAME' before using 'fundle install'" 331 | end 332 | 333 | for i in (__fundle_seq (count $__fundle_plugin_names)) 334 | __fundle_install_plugin $__fundle_plugin_names[$i] $__fundle_plugin_urls[$i] $argv 335 | end 336 | 337 | set -l original_plugins_count (count (__fundle_list -s)) 338 | __fundle_init 339 | 340 | # if plugins count increase after init, new plugins have dependencies 341 | # install new plugins dependencies if any 342 | if test (count (__fundle_list -s)) -gt $original_plugins_count 343 | __fundle_install $argv 344 | end 345 | end 346 | 347 | function __fundle_clean -d "cleans fundle directory" 348 | set -l fundle_dir (__fundle_plugins_dir) 349 | set -l used_plugins (__fundle_list -s) 350 | set -l installed_plugins $fundle_dir/*/*/ 351 | for installed_plugin in $installed_plugins 352 | set -l plugin (string trim --chars="/" \ 353 | (string replace -r -- "$fundle_dir" "" $installed_plugin)) 354 | if not contains $plugin $used_plugins 355 | echo "Removing $plugin" 356 | rm -rf $fundle_dir/$plugin 357 | end 358 | end 359 | end 360 | 361 | function __fundle_plugin -d "add plugin to fundle" -a name 362 | set -l plugin_url "" 363 | set -l plugin_path "." 364 | set -l argv_count (count $argv) 365 | set -l skip_next true 366 | if test $argv_count -eq 0 -o -z "$argv" 367 | echo "usage: fundle plugin NAME [[--url] URL] [--path PATH]" 368 | return 1 369 | else if test $argv_count -gt 1 370 | for i in (__fundle_seq (count $argv)) 371 | test $skip_next = true; and set skip_next false; and continue 372 | set -l arg $argv[$i] 373 | switch $arg 374 | case '--url' 375 | set plugin_url (__fundle_next_arg $i $argv) 376 | test $status -eq 1; and echo $plugin_url; and return 1 377 | set skip_next true 378 | case '--path' 379 | set plugin_path (__fundle_next_arg $i $argv) 380 | test $status -eq 1; and echo $plugin_path; and return 1 381 | set skip_next true 382 | case '--*' 383 | echo "unknown flag $arg"; and return 1 384 | case '*' 385 | test $i -ne 2; and echo "invalid argument $arg"; and return 1 386 | set plugin_url $arg 387 | end 388 | end 389 | end 390 | test -z "$plugin_url"; and set plugin_url (__fundle_get_url $name) 391 | set name (string split @ $name)[1] 392 | 393 | if not contains $name $__fundle_plugin_names 394 | set -g __fundle_plugin_names $__fundle_plugin_names $name 395 | set -g __fundle_plugin_urls $__fundle_plugin_urls $plugin_url 396 | set -g __fundle_plugin_name_paths $__fundle_plugin_name_paths $name:$plugin_path 397 | end 398 | end 399 | 400 | function __fundle_version -d "prints fundle version" 401 | echo $__fundle_current_version 402 | end 403 | 404 | function __fundle_print_help -d "prints fundle help" 405 | echo "usage: fundle (init | plugin | list | install | update | clean | self-update | version | help)" 406 | end 407 | 408 | function __fundle_list -d "list registered plugins" 409 | if begin; contains -- -s $argv; or contains -- --short $argv; end 410 | for name in $__fundle_plugin_names 411 | echo $name 412 | end 413 | else 414 | for i in (__fundle_seq (count $__fundle_plugin_names)) 415 | echo {$__fundle_plugin_names[$i]}\n\t{$__fundle_plugin_urls[$i]} 416 | end 417 | end 418 | end 419 | 420 | function fundle -d "run fundle" 421 | if __fundle_no_git 422 | return 1 423 | end 424 | 425 | set -l sub_args "" 426 | 427 | switch (count $argv) 428 | case 0 429 | __fundle_print_help 430 | return 1 431 | case 1 432 | case '*' 433 | set sub_args $argv[2..-1] 434 | end 435 | 436 | switch $argv[1] 437 | case "init" 438 | __fundle_init $sub_args 439 | case "plugin" 440 | __fundle_plugin $sub_args 441 | case "list" 442 | __fundle_list $sub_args 443 | case "plugins" 444 | echo "'fundle plugins' has been replaced by 'fundle list'" 445 | case "install" 446 | __fundle_install $sub_args 447 | case "update" 448 | __fundle_update $sub_args 449 | case "clean" 450 | __fundle_clean 451 | case "self-update" 452 | __fundle_self_update 453 | case "version" -v --version 454 | __fundle_version 455 | case "help" -h --help 456 | __fundle_print_help 457 | return 0 458 | case "*" 459 | __fundle_print_help 460 | return 1 461 | end 462 | end 463 | --------------------------------------------------------------------------------