From 98923dbe9fd23d9a4e5659e470b5b3f446d36892 Mon Sep 17 00:00:00 2001 From: Deven Blake Date: Sun, 30 May 2021 17:16:34 -0400 Subject: [PATCH] divide labor --- it/buffer.py | 65 +++++++++++++++++++++++++++++++++ it/it.py | 89 ++++++++++++++++----------------------------- it/parse_command.py | 65 +++++++++++++++++++++++++++++++++ 3 files changed, 161 insertions(+), 58 deletions(-) create mode 100755 it/buffer.py create mode 100755 it/parse_command.py diff --git a/it/buffer.py b/it/buffer.py new file mode 100755 index 0000000..8a6a4d2 --- /dev/null +++ b/it/buffer.py @@ -0,0 +1,65 @@ +#!/usr/bin/env python3 +import importlib +import sys +from parse_command import parse_command + +class Buffer: # all the information about the current file + def carat(self): + return self.index + def dollar(self): + return self.length() - 1 + self.index + + # Rather than get the content as it's presented in the buffer object + # (as one big string), get it as a list. + def content_list(self): + return self.split(self.delimiter) + + # Build a string with the same format as the buffer.content and set the + # buffer.content to that string, from the kind of list output by + # buffer.content_list(). + # buffer.content_set_list(buffer.content_list()) is an expensive nop. + def content_set_list(self, content_as_list): + content = "" + for line in content_as_list: + content += line + self.delimiter + self.content = content + return None + + # this is really bad because any module can call import_module_ just as + # easily as any other. so malicious modules that, say, take 'q' and + # make it upload a file to some external server before exiting would be + # super easy to make. + # the solution I see is OS-level permissions but this needs to be + # talked about like all the time if this tool gets popular + # [why would it?] lest some fool runs a zelda.sh script that changes + # ~/src/it/w.py and doesn't realize in time + def import_module_(self, name): + try: + self.modules[name] = importlib.import_module(name) + except (ModuleNotFoundError, TypeError) as err: + print(err) + return False + else: + return True + + def length(self): + return self.content.count(self.delimiter) + + def __init__(self): + self.content = '' # content of the file + self.delimiter = '\n' # line delimiter + self.filename = "" # name of where we'll save the file + self.index = 0 # indexing of dot + self.dot = self.index - 1 # invalid position to start + self.modules = {} + self.saved = 1 # bool that says whether or not we have saved the file + +def main(buffer, command): + if len(command) == 1: + command = command + list(vars(buffer)) + for attrib in command[1:]: + if attrib in list(vars(buffer)): + print("%s:\t%s" % (attrib, vars(buffer)[attrib])) + else: + print("No attribute: %s" % attrib) + return buffer diff --git a/it/it.py b/it/it.py index 6521aa0..50ff947 100755 --- a/it/it.py +++ b/it/it.py @@ -1,70 +1,43 @@ #!/usr/bin/env python3 -# it, a shITtier version of ed import importlib import sys +from buffer import Buffer +from parse_command import parse_command -def parsecommand(command): - casesensitive = True - escapes = {"\\"} - quotes = {"'", '"'} - spaces = {" ", "\t"} +def get_command(): + try: + return parse_command(input()) + except KeyboardInterrupt: # bastard behavior from ed + pass + except EOFError: + return 0 - command = command.strip() +def main(buffer, supplied_command): + if supplied_command != [] and len(supplied_command) > 1: + command = supplied_command[1:] + else: + command = get_command() - inQuotes = 0 - word = "" - parsed_command = [] - - # copied from other project. mystery code. works though - for i in range(len(command)): - if ((command[i] in quotes) - and inQuotes == 0 - and (i == 0 - or (i > 0 and not(command[i-1] in escapes)))): - inQuotes = command[i] - - elif (command[i] == inQuotes - and (i > 0 and not(command[i-1] in escapes))): - inQuotes = 0 - - elif (command[i] in spaces and inQuotes == 0 - and (i > 0 and not(command[i-1] in escapes))): - parsed_command += [word] - word = "" - - elif (command[i] != "\\" or (i == len(command) - 1) - or not(command[i+1] in spaces + quotes)): - word += command[i] - - parsed_command += [word] - return [] if parsed_command == [''] else parsed_command - -class Buffer: # all the information about the current file - def __init__(self): - self.content = [] # content of the file - self.dot = 0 # where we are in the file - self.filename = "" # name of where we'll save the file - self.saved = 1 # bool that says whether or not we have saved the file - -def main(): - buffer = Buffer() - modules = {} while True: - try: - command = parsecommand(input()) - except KeyboardInterrupt: # bastard behavior from ed - pass - except EOFError: + # EOFError in get_command(); ^D + if command == 0: break + if command == []: continue - try: - modules[command[0]] = importlib.import_module(command[0]) - except ModuleNotFoundError as err: - print(err) - else: - buffer = modules[command[0]].main(buffer, command) - return 0 + + if command[0] in buffer.modules.keys() or buffer.import_module_(command[0]): + buffer = buffer.modules[command[0]].main(buffer, command) + if type(buffer) is int: + break + + command = get_command() + + return buffer if __name__ == "__main__": - sys.exit(main()) + buffer = main(Buffer(), []) + if type(buffer) is int: + sys.exit(buffer) + else: + sys.exit(0) diff --git a/it/parse_command.py b/it/parse_command.py new file mode 100755 index 0000000..151e06d --- /dev/null +++ b/it/parse_command.py @@ -0,0 +1,65 @@ +#!/usr/bin/env python3 +import sys + +def parse_command(command): + casesensitive = True + escapes = {"\\"} + quotes = {"'", '"'} + spaces = {" ", "\t"} + + command = command.strip() + + in_quotes = 0 + word = "" + parsed_command = [] + + for i in range(len(command)): + # if this char is a quote char + # , we're in quotes + if ((command[i] in quotes) + and in_quotes == 0 + and (i == 0 + or (i > 0 and not(command[i-1] in escapes)))): + in_quotes = command[i] + + # if this char matches the char by which we're in quotes + # , we're not in quotes + elif (command[i] == in_quotes + and (i > 0 and not(command[i-1] in escapes))): + in_quotes = 0 + + # if this char is an arg delimiter + # and we're not in quotes + # and the last char isn't an escape + # , this word is an argument + elif (command[i] in spaces and in_quotes == 0 + and (i > 0 and not(command[i-1] in escapes))): + parsed_command += [word] + word = "" + + elif (not(command[i] in escapes) or (i == len(command) - 1) + or not(command[i+1] in spaces + quotes)): + word += command[i] + + parsed_command += [word] + return [] if parsed_command == [''] else parsed_command + +def main(*args): + while True: + try: + command = input() + except: + break + + if command == ".": + break + + command = parse_command(command) + + for i in range(len(command)): + print("\t%d:\t%s" % (i, command[i])) + + return 0 if len(args) != 2 else args[0] + +if __name__ == "__main__": + sys.exit(main())