def copy(editorObj): """ Copy aLinkedList and return a pointer to it """ currentLine = topLine = None walk = editorObj.lineLinkedList.start newList = LineLinkedList([]) lastNode = None while walk != None: node = LineNode(walk.value, None) if node.value == editorObj.topLine.value: topLine = node if node.value == editorObj.currentLine.value: currentLine = node if newList.start is None: newList.start = node node.lastNode = lastNode if lastNode != None: lastNode.nextNode = node lastNode = node newList.length += 1 walk = walk.nextNode if walk is None: break newList.end = lastNode if currentLine is None: currentLine = newList.start if topLine is None: topLine = newList.start return (newList, currentLine, topLine)
def loadFile(fileName): """ Loads all lines from the fileName in cwd Returns a LineLinkedList object If file fileName is empty, returns a LineLinkedList object with just one newline node """ with open(fileName, 'r') as f: fileLines = f.readlines() if fileLines: # making the linked list return LineLinkedList(fileLines) return LineLinkedList(['\n'])
def drawTerminalChatter(editorObj, cmd): """ Output whatever process sends to stdout in real time """ process = subprocess.Popen(cmd.split(), stdout=subprocess.PIPE) # clean the screen to prepare for output editorObj.editorscr.clear() # save these for later tempLinkedList = editorObj.lineLinkedList tempPointer = editorObj.topLine outputStr = '' while True: out = process.stdout.read(1).decode() if out == '' and process.poll() is not None: break if out != '': outputStr += out consoleChatterLines = LineLinkedList(outputStr.split('\n')) # set these so you can use drawLines editorObj.lineLinkedList = consoleChatterLines editorObj.topLine = editorObj.lineLinkedList.start # draw the output drawLines(editorObj, editorObj.editorscr, editorObj.topLine) editorObj.drawLineNumbers() editorObj.editorscr.refresh() # kill the pipe process.stdout.close() # now wait for the user to send some ready confirmation # that he's seen the output and he's good to go editorObj.statusscr.clear() editorObj.statusscr.addstr('Please press any key to proceed.') editorObj.statusscr.refresh() editorObj.editorscr.getch() # wait for confirmation # set the old lines and topline back editorObj.lineLinkedList = tempLinkedList editorObj.topLine = tempPointer drawLines(editorObj, editorObj.editorscr, editorObj.topLine) editorObj.drawLineNumbers() editorObj.editorscr.refresh()
def changeColorsUI(editorObj, backgroundKey): raise NotImplementedError """ backgroundKey is the key for the background color currently being used in the editor Opens up a curses interface for the user to pick the colors for each type of token as defined in syntaxHighlighting.py by displaying all the possible colors and telling the user what the user is picking it for. The user then gets a sample display of some file with the syntax applied, and is prompted with a yes/no to save the syntax with some specified filename and load it. """ editorObj.editorscr.clear() editorObj.lineLinkedList = LineLinkedList(['A']) editorObj.topLine = editorObj.currentLine = editorObj.lineLinkedList.start editorUtil.insertLine(editorObj, editorObj.currentLine) editorObj.drawLines(editorObj.editorscr, editorObj.topLine) # don't have to save anything for later since the only time where # we call this, we are in options from before so we'll retrieve everything # on the way out of this function ref = 50 for i in range(0, 1000, 200): for j in range(0, 1000, 200): for k in range(0, 1000, 200): curses.init_color(ref, i, j, k) curses.init_pair(ref, ref, backgroundKey) #editorObj.editorscr.addstr('A', curses.color_pair(ref)) editorObj.currentLine.value = ( editorObj.currentLine.value[:-1] + 'A' + '\n') editorObj.currentLine.colors.append(ref) ref += 1 editorObj.drawLines(editorObj.editorscr, editorObj.topLine) # getcmd for the name editorObj.editorscr.getch() return 'default.json'
def displayThemes(editorObj, dimDir): os.chdir(dimDir+'/themes') editorObj.lineLinkedList = LineLinkedList(os.listdir()) editorObj.currentLine = editorObj.topLine = editorObj.lineLinkedList.start editorObj.drawLines(editorObj.editorscr, editorObj.topLine) editorObj.drawLineNumbers() editorObj.editorscr.refresh() while True: c = chr(editorObj.editorscr.getch()) if c == 'j': editorMovement.moveDown(editorObj) if c == 'k': editorMovement.moveUp(editorObj) if c == chr(10): # enter return editorObj.currentLine.value if c == chr(27): # escape break editorObj.drawLineNumbers() editorObj.editorscr.refresh()
def __init__(self): """ Inits screens, curses stuff, colors, attributes, etc """ # set up curses stuff initScreens(self, WindowConstants) cursesUtil.birth() # init all the colors self.dimDir = os.getcwd() self.colorMap = initColors(self.dimDir, 'default.json') self.stdscr.attrset(curses.color_pair(self.colorMap['TEXT'])) self.stdscr.bkgd(' ', curses.color_pair(self.colorMap['TEXT'])) self.editorscr.bkgd(' ', curses.color_pair(self.colorMap['TEXT'])) self.filenavscr.bkgd(' ', curses.color_pair(self.colorMap['TEXT'])) self.filenavscr.refresh() self.linenumscr.attrset( curses.color_pair(self.colorMap['LINE_NUMBER']) ) self.linenumscr.bkgd( ' ', curses.color_pair(self.colorMap['LINE_NUMBER']) ) self.cmdlinescr.attrset( curses.color_pair(self.colorMap['TEXT']) ) self.cmdlinescr.bkgd( ' ', curses.color_pair(self.colorMap['TEXT']) ) self.setState(State.NORMAL) self.runFileNavigation(breakEarly=True) self.matchBuffer = [] # grabbing the lines from the file self.fileName = '' self.lineLinkedList = LineLinkedList(['\n']) (maxY, maxX) = self.stdscr.getmaxyx() # setting ui up self.editorscr.move(0, 0) self.currentLineCount = 0 # set up something bright for statusscr self.statusscr.bkgd(' ', curses.color_pair(self.colorMap['STATUS'])) self.statusscr.attrset(curses.color_pair(self.colorMap['STATUS'])) self.statusscr.refresh() # keep 2 pointers; 1 for top line node, 1 for current line node self.topLine = self.currentLine = self.lineLinkedList.start self.topLineCount = 1 # number to draw for topLine self.currentLineIndex = 0 # set up undo redo stack self.undoRedoStack = UndoRedoStack() # draw everything for first iteration syntaxHighlighting.setColors(self, self.colorMap) drawUtil.drawLineNumbers(self) drawUtil.drawLines(self, self.editorscr, self.topLine) self.setState(State.NORMAL) self.commandRepeats = '' # set up punctuation dictionary for fast checking of punctuation self.punctuationChars = {} for c in string.punctuation: self.punctuationChars[c] = True # set up bk tree for spellcheck self.spellCheckLine = 1000 spellCheckStream = open('dataStructures/words.txt') self.spellCheckWords = [] for line in spellCheckStream: self.spellCheckWords.append(line[:-1]) # take off newline character self.spellCheck = bk_tree()
class MainScr: def __init__(self): """ Inits screens, curses stuff, colors, attributes, etc """ # set up curses stuff initScreens(self, WindowConstants) cursesUtil.birth() # init all the colors self.dimDir = os.getcwd() self.colorMap = initColors(self.dimDir, 'default.json') self.stdscr.attrset(curses.color_pair(self.colorMap['TEXT'])) self.stdscr.bkgd(' ', curses.color_pair(self.colorMap['TEXT'])) self.editorscr.bkgd(' ', curses.color_pair(self.colorMap['TEXT'])) self.filenavscr.bkgd(' ', curses.color_pair(self.colorMap['TEXT'])) self.filenavscr.refresh() self.linenumscr.attrset( curses.color_pair(self.colorMap['LINE_NUMBER']) ) self.linenumscr.bkgd( ' ', curses.color_pair(self.colorMap['LINE_NUMBER']) ) self.cmdlinescr.attrset( curses.color_pair(self.colorMap['TEXT']) ) self.cmdlinescr.bkgd( ' ', curses.color_pair(self.colorMap['TEXT']) ) self.setState(State.NORMAL) self.runFileNavigation(breakEarly=True) self.matchBuffer = [] # grabbing the lines from the file self.fileName = '' self.lineLinkedList = LineLinkedList(['\n']) (maxY, maxX) = self.stdscr.getmaxyx() # setting ui up self.editorscr.move(0, 0) self.currentLineCount = 0 # set up something bright for statusscr self.statusscr.bkgd(' ', curses.color_pair(self.colorMap['STATUS'])) self.statusscr.attrset(curses.color_pair(self.colorMap['STATUS'])) self.statusscr.refresh() # keep 2 pointers; 1 for top line node, 1 for current line node self.topLine = self.currentLine = self.lineLinkedList.start self.topLineCount = 1 # number to draw for topLine self.currentLineIndex = 0 # set up undo redo stack self.undoRedoStack = UndoRedoStack() # draw everything for first iteration syntaxHighlighting.setColors(self, self.colorMap) drawUtil.drawLineNumbers(self) drawUtil.drawLines(self, self.editorscr, self.topLine) self.setState(State.NORMAL) self.commandRepeats = '' # set up punctuation dictionary for fast checking of punctuation self.punctuationChars = {} for c in string.punctuation: self.punctuationChars[c] = True # set up bk tree for spellcheck self.spellCheckLine = 1000 spellCheckStream = open('dataStructures/words.txt') self.spellCheckWords = [] for line in spellCheckStream: self.spellCheckWords.append(line[:-1]) # take off newline character self.spellCheck = bk_tree() def __exit__(self, exc_type, exc_value, traceback): """ Prepares curses and filesystem for exit """ curses.echo() curses.nocbreak() self.stdscr.keypad(False) curses.endwin() def setState(self, stateToSet): try: if self.state is State.NORMAL and stateToSet is State.APPEND: self.appendLineNode = self.currentLine except AttributeError: self.state = stateToSet if self.state is State.APPEND: if len(self.appendLineNode.value) > 1: if self.appendLineNode.value[-2] == ' ': self.appendLineNode.value = self.appendLineNode.value[:-2]+'\n' self.state = stateToSet def getStateStr(self): if self.state is State.NORMAL: return 'NORMAL' elif self.state is State.INSERT: return 'INSERT' elif self.state is State.VISUAL: return 'VISUAL' elif self.state is State.COMMAND_LINE: return 'CMD_LINE' elif self.state is State.FILE_NAVIGATION: return 'FILE_NAV' elif self.state is State.APPEND: return 'APPEND' else: return 'UNKNOWN_STATE' def setUpFileHighlighting(self): directory = self.dirs.start while directory is not None: color = self.colorMap['FILE'] if os.path.isdir(directory.value): color = self.colorMap['FOLDER'] for i in range(len(directory.value)): directory.colors[i] = color directory = directory.nextNode def drawAndRefreshFileNavigation(self): self.filenavscr.clear() drawUtil.drawLines(self, self.filenavscr, self.topDir) def runFileNavigation(self, breakEarly=False): self.dirs = LineLinkedList(editorUtil.getDirs()) self.topDir = self.currentDir = self.dirs.start self.setUpFileHighlighting() self.drawAndRefreshFileNavigation() self.filenavscr.move(0, 0) y = 0 while True: if breakEarly: self.setState(State.NORMAL) break c = chr(self.filenavscr.getch()) if c == '`': self.setState(State.NORMAL) break if c == 'k': y = fileNavMovement.moveUp(self, y) elif c == 'j': y = fileNavMovement.moveDown(self, y) elif c == '\n': try: os.chdir(self.currentDir.value) self.dirs = LineLinkedList(editorUtil.getDirs()) self.currentDir = self.topDir = self.dirs.start self.setUpFileHighlighting() except NotADirectoryError: # reload file and prep self.fileName = self.currentDir.value self.lineLinkedList = fileUtil.loadFile(self.fileName) self.topLine = self.currentLine = self.lineLinkedList.start self.currentLineIndex = 0 syntaxHighlighting.setColors(self, self.colorMap) drawUtil.drawLines(self, self.editorscr, self.topLine) drawUtil.drawLineNumbers(self) # reset file dir self.currentDir = self.topDir = self.dirs.start y = 0 elif c == '?': searchSubStr = editorUtil.getCmd(self, altDisplayChar='?')[1:] # want to take off the '?' character from the start searchSubStr = searchSubStr.lstrip() if searchSubStr == chr(27): # escape character continue else: wantedDir = dirBinSearch(self.dirs, self.dirs.toList(), searchSubStr, self.currentDir) if wantedDir is None: # we couldn't find anything continue y = 0 self.currentDir = self.topDir = self.dirs.start while self.currentDir != wantedDir: y = fileNavMovement.moveDown(self, y) self.drawAndRefreshFileNavigation() self.filenavscr.move(y, 0) def run(self): """ Main loop of the state machine """ if self.spellCheckLine < 9998: self.spellCheckLine += 1 self.spellCheck.add(self.spellCheckWords[self.spellCheckLine]) while True: # set everything up for the run (y, x) = self.editorscr.getyx() # get cursor position relative to top left repeats = 1 if self.commandRepeats == '' else int(self.commandRepeats) if self.state == State.NORMAL: c = chr(self.editorscr.getch()) # get a key # movement # remember top left is (0, 0) if c == 'j': # down editorMovement.moveDown(self) elif c == 'k': # up editorMovement.moveUp(self) elif c == 'h': # left editorMovement.moveLeft(self) elif c == 'l': # right editorMovement.moveRight(self) elif c == '$': # eol editorUtil.moveToEndOfLine(self) elif c == '0': # beginning if self.commandRepeats != '': self.commandRepeats += '0' continue editorUtil.moveToBeginningOfLine(self) elif c == 'w': editorJumps.jump_forward_one_word(self, repeats, x) elif c == 'e': editorJumps.jump_one_word_and_whitespace(self, repeats, x) elif c == 'b': editorJumps.jump_backward_one_word(self, repeats, x) elif c == 'g': editorJumps.jump_to_line(self, repeats) elif c == '/': # search function pattern_to_find = editorUtil.getCmd(self, altDisplayChar='/') self.matchBuffer = (editorUtil.find_pattern_in_syntax( self, pattern_to_find)) self.currentLine = self.topLine = self.lineLinkedList.start # go to first match if self.matchBuffer: (lineNumber, lineIndex) = self.matchBuffer[0] editorUtil.move_to_node_and_index(self, lineNumber, lineIndex) temp = self.matchBuffer[0] del self.matchBuffer[0] self.matchBuffer.append(temp) elif c == 'n': # jump to the next thing in the match buffer if self.matchBuffer != []: (lineNumber, lineIndex) = self.matchBuffer[0] editorUtil.move_to_node_and_index(self, lineNumber, lineIndex) temp = self.matchBuffer[0] del self.matchBuffer[0] self.matchBuffer.append(temp) # move to different states elif c == 'd': if self.deleteMode is True: # equivalent to dd command self.undoRedoStack.pushOntoUndo(self) if self.currentLine.nextNode is None: # last node temp = self.currentLine.lastNode editorUtil.deleteLine(self, self.currentLine, trueDelete=True) self.currentLine = temp else: self.currentLine = editorUtil.deleteLine(self, self.currentLine, trueDelete=True) self.deleteMode = False else: self.deleteMode = True continue elif c == 'u': # undo self.undoRedoStack.undo(self) elif c == chr(18): # ctrl + r self.undoRedoStack.redo(self) elif c in [str(x) for x in range(10)]: self.commandRepeats += str(c) continue elif c == 'i': self.undoRedoStack.pushOntoUndo(self) # put currentLine and its value onto undo stack self.setState(State.INSERT) elif c == 'a': self.undoRedoStack.pushOntoUndo(self) # put currentLine and its value onto undo stack if editorUtil.getCurrentChar(self) == '\n': self.currentLine.value = self.currentLine.value[:self.currentLineIndex+1] + ' \n' self.currentLine.colors.append(0) if editorUtil.getNextChar(self) == '\n': self.currentLine.value = self.currentLine.value[:self.currentLineIndex+1] + ' \n' self.currentLine.colors.append(0) # insert a space editorMovement.moveRight(self) self.setState(State.APPEND) elif c == 'A': editorUtil.moveToEndOfLine(self) self.undoRedoStack.pushOntoUndo(self) if editorUtil.getNextChar(self) == '\n': self.currentLine.value = self.currentLine.value[:self.currentLineIndex+1] + ' \n' self.currentLine.colors.append(0) # insert a space editorMovement.moveRight(self) self.setState(State.APPEND) elif c == 'x': # delete character editorUtil.deleteCharacter(self, self.currentLine, self.currentLineIndex) elif c == 'v': self.setState(State.VISUAL) elif c == ':': self.setState(State.COMMAND_LINE) elif c == '`': self.setState(State.FILE_NAVIGATION) elif c == '.': self.setState(State.OPTIONS) self.deleteMode = False self.commandRepeats = '' drawUtil.drawLines(self, self.editorscr, self.topLine) drawUtil.drawLineNumbers(self) if self.state == State.INSERT or self.state == State.APPEND: c = chr(self.editorscr.getch()) if ord(c) == 27: # escape editorMovement.moveLeft(self) self.setState(State.NORMAL) elif ord(c) == 127: # backspace self.currentLine.value = (self.currentLine.value[:max(self. currentLineIndex-1, 0)]+self.currentLine.value[max(self .currentLineIndex, 0):]) self.currentLineIndex -= 1 self.colors = self.currentLine.colors[:-1] if self.currentLineIndex == -1: # delete the line self.currentLine = editorUtil.deleteLine(self, self.currentLine) elif ord(c) == 10: # enter if self.editorscr.getyx()[0] + 1 > self.editorscr.getmaxyx()[0] -2: self.topLine = self.topLine.nextNode self.currentLine = editorUtil.insertLine(self, self.currentLine) editorUtil.moveToBeginningOfLine(self) # get the spacing from the line above i = 0 lastLineValue = self.currentLine.lastNode.value while True: if lastLineValue[i] == ' ' or lastLineValue[i] == '\t': self.currentLine.value = (self.currentLine.value[:-1]+ ('\t' if lastLineValue[i] == '\t' else ' ')+'\n') self.currentLineIndex += 1 self.currentLine.colors.append(0) i += 1 else: break else: # any other character #editorUtil.insert_character(self.currentLine, self.currentLineIndex, c) self.currentLine.value = (self.currentLine.value[:self.currentLineIndex] + c + self.currentLine.value[self.currentLineIndex:]) self.currentLineIndex += 1 self.currentLine.colors.append(0) elif self.state == State.VISUAL: cursesUtil.kill(self) raise NotImplementedError elif self.state == State.COMMAND_LINE: cmd_string = editorUtil.getCmd(self) if cmd_string == chr(27): # escape character self.setState(State.NORMAL) continue cmd_list = cmd_string.strip(' \t\n\r') # tokenize based on '|' cmds = cmd_list.split('|') for cmd in cmds: for cmdChar in cmd: if cmdChar == 'w': args = cmd.split() # what if the fileName is ''? if self.fileName is '': if len(args) - 1 > 0: self.fileName = args[1] fileUtil.saveFile(self) self.drawAndRefreshFileNavigation() # disp new file if one is made else: self.statusscr.clear() self.statusscr.addstr('Error; No file name') self.statusscr.refresh() else: fileUtil.saveFile(self) if cmdChar == 'q': cursesUtil.kill(self) sys.exit(0) if cmdChar == '!': # clear the screens to prep self.stdscr.clear() self.editorscr.clear() self.linenumscr.clear() # kill the process to give stdin pipe back to terminal cursesUtil.kill(self) if cmd[0] == ':': cmd = cmd[1:] if cmd[0] == '!': cmd = cmd[1:] cursesUtil.kill(self) drawUtil.drawTerminalChatter(self, cmd) # bring what we killed back to life cursesUtil.birth() # set state to normal upon exit self.setState(State.NORMAL) elif self.state == State.FILE_NAVIGATION: self.runFileNavigation() elif self.state == State.OPTIONS: self.editorscr.clear() # save all of the pointers for later tempLinkedList = self.lineLinkedList tempCurrentLine = self.currentLine tempTopLine = self.topLine optionsText = LineLinkedList(['Change Colors']) self.lineLinkedList = optionsText self.topLine = self.currentLine = self.lineLinkedList.start drawUtil.drawLineNumbers(self) drawUtil.drawLines(self, self.editorscr, self.topLine) self.editorscr.refresh() self.linenumscr.refresh() self.editorscr.move(0,0) while True: c = chr(self.editorscr.getch()) if c == chr(27): # escape self.lineLinkedList = tempLinkedList self.topLine = tempTopLine self.currentLine = tempCurrentLine self.state = State.NORMAL break elif c == chr(10): if self.currentLine.value is 'Change Colors': themeFileName = changeColorsUtil.displayThemes( self, self.dimDir) # need dimDir so we know the path to themes self.colorMap = initColors(self.dimDir, themeFileName) self.state = State.NORMAL break elif c == 'j': editorMovement.moveDown(self) elif c == 'k': editorMovement.moveUp(self) # set everything back to the way it was on the way out self.lineLinkedList = tempLinkedList self.currentLine = tempCurrentLine self.topLine = tempTopLine # draw everything again syntaxHighlighting.setColors(self, self.colorMap) drawUtil.drawStatus(self) # draw the status bar text on status bar drawUtil.drawLines(self, self.editorscr, self.topLine) drawUtil.drawLineNumbers(self)
def run(self): """ Main loop of the state machine """ if self.spellCheckLine < 9998: self.spellCheckLine += 1 self.spellCheck.add(self.spellCheckWords[self.spellCheckLine]) while True: # set everything up for the run (y, x) = self.editorscr.getyx() # get cursor position relative to top left repeats = 1 if self.commandRepeats == '' else int(self.commandRepeats) if self.state == State.NORMAL: c = chr(self.editorscr.getch()) # get a key # movement # remember top left is (0, 0) if c == 'j': # down editorMovement.moveDown(self) elif c == 'k': # up editorMovement.moveUp(self) elif c == 'h': # left editorMovement.moveLeft(self) elif c == 'l': # right editorMovement.moveRight(self) elif c == '$': # eol editorUtil.moveToEndOfLine(self) elif c == '0': # beginning if self.commandRepeats != '': self.commandRepeats += '0' continue editorUtil.moveToBeginningOfLine(self) elif c == 'w': editorJumps.jump_forward_one_word(self, repeats, x) elif c == 'e': editorJumps.jump_one_word_and_whitespace(self, repeats, x) elif c == 'b': editorJumps.jump_backward_one_word(self, repeats, x) elif c == 'g': editorJumps.jump_to_line(self, repeats) elif c == '/': # search function pattern_to_find = editorUtil.getCmd(self, altDisplayChar='/') self.matchBuffer = (editorUtil.find_pattern_in_syntax( self, pattern_to_find)) self.currentLine = self.topLine = self.lineLinkedList.start # go to first match if self.matchBuffer: (lineNumber, lineIndex) = self.matchBuffer[0] editorUtil.move_to_node_and_index(self, lineNumber, lineIndex) temp = self.matchBuffer[0] del self.matchBuffer[0] self.matchBuffer.append(temp) elif c == 'n': # jump to the next thing in the match buffer if self.matchBuffer != []: (lineNumber, lineIndex) = self.matchBuffer[0] editorUtil.move_to_node_and_index(self, lineNumber, lineIndex) temp = self.matchBuffer[0] del self.matchBuffer[0] self.matchBuffer.append(temp) # move to different states elif c == 'd': if self.deleteMode is True: # equivalent to dd command self.undoRedoStack.pushOntoUndo(self) if self.currentLine.nextNode is None: # last node temp = self.currentLine.lastNode editorUtil.deleteLine(self, self.currentLine, trueDelete=True) self.currentLine = temp else: self.currentLine = editorUtil.deleteLine(self, self.currentLine, trueDelete=True) self.deleteMode = False else: self.deleteMode = True continue elif c == 'u': # undo self.undoRedoStack.undo(self) elif c == chr(18): # ctrl + r self.undoRedoStack.redo(self) elif c in [str(x) for x in range(10)]: self.commandRepeats += str(c) continue elif c == 'i': self.undoRedoStack.pushOntoUndo(self) # put currentLine and its value onto undo stack self.setState(State.INSERT) elif c == 'a': self.undoRedoStack.pushOntoUndo(self) # put currentLine and its value onto undo stack if editorUtil.getCurrentChar(self) == '\n': self.currentLine.value = self.currentLine.value[:self.currentLineIndex+1] + ' \n' self.currentLine.colors.append(0) if editorUtil.getNextChar(self) == '\n': self.currentLine.value = self.currentLine.value[:self.currentLineIndex+1] + ' \n' self.currentLine.colors.append(0) # insert a space editorMovement.moveRight(self) self.setState(State.APPEND) elif c == 'A': editorUtil.moveToEndOfLine(self) self.undoRedoStack.pushOntoUndo(self) if editorUtil.getNextChar(self) == '\n': self.currentLine.value = self.currentLine.value[:self.currentLineIndex+1] + ' \n' self.currentLine.colors.append(0) # insert a space editorMovement.moveRight(self) self.setState(State.APPEND) elif c == 'x': # delete character editorUtil.deleteCharacter(self, self.currentLine, self.currentLineIndex) elif c == 'v': self.setState(State.VISUAL) elif c == ':': self.setState(State.COMMAND_LINE) elif c == '`': self.setState(State.FILE_NAVIGATION) elif c == '.': self.setState(State.OPTIONS) self.deleteMode = False self.commandRepeats = '' drawUtil.drawLines(self, self.editorscr, self.topLine) drawUtil.drawLineNumbers(self) if self.state == State.INSERT or self.state == State.APPEND: c = chr(self.editorscr.getch()) if ord(c) == 27: # escape editorMovement.moveLeft(self) self.setState(State.NORMAL) elif ord(c) == 127: # backspace self.currentLine.value = (self.currentLine.value[:max(self. currentLineIndex-1, 0)]+self.currentLine.value[max(self .currentLineIndex, 0):]) self.currentLineIndex -= 1 self.colors = self.currentLine.colors[:-1] if self.currentLineIndex == -1: # delete the line self.currentLine = editorUtil.deleteLine(self, self.currentLine) elif ord(c) == 10: # enter if self.editorscr.getyx()[0] + 1 > self.editorscr.getmaxyx()[0] -2: self.topLine = self.topLine.nextNode self.currentLine = editorUtil.insertLine(self, self.currentLine) editorUtil.moveToBeginningOfLine(self) # get the spacing from the line above i = 0 lastLineValue = self.currentLine.lastNode.value while True: if lastLineValue[i] == ' ' or lastLineValue[i] == '\t': self.currentLine.value = (self.currentLine.value[:-1]+ ('\t' if lastLineValue[i] == '\t' else ' ')+'\n') self.currentLineIndex += 1 self.currentLine.colors.append(0) i += 1 else: break else: # any other character #editorUtil.insert_character(self.currentLine, self.currentLineIndex, c) self.currentLine.value = (self.currentLine.value[:self.currentLineIndex] + c + self.currentLine.value[self.currentLineIndex:]) self.currentLineIndex += 1 self.currentLine.colors.append(0) elif self.state == State.VISUAL: cursesUtil.kill(self) raise NotImplementedError elif self.state == State.COMMAND_LINE: cmd_string = editorUtil.getCmd(self) if cmd_string == chr(27): # escape character self.setState(State.NORMAL) continue cmd_list = cmd_string.strip(' \t\n\r') # tokenize based on '|' cmds = cmd_list.split('|') for cmd in cmds: for cmdChar in cmd: if cmdChar == 'w': args = cmd.split() # what if the fileName is ''? if self.fileName is '': if len(args) - 1 > 0: self.fileName = args[1] fileUtil.saveFile(self) self.drawAndRefreshFileNavigation() # disp new file if one is made else: self.statusscr.clear() self.statusscr.addstr('Error; No file name') self.statusscr.refresh() else: fileUtil.saveFile(self) if cmdChar == 'q': cursesUtil.kill(self) sys.exit(0) if cmdChar == '!': # clear the screens to prep self.stdscr.clear() self.editorscr.clear() self.linenumscr.clear() # kill the process to give stdin pipe back to terminal cursesUtil.kill(self) if cmd[0] == ':': cmd = cmd[1:] if cmd[0] == '!': cmd = cmd[1:] cursesUtil.kill(self) drawUtil.drawTerminalChatter(self, cmd) # bring what we killed back to life cursesUtil.birth() # set state to normal upon exit self.setState(State.NORMAL) elif self.state == State.FILE_NAVIGATION: self.runFileNavigation() elif self.state == State.OPTIONS: self.editorscr.clear() # save all of the pointers for later tempLinkedList = self.lineLinkedList tempCurrentLine = self.currentLine tempTopLine = self.topLine optionsText = LineLinkedList(['Change Colors']) self.lineLinkedList = optionsText self.topLine = self.currentLine = self.lineLinkedList.start drawUtil.drawLineNumbers(self) drawUtil.drawLines(self, self.editorscr, self.topLine) self.editorscr.refresh() self.linenumscr.refresh() self.editorscr.move(0,0) while True: c = chr(self.editorscr.getch()) if c == chr(27): # escape self.lineLinkedList = tempLinkedList self.topLine = tempTopLine self.currentLine = tempCurrentLine self.state = State.NORMAL break elif c == chr(10): if self.currentLine.value is 'Change Colors': themeFileName = changeColorsUtil.displayThemes( self, self.dimDir) # need dimDir so we know the path to themes self.colorMap = initColors(self.dimDir, themeFileName) self.state = State.NORMAL break elif c == 'j': editorMovement.moveDown(self) elif c == 'k': editorMovement.moveUp(self) # set everything back to the way it was on the way out self.lineLinkedList = tempLinkedList self.currentLine = tempCurrentLine self.topLine = tempTopLine # draw everything again syntaxHighlighting.setColors(self, self.colorMap) drawUtil.drawStatus(self) # draw the status bar text on status bar drawUtil.drawLines(self, self.editorscr, self.topLine) drawUtil.drawLineNumbers(self)
def runFileNavigation(self, breakEarly=False): self.dirs = LineLinkedList(editorUtil.getDirs()) self.topDir = self.currentDir = self.dirs.start self.setUpFileHighlighting() self.drawAndRefreshFileNavigation() self.filenavscr.move(0, 0) y = 0 while True: if breakEarly: self.setState(State.NORMAL) break c = chr(self.filenavscr.getch()) if c == '`': self.setState(State.NORMAL) break if c == 'k': y = fileNavMovement.moveUp(self, y) elif c == 'j': y = fileNavMovement.moveDown(self, y) elif c == '\n': try: os.chdir(self.currentDir.value) self.dirs = LineLinkedList(editorUtil.getDirs()) self.currentDir = self.topDir = self.dirs.start self.setUpFileHighlighting() except NotADirectoryError: # reload file and prep self.fileName = self.currentDir.value self.lineLinkedList = fileUtil.loadFile(self.fileName) self.topLine = self.currentLine = self.lineLinkedList.start self.currentLineIndex = 0 syntaxHighlighting.setColors(self, self.colorMap) drawUtil.drawLines(self, self.editorscr, self.topLine) drawUtil.drawLineNumbers(self) # reset file dir self.currentDir = self.topDir = self.dirs.start y = 0 elif c == '?': searchSubStr = editorUtil.getCmd(self, altDisplayChar='?')[1:] # want to take off the '?' character from the start searchSubStr = searchSubStr.lstrip() if searchSubStr == chr(27): # escape character continue else: wantedDir = dirBinSearch(self.dirs, self.dirs.toList(), searchSubStr, self.currentDir) if wantedDir is None: # we couldn't find anything continue y = 0 self.currentDir = self.topDir = self.dirs.start while self.currentDir != wantedDir: y = fileNavMovement.moveDown(self, y) self.drawAndRefreshFileNavigation() self.filenavscr.move(y, 0)