├── .gitignore ├── LICENSE ├── README.md └── kakboard.kak /.gitignore: -------------------------------------------------------------------------------- 1 | # .gitignore 2 | 3 | # Backups 4 | *~ 5 | 6 | # MAC stuff 7 | .DS_Store 8 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2019 Zach Peltzer 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the \"Software\"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | 23 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # kakboard 2 | 3 | Clipboard integration for [kakoune](https://kakoune.org). 4 | 5 | 6 | ## Installation 7 | 8 | ### With [plug.kak](https://github.com/andreyorst/plug.kak) (recommended) 9 | 10 | Just add this to your `kakrc`: 11 | ``` 12 | plug "lePerdu/kakboard" %{ 13 | hook global WinCreate .* %{ kakboard-enable } 14 | } 15 | ``` 16 | 17 | ### Manually 18 | 19 | There are two methods: 20 | 21 | 1. Clone this repository and `source` the file `kakboard.kak` in your `kakrc`, or 22 | 2. Simply clone the repo into your `autoload` subdirectory. 23 | 24 | Then, set it up to run with: 25 | ``` 26 | hook global WinCreate .* %{ kakboard-enable } 27 | ``` 28 | 29 | 30 | ## Usage 31 | 32 | Just copy and paste with the normal commands (`y`, `c`, `p`, `R`, etc.)! Copy 33 | keys copy the main selection to the system clipboard and paste commands sync the 34 | system clipboard with the `"` register before executing. Copying/pasting to/from 35 | the system clipboard can be prevented by specifying a register to use, even the 36 | default `"` register. 37 | 38 | ### Configuration 39 | 40 | The `kakboard_copy_cmd` and `kakboard_paste_cmd` options specify the commands to 41 | copy to and paste from the system clipboard. If they are unset, kakboard will 42 | try to detect command pair to use. 43 | 44 | Currently supports: 45 | 46 | - [wl-clipboard](https://github.com/bugaevc/wl-clipboard) (Wayland) 47 | - [xsel](http://www.kfish.org/software/xsel/) 48 | - [xclip](https://github.com/astrand/xclip) 49 | - pbcopy/pbpaste (macOS) 50 | 51 | To change the keys for which clipboard syncing is done, just set the 52 | `kakboard_copy_keys` and `kakboard_paste_keys` options. 53 | 54 | Note: This plugin will map all of the keys in `kakboard_paste_keys` and 55 | `kakboard_copy_keys`, so if you already have mappings for these keys, you will 56 | have to edit those bindings to call `kakboard-{pull,push}-if-unset` to sync the 57 | clipboard after copying / before pasting and remove said keys from kakboard's 58 | lists. 59 | 60 | ### Commands 61 | 62 | - `kakboard-enable`/`kakboard-disable`/`kakboard-toggle`: enable/disable/toggle 63 | clipboard integration 64 | - `kakboard-pull-clipboard`: Pull system clipboard into the `"` register. 65 | - `kakboard-pull-if-unset`: Call `kakboard-pull-clipboard` if 66 | `%val{register}` is empty. 67 | - `kakboard-with-pull-clipboard `: Call `kakboard-pull-if-unset` then 68 | execute ``. 69 | - `kakboard-push-clipboard`: Set system clipboard from the `"` register. 70 | - `kakboard-push-if-unset`: Call `kakboard-push-clipboard` if 71 | `%val{register}` is empty. 72 | - `kakboard-with-push-clipboard `: Execute `` then call 73 | `kakboard-push-if-unset` 74 | 75 | 76 | ## Limitations 77 | 78 | System clipboards don't support multiple selections, so only the primary 79 | selection is copied to the clipboard. Correspondingly, when the `"` register is 80 | synced to the system clipboard, it is filled with a single value and remaining 81 | values, if any, are deleted. To get around this, the `"` register can be 82 | specified explicitly when pasting multiple selections (before syncing with the 83 | system clipboard) as mentioned above. 84 | 85 | 86 | ## License 87 | 88 | MIT License 89 | -------------------------------------------------------------------------------- /kakboard.kak: -------------------------------------------------------------------------------- 1 | 2 | declare-option -docstring 'command to copy to clipboard' \ 3 | str kakboard_copy_cmd 4 | 5 | declare-option -docstring 'command to paste from clipboard' \ 6 | str kakboard_paste_cmd 7 | 8 | declare-option -docstring 'keys to pull clipboard for' \ 9 | str-list kakboard_paste_keys p P R 10 | 11 | declare-option -docstring 'keys to copy to clipboard' \ 12 | str-list kakboard_copy_keys y c d 13 | 14 | declare-option -hidden bool kakboard_enabled false 15 | 16 | define-command -docstring 'copy system clipboard into the " register' \ 17 | kakboard-pull-clipboard %{ evaluate-commands %sh{ 18 | # Shell expansions are stripped of new lines, so the output of the 19 | # command has to be wrapped in quotes (and its quotes escaped) 20 | # 21 | # (All of this quoting and escaping really messes up kakoune's syntax 22 | # highlighter) 23 | if test -n "$kak_opt_kakboard_paste_cmd"; then 24 | # This doesn't always work because sed appends a new line regardless of 25 | # whether or not there was one at the end of the text on some patforms 26 | # / versions 27 | # printf 'set-register dquote %s' \ 28 | # "'$($kak_opt_kakboard_paste_cmd | sed -e "s/'/''/g"; echo \')" 29 | 30 | # This is probably a lot less efficient, but works more consistently 31 | # mktemp is quite platform-dependant, but this should work on all (most) 32 | # platforms 33 | temp_file=$(mktemp ${TMPDIR:-/tmp}/kakboard-paste-XXXXXX) 34 | temp_file2=$(mktemp ${TMPDIR:-/tmp}/kakboard-paste-XXXXXX) 35 | 36 | eval $kak_opt_kakboard_paste_cmd >$temp_file 37 | printf '%s' "$kak_main_reg_dquote" >$temp_file2 38 | if ! cmp --silent $temp_file $temp_file2; then 39 | echo "set-register dquote %file{$temp_file}" 40 | fi 41 | echo "nop %sh{rm $temp_file 2>/dev/null}" 42 | echo "nop %sh{rm $temp_file2 2>/dev/null}" 43 | else 44 | echo "echo -debug 'kakboard: kakboard_paste_cmd not set'" 45 | fi 46 | }} 47 | 48 | define-command -docstring 'copy system clipboard if current register is unset' \ 49 | kakboard-pull-if-unset %{ evaluate-commands %sh{ 50 | if test -z "$kak_register"; then 51 | echo "kakboard-pull-clipboard" 52 | fi 53 | }} 54 | 55 | # Pull the clipboard and execute the key with the same context 56 | define-command -docstring 'copy system clipboard then execute keys' \ 57 | kakboard-with-pull-clipboard -params 1 %{ 58 | kakboard-pull-if-unset 59 | evaluate-commands %sh{ 60 | if test -n "$kak_register"; then 61 | register="\"$kak_register" 62 | fi 63 | echo "execute-keys -with-hooks -save-regs '' '$register$kak_count$1'" 64 | } 65 | } 66 | 67 | define-command -docstring 'set system clipboard from the " register' \ 68 | kakboard-push-clipboard %{ nop %sh{ 69 | # The copy command is executed and forked in a subshell because some 70 | # commands (looking at you, xclip and wl-copy) block when executed by 71 | # kakoune normally 72 | if test -n "$kak_opt_kakboard_copy_cmd"; then 73 | printf '%s' "$kak_main_reg_dquote" \ 74 | | (eval $kak_opt_kakboard_copy_cmd) >/dev/null 2>&1 & 75 | else 76 | echo "echo -debug 'kakboard: kakboard_copy_cmd not set'" 77 | fi 78 | }} 79 | 80 | define-command -docstring 'set system clipboard if current register is unset' \ 81 | kakboard-push-if-unset %{ evaluate-commands %sh{ 82 | if test -z "$kak_register"; then 83 | echo "kakboard-push-clipboard" 84 | fi 85 | }} 86 | 87 | # Set the clipboard and execute the key with the same context 88 | define-command -docstring 'execute keys then set system clipboard' \ 89 | kakboard-with-push-clipboard -params 1 %{ 90 | evaluate-commands %sh{ 91 | if test -n "$kak_register"; then 92 | register="\"$kak_register" 93 | fi 94 | # Don't preserve registers since we want the same behavior as just 95 | # executing the keys (and don't want to preseve the " register) 96 | echo "execute-keys -with-hooks -save-regs '' '$register$kak_count$1'" 97 | } 98 | # Has to be outside of the sh expansion so that the register environment 99 | # variable will update 100 | kakboard-push-if-unset 101 | } 102 | 103 | define-command -hidden kakboard-autodetect %{ 104 | evaluate-commands %sh{ 105 | # Don't override if there are already commands 106 | if test -n "$kak_opt_kakboard_copy_cmd" -o \ 107 | -n "$kak_opt_kakboard_paste_cmd" 108 | then 109 | exit 110 | fi 111 | 112 | case $(uname -s | tr '[:upper:]' '[:lower:]') in 113 | 'cygwin') 114 | copy='tee /dev/clipboard 2>&-' 115 | paste='cat /dev/clipboard' 116 | ;; 117 | 'darwin'*) 118 | copy='pbcopy' 119 | paste='pbpaste' 120 | ;; 121 | *) 122 | if [ -n "$WAYLAND_DISPLAY" ]; then 123 | if [ -x "$(command -v wl-copy)" ] && [ -x "$(command -v wl-paste)" ]; then 124 | copy='wl-copy' 125 | paste='wl-paste --no-newline' 126 | else 127 | printf '%s\n%s' "echo -debug \"kakboard: can't interact with Wayland's clipboard\"" \ 128 | "echo -debug \"please install 'wl-clipboard'\"" 129 | 130 | exit 1 131 | fi 132 | elif [ -n "$DISPLAY" ]; then 133 | if [ -x "$(command -v xclip)" ]; then 134 | copy='xclip -in -selection clipboard' 135 | paste='xclip -out -selection clipboard' 136 | elif [ -x "$(command -v xsel)" ]; then 137 | copy='xsel --input --clipboard' 138 | paste='xsel --output --clipboard' 139 | else 140 | printf '%s\n%s' "echo -debug \"kakboard: can't interact with Xorg's clipboard\"" \ 141 | "echo -debug \"please install 'xclip' or 'xsel'\"" 142 | 143 | exit 1 144 | fi 145 | else 146 | if [ -x "$(command -v termux-clipboard-set)" ]; then 147 | copy='termux-clipboard-set' 148 | paste='termux-clipboard-get' 149 | else 150 | printf '%s' "echo -debug \"kakboard: this system is not supported\"" 151 | 152 | exit 1 153 | fi 154 | fi 155 | ;; 156 | esac 157 | 158 | printf '%s\n%s' "set-option global kakboard_copy_cmd '$copy'" \ 159 | "set-option global kakboard_paste_cmd '$paste'" 160 | } 161 | } 162 | 163 | define-command -docstring 'enable clipboard integration' kakboard-enable %{ 164 | set-option window kakboard_enabled true 165 | kakboard-autodetect 166 | 167 | evaluate-commands %sh{ 168 | if test -z "$kak_opt_kakboard_copy_cmd" -o \ 169 | -z "$kak_opt_kakboard_paste_cmd" 170 | then 171 | echo "echo -debug 'kakboard: Could not auto-detect clipboard commands. Please set them explicitly.'" 172 | fi 173 | 174 | # Still make the bindings so that they can be set later 175 | 176 | eval set -- "$kak_quoted_opt_kakboard_paste_keys" 177 | while test $# -gt 0; do 178 | escaped=$(echo "$1" | sed -e 's//') 179 | echo map global normal "$1" \ 180 | "': kakboard-with-pull-clipboard $escaped'" 181 | shift 182 | done 183 | 184 | eval set -- "$kak_quoted_opt_kakboard_copy_keys" 185 | while test $# -gt 0; do 186 | escaped=$(echo "$1" | sed -e 's//') 187 | echo map global normal "$1" \ 188 | "': kakboard-with-push-clipboard $escaped'" 189 | shift 190 | done 191 | } 192 | } 193 | 194 | define-command -docstring 'disable clipboard integration' kakboard-disable %{ 195 | set-option window kakboard_enabled false 196 | 197 | remove-hooks window kakboard 198 | 199 | evaluate-commands %sh{ 200 | eval set -- "$kak_quoted_opt_kakboard_paste_keys" \ 201 | "$kak_quoted_opt_kakboard_copy_keys" 202 | while test $# -gt 0; do 203 | echo unmap global normal "$1" 204 | shift 205 | done 206 | } 207 | } 208 | 209 | define-command -docstring 'toggle clipboard integration' kakboard-toggle %{ 210 | evaluate-commands %sh{ 211 | if test "$kak_opt_kakboard_enabled" = true; then 212 | echo "kakboard-disable" 213 | else 214 | echo "kakboard-enable" 215 | fi 216 | } 217 | } 218 | --------------------------------------------------------------------------------