|
1 # -*- coding: utf-8 -*- |
|
2 |
|
3 # Copyright (c) 2019 Detlev Offenbach <detlev@die-offenbachs.de> |
|
4 # |
|
5 |
|
6 """ |
|
7 Module implementing a typing completer for Python. |
|
8 """ |
|
9 |
|
10 import re |
|
11 |
|
12 from PyQt5.Qsci import QsciScintilla |
|
13 |
|
14 from .CompleterBase import CompleterBase |
|
15 |
|
16 import Preferences |
|
17 |
|
18 |
|
19 class CompleterYaml(CompleterBase): |
|
20 """ |
|
21 Class implementing typing completer for Python. |
|
22 """ |
|
23 def __init__(self, editor, parent=None): |
|
24 """ |
|
25 Constructor |
|
26 |
|
27 @param editor reference to the editor object |
|
28 @type QScintilla.Editor |
|
29 @param parent reference to the parent object |
|
30 @type QObject |
|
31 """ |
|
32 super(CompleterYaml, self).__init__(editor, parent) |
|
33 |
|
34 self.readSettings() |
|
35 |
|
36 def readSettings(self): |
|
37 """ |
|
38 Public slot called to reread the configuration parameters. |
|
39 """ |
|
40 self.setEnabled( |
|
41 Preferences.getEditorTyping("Yaml/EnabledTypingAids")) |
|
42 self.__insertClosingBrace = Preferences.getEditorTyping( |
|
43 "Yaml/InsertClosingBrace") |
|
44 self.__skipBrace = Preferences.getEditorTyping( |
|
45 "Yaml/SkipBrace") |
|
46 self.__insertQuote = Preferences.getEditorTyping( |
|
47 "Yaml/InsertQuote") |
|
48 self.__autoIndentation = Preferences.getEditorTyping( |
|
49 "Yaml/AutoIndentation") |
|
50 self.__colonDetection = Preferences.getEditorTyping( |
|
51 "Yaml/ColonDetection") |
|
52 self.__insertBlankDash = Preferences.getEditorTyping( |
|
53 "Yaml/InsertBlankDash") |
|
54 self.__insertBlankColon = Preferences.getEditorTyping( |
|
55 "Yaml/InsertBlankColon") |
|
56 self.__insertBlankQuestion = Preferences.getEditorTyping( |
|
57 "Yaml/InsertBlankQuestion") |
|
58 self.__insertBlankComma = Preferences.getEditorTyping( |
|
59 "Yaml/InsertBlankComma") |
|
60 |
|
61 def charAdded(self, charNumber): |
|
62 """ |
|
63 Public slot called to handle the user entering a character. |
|
64 |
|
65 @param charNumber value of the character entered |
|
66 @type int |
|
67 """ |
|
68 char = chr(charNumber) |
|
69 if char not in ['{', '}', '[', ']', "'", '"', '-', ':', '?', ',', |
|
70 '\n']: |
|
71 return # take the short route |
|
72 |
|
73 line, col = self.editor.getCursorPosition() |
|
74 |
|
75 if self.__inComment(line, col): |
|
76 return |
|
77 |
|
78 # open curly brace |
|
79 # insert closing brace |
|
80 if char == '{': |
|
81 if self.__insertClosingBrace: |
|
82 self.editor.insert('}') |
|
83 |
|
84 # open bracket |
|
85 # insert closing bracket |
|
86 elif char == '[': |
|
87 if self.__insertClosingBrace: |
|
88 self.editor.insert(']') |
|
89 |
|
90 # closing parenthesis |
|
91 # skip matching closing parenthesis |
|
92 elif char in ['}', ']']: |
|
93 txt = self.editor.text(line) |
|
94 if col < len(txt) and char == txt[col]: |
|
95 if self.__skipBrace: |
|
96 self.editor.setSelection(line, col, line, col + 1) |
|
97 self.editor.removeSelectedText() |
|
98 |
|
99 # dash |
|
100 # insert blank |
|
101 elif char == '-': |
|
102 if self.__insertBlankDash: |
|
103 self.editor.insert(' ') |
|
104 self.editor.setCursorPosition(line, col + 1) |
|
105 |
|
106 # colon |
|
107 # 1. skip colon if not last character |
|
108 # 2. insert blank if last character |
|
109 elif char == ':': |
|
110 text = self.editor.text(line) |
|
111 if col < len(text) and char == text[col]: |
|
112 if self.__colonDetection: |
|
113 self.editor.setSelection(line, col, line, col + 1) |
|
114 self.editor.removeSelectedText() |
|
115 elif self.__insertBlankColon: |
|
116 if col == len(text.rstrip()): |
|
117 self.editor.insert(' ') |
|
118 self.editor.setCursorPosition(line, col + 1) |
|
119 |
|
120 # question mark |
|
121 # insert blank |
|
122 elif char == '?': |
|
123 if self.__insertBlankQuestion: |
|
124 self.editor.insert(' ') |
|
125 self.editor.setCursorPosition(line, col + 1) |
|
126 |
|
127 # comma |
|
128 # insert blank |
|
129 elif char == ',': |
|
130 if self.__insertBlankComma: |
|
131 self.editor.insert(' ') |
|
132 self.editor.setCursorPosition(line, col + 1) |
|
133 |
|
134 # double quote |
|
135 # insert double quote |
|
136 elif char == '"': |
|
137 if self.__insertQuote: |
|
138 self.editor.insert('"') |
|
139 |
|
140 # quote |
|
141 # insert quote |
|
142 elif char == "'": |
|
143 if self.__insertQuote: |
|
144 self.editor.insert("'") |
|
145 |
|
146 # new line |
|
147 # indent after line ending with ':' |
|
148 elif char == '\n': |
|
149 if self.__autoIndentation: |
|
150 txt = self.editor.text(line - 1) |
|
151 match = re.search( |
|
152 "(?:\||\|-|\|\+|>|>-|>\+|-|:)(\s*)\r?\n", |
|
153 # __IGNORE_WARNING_W605__ |
|
154 txt) |
|
155 if match is not None: |
|
156 startBlanks = match.start(1) |
|
157 endBlanks = match.end(1) |
|
158 if startBlanks != -1 and startBlanks != endBlanks: |
|
159 # previous line ends with whitespace, e.g. caused by |
|
160 # blank insertion above |
|
161 self.editor.setSelection(line - 1, startBlanks, |
|
162 line - 1, endBlanks) |
|
163 self.editor.removeSelectedText() |
|
164 |
|
165 self.editor.indent(line) |
|
166 self.editor.setCursorPosition(line, 0) |
|
167 self.editor.editorCommand(QsciScintilla.SCI_VCHOME) |
|
168 |
|
169 def __inComment(self, line, col): |
|
170 """ |
|
171 Private method to check, if the cursor is inside a comment. |
|
172 |
|
173 @param line current line |
|
174 @type int |
|
175 @param col current position within line |
|
176 @type int |
|
177 @return flag indicating, if the cursor is inside a comment |
|
178 @rtype bool |
|
179 """ |
|
180 txt = self.editor.text(line) |
|
181 if col == len(txt): |
|
182 col -= 1 |
|
183 while col >= 0: |
|
184 if txt[col] == "#": |
|
185 return True |
|
186 col -= 1 |
|
187 return False |