Vim Tips Wiki
Tip 786 Printable Monobook Previous Next

created September 9, 2004 · complexity intermediate · author Breadman · version 5.7

I tend to swap double and single quotation marks around, as well as other pairs of characters. There is a transform command that I initially thought would be very helpful in script#72.

Unfortunately, the original command fails in this case. Below is an updated version which is probably slower, but more powerful, as well as a map for my favorite way to use it.

Also included is a character-switching function I developed in the process, but ended up including inline for efficiency. It turns out that directly assigning to a character in a string (let string[i] = a:new[pos]) is illegal, probably because the rhs can include more than one byte. StrSwitchPos() takes care of that, but doesn't enforce a single-byte replacement.

" Translate character sets, either in the current line, on a range, or in a string
" Note that in this version, unmatched characters in old are deleted
command! -nargs=* -range Transform <line1>,<line2> call Transform(<f-args>)
function! Transform(old, new, ...)
  let string = a:0 ? a:1 : getline('.')
  let i = strlen(string)
  while i > 0
    let i = i - 1
    let pos = stridx(a:old, string[i])
    if pos > -1
      let string = strpart(string, 0, i) . a:new[pos] . strpart(string, i + 1)
  if a:0
    return string
    call setline('.', string)
noremap <silent> "" :Transform "' '"<CR>

" Spin-off from the above: switch a single character specified by index
fun! StrSwitchPos(string, pos, char)
  return strpart(a:string, 0, a:pos) . a:char . strpart(a:string, a:pos + 1)