├── LICENSE.md ├── README.md └── fpp.tmux /LICENSE.md: -------------------------------------------------------------------------------- 1 | Copyright (C) Joshua Boy Nicolai Appelman 2 | 3 | Permission is hereby granted, free of charge, to any person obtaining 4 | a copy of this software and associated documentation files (the "Software"), 5 | to deal in the Software without restriction, including without limitation 6 | the rights to use, copy, modify, merge, publish, distribute, sublicense, 7 | and/or sell copies of the Software, and to permit persons to whom the 8 | Software is furnished to do so, subject to the following conditions: 9 | 10 | The above copyright notice and this permission notice shall be included 11 | in all copies or substantial portions of the Software. 12 | 13 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 14 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES 15 | OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 16 | IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, 17 | DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 18 | TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE 19 | OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 20 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Tmux fpp 2 | 3 | Plugin wrapper around [Facebook PathPicker](http://facebook.github.io/PathPicker/). 4 | 5 | Quickly open any path on your terminal window in your `$EDITOR` of choice! 6 | 7 | ### Demo 8 | 9 | [![Demo tmux-fpp](http://g.recordit.co/MhLPNgOKyN.gif)](http://recordit.co/MhLPNgOKyN) 10 | 11 | ### Dependencies 12 | 13 | - `fpp` - Facebook PathPicker. 14 | 15 | ### Key bindings 16 | 17 | - `prefix + f` - open a new window with a fpp selection of your current tmux pane. 18 | 19 | ### Installation with [Tmux Plugin Manager](https://github.com/tmux-plugins/tpm) (recommended) 20 | 21 | Add plugin to the list of TPM plugins in `.tmux.conf`: 22 | 23 | set -g @plugin 'tmux-plugins/tmux-fpp' 24 | 25 | Hit `prefix + I` to fetch the plugin and source it. You should now be able to 26 | use the plugin. 27 | 28 | ### Manual Installation 29 | 30 | Clone the repo: 31 | 32 | $ git clone https://github.com/tmux-plugins/tmux-fpp ~/clone/path 33 | 34 | Add this line to the bottom of `.tmux.conf`: 35 | 36 | run-shell ~/clone/path/fpp.tmux 37 | 38 | Reload TMUX environment: 39 | 40 | # type this in terminal 41 | $ tmux source-file ~/.tmux.conf 42 | 43 | You should now be able to use the plugin. 44 | 45 | ### Configuration 46 | 47 | > How can I change the default "f" key binding to something else? For example, 48 | > key "x"? 49 | 50 | Put `set -g @fpp-key 'x'` in `tmux.conf`. 51 | 52 | > How can I paste the selected file paths into my original pane, instead of 53 | > launching an editor? 54 | 55 | Put `set -g @fpp-mode 'paste'` in `tmux.conf`. 56 | 57 | Alternatively you can bind both behaviours to different keys manually: 58 | 59 | ```sh 60 | # Disable default binding 61 | set -g @fpp-bind off 62 | 63 | # Bind 'f' to run FPP launching an editor 64 | bind-key f run-shell '~/.tmux/plugins/tmux-fpp/fpp.tmux start edit' 65 | 66 | # Bind 'x' to run FPP and paste the list of files in the initial pane 67 | bind-key x run-shell '~/.tmux/plugins/tmux-fpp/fpp.tmux start paste' 68 | ``` 69 | 70 | > How can I specify custom path to fpp? 71 | 72 | Put `set -g @fpp-path '~/my/path/fpp'` in `tmux.conf`. 73 | 74 | ### Other goodies 75 | 76 | `tmux-fpp` works great with: 77 | 78 | - [tmux-urlview](https://github.com/jbnicolai/tmux-urlview) - a plugin for 79 | quickly opening any url on your terminal window 80 | - [tmux-copycat](https://github.com/tmux-plugins/tmux-copycat) - a plugin for 81 | regex searches in tmux and fast match selection 82 | - [tmux-yank](https://github.com/tmux-plugins/tmux-yank) - enables copying 83 | highlighted text to system clipboard 84 | 85 | ### License 86 | 87 | [MIT](LICENSE.md) 88 | -------------------------------------------------------------------------------- /fpp.tmux: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | set -Eeu -o pipefail 3 | 4 | # This tmux plugin respects the following options: 5 | # @fpp-bind on/off 6 | # - Whether to bind keys on initialization. 7 | # - Defaults to 'on'. 8 | # @fpp-key 9 | # - The tmux key to bind to launching FPP. 10 | # - Defaults to 'f'. 11 | # @fpp-mode edit/paste 12 | # - Whether to launch EDITOR after FPP, or paste the file list into the 13 | # invoking pane. 14 | # - Defaults to 'edit'. 15 | # @fpp-path 16 | # - Custom path to FPP. 17 | # - Default to 'fpp'. 18 | # 19 | # This script has several entry points. With no arguments, it defaults to 'init'. 20 | # The entrypoints are defined by functions prefixed with `tmux_fpp_…`: 21 | # init 22 | # - Sets default key bindings, according to the above options. 23 | # start $mode 24 | # - Start FPP in a new window. 25 | # - edit: FPP will launch an editor in that temporary window. 26 | # - paste: Pastes the selected file list back into the original pane. 27 | # 28 | # There are also internal entry points for handling the behaviour above: 29 | # internal_run 30 | # - Invoked in then new window; launches FPP itself and performs cleanup. 31 | # internal_finish_paste 32 | # - Invoked by FPP, if using paste mode, after selecting files. 33 | # - Handles pasting the file list into the original buffer. 34 | 35 | # Bind the key to run the "start" command. 36 | # Defaults to 'f' using mode 'edit'. 37 | tmux_fpp_init() { 38 | local should_bind key mode 39 | 40 | # @fpp-bind can be set to 'off' to prevent binding keys, 41 | # in case the user wants to do all the binding on their own. 42 | # By default, we will bind keys. 43 | should_bind="$(tmux show-option -gqv @fpp-bind)" || true 44 | : "${should_bind:=on}" 45 | 46 | # If @fpp-bind was set to anything except 'on', do not bind. 47 | [ "${should_bind}" = on ] || return 0 48 | 49 | # @fpp-key determines which key to bind. 50 | # Defaults to 'f'. 51 | key="$(tmux show-option -gqv @fpp-key)" || true 52 | : "${key:=f}" 53 | 54 | # @fpp-mode can be 'edit' or 'paste'. 55 | # Defaults to 'edit'. 56 | mode="$(tmux show-option -gqv @fpp-mode)" || true 57 | : "${mode:=edit}" 58 | 59 | tmux bind-key -N "Facebook Path Picker" "${key}" run-shell "$(printf '%q start %q' "${BASH_SOURCE[0]}" "${mode}")" 60 | } 61 | 62 | # Save the buffer contents and create a new window for running FPP. 63 | tmux_fpp_start() { 64 | local fpp_path mode target_pane_id mode tmpfile 65 | 66 | # @fpp-path determines path to FPP. 67 | # Defaults to 'fpp'. 68 | fpp_path="$(tmux show-option -gqv @fpp-path)" || true 69 | : "${fpp_path:=fpp}" 70 | 71 | # Display error if fpp is not found. 72 | if ! command -v "${fpp_path}" &> /dev/null; then 73 | tmux display-message "tmux-fpp: fpp is not found" 74 | # Intentionally not returning non zero here to exit gracefully. 75 | return 76 | fi 77 | 78 | # Remember the invocation mode 79 | mode="${1}" 80 | 81 | # Remember the current pane ID 82 | target_pane_id="$(tmux display -p '#{pane_id}')" || return $? 83 | 84 | # Create a temporary file to hold the pane contents 85 | tmpfile="$(mktemp -t tmux-fpp-buffer.XXXXXX)" || return $? 86 | 87 | # If we exit prematurely, clean up the temp file. 88 | # Otherwise, it's cleaned up in the "run" invocation after piping to fpp. 89 | trap 'rm -f "${tmpfile}"' ERR RETURN 90 | 91 | # Save the pane contents to the temporary file. 92 | tmux capture-pane -Jp > "${tmpfile}" 93 | 94 | # Create a new window, running the "tmux_fpp_internal_run" function. 95 | # It will run fpp and clean up the temp file. 96 | tmux \ 97 | new-window \ 98 | -n fpp \ 99 | -c '#{pane_current_path}' \ 100 | "${BASH_SOURCE[0]}" internal_run \ 101 | "${mode}" "${target_pane_id}" "${tmpfile}" "${fpp_path}" \ 102 | ; 103 | 104 | # If we made it here, the new window (tmux_fpp_internal_run) will handle cleanup. 105 | trap - ERR RETURN 106 | } 107 | 108 | # Execute FPP and clean up the temporary buffer contents file. 109 | tmux_fpp_internal_run() { 110 | local mode target_pane_id tmpfile 111 | mode="${1}" 112 | target_pane_id="${2}" 113 | tmpfile="${3}" 114 | fpp_path="${4}" 115 | 116 | # Clean up the temp file at the end, no matter what. 117 | trap 'rm -f "${tmpfile}"' ERR RETURN 118 | 119 | # Construct the command arguments for running fpp. 120 | local fpp_cmd 121 | fpp_cmd=($fpp_path) 122 | case "${mode}" in 123 | paste) 124 | # In 'paste' mode, we execute tmux_fpp_finish_paste with the file list. 125 | # This pastes the selected file list into the original pane. 126 | fpp_cmd+=(-c "${BASH_SOURCE[0]}" internal_finish_paste "${target_pane_id}") 127 | ;; 128 | edit|*) 129 | # In 'edit' mode, just let fpp do what it would normally do 130 | # (i.e. launch EDITOR or FPP_EDITOR in the fpp window). 131 | ;; 132 | esac 133 | 134 | # Run fpp with the buffer contents. 135 | "${fpp_cmd[@]}" < "${tmpfile}" 136 | 137 | # (The trap will remove tmpfile at the end). 138 | } 139 | 140 | # Executed after FPP completes if we ran in 'paste' mode. 141 | # Paste the quoted list of file names back into the original buffer. 142 | tmux_fpp_internal_finish_paste() { 143 | local target_pane_id 144 | target_pane_id="${1}" 145 | shift 146 | 147 | # Quote each of the file arguments 148 | local output f 149 | output=() 150 | for f in "$@"; do 151 | output+=("$(printf %q "$f")") 152 | done 153 | 154 | # Paste the list of files back to our original pane. 155 | tmux \ 156 | set-buffer "${output[*]}" ';' \ 157 | paste-buffer -t "${target_pane_id}" ';' \ 158 | ; 159 | } 160 | 161 | # Choose the function to run based on the arguments. 162 | run_func() { 163 | local func 164 | func="tmux_fpp_${1:-init}" 165 | 166 | if [ "$(type -t "${func}" || true)" = function ]; then 167 | "${func}" "${@+${@:2}}" 168 | else 169 | echo 'Bad arguments: $*' >&2 170 | return 1 171 | fi 172 | } 173 | 174 | run_func "$@" 175 | --------------------------------------------------------------------------------