def check(cmd): type = ex.linecmd(cmd.plain) if not type or 'map' not in type or 'unmap' in type: return sp = re.split('\s+', cmd.plain.lstrip("\t :"), maxsplit=1) if len(sp) == 1: return ex.LintMessage('Missing {lhs}') typestr, rest = sp modifiers = set() while True: if rest.isspace(): return ex.LintMessage('Missing {lhs}') sp = re.split('\s+', rest, maxsplit=1) if len(sp) == 1: return ex.LintMessage("Missing {rhs}") val, rest = sp if val.lower() in map_modifiers: modifiers.add(val.lower()) elif re.match('(<\w+>)+', val): all_match = True for m in re.findall('<\w+>', val.lower()): if m not in map_modifiers: all_match = False break modifiers.add(m) if not all_match: break else: break lhs = val rhs = rest if rhs.isspace(): return ex.LintMessage("Missing {rhs}") if type in ['vnoremap', 'vmap'] and re.match('([^<^]|<leader>|<space>)', lhs, re.IGNORECASE): return ex.LintMessage("Consider using xnoremap or xmap for visual mappings", warning=True) if type in ['nnoremap', 'nmap', 'noremap', 'map'] \ and '<buffer>' not in modifiers \ and lhs.lower() in ['<c-i>', '<tab>']: return ex.LintMessage("It's generally better not to remap <Tab> or <C-i>", warning=True) if 'remap' in type and re.match('<plug>', rhs, re.IGNORECASE): return ex.LintMessage("Use a normal 'map' command to make use of <Plug>") # if re.match(':call\s', rhs, re.IGNORECASE): # return ex.LintMessage("Consider using ':<C-U>call' instead to prevent range errors", warning=True, col=cmd.plain.index(':') + 1) if re.match('.*\s+$', rhs): return ex.LintMessage("Use <space> instead of trailing spaces in mappings", warning=True, col=len(cmd.plain))
def check(commands): messages = [] control_stack = [] for cmd in commands: type = ex.linecmd(cmd.plain) if type in starts: control_stack += [(type, cmd)] elif type in checks: nested = False for start, _ in control_stack: if start in checks[type]: nested = True if not nested: messages += [ex.LintMessage('Statement not nested in the appropriate control structure', line=cmd.startline)] elif type in ends: if not control_stack: messages += [ex.LintMessage('There is nothing open to close', line=cmd.startline)] else: start, _ = control_stack[-1] if start in ends[type]: control_stack.pop() else: messages += [ex.LintMessage('Unmatched closing statement', line=cmd.startline)] for type, cmd in control_stack: messages += [ex.LintMessage('Missing closing statement', line=cmd.startline)] return messages
def check_cmd(cmd): type = ex.linecmd(cmd.plain) if type not in ['set', 'setlocal', 'setglobal']: return sp = re.match('\s*:*set\S*\s+(.+$)', cmd.plain) if not sp: return ex.LintMessage('Missing options list') for option in parse(sp.group(1)): msg = check_option(option) if msg: if msg.col is None: msg.col = cmd.plain.index(option) + 1 return msg
def check(cmd): type = ex.linecmd(cmd.plain) if not type or "map" not in type or "unmap" in type: return sp = re.split("\s+", cmd.plain.lstrip("\t :"), maxsplit=1) if len(sp) == 1: return ex.LintMessage("Missing {lhs}") typestr, rest = sp modifiers = set() while True: if rest.isspace(): return ex.LintMessage("Missing {lhs}") sp = re.split("\s+", rest, maxsplit=1) if len(sp) == 1: return ex.LintMessage("Missing {rhs}") val, rest = sp if val.lower() in map_modifiers: modifiers.add(val.lower()) elif re.match("(<\w+>)+", val): all_match = True for m in re.findall("<\w+>", val.lower()): if m not in map_modifiers: all_match = False break modifiers.add(m) if not all_match: break else: break lhs = val rhs = rest if rhs.isspace(): return ex.LintMessage("Missing {rhs}") if type in ["vnoremap", "vmap"] and re.match("([^<^]|<leader>|<space>)", lhs, re.IGNORECASE): return ex.LintMessage("Consider using xnoremap or xmap for visual mappings", warning=True) if ( type in ["nnoremap", "nmap", "noremap", "map"] and "<buffer>" not in modifiers and lhs.lower() in ["<c-i>", "<tab>"] ): return ex.LintMessage("It's generally better not to remap <Tab> or <C-i>", warning=True) if "remap" in type and re.match("<plug>", rhs, re.IGNORECASE): return ex.LintMessage("Use a normal 'map' command to make use of <Plug>") # if re.match(':call\s', rhs, re.IGNORECASE): # return ex.LintMessage("Consider using ':<C-U>call' instead to prevent range errors", warning=True, col=cmd.plain.index(':') + 1) if re.match(".*\s+$", rhs): return ex.LintMessage("Use <space> instead of trailing spaces in mappings", warning=True, col=len(cmd.plain))