├── .gitattributes ├── .gitignore ├── .gitmodules ├── .travis.yml ├── CHANGELOG.md ├── HOW_TO_PLUGIN.md ├── LICENSE.md ├── README.md ├── bin ├── clean_plugins ├── install_plugins └── update_plugins ├── bindings ├── clean_plugins ├── install_plugins └── update_plugins ├── docs ├── automatic_tpm_installation.md ├── changing_plugins_install_dir.md ├── how_to_create_plugin.md ├── managing_plugins_via_cmd_line.md └── tpm_not_working.md ├── scripts ├── check_tmux_version.sh ├── clean_plugins.sh ├── helpers │ ├── plugin_functions.sh │ ├── shell_echo_functions.sh │ ├── tmux_echo_functions.sh │ ├── tmux_utils.sh │ └── utility.sh ├── install_plugins.sh ├── source_plugins.sh ├── update_plugin.sh ├── update_plugin_prompt_handler.sh └── variables.sh ├── tests ├── expect_failed_plugin_download ├── expect_successful_clean_plugins ├── expect_successful_multiple_plugins_download ├── expect_successful_plugin_download ├── expect_successful_update_of_a_single_plugin ├── expect_successful_update_of_all_plugins ├── helpers │ └── tpm.sh ├── test_plugin_clean.sh ├── test_plugin_installation.sh ├── test_plugin_installation_legacy.sh ├── test_plugin_sourcing.sh └── test_plugin_update.sh └── tpm /.gitattributes: -------------------------------------------------------------------------------- 1 | # Force text files to have unix eols, so Windows/Cygwin does not break them 2 | *.* eol=lf 3 | 4 | # These files are unfortunately not recognized as text files so 5 | # explicitly listing them here 6 | tpm eol=lf 7 | bin/* eol=lf 8 | bindings/* eol=lf 9 | tests/* eol=lf 10 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | **/.vagrant/ 2 | run_tests 3 | tests/run_tests_in_isolation 4 | tests/helpers/helpers.sh 5 | -------------------------------------------------------------------------------- /.gitmodules: -------------------------------------------------------------------------------- 1 | [submodule "lib/tmux-test"] 2 | path = lib/tmux-test 3 | url = https://github.com/tmux-plugins/tmux-test.git 4 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | # generic packages and tmux 2 | before_install: 3 | - sudo apt-get update 4 | - sudo apt-get install -y git-core expect 5 | - sudo apt-get install -y python-software-properties software-properties-common 6 | - sudo apt-get install -y libevent-dev libncurses-dev 7 | - git clone https://github.com/tmux/tmux.git 8 | - cd tmux 9 | - git checkout 2.0 10 | - sh autogen.sh 11 | - ./configure && make && sudo make install 12 | 13 | install: 14 | - git fetch --unshallow --recurse-submodules || git fetch --recurse-submodules 15 | # manual `git clone` required for testing `tmux-test` plugin itself 16 | - git clone https://github.com/tmux-plugins/tmux-test lib/tmux-test; true 17 | - lib/tmux-test/setup 18 | 19 | script: ./tests/run_tests_in_isolation 20 | -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # Changelog 2 | 3 | ### master 4 | 5 | ### v3.1.0, 2023-01-03 6 | - upgrade to new version of `tmux-test` 7 | - bug: when using `emacs` copy mode, Enter does not quit screen after tpm 8 | installation/update. Fix by making `Escape` the key for emacs mode. 9 | - add a doc with troubleshooting instructions 10 | - add `.gitattributes` file that forces linefeed characters (classic `\n`) as 11 | line endings - helps with misconfigured git on windows/cygwin 12 | - readme update: announce Cygwin support 13 | - un-deprecate old plugin definition syntax: `set -g @tpm_plugins` 14 | - More stuff, check `git log`. 15 | 16 | ### v3.0.0, 2015-08-03 17 | - refactor `shared_set_tpm_path_constant` function 18 | - move all instructions to `docs/` dir 19 | - add `bin/install_plugins` cli executable script 20 | - improved test runner function 21 | - switch to using [tmux-test](https://github.com/tmux-plugins/tmux-test) 22 | framework 23 | - add `bin/update_plugins` cli executable script 24 | - refactor test `expect` scripts, make them simpler and ensure they properly 25 | assert expectations 26 | - refactor code that sets 'TMUX_PLUGIN_MANAGER_PATH' global env var 27 | - stop using global variable for 'tpm path' 28 | - support defining plugins via `set -g @plugin` in sourced files as well 29 | 30 | ### v2.0.0, 2015-07-07 31 | - enable overriding default key bindings 32 | - start using `C-c` to clear screen 33 | - add uninstall/clean procedure and keybinding (prefix+alt+u) (@chilicuil) 34 | - add new `set @plugin 'repo'` plugin definition syntax (@chilicuil) 35 | - revert back to using `-g` flag in new plugin definition syntax 36 | - permit leading whitespace with new plugin definition syntax (thanks @chilicuil) 37 | - make sure `TMUX_PLUGIN_MANAGER_PATH` always has trailng slash 38 | - ensure old/deprecated plugin syntax `set -g @tpm_plugins` works alongside new 39 | `set -g @plugin` syntax 40 | 41 | ### v1.2.2, 2015-02-08 42 | - set GIT_TERMINAL_PROMPT=0 when doing `git clone`, `pull` or `submodule update` 43 | to ensure git does not prompt for username/password in any case 44 | 45 | ### v1.2.1, 2014-11-21 46 | - change the way plugin name is expanded. It now uses the http username 47 | and password by default, like this: `https://git::@github.com/`. This prevents 48 | username and password prompt (and subsequently tmux install hanging) with old 49 | git versions. Fixes #7. 50 | 51 | ### v1.2.0, 2014-11-20 52 | - refactor tests so they can be used on travis 53 | - add travis.yml, add travis badge to the readme 54 | 55 | ### v1.1.0, 2014-11-19 56 | - if the plugin is not downloaded do not source it 57 | - remove `PLUGINS.md`, an obsolete list of plugins 58 | - update readme with instructions about uninstalling plugins 59 | - tilde char and `$HOME` in `TMUX_SHARED_MANAGER_PATH` couldn't be used because 60 | they are just plain strings. Fixing the problem by manually expanding them. 61 | - bugfix: fragile `*.tmux` file globbing (@majutsushi) 62 | 63 | ### v1.0.0, 2014-08-05 64 | - update readme because of github organization change to 65 | [tmux-plugins](https://github.com/tmux-plugins) 66 | - update tests to pass 67 | - update README to suggest different first plugin 68 | - update list of plugins in the README 69 | - remove README 'about' section 70 | - move key binding to the main file. Delete `key_binding.sh`. 71 | - rename `display_message` -> `echo_message` 72 | - installing plugins installs just new plugins. Already installed plugins aren't 73 | updated. 74 | - add 'update plugin' binding and functionality 75 | - add test for updating a plugin 76 | 77 | ### v0.0.2, 2014-07-17 78 | - run all *.tmux plugin files as executables 79 | - fix all redirects to /dev/null 80 | - fix bug: TPM shared path is created before sync (cloning plugins from github 81 | is done) 82 | - add test suite running in Vagrant 83 | - add Tmux version check. `TPM` won't run if Tmux version is less than 1.9. 84 | 85 | ### v0.0.1, 2014-05-21 86 | - get TPM up and running 87 | -------------------------------------------------------------------------------- /HOW_TO_PLUGIN.md: -------------------------------------------------------------------------------- 1 | Instructions moved to 2 | [docs/how_to_create_plugin.md](docs/how_to_create_plugin.md). 3 | -------------------------------------------------------------------------------- /LICENSE.md: -------------------------------------------------------------------------------- 1 | MIT license 2 | Copyright (C) 2014 Bruno Sutic 3 | 4 | Permission is hereby granted, free of charge, to any person obtaining 5 | a copy of this software and associated documentation files (the "Software"), 6 | to deal in the Software without restriction, including without limitation 7 | the rights to use, copy, modify, merge, publish, distribute, sublicense, 8 | and/or sell copies of the Software, and to permit persons to whom the 9 | Software is furnished to do so, subject to the following conditions: 10 | 11 | The above copyright notice and this permission notice shall be included 12 | in all copies or substantial portions of the Software. 13 | 14 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 15 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES 16 | OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 17 | IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, 18 | DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 19 | TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE 20 | OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 21 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Tmux Plugin Manager 2 | 3 | [![Build Status](https://travis-ci.org/tmux-plugins/tpm.svg?branch=master)](https://travis-ci.org/tmux-plugins/tpm) 4 | 5 | Installs and loads `tmux` plugins. 6 | 7 | Tested and working on Linux, OSX, and Cygwin. 8 | 9 | See list of plugins [here](https://github.com/tmux-plugins/list). 10 | 11 | ### Installation 12 | 13 | Requirements: `tmux` version 1.9 (or higher), `git`, `bash`. 14 | 15 | Clone TPM: 16 | 17 | ```bash 18 | git clone https://github.com/tmux-plugins/tpm ~/.tmux/plugins/tpm 19 | ``` 20 | 21 | Put this at the bottom of `~/.tmux.conf` (`$XDG_CONFIG_HOME/tmux/tmux.conf` 22 | works too): 23 | 24 | ```bash 25 | # List of plugins 26 | set -g @plugin 'tmux-plugins/tpm' 27 | set -g @plugin 'tmux-plugins/tmux-sensible' 28 | 29 | # Other examples: 30 | # set -g @plugin 'github_username/plugin_name' 31 | # set -g @plugin 'github_username/plugin_name#branch' 32 | # set -g @plugin 'git@github.com:user/plugin' 33 | # set -g @plugin 'git@bitbucket.com:user/plugin' 34 | 35 | # Initialize TMUX plugin manager (keep this line at the very bottom of tmux.conf) 36 | run '~/.tmux/plugins/tpm/tpm' 37 | ``` 38 | 39 | Reload TMUX environment so TPM is sourced: 40 | 41 | ```bash 42 | # type this in terminal if tmux is already running 43 | tmux source ~/.tmux.conf 44 | ``` 45 | 46 | That's it! 47 | 48 | ### Installing plugins 49 | 50 | 1. Add new plugin to `~/.tmux.conf` with `set -g @plugin '...'` 51 | 2. Press `prefix` + I (capital i, as in **I**nstall) to fetch the plugin. 52 | 53 | You're good to go! The plugin was cloned to `~/.tmux/plugins/` dir and sourced. 54 | 55 | ### Uninstalling plugins 56 | 57 | 1. Remove (or comment out) plugin from the list. 58 | 2. Press `prefix` + alt + u (lowercase u as in **u**ninstall) to remove the plugin. 59 | 60 | All the plugins are installed to `~/.tmux/plugins/` so alternatively you can 61 | find plugin directory there and remove it. 62 | 63 | ### Key bindings 64 | 65 | `prefix` + I 66 | - Installs new plugins from GitHub or any other git repository 67 | - Refreshes TMUX environment 68 | 69 | `prefix` + U 70 | - updates plugin(s) 71 | 72 | `prefix` + alt + u 73 | - remove/uninstall plugins not on the plugin list 74 | 75 | ### Docs 76 | 77 | - [Help, tpm not working](docs/tpm_not_working.md) - problem solutions 78 | 79 | More advanced features and instructions, regular users probably do not need 80 | this: 81 | 82 | - [How to create a plugin](docs/how_to_create_plugin.md). It's easy. 83 | - [Managing plugins via the command line](docs/managing_plugins_via_cmd_line.md) 84 | - [Changing plugins install dir](docs/changing_plugins_install_dir.md) 85 | - [Automatic TPM installation on a new machine](docs/automatic_tpm_installation.md) 86 | 87 | ### Tests 88 | 89 | Tests for this project run on [Travis CI](https://travis-ci.org/tmux-plugins/tpm). 90 | 91 | When run locally, [vagrant](https://www.vagrantup.com/) is required. 92 | Run tests with: 93 | 94 | ```bash 95 | # within project directory 96 | ./run_tests 97 | ``` 98 | 99 | ### License 100 | 101 | [MIT](LICENSE.md) 102 | -------------------------------------------------------------------------------- /bin/clean_plugins: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | # Script intended for use via the command line. 4 | # 5 | # `.tmux.conf` needs to be set for TPM. Tmux has to be installed on the system, 6 | # but does not need to be started in order to run this script. 7 | 8 | CURRENT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )" 9 | SCRIPTS_DIR="$CURRENT_DIR/../scripts" 10 | 11 | main() { 12 | "$SCRIPTS_DIR/clean_plugins.sh" # has correct exit code 13 | } 14 | main 15 | -------------------------------------------------------------------------------- /bin/install_plugins: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | # Script intended for use via the command line. 4 | # 5 | # `.tmux.conf` needs to be set for TPM. Tmux has to be installed on the system, 6 | # but does not need to be started in order to run this script. 7 | 8 | CURRENT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )" 9 | SCRIPTS_DIR="$CURRENT_DIR/../scripts" 10 | 11 | main() { 12 | "$SCRIPTS_DIR/install_plugins.sh" # has correct exit code 13 | } 14 | main 15 | -------------------------------------------------------------------------------- /bin/update_plugins: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | # Script intended for use via the command line. 4 | # 5 | # `.tmux.conf` needs to be set for TPM. Tmux has to be installed on the system, 6 | # but does not need to be started in order to run this script. 7 | 8 | CURRENT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )" 9 | SCRIPTS_DIR="$CURRENT_DIR/../scripts" 10 | PROGRAM_NAME="$0" 11 | 12 | if [ $# -eq 0 ]; then 13 | echo "usage:" 14 | echo " $PROGRAM_NAME all update all plugins" 15 | echo " $PROGRAM_NAME tmux-foo update plugin 'tmux-foo'" 16 | echo " $PROGRAM_NAME tmux-bar tmux-baz update multiple plugins" 17 | exit 1 18 | fi 19 | 20 | main() { 21 | "$SCRIPTS_DIR/update_plugin.sh" --shell-echo "$*" # has correct exit code 22 | } 23 | main "$*" 24 | 25 | -------------------------------------------------------------------------------- /bindings/clean_plugins: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | # Tmux key-binding script. 4 | # Scripts intended to be used via the command line are in `bin/` directory. 5 | 6 | CURRENT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )" 7 | SCRIPTS_DIR="$CURRENT_DIR/../scripts" 8 | HELPERS_DIR="$SCRIPTS_DIR/helpers" 9 | 10 | source "$HELPERS_DIR/tmux_echo_functions.sh" 11 | source "$HELPERS_DIR/tmux_utils.sh" 12 | 13 | main() { 14 | reload_tmux_environment 15 | "$SCRIPTS_DIR/clean_plugins.sh" --tmux-echo >/dev/null 2>&1 16 | reload_tmux_environment 17 | end_message 18 | } 19 | main 20 | -------------------------------------------------------------------------------- /bindings/install_plugins: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | # Tmux key-binding script. 4 | # Scripts intended to be used via the command line are in `bin/` directory. 5 | 6 | CURRENT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )" 7 | SCRIPTS_DIR="$CURRENT_DIR/../scripts" 8 | HELPERS_DIR="$SCRIPTS_DIR/helpers" 9 | 10 | source "$HELPERS_DIR/tmux_echo_functions.sh" 11 | source "$HELPERS_DIR/tmux_utils.sh" 12 | 13 | main() { 14 | reload_tmux_environment 15 | "$SCRIPTS_DIR/install_plugins.sh" --tmux-echo >/dev/null 2>&1 16 | reload_tmux_environment 17 | end_message 18 | } 19 | main 20 | -------------------------------------------------------------------------------- /bindings/update_plugins: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | # Tmux key-binding script. 4 | # Scripts intended to be used via the command line are in `bin/` directory. 5 | 6 | # This script: 7 | # - shows a list of installed plugins 8 | # - starts a prompt to enter the name of the plugin that will be updated 9 | 10 | CURRENT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )" 11 | SCRIPTS_DIR="$CURRENT_DIR/../scripts" 12 | HELPERS_DIR="$SCRIPTS_DIR/helpers" 13 | 14 | source "$HELPERS_DIR/plugin_functions.sh" 15 | source "$HELPERS_DIR/tmux_echo_functions.sh" 16 | source "$HELPERS_DIR/tmux_utils.sh" 17 | 18 | display_plugin_update_list() { 19 | local plugins="$(tpm_plugins_list_helper)" 20 | tmux_echo "Installed plugins:" 21 | tmux_echo "" 22 | 23 | for plugin in $plugins; do 24 | # displaying only installed plugins 25 | if plugin_already_installed "$plugin"; then 26 | local plugin_name="$(plugin_name_helper "$plugin")" 27 | tmux_echo " $plugin_name" 28 | fi 29 | done 30 | 31 | tmux_echo "" 32 | tmux_echo "Type plugin name to update it." 33 | tmux_echo "" 34 | tmux_echo "- \"all\" - updates all plugins" 35 | tmux_echo "- ENTER - cancels" 36 | } 37 | 38 | update_plugin_prompt() { 39 | tmux command-prompt -p 'plugin update:' " \ 40 | send-keys C-c; \ 41 | run-shell '$SCRIPTS_DIR/update_plugin_prompt_handler.sh %1'" 42 | } 43 | 44 | main() { 45 | reload_tmux_environment 46 | display_plugin_update_list 47 | update_plugin_prompt 48 | } 49 | main 50 | -------------------------------------------------------------------------------- /docs/automatic_tpm_installation.md: -------------------------------------------------------------------------------- 1 | # Automatic tpm installation 2 | 3 | One of the first things we do on a new machine is cloning our dotfiles. Not everything comes with them though, so for example `tpm` most likely won't be installed. 4 | 5 | If you want to install `tpm` and plugins automatically when tmux is started, put the following snippet in `.tmux.conf` before the final `run '~/.tmux/plugins/tpm/tpm'`: 6 | 7 | ``` 8 | if "test ! -d ~/.tmux/plugins/tpm" \ 9 | "run 'git clone https://github.com/tmux-plugins/tpm ~/.tmux/plugins/tpm && ~/.tmux/plugins/tpm/bin/install_plugins'" 10 | ``` 11 | 12 | This useful tip was submitted by @acr4 and narfman0. 13 | -------------------------------------------------------------------------------- /docs/changing_plugins_install_dir.md: -------------------------------------------------------------------------------- 1 | # Changing plugins install dir 2 | 3 | By default, TPM installs plugins in a subfolder named `plugins/` inside 4 | `$XDG_CONFIG_HOME/tmux/` if a `tmux.conf` file was found at that location, or 5 | inside `~/.tmux/` otherwise. 6 | 7 | You can change the install path by putting this in `.tmux.conf`: 8 | 9 | set-environment -g TMUX_PLUGIN_MANAGER_PATH '/some/other/path/' 10 | 11 | Tmux plugin manager initialization in `.tmux.conf` should also be updated: 12 | 13 | # initializes TMUX plugin manager in a new path 14 | run /some/other/path/tpm/tpm 15 | 16 | Please make sure that the `run` line is at the very bottom of `.tmux.conf`. 17 | -------------------------------------------------------------------------------- /docs/how_to_create_plugin.md: -------------------------------------------------------------------------------- 1 | # How to create Tmux plugins 2 | 3 | Creating a new plugin is easy. 4 | 5 | For demonstration purposes we'll create a simple plugin that lists all 6 | installed TPM plugins. Yes, a plugin that lists plugins :) We'll bind that to 7 | `prefix + T`. 8 | 9 | The source code for this example plugin can be found 10 | [here](https://github.com/tmux-plugins/tmux-example-plugin). 11 | 12 | ### 1. create a new git project 13 | 14 | TPM depends on git for downloading and updating plugins. 15 | 16 | To create a new git project: 17 | 18 | $ mkdir tmux_my_plugin 19 | $ cd tmux_my_plugin 20 | $ git init 21 | 22 | ### 2. create a `*.tmux` plugin run file 23 | 24 | When it sources a plugin, TPM executes all `*.tmux` files in your plugins' 25 | directory. That's how plugins are run. 26 | 27 | Create a plugin run file in plugin directory: 28 | 29 | $ touch my_plugin.tmux 30 | $ chmod u+x my_plugin.tmux 31 | 32 | You can have more than one `*.tmux` file, and all will get executed. However, usually 33 | you'll need just one. 34 | 35 | ### 3. create a plugin key binding 36 | 37 | We want the behavior of the plugin to trigger when a user hits `prefix + T`. 38 | 39 | Key `T` is chosen because: 40 | - it's "kind of" a mnemonic for `TPM` 41 | - the key is not used by Tmux natively. Tmux man page, KEY BINDINGS section 42 | contains a list of all the bindings Tmux uses. There's plenty of unused keys 43 | and we don't want to override any of Tmux default key bindings. 44 | 45 | Open the plugin run file in your favorite text editor: 46 | 47 | $ vim my_plugin.tmux 48 | # or 49 | $ subl my_plugin.tmux 50 | 51 | Put the following content in the file: 52 | 53 | #!/usr/bin/env bash 54 | 55 | CURRENT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )" 56 | tmux bind-key T run-shell "$CURRENT_DIR/scripts/tmux_list_plugins.sh" 57 | 58 | As you can see, plugin run file is a simple bash script that sets up the binding. 59 | 60 | When pressed, `prefix + T` will execute another shell script: 61 | `tmux_list_plugins.sh`. That script should be in `scripts/` directory - 62 | relative to the plugin run file. 63 | 64 | 65 | ### 4. listing plugins 66 | 67 | Now that we have the binding, let's create a script that's invoked with 68 | `prefix + T`. 69 | 70 | $ mkdir scripts 71 | $ touch scripts/tmux_list_plugins.sh 72 | $ chmod u+x scripts/tmux_list_plugins.sh 73 | 74 | And here's the script content: 75 | 76 | #!/usr/bin/env bash 77 | 78 | # fetching the directory where plugins are installed 79 | plugin_path="$(tmux show-env -g TMUX_PLUGIN_MANAGER_PATH | cut -f2 -d=)" 80 | 81 | # listing installed plugins 82 | ls -1 "$plugin_path" 83 | 84 | ### 5. try it out 85 | 86 | To see if this works, execute the plugin run file: 87 | 88 | $ ./my_plugin.tmux 89 | 90 | That should set up the key binding. Now hit `prefix + T` and see if it works. 91 | 92 | ### 6. publish the plugin 93 | 94 | When everything is ready, push the plugin to an online git repository, 95 | preferably GitHub. 96 | 97 | Other users can install your plugin by just adding plugin git URL to the 98 | `@plugin` list in their `.tmux.conf`. 99 | 100 | If the plugin is on GitHub, your users will be able to use the shorthand of 101 | `github_username/repository`. 102 | 103 | ### Conclusion 104 | 105 | Hopefully, that was easy. As you can see, it's mostly shell scripting. 106 | 107 | You can use other scripting languages (ruby, python etc) but plain old shell 108 | is preferred because of portability. 109 | -------------------------------------------------------------------------------- /docs/managing_plugins_via_cmd_line.md: -------------------------------------------------------------------------------- 1 | # Managing plugins via the command line 2 | 3 | Aside from tmux key bindings, TPM provides shell interface for managing plugins 4 | via scripts located in [bin/](../bin/) directory. 5 | 6 | Tmux does not need to be started in order to run scripts (but it's okay if it 7 | is). If you [changed tpm install dir](../docs/changing_plugins_install_dir.md) 8 | in `.tmux.conf` that should work fine too. 9 | 10 | Prerequisites: 11 | 12 | - tmux installed on the system (doh) 13 | - `.tmux.conf` set up for TPM 14 | 15 | ### Installing plugins 16 | 17 | As usual, plugins need to be specified in `.tmux.conf`. Run the following 18 | command to install plugins: 19 | 20 | ~/.tmux/plugins/tpm/bin/install_plugins 21 | 22 | ### Updating plugins 23 | 24 | To update all installed plugins: 25 | 26 | ~/.tmux/plugins/tpm/bin/update_plugins all 27 | 28 | or update a single plugin: 29 | 30 | ~/.tmux/plugins/tpm/bin/update_plugins tmux-sensible 31 | 32 | ### Removing plugins 33 | 34 | To remove plugins not on the plugin list: 35 | 36 | ~/.tmux/plugins/tpm/bin/clean_plugins 37 | -------------------------------------------------------------------------------- /docs/tpm_not_working.md: -------------------------------------------------------------------------------- 1 | # Help, tpm not working! 2 | 3 | Here's the list of issues users had with `tpm`: 4 | 5 |
6 | 7 | > Nothing works. `tpm` key bindings `prefix + I`, `prefix + U` not even 8 | defined. 9 | 10 | Related [issue #22](https://github.com/tmux-plugins/tpm/issues/22) 11 | 12 | - Do you have required `tmux` version to run `tpm`?
13 | Check `tmux` version with `$ tmux -V` command and make sure it's higher or 14 | equal to the required version for `tpm` as stated in the readme. 15 | 16 | - ZSH tmux plugin might be causing issues.
17 | If you have it installed, try disabling it and see if `tpm` works then. 18 | 19 |
20 | 21 | > Help, I'm using custom config file with `tmux -f /path/to/my_tmux.conf` 22 | to start Tmux and for some reason plugins aren't loaded!? 23 | 24 | Related [issue #57](https://github.com/tmux-plugins/tpm/issues/57) 25 | 26 | `tpm` has a known issue when using custom config file with `-f` option. 27 | The solution is to use alternative plugin definition syntax. Here are the steps 28 | to make it work: 29 | 30 | 1. remove all `set -g @plugin` lines from tmux config file 31 | 2. in the config file define the plugins in the following way: 32 | 33 | # List of plugins 34 | set -g @tpm_plugins ' \ 35 | tmux-plugins/tpm \ 36 | tmux-plugins/tmux-sensible \ 37 | tmux-plugins/tmux-resurrect \ 38 | ' 39 | 40 | # Initialize TMUX plugin manager (keep this line at the very bottom of tmux.conf) 41 | run '~/.tmux/plugins/tpm/tpm' 42 | 43 | 3. Reload TMUX environment so TPM is sourced: `$ tmux source /path/to/my_tmux.conf` 44 | 45 | The plugins should now be working. 46 | 47 |
48 | 49 | > Weird sequence of characters show up when installing or updating plugins 50 | 51 | Related: [issue #25](https://github.com/tmux-plugins/tpm/issues/25) 52 | 53 | - This could be caused by [tmuxline.vim](https://github.com/edkolev/tmuxline.vim) 54 | plugin. Uninstall it and see if things work. 55 | 56 |
57 | 58 | > "failed to connect to server" error when sourcing .tmux.conf 59 | 60 | Related: [issue #48](https://github.com/tmux-plugins/tpm/issues/48) 61 | 62 | - Make sure `tmux source ~/.tmux.conf` command is ran from inside `tmux`. 63 | 64 |
65 | 66 | > tpm not working: '~/.tmux/plugins/tpm/tpm' returned 2 (Windows / Cygwin) 67 | 68 | Related: [issue #81](https://github.com/tmux-plugins/tpm/issues/81) 69 | 70 | This issue is most likely caused by Windows line endings. For example, if you 71 | have git's `core.autocrlf` option set to `true`, git will automatically convert 72 | all the files to Windows line endings which might cause a problem. 73 | 74 | The solution is to convert all line ending to Unix newline characters. This 75 | command handles that for all files under `.tmux/` dir (skips `.git` 76 | subdirectories): 77 | 78 | ```bash 79 | find ~/.tmux -type d -name '.git*' -prune -o -type f -print0 | xargs -0 dos2unix 80 | ``` 81 | 82 |
83 | 84 | > '~/.tmux/plugins/tpm/tpm' returned 127 (on macOS, w/ tmux installed using brew) 85 | 86 | Related: [issue #67](https://github.com/tmux-plugins/tpm/issues/67) 87 | 88 | This problem is because tmux's `run-shell` command runs a shell which doesn't read from user configs, thus tmux installed in a brew prefix (e.g. `/usr/local/bin`) will not be found. 89 | 90 | The solution is to find your brew prefix 91 | 92 | ```sh 93 | > echo "$(brew --prefix)/bin" 94 | /opt/homebrew/bin 95 | ``` 96 | 97 | And prepend it to the `PATH` environment variable 98 | ``` 99 | set-environment -g PATH "/opt/homebrew/bin:/bin:/usr/bin" 100 | ``` 101 | 102 | before any `run-shell`/`run` commands in `~/.tmux.conf`. 103 | -------------------------------------------------------------------------------- /scripts/check_tmux_version.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | VERSION="$1" 4 | UNSUPPORTED_MSG="$2" 5 | 6 | get_tmux_option() { 7 | local option=$1 8 | local default_value=$2 9 | local option_value=$(tmux show-option -gqv "$option") 10 | if [ -z "$option_value" ]; then 11 | echo "$default_value" 12 | else 13 | echo "$option_value" 14 | fi 15 | } 16 | 17 | # Ensures a message is displayed for 5 seconds in tmux prompt. 18 | # Does not override the 'display-time' tmux option. 19 | display_message() { 20 | local message="$1" 21 | 22 | # display_duration defaults to 5 seconds, if not passed as an argument 23 | if [ "$#" -eq 2 ]; then 24 | local display_duration="$2" 25 | else 26 | local display_duration="5000" 27 | fi 28 | 29 | # saves user-set 'display-time' option 30 | local saved_display_time=$(get_tmux_option "display-time" "750") 31 | 32 | # sets message display time to 5 seconds 33 | tmux set-option -gq display-time "$display_duration" 34 | 35 | # displays message 36 | tmux display-message "$message" 37 | 38 | # restores original 'display-time' value 39 | tmux set-option -gq display-time "$saved_display_time" 40 | } 41 | 42 | # this is used to get "clean" integer version number. Examples: 43 | # `tmux 1.9` => `19` 44 | # `1.9a` => `19` 45 | get_digits_from_string() { 46 | local string="$1" 47 | local only_digits="$(echo "$string" | tr -dC '[:digit:]')" 48 | echo "$only_digits" 49 | } 50 | 51 | tmux_version_int() { 52 | local tmux_version_string=$(tmux -V) 53 | echo "$(get_digits_from_string "$tmux_version_string")" 54 | } 55 | 56 | unsupported_version_message() { 57 | if [ -n "$UNSUPPORTED_MSG" ]; then 58 | echo "$UNSUPPORTED_MSG" 59 | else 60 | echo "Error, Tmux version unsupported! Please install Tmux version $VERSION or greater!" 61 | fi 62 | } 63 | 64 | exit_if_unsupported_version() { 65 | local current_version="$1" 66 | local supported_version="$2" 67 | if [ "$current_version" -lt "$supported_version" ]; then 68 | display_message "$(unsupported_version_message)" 69 | exit 1 70 | fi 71 | } 72 | 73 | main() { 74 | local supported_version_int="$(get_digits_from_string "$VERSION")" 75 | local current_version_int="$(tmux_version_int)" 76 | exit_if_unsupported_version "$current_version_int" "$supported_version_int" 77 | } 78 | main 79 | -------------------------------------------------------------------------------- /scripts/clean_plugins.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | CURRENT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )" 4 | HELPERS_DIR="$CURRENT_DIR/helpers" 5 | 6 | source "$HELPERS_DIR/plugin_functions.sh" 7 | source "$HELPERS_DIR/utility.sh" 8 | 9 | if [ "$1" == "--tmux-echo" ]; then # tmux-specific echo functions 10 | source "$HELPERS_DIR/tmux_echo_functions.sh" 11 | else # shell output functions 12 | source "$HELPERS_DIR/shell_echo_functions.sh" 13 | fi 14 | 15 | clean_plugins() { 16 | local plugins plugin plugin_directory 17 | plugins="$(tpm_plugins_list_helper)" 18 | 19 | for plugin_directory in "$(tpm_path)"/*; do 20 | [ -d "${plugin_directory}" ] || continue 21 | plugin="$(plugin_name_helper "${plugin_directory}")" 22 | case "${plugins}" in 23 | *"${plugin}"*) : ;; 24 | *) 25 | [ "${plugin}" = "tpm" ] && continue 26 | echo_ok "Removing \"$plugin\"" 27 | rm -rf "${plugin_directory}" >/dev/null 2>&1 28 | [ -d "${plugin_directory}" ] && 29 | echo_err " \"$plugin\" clean fail" || 30 | echo_ok " \"$plugin\" clean success" 31 | ;; 32 | esac 33 | done 34 | } 35 | 36 | main() { 37 | ensure_tpm_path_exists 38 | clean_plugins 39 | exit_value_helper 40 | } 41 | main 42 | -------------------------------------------------------------------------------- /scripts/helpers/plugin_functions.sh: -------------------------------------------------------------------------------- 1 | # using @tpm_plugins is now deprecated in favor of using @plugin syntax 2 | tpm_plugins_variable_name="@tpm_plugins" 3 | 4 | # manually expanding tilde char or `$HOME` variable. 5 | _manual_expansion() { 6 | local path="$1" 7 | local expanded_tilde="${path/#\~/$HOME}" 8 | echo "${expanded_tilde/#\$HOME/$HOME}" 9 | } 10 | 11 | _tpm_path() { 12 | local string_path="$(tmux start-server\; show-environment -g TMUX_PLUGIN_MANAGER_PATH | cut -f2 -d=)/" 13 | _manual_expansion "$string_path" 14 | } 15 | 16 | _CACHED_TPM_PATH="$(_tpm_path)" 17 | 18 | # Get the absolute path to the users configuration file of TMux. 19 | # This includes a prioritized search on different locations. 20 | # 21 | _get_user_tmux_conf() { 22 | # Define the different possible locations. 23 | xdg_location="${XDG_CONFIG_HOME:-$HOME/.config}/tmux/tmux.conf" 24 | default_location="$HOME/.tmux.conf" 25 | 26 | # Search for the correct configuration file by priority. 27 | if [ -f "$xdg_location" ]; then 28 | echo "$xdg_location" 29 | 30 | else 31 | echo "$default_location" 32 | fi 33 | } 34 | 35 | _tmux_conf_contents() { 36 | user_config=$(_get_user_tmux_conf) 37 | cat /etc/tmux.conf "$user_config" 2>/dev/null 38 | if [ "$1" == "full" ]; then # also output content from sourced files 39 | local file 40 | for file in $(_sourced_files); do 41 | cat $(_manual_expansion "$file") 2>/dev/null 42 | done 43 | fi 44 | } 45 | 46 | # return files sourced from tmux config files 47 | _sourced_files() { 48 | _tmux_conf_contents | 49 | sed -E -n -e "s/^[[:space:]]*source(-file)?[[:space:]]+(-q+[[:space:]]+)?['\"]?([^'\"]+)['\"]?/\3/p" 50 | } 51 | 52 | # Want to be able to abort in certain cases 53 | trap "exit 1" TERM 54 | export TOP_PID=$$ 55 | 56 | _fatal_error_abort() { 57 | echo >&2 "Aborting." 58 | kill -s TERM $TOP_PID 59 | } 60 | 61 | # PUBLIC FUNCTIONS BELOW 62 | 63 | tpm_path() { 64 | if [ "$_CACHED_TPM_PATH" == "/" ]; then 65 | echo >&2 "FATAL: Tmux Plugin Manager not configured in tmux.conf" 66 | _fatal_error_abort 67 | fi 68 | echo "$_CACHED_TPM_PATH" 69 | } 70 | 71 | tpm_plugins_list_helper() { 72 | # lists plugins from @tpm_plugins option 73 | echo "$(tmux start-server\; show-option -gqv "$tpm_plugins_variable_name")" 74 | 75 | # read set -g @plugin "tmux-plugins/tmux-example-plugin" entries 76 | _tmux_conf_contents "full" | 77 | awk '/^[ \t]*set(-option)? +-g +@plugin/ { gsub(/'\''/,""); gsub(/'\"'/,""); print $4 }' 78 | } 79 | 80 | # Allowed plugin name formats: 81 | # 1. "git://github.com/user/plugin_name.git" 82 | # 2. "user/plugin_name" 83 | plugin_name_helper() { 84 | local plugin="$1" 85 | # get only the part after the last slash, e.g. "plugin_name.git" 86 | local plugin_basename="$(basename "$plugin")" 87 | # remove ".git" extension (if it exists) to get only "plugin_name" 88 | local plugin_name="${plugin_basename%.git}" 89 | echo "$plugin_name" 90 | } 91 | 92 | plugin_path_helper() { 93 | local plugin="$1" 94 | local plugin_name="$(plugin_name_helper "$plugin")" 95 | echo "$(tpm_path)${plugin_name}/" 96 | } 97 | 98 | plugin_already_installed() { 99 | local plugin="$1" 100 | local plugin_path="$(plugin_path_helper "$plugin")" 101 | [ -d "$plugin_path" ] && 102 | cd "$plugin_path" && 103 | git remote >/dev/null 2>&1 104 | } 105 | -------------------------------------------------------------------------------- /scripts/helpers/shell_echo_functions.sh: -------------------------------------------------------------------------------- 1 | echo_ok() { 2 | echo "$*" 3 | } 4 | 5 | echo_err() { 6 | fail_helper "$*" 7 | } 8 | -------------------------------------------------------------------------------- /scripts/helpers/tmux_echo_functions.sh: -------------------------------------------------------------------------------- 1 | _has_emacs_mode_keys() { 2 | $(tmux show -gw mode-keys | grep -q emacs) 3 | } 4 | 5 | tmux_echo() { 6 | local message="$1" 7 | tmux run-shell "echo '$message'" 8 | } 9 | 10 | echo_ok() { 11 | tmux_echo "$*" 12 | } 13 | 14 | echo_err() { 15 | tmux_echo "$*" 16 | } 17 | 18 | end_message() { 19 | if _has_emacs_mode_keys; then 20 | local continue_key="ESCAPE" 21 | else 22 | local continue_key="ENTER" 23 | fi 24 | tmux_echo "" 25 | tmux_echo "TMUX environment reloaded." 26 | tmux_echo "" 27 | tmux_echo "Done, press $continue_key to continue." 28 | } 29 | -------------------------------------------------------------------------------- /scripts/helpers/tmux_utils.sh: -------------------------------------------------------------------------------- 1 | HELPERS_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )" 2 | source "$HELPERS_DIR/plugin_functions.sh" 3 | 4 | reload_tmux_environment() { 5 | tmux source-file $(_get_user_tmux_conf) >/dev/null 2>&1 6 | } 7 | -------------------------------------------------------------------------------- /scripts/helpers/utility.sh: -------------------------------------------------------------------------------- 1 | ensure_tpm_path_exists() { 2 | mkdir -p "$(tpm_path)" 3 | } 4 | 5 | fail_helper() { 6 | local message="$1" 7 | echo "$message" >&2 8 | FAIL="true" 9 | } 10 | 11 | exit_value_helper() { 12 | if [ "$FAIL" == "true" ]; then 13 | exit 1 14 | else 15 | exit 0 16 | fi 17 | } 18 | -------------------------------------------------------------------------------- /scripts/install_plugins.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | CURRENT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )" 4 | HELPERS_DIR="$CURRENT_DIR/helpers" 5 | 6 | source "$HELPERS_DIR/plugin_functions.sh" 7 | source "$HELPERS_DIR/utility.sh" 8 | 9 | if [ "$1" == "--tmux-echo" ]; then # tmux-specific echo functions 10 | source "$HELPERS_DIR/tmux_echo_functions.sh" 11 | else # shell output functions 12 | source "$HELPERS_DIR/shell_echo_functions.sh" 13 | fi 14 | 15 | clone() { 16 | local plugin="$1" 17 | local branch="$2" 18 | if [ -n "$branch" ]; then 19 | cd "$(tpm_path)" && 20 | GIT_TERMINAL_PROMPT=0 git clone -b "$branch" --single-branch --recursive "$plugin" >/dev/null 2>&1 21 | else 22 | cd "$(tpm_path)" && 23 | GIT_TERMINAL_PROMPT=0 git clone --single-branch --recursive "$plugin" >/dev/null 2>&1 24 | fi 25 | } 26 | 27 | # tries cloning: 28 | # 1. plugin name directly - works if it's a valid git url 29 | # 2. expands the plugin name to point to a GitHub repo and tries cloning again 30 | clone_plugin() { 31 | local plugin="$1" 32 | local branch="$2" 33 | clone "$plugin" "$branch" || 34 | clone "https://git::@github.com/$plugin" "$branch" 35 | } 36 | 37 | # clone plugin and produce output 38 | install_plugin() { 39 | local plugin="$1" 40 | local branch="$2" 41 | local plugin_name="$(plugin_name_helper "$plugin")" 42 | 43 | if plugin_already_installed "$plugin"; then 44 | echo_ok "Already installed \"$plugin_name\"" 45 | else 46 | echo_ok "Installing \"$plugin_name\"" 47 | clone_plugin "$plugin" "$branch" && 48 | echo_ok " \"$plugin_name\" download success" || 49 | echo_err " \"$plugin_name\" download fail" 50 | fi 51 | } 52 | 53 | install_plugins() { 54 | local plugins="$(tpm_plugins_list_helper)" 55 | for plugin in $plugins; do 56 | IFS='#' read -ra plugin <<< "$plugin" 57 | install_plugin "${plugin[0]}" "${plugin[1]}" 58 | done 59 | } 60 | 61 | verify_tpm_path_permissions() { 62 | local path="$(tpm_path)" 63 | # check the write permission flag for all users to ensure 64 | # that we have proper access 65 | [ -w "$path" ] || 66 | echo_err "$path is not writable!" 67 | } 68 | 69 | main() { 70 | ensure_tpm_path_exists 71 | verify_tpm_path_permissions 72 | install_plugins 73 | exit_value_helper 74 | } 75 | main 76 | -------------------------------------------------------------------------------- /scripts/source_plugins.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | CURRENT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )" 4 | HELPERS_DIR="$CURRENT_DIR/helpers" 5 | 6 | source "$HELPERS_DIR/plugin_functions.sh" 7 | 8 | plugin_dir_exists() { 9 | [ -d "$1" ] 10 | } 11 | 12 | # Runs all *.tmux files from the plugin directory. 13 | # Files are ran as executables. 14 | # No errors if the plugin dir does not exist. 15 | silently_source_all_tmux_files() { 16 | local plugin_path="$1" 17 | local plugin_tmux_files="$plugin_path*.tmux" 18 | if plugin_dir_exists "$plugin_path"; then 19 | for tmux_file in $plugin_tmux_files; do 20 | # if the glob didn't find any files this will be the 21 | # unexpanded glob which obviously doesn't exist 22 | [ -f "$tmux_file" ] || continue 23 | # runs *.tmux file as an executable 24 | $tmux_file >/dev/null 2>&1 25 | done 26 | fi 27 | } 28 | 29 | source_plugins() { 30 | local plugin plugin_path 31 | local plugins="$(tpm_plugins_list_helper)" 32 | for plugin in $plugins; do 33 | IFS='#' read -ra plugin <<< "$plugin" 34 | plugin_path="$(plugin_path_helper "${plugin[0]}")" 35 | silently_source_all_tmux_files "$plugin_path" 36 | done 37 | } 38 | 39 | main() { 40 | source_plugins 41 | } 42 | main 43 | -------------------------------------------------------------------------------- /scripts/update_plugin.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | # this script handles core logic of updating plugins 4 | 5 | CURRENT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )" 6 | HELPERS_DIR="$CURRENT_DIR/helpers" 7 | 8 | source "$HELPERS_DIR/plugin_functions.sh" 9 | source "$HELPERS_DIR/utility.sh" 10 | 11 | if [ "$1" == "--tmux-echo" ]; then # tmux-specific echo functions 12 | source "$HELPERS_DIR/tmux_echo_functions.sh" 13 | else # shell output functions 14 | source "$HELPERS_DIR/shell_echo_functions.sh" 15 | fi 16 | 17 | # from now on ignore first script argument 18 | shift 19 | 20 | pull_changes() { 21 | local plugin="$1" 22 | local plugin_path="$(plugin_path_helper "$plugin")" 23 | cd "$plugin_path" && 24 | GIT_TERMINAL_PROMPT=0 git pull && 25 | GIT_TERMINAL_PROMPT=0 git submodule update --init --recursive 26 | } 27 | 28 | update() { 29 | local plugin="$1" output 30 | output=$(pull_changes "$plugin" 2>&1) 31 | if (( $? == 0 )); then 32 | echo_ok " \"$plugin\" update success" 33 | echo_ok "$(echo "$output" | sed -e 's/^/ | /')" 34 | else 35 | echo_err " \"$plugin\" update fail" 36 | echo_err "$(echo "$output" | sed -e 's/^/ | /')" 37 | fi 38 | } 39 | 40 | update_all() { 41 | echo_ok "Updating all plugins!" 42 | echo_ok "" 43 | local plugins="$(tpm_plugins_list_helper)" 44 | for plugin in $plugins; do 45 | IFS='#' read -ra plugin <<< "$plugin" 46 | local plugin_name="$(plugin_name_helper "${plugin[0]}")" 47 | # updating only installed plugins 48 | if plugin_already_installed "$plugin_name"; then 49 | update "$plugin_name" & 50 | fi 51 | done 52 | wait 53 | } 54 | 55 | update_plugins() { 56 | local plugins="$*" 57 | for plugin in $plugins; do 58 | IFS='#' read -ra plugin <<< "$plugin" 59 | local plugin_name="$(plugin_name_helper "${plugin[0]}")" 60 | if plugin_already_installed "$plugin_name"; then 61 | update "$plugin_name" & 62 | else 63 | echo_err "$plugin_name not installed!" & 64 | fi 65 | done 66 | wait 67 | } 68 | 69 | main() { 70 | ensure_tpm_path_exists 71 | if [ "$1" == "all" ]; then 72 | update_all 73 | else 74 | update_plugins "$*" 75 | fi 76 | exit_value_helper 77 | } 78 | main "$*" 79 | -------------------------------------------------------------------------------- /scripts/update_plugin_prompt_handler.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | CURRENT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )" 4 | HELPERS_DIR="$CURRENT_DIR/helpers" 5 | 6 | if [ $# -eq 0 ]; then 7 | exit 0 8 | fi 9 | 10 | source "$HELPERS_DIR/tmux_echo_functions.sh" 11 | source "$HELPERS_DIR/tmux_utils.sh" 12 | 13 | main() { 14 | "$CURRENT_DIR/update_plugin.sh" --tmux-echo "$*" 15 | reload_tmux_environment 16 | end_message 17 | } 18 | main "$*" 19 | -------------------------------------------------------------------------------- /scripts/variables.sh: -------------------------------------------------------------------------------- 1 | install_key_option="@tpm-install" 2 | default_install_key="I" 3 | 4 | update_key_option="@tpm-update" 5 | default_update_key="U" 6 | 7 | clean_key_option="@tpm-clean" 8 | default_clean_key="M-u" 9 | 10 | SUPPORTED_TMUX_VERSION="1.9" 11 | 12 | DEFAULT_TPM_ENV_VAR_NAME="TMUX_PLUGIN_MANAGER_PATH" 13 | DEFAULT_TPM_PATH="$HOME/.tmux/plugins/" 14 | -------------------------------------------------------------------------------- /tests/expect_failed_plugin_download: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env expect 2 | 3 | # disables script output 4 | log_user 0 5 | 6 | spawn tmux 7 | 8 | # Waiting for tmux to attach. If this is not done, next command, `send` will 9 | # not work properly. 10 | sleep 1 11 | 12 | # this is tmux prefix + I 13 | send "I" 14 | 15 | # cloning might take a while 16 | set timeout 20 17 | 18 | expect_after { 19 | timeout { exit 1 } 20 | } 21 | 22 | expect { 23 | "Installing \"non-existing-plugin\"" 24 | } 25 | 26 | expect { 27 | "\"non-existing-plugin\" download fail" 28 | } 29 | 30 | expect { 31 | "Done, press ENTER to continue" { 32 | exit 0 33 | } 34 | } 35 | 36 | exit 1 37 | -------------------------------------------------------------------------------- /tests/expect_successful_clean_plugins: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env expect 2 | 3 | # disables script output 4 | log_user 0 5 | 6 | spawn tmux 7 | 8 | # Waiting for tmux to attach. If this is not done, next command, `send` will 9 | # not work properly. 10 | sleep 1 11 | 12 | # this is tmux prefix + alt + u 13 | send "u" 14 | 15 | set timeout 5 16 | 17 | expect_after { 18 | timeout { exit 1 } 19 | } 20 | 21 | expect { 22 | "Removing \"tmux-example-plugin\"" 23 | } 24 | 25 | expect { 26 | "\"tmux-example-plugin\" clean success" 27 | } 28 | 29 | expect { 30 | "Done, press ENTER to continue." { 31 | exit 0 32 | } 33 | } 34 | 35 | exit 1 36 | -------------------------------------------------------------------------------- /tests/expect_successful_multiple_plugins_download: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env expect 2 | 3 | # disables script output 4 | log_user 0 5 | 6 | spawn tmux 7 | 8 | # Waiting for tmux to attach. If this is not done, next command, `send` will 9 | # not work properly. 10 | sleep 1 11 | 12 | # this is tmux prefix + I 13 | send "I" 14 | 15 | # cloning might take a while 16 | set timeout 15 17 | 18 | expect_after { 19 | timeout { exit 1 } 20 | } 21 | 22 | expect { 23 | "Installing \"tmux-example-plugin\"" 24 | } 25 | 26 | expect { 27 | "\"tmux-example-plugin\" download success" 28 | } 29 | 30 | expect { 31 | "Installing \"tmux-copycat\"" 32 | } 33 | 34 | expect { 35 | "\"tmux-copycat\" download success" 36 | } 37 | 38 | expect { 39 | "Done, press ENTER to continue." { 40 | exit 0 41 | } 42 | } 43 | 44 | exit 1 45 | -------------------------------------------------------------------------------- /tests/expect_successful_plugin_download: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env expect 2 | 3 | # disables script output 4 | log_user 0 5 | 6 | spawn tmux 7 | 8 | # Waiting for tmux to attach. If this is not done, next command, `send` will 9 | # not work properly. 10 | sleep 1 11 | 12 | # this is tmux prefix + I 13 | send "I" 14 | 15 | # cloning might take a while 16 | set timeout 15 17 | 18 | expect_after { 19 | timeout { exit 1 } 20 | } 21 | 22 | expect { 23 | "Installing \"tmux-example-plugin\"" 24 | } 25 | 26 | expect { 27 | "\"tmux-example-plugin\" download success" 28 | } 29 | 30 | expect { 31 | "Done, press ENTER to continue" { 32 | send " " 33 | } 34 | } 35 | 36 | sleep 1 37 | # this is tmux prefix + I 38 | send "I" 39 | 40 | expect { 41 | "Already installed \"tmux-example-plugin\"" 42 | } 43 | 44 | expect { 45 | "Done, press ENTER to continue" { 46 | exit 0 47 | } 48 | } 49 | 50 | exit 1 51 | -------------------------------------------------------------------------------- /tests/expect_successful_update_of_a_single_plugin: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env expect 2 | 3 | # disables script output 4 | log_user 0 5 | 6 | spawn tmux 7 | 8 | # Waiting for tmux to attach. If this is not done, next command, `send` will 9 | # not work properly. 10 | sleep 1 11 | 12 | # this is tmux prefix + U 13 | send "U" 14 | 15 | set timeout 15 16 | 17 | expect_after { 18 | timeout { exit 1 } 19 | } 20 | 21 | expect { 22 | "Installed plugins" 23 | } 24 | 25 | expect { 26 | "tmux-example-plugin" 27 | } 28 | 29 | expect { 30 | "\"all\" - updates all plugins" 31 | } 32 | 33 | expect { 34 | "ENTER - cancels" 35 | } 36 | 37 | # wait for tmux to display prompt before sending characters 38 | sleep 1 39 | send "tmux-example-plugin\r" 40 | 41 | expect { 42 | "Updating \"tmux-example-plugin\"" 43 | } 44 | 45 | expect { 46 | "\"tmux-example-plugin\" update success" 47 | } 48 | 49 | expect { 50 | "Done, press ENTER to continue." { 51 | exit 0 52 | } 53 | } 54 | 55 | exit 1 56 | -------------------------------------------------------------------------------- /tests/expect_successful_update_of_all_plugins: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env expect 2 | 3 | # disables script output 4 | log_user 0 5 | 6 | spawn tmux 7 | 8 | # Waiting for tmux to attach. If this is not done, next command, `send` will 9 | # not work properly. 10 | sleep 1 11 | 12 | # this is tmux prefix + U 13 | send "U" 14 | 15 | set timeout 5 16 | 17 | expect_after { 18 | timeout { exit 1 } 19 | } 20 | 21 | expect { 22 | "Installed plugins" 23 | } 24 | 25 | expect { 26 | "tmux-example-plugin" 27 | } 28 | 29 | expect { 30 | "\"all\" - updates all plugins" 31 | } 32 | 33 | expect { 34 | "ENTER - cancels" 35 | } 36 | 37 | # wait for tmux to display prompt before sending characters 38 | sleep 1 39 | send "all\r" 40 | 41 | expect { 42 | "Updating all plugins!" 43 | } 44 | 45 | expect { 46 | "Updating \"tmux-example-plugin\"" 47 | } 48 | 49 | expect { 50 | "\"tmux-example-plugin\" update success" 51 | } 52 | 53 | expect { 54 | "Done, press ENTER to continue." { 55 | exit 0 56 | } 57 | } 58 | 59 | exit 1 60 | -------------------------------------------------------------------------------- /tests/helpers/tpm.sh: -------------------------------------------------------------------------------- 1 | check_dir_exists_helper() { 2 | [ -d "$1" ] 3 | } 4 | 5 | # runs the scripts and asserts it has the correct output and exit code 6 | script_run_helper() { 7 | local script="$1" 8 | local expected_output="$2" 9 | local expected_exit_code="${3:-0}" 10 | $script 2>&1 | 11 | grep "$expected_output" >/dev/null 2>&1 && # grep -q flag quits the script early 12 | [ "${PIPESTATUS[0]}" -eq "$expected_exit_code" ] 13 | } 14 | -------------------------------------------------------------------------------- /tests/test_plugin_clean.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | CURRENT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )" 4 | TPM_DIR="$PWD" 5 | PLUGINS_DIR="$HOME/.tmux/plugins" 6 | 7 | source "$CURRENT_DIR/helpers/helpers.sh" 8 | source "$CURRENT_DIR/helpers/tpm.sh" 9 | 10 | manually_install_the_plugin() { 11 | rm -rf "$PLUGINS_DIR" 12 | mkdir -p "$PLUGINS_DIR" 13 | cd "$PLUGINS_DIR" 14 | git clone --quiet https://github.com/tmux-plugins/tmux-example-plugin 15 | } 16 | 17 | # TMUX KEY-BINDING TESTS 18 | 19 | test_plugin_uninstallation_via_tmux_key_binding() { 20 | set_tmux_conf_helper <<- HERE 21 | set -g mode-keys vi 22 | run-shell "$TPM_DIR/tpm" 23 | HERE 24 | 25 | manually_install_the_plugin 26 | 27 | "$CURRENT_DIR/expect_successful_clean_plugins" || 28 | fail_helper "[key-binding] clean fails" 29 | 30 | teardown_helper 31 | } 32 | 33 | # SCRIPT TESTS 34 | 35 | test_plugin_uninstallation_via_script() { 36 | set_tmux_conf_helper <<- HERE 37 | set -g mode-keys vi 38 | run-shell "$TPM_DIR/tpm" 39 | HERE 40 | 41 | manually_install_the_plugin 42 | 43 | script_run_helper "$TPM_DIR/bin/clean_plugins" '"tmux-example-plugin" clean success' || 44 | fail_helper "[script] plugin cleaning fails" 45 | 46 | teardown_helper 47 | } 48 | 49 | test_unsuccessful_plugin_uninstallation_via_script() { 50 | set_tmux_conf_helper <<- HERE 51 | set -g mode-keys vi 52 | run-shell "$TPM_DIR/tpm" 53 | HERE 54 | 55 | manually_install_the_plugin 56 | chmod 000 "$PLUGINS_DIR/tmux-example-plugin" # disable directory deletion 57 | 58 | local expected_exit_code=1 59 | script_run_helper "$TPM_DIR/bin/clean_plugins" '"tmux-example-plugin" clean fail' "$expected_exit_code" || 60 | fail_helper "[script] unsuccessful plugin cleaning doesn't fail" 61 | 62 | chmod 755 "$PLUGINS_DIR/tmux-example-plugin" # enable directory deletion 63 | 64 | teardown_helper 65 | } 66 | 67 | run_tests 68 | -------------------------------------------------------------------------------- /tests/test_plugin_installation.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | CURRENT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )" 4 | PLUGINS_DIR="$HOME/.tmux/plugins" 5 | TPM_DIR="$PWD" 6 | 7 | CUSTOM_PLUGINS_DIR="$HOME/foo/plugins" 8 | ADDITIONAL_CONFIG_FILE_1="$HOME/.tmux/additional_config_file_1" 9 | ADDITIONAL_CONFIG_FILE_2="$HOME/.tmux/additional_config_file_2" 10 | 11 | source "$CURRENT_DIR/helpers/helpers.sh" 12 | source "$CURRENT_DIR/helpers/tpm.sh" 13 | 14 | # TMUX KEY-BINDING TESTS 15 | 16 | test_plugin_installation_via_tmux_key_binding() { 17 | set_tmux_conf_helper <<- HERE 18 | set -g mode-keys vi 19 | set -g @plugin "tmux-plugins/tmux-example-plugin" 20 | run-shell "$TPM_DIR/tpm" 21 | HERE 22 | 23 | "$CURRENT_DIR/expect_successful_plugin_download" || 24 | fail_helper "[key-binding] plugin installation fails" 25 | 26 | check_dir_exists_helper "$PLUGINS_DIR/tmux-example-plugin/" || 27 | fail_helper "[key-binding] plugin download fails" 28 | 29 | teardown_helper 30 | } 31 | 32 | test_plugin_installation_via_tmux_key_binding_set_option() { 33 | set_tmux_conf_helper <<- HERE 34 | set -g mode-keys vi 35 | set-option -g @plugin "tmux-plugins/tmux-example-plugin" 36 | run-shell "$TPM_DIR/tpm" 37 | HERE 38 | 39 | "$CURRENT_DIR/expect_successful_plugin_download" || 40 | fail_helper "[key-binding][set-option] plugin installation fails" 41 | 42 | check_dir_exists_helper "$PLUGINS_DIR/tmux-example-plugin/" || 43 | fail_helper "[key-binding][set-option] plugin download fails" 44 | 45 | teardown_helper 46 | } 47 | 48 | test_plugin_installation_custom_dir_via_tmux_key_binding() { 49 | set_tmux_conf_helper <<- HERE 50 | set -g mode-keys vi 51 | set-environment -g TMUX_PLUGIN_MANAGER_PATH '$CUSTOM_PLUGINS_DIR' 52 | 53 | set -g @plugin "tmux-plugins/tmux-example-plugin" 54 | run-shell "$TPM_DIR/tpm" 55 | HERE 56 | 57 | "$CURRENT_DIR/expect_successful_plugin_download" || 58 | fail_helper "[key-binding][custom dir] plugin installation fails" 59 | 60 | check_dir_exists_helper "$CUSTOM_PLUGINS_DIR/tmux-example-plugin/" || 61 | fail_helper "[key-binding][custom dir] plugin download fails" 62 | 63 | teardown_helper 64 | rm -rf "$CUSTOM_PLUGINS_DIR" 65 | } 66 | 67 | test_non_existing_plugin_installation_via_tmux_key_binding() { 68 | set_tmux_conf_helper <<- HERE 69 | set -g mode-keys vi 70 | set -g @plugin "tmux-plugins/non-existing-plugin" 71 | run-shell "$TPM_DIR/tpm" 72 | HERE 73 | 74 | "$CURRENT_DIR/expect_failed_plugin_download" || 75 | fail_helper "[key-binding] non existing plugin installation doesn't fail" 76 | 77 | teardown_helper 78 | } 79 | 80 | test_multiple_plugins_installation_via_tmux_key_binding() { 81 | set_tmux_conf_helper <<- HERE 82 | set -g mode-keys vi 83 | set -g @plugin "tmux-plugins/tmux-example-plugin" 84 | \ \ set -g @plugin 'tmux-plugins/tmux-copycat' 85 | run-shell "$TPM_DIR/tpm" 86 | HERE 87 | 88 | "$CURRENT_DIR/expect_successful_multiple_plugins_download" || 89 | fail_helper "[key-binding] multiple plugins installation fails" 90 | 91 | check_dir_exists_helper "$PLUGINS_DIR/tmux-example-plugin/" || 92 | fail_helper "[key-binding] plugin download fails (tmux-example-plugin)" 93 | 94 | check_dir_exists_helper "$PLUGINS_DIR/tmux-copycat/" || 95 | fail_helper "[key-binding] plugin download fails (tmux-copycat)" 96 | 97 | teardown_helper 98 | } 99 | 100 | test_plugins_installation_from_sourced_file_via_tmux_key_binding() { 101 | set_tmux_conf_helper <<- HERE 102 | set -g mode-keys vi 103 | source '$ADDITIONAL_CONFIG_FILE_1' 104 | set -g @plugin 'tmux-plugins/tmux-example-plugin' 105 | run-shell "$TPM_DIR/tpm" 106 | HERE 107 | 108 | mkdir ~/.tmux 109 | echo "set -g @plugin 'tmux-plugins/tmux-copycat'" > "$ADDITIONAL_CONFIG_FILE_1" 110 | 111 | "$CURRENT_DIR/expect_successful_multiple_plugins_download" || 112 | fail_helper "[key-binding][sourced file] plugins installation fails" 113 | 114 | check_dir_exists_helper "$PLUGINS_DIR/tmux-example-plugin/" || 115 | fail_helper "[key-binding][sourced file] plugin download fails (tmux-example-plugin)" 116 | 117 | check_dir_exists_helper "$PLUGINS_DIR/tmux-copycat/" || 118 | fail_helper "[key-binding][sourced file] plugin download fails (tmux-copycat)" 119 | 120 | teardown_helper 121 | } 122 | 123 | test_plugins_installation_from_multiple_sourced_files_via_tmux_key_binding() { 124 | set_tmux_conf_helper <<- HERE 125 | set -g mode-keys vi 126 | \ \ source '$ADDITIONAL_CONFIG_FILE_1' 127 | source-file '$ADDITIONAL_CONFIG_FILE_2' 128 | run-shell "$TPM_DIR/tpm" 129 | HERE 130 | 131 | mkdir ~/.tmux 132 | echo "set -g @plugin 'tmux-plugins/tmux-example-plugin'" > "$ADDITIONAL_CONFIG_FILE_1" 133 | echo " set -g @plugin 'tmux-plugins/tmux-copycat'" > "$ADDITIONAL_CONFIG_FILE_2" 134 | 135 | "$CURRENT_DIR/expect_successful_multiple_plugins_download" || 136 | fail_helper "[key-binding][multiple sourced files] plugins installation fails" 137 | 138 | check_dir_exists_helper "$PLUGINS_DIR/tmux-example-plugin/" || 139 | fail_helper "[key-binding][multiple sourced files] plugin download fails (tmux-example-plugin)" 140 | 141 | check_dir_exists_helper "$PLUGINS_DIR/tmux-copycat/" || 142 | fail_helper "[key-binding][multiple sourced files] plugin download fails (tmux-copycat)" 143 | 144 | teardown_helper 145 | } 146 | 147 | # SCRIPT TESTS 148 | 149 | test_plugin_installation_via_script() { 150 | set_tmux_conf_helper <<- HERE 151 | set -g mode-keys vi 152 | set -g @plugin "tmux-plugins/tmux-example-plugin" 153 | run-shell "$TPM_DIR/tpm" 154 | HERE 155 | 156 | script_run_helper "$TPM_DIR/bin/install_plugins" '"tmux-example-plugin" download success' || 157 | fail_helper "[script] plugin installation fails" 158 | 159 | check_dir_exists_helper "$PLUGINS_DIR/tmux-example-plugin/" || 160 | fail_helper "[script] plugin download fails" 161 | 162 | script_run_helper "$TPM_DIR/bin/install_plugins" 'Already installed "tmux-example-plugin"' || 163 | fail_helper "[script] plugin already installed message fail" 164 | 165 | teardown_helper 166 | } 167 | 168 | test_plugin_installation_custom_dir_via_script() { 169 | set_tmux_conf_helper <<- HERE 170 | set -g mode-keys vi 171 | set-environment -g TMUX_PLUGIN_MANAGER_PATH '$CUSTOM_PLUGINS_DIR' 172 | 173 | set -g @plugin "tmux-plugins/tmux-example-plugin" 174 | run-shell "$TPM_DIR/tpm" 175 | HERE 176 | 177 | script_run_helper "$TPM_DIR/bin/install_plugins" '"tmux-example-plugin" download success' || 178 | fail_helper "[script][custom dir] plugin installation fails" 179 | 180 | check_dir_exists_helper "$CUSTOM_PLUGINS_DIR/tmux-example-plugin/" || 181 | fail_helper "[script][custom dir] plugin download fails" 182 | 183 | script_run_helper "$TPM_DIR/bin/install_plugins" 'Already installed "tmux-example-plugin"' || 184 | fail_helper "[script][custom dir] plugin already installed message fail" 185 | 186 | teardown_helper 187 | rm -rf "$CUSTOM_PLUGINS_DIR" 188 | } 189 | 190 | test_non_existing_plugin_installation_via_script() { 191 | set_tmux_conf_helper <<- HERE 192 | set -g mode-keys vi 193 | set -g @plugin "tmux-plugins/non-existing-plugin" 194 | run-shell "$TPM_DIR/tpm" 195 | HERE 196 | 197 | local expected_exit_code=1 198 | script_run_helper "$TPM_DIR/bin/install_plugins" '"non-existing-plugin" download fail' "$expected_exit_code" || 199 | fail_helper "[script] non existing plugin installation doesn't fail" 200 | 201 | teardown_helper 202 | } 203 | 204 | test_multiple_plugins_installation_via_script() { 205 | set_tmux_conf_helper <<- HERE 206 | set -g mode-keys vi 207 | set -g @plugin "tmux-plugins/tmux-example-plugin" 208 | \ \ set -g @plugin 'tmux-plugins/tmux-copycat' 209 | run-shell "$TPM_DIR/tpm" 210 | HERE 211 | 212 | script_run_helper "$TPM_DIR/bin/install_plugins" '"tmux-example-plugin" download success' || 213 | fail_helper "[script] multiple plugins installation fails" 214 | 215 | check_dir_exists_helper "$PLUGINS_DIR/tmux-example-plugin/" || 216 | fail_helper "[script] plugin download fails (tmux-example-plugin)" 217 | 218 | check_dir_exists_helper "$PLUGINS_DIR/tmux-copycat/" || 219 | fail_helper "[script] plugin download fails (tmux-copycat)" 220 | 221 | script_run_helper "$TPM_DIR/bin/install_plugins" 'Already installed "tmux-copycat"' || 222 | fail_helper "[script] multiple plugins already installed message fail" 223 | 224 | teardown_helper 225 | } 226 | 227 | test_plugins_installation_from_sourced_file_via_script() { 228 | set_tmux_conf_helper <<- HERE 229 | set -g mode-keys vi 230 | source '$ADDITIONAL_CONFIG_FILE_1' 231 | set -g @plugin 'tmux-plugins/tmux-example-plugin' 232 | run-shell "$TPM_DIR/tpm" 233 | HERE 234 | 235 | mkdir ~/.tmux 236 | echo "set -g @plugin 'tmux-plugins/tmux-copycat'" > "$ADDITIONAL_CONFIG_FILE_1" 237 | 238 | script_run_helper "$TPM_DIR/bin/install_plugins" '"tmux-copycat" download success' || 239 | fail_helper "[script][sourced file] plugins installation fails" 240 | 241 | check_dir_exists_helper "$PLUGINS_DIR/tmux-example-plugin/" || 242 | fail_helper "[script][sourced file] plugin download fails (tmux-example-plugin)" 243 | 244 | check_dir_exists_helper "$PLUGINS_DIR/tmux-copycat/" || 245 | fail_helper "[script][sourced file] plugin download fails (tmux-copycat)" 246 | 247 | script_run_helper "$TPM_DIR/bin/install_plugins" 'Already installed "tmux-copycat"' || 248 | fail_helper "[script][sourced file] plugins already installed message fail" 249 | 250 | teardown_helper 251 | } 252 | 253 | test_plugins_installation_from_multiple_sourced_files_via_script() { 254 | set_tmux_conf_helper <<- HERE 255 | set -g mode-keys vi 256 | \ \ source '$ADDITIONAL_CONFIG_FILE_1' 257 | source-file '$ADDITIONAL_CONFIG_FILE_2' 258 | set -g @plugin 'tmux-plugins/tmux-example-plugin' 259 | run-shell "$TPM_DIR/tpm" 260 | HERE 261 | 262 | mkdir ~/.tmux 263 | echo " set -g @plugin 'tmux-plugins/tmux-copycat'" > "$ADDITIONAL_CONFIG_FILE_1" 264 | echo "set -g @plugin 'tmux-plugins/tmux-sensible'" > "$ADDITIONAL_CONFIG_FILE_2" 265 | 266 | script_run_helper "$TPM_DIR/bin/install_plugins" '"tmux-sensible" download success' || 267 | fail_helper "[script][multiple sourced files] plugins installation fails" 268 | 269 | check_dir_exists_helper "$PLUGINS_DIR/tmux-example-plugin/" || 270 | fail_helper "[script][multiple sourced files] plugin download fails (tmux-example-plugin)" 271 | 272 | check_dir_exists_helper "$PLUGINS_DIR/tmux-copycat/" || 273 | fail_helper "[script][multiple sourced files] plugin download fails (tmux-copycat)" 274 | 275 | check_dir_exists_helper "$PLUGINS_DIR/tmux-sensible/" || 276 | fail_helper "[script][multiple sourced files] plugin download fails (tmux-sensible)" 277 | 278 | script_run_helper "$TPM_DIR/bin/install_plugins" 'Already installed "tmux-sensible"' || 279 | fail_helper "[script][multiple sourced files] plugins already installed message fail" 280 | 281 | teardown_helper 282 | } 283 | 284 | run_tests 285 | -------------------------------------------------------------------------------- /tests/test_plugin_installation_legacy.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | CURRENT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )" 4 | PLUGINS_DIR="$HOME/.tmux/plugins" 5 | TPM_DIR="$PWD" 6 | 7 | source "$CURRENT_DIR/helpers/helpers.sh" 8 | source "$CURRENT_DIR/helpers/tpm.sh" 9 | 10 | # TMUX KEY-BINDING TESTS 11 | 12 | test_plugin_installation_via_tmux_key_binding() { 13 | set_tmux_conf_helper <<- HERE 14 | set -g mode-keys vi 15 | set -g @tpm_plugins "tmux-plugins/tmux-example-plugin" 16 | run-shell "$TPM_DIR/tpm" 17 | HERE 18 | 19 | # opens tmux and test it with `expect` 20 | $CURRENT_DIR/expect_successful_plugin_download || 21 | fail_helper "[key-binding] plugin installation fails" 22 | 23 | # check plugin dir exists after download 24 | check_dir_exists_helper "$PLUGINS_DIR/tmux-example-plugin/" || 25 | fail_helper "[key-binding] plugin download fails" 26 | 27 | teardown_helper 28 | } 29 | 30 | test_legacy_and_new_syntax_for_plugin_installation_work_via_tmux_key_binding() { 31 | set_tmux_conf_helper <<- HERE 32 | set -g mode-keys vi 33 | set -g @tpm_plugins " \ 34 | tmux-plugins/tmux-example-plugin \ 35 | " 36 | set -g @plugin 'tmux-plugins/tmux-copycat' 37 | run-shell "$TPM_DIR/tpm" 38 | HERE 39 | 40 | # opens tmux and test it with `expect` 41 | "$CURRENT_DIR"/expect_successful_multiple_plugins_download || 42 | fail_helper "[key-binding] multiple plugins installation fails" 43 | 44 | # check plugin dir exists after download 45 | check_dir_exists_helper "$PLUGINS_DIR/tmux-example-plugin/" || 46 | fail_helper "[key-binding] plugin download fails (tmux-example-plugin)" 47 | 48 | check_dir_exists_helper "$PLUGINS_DIR/tmux-copycat/" || 49 | fail_helper "[key-binding] plugin download fails (tmux-copycat)" 50 | 51 | teardown_helper 52 | } 53 | 54 | # SCRIPT TESTS 55 | 56 | test_plugin_installation_via_script() { 57 | set_tmux_conf_helper <<- HERE 58 | set -g mode-keys vi 59 | set -g @tpm_plugins "tmux-plugins/tmux-example-plugin" 60 | run-shell "$TPM_DIR/tpm" 61 | HERE 62 | 63 | script_run_helper "$TPM_DIR/bin/install_plugins" '"tmux-example-plugin" download success' || 64 | fail_helper "[script] plugin installation fails" 65 | 66 | check_dir_exists_helper "$PLUGINS_DIR/tmux-example-plugin/" || 67 | fail_helper "[script] plugin download fails" 68 | 69 | script_run_helper "$TPM_DIR/bin/install_plugins" 'Already installed "tmux-example-plugin"' || 70 | fail_helper "[script] plugin already installed message fail" 71 | 72 | teardown_helper 73 | } 74 | 75 | test_legacy_and_new_syntax_for_plugin_installation_work_via_script() { 76 | set_tmux_conf_helper <<- HERE 77 | set -g mode-keys vi 78 | set -g @tpm_plugins " \ 79 | tmux-plugins/tmux-example-plugin \ 80 | " 81 | set -g @plugin 'tmux-plugins/tmux-copycat' 82 | run-shell "$TPM_DIR/tpm" 83 | HERE 84 | 85 | script_run_helper "$TPM_DIR/bin/install_plugins" '"tmux-example-plugin" download success' || 86 | fail_helper "[script] multiple plugin installation fails" 87 | 88 | check_dir_exists_helper "$PLUGINS_DIR/tmux-example-plugin/" || 89 | fail_helper "[script] plugin download fails (tmux-example-plugin)" 90 | 91 | check_dir_exists_helper "$PLUGINS_DIR/tmux-copycat/" || 92 | fail_helper "[script] plugin download fails (tmux-copycat)" 93 | 94 | script_run_helper "$TPM_DIR/bin/install_plugins" 'Already installed "tmux-copycat"' || 95 | fail_helper "[script] multiple plugins already installed message fail" 96 | 97 | teardown_helper 98 | } 99 | 100 | run_tests 101 | -------------------------------------------------------------------------------- /tests/test_plugin_sourcing.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | CURRENT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )" 4 | TPM_DIR="$PWD" 5 | PLUGINS_DIR="$HOME/.tmux/plugins" 6 | 7 | CUSTOM_PLUGINS_DIR="$HOME/foo/plugins" 8 | 9 | source "$CURRENT_DIR/helpers/helpers.sh" 10 | source "$CURRENT_DIR/helpers/tpm.sh" 11 | 12 | check_binding_defined() { 13 | local binding="$1" 14 | tmux list-keys | grep -q "$binding" 15 | } 16 | 17 | create_test_plugin_helper() { 18 | local plugin_path="$PLUGINS_DIR/tmux_test_plugin/" 19 | rm -rf "$plugin_path" 20 | mkdir -p "$plugin_path" 21 | 22 | while read line; do 23 | echo "$line" >> "$plugin_path/test_plugin.tmux" 24 | done 25 | chmod +x "$plugin_path/test_plugin.tmux" 26 | } 27 | 28 | check_tpm_path() { 29 | local correct_tpm_path="$1" 30 | local tpm_path="$(tmux start-server\; show-environment -g TMUX_PLUGIN_MANAGER_PATH | cut -f2 -d=)" 31 | [ "$correct_tpm_path" == "$tpm_path" ] 32 | } 33 | 34 | test_plugin_sourcing() { 35 | set_tmux_conf_helper <<- HERE 36 | set -g mode-keys vi 37 | set -g @plugin "doesnt_matter/tmux_test_plugin" 38 | run-shell "$TPM_DIR/tpm" 39 | HERE 40 | 41 | # manually creates a local tmux plugin 42 | create_test_plugin_helper <<- HERE 43 | tmux bind-key R run-shell foo_command 44 | HERE 45 | 46 | tmux new-session -d # tmux starts detached 47 | check_binding_defined "R run-shell foo_command" || 48 | fail_helper "Plugin sourcing fails" 49 | 50 | teardown_helper 51 | } 52 | 53 | test_default_tpm_path() { 54 | set_tmux_conf_helper <<- HERE 55 | set -g mode-keys vi 56 | run-shell "$TPM_DIR/tpm" 57 | HERE 58 | 59 | check_tpm_path "${PLUGINS_DIR}/" || 60 | fail_helper "Default TPM path not correct" 61 | 62 | teardown_helper 63 | } 64 | 65 | test_custom_tpm_path() { 66 | set_tmux_conf_helper <<- HERE 67 | set -g mode-keys vi 68 | set-environment -g TMUX_PLUGIN_MANAGER_PATH '$CUSTOM_PLUGINS_DIR' 69 | run-shell "$TPM_DIR/tpm" 70 | HERE 71 | 72 | check_tpm_path "$CUSTOM_PLUGINS_DIR" || 73 | fail_helper "Custom TPM path not correct" 74 | 75 | teardown_helper 76 | } 77 | 78 | run_tests 79 | -------------------------------------------------------------------------------- /tests/test_plugin_update.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | CURRENT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )" 4 | TPM_DIR="$PWD" 5 | PLUGINS_DIR="$HOME/.tmux/plugins" 6 | 7 | source "$CURRENT_DIR/helpers/helpers.sh" 8 | source "$CURRENT_DIR/helpers/tpm.sh" 9 | 10 | manually_install_the_plugin() { 11 | mkdir -p "$PLUGINS_DIR" 12 | cd "$PLUGINS_DIR" 13 | git clone --quiet https://github.com/tmux-plugins/tmux-example-plugin 14 | } 15 | 16 | # TMUX KEY-BINDING TESTS 17 | 18 | test_plugin_update_via_tmux_key_binding() { 19 | set_tmux_conf_helper <<- HERE 20 | set -g mode-keys vi 21 | set -g @plugin "tmux-plugins/tmux-example-plugin" 22 | run-shell "$TPM_DIR/tpm" 23 | HERE 24 | 25 | manually_install_the_plugin 26 | 27 | "$CURRENT_DIR/expect_successful_update_of_all_plugins" || 28 | fail_helper "[key-binding] 'update all plugins' fails" 29 | 30 | "$CURRENT_DIR/expect_successful_update_of_a_single_plugin" || 31 | fail_helper "[key-binding] 'update single plugin' fails" 32 | 33 | teardown_helper 34 | } 35 | 36 | # SCRIPT TESTS 37 | 38 | test_plugin_update_via_script() { 39 | set_tmux_conf_helper <<- HERE 40 | set -g mode-keys vi 41 | set -g @plugin "tmux-plugins/tmux-example-plugin" 42 | run-shell "$TPM_DIR/tpm" 43 | HERE 44 | 45 | manually_install_the_plugin 46 | 47 | local expected_exit_code=1 48 | script_run_helper "$TPM_DIR/bin/update_plugins" 'usage' "$expected_exit_code" || 49 | fail_helper "[script] running update plugins without args should fail" 50 | 51 | script_run_helper "$TPM_DIR/bin/update_plugins tmux-example-plugin" '"tmux-example-plugin" update success' || 52 | fail_helper "[script] plugin update fails" 53 | 54 | script_run_helper "$TPM_DIR/bin/update_plugins all" '"tmux-example-plugin" update success' || 55 | fail_helper "[script] update all plugins fails" 56 | 57 | teardown_helper 58 | } 59 | 60 | run_tests 61 | -------------------------------------------------------------------------------- /tpm: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | CURRENT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )" 4 | BINDINGS_DIR="$CURRENT_DIR/bindings" 5 | SCRIPTS_DIR="$CURRENT_DIR/scripts" 6 | 7 | source "$SCRIPTS_DIR/variables.sh" 8 | 9 | get_tmux_option() { 10 | local option="$1" 11 | local default_value="$2" 12 | local option_value="$(tmux show-option -gqv "$option")" 13 | if [ -z "$option_value" ]; then 14 | echo "$default_value" 15 | else 16 | echo "$option_value" 17 | fi 18 | } 19 | 20 | tpm_path_set() { 21 | tmux show-environment -g "$DEFAULT_TPM_ENV_VAR_NAME" >/dev/null 2>&1 22 | } 23 | 24 | # Check if configuration file exists at an XDG-compatible location, if so use 25 | # that directory for TMUX_PLUGIN_MANAGER_PATH. Otherwise use $DEFAULT_TPM_PATH. 26 | set_default_tpm_path() { 27 | local xdg_tmux_path="${XDG_CONFIG_HOME:-$HOME/.config}/tmux" 28 | local tpm_path="$DEFAULT_TPM_PATH" 29 | 30 | if [ -f "$xdg_tmux_path/tmux.conf" ]; then 31 | tpm_path="$xdg_tmux_path/plugins/" 32 | fi 33 | 34 | tmux set-environment -g "$DEFAULT_TPM_ENV_VAR_NAME" "$tpm_path" 35 | } 36 | 37 | # Ensures TMUX_PLUGIN_MANAGER_PATH global env variable is set. 38 | # 39 | # Put this in `.tmux.conf` to override the default: 40 | # `set-environment -g TMUX_PLUGIN_MANAGER_PATH "/some/other/path/"` 41 | set_tpm_path() { 42 | if ! tpm_path_set; then 43 | set_default_tpm_path 44 | fi 45 | } 46 | 47 | # 1. Fetches plugin names from `@plugin` variables 48 | # 2. Creates full plugin path 49 | # 3. Sources all *.tmux files from each of the plugin directories 50 | # - no errors raised if directory does not exist 51 | # Files are sourced as tmux config files, not as shell scripts! 52 | source_plugins() { 53 | "$SCRIPTS_DIR/source_plugins.sh" >/dev/null 2>&1 54 | } 55 | 56 | # prefix + I - downloads TPM plugins and reloads TMUX environment 57 | # prefix + U - updates a plugin (or all of them) and reloads TMUX environment 58 | # prefix + alt + u - remove unused TPM plugins and reloads TMUX environment 59 | set_tpm_key_bindings() { 60 | local install_key="$(get_tmux_option "$install_key_option" "$default_install_key")" 61 | tmux bind-key "$install_key" run-shell "$BINDINGS_DIR/install_plugins" 62 | 63 | local update_key="$(get_tmux_option "$update_key_option" "$default_update_key")" 64 | tmux bind-key "$update_key" run-shell "$BINDINGS_DIR/update_plugins" 65 | 66 | local clean_key="$(get_tmux_option "$clean_key_option" "$default_clean_key")" 67 | tmux bind-key "$clean_key" run-shell "$BINDINGS_DIR/clean_plugins" 68 | } 69 | 70 | supported_tmux_version_ok() { 71 | "$SCRIPTS_DIR/check_tmux_version.sh" "$SUPPORTED_TMUX_VERSION" 72 | } 73 | 74 | main() { 75 | if supported_tmux_version_ok; then 76 | set_tpm_path 77 | set_tpm_key_bindings 78 | source_plugins 79 | fi 80 | } 81 | main 82 | --------------------------------------------------------------------------------