Skip to content

Instantly share code, notes, and snippets.

@Vftdan
Created October 24, 2022 20:00
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save Vftdan/3b545890eda742eb4d626f0e62f3fa3b to your computer and use it in GitHub Desktop.
Save Vftdan/3b545890eda742eb4d626f0e62f3fa3b to your computer and use it in GitHub Desktop.
Vim keymap for https://bouncepaw.github.io/sunskribo (breaks in my version of NeoVim, but works in vim.gtk3)
scriptencoding utf-8
let b:keymap_name = "sunskribo"
lmapclear <buffer>
function! s:get_any_var(name, default)
let l:g = get(g:, a:name, a:default)
let l:b = get(b:, a:name, l:g)
return get(w:, a:name, l:b)
endfunction
function! s:get_plugin_setting(name, default)
return s:get_any_var('sunskribo_' . a:name, a:default)
endfunction
function! s:escape_ltgt(str)
" Add more from |key-notation| if needed
let l:str = a:str
for [l:pat, l:code] in [['<', 'lt'], ['\\', 'Bslash'], ['|', 'Bar'], ['\r', 'CR'], [' ', 'Space'], ["\<plug>", 'Plug']]
let l:str = substitute(l:str, '\Z' . l:pat, '<' . l:code . '>', 'g')
endfor
return l:str
endfunction
function! sunskribo#do_lmap(lhs, rhs)
" echom 'lmap ' . s:escape_ltgt(a:lhs) . ' ' . s:escape_ltgt(a:rhs)
" echom a:lhs . "\t" . a:rhs
execute 'lmap <buffer> ' . s:escape_ltgt(a:lhs) . ' ' . s:escape_ltgt(a:rhs)
endfunction
" SYLLABLE := CONSONANT LEFT_MODIFIER VOWEL MODIFIER*
let s:consonants = {
\ '': 'ı',
\ 'b': 'ə',
\ 'c': 'Ա',
\ 'cx': 'ч',
\ 'ĉ': 'ч',
\ 'd': 'თ',
\ 'f': 'ᑫ',
\ 'g': 'γ',
\ 'gx': 'Ꮽ',
\ 'ĝ': 'Ꮽ',
\ 'h': 'H',
\ 'j': 'ᒍ',
\ 'jx': 'ᒐ',
\ 'ĵ': 'ᒐ',
\ 'k': 'к',
\ 'l': 'Λ',
\ 'm': 'μ',
\ 'n': 'v',
\ 'p': 'ρ',
\ 'r': 'ᒥ',
\ 's': 'с',
\ 'sx': 'ᑐ',
\ 'ŝ': 'ᑐ',
\ 't': '├',
\ 'T': '┤',
\ 'w': 'ω',
\ 'ux': 'ω',
\ 'ŭ': 'ω',
\ 'v': 'ვ',
\ 'z': 'z',
\ }
let s:vowels = {
\ '': '',
\ 'a': '̀',
\ 'e': '́',
\ 'u': '̈',
\ 'o': 'ᷦ',
\ 'i': '͗',
\ 'y': '̃',
\ 'ı': '̃',
\ 'ɨ': '̃',
\ }
" y: Slavic, ı: Turkic, ɨ: IPA
let s:modifiers = {
\ 'ː': '̰',
\ ':': '̰',
\ 'x': '̦',
\ 'xx': '᪸',
\ '_': '̣',
\ }
" Use 'x' as alternative sound mark. As long as we do not use it for 'c', 'j', 's' should be ok
" Should we interpret double letters as long?
let s:soft_prefix = 'ʻ'
" Typed on the right (before the vowel), result on the left
let s:left_modifiers = {
\ '': '',
\ 'j': s:soft_prefix,
\ 'ʲ': s:soft_prefix,
\ '́': s:soft_prefix,
\ }
" 'j' can be both modifier and consonant, so we need to define priority
" Interpret consonant acute as softness marker
let s:left_modified_consonants = {
\ 'ć': s:soft_prefix . s:consonants['c'],
\ 'ćx': s:soft_prefix . s:consonants['cx'],
\ 'ǵ': s:soft_prefix . s:consonants['g'],
\ 'ǵx': s:soft_prefix . s:consonants['gx'],
\ 'ḱ': s:soft_prefix . s:consonants['k'],
\ 'ĺ': s:soft_prefix . s:consonants['l'],
\ 'ḿ': s:soft_prefix . s:consonants['m'],
\ 'ń': s:soft_prefix . s:consonants['n'],
\ 'ṕ': s:soft_prefix . s:consonants['p'],
\ 'ŕ': s:soft_prefix . s:consonants['r'],
\ 'ś': s:soft_prefix . s:consonants['s'],
\ 'śx': s:soft_prefix . s:consonants['sx'],
\ 'ź': s:soft_prefix . s:consonants['z'],
\ }
" Do all of them make sense? 'cx' is already soft
" Make 'ä' synonymous to 'ʲa'
let s:umlauts = {
\ 'a': 'ä',
\ 'e': 'ë',
\ 'u': 'ü',
\ 'o': 'ö',
\ }
" let s:left_modifiers_vowel = {
" \ 'ä': ['ʻ', '̀'],
" \ 'ë': ['ʻ', '́'],
" \ 'ü': ['ʻ', '̈'],
" \ 'ö': ['ʻ', 'ᷦ'],
" \ }
let s:eo_endings = {
\ 'o': '̊',
\ 'on': '̊́',
\ 'oj': '̊̄',
\ 'ojn': '̊́̄',
\ 'a': '̏',
\ 'an': '̀́',
\ 'aj': '̄̀',
\ 'ajn': '⃰',
\ 'e': '̋',
\ 'en': '᷻',
\ 'i': '͑',
\ 'is': '̄͑',
\ 'u': '̄͑̄',
\ 'us': '̄ͤ̄',
\ 'os': '͑̄',
\ 'as': 'ͤ',
\ }
" Unicode 14.0 added Combining Plus Sign Above (U+1AC8), which may be used for 'aj'
let s:punctuation = {
\ '.': '∘',
\ ',': '⌕',
\ ':': '⦂',
\ ';': '⨾',
\ '!': '⫰',
\ '?': '?',
\ ',,': '「',
\ '``': '「',
\ '<<': '「',
\ '"': '」',
\ "''": '」',
\ '>>': '」',
\ '...': '⁝',
\ '--': '⟜',
\ '–': '⟜',
\ '—': '⟜',
\ }
" I haven't found anything better for comma
" I don't think unicode has anything for the question mark
let s:logographs = {
\ 'skrib': '📝︎',
\ 'graf': '📝︎',
\ 'de': 'Δ',
\ 'da': 'Δ',
\ 'cxu': '߂',
\ 'ĉu': '߂',
\ 'ki': '𝈎',
\ 'ti': 'T',
\ 'cxi': 'h',
\ 'ĉi': 'h',
\ 'nov': '¤',
\ 'ar': '◫',
\ 'la': 'L',
\ 'mi': '工',
\ 'ni': '王',
\ 'vi': '▽',
\ 'ri': 'ᕈ',
\ 'ili': '⚻',
\ 'gi': 'G',
\ 'kaj': '&',
\ 'estas': '∃',
\ 'ne': 'И',
\ 'ke': '𝈲',
\ }
" Seems like vim terminal renderer doesn't know that variation selectors are combining
" I do not know how to encode 'est' ligature
" Consumed once in case of ambiguous mapping
let s:commit_key = s:get_plugin_setting('commit_key', "'")
let s:all_maps = {}
" let s:count = 0
for [s:lhs_C, s:rhs_C] in items(s:consonants)
for [s:lhs_V, s:rhs_V] in items(s:vowels)
for [s:lhs_L, s:rhs_L] in items(s:left_modifiers)
if s:lhs_C == '' && has_key(s:consonants, s:lhs_L)
continue
endif
let s:lhs = s:lhs_C . s:lhs_L . s:lhs_V
let s:rhs = s:rhs_L . s:rhs_C . s:rhs_V
let s:all_maps[s:lhs] = s:rhs
if s:lhs_V != ''
let s:all_maps[s:lhs . s:lhs_V] = s:rhs . s:modifiers[':']
endif
" let s:count += 2
endfor
endfor
for [s:vowel, s:lhs_V] in items(s:umlauts)
let s:lhs = s:lhs_C . s:lhs_V
let s:rhs = s:soft_prefix . s:rhs_C . s:vowels[s:vowel]
let s:all_maps[s:lhs] = s:rhs
if s:lhs_V != ''
let s:all_maps[s:lhs . s:lhs_V] = s:rhs . s:modifiers[':']
endif
" let s:count += 2
endfor
" We do not need soft marks and long vowels with Esperanto endings?
for [s:lhs_V, s:rhs_V] in items(s:eo_endings)
let s:lhs = s:lhs_C . toupper(s:lhs_V)
let s:rhs = s:rhs_C . s:rhs_V
let s:all_maps[s:lhs] = s:rhs
" let s:count += 1
endfor
endfor
for [s:lhs_C, s:rhs_C] in items(s:left_modified_consonants)
for [s:lhs_V, s:rhs_V] in items(s:vowels)
let s:lhs = s:lhs_C . s:lhs_V
let s:rhs = s:rhs_C . s:rhs_V
let s:all_maps[s:lhs] = s:rhs
if s:lhs_V != ''
let s:all_maps[s:lhs . s:lhs_V] = s:rhs . s:modifiers[':']
endif
" let s:count += 2
endfor
endfor
for [s:lhs, s:rhs] in items(s:modifiers)
let s:all_maps[s:lhs] = s:rhs
" let s:count += 1
endfor
for [s:lhs, s:rhs] in items(s:punctuation)
let s:all_maps[s:lhs] = s:rhs
" let s:count += 1
endfor
for [s:lhs, s:rhs] in items(s:logographs)
let s:all_maps[toupper(s:lhs)] = s:rhs
" let s:count += 1
endfor
" echo s:all_maps
" echo len(s:all_maps)
" echo s:count
if has_key(s:all_maps, '')
unlet s:all_maps['']
endif
let s:lhs_all = sort(keys(s:all_maps))
if s:commit_key != ''
for s:i in range(len(s:lhs_all) - 1)
let s:lhs = s:lhs_all[s:i]
let s:longer = s:lhs_all[s:i + 1]
if s:longer[:len(s:lhs) - 1] != s:lhs
continue
endif
let s:all_maps[s:lhs . s:commit_key] = s:all_maps[s:lhs]
endfor
endif
for [s:lhs, s:rhs] in items(s:all_maps)
call sunskribo#do_lmap(s:lhs, s:rhs)
endfor
if !s:get_plugin_setting('no_cleanup', v:false)
unlet s:consonants
unlet s:vowels
unlet s:left_modifiers
unlet s:left_modified_consonants
unlet s:umlauts
unlet s:eo_endings
unlet s:punctuation
unlet s:logographs
unlet s:all_maps
unlet s:lhs_all
endif
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment