264

How can I quickly quote/unquote words and change quoting (e.g. from ' to ") in Vim? I know about the surround.vim plugin, but I would like to use just Vim.

dreftymac
  • 31,404
  • 26
  • 119
  • 182
Eugene Yarmash
  • 142,882
  • 41
  • 325
  • 378
  • A solution really depends on context. Do you want to do it on just one line, or in the whole file, or just for a single quoted string? – Lucas Oman Jan 27 '10 at 15:18
  • For a single word or all words in a line. E.g. when converting pasted words to string literals. – Eugene Yarmash Jan 27 '10 at 18:45
  • 2
    To unquote a word: `F'x,x` (and accordingly for double quotes); to toggle from single to double: `F'r",.` (and accordingly reverse). Contrary to very complicated answers below. – bloody Dec 02 '20 at 23:43
  • I don't understand why this question excludes surround.vim explicitly and is still the most popular question, and the first surround answer is long scroll down. One should use surround in 95% of cases as is obvious from the solution: `ds'` for deleting quotes and `cs'"` for changing. – Cornelius Roemer Jun 16 '21 at 10:23

21 Answers21

333

surround.vim is going to be your easiest answer. If you are truly set against using it, here are some examples for what you can do. Not necessarily the most efficient, but that's why surround.vim was written.

  • Quote a word, using single quotes
    ciw'Ctrl+r"'
    • ciw - Delete the word the cursor is on, and end up in insert mode.
    • ' - add the first quote.
    • Ctrl+r" - Insert the contents of the " register, aka the last yank/delete.
    • ' - add the closing quote.

  • Unquote a word that's enclosed in single quotes
    di'hPl2x
    • di' - Delete the word enclosed by single quotes.
    • hP - Move the cursor left one place (on top of the opening quote) and put the just deleted text before the quote.
    • l - Move the cursor right one place (on top of the opening quote).
    • 2x - Delete the two quotes.

  • Change single quotes to double quotes
    va':s/\%V'\%V/"/g
    • va' - Visually select the quoted word and the quotes.
    • :s/ - Start a replacement.
    • \%V'\%V - Only match single quotes that are within the visually selected region.
    • /"/g - Replace them all with double quotes.
jamessan
  • 41,569
  • 8
  • 85
  • 85
  • 1
    These work fine for me. Just googled that pasting in insert mode is also possible with Ctrl+op. – Eugene Yarmash Jan 27 '10 at 19:00
  • 1
    Used in combination with Record Mode (q), works like a charm for quick jobs. – bishop Feb 25 '15 at 21:29
  • Why `ciw` and not just `cw`? I find the first confusing and the second works fine. – Big McLargeHuge Apr 25 '15 at 19:39
  • 21
    @Koveras `ciw` works regardless of where your cursor is in the word. `cw` only works if your cursor is at the start of the word. See `:help iw`. – jamessan Apr 25 '15 at 19:50
  • 13
    Hijacking the top answer to give a nice little trick: if you have several words to replace enclosing single quote in double-quote, you might notice that the first solution of @jamessan does not work with the `.` command. To make it work, use `ciw' Ctrl+r Ctrl+p"`. Then `.` will behave as you want it for the following word: instead of remembering the content of the register, it will remember you want whatever is in the register right now (kind of hard to explain, but if you try both, it will become obvious :-) ) – autra Nov 25 '15 at 09:25
  • I tried @autra 's suggestion, but then `.` replaces the word with the first word that was yanked – Aaron McMillin Feb 22 '18 at 16:19
  • Unquote is a little complex, ```diwp_xx``` should be easier – Pham Aug 14 '18 at 07:10
  • @autra Works like a charm! I don't understand how though. From the Vim docs, inserts contents of a register, and does "Insert the contents of a register literally and fix the indent". How does that affect how .(period) works? Afaik the period command repeats the last change. So with or without it should have pasted the same text, yeah? Also, I noticed that if I'm using a macro, it doesn't make a difference - macro (with just ) repeated does the trick. – Ambareesh Apr 19 '20 at 01:15
  • 1
    @autra Tried a few more variants, alone does not work for several words (as you pointed out). doesn't work either (This is supposed to paste contents of register literally). and seem to work (these also paste literally, but differ in auto-indent or not). The difference lies in how Insert mode handles pasting register contents for all of the above variants. More details at mgiuffrida's fascinating answer at https://stackoverflow.com/questions/20617329/in-vim-what-is-the-difference-between-c-rregister-and-c-rc-pregister-wi – Ambareesh Apr 19 '20 at 02:36
  • quote: `ciw""P` – Hans Ginzel Jun 12 '20 at 09:38
  • To unquote a word: `F'x,x` (and accordingly for double quotes); to toggle from single to double: `F'r",.` (and accordingly reverse). – bloody Dec 02 '20 at 23:38
  • @HansGinzel works fine, but unfortunately repeating the command with `.` does not work. – Wolfson Dec 03 '20 at 11:18
  • 1
    @autra I had to use `ciw' Ctrl+r Ctrl+p " '`, so adding a final `'` for surrounding a word with single quotes and a following `.` to work. – Wolfson Dec 03 '20 at 11:37
  • Just noting you can use this with _IdeaVim_ (JetBrains), `set surround` in `.ideavimrc` – Christopher Galpin Mar 07 '21 at 15:03
227

Quote a word, using single quotes

ciw'Ctrl+r"'

It was easier for me to do it this way

ciw '' Esc P
Community
  • 1
  • 1
installero
  • 9,096
  • 3
  • 39
  • 43
  • 10
    Unfortunately, that does not seem to allow . (repeat). – Wil Moore III Jan 17 '14 at 20:16
  • 2
    I prefer this as I can use it on terminals/repls with vim mode as Ctrl+r is usually already used for reverse history search. – krock Aug 19 '15 at 05:09
  • 6
    @wilmoore Record the above as a macro, then replay. – Christopher Oct 13 '16 at 23:00
  • 1
    @WilMooreIII jamessan's accepted answer does not allow `.` either. It pastes the previous word (instead of quoting the new one). So this answer still prevails (at least over that one, probably mappings do the job best). – bloody Feb 03 '23 at 16:52
44

Here's some mapping that could help:

:nnoremap <Leader>q" ciw""<Esc>P
:nnoremap <Leader>q' ciw''<Esc>P
:nnoremap <Leader>qd daW"=substitute(@@,"'\\\|\"","","g")<CR>P

If you haven't changed the mapleader variable, then activate the mapping with \q" \q' or \qd. They add double quote around the word under the cursor, single quote around the word under the cursor, delete any quotes around the word under the cursor respectively.

Geoff Reedy
  • 34,891
  • 3
  • 56
  • 79
  • Awesome idea! I ended up adding `map ' gewi'A'` to my `.vimrc` file to insert single quote comments from current position to the end of the line; which helped me while converting some MSDOS scripts to bash. – ILMostro_7 Mar 26 '14 at 07:57
  • @Geoff, it works fine for single quotes. but for double quotes it insterts ` "" "" ` infront of the word – RameshVel Jul 18 '14 at 14:28
  • @RameshVel It's possible you had some of your own macros that affected the right hand side of the mapping. I updated the mapping command to nnoremap so that other mappings are not expanded. I also improved the mappings. The previous ones had problems when the cursor is on the first word on a line. – Geoff Reedy Jul 23 '14 at 03:13
  • 2
    This can also be easily adapted for visual mode to surround a selection with quotes, e.g. `:vnoremap q c""P`. – Dominik Jun 10 '20 at 13:22
40

If you use the vim plugin https://github.com/tpope/vim-surround (or use VSCode Vim plugin, which comes with vim-surround pre-installed), its pretty convinient!

add

ysiw' // surround in word `'`

drop

ds' // drop surround `'`

change

cs'" // change surround from `'` to `"`

It even works for html tags!

cst<em> // change surround from current tag to `<em>`

check out the readme on github for better examples

Ulad Kasach
  • 11,558
  • 11
  • 61
  • 87
37

The macro ways !

  1. press q and q for recording into q register (we use "q" as shortcut to remember "quotes").

  2. press shift + b move cursor to front of current word

  3. press i type ' (a single quotes)

  4. press esc then press e to move to end of word

  5. press a then press ' again to surround the word with quotes.

  6. press esc to get into normal mode.

  7. finally press q to record it into q register.

How to use

  1. Move cursor to desired word.
  2. Press @q to surround a word with quotes.
  3. Press @@ if you want repeat it into another word.

You can alter step 4 with anything you like {a line, a word until found some character, etc}.

Make recorded macro persistent

  1. open .vimrc
  2. go to end of file
  3. change to insert mode. type this to make it persistent:
let @q='ctrl + r ctrl + r q'
  1. save and quit

  2. open your files, go to some words

  3. now press @q

if you do it correctly, magic things should appear in your words.

You can apply this to other macros you loved.

Brain90
  • 1,551
  • 18
  • 21
  • 4
    Have to say I like this solution. No surround.vim necessary and easy invocation and creation of the macros. Also easily usable for whatever else you'd need (for me for example quote current word up until the end of the line, perfect for ansible). To show the macro do: "qp . To save it go to .vimrc and do: let @q = 'macro contents' (just for completeness) – th3penguinwhisperer Apr 07 '17 at 11:05
  • 2
    I like this a lot. You can nest these macros also. So you could record in register j `@q w` and then you could wrap the next `n` words with quotes using with `n@j`. – hidden-username Apr 26 '18 at 16:39
  • 2
    I added some steps to made the macro persistent. – Brain90 Nov 19 '19 at 09:28
  • 1
    Pedantic, but, word and WORD are different in Vim. Shift+b = B, so step 2 should ideally be changed to "... front of current WORD". If you meant beginning of word however, you needn't use Shift. – Ambareesh Apr 19 '20 at 01:25
  • Thanks for point that. I use shift + b purposely to deal with WORD. The macro should run in word or WORD [0]. Actually step 3 should also changes to shift + e. [0] https://stackoverflow.com/a/14390568/341959 – Brain90 Apr 19 '20 at 03:19
29

In addition to the other commands, this will enclose all words in a line in double quotes (as per your comment)

:s/\(\S\+\)/"\1"/

or if you want to reduce the number of backslashes, you can put a \v (very-magic) modifier at the start of the pattern

:s/\v(\S+)/"\1"/
Matteo Riva
  • 24,728
  • 12
  • 72
  • 104
24

To wrap in single quotes (for example) ciw'<C-r>"'<esc> works, but repeat won't work. Try:

ciw'<C-r><C-o>"'<esc>

This puts the contents of the default register "literally". Now you can press . on any word to wrap it in quotes. To learn more see :h[elp] i_ctrl-r and more about text objects at :h text-objects

Source: http://vimcasts.org/episodes/pasting-from-insert-mode/

jamessan
  • 41,569
  • 8
  • 85
  • 85
James Scriven
  • 7,784
  • 1
  • 32
  • 36
  • 3
    Excellent tip! If anybody wants to make a mapping out of this, the proper notation is `ciw'"'`. – glts Dec 08 '13 at 17:45
  • What does " exactly do? – CodeCrack May 14 '15 at 23:54
  • @CodeCrack It is CTRL-R. CTRL-R inserts the contents of the register at the cursor and stays in insert mode. – user2609980 Oct 28 '15 at 11:08
  • This is repeatable as you mentionned, but when stored in a macro, repeating the macro with `.` will rewrite the content of the last actual call. – Sbu Jul 24 '19 at 15:16
  • This is awesome! Could someone explain why the `` is needed for the `.` repeating to work? The help text makes it seem like it would only affect things like autoindenting. – user1717828 Nov 04 '21 at 20:49
22

For users of VSCodeVim, Neovim and Macvim, you can do

vwS"

  • You can replace " with whatever you would like to wrap by.
  • You can replace w with any other selection operator
Janac Meena
  • 3,203
  • 35
  • 32
12

Add quote to surrounding of word: v i w S '

  • viw: select word under the cursor
  • S: add surrounding
  • ': single quote

Change surrounding from ' to ": c s ' "

  • cs: change surrounding
  • ': single quote
  • ": change to double quote
DuyVinh
  • 157
  • 1
  • 3
  • The "s" command deletes the character under the cursor and enters insert mode, placing the cursor at the same location where the deleted character was. The "S" command deletes the entire line and enters insert mode at the beginning of the line. Is this what OP want? – Alexei Sosin May 11 '23 at 17:27
6

I don't know any builtin vim command for this, but using r"f'r" to change from ' to " and r'f"r' to change from " to ' works if you stand on the first ' or ". The command r' replaces whatever character is under your cursor with ', and f" moves you forward to the next ".

Håvard S
  • 23,244
  • 8
  • 61
  • 72
  • 2
    The most intuitive "manual" solution to me. Instead of the second replacement command (`'r` and `"r`), you can just type `.` And if you want to change more quotes, `;` and `,` take you to the next or previous one as they repeat the last `f/F/t/T` search in the same direction or the opposite one, respectively. – Endre Both Mar 10 '15 at 00:13
  • Also, if you're dealing with "words" you can `B` to jump to the start of the WORD `Br"f'.` – CervEd Mar 16 '23 at 10:36
6

Adding Quotes

I started using this quick and dirty function in my .vimrc:

vnoremap q <esc>:call QuickWrap("'")<cr>
vnoremap Q <esc>:call QuickWrap('"')<cr>

function! QuickWrap(wrapper)
  let l:w = a:wrapper
  let l:inside_or_around = (&selection == 'exclusive') ? ('i') : ('a')
  normal `>
  execute "normal " . inside_or_around . escape(w, '\')
  normal `<
  execute "normal i" . escape(w, '\')
  normal `<
endfunction

So now, I visually select whatever I want (typically via viw - visually select inside word) in quotes and press Q for double quotes, or press q for single quotes.

Removing Quotes

vnoremap s <esc>:call StripWrap()<cr>

function! StripWrap()
  normal `>x`<x
endfunction

I use vim-textobj-quotes so that vim treats quotes as a text objects. This means I can do vaq (visually select around quotes. This finds the nearest quotes and visually selects them. (This is optional, you can just do something like f"vww). Then I press s to strip the quotes from the selection.

Changing Quotes

KISS. I remove quotes then add quotes. For example, to replace single quotes with double quotes, I would perform the steps: 1. remove single quotes: vaqs, 2. add new quotes: vwQ.


James Lawson
  • 8,150
  • 48
  • 47
4

VIM for vscode does it awsomely. It's based one vim-surround if you don't use vscode.

Some examples:

"test" with cursor inside quotes type cs"' to end up with 'test'

"test" with cursor inside quotes type ds" to end up with test

"test" with cursor inside quotes type cs"t and enter 123> to end up with <123>test

test with cursor on word test type ysaw) to end up with (test)

Lev
  • 13,856
  • 14
  • 52
  • 84
4

wrap all words with quotes:

s/\(\w\+\)/"\1"/g

before:

aaa,bbb,ccc

after:

"aaa","bbb","ccc"
kai
  • 1,640
  • 18
  • 11
3

Here are some simple mappings that can be used to quote and unquote a word:

" 'quote' a word
nnoremap qw :silent! normal mpea'<Esc>bi'<Esc>`pl
" double "quote" a word
nnoremap qd :silent! normal mpea"<Esc>bi"<Esc>`pl
" remove quotes from a word
nnoremap wq :silent! normal mpeld bhd `ph<CR>
falcucci
  • 319
  • 3
  • 5
3

I am using the vim-surround command, almost vim in nature.

Surround.vim is all about "surroundings": parentheses, brackets, quotes, XML tags, and more. The plugin provides mappings to easily delete, change and add such surroundings in pairs.

Plugin 'tpope/vim-surround' 

for example, To remove the delimiters entirely, press ds". More details are here: https://github.com/tpope/vim-surround

Dr Neo
  • 724
  • 6
  • 11
1

Visual mode map example to add single quotes around a selected block of text:

:vnoremap qq <Esc>`>a'<Esc>`<i'<Esc>
mrded
  • 4,674
  • 2
  • 34
  • 36
1

I'm using nnoremap in my .vimrc

To single quote a word:

nnoremap sq :silent! normal mpea'<Esc>bi'<Esc>`pl

To remove quotes (works on double quotes as well):

nnoremap qs :silent! normal mpeld bhd `ph<CR>

Rule to remember: 'sq' = single quote.

Niko Riitala
  • 179
  • 3
0

how about this?

 :%s/\'/"/g
ghostdog74
  • 327,991
  • 56
  • 259
  • 343
0

I wrote a script that does this:

function! WrapSelect (front)
    "puts characters around the selected text.
    let l:front = a:front
    if (a:front == '[')
        let l:back = ']'
    elseif (a:front == '(')
        let l:back = ')'
    elseif (a:front == '{')
        let l:back = '}'
    elseif (a:front == '<')
        let l:back = '>'
    elseif (a:front =~ " ")
        let l:split = split(a:front)
        let l:back = l:split[1]
        let l:front = l:split[0]
    else
        let l:back = a:front
    endif
    "execute: concat all these strings. '.' means "concat without spaces"
    "norm means "run in normal mode and also be able to use \<C-x> characters"
    "gv means "get the previous visual selection back up"
    "c means "cut visual selection and go to insert mode"
    "\<C-R> means "insert the contents of a register. in this case, the
    "default register"
    execute 'norm! gvc' . l:front. "\<C-R>\""  . l:back
endfunction
vnoremap <C-l> :<C-u>call WrapSelect(input('Wrapping? Give both (space separated) or just the first one: '))<cr>

To use, just highlight something, hit control l, and then type a character. If it's one of the characters the function knows about, it'll provide the correct terminating character. If it's not, it'll use the same character to insert on both sides.

Surround.vim can do more than just this, but this was sufficient for my needs.

jeremysprofile
  • 10,028
  • 4
  • 33
  • 53
0

You can map a key to surround a word by any char or pair of chars with this line:

noremap " yiw :let surrounder=input('surrounder(s)? ') <bar> :execute 'normal ciw'.surrounder[0].'<c-r>"'.(surrounder[1]??surrounder[0]).'<c-v><esc>'<cr> 

in this case is mapped to ", you can change it to whatever you want.

If you enter a single char it will be used as surrounder in both extremes, if you enter 2 chars it will use the first at the beginning and the second at the end.

Ejs:

  1. you press " over a word and enter ' will result in 'word'
  2. you press " over a word and enter [] will result in [word]
GIPeN
  • 11
  • 3
0

In NVIM you can use this function and map <leader>sw or <leader>sW to use :lua Surround("w") and :lua Surround("W") respectively.

After pressing <leader>sw or <leader>sW in insert mode you will be asked for the character you want to surround with.

If you want to surround with characters whose closing character is different from the opening character, just type the opening one

Note that this is easily reproduced in VIM.

function Surround(w_or_W)
    local open_char = vim.fn.input("Surround with: ")
    local closed_char = nil
    if open_char == "(" then closed_char = ")" end
    if open_char == "[" then closed_char = "]" end
    if open_char == "{" then closed_char = "}" end
    if open_char == "<" then closed_char = ">" end
    if open_char == "'" then closed_char = "'" end
    if open_char == '"' then closed_char = '"' end
    if open_char == "`" then closed_char = "`" end
    if open_char == "/" then closed_char = "/" end
    if open_char == "|" then closed_char = "|" end

    if w_or_W == "w" then
        vim.cmd("normal! ciw" .. open_char)
    elseif w_or_W == "W" then
        vim.cmd([[normal! ciW]] .. open_char)
    end
    vim.cmd("normal! p")
    vim.cmd("normal! a" .. closed_char)
    vim.cmd("normal! a")
end

vim.api.nvim_set_keymap("n", "<leader>sw", ":lua Surround('w')<CR>", { noremap = true, silent = true })
vim.api.nvim_set_keymap("n", "<leader>sW", ":lua Surround('W')<CR>", { noremap = true, silent = true })