Commits

Michał Górny committed e151649

Support option list.

The list is used to map short options to long ones, and to handle
booleans.

Comments (0)

Files changed (2)

pymodeline/__init__.py

 {}
 >>> pprint(p.parse_line('vim<100:syntax=perl'))
 {}
+>>> pprint(p.parse_line('vim:syn=perl:ft=python:tw=80'))
+{'filetype': 'python', 'syntax': 'perl', 'textwidth': '80'}
+>>> pprint(p.parse_line('vim:noai:ari'))
+{'allowrevins': True, 'autoindent': False}
 """
 
 import re
 
+from optionlist import boolean_options, option_mapping, option_list
+
+class ModelineDict(dict):
+	"""
+	Dict wrapper mapping option names.
+
+	The short option names will be mapped to the long ones.
+	Additionally, boolean variables will be mapped from 'no*' variants
+	to the positive ones, and when queried -- the other way.
+	"""
+
+	@staticmethod
+	def _get_long_option(key):
+		if key.startswith('no'):
+			key = key[2:]
+		if key in option_mapping:
+			key = option_mapping[key]
+		elif key not in option_list:
+			raise KeyError('Invalid vim option: %s' % key)
+		return key
+
+	def __getitem__(self, key):
+		return dict.__getitem__(self, self._get_long_option(key))
+
+	def __setitem__(self, key, val):
+		long_key = self._get_long_option(key)
+
+		if long_key in boolean_options:
+			if val is not None:
+				raise ValueError('Boolean option has a value: %s=%s'
+						% (key, val))
+			val = not key.startswith('no')
+		elif val is None:
+			raise ValueError('Non-boolean option lacks value: %s' % key)
+
+		return dict.__setitem__(self, long_key, val)
+
+	def __hasitem__(self, key):
+		return dict.__hasitem__(self, self._get_long_option(key))
+
 class ModelineParser(object):
 	"""
 	A parser for vim modelines.
 		# Note: 'modelines' option in modeline does not affect modeline
 		# parsing, so we can treat that as const.
 		mls = self._modelines
-		ret = dict()
+		ret = ModelineDict()
 
 		# XXX: replace it with something more efficient. And prevent
 		# parsing the same lines twice.
 		Returns a dict with options and their values.
 		"""
 
-		ret = {}
+		ret = ModelineDict()
 
 		m = self._form2_re.match(l) or self._form1_re.match(l)
 		if m:
 				if len(kv) > 1:
 					value = self._option_unescape_re.sub(r'\1', kv[1])
 				else:
-					value = True
+					value = None
 
 				ret[key] = value
 

pymodeline/optionlist.py

+#!/usr/bin/python
+#	vim:fileencoding=utf-8
+# vim modeline parsing -- option list.
+# (c) 2012 Michał Górny <mgorny@gentoo.org>
+# Released under the terms of the 2-clause BSD license.
+
+# to generate:
+# :help aleph, :w /tmp/l.txt
+# awk "/^'.*boolean/ "'{ print $1 "," }' /tmp/l.txt
+
+boolean_options = frozenset([
+	'allowrevins',
+	'altkeymap',
+	'antialias',
+	'autochdir',
+	'arabic',
+	'arabicshape',
+	'autoindent',
+	'autoread',
+	'autowrite',
+	'autowriteall',
+	'backup',
+	'ballooneval',
+	'binary',
+	'bioskey',
+	'bomb',
+	'buflisted',
+	'cindent',
+	'compatible',
+	'confirm',
+	'conskey',
+	'copyindent',
+	'cscoperelative',
+	'cscopetag',
+	'cscopeverbose',
+	'cursorbind',
+	'cursorcolumn',
+	'cursorline',
+	'delcombine',
+	'diff',
+	'digraph',
+	'edcompatible',
+	'endofline',
+	'equalalways',
+	'errorbells',
+	'esckeys',
+	'expandtab',
+	'exrc',
+	'fkmap',
+	'foldenable',
+	'fsync',
+	'gdefault',
+	'guipty',
+	'hidden',
+	'hlsearch',
+	'hkmap',
+	'hkmapp',
+	'icon',
+	'ignorecase',
+	'imcmdline',
+	'imdisable',
+	'incsearch',
+	'infercase',
+	'insertmode',
+	'joinspaces',
+	'lazyredraw',
+	'linebreak',
+	'lisp',
+	'list',
+	'loadplugins',
+	'macatsui',
+	'magic',
+	'modeline',
+	'modifiable',
+	'modified',
+	'more',
+	'mousefocus',
+	'mousehide',
+	'number',
+	'opendevice',
+	'paste',
+	'preserveindent',
+	'previewwindow',
+	'prompt',
+	'readonly',
+	'relativenumber',
+	'remap',
+	'restorescreen',
+	'revins',
+	'rightleft',
+	'ruler',
+	'scrollbind',
+	'secure',
+	'shellslash',
+	'shelltemp',
+	'shiftround',
+	'shortname',
+	'showcmd',
+	'showfulltag',
+	'showmatch',
+	'showmode',
+	'smartcase',
+	'smartindent',
+	'smarttab',
+	'spell',
+	'splitbelow',
+	'splitright',
+	'startofline',
+	'swapfile',
+	'tagbsearch',
+	'tagrelative',
+	'tagstack',
+	'termbidi',
+	'terse',
+	'textauto',
+	'textmode',
+	'tildeop',
+	'timeout',
+	'ttimeout',
+	'title',
+	'ttybuiltin',
+	'ttyfast',
+	'undofile',
+	'visualbell',
+	'warn',
+	'weirdinvert',
+	'wildignorecase',
+	'wildmenu',
+	'winfixheight',
+	'winfixwidth',
+	'wrap',
+	'wrapscan',
+	'write',
+	'writeany',
+	'writebackup'
+])
+
+# to generate:
+# :help aleph, :w /tmp/l.txt
+# awk "/^'/ && \$2 ~ /^'/ "'{ print $2 ": " $1 "," }' /tmp/l.txt
+
+option_mapping = {
+	'al': 'aleph',
+	'ari': 'allowrevins',
+	'akm': 'altkeymap',
+	'ambw': 'ambiwidth',
+	'anti': 'antialias',
+	'acd': 'autochdir',
+	'arab': 'arabic',
+	'arshape': 'arabicshape',
+	'ai': 'autoindent',
+	'ar': 'autoread',
+	'aw': 'autowrite',
+	'awa': 'autowriteall',
+	'bg': 'background',
+	'bs': 'backspace',
+	'bk': 'backup',
+	'bkc': 'backupcopy',
+	'bdir': 'backupdir',
+	'bex': 'backupext',
+	'bsk': 'backupskip',
+	'bdlay': 'balloondelay',
+	'beval': 'ballooneval',
+	'bexpr': 'balloonexpr',
+	'bin': 'binary',
+	'biosk': 'bioskey',
+	'brk': 'breakat',
+	'bsdir': 'browsedir',
+	'bh': 'bufhidden',
+	'bl': 'buflisted',
+	'bt': 'buftype',
+	'cmp': 'casemap',
+	'cd': 'cdpath',
+	'ccv': 'charconvert',
+	'cin': 'cindent',
+	'cink': 'cinkeys',
+	'cino': 'cinoptions',
+	'cinw': 'cinwords',
+	'cb': 'clipboard',
+	'ch': 'cmdheight',
+	'cwh': 'cmdwinheight',
+	'cc': 'colorcolumn',
+	'co': 'columns',
+	'com': 'comments',
+	'cms': 'commentstring',
+	'cp': 'compatible',
+	'cpt': 'complete',
+	'cfu': 'completefunc',
+	'cot': 'completeopt',
+	'cocu': 'concealcursor',
+	'cole': 'conceallevel',
+	'cf': 'confirm',
+	'consk': 'conskey',
+	'ci': 'copyindent',
+	'cpo': 'cpoptions',
+	'cspc': 'cscopepathcomp',
+	'csprg': 'cscopeprg',
+	'csqf': 'cscopequickfix',
+	'csre': 'cscoperelative',
+	'cst': 'cscopetag',
+	'csto': 'cscopetagorder',
+	'csverb': 'cscopeverbose',
+	'crb': 'cursorbind',
+	'cuc': 'cursorcolumn',
+	'cul': 'cursorline',
+	'def': 'define',
+	'deco': 'delcombine',
+	'dict': 'dictionary',
+	'dex': 'diffexpr',
+	'dip': 'diffopt',
+	'dg': 'digraph',
+	'dir': 'directory',
+	'dy': 'display',
+	'ead': 'eadirection',
+	'ed': 'edcompatible',
+	'enc': 'encoding',
+	'eol': 'endofline',
+	'ea': 'equalalways',
+	'ep': 'equalprg',
+	'eb': 'errorbells',
+	'ef': 'errorfile',
+	'efm': 'errorformat',
+	'ek': 'esckeys',
+	'ei': 'eventignore',
+	'et': 'expandtab',
+	'ex': 'exrc',
+	'fenc': 'fileencoding',
+	'fencs': 'fileencodings',
+	'ff': 'fileformat',
+	'ffs': 'fileformats',
+	'ft': 'filetype',
+	'fcs': 'fillchars',
+	'fk': 'fkmap',
+	'fcl': 'foldclose',
+	'fdc': 'foldcolumn',
+	'fen': 'foldenable',
+	'fde': 'foldexpr',
+	'fdi': 'foldignore',
+	'fdl': 'foldlevel',
+	'fdls': 'foldlevelstart',
+	'fmr': 'foldmarker',
+	'fdm': 'foldmethod',
+	'fml': 'foldminlines',
+	'fdn': 'foldnestmax',
+	'fdo': 'foldopen',
+	'fdt': 'foldtext',
+	'fo': 'formatoptions',
+	'flp': 'formatlistpat',
+	'fp': 'formatprg',
+	'fex': 'formatexpr',
+	'fs': 'fsync',
+	'gd': 'gdefault',
+	'gfm': 'grepformat',
+	'gp': 'grepprg',
+	'gcr': 'guicursor',
+	'gfn': 'guifont',
+	'gfs': 'guifontset',
+	'gfw': 'guifontwide',
+	'ghr': 'guiheadroom',
+	'go': 'guioptions',
+	'gtl': 'guitablabel',
+	'gtt': 'guitabtooltip',
+	'hf': 'helpfile',
+	'hh': 'helpheight',
+	'hlg': 'helplang',
+	'hid': 'hidden',
+	'hl': 'highlight',
+	'hls': 'hlsearch',
+	'hi': 'history',
+	'hk': 'hkmap',
+	'hkp': 'hkmapp',
+	'ic': 'ignorecase',
+	'imak': 'imactivatekey',
+	'imc': 'imcmdline',
+	'imd': 'imdisable',
+	'imi': 'iminsert',
+	'ims': 'imsearch',
+	'inc': 'include',
+	'inex': 'includeexpr',
+	'is': 'incsearch',
+	'inde': 'indentexpr',
+	'indk': 'indentkeys',
+	'inf': 'infercase',
+	'im': 'insertmode',
+	'isf': 'isfname',
+	'isi': 'isident',
+	'isk': 'iskeyword',
+	'isp': 'isprint',
+	'js': 'joinspaces',
+	'kmp': 'keymap',
+	'km': 'keymodel',
+	'kp': 'keywordprg',
+	'lmap': 'langmap',
+	'lm': 'langmenu',
+	'ls': 'laststatus',
+	'lz': 'lazyredraw',
+	'lbr': 'linebreak',
+	'lsp': 'linespace',
+	'lw': 'lispwords',
+	'lcs': 'listchars',
+	'lpl': 'loadplugins',
+	'mef': 'makeef',
+	'mp': 'makeprg',
+	'mps': 'matchpairs',
+	'mat': 'matchtime',
+	'mco': 'maxcombine',
+	'mfd': 'maxfuncdepth',
+	'mmd': 'maxmapdepth',
+	'mm': 'maxmem',
+	'mmp': 'maxmempattern',
+	'mmt': 'maxmemtot',
+	'mis': 'menuitems',
+	'msm': 'mkspellmem',
+	'ml': 'modeline',
+	'mls': 'modelines',
+	'ma': 'modifiable',
+	'mod': 'modified',
+	'mousef': 'mousefocus',
+	'mh': 'mousehide',
+	'mousem': 'mousemodel',
+	'mouses': 'mouseshape',
+	'mouset': 'mousetime',
+	'mzq': 'mzquantum',
+	'nf': 'nrformats',
+	'nu': 'number',
+	'nuw': 'numberwidth',
+	'ofu': 'omnifunc',
+	'odev': 'opendevice',
+	'opfunc': 'operatorfunc',
+	'oft': 'osfiletype',
+	'para': 'paragraphs',
+	'pt': 'pastetoggle',
+	'pex': 'patchexpr',
+	'pm': 'patchmode',
+	'pa': 'path',
+	'pi': 'preserveindent',
+	'pvh': 'previewheight',
+	'pvw': 'previewwindow',
+	'pdev': 'printdevice',
+	'penc': 'printencoding',
+	'pexpr': 'printexpr',
+	'pfn': 'printfont',
+	'pheader': 'printheader',
+	'pmbcs': 'printmbcharset',
+	'pmbfn': 'printmbfont',
+	'popt': 'printoptions',
+	'ph': 'pumheight',
+	'qe': 'quoteescape',
+	'ro': 'readonly',
+	'rdt': 'redrawtime',
+	'rnu': 'relativenumber',
+	'rs': 'restorescreen',
+	'ri': 'revins',
+	'rl': 'rightleft',
+	'rlc': 'rightleftcmd',
+	'ru': 'ruler',
+	'ruf': 'rulerformat',
+	'rtp': 'runtimepath',
+	'scr': 'scroll',
+	'scb': 'scrollbind',
+	'sj': 'scrolljump',
+	'so': 'scrolloff',
+	'sbo': 'scrollopt',
+	'sect': 'sections',
+	'sel': 'selection',
+	'slm': 'selectmode',
+	'ssop': 'sessionoptions',
+	'sh': 'shell',
+	'shcf': 'shellcmdflag',
+	'sp': 'shellpipe',
+	'shq': 'shellquote',
+	'srr': 'shellredir',
+	'ssl': 'shellslash',
+	'stmp': 'shelltemp',
+	'st': 'shelltype',
+	'sxe': 'shellxescape',
+	'sxq': 'shellxquote',
+	'sr': 'shiftround',
+	'sw': 'shiftwidth',
+	'shm': 'shortmess',
+	'sn': 'shortname',
+	'sbr': 'showbreak',
+	'sc': 'showcmd',
+	'sft': 'showfulltag',
+	'sm': 'showmatch',
+	'smd': 'showmode',
+	'stal': 'showtabline',
+	'ss': 'sidescroll',
+	'siso': 'sidescrolloff',
+	'scs': 'smartcase',
+	'si': 'smartindent',
+	'sta': 'smarttab',
+	'sts': 'softtabstop',
+	'spc': 'spellcapcheck',
+	'spf': 'spellfile',
+	'spl': 'spelllang',
+	'sps': 'spellsuggest',
+	'sb': 'splitbelow',
+	'spr': 'splitright',
+	'sol': 'startofline',
+	'stl': 'statusline',
+	'su': 'suffixes',
+	'sua': 'suffixesadd',
+	'swf': 'swapfile',
+	'sws': 'swapsync',
+	'swb': 'switchbuf',
+	'smc': 'synmaxcol',
+	'syn': 'syntax',
+	'tal': 'tabline',
+	'tpm': 'tabpagemax',
+	'ts': 'tabstop',
+	'tbs': 'tagbsearch',
+	'tl': 'taglength',
+	'tr': 'tagrelative',
+	'tag': 'tags',
+	'tgst': 'tagstack',
+	'tbidi': 'termbidi',
+	'tenc': 'termencoding',
+	'ta': 'textauto',
+	'tx': 'textmode',
+	'tw': 'textwidth',
+	'tsr': 'thesaurus',
+	'top': 'tildeop',
+	'to': 'timeout',
+	'tm': 'timeoutlen',
+	'ttm': 'ttimeoutlen',
+	'tb': 'toolbar',
+	'tbis': 'toolbariconsize',
+	'tbi': 'ttybuiltin',
+	'tf': 'ttyfast',
+	'ttym': 'ttymouse',
+	'tsl': 'ttyscroll',
+	'tty': 'ttytype',
+	'udir': 'undodir',
+	'udf': 'undofile',
+	'ul': 'undolevels',
+	'ur': 'undoreload',
+	'uc': 'updatecount',
+	'ut': 'updatetime',
+	'vbs': 'verbose',
+	'vfile': 'verbosefile',
+	'vdir': 'viewdir',
+	'vop': 'viewoptions',
+	'vi': 'viminfo',
+	've': 'virtualedit',
+	'vb': 'visualbell',
+	'wiv': 'weirdinvert',
+	'ww': 'whichwrap',
+	'wc': 'wildchar',
+	'wcm': 'wildcharm',
+	'wig': 'wildignore',
+	'wic': 'wildignorecase',
+	'wmnu': 'wildmenu',
+	'wim': 'wildmode',
+	'wop': 'wildoptions',
+	'wak': 'winaltkeys',
+	'wi': 'window',
+	'wh': 'winheight',
+	'wfh': 'winfixheight',
+	'wfw': 'winfixwidth',
+	'wmh': 'winminheight',
+	'wmw': 'winminwidth',
+	'wiw': 'winwidth',
+	'wm': 'wrapmargin',
+	'ws': 'wrapscan',
+	'wa': 'writeany',
+	'wb': 'writebackup',
+	'wd': 'writedelay'
+}
+
+option_list = frozenset(option_mapping.values())