diff --git a/src/calibre/gui2/tweak_book/editor/smarts/python.py b/src/calibre/gui2/tweak_book/editor/smarts/python.py index 1a06c3bf8b..a5e5648906 100644 --- a/src/calibre/gui2/tweak_book/editor/smarts/python.py +++ b/src/calibre/gui2/tweak_book/editor/smarts/python.py @@ -12,8 +12,8 @@ from PyQt5.Qt import Qt from calibre.gui2.tweak_book.editor.smarts import NullSmarts from calibre.gui2.tweak_book.editor.smarts.utils import ( - get_text_before_cursor, get_leading_whitespace_on_block as lw, no_modifiers, - test_modifiers, is_cursor_on_wrapped_line) + get_text_before_cursor, get_leading_whitespace_on_block as lw, + smart_home, smart_backspace, smart_tab) get_leading_whitespace_on_block = lambda editor, previous=False: expand_tabs(lw(editor, previous=previous)) @@ -35,29 +35,11 @@ class Smarts(NullSmarts): def handle_key_press(self, ev, editor): key = ev.key() - if key == Qt.Key_Tab: - cursor, text = get_text_before_cursor(editor) - if not text.lstrip(): - # cursor is preceded by whitespace - text = expand_tabs(text) - spclen = len(text) - (len(text) % tw) + tw - cursor.insertText(' ' * spclen) - editor.setTextCursor(cursor) - else: - cursor = editor.textCursor() - cursor.insertText(' ' * tw) - editor.setTextCursor(cursor) + if key == Qt.Key_Tab and smart_tab(editor, ev, tw): return True - elif key == Qt.Key_Backspace: - cursor, text = get_text_before_cursor(editor) - if text and not text.lstrip(): - # cursor is preceded by whitespace - text = expand_tabs(text) - spclen = max(0, len(text) - (len(text) % tw) - tw) - cursor.insertText(' ' * spclen) - editor.setTextCursor(cursor) - return True + elif key == Qt.Key_Backspace and smart_backspace(editor, ev, tw): + return True elif key in (Qt.Key_Enter, Qt.Key_Return): ls = get_leading_whitespace_on_block(editor) @@ -83,15 +65,7 @@ class Smarts(NullSmarts): editor.setTextCursor(cursor) return True - elif key == Qt.Key_Home and no_modifiers(ev, Qt.ControlModifier) and not is_cursor_on_wrapped_line(editor): - cursor, text = get_text_before_cursor(editor) - cursor = editor.textCursor() - mode = cursor.KeepAnchor if test_modifiers(ev, Qt.ShiftModifier) else cursor.MoveAnchor - cursor.movePosition(cursor.StartOfBlock, mode) - if text.strip(): - # Move to the start of text - cursor.movePosition(cursor.NextWord, mode) - editor.setTextCursor(cursor) + if key == Qt.Key_Home and smart_home(editor, ev): return True if __name__ == '__main__': diff --git a/src/calibre/gui2/tweak_book/editor/smarts/utils.py b/src/calibre/gui2/tweak_book/editor/smarts/utils.py index bbb3bf8a84..8a5c6d3763 100644 --- a/src/calibre/gui2/tweak_book/editor/smarts/utils.py +++ b/src/calibre/gui2/tweak_book/editor/smarts/utils.py @@ -6,12 +6,16 @@ from __future__ import (unicode_literals, division, absolute_import, __license__ = 'GPL v3' __copyright__ = '2014, Kovid Goyal ' -def get_text_before_cursor(editor): +from PyQt5.Qt import Qt + +def get_text_around_cursor(editor, before=True): cursor = editor.textCursor() cursor.clearSelection() - cursor.movePosition(cursor.StartOfBlock, cursor.KeepAnchor) - text = cursor.selectedText() + cursor.movePosition((cursor.StartOfBlock if before else cursor.EndOfBlock), cursor.KeepAnchor) + text = editor.selected_text_from_cursor(cursor) return cursor, text +get_text_before_cursor = get_text_around_cursor +get_text_after_cursor = lambda editor: get_text_around_cursor(editor, before=False) def is_cursor_on_wrapped_line(editor): cursor = editor.textCursor() @@ -45,5 +49,41 @@ def test_modifiers(ev, *args): return False return True +def smart_home(editor, ev): + if no_modifiers(ev, Qt.ControlModifier) and not is_cursor_on_wrapped_line(editor): + cursor, text = get_text_before_cursor(editor) + cursor = editor.textCursor() + mode = cursor.KeepAnchor if test_modifiers(ev, Qt.ShiftModifier) else cursor.MoveAnchor + cursor.movePosition(cursor.StartOfBlock, mode) + if text.strip(): + # Move to the start of text + cursor.movePosition(cursor.NextWord, mode) + editor.setTextCursor(cursor) + return True + return False +def expand_tabs(text, tw): + return text.replace('\t', ' ' * tw) + +def smart_tab(editor, ev, tw): + cursor, text = get_text_before_cursor(editor) + if not text.lstrip(): + # cursor is preceded by only whitespace + text = expand_tabs(text, tw) + spclen = len(text) - (len(text) % tw) + tw + cursor.insertText(' ' * spclen) + editor.setTextCursor(cursor) + return True + return False + +def smart_backspace(editor, ev, tw): + cursor, text = get_text_before_cursor(editor) + if text and not text.lstrip(): + # cursor is preceded by only whitespace + text = expand_tabs(text, tw) + spclen = max(0, len(text) - (len(text) % tw) - tw) + cursor.insertText(' ' * spclen) + editor.setTextCursor(cursor) + return True + return False