From 2004047f2b98ed9e78bd3413c9d7591f63024c61 Mon Sep 17 00:00:00 2001 From: Stuart Grieve Date: Mon, 21 Aug 2017 15:26:08 +0100 Subject: [PATCH 01/13] Document listener implemented so we can detect when newlines are added --- python/nammu/controller/AtfAreaController.py | 4 +++ python/nammu/view/AtfAreaView.py | 36 +++++++++++++++++++- 2 files changed, 39 insertions(+), 1 deletion(-) diff --git a/python/nammu/controller/AtfAreaController.py b/python/nammu/controller/AtfAreaController.py index 1e77bda9..0fd3fa4c 100644 --- a/python/nammu/controller/AtfAreaController.py +++ b/python/nammu/controller/AtfAreaController.py @@ -219,6 +219,10 @@ def pad_bottom_viewport_caret(self, bottom_left_char, text): return bottom_left_char + def update_error_lines_insert(self, caret_line, no_of_newlines): + print 'newlines', no_of_newlines + print 'caret_line', caret_line + def syntax_highlight(self, top_caret=None, bottom_caret=None): ''' Short hand for syntax highlighting. Takes the line bounds. diff --git a/python/nammu/view/AtfAreaView.py b/python/nammu/view/AtfAreaView.py index b684ac64..49be9bc7 100644 --- a/python/nammu/view/AtfAreaView.py +++ b/python/nammu/view/AtfAreaView.py @@ -24,7 +24,7 @@ from javax.swing.text import StyleContext, StyleConstants from javax.swing.text import SimpleAttributeSet from javax.swing.undo import UndoManager, CompoundEdit -from javax.swing.event import UndoableEditListener +from javax.swing.event import UndoableEditListener, DocumentListener from contextlib import contextmanager from .AtfEditArea import AtfEditArea @@ -78,6 +78,9 @@ def __init__(self, controller): # Also needed in secondary area: self.secondary_area.addKeyListener(AtfAreaKeyListener(self)) + # Add a document listener to track changes to files + self.edit_area.getDocument().addDocumentListener(atfAreaDocumentListener(self)) + def toggle_split(self, split_orientation=None): ''' Clear ATF edit area and repaint chosen layout (splitscreen/scrollpane). @@ -145,6 +148,37 @@ def get_viewport_carets(self): return top_ch, bottom_ch +class atfAreaDocumentListener(DocumentListener): + def __init__(self, areaview): + self.areaviewcontroller = areaview.controller + self.areaview = areaview + + def changedUpdate(self, e): + pass + + def insertUpdate(self, e): + text = self.areaviewcontroller.edit_area.getText() + length = e.getLength() + offset = e.getOffset() + + insert = text[offset:length + offset] + + if '\n' in insert: + no_of_newlines = insert.count('\n') + + # Get the line no of the caret postion + caret_line = self.areaviewcontroller.edit_area.get_line_num(offset) + + # Call our error line update method here, passing no_of_newlines + self.areaviewcontroller.update_error_lines_insert(caret_line, + no_of_newlines) + + def removeUpdate(self, e): + print 'remove' + print 'length', e.getLength() + print 'offset', e.getOffset() + + class atfAreaAdjustmentListener(AdjustmentListener): def __init__(self, areaview): self.areaviewcontroller = areaview.controller From 3f65732f6e0880ce6dde843ee758c08b7ab0196d Mon Sep 17 00:00:00 2001 From: Stuart Grieve Date: Tue, 22 Aug 2017 09:18:09 +0100 Subject: [PATCH 02/13] working error line update on insert --- python/nammu/controller/AtfAreaController.py | 26 ++++++++++++++++++-- 1 file changed, 24 insertions(+), 2 deletions(-) diff --git a/python/nammu/controller/AtfAreaController.py b/python/nammu/controller/AtfAreaController.py index 0fd3fa4c..54cc1213 100644 --- a/python/nammu/controller/AtfAreaController.py +++ b/python/nammu/controller/AtfAreaController.py @@ -220,8 +220,30 @@ def pad_bottom_viewport_caret(self, bottom_left_char, text): return bottom_left_char def update_error_lines_insert(self, caret_line, no_of_newlines): - print 'newlines', no_of_newlines - print 'caret_line', caret_line + + if no_of_newlines < 1: + return + + if self.validation_errors == {}: + return + + error_lines = self.validation_errors.keys() + + error_lines_int = [int(a) for a in error_lines] + + if caret_line < min(error_lines_int): + + tmp = {} + for q, err in enumerate(error_lines_int): + if err > caret_line: + error_lines_int[q] += no_of_newlines + + # rebuild self.controller.validation_errors.keys() + tmp[str(error_lines_int[q])] = self.validation_errors[str(err)] + + self.validation_errors = tmp + + top_l_char, bottom_l_char = self.view.get_viewport_carets() def syntax_highlight(self, top_caret=None, bottom_caret=None): ''' From 6e32fd5ee9d9c4acd540b8768d6d7f629f11fe82 Mon Sep 17 00:00:00 2001 From: Stuart Grieve Date: Tue, 22 Aug 2017 11:43:16 +0100 Subject: [PATCH 03/13] working error line updating for insert and remove, but not for cut text triggered from the menu. --- python/nammu/controller/AtfAreaController.py | 24 ++++++++++-- python/nammu/view/AtfAreaView.py | 40 ++++++++++++++++++-- 2 files changed, 56 insertions(+), 8 deletions(-) diff --git a/python/nammu/controller/AtfAreaController.py b/python/nammu/controller/AtfAreaController.py index 54cc1213..bc32d789 100644 --- a/python/nammu/controller/AtfAreaController.py +++ b/python/nammu/controller/AtfAreaController.py @@ -224,9 +224,6 @@ def update_error_lines_insert(self, caret_line, no_of_newlines): if no_of_newlines < 1: return - if self.validation_errors == {}: - return - error_lines = self.validation_errors.keys() error_lines_int = [int(a) for a in error_lines] @@ -243,7 +240,26 @@ def update_error_lines_insert(self, caret_line, no_of_newlines): self.validation_errors = tmp - top_l_char, bottom_l_char = self.view.get_viewport_carets() + def update_error_lines_remove(self, caret_line, no_of_removed_lines): + + if no_of_removed_lines < 1: + return + + error_lines = self.validation_errors.keys() + + error_lines_int = [int(a) for a in error_lines] + + if caret_line < min(error_lines_int): + + tmp = {} + for q, err in enumerate(error_lines_int): + if err > caret_line: + error_lines_int[q] -= no_of_removed_lines + + # rebuild self.controller.validation_errors.keys() + tmp[str(error_lines_int[q])] = self.validation_errors[str(err)] + + self.validation_errors = tmp def syntax_highlight(self, top_caret=None, bottom_caret=None): ''' diff --git a/python/nammu/view/AtfAreaView.py b/python/nammu/view/AtfAreaView.py index 49be9bc7..f601e204 100644 --- a/python/nammu/view/AtfAreaView.py +++ b/python/nammu/view/AtfAreaView.py @@ -81,6 +81,8 @@ def __init__(self, controller): # Add a document listener to track changes to files self.edit_area.getDocument().addDocumentListener(atfAreaDocumentListener(self)) + self.oldtext = '' + def toggle_split(self, split_orientation=None): ''' Clear ATF edit area and repaint chosen layout (splitscreen/scrollpane). @@ -157,6 +159,11 @@ def changedUpdate(self, e): pass def insertUpdate(self, e): + + # Only need to do this if we have error lines + if self.areaviewcontroller.validation_errors == {}: + return + text = self.areaviewcontroller.edit_area.getText() length = e.getLength() offset = e.getOffset() @@ -174,9 +181,27 @@ def insertUpdate(self, e): no_of_newlines) def removeUpdate(self, e): - print 'remove' - print 'length', e.getLength() - print 'offset', e.getOffset() + + # Only need to do this if we have error_lines + if self.areaviewcontroller.validation_errors == {}: + return + + text = self.areaview.oldtext + length = e.getLength() + offset = e.getOffset() + + removed = text[offset:length + offset] + + if '\n' in removed: + no_removed_lines = removed.count('\n') + + # Get the line no of the caret postion + caret_line = self.areaviewcontroller.edit_area.get_line_num(offset) + + # Call our error line update method here, passing no_removed_lines + self.areaviewcontroller.update_error_lines_remove(caret_line, + no_removed_lines) + class atfAreaAdjustmentListener(AdjustmentListener): @@ -216,7 +241,10 @@ def keyReleased(self, ke): # We have to implement these since the baseclass versions # raise non implemented errors when called by the event. def keyPressed(self, ke): - pass + # Set the oldtext parameter, which stores the contents of the textfield + # prior to the edits triggered by the keypress event. Needed for + # tracking error highlighting on removal of lines. + self.areaview.oldtext = self.areaviewcontroller.edit_area.getText() def keyTyped(self, ke): # It would be more natural to use this event. However @@ -260,6 +288,10 @@ def undoableEditHappened(self, event): edit = event.getEdit() edit_type = str(edit.getType()) + if edit_type == "REMOVE": + # This could be a place where we can get info about the removed text + pass + # If significant INSERT/REMOVE event happen, end and add current # edit compound to undo_manager and start a new one. if ((edit_type == "INSERT" or edit_type == "REMOVE") and From 9962294c0addddd714bba256d4f23011d5a26337 Mon Sep 17 00:00:00 2001 From: Stuart Grieve Date: Tue, 22 Aug 2017 11:45:15 +0100 Subject: [PATCH 04/13] adding some comments to explain the odd logic needed here --- python/nammu/view/AtfAreaView.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/python/nammu/view/AtfAreaView.py b/python/nammu/view/AtfAreaView.py index f601e204..642d0062 100644 --- a/python/nammu/view/AtfAreaView.py +++ b/python/nammu/view/AtfAreaView.py @@ -81,6 +81,9 @@ def __init__(self, controller): # Add a document listener to track changes to files self.edit_area.getDocument().addDocumentListener(atfAreaDocumentListener(self)) + # instance variable to store a record of the text contents prior to the + # most recent change. Needed so that the different listeners can access + # this to handle error line updating. self.oldtext = '' def toggle_split(self, split_orientation=None): From 3257c9660ea6fe27bbd3b8ea85f628ebefad16c0 Mon Sep 17 00:00:00 2001 From: Stuart Grieve Date: Tue, 22 Aug 2017 11:46:56 +0100 Subject: [PATCH 05/13] removing edits to undo code that are no longer relevant --- python/nammu/view/AtfAreaView.py | 4 ---- 1 file changed, 4 deletions(-) diff --git a/python/nammu/view/AtfAreaView.py b/python/nammu/view/AtfAreaView.py index 642d0062..a88d3bdd 100644 --- a/python/nammu/view/AtfAreaView.py +++ b/python/nammu/view/AtfAreaView.py @@ -291,10 +291,6 @@ def undoableEditHappened(self, event): edit = event.getEdit() edit_type = str(edit.getType()) - if edit_type == "REMOVE": - # This could be a place where we can get info about the removed text - pass - # If significant INSERT/REMOVE event happen, end and add current # edit compound to undo_manager and start a new one. if ((edit_type == "INSERT" or edit_type == "REMOVE") and From c3f360f773d3da30ec5e8b2dc32c1cec4afd4236 Mon Sep 17 00:00:00 2001 From: Stuart Grieve Date: Tue, 22 Aug 2017 11:57:41 +0100 Subject: [PATCH 06/13] Removing redundant calls to syntax highlight on copy, cut paste, replace. These resulted in duplicate calls and overflow errors due to the new error highlight code --- python/nammu/view/AtfEditArea.py | 4 ---- 1 file changed, 4 deletions(-) diff --git a/python/nammu/view/AtfEditArea.py b/python/nammu/view/AtfEditArea.py index b225bfc6..b8c78578 100644 --- a/python/nammu/view/AtfEditArea.py +++ b/python/nammu/view/AtfEditArea.py @@ -90,7 +90,6 @@ def replaceSelection(self, text): after replacing some text. ''' super(AtfEditArea, self).replaceSelection(text) - self.controller.syntax_highlight() def cut(self): ''' @@ -98,7 +97,6 @@ def cut(self): works when user cuts text via toolbar button or mouse. ''' super(AtfEditArea, self).cut() - self.controller.syntax_highlight() def copy(self): ''' @@ -106,7 +104,6 @@ def copy(self): works when user copies text via toolbar button or mouse. ''' super(AtfEditArea, self).copy() - self.controller.syntax_highlight() def paste(self): ''' @@ -114,7 +111,6 @@ def paste(self): works when user pastes text via toolbar button or mouse. ''' super(AtfEditArea, self).paste() - self.controller.syntax_highlight() class CustomMouseListener(MouseAdapter): From b0c6e29c03ec783daca2a96d1b2baecfccd9d285 Mon Sep 17 00:00:00 2001 From: Stuart Grieve Date: Tue, 22 Aug 2017 12:59:17 +0100 Subject: [PATCH 07/13] refactoring and removing duplicated code --- python/nammu/controller/AtfAreaController.py | 51 ++++++++--------- python/nammu/view/AtfAreaView.py | 59 ++++++++++---------- 2 files changed, 56 insertions(+), 54 deletions(-) diff --git a/python/nammu/controller/AtfAreaController.py b/python/nammu/controller/AtfAreaController.py index bc32d789..3e84c6b2 100644 --- a/python/nammu/controller/AtfAreaController.py +++ b/python/nammu/controller/AtfAreaController.py @@ -155,6 +155,10 @@ def get_viewport_top_bottom(self, top, bottom): return top_line, bottom_line def pad_top_viewport_caret(self, top_left_char, text): + ''' + Extend the top of the viewport to the nearest header, so we don't + have problems with malformed atf files being highlighted. + ''' # Test that there is text in the edit area if len(text) == 0: @@ -198,6 +202,10 @@ def pad_top_viewport_caret(self, top_left_char, text): return top_left_char def pad_bottom_viewport_caret(self, bottom_left_char, text): + ''' + Adds two lines to the bottom of the viewport so we dont have any + unhighlighted lines visible. + ''' # Test that there is text in the edit area if len(text) == 0: @@ -219,42 +227,35 @@ def pad_bottom_viewport_caret(self, bottom_left_char, text): return bottom_left_char - def update_error_lines_insert(self, caret_line, no_of_newlines): - - if no_of_newlines < 1: - return - - error_lines = self.validation_errors.keys() - - error_lines_int = [int(a) for a in error_lines] - - if caret_line < min(error_lines_int): - - tmp = {} - for q, err in enumerate(error_lines_int): - if err > caret_line: - error_lines_int[q] += no_of_newlines - - # rebuild self.controller.validation_errors.keys() - tmp[str(error_lines_int[q])] = self.validation_errors[str(err)] - - self.validation_errors = tmp - - def update_error_lines_remove(self, caret_line, no_of_removed_lines): + def update_error_lines(self, caret_line, no_of_lines, flag): + ''' + Given a caret line number, a number of lines and a flag indicating + whether the error lines need incremented ('insert') or decremented + ('remove'). Update the line numbers of the keys in the dictionary + self.validation_errors so that error highlighting follows broken lines + during editing. + ''' - if no_of_removed_lines < 1: + # If the supplied edit does not add or remove any lines, do nothing + if no_of_lines < 1: return error_lines = self.validation_errors.keys() + # For legacy reasons the keys are strings, but we need ints error_lines_int = [int(a) for a in error_lines] - if caret_line < min(error_lines_int): + # We only care about edits hapenning above error lines + if caret_line < max(error_lines_int): tmp = {} for q, err in enumerate(error_lines_int): if err > caret_line: - error_lines_int[q] -= no_of_removed_lines + # either increment or decrement based on insert or remove + if flag == 'insert': + error_lines_int[q] += no_of_lines + elif flag == 'remove': + error_lines_int[q] -= no_of_lines # rebuild self.controller.validation_errors.keys() tmp[str(error_lines_int[q])] = self.validation_errors[str(err)] diff --git a/python/nammu/view/AtfAreaView.py b/python/nammu/view/AtfAreaView.py index a88d3bdd..5c66d8bc 100644 --- a/python/nammu/view/AtfAreaView.py +++ b/python/nammu/view/AtfAreaView.py @@ -158,53 +158,54 @@ def __init__(self, areaview): self.areaviewcontroller = areaview.controller self.areaview = areaview - def changedUpdate(self, e): - pass - def insertUpdate(self, e): + def errorUpdate(self, e, text, flag): + ''' + Method to handle the updating of error lines. + ''' - # Only need to do this if we have error lines + # Only need to do this if we have error_lines if self.areaviewcontroller.validation_errors == {}: return - text = self.areaviewcontroller.edit_area.getText() + # Gets the position and length of the edit to the document length = e.getLength() offset = e.getOffset() - insert = text[offset:length + offset] + # Slice out the edited text + edited = text[offset:length + offset] - if '\n' in insert: - no_of_newlines = insert.count('\n') + if '\n' in edited: + no_of_newlines = edited.count('\n') # Get the line no of the caret postion caret_line = self.areaviewcontroller.edit_area.get_line_num(offset) # Call our error line update method here, passing no_of_newlines - self.areaviewcontroller.update_error_lines_insert(caret_line, - no_of_newlines) + self.areaviewcontroller.update_error_lines(caret_line, + no_of_newlines, + flag) - def removeUpdate(self, e): + def changedUpdate(self, e): + ''' + Must be implemented to avoid NotImplemented errors + ''' + pass - # Only need to do this if we have error_lines - if self.areaviewcontroller.validation_errors == {}: - return + def insertUpdate(self, e): + ''' + Listen for an insertion to the document. + ''' + text = self.areaviewcontroller.edit_area.getText() + self.errorUpdate(e, text, 'insert') + def removeUpdate(self, e): + ''' + Listen for a removal from the document + ''' + # Get the text prior to this edit event text = self.areaview.oldtext - length = e.getLength() - offset = e.getOffset() - - removed = text[offset:length + offset] - - if '\n' in removed: - no_removed_lines = removed.count('\n') - - # Get the line no of the caret postion - caret_line = self.areaviewcontroller.edit_area.get_line_num(offset) - - # Call our error line update method here, passing no_removed_lines - self.areaviewcontroller.update_error_lines_remove(caret_line, - no_removed_lines) - + self.errorUpdate(e, text, 'remove') class atfAreaAdjustmentListener(AdjustmentListener): From bfe48cc2f39b27d305ba2152b51cfd1c89d87ef0 Mon Sep 17 00:00:00 2001 From: Stuart Grieve Date: Tue, 22 Aug 2017 13:03:30 +0100 Subject: [PATCH 08/13] Fixing pep8 errors --- python/nammu/controller/AtfAreaController.py | 10 +++++----- python/nammu/view/AtfAreaView.py | 6 ++++-- 2 files changed, 9 insertions(+), 7 deletions(-) diff --git a/python/nammu/controller/AtfAreaController.py b/python/nammu/controller/AtfAreaController.py index 3e84c6b2..580b0568 100644 --- a/python/nammu/controller/AtfAreaController.py +++ b/python/nammu/controller/AtfAreaController.py @@ -243,22 +243,22 @@ def update_error_lines(self, caret_line, no_of_lines, flag): error_lines = self.validation_errors.keys() # For legacy reasons the keys are strings, but we need ints - error_lines_int = [int(a) for a in error_lines] + e_lines_int = [int(a) for a in error_lines] # We only care about edits hapenning above error lines if caret_line < max(error_lines_int): tmp = {} - for q, err in enumerate(error_lines_int): + for q, err in enumerate(e_lines_int): if err > caret_line: # either increment or decrement based on insert or remove if flag == 'insert': - error_lines_int[q] += no_of_lines + e_lines_int[q] += no_of_lines elif flag == 'remove': - error_lines_int[q] -= no_of_lines + e_lines_int[q] -= no_of_lines # rebuild self.controller.validation_errors.keys() - tmp[str(error_lines_int[q])] = self.validation_errors[str(err)] + tmp[str(e_lines_int[q])] = self.validation_errors[str(err)] self.validation_errors = tmp diff --git a/python/nammu/view/AtfAreaView.py b/python/nammu/view/AtfAreaView.py index 5c66d8bc..17ff2df3 100644 --- a/python/nammu/view/AtfAreaView.py +++ b/python/nammu/view/AtfAreaView.py @@ -79,7 +79,8 @@ def __init__(self, controller): self.secondary_area.addKeyListener(AtfAreaKeyListener(self)) # Add a document listener to track changes to files - self.edit_area.getDocument().addDocumentListener(atfAreaDocumentListener(self)) + docListener = atfAreaDocumentListener(self) + self.edit_area.getDocument().addDocumentListener(docListener) # instance variable to store a record of the text contents prior to the # most recent change. Needed so that the different listeners can access @@ -158,10 +159,11 @@ def __init__(self, areaview): self.areaviewcontroller = areaview.controller self.areaview = areaview - def errorUpdate(self, e, text, flag): ''' Method to handle the updating of error lines. + flag indicates whether the error lines need incremented ('insert') + or decrmented ('remove'). ''' # Only need to do this if we have error_lines From 1b7542536c2eb9d2ad3488bfd20be1a4819ef29f Mon Sep 17 00:00:00 2001 From: Stuart Grieve Date: Tue, 22 Aug 2017 14:43:15 +0100 Subject: [PATCH 09/13] Found a bunch of edge cases, most are fixed but still some stuff to resolve --- python/nammu/controller/AtfAreaController.py | 62 ++++++++++++++++---- 1 file changed, 50 insertions(+), 12 deletions(-) diff --git a/python/nammu/controller/AtfAreaController.py b/python/nammu/controller/AtfAreaController.py index 580b0568..aa2a3603 100644 --- a/python/nammu/controller/AtfAreaController.py +++ b/python/nammu/controller/AtfAreaController.py @@ -246,21 +246,59 @@ def update_error_lines(self, caret_line, no_of_lines, flag): e_lines_int = [int(a) for a in error_lines] # We only care about edits hapenning above error lines - if caret_line < max(error_lines_int): + if caret_line > max(e_lines_int): + return + + tmp = {} + for q, err in enumerate(e_lines_int): + + # The easiest case, we are above an error line + if err > caret_line: + fixed_line_no = self.line_fix(e_lines_int[q], no_of_lines, + flag) + + # rebuild self.controller.validation_errors + tmp[str(fixed_line_no)] = self.validation_errors[str(err)] + + # Edge case - we are on the error line + elif err == caret_line: - tmp = {} - for q, err in enumerate(e_lines_int): - if err > caret_line: - # either increment or decrement based on insert or remove - if flag == 'insert': - e_lines_int[q] += no_of_lines - elif flag == 'remove': - e_lines_int[q] -= no_of_lines + # need logic here to detect if not at end of a line + # THIS ALWAYS EVALS TO TRUE WHICH CORRESPONDS TO *NOT* being + # AT THE END OF A LINE. CHANGE TO A FALSE STATEMENT TO MAKE + # WORK FOR THE CURSOR AT THE END OF THE LINE BEHAVIOUR. + # NOT YET SURE HOW TO ACTUALLY TEST FOR THESE CONDITIONS + if 1 == 1: - # rebuild self.controller.validation_errors.keys() - tmp[str(e_lines_int[q])] = self.validation_errors[str(err)] + fixed_line_no = self.line_fix(e_lines_int[q], + no_of_lines, + flag) - self.validation_errors = tmp + # rebuild self.controller.validation_errors + tmp[str(fixed_line_no)] = self.validation_errors[str(err)] + else: + tmp[str(err)] = self.validation_errors[str(err)] + # We are below the error line so do nothing + else: + tmp[str(err)] = self.validation_errors[str(err)] + + # Write the updated line numbers to the error dictionary + self.validation_errors = tmp + + def line_fix(self, e_line_no, no_of_lines, flag): + ''' + Helper function containing the logic for incrementing or decrementing + line numbers + ''' + if flag == 'insert': + e_line_no += no_of_lines + elif flag == 'remove': + e_line_no -= no_of_lines + # handle potential out of bounds - 1 is top of the file + if e_line_no < 1: + e_line_no = 1 + + return e_line_no def syntax_highlight(self, top_caret=None, bottom_caret=None): ''' From b3e1466efc7a6182d5cd30a59fcb38a35e6a7654 Mon Sep 17 00:00:00 2001 From: Stuart Grieve Date: Wed, 23 Aug 2017 09:29:12 +0100 Subject: [PATCH 10/13] Fixed final edge case so inserts and deletions on error lines are handled correctly. --- python/nammu/controller/AtfAreaController.py | 38 ++++++++++++++++---- 1 file changed, 32 insertions(+), 6 deletions(-) diff --git a/python/nammu/controller/AtfAreaController.py b/python/nammu/controller/AtfAreaController.py index aa2a3603..6577e2f2 100644 --- a/python/nammu/controller/AtfAreaController.py +++ b/python/nammu/controller/AtfAreaController.py @@ -263,12 +263,13 @@ def update_error_lines(self, caret_line, no_of_lines, flag): # Edge case - we are on the error line elif err == caret_line: - # need logic here to detect if not at end of a line - # THIS ALWAYS EVALS TO TRUE WHICH CORRESPONDS TO *NOT* being - # AT THE END OF A LINE. CHANGE TO A FALSE STATEMENT TO MAKE - # WORK FOR THE CURSOR AT THE END OF THE LINE BEHAVIOUR. - # NOT YET SURE HOW TO ACTUALLY TEST FOR THESE CONDITIONS - if 1 == 1: + # We need the line end position and the caret position + positions = self.getLinePositions(self.view.oldtext) + caret_pos = self.edit_area.getCaretPosition() + line_end = positions[caret_line - 1][1] + + # If we are not at the end of a line, update the highlighting + if caret_pos != line_end: fixed_line_no = self.line_fix(e_lines_int[q], no_of_lines, @@ -277,6 +278,8 @@ def update_error_lines(self, caret_line, no_of_lines, flag): # rebuild self.controller.validation_errors tmp[str(fixed_line_no)] = self.validation_errors[str(err)] else: + # We are at the end of a line, so an insert will not alter + # the error line's position tmp[str(err)] = self.validation_errors[str(err)] # We are below the error line so do nothing else: @@ -346,3 +349,26 @@ def getPositionFromLine(self, text, line_num): pos = 0 return pos + + def getLinePositions(self, text): + ''' + Given a block of text, return the caret positions + at the start and end of each line as a list of tuples in the order + (start, end) assuming left to right text. + The hacky list addition is to handle off by one errors as the 1st line + starts at position 0, whereas every other line starts at +1 past the + end of the last line and we also need to add in the final line length + manually. + ''' + if len(text) > 0: + compiled = re.compile(r"\n") + textiter = compiled.finditer(text) + pos = [m.start() for m in textiter] + else: + return [(0, 0)] + + # Build lists of the starts and ends of each line + starts = [0] + [x + 1 for x in pos] + ends = pos + [len(text)] + + return zip(starts, ends) From 279c7928362343ab49aa4410c3e70ddefaacaa41 Mon Sep 17 00:00:00 2001 From: Stuart Grieve Date: Wed, 23 Aug 2017 09:33:39 +0100 Subject: [PATCH 11/13] pep8 fix --- python/nammu/controller/AtfAreaController.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/python/nammu/controller/AtfAreaController.py b/python/nammu/controller/AtfAreaController.py index 6577e2f2..c3a15be0 100644 --- a/python/nammu/controller/AtfAreaController.py +++ b/python/nammu/controller/AtfAreaController.py @@ -267,7 +267,7 @@ def update_error_lines(self, caret_line, no_of_lines, flag): positions = self.getLinePositions(self.view.oldtext) caret_pos = self.edit_area.getCaretPosition() line_end = positions[caret_line - 1][1] - + # If we are not at the end of a line, update the highlighting if caret_pos != line_end: From 9b40b64bf29d902ed6d2a6c7df2a65103b379ade Mon Sep 17 00:00:00 2001 From: Stuart Grieve Date: Wed, 23 Aug 2017 14:50:32 +0100 Subject: [PATCH 12/13] simplifying error moving logic following review. --- python/nammu/controller/AtfAreaController.py | 33 +++++--------------- 1 file changed, 8 insertions(+), 25 deletions(-) diff --git a/python/nammu/controller/AtfAreaController.py b/python/nammu/controller/AtfAreaController.py index c3a15be0..904204fa 100644 --- a/python/nammu/controller/AtfAreaController.py +++ b/python/nammu/controller/AtfAreaController.py @@ -249,39 +249,22 @@ def update_error_lines(self, caret_line, no_of_lines, flag): if caret_line > max(e_lines_int): return + # We need the line end position and the caret position + positions = self.getLinePositions(self.view.oldtext) + caret_pos = self.edit_area.getCaretPosition() + line_end = positions[caret_line - 1][1] + tmp = {} for q, err in enumerate(e_lines_int): - - # The easiest case, we are above an error line - if err > caret_line: + # We are above an error line or on an error line but not at its end + if (err > caret_line) or (err == caret_line and caret_pos != line_end): fixed_line_no = self.line_fix(e_lines_int[q], no_of_lines, flag) # rebuild self.controller.validation_errors tmp[str(fixed_line_no)] = self.validation_errors[str(err)] - # Edge case - we are on the error line - elif err == caret_line: - - # We need the line end position and the caret position - positions = self.getLinePositions(self.view.oldtext) - caret_pos = self.edit_area.getCaretPosition() - line_end = positions[caret_line - 1][1] - - # If we are not at the end of a line, update the highlighting - if caret_pos != line_end: - - fixed_line_no = self.line_fix(e_lines_int[q], - no_of_lines, - flag) - - # rebuild self.controller.validation_errors - tmp[str(fixed_line_no)] = self.validation_errors[str(err)] - else: - # We are at the end of a line, so an insert will not alter - # the error line's position - tmp[str(err)] = self.validation_errors[str(err)] - # We are below the error line so do nothing + # We are below or after the error lines so do nothing else: tmp[str(err)] = self.validation_errors[str(err)] From b9fa41b6ed47fd8a9dee73c4a24f5735fc01a542 Mon Sep 17 00:00:00 2001 From: Stuart Grieve Date: Wed, 23 Aug 2017 14:52:07 +0100 Subject: [PATCH 13/13] breaking a long line --- python/nammu/controller/AtfAreaController.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/python/nammu/controller/AtfAreaController.py b/python/nammu/controller/AtfAreaController.py index 904204fa..86f54b7e 100644 --- a/python/nammu/controller/AtfAreaController.py +++ b/python/nammu/controller/AtfAreaController.py @@ -257,7 +257,8 @@ def update_error_lines(self, caret_line, no_of_lines, flag): tmp = {} for q, err in enumerate(e_lines_int): # We are above an error line or on an error line but not at its end - if (err > caret_line) or (err == caret_line and caret_pos != line_end): + if (err > caret_line) or (err == caret_line and + caret_pos != line_end): fixed_line_no = self.line_fix(e_lines_int[q], no_of_lines, flag)