def _ex_route_delete(state): command = TokenCommand('delete') command.addressable = True params = {'register': '"', 'count': None} state.skip(' ') state.ignore() c = state.consume() if c == state.EOF: command.params = params return None, [command, TokenEof()] state.backup() state.skip(' ') state.ignore() m = state.expect_match( r'(?P<register>[a-zA-Z0-9"])(?:\s+(?P<count>\d+))?\s*$') params.update(m.groupdict()) if params['count']: raise NotImplementedError('parameter not implemented') command.params = params return None, [command, TokenEof()]
def _ex_route_print(state): command = TokenCommand('print') command.addressable = True command.cooperates_with_global = True # TODO [review] count param looks unused. params = {'count': '', 'flags': []} while True: c = state.consume() state.skip(' ') state.ignore() if c == state.EOF: command.params = params return None, [command, TokenEof()] if c.isdigit(): state.match(r'\d*') params['count'] = state.emit() continue m = state.expect_match(r'[l#p]+') params['flags'] = list(m.group(0)) state.ignore() state.expect_eof() break command.params = params return None, [command, TokenEof()]
def _ex_route_tabprevious(state): command = TokenCommand('tabprevious') c = state.consume() if c == state.EOF: return None, [command, TokenEof()] command.forced = c == '!' return None, [command, TokenEof()]
def _ex_route_wq(state): command = TokenCommand('wq') # TODO [review] None of the prams looks used params = { '++': None, 'file': None, } c = state.consume() if c == state.EOF: command.params = params return None, [command, TokenEof()] bang = True if c == '!' else False if not bang: state.backup() c = state.consume() if c == '+': state.expect('+') state.ignore() # TODO: expect_match should work with emit() # https://vimhelp.appspot.com/editing.txt.html#[++opt] m = state.expect_match( r'(?:f(?:ile)?f(?:ormat)?|(?:file)?enc(?:oding)?|(?:no)?bin(?:ary)?|bad|edit)(?=\s|$)', lambda: Exception("E474: Invalid argument")) name = m.group(0) plus_plus_translations = { 'ff': 'fileformat', 'bin': 'binary', 'enc': 'fileencoding', 'nobin': 'nobinary', } params['++'] = plus_plus_translations.get(name, name) state.ignore() raise NotImplementedError('param not implemented') if c == state.EOF: command.params = params command.forced = bang return None, [command, TokenEof()] m = state.expect_match(r'.+$') params['file'] = m.group(0).strip() command.params = params command.forced = bang return None, [command, TokenEof()]
def _ex_route_file(state): command = TokenCommand('file') bang = state.consume() if bang == state.EOF: return None, [command, TokenEof()] bang = bang == '!' if not bang: raise Exception("E488: Trailing characters") state.expect_eof(on_error=lambda: Exception("E488: Trailing characters")) command.forced = bang return None, [command, TokenEof()]
def _ex_route_cdd(state): command = TokenCommand('cdd') c = state.consume() if c == state.EOF: return None, [command, TokenEof()] bang = c == '!' if not bang: state.backup() state.expect_eof() command.forced = bang return None, [command, TokenEof()]
def _ex_route_wqall(state): command = TokenCommand('wqall') command.addressable = True params = {'++': ''} state.skip(' ') state.ignore() c = state.consume() if c == '+': state.expect('+') state.ignore() # TODO: expect_match should work with emit() # https://vimhelp.appspot.com/editing.txt.html#[++opt] m = state.expect_match( r'(?:f(?:ile)?f(?:ormat)?|(?:file)?enc(?:oding)?|(?:no)?bin(?:ary)?|bad|edit)(?=\s|$)', lambda: Exception("E474: Invalid argument")) name = m.group(0) plus_plus_translations = { 'ff': 'fileformat', 'bin': 'binary', 'enc': 'fileencoding', 'nobin': 'nobinary' } params['++'] = plus_plus_translations.get(name, name) state.ignore() state.expect_eof() command.params = params return None, [command, TokenEof()]
def _scan_offset(state): offsets = [] def to_int(x): return int(x, 10) sign = '-' if state.source[state.position - 1] == '-' else '' digits = state.expect_match(r'\s*(\d+)') offsets.append(sign + digits.group(1)) while True: c = state.consume() if c == state.EOF: state.ignore() return None, [TokenOffset(list(map(to_int, offsets))), TokenEof()] if c == '+' or c == '-': digits = state.expect_match(r'\s*(\d+)') sign = '-' if state.source[state.position - 1] == '-' else '' offsets.append(sign + digits.group(1)) continue if not c.isdigit(): state.backup() state.ignore() return _scan_range, [TokenOffset(list(map(to_int, offsets)))]
def _ex_route_only(state): command = TokenCommand('only') bang = state.consume() if bang == '!': state.ignore() state.expect_eof() command.forced = True return None, [command, TokenEof()] # TODO [refactor] and remove assertion assert bang == state.EOF, 'trailing characters' return None, [command, TokenEof()]
def _scan_range(state): # Produce tokens found in a command line range. # https://vimhelp.appspot.com/cmdline.txt.html#cmdline-ranges # # Args: # :state (_ScannerState): # # Returns: # tuple c = state.consume() if c == state.EOF: return None, [TokenEof()] if c == '.': state.emit() return _scan_range, [TokenDot()] if c == '$': state.emit() return _scan_range, [TokenDollar()] if c == ',': state.emit() return _scan_range, [TokenComma()] if c in ';': state.emit() return _scan_range, [TokenSemicolon()] if c == "'": return _scan_mark(state) if c in '/?': return _scan_search(state) if c in '+-': return _scan_offset(state) if c == '%': state.emit() return _scan_range, [TokenPercent()] if c in '\t ': state.skip_run(' \t') state.ignore() if c.isdigit(): return _scan_digits(state) state.backup() return _scan_command, []
def _ex_route_quit(state): command = TokenCommand('quit') bang = state.consume() == '!' state.expect_eof() command.forced = bang return None, [command, TokenEof()]
def _ex_route_help(state): command = TokenCommand('help') match = state.expect_match(r'(?P<bang>!)?\s*(?P<subject>.+)?$').groupdict() params = {'subject': match['subject']} bang = bool(match['bang']) command.params = params command.forced = bang return None, [command, TokenEof()]
def _ex_route_abbreviate(state): command = TokenCommand('abbreviate') params = {'short': None, 'full': None} state.expect(' ') state.skip(' ') state.ignore() if state.consume() == state.EOF: return None, [command, TokenEof()] state.backup() m = state.match(r'(?P<short>.+?)(?: +(?P<full>.+))?$') params.update(m.groupdict()) command.params = params return None, [command, TokenEof()]
def _scan_command(state): # Args: # :state (_ScannerState): # # Returns: # Tuple[None, list(TokenEof)] for route, command in ex_routes.items(): if state.match(route): state.ignore() cmd = command(state) state.expect_eof(lambda: Exception("E492: Not an editor command")) return None, [cmd, TokenEof()] state.expect_eof(lambda: Exception("E492: Not an editor command")) return None, [TokenEof()]
def _ex_route_unabbreviate(state): command = TokenCommand('unabbreviate') params = {'lhs': None} m = state.expect_match(r'\s+(?P<lhs>.+?)\s*$') params.update(m.groupdict()) command.params = params return None, [command, TokenEof()]
def _ex_route_buffers(state): command = TokenCommand('buffers') try: state.expect_eof() except ValueError: # TODO Use a special domain exception for exceptions raised in scans. raise Exception("E488: Trailing characters") return None, [command, TokenEof()]
def _ex_route_split(state): command = TokenCommand('split') params = {'file': None} state.skip(' ') state.ignore() if state.consume() == state.EOF: command.params = params return None, [command, TokenEof()] state.backup() params['file'] = state.match(r'.+$').group(0).strip() command.params = params return None, [command, TokenEof()]
def _scan_digits(state): while True: c = state.consume() if not c.isdigit(): if c == state.EOF: return None, [TokenDigits(state.emit()), TokenEof()] state.backup() break return _scan_range, [TokenDigits(state.emit())]
def _ex_route_copy(state): command = TokenCommand('copy') command.addressable = True params = {'address': None} m = state.expect_match(r'\s*(?P<address>.+?)\s*$') params.update(m.groupdict()) command.params = params return None, [command, TokenEof()]
def _ex_route_sunmap(state): command = TokenCommand('sunmap') params = {'keys': None} m = state.match(r'\s*(?P<keys>.+?)\s*$') if m: params.update(m.groupdict()) command.params = params return None, [command, TokenEof()]
def _ex_route_shell_out(state): command = TokenCommand('!', target='shell_out') command.addressable = True params = {'cmd': None} m = state.expect_match(r'(?P<cmd>.+)$') params.update(m.groupdict()) command.params = params return None, [command, TokenEof()]
def _ex_route_cd(state): command = TokenCommand('cd') # TODO [refactor] Should params should used keys compatible with **kwargs? (review other commands too) # noqa: E501 params = {'path': None, '-': None} bang = False c = state.consume() if c == state.EOF: command.params = params command.forced = bang return None, [command, TokenEof()] bang = c == '!' if not bang: state.backup() state.skip(' ') state.ignore() c = state.consume() if c == state.EOF: command.params = params command.forced = bang return None, [command, TokenEof()] if c == '-': raise NotImplementedError('parameter not implemented') state.backup() m = state.match(r'(?P<path>.+?)\s*$') params.update(m.groupdict()) command.params = params command.forced = bang return None, [command, TokenEof()]
def _ex_route_setlocal(state): command = TokenCommand('setlocal') params = {'option': None, 'value': None} state.skip(' ') state.ignore() m = state.expect_match(r'(?P<option>.+?)(?:[:=](?P<value>.+?))?$') params.update(m.groupdict()) command.params = params return None, [command, TokenEof()]
def _ex_route_let(state): command = TokenCommand('let') params = {'name': None, 'value': None} m = state.expect_match( r'(?P<name>.+?)\s*=\s*(?P<value>.+?)\s*$', on_error=lambda: Exception("E121: Undefined variable")) params.update(m.groupdict()) command.params = params return None, [command, TokenEof()]
def _ex_route_read(state): command = TokenCommand('read') params = { 'cmd': None, '++': [], 'file_name': None, } state.skip(' ') state.ignore() c = state.consume() if c == '+': state.expect('+') state.ignore() # TODO: expect_match should work with emit() # https://vimhelp.appspot.com/editing.txt.html#[++opt] m = state.expect_match( r'(?:f(?:ile)?f(?:ormat)?|(?:file)?enc(?:oding)?|(?:no)?bin(?:ary)?|bad|edit)(?=\s|$)', lambda: Exception("E474: Invalid argument")) name = m.group(0) plus_plus_translations = { 'ff': 'fileformat', 'bin': 'binary', 'enc': 'fileencoding', 'nobin': 'nobinary', } params['++'] = plus_plus_translations.get(name, name) state.ignore() raise NotImplementedError('++opt not implemented') elif c == '!': m = state.match(r'(?P<cmd>.+)') params.update(m.groupdict()) else: state.backup() m = state.match(r'(?P<file_name>.+)$') params.update(m.groupdict()) state.expect_eof() command.params = params return None, [command, TokenEof()]
def _ex_route_double_ampersand(state): command = TokenCommand('&&', target='double_ampersand') command.addressable = True params = {'flags': [], 'count': ''} m = state.match(r'\s*([cgr])*\s*(\d*)\s*$') params['flags'] = list(m.group(1)) if m.group(1) else [] params['count'] = m.group(2) or '' state.expect_eof() command.params = params return None, [command, TokenEof()]
def _ex_route_move(state): command = TokenCommand('move') command.addressable = True params = {'address': None} state.skip(' ') state.ignore() m = state.match(r'(?P<address>.*$)') if m: address_command_line = m.group(0).strip() or '.' params['address'] = address_command_line command.params = params return None, [command, TokenEof()]
def _ex_route_browse(state): command = TokenCommand('browse') # TODO [review] "cmd" param looks unused. params = {'cmd': None} state.skip(' ') state.ignore() m = state.match(r'(?P<cmd>.*)$') params.update(m.groupdict()) if params['cmd']: raise NotImplementedError('parameter not implemented') command.params = params return None, [command, TokenEof()]
def _ex_route_registers(state): command = TokenCommand('registers') # TODO [review] "names" param looks unused by ex_registers params = {'names': []} state.skip(' ') state.ignore() while True: c = state.consume() if c == state.EOF: command.params = params return None, [command, TokenEof()] elif c.isalpha() or c.isdigit(): params['names'].append(c) else: raise ValueError('wrong arguments')
def _ex_route_unmap(state): command = TokenCommand('unmap') params = {'keys': None} # TODO [refactor] Some commands require certain arguments e.g "keys" is a # required argument for the unmap ex command. Currently the do_ex_command # (may have been refactored into another name), passes params to the ex # commands, and None is valid argument, but in the case of this command # it's a required argument, so rather than the ex command deal with the # invalid argument, it should be dealt with a) either here, or b) by the # command runner. m = state.match(r'\s*(?P<keys>.+?)\s*$') if m: params.update(m.groupdict()) command.params = params return None, [command, TokenEof()]