" UniCycle, Release 1, 2005-10-20
"
" by Jason Diamond
"
" This document has been placed in the public domain.
"
" This script cycles through certain Unicode characters while typing. It only
" works if set encoding=utf-8.
"
" To install, drop it in your plugins directory. To use, execute the
" :UniCycleOn command. Turn turn it off, execute :UniCycleOff.
"
" When on, the hyphen (-), period (.), apostrophe ('), and quote (")
" characters are mapped to the appropriate functions within this file.
"
" When you enter two hyphen characters in a row, the first hyphen character
" will cycle to an EN DASH character. A third hyphen will turn the EN DASH
" into an EM DASH. A fourth hyphen will turn your EM DASH back into a
" HYPHEN-MINUS.
"
" Entering three periods in a row will replace all three periods with a
" HORIZONTAL ELLIPSIS character.
"
" Entering an apostrophe will try to determine if the apostrophe should be a
" LEFT SINGLE QUOTATION MARK or RIGHT SINGLE QUOTATION MARK. It does this by
" looking at the character to the left of the new character. You can cycle
" between LEFT SINGLE QUOTATION MARK, APOSTROPHE, and RIGHT SINGLE QUOTATION
" MARK by repeatedly hitting your apostrophe key.
"
" Quote characters are treated in the same manner as apostrophe characters.
" You get either a LEFT DOUBLE QUOTATION MARK, normal QUOTATION MARK, or RIGHT
" DOUBLE QUOTATION MARK based on the previous character and how many times you
" hit your quote key in a row.
"
" All of this is supposed to just work so you don't have to think about it.
" Let me know how well it does.
"
" If you set cmdheight=2 or greater, you'll see some handy messages indicating
" what special character was last inserted into the buffer.
function! UniCycleGetUTF8Char(src, start)
let nr = char2nr(strpart(a:src, a:start, 1))
if nr < 128
let len = 1
elseif nr < 192
" Huh? This is not the start of a UTF-8 character!
let len = 0
elseif nr < 224
let len = 2
elseif nr < 240
let len = 3
elseif nr < 248
let len = 4
elseif nr < 252
let len = 5
else
let len = 6
endif
return strpart(a:src, a:start, len)
endfunction
function! UniCycleHyphen()
if col(".") == 1
echo "HYPHEN-MINUS"
else
normal h
let prev_char = UniCycleGetUTF8Char(getline("."), col(".") - 1)
if prev_char == "-"
execute "normal xr\u2013"
echo "EN DASH"
elseif prev_char == "\u2013"
execute "normal xr\u2014"
echo "EM DASH"
elseif prev_char == "\u2014"
normal xr-
echo "HYPHEN-MINUS"
else
normal l
echo "HYPHEN-MINUS"
endif
endif
endfunction
function! UniCyclePeriod()
if col(".") < 3
echo "FULL STOP"
else
normal h
let prev1 = UniCycleGetUTF8Char(getline("."), col(".") - 1)
if prev1 == "."
normal h
let prev2 = UniCycleGetUTF8Char(getline("."), col(".") - 1)
if prev2 == "."
execute "normal xxr\u2026"
echo "HORIZONTAL ELLIPSIS"
else
normal ll
echo "FULL STOP"
endif
else
normal l
echo "FULL STOP"
endif
endif
endfunction
function! UniCycleApostrophe()
if col(".") == 1
execute "normal r\u2018"
echo "LEFT SINGLE QUOTATION MARK"
else
normal h
let prev_char = UniCycleGetUTF8Char(getline("."), col(".") - 1)
if stridx(" <>()[]{}", prev_char) != -1
execute "normal lr\u2018"
echo "LEFT SINGLE QUOTATION MARK"
elseif prev_char == "\u2018"
normal xr'
echo "APOSTROPHE"
elseif prev_char == "'"
execute "normal xr\u2019"
echo "RIGHT SINGLE QUOTATION MARK"
elseif prev_char == "\u2019"
execute "normal xr\u2018"
echo "LEFT SINGLE QUOTATION MARK"
else
execute "normal lr\u2019"
echo "RIGHT SINGLE QUOTATION MARK"
endif
endif
endfunction
function! UniCycleQuote()
if col(".") == 1
execute "normal r\u201C"
echo "LEFT DOUBLE QUOTATION MARK"
else
normal h
let prev_char = UniCycleGetUTF8Char(getline("."), col(".") - 1)
if stridx(" <>()[]{}", prev_char) != -1
execute "normal lr\u201C"
echo "LEFT DOUBLE QUOTATION MARK"
elseif prev_char == "\u201C"
normal xr"
echo "QUOTATION MARK"
elseif prev_char == "\""
execute "normal xr\u201D"
echo "RIGHT DOUBLE QUOTATION MARK"
elseif prev_char == "\u201D"
execute "normal xr\u201C"
echo "LEFT DOUBLE QUOTATION MARK"
else
execute "normal lr\u201D"
echo "RIGHT DOUBLE QUOTATION MARK"
endif
endif
endfunction
function! UniCycleOn()
inoremap - -:call UniCycleHyphen()a
inoremap . .:call UniCyclePeriod()a
inoremap ' x:call UniCycleApostrophe()a
inoremap " x:call UniCycleQuote()a
endfunction
function! UniCycleOff()
iunmap -
iunmap .
iunmap '
iunmap "
endfunction
command UniCycleOn call UniCycleOn()
command UniCycleOff call UniCycleOff()