def test(): '''Test the basics of `get_n_identical_edge_characters`.''' assert get_n_identical_edge_characters('qqqwee') == 3 assert get_n_identical_edge_characters('qqqqwee') == 4 assert get_n_identical_edge_characters('qqqqwee', head=False) == 2 assert get_n_identical_edge_characters('1234') == 1 assert get_n_identical_edge_characters('1234', character='4') == 0 assert get_n_identical_edge_characters('1234', character='4', head=False) == 1 assert get_n_identical_edge_characters('1234', character='&', head=False) == 0 assert get_n_identical_edge_characters('pppp') == \ get_n_identical_edge_characters('pppp', head=False) == \ get_n_identical_edge_characters('pppp', character='p', head=False) == 4
def parse(self, name, class_name): ''' Parse a name into a tuple of "words". For example, under default settings, an input of '_on_navigation_panel__left_down' would result in an output of `('navigation_panel', 'left_down')`. Returns `None` if there is no match. ''' unmangled_name = name_mangling.unmangle_attribute_name_if_needed( name, class_name ) n_preceding_underscores = string_tools.get_n_identical_edge_characters( unmangled_name, character='_', head=True ) if n_preceding_underscores not in \ self.n_preceding_underscores_possibilities: return None cleaned_name = unmangled_name[n_preceding_underscores:] for case_style in self.case_style_possibilites: result = case_style.parse(cleaned_name) if result is not None: return result else: return None
def test(): '''Test the basics of `get_n_identical_edge_characters`.''' assert get_n_identical_edge_characters('qqqwee') == 3 assert get_n_identical_edge_characters('qqqqwee') == 4 assert get_n_identical_edge_characters('qqqqwee', head=False) == 2 assert get_n_identical_edge_characters('1234') == 1 assert get_n_identical_edge_characters('1234', character='4') == 0 assert get_n_identical_edge_characters('1234', character='4', head=False) == 1 assert get_n_identical_edge_characters('1234', character='&', head=False) == 0 assert get_n_identical_edge_characters('pppp') == \ get_n_identical_edge_characters('pppp', head=False) == \ get_n_identical_edge_characters('pppp', character='p', head=False) == 4
def push_line_to_end(editor=wingapi.kArgEditor, line_offset=0): ''' Push the current line to the end, aligning it to right border of editor. This inserts or deletes as many spaces as necessary from the beginning of the line to make the end of the line exactly coincide with the right border of the editor. (Whose width can be configured in Wing's "Preferences" -> "Line Wrapping" -> "Reformatting Wrap Column".) This is useful for creating lines of this style: if first_long_condition(foo, foobar) and \ second_long_condition(fubaz, bazbar): Also deletes trailing spaces. Suggested key combination: `Insert End` ''' assert isinstance(editor, wingapi.CAPIEditor) document = editor.GetDocument() assert isinstance(document, wingapi.CAPIDocument) position, _ = editor.GetSelection() line = document.GetLineNumberFromPosition(position) + line_offset line_start = document.GetLineStart(line) line_end = document.GetLineEnd(line) line_content = document.GetCharRange(line_start, line_end) n_trailing_spaces = _get_n_identical_edge_characters(line_content, character=' ', head=False) current_line_length = line_end - line_start n_spaces_to_add = \ wingapi.gApplication.GetPreference('edit.text-wrap-column') - \ current_line_length + n_trailing_spaces with shared.UndoableAction(document): document.DeleteChars(line_end - n_trailing_spaces, line_end - 1) if n_spaces_to_add == 0: return elif n_spaces_to_add > 0: string_to_insert = (' ' * n_spaces_to_add) document.InsertChars(line_start, string_to_insert) else: assert n_spaces_to_add < 0 n_spaces_to_delete = min( -n_spaces_to_add, string_tools.get_n_identical_edge_characters( line_content, character=' ' ) ) document.DeleteChars( line_start, line_start + (n_spaces_to_delete - 1) )
def unmangle_attribute_name_if_needed(attribute_name, class_name): # Ruling out four cases in which mangling wouldn't have happened: if ((string_tools.get_n_identical_edge_characters(attribute_name, '_') != 1) or (len(attribute_name) >= MANGLE_LEN) or (attribute_name.endswith('__')) or set(class_name) == set('_')): return attribute_name cleaned_class_name = class_name.lstrip('_') if not attribute_name[1:].startswith(cleaned_class_name + '__'): return attribute_name return attribute_name[(len(cleaned_class_name) + 1):]
def push_line_to_end(editor=wingapi.kArgEditor, line_offset=0): ''' Push the current line to the end, aligning it to right border of editor. This inserts or deletes as many spaces as necessary from the beginning of the line to make the end of the line exactly coincide with the right border of the editor. (Whose width can be configured in Wing's "Preferences" -> "Line Wrapping" -> "Reformatting Wrap Column".) This is useful for creating lines of this style: if first_long_condition(foo, foobar) and \ second_long_condition(fubaz, bazbar): Also deletes trailing spaces. Suggested key combination: `Insert End` ''' assert isinstance(editor, wingapi.CAPIEditor) document = editor.GetDocument() assert isinstance(document, wingapi.CAPIDocument) position, _ = editor.GetSelection() line = document.GetLineNumberFromPosition(position) + line_offset line_start = document.GetLineStart(line) line_end = document.GetLineEnd(line) line_content = document.GetCharRange(line_start, line_end) n_trailing_spaces = _get_n_identical_edge_characters(line_content, character=' ', head=False) current_line_length = line_end - line_start n_spaces_to_add = \ wingapi.gApplication.GetPreference('edit.text-wrap-column') - \ current_line_length + n_trailing_spaces with shared.UndoableAction(document): document.DeleteChars(line_end - n_trailing_spaces, line_end - 1) if n_spaces_to_add == 0: return elif n_spaces_to_add > 0: string_to_insert = (' ' * n_spaces_to_add) document.InsertChars(line_start, string_to_insert) else: assert n_spaces_to_add < 0 n_spaces_to_delete = min( -n_spaces_to_add, string_tools.get_n_identical_edge_characters(line_content, character=' ')) document.DeleteChars(line_start, line_start + (n_spaces_to_delete - 1))
def unmangle_attribute_name_if_needed(attribute_name, class_name): # Ruling out four cases in which mangling wouldn't have happened: if ((string_tools.get_n_identical_edge_characters(attribute_name, '_') != 1) or (len(attribute_name) >= MANGLE_LEN) or (attribute_name.endswith('__')) or set(class_name) == set('_')): return attribute_name cleaned_class_name = class_name.lstrip('_') if not attribute_name[1:].startswith(cleaned_class_name + '__'): return attribute_name return attribute_name[(len(cleaned_class_name) + 1):]
def parse(self, name, class_name): ''' Parse a name into a tuple of "words". For example, under default settings, an input of '_on_navigation_panel__left_down' would result in an output of `('navigation_panel', 'left_down')`. Returns `None` if there is no match. ''' unmangled_name = name_mangling.unmangle_attribute_name_if_needed( name, class_name) n_preceding_underscores = string_tools.get_n_identical_edge_characters( unmangled_name, character='_', head=True) if n_preceding_underscores not in \ self.n_preceding_underscores_possibilities: return None cleaned_name = unmangled_name[n_preceding_underscores:] for case_style in self.case_style_possibilites: result = case_style.parse(cleaned_name) if result is not None: return result else: return None
def deep_to_var(editor=wingapi.kArgEditor): ''' Create a variable from a deep expression. When you're programming, you're often writing lines like these: html_color = self._style_handler.html_color Or: location = context_data['location'] Or: event_handler = super(Foobsnicator, self).get_event_handler() Or: user_profile = models.UserProfile.objects.get(pk=pk) What's common to all these lines is that you're accessing some expression, sometimes a deep one, and then getting an object, and making a variable for that object with the same name that it has in the deep expression. What this `deep-to-var` script will do for you is save you from having to write the `html_color = ` part, which is annoying to type because you don't have autocompletion for it. Just write your deep expression, like `self._style_handler.html_color`, invoke this `deep-to-var` script, and you'll get the full line and have the caret put on the next line. Suggested key combination: `Insert E` ''' assert isinstance(editor, wingapi.CAPIEditor) document = editor.GetDocument() assert isinstance(document, wingapi.CAPIDocument) position, _ = editor.GetSelection() line_number = document.GetLineNumberFromPosition(position) line_start = document.GetLineStart(line_number) line_end = document.GetLineEnd(line_number) line = document.GetCharRange(line_start, line_end) line_stripped = line.strip() variable_name = None match = None for pattern in patterns: match = pattern.search(line_stripped) if match: if pattern in variable_name_map: variable_name = variable_name_map[pattern] else: (variable_name,) = match.groups() break if match: if variable_name != variable_name.lower(): # `variable_name` has an uppercase letter, and thus is probably # camel-case. Let's flip it to underscore: variable_name = shared.camel_case_to_lower_case(variable_name) string_to_insert = '%s = ' % variable_name actual_line_start = line_start + \ string_tools.get_n_identical_edge_characters(line, character=' ') with shared.UndoableAction(document): document.InsertChars(actual_line_start, string_to_insert) new_position = line_end + len(string_to_insert) editor.SetSelection(new_position, new_position) editor.ExecuteCommand('new-line')
def deep_to_var(editor=wingapi.kArgEditor): ''' Create a variable from a deep expression. When you're programming, you're often writing lines like these: html_color = self._style_handler.html_color Or: location = context_data['location'] Or: event_handler = super(Foobsnicator, self).get_event_handler() Or: user_profile = models.UserProfile.objects.get(pk=pk) What's common to all these lines is that you're accessing some expression, sometimes a deep one, and then getting an object, and making a variable for that object with the same name that it has in the deep expression. What this `deep-to-var` script will do for you is save you from having to write the `html_color = ` part, which is annoying to type because you don't have autocompletion for it. Just write your deep expression, like `self._style_handler.html_color`, invoke this `deep-to-var` script, and you'll get the full line and have the caret put on the next line. Suggested key combination: `Insert E` ''' assert isinstance(editor, wingapi.CAPIEditor) document = editor.GetDocument() assert isinstance(document, wingapi.CAPIDocument) position, _ = editor.GetSelection() line_number = document.GetLineNumberFromPosition(position) line_start = document.GetLineStart(line_number) line_end = document.GetLineEnd(line_number) line = document.GetCharRange(line_start, line_end) line_stripped = line.strip() variable_name = None match = None for pattern in patterns: match = pattern.search(line_stripped) if match: if pattern in variable_name_map: variable_name = variable_name_map[pattern] else: (variable_name, ) = match.groups() break if match: if variable_name != variable_name.lower(): # `variable_name` has an uppercase letter, and thus is probably # camel-case. Let's flip it to underscore: variable_name = shared.camel_case_to_lower_case(variable_name) string_to_insert = '%s = ' % variable_name actual_line_start = line_start + \ string_tools.get_n_identical_edge_characters(line, character=' ') with shared.UndoableAction(document): document.InsertChars(actual_line_start, string_to_insert) new_position = line_end + len(string_to_insert) editor.SetSelection(new_position, new_position) editor.ExecuteCommand('new-line')