├── LICENSE ├── README.md ├── surround.kak ├── test.html └── test.txt /LICENSE: -------------------------------------------------------------------------------- 1 | This is free and unencumbered software released into the public domain. 2 | 3 | Anyone is free to copy, modify, publish, use, compile, sell, or 4 | distribute this software, either in source code form or as a compiled 5 | binary, for any purpose, commercial or non-commercial, and by any 6 | means. 7 | 8 | In jurisdictions that recognize copyright laws, the author or authors 9 | of this software dedicate any and all copyright interest in the 10 | software to the public domain. We make this dedication for the benefit 11 | of the public at large and to the detriment of our heirs and 12 | successors. We intend this dedication to be an overt act of 13 | relinquishment in perpetuity of all present and future rights to this 14 | software under copyright law. 15 | 16 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 17 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 18 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 19 | IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR 20 | OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 21 | ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 22 | OTHER DEALINGS IN THE SOFTWARE. 23 | 24 | For more information, please refer to 25 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Surround plugin for Kakoune 2 | 3 | ## Usage 4 | These commands are exposed to map or alias. 5 | - surround 6 | - change-surround 7 | - delete-surround 8 | - select-surround 9 | - surround-with-tag 10 | - delete-surrounding-tag 11 | - change-surrounding-tag 12 | - select-surrounding-tag 13 | 14 | For example, 15 | ``` 16 | map global normal 'some key' ':surround' 17 | ``` 18 | Or you can use user mode like this, 19 | ``` 20 | declare-user-mode surround 21 | map global surround s ':surround' -docstring 'surround' 22 | map global surround c ':change-surround' -docstring 'change' 23 | map global surround d ':delete-surround' -docstring 'delete' 24 | map global surround t ':select-surrounding-tag' -docstring 'select tag' 25 | map global normal 'some key' ':enter-user-mode surround' 26 | ``` 27 | 28 | ## Feature 29 | ### Surround 30 | ``` 31 | abc 32 | ``` 33 | select abc with `w` 34 | 35 | `:surround` 36 | 37 | Popup information, which surrounder do you use to surround with? 38 | 39 | `(` 40 | ``` 41 | (abc) 42 | ``` 43 | You can also surround with tag 44 | 45 | `:surround` `t` 46 | 47 | start insert mode inside angle both side of selection, | means cursor here. 48 | ``` 49 | <|>abc 50 | ``` 51 | If insert space while the context, close tag is confirmed and you can continue to insert attribute. 52 | ``` 53 |
abc
54 | ``` 55 | ### Change surrounder 56 | ``` 57 | 'abc' 58 | ``` 59 | `:change-surround` 60 | 61 | Popup information, which surrounder do you want to change from? 62 | 63 | `'` 64 | 65 | Popup information, which surrounder do you want to change to? 66 | 67 | `(` 68 | ``` 69 | (abc) 70 | ``` 71 | You can also change tag 72 | ``` 73 |
abc
74 | ``` 75 | `:change-surround` `t` 76 | 77 | delete tag content and start insert mode there, | means cursor here. 78 | ``` 79 | <|>abc 80 | ``` 81 | If insert space while the context, close tag is confirmed and you can continue to insert attribute. 82 | ``` 83 |
abc
84 | ``` 85 | 86 | ### Delete surrounder 87 | ``` 88 | {abc} 89 | ``` 90 | `:delete-surround` 91 | 92 | Popup information, which surrounder do you want to delete? 93 | 94 | `{` 95 | ``` 96 | abc 97 | ``` 98 | You can also delete tag 99 | ``` 100 |

abc

101 | ``` 102 | `:delete-surround` `t` 103 | ``` 104 | abc 105 | ``` 106 | -------------------------------------------------------------------------------- /surround.kak: -------------------------------------------------------------------------------- 1 | define-command -hidden -params 2 _surround %{ execute-keys "i%arg{1}a%arg{2}" } 2 | define-command surround %{ 3 | _surrounder-info 'surround' 4 | on-key %{ eval %sh{ 5 | if [ $kak_key = t ] ; then 6 | echo surround-with-tag 7 | else 8 | #use $val{key}. if use $kak_key, it break quote case 9 | echo '_impl-surround _surround %val{key}' 10 | fi 11 | }} 12 | } 13 | 14 | define-command delete-surround %! 15 | _surrounding-object-info 'delete surround' 16 | on-key %@ eval %sh^ 17 | case $kak_key in 18 | b|'('|')'|B|'{'|'}'|r|'['|']'|a|''|''|'"'|Q|"'"|q|'`'|g) 19 | #use $val{key}. if use $kak_key, it break quote case 20 | echo '_select-surrounding-pair %val{key}' 21 | echo 'execute-keys d' ;; 22 | t) echo delete-surrounding-tag ;; 23 | #to close information window, use execute-keys 24 | *) echo 'execute-keys :nop' ;; 25 | esac 26 | ^@ 27 | ! 28 | 29 | define-command change-surround %! 30 | _surrounding-object-info 'change surround' 31 | on-key %@ eval %sh^ 32 | case $kak_key in 33 | b|'('|')'|B|'{'|'}'|r|'['|']'|a|''|''|'"'|Q|"'"|q|'`'|g) 34 | #use $val{key}. if use $kak_key, it break quote case 35 | echo '_change-surrounding-pair %val{key}' ;; 36 | t) echo change-surrounding-tag ;; 37 | #to close information window, use execute-keys 38 | *) echo 'execute-keys :nop' ;; 39 | esac 40 | ^@ 41 | ! 42 | 43 | define-command -hidden -params 1 _select-surrounding-pair %{ execute-keys "%arg{1}" } 44 | define-command select-surround %! 45 | _surrounding-object-info 'select surround' 46 | on-key %@ eval %sh^ 47 | case $kak_key in 48 | b|'('|')'|B|'{'|'}'|r|'['|']'|a|''|''|'"'|Q|"'"|q|'`'|g) 49 | #use $val{key}. if use $kak_key, it break quote case 50 | echo '_select-surrounding-pair %val{key}' ;; 51 | t) echo select-surrounding-tag ;; 52 | #to close information window, use execute-keys 53 | *) echo 'execute-keys :nop' ;; 54 | esac 55 | ^@ 56 | ! 57 | 58 | define-command -hidden -params 2 _impl-surround %! eval %sh@ 59 | command=$1 60 | case $2 in 61 | b|'('|')') open='('; close=')' ;; 62 | r|'['|']') open='['; close=']' ;; 63 | B|'{'|'}') open='{'; close='}' ;; 64 | a|''|'') open=''; close='>' ;; 65 | #also catch ' " to escape quotes 66 | q|\') open="<'>"; close="<'>" ;; 67 | Q|\") open='<">'; close='<">' ;; 68 | g) open='`'; close='`' ;; 69 | *) open=$2; close=$2 ;; 70 | esac 71 | echo "$command $open $close" 72 | @! 73 | 74 | define-command -hidden -params 1 _surrounding-object-info %{ 75 | info -title %arg{1} 'select surrounding object 76 | b,(,): parentheses block 77 | B,{,}: braces block 78 | r,[,]: bracket block 79 | a,<,>: angle block 80 | ",Q: double quote string 81 | '',q: single quote string 82 | `,g: grave quote string 83 | t: markup tag 84 | ' 85 | } 86 | 87 | define-command -hidden -params 1 _surrounder-info %{ 88 | info -title %arg{1} 'enter char to select surrounder 89 | b,(,): parentheses block 90 | B,{,}: braces block 91 | r,[,]: bracket block 92 | a,<,>: angle block 93 | ",Q: double quote string 94 | '',q: single quote string 95 | `,g: grave quote string 96 | t: markup tag 97 | others: pressed character 98 | ' 99 | } 100 | 101 | #after implement change surround pair for tag, 102 | # remove this command, and use _surrounder-info 103 | define-command -hidden _change-surround-info %{ 104 | info -title 'change surround' 'enter char to select surrounder 105 | b,(,): parentheses block 106 | B,{,}: braces block 107 | r,[,]: bracket block 108 | a,<,>: angle block 109 | ",Q: double quote string 110 | '',q: single quote string 111 | `,g: grave quote string 112 | others: pressed character 113 | ' 114 | } 115 | 116 | define-command -hidden _change-surrounding-pair -params 1 %{ eval %sh{ 117 | #restore selection within on-key to use itersel 118 | selections="$kak_selections_desc" 119 | #while discard this selection within proceeding process, 120 | #use this command to show what is going to be selected 121 | echo '_select-surrounding-pair %arg{1}' 122 | # echo "_surrounder-info 'change surround'" 123 | echo _change-surround-info 124 | echo "on-key %{ 125 | select $selections 126 | evaluate-commands -itersel %{ 127 | _select-surrounding-pair %arg{1} 128 | _impl-surround _change-surround %val{key} 129 | } 130 | }" 131 | }} 132 | define-command -hidden -params 2 _change-surround %{ execute-keys "r%arg{1}r%arg{2}" } 133 | 134 | #use evaluate-commands to collapse undo history 135 | define-command surround-with-tag %{ evaluate-commands %{ 136 | #first append, to put cursor inside inserting tag pair 137 | execute-keys 'a/>i>' 138 | execute-keys 'c>,/>' 139 | execute-keys '>s>)' 140 | _activate-hooks-tag-attribute-handler 141 | execute-keys -with-hooks i 142 | }} 143 | 144 | define-command delete-surrounding-tag %{ 145 | evaluate-commands -itersel _select-surrounding-tag-including-space 146 | execute-keys d 147 | } 148 | 149 | define-command change-surrounding-tag %{ 150 | evaluate-commands -itersel _select-boundary-of-surrounding-tag 151 | execute-keys 'c/?,>)' 152 | _activate-hooks-tag-attribute-handler 153 | execute-keys -with-hooks c 154 | } 155 | 156 | define-command select-surrounding-tag %{ 157 | evaluate-commands -itersel _select-boundary-of-surrounding-tag 158 | execute-keys 'c/?,>' 159 | } 160 | 161 | define-command -hidden _activate-hooks-tag-attribute-handler %{ 162 | hook -group surround-tag-attribute-handler window RawKey '' %{ 163 | execute-keys '' 164 | _keep-odds 165 | execute-keys '' 166 | remove-hooks window surround-tag-attribute-handler 167 | } 168 | hook -group surround-tag-attribute-handler window ModeChange insert:normal %{ 169 | remove-hooks window surround-tag-attribute-handler 170 | } 171 | } 172 | 173 | #for multiple selection 174 | #odd selections is open tag 175 | #even selections is close tag 176 | define-command -hidden _keep-odds %{ eval %sh{ 177 | accum_selections= 178 | is_odd=0 179 | for selection in $kak_selections_desc ; do 180 | if [ $is_odd -eq 0 ] ; then 181 | is_odd=1 182 | accum_selections="$accum_selections $selection" 183 | else 184 | is_odd=0 185 | fi 186 | done 187 | #accum_selections has space on head 188 | echo "select$accum_selections" 189 | }} 190 | 191 | #use evaluate-commands to restore mark 192 | define-command -hidden _select-surrounding-tag-including-space %{ evaluate-commands %{ 193 | _select-boundary-of-surrounding-tag 194 | execute-keys -save-regs '' 'Zc\\s*/,>a' 195 | execute-keys -save-regs '' 'z(c,>\\h*\\n?' 196 | execute-keys -save-regs '' 'a' 197 | }} 198 | 199 | define-command -hidden _select-boundary-of-surrounding-tag %{ 200 | execute-keys \; 201 | #handle inside open tag 202 | try %{ 203 | #> produce side effect inside close tag 204 | #that make tag_list include the close tag 205 | execute-keys -draft 'c/,>' 206 | } catch %{ 207 | try %{ 208 | execute-keys '>' 209 | } 210 | } 211 | execute-keys 'Ge' 212 | eval %sh{ 213 | tag_list=`echo "$kak_selection" | grep -P -o '(?<=<)[^>]+(?=>)' | cut -d ' ' -f 1` 214 | open= 215 | open_stack= 216 | result= 217 | for tag in $tag_list ; do 218 | if [ `echo $tag | cut -c 1` != / ] ; then 219 | case $tag in 220 | #self-closing tags 221 | area|base|br|col|command|embed|hr|img|input|keygen|link|meta|param|source|track|wbr) continue ;; 222 | *) 223 | open=$tag 224 | open_stack=$open\\n$open_stack ;; 225 | esac 226 | else 227 | if [ $tag = /$open ] ; then 228 | open_stack=${open_stack#*\\n} 229 | open=`echo $open_stack | head -n 1` 230 | else 231 | result=${tag#/} 232 | break 233 | fi 234 | fi 235 | done 236 | echo "execute-keys 'c$result\s?[^>]*>,/$result>'" 237 | } 238 | execute-keys '' 239 | } 240 | -------------------------------------------------------------------------------- /test.html: -------------------------------------------------------------------------------- 1 |
2 |
3 | 4 |
5 |
6 | 7 |
8 | 9 | tt tt 10 | 11 | (t) (t) 12 | -------------------------------------------------------------------------------- /test.txt: -------------------------------------------------------------------------------- 1 | ( a ) 2 | 3 | [ a ] 4 | 5 | { a } 6 | 7 | < a > 8 | 9 | ' a ' 10 | 11 | " a " 12 | 13 | { 14 | a 15 | } 16 | --------------------------------------------------------------------------------