*sandwich.txt*				Last change:28-Nov-2021.

The set of operator and textobject plugins to edit sandwiched textobjects.

Author  : machakann <mckn{at}outlook.jp>
License : NYSL license
          Japanese <http://www.kmonos.net/nysl/>
          English (Unofficial) <http://www.kmonos.net/nysl/index.en.html>

Requirement:	Vim 7.4 or higher
		|+reltime| feature (optional)
		|+float| feature (optional)

==============================================================================
CONTENTS				*sandwich-contents*

QUICK START			|sandwich-quick-start|
INTRODUCTION			|sandwich-introduction|
KEYMAPPINGS			|sandwich-keymappings|
CONFIGURATION			|sandwich-configuration|
MAGICCHARACTERS			|sandwich-magiccharacters|
FILETYPE RECIPES		|sandwich-filetype-recipes|
FUNCTIONS			|sandwich-functions|
MISCELLANEOUS			|sandwich-miscellaneous|
  Introduce vim-surround keymappings
  Customize the behavior of magicchar-f

==============================================================================
QUICK START				*sandwich-quick-start*

*sandwich.vim* is the set of operator and textobject plugins to
add/delete/replace surroundings of a sandwiched textobject, like (foo), "bar".

add~
Press sa{motion/textobject}{addition}.
For example, saiw( makes foo to (foo).

delete~
Press sdb or sd{deletion}.
For example, sdb or sd( makes (foo) to foo.
sdb searchs a set of surrounding automatically.

replace~
Press srb{addition} or sr{deletion}{addition}.
For example, srb" or sr(" makes (foo) to "foo".

That's all. Now you already know enough about sandwich.vim. If you want more,
read following descriptions and each help for operator/textobject,
|operator-sandwich| and |textobj-sandwich|.



==============================================================================
INTRODUCTION				*sandwich-introduction*

This plugin provides functions to add/delete/replace surroundings of
sandwiched texts. These functions are implemented genuinely by utilizing
operator/textobject framework. Their action can be repeated by |.| command
without any dependency. It consists of two parts, |operator-sandwich| and
|textobj-sandwich|. These two cooperate gracefully to realize the
functionality. However, at the same time, each of them are independent, thus
they could work with any other operators/textobjects.

|operator-sandwich| gives three kinds of operators,
|<Plug>(operator-sandwich-add)|, |<Plug>(operator-sandwich-delete)|,
|<Plug>(operator-sandwich-replace)|. These operators edit sandwiched text.

|textobj-sandwich| gives four kinds of textobjects,
|<Plug>(textobj-sandwich-auto-i)|, |<Plug>(textobj-sandwich-auto-a)|,
|<Plug>(textobj-sandwich-query-i)|, |<Plug>(textobj-sandwich-query-a)|.
These textobjects search and select sandwiched text.



==============================================================================
KEYMAPPINGS				*sandwich-keymappings*

This plugin defines the following keymappings.

function	default keymappings
--------------------------------------------------------------------------
add		sa{motion/textobject}{addition}	(normal and visual mode)

delete		sd				(visual mode)
		sdb				(normal mode)
		sd{deletion}			(normal mode)

replace		sr{addition}			(visual mode)
		srb{addition}			(normal mode)
		sr{deletion}{addition}		(normal mode)

textobjct	ib			(operator-pending and visual mode)
		ab			(operator-pending and visual mode)
		is			(operator-pending and visual mode)
		as			(operator-pending and visual mode)
--------------------------------------------------------------------------

NOTE: To prevent unintended operation, the following setting is strongly
      recommended to add to your vimrc.
>
	nmap s <Nop>
	xmap s <Nop>
<
      |s| could be easily replaced by |c|l| commands.



The detailed breakdown is described below.

  * |operator-sandwich|
|<Plug>(operator-sandwich-add)| which is a operator to add surroundings is
mapped to the key sequences sa. This is valid in both normal and visual modes.

|<Plug>(operator-sandwich-delete)| which is a operator to delete surroundings
is mapped to the key sequences sd in visual mode. If the both ends of the
selected region are the same characters or the set of registered surroundings,
then it deletes them.

|<Plug>(operator-sandwich-replace)| which is a operator to replace
surroundings is mapped to the key sequences sr in visual mode. If the both
ends of the selected region are the same characters or the set of registered
surroundings, then it replaces them.



  * |textobj-sandwich|
|<Plug>(textobj-sandwich-auto-i)| and |<Plug>(textobj-sandwich-auto-a)| which
are the textobjects to search and select a sandwiched text automatically are
mapped to the key sequences ib and ab. They are valid in both operator-pending
mode and visual mode. ib selects the text inside the surroundings. ab selects
the text including surroundings.

|<Plug>(textobj-sandwich-query-i)| and |<Plug>(textobj-sandwich-query-a)|
which are the textobjects to search and select a sandwiched text depending on
user input are mapped to the key sequences is and as. They are valid in both
operator-pending mode and visual mode. is selects the text inside the
surroundings. as selects the text including surroundings.



In addition to the above, the key sequences sd, sdb, sr and srb in normal mode
is used by compound mappings of |operator-sandwich| and |textobj-sandwich|.
Each of them are the short-hand mappings as following keysequences.

  sd
>
	<Plug>(operator-sandwich-delete)<Plug>(textobj-sandwich-query-a)
<
  sdb
>
	<Plug>(operator-sandwich-delete)<Plug>(textobj-sandwich-auto-a)
<
  sr
>
	<Plug>(operator-sandwich-replace)<Plug>(textobj-sandwich-query-a)
<
  srb
>
	<Plug>(operator-sandwich-replace)<Plug>(textobj-sandwich-auto-a)
<
This is just for convenience, since these textobjects perfectly fills up the
working condition of these operators. Users only have to assign surroundings
as listed above. If you don't like the short-hands, define
g:sandwich_no_default_key_mappings in your vimrc.
>
	let g:sandwich_no_default_key_mappings = 1
<
NOTE: In fact, these compound keymappings have one more key sequence
      |<Plug>(operator-sandwich-release-count)| in between the two key
      sequences. It is a tiny trick for the [count] handling. For example the
      key sequences 2sdb is identical to:
>
	<Plug>(operator-sandwich-delete)2<Plug>(textobj-sandwich-auto-a)
<
      It searches the second closest sandwiched text and deletes them.
>
	      #                            : cursor
	[bar(foo)baz]   --->   bar(foo)baz
<



==============================================================================
CONFIGURATION				*sandwich-configuration*

A set of surroundings and options for it is called "recipe". Each recipe is a
dictionary and the |list|s of recipes determines the operator's behavior and
textobject's behavior.  |g:sandwich#default_recipes| is one of the |list|s of
recipes. This is shared to be used by |operator-sandwich| and
|textobj-sandwich| since it is convenient in many cases. If
|g:sandwich#recipes| is defined by user, it is employed alternatively. The
default recipes |g:sandwich#default_recipes| can be checked by |:echo|
command.
>
	:echo g:sandwich#default_recipes
<
Besides them, |g:operator#sandwich#recipes| and |g:textobj#sandwich#recipes|
can be used. They are used only by |operator-sandwich| and |textobj-sandwich|
respectively.

About the contents of a recipe, please see |operator-sandwich-configuration|
and |textobj-sandwich-configuration|.



g:sandwich#recipes			*g:sandwich#recipes*
	This is one of the lists of recipes which is referred from both
	|operator-sandwich| and |textobj-sandwich|. If this list does not
	exist, |g:sandwich#default_recipes| is used.
					*b:sandwich_recipes*
	If |b:sandwich_recipes| exists, it would be used instead of
	|g:sandwich#recipes|. This is buffer local, thus it might be
	convenient to manage too many filetype-specific recipes.



g:sandwich#default_recipes		*g:sandwich#default_recipes*
	This is a list of recipes which is prepared in default. If
	|g:sandwich#recipes| exists, it will be used instead.

	This variable is locked usually, but it can be copied when you declare
	|g:sandwich#recipes| if you need.
>
	:let g:sandwich#recipes = deepcopy(g:sandwich#default_recipes)
<

Notes on default recipes~
`(`, `)`
`[`, `]`
`{`, `}`
`<`, `>`
	Both open/close braces behave as same. For example, `saiw(` and `saiw)`
	result in the same text.
>
		foo -> (foo)
<
	`sd(` and `sd)` do the opposite.

------------------------------------------------------------------------------
`'`
`"`
	Wrap a text by quotes.
>
		foo -> 'foo'
<
	When deleting a pair of quotes, 'quoteescape' option is considered.
	The pair of quotes are searched only in a same line.

------------------------------------------------------------------------------
`<Space>`
	When deleting a pair of spaces, successive spaces are deleted at a
	time.

------------------------------------------------------------------------------
`t`, `T`
`f`, `F`
`i`, `I`
	See |sandwich-magiccharacters|.



------------------------------------------------------------------------------
Global options~
g:sandwich#timeout			*g:sandwich#timeout*
	If this option is a falsy value, the operators and the
	query-textobject will wait for subsequent inputs until the complete
	key sequence has been received to specify a recipe. For example, with
	the following recipes,
>
	let g:sandwich#recipes = [
	  \   {'buns': ['for {', '}'],  'nesting': 1, 'input': ['bf']}
	  \   {'buns': ['if {', '}'],   'nesting': 1, 'input': ['bi']}
	  \   {'buns': ['else {', '}'], 'nesting': 1, 'input': ['be']}
	  \ ]
<
	type `saiwb` and a while later the operator eagerly wrap a word with
	`b` if this option is true. The operators wait next input until a
	recipe is specified if this option is false. This option takes effect
	both on the operators and the query-textobject.
	|g:operator#sandwich#timeout| or |g:textobj#sandwich#timeout| takes
	priority over this option if it exists. If this has not been defined,
	'timeout' option is referred. See |g:sandwich#timeoutlen| also.



g:sandwich#timeoutlen			*g:sandwich#timeoutlen*
	The time in milli seconds that waits for a key code or mapped key
	sequence to complete. If there are recipes overlapped, this option is
	used. Assume that the following recipes are prepared:
>
	let g:sandwich#recipes = [
	  \   {'buns': ['(', ')']}
	  \   {'buns': ['((', '))']}
	  \ ]
<
	after pressing saiw(, the operator waits in the time. If you press one
	more ( in the time, then a recipe for '((' and '))' is decided to use.
	No keypress has come through the time a recipe for '(' and ')' is
	settled. This option takes effect both on the operators and the
	query-textobject. |g:operator#sandwich#timeoutlen| or
	|g:textobj#sandwich#timeoutlen| takes priority over this option if it
	exists. If this variable has not been defined, 'timeoutlen' option is
	referred.

	When the timeout option (|g:operator#sandwich#timeout|,
	|g:textobj#sandwich#timeout|, |g:sandwich#timeout|, 'timeout') is off,
	this option is ignored.



==============================================================================
MAGICCHARACTERS				*sandwich-magiccharacters*

Sandwich.vim requests user to input keys for determination of
{addtion}/{deletion}. Usually it is something like `(` for `()` pair or
`"` for `""` pair, but there is several functional inputs for cumbersome
editings. It might be helpful for your work, give it a try!

f~
F~
	Press `saiwf` to surround a word by function. After inputting `f` key,
	user would be requested to input function name and press <CR>, then
	the target textobject would be surrounded by parenthesis with the
	function name. <Tab> key completes function names from the current
	buffer in input.
>
	          arg      -- saiwffunc<CR> -->     func(arg)
<
	The key sequence `sdf`, conversely, deletes function surrounding.
>
	       func(arg)       -- sdf -->             arg
<
	In case of nested functions, `sdf` deletes the function under the
	cursor while `sdF` deletes the function surrounding.
>
	cursor is on 'func2':
	    func1(func2(arg))  -- sdf -->   func1(arg)
	                       -- sdF -->   func2(arg)
<

i~
I~
	It realizes to define `I`nstant surroundings. `saiwi` ask user for
	inputting former and latter surroundings. For example,
	`saiwifoo<CR>bar<CR>` makes a word surrounded by `foo` and `bar`.
	<Tab> key completes words from the current buffer, just simply.
	On the other hand `sdi` deletes arbitrary surroundings. For example,
	`sdifoo<CR>bar<CR>` makes `foowordbar` to `word`, the inputs would be
	interpreted as regular expressions. This is useful when a lot of
	targets are there because the action could be repeated by |.| command.
	`sa{textobj}I`, `sdI` reuse the last inputs.


t~
T~
	The inputs `t` and `T` support to edit HTML style tags. `saiwt` ask
	user to input a name of element, then a textobject would be surrounded
	by the tag. `saiwT` works as same.
>
	       word      -- saiwtp<CR> -->   <p>word</p>
<
	 `sdt` deletes the nearest tag surroundings. `sdT` works as same.
>
	    <p>word</p>  -- sdt -->             word
<
	`t` and `T` works differently only when replacing surroundings.
	`srtt` replaces only the name of element, does not touch attributes.
	`srTT` replaces the whole body of tags.




==============================================================================
FILETYPE RECIPES			*sandwich-filetype-recipes*

Sandwich.vim has filetype specific settings. They will be available when
'filetype' option was set to a certain value. User settings are not
overwrittern by them, use only the recipes helpful for you. These recipes are
written in ftplugin/{filetype}/sandwich.vim.

If you don't want vim to load these files, set
`g:sandwich_no_{filetype}_ftplugin` as true in advance. For example, add the
following line to your vimrc in case you don't need tex specific recipes.
>
	let g:sandwich_no_tex_ftplugin = 1
<

------------------------------------------------------------------------------
plaintex~
tex~
>
 Surroundings		Input
 “{text}”		u"
 „{text}“		U"
 			ug
 			u,
 «{text}»		u<
 			uf
 `{text}'		l'
 			l`
 ``{text}''		l"
 "`{text}"'		L"
 ,,{text}``		l,
 <<{text}>>		l<
 \{{text}\}		\{
 \[{text}\]		\[

 \left({text}\right)				m(
 \left[{text}\right]				m[
 \left|{text}\right|				m|
 \left\{{text}\right\}				m{
 \left\langle {text}\right\rangle		m<
<	The surroundings its input starting from 'm' could be removed/replaced
	by a input `ma`, for example press `sdma`.
>
 \big({text}\big)				M(
 \big[{text}\big]				M[
 \big|{text}\big|				M|
 \big\{{text}\big\}				M{
 \big\langle {text}\big\rangle			M<

 \begingroup{text}\endgroup			gr
 						\gr
 \toprule{text}\bottomrule			tr
 						br
 						\tr
 						\br

 \{input}{{text}}				c
<	This recipe asks user to input a string and then {input} is
	substituted by the input string.
>
 \begin{{input}}{text}\end{{input}}		e
<	This recipe asks user to input a string and then {input} is
	substituted by the input string.
	Use <Tab> to complete {input}, the completion items are loaded from
	`g:sandwich#filetype#tex#environments`
	(or `b:sandwich#filetype#tex#environments` if exists).


==============================================================================
FUNCTIONS				*sandwich-functions*

sandwich#util#addlocal({recipes})	*sandwich#util#addlocal()*
	This function appends the list of recipes {recipes} as buffer-local
	settings with inheritance of the global settings. This is useful when
	one wants to add filetype specific settings with keeping global
	setting |g:sandwich#recipes| clean. Note that {recipe} is a |List| of
	recipes.
>
	autocmd FileType python call sandwich#util#addlocal([
	  \   {'buns': ['"""', '"""'], 'nesting': 0, 'input': ['3"']},
	  \ ])
<

==============================================================================
MISCELLANEOUS				*sandwich-miscellaneous*

Introduce vim-surround keymappings~
	If you want to use with vim-surround (vim script #1697) keymappings,
	add the following line to your vimrc.
>
	runtime macros/sandwich/keymap/surround.vim
<
	NOTE: Unlike surround.vim, the inputs `(` and `)` behave as same.
	      If you want the spaces inside braces with `(` input, add the
	      lines.
>
	runtime macros/sandwich/keymap/surround.vim
	let g:sandwich#recipes += [
	\   {'buns': ['{ ', ' }'], 'nesting': 1, 'match_syntax': 1,
	\    'kind': ['add', 'replace'], 'action': ['add'], 'input': ['{']},
	\
	\   {'buns': ['[ ', ' ]'], 'nesting': 1, 'match_syntax': 1,
	\    'kind': ['add', 'replace'], 'action': ['add'], 'input': ['[']},
	\
	\   {'buns': ['( ', ' )'], 'nesting': 1, 'match_syntax': 1,
	\    'kind': ['add', 'replace'], 'action': ['add'], 'input': ['(']},
	\
	\   {'buns': ['{\s*', '\s*}'],   'nesting': 1, 'regex': 1,
	\    'match_syntax': 1, 'kind': ['delete', 'replace', 'textobj'],
	\    'action': ['delete'], 'input': ['{']},
	\
	\   {'buns': ['\[\s*', '\s*\]'], 'nesting': 1, 'regex': 1,
	\    'match_syntax': 1, 'kind': ['delete', 'replace', 'textobj'],
	\    'action': ['delete'], 'input': ['[']},
	\
	\   {'buns': ['(\s*', '\s*)'],   'nesting': 1, 'regex': 1,
	\    'match_syntax': 1, 'kind': ['delete', 'replace', 'textobj'],
	\    'action': ['delete'], 'input': ['(']},
	\ ]
<


	`ys`, `yss`, `yS`, `ds`, `cs` in normal mode and `S` in visual mode
	are available. Not in vim-surround but `dss` and `css` are also
	available, these are similar as `ds` and `cs` but determine
	deleted/replaced texts automatically. See the file directly for
	detail.

	Additionally, vim-sandwich provides several textobjects. They would
	also be helpful, give it a try!

	* Textobjects to select a text surrounded by braket or same characters
	  user input.
	|<Plug>(textobj-sandwich-query-i)|, |<Plug>(textobj-sandwich-query-a)|
>
	xmap is <Plug>(textobj-sandwich-query-i)
	xmap as <Plug>(textobj-sandwich-query-a)
	omap is <Plug>(textobj-sandwich-query-i)
	omap as <Plug>(textobj-sandwich-query-a)
<
	* Textobjects to select the nearest surrounded text automatically.
	|<Plug>(textobj-sandwich-auto-i)|, |<Plug>(textobj-sandwich-auto-a)|.
>
	xmap iss <Plug>(textobj-sandwich-auto-i)
	xmap ass <Plug>(textobj-sandwich-auto-a)
	omap iss <Plug>(textobj-sandwich-auto-i)
	omap ass <Plug>(textobj-sandwich-auto-a)
<
	* Textobjects to select a text surrounded by same characters user
	  input.
	|<Plug>(textobj-sandwich-literal-query-i)|,
	|<Plug>(textobj-sandwich-literal-query-a)|
>
	xmap im <Plug>(textobj-sandwich-literal-query-i)
	xmap am <Plug>(textobj-sandwich-literal-query-a)
	omap im <Plug>(textobj-sandwich-literal-query-i)
	omap am <Plug>(textobj-sandwich-literal-query-a)
<

------------------------------------------------------------------------------
Customize the behavior of magicchar-f~

`magicchar-f` can delete simple function-call like syntax:
>
	     func(arg)          -- sdf -->             arg
<
If you want to delete more advanced patterns, for example:
>
	     obj.method(arg)    -- sdf -->             arg
<
You can use `g:sandwich#magicchar#f#patterns` or
`b:sandwich_magicchar_f_patterns` for the purpose. Each of those are a list of
patterns like:
>
	let g:sandwich#magicchar#f#patterns = [
	\   {
	\     'header' : '\<\h\k*',
	\     'bra'    : '(',
	\     'ket'    : ')',
	\     'footer' : '',
	\   },
	\ ]
<
Those four values are all regex patterns, which match with something before
open parenthesis, open & close parentheses, something after close parenthesis.
Therefore, you can delete a method with an object by the following setting.
>
	let g:sandwich#magicchar#f#patterns = [
	\   {
	\     'header' : '\<\%(\h\k*\.\)*\h\k*',
	\     'bra'    : '(',
	\     'ket'    : ')',
	\     'footer' : '',
	\   },
	\ ]
<
`b:sandwich_magicchar_f_patterns` can be used to define filetype specific
setting.
>
	augroup sandwich-ft-python
	  autocmd Filetype python let b:sandwich_magicchar_f_patterns = [
	                              \   {
	                              \     'header' : '\<\%(\h\k*\.\)*\h\k*',
	                              \     'bra'    : '(',
	                              \     'ket'    : ')',
	                              \     'footer' : '',
	                              \   },
	                              \ ]
	augroup END
<
The default settings is in `g:sandwich#magicchar#f#default_patterns`.

==============================================================================
vim:tw=78:ts=8:ft=help:norl:noet:
