Need help with vim-sandwich?
Click the “chat” button below for chat support from the developer who created it, or find similar developers for support.

About the developer

machakann
789 Stars 18 Forks 422 Commits 20 Opened issues

Description

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

Services available

!
?

Need anything else?

Contributors list

vim-sandwich

Build Status Build status

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

Quick start

Add

Press

sa{motion/textobject}{addition}
. For example, a key sequence
saiw(
makes foo to (foo).

Delete

Press

sdb
or
sd{deletion}
. For example, key sequences
sdb
or
sd(
makes (foo) to foo.
sdb
searches a set of surrounding automatically.

Replace

Press

srb{addition}
or
sr{deletion}{addition}
. For example, key sequences
srb"
or
sr("
makes (foo) to "foo".

That's all. Now you already know enough about

sandwich.vim
. If you are using vim-surround, you can use a preset keymappings similar as it. See here

sandwich.vim
has some functional input for {addition}/{deletion}. Check here!

Design

This plugin provides functions to add/delete/replace surroundings of a sandwiched text. These functions are implemented genuinely by utilizing operator/textobject framework. Thus their action can be repeated by

.
command without any dependency. It consists of two parts, operator-sandwich and textobj-sandwich.

operator-sandwich

A sandwiched text could be resolved into two parts, {surrounding} and {surrounded text}.

  • Add surroundings: mapped to the key sequence

    sa
    • {surrounded text} ---> {surrounding}{surrounded text}{surrounding}
  • Delete surroundings: mapped to the key sequence

    sd
    • {surrounding}{surrounded text}{surrounding} ---> {surrounded text}
  • Replace surroundings: mapped to the key sequence

    sr
    • {surrounding}{surrounded text}{surrounding} ---> {new surrounding}{surrounded text}{new surrounding}

textobj-sandwich

  • Search and select a sandwiched text automatically: mapped to the key sequence
    ib
    and
    ab
  • Search and select a sandwiched text with query: mapped to the key sequence
    is
    and
    as

ib
and
is
selects {surrounded text}.
ab
and
as
selects {surrounded text} including {surrounding}s.
             ||
{surrounding}{surrounded text}{surrounding}
||

Configuration

The point is that it would be nice to be shared the definitions of {surrounding}s pairs in all kinds of operations. User can freely add new settings to extend the functionality. If

g:sandwich#recipes
was defined, this plugin works with the settings inside. As a first step, it would be better to copy the default settings in
g:sandwich#default_recipes
.
vim
let g:sandwich#recipes = deepcopy(g:sandwich#default_recipes)
Each setting, it is called
recipe
, is a set of a definition of {surrounding}s pair and options. The key named
buns
is used for the definition of {surrounding}. ``` let g:sandwich#recipes += [{'buns': [{surrounding}, {surrounding}], 'option-name1': {value1}, 'option-name2': {value2} ...}]

For example: {'buns': ['(', ')']} foo ---> (foo) ```

Or there is a different way, use external textobjects to define {surrounding}s from the difference of two textobjects. ``` let g:sandwich#recipes += [{'external': [{textobj-i}, {textobj-a}], 'option-name1': {value1}, 'option-name2': {value} ...}]

For example: {'external': ['it', 'at']}

foo ---> foo ```

Features

Unique count handling

As for the default operators, the possible key input in normal mode is like this.

        [count1]{operator}[count2]{textobject}
Default operators do not distinguish
[count1]
and
[count2]
but operator-sandwich does.
[count1]
is given for
{operators}
and
[count2]
is given for
{textobject}
.

Linewise and blockwise operations

Operator-sandwich works linewise with the linewise-visual selection and linewise motions.

" press Vsa(
    foo  --->  (
               foo
               )

Using

command
option, user can execute vim Ex-commands after an action. For example it can be used to adjust indent automatically.
let g:sandwich#recipes += [
      \   {
      \     'buns'        : ['{', '}'],
      \     'motionwise'  : ['line'],
      \     'kind'        : ['add'],
      \     'linewise'    : 1,
      \     'command'     : ["'[+1,']-1normal! >>"],
      \   },
      \   {
      \     'buns'        : ['{', '}'],
      \     'motionwise'  : ['line'],
      \     'kind'        : ['delete'],
      \     'linewise'    : 1,
      \     'command'     : ["'[,']normal! <  {
                   foo
                 }

" press V2jsd { ---> foo foo }

Operator-sandwich also can work blockwise with the blockwise-visual selection and blockwise motions.

" press 2j2lsa(
    foo        (foo)
    bar  --->  (bar)
    baz        (baz)

There is an option to skip white space

skip_space
, it is valid in default. Empty line is ignored.
" press 3j$sa(
    fooooooo            (fooooooo)
      baaaar   --->       (baaaar)

baaaz               (baaaz)

Expression surroundings and regular expression matching

The option

expr
enables to evaluate surroundings (
buns
) before adding/deleting/replacing surroundings. The following recipe is an simple example to wrap texts by html style tags.
let g:sandwich#recipes += [
      \   {
      \     'buns'    : ['TagInput(1)', 'TagInput(0)'],
      \     'expr'    : 1,
      \     'filetype': ['html'],
      \     'kind'    : ['add', 'replace'],
      \     'action'  : ['add'],
      \     'input'   : ['t'],
      \   },
      \ ]

function! TagInput(is_head) abort if a:is_head let s:TagLast = input('Tag: ') if s:TagLast !=# '' let tag = printf('', s:TagLast) else throw 'OperatorSandwichCancel' endif else let tag = printf('%s>', matchstr(s:TagLast, '^\a[^[:blank:]>/]*')) endif return tag endfunction

The option

regex
is to regard surroundings (
buns
) as regular expressions to match and delete/replace. The following recipe is an simple example to delete both ends of html tag.
let g:sandwich#recipes += [
      \   {
      \     'buns'    : ['/]*.\{-}>',
      \                  '\a[^[:blank:]>/]*>'],
      \     'regex'   : 1,
      \     'filetype': ['html'],
      \     'nesting' : 1,
      \     'input'   : ['t'],
      \   },
      \ ]

However the above example is not so accurate. Instead of the example, there are excellent built-in textobjects

it
and
at
, these external textobjects also can be utilized through
external
.
let g:sandwich#recipes += [
      \   {
      \     'external': ['it', 'at'],
      \     'noremap' : 1,
      \     'filetype': ['html'],
      \     'input'   : ['t'],
      \   },
      \ ]

Demo

sandwich.vim

Pioneers

We use cookies. If you continue to browse the site, you agree to the use of cookies. For more information on our use of cookies please see our Privacy Policy.