bpo-35689: IDLE: Add docstrings and unittests for colorizer.py (GH-11… · python/cpython@99e9c36 (original) (raw)

`@@ -53,6 +53,21 @@ def color_config(text):

`

53

53

``

54

54

``

55

55

`class ColorDelegator(Delegator):

`

``

56

`+

"""Delegator for syntax highlighting (text coloring).

`

``

57

+

``

58

`+

Class variables:

`

``

59

`+

after_id: Identifier for scheduled after event.

`

``

60

`+

allow_colorizing: Boolean toggle for applying colorizing.

`

``

61

`+

colorizing: Boolean flag when colorizing is in process.

`

``

62

`+

stop_colorizing: Boolean flag to end an active colorizing

`

``

63

`+

process.

`

``

64

`+

close_when_done: Widget to destroy after colorizing process

`

``

65

`+

completes (doesn't seem to be used by IDLE).

`

``

66

+

``

67

`+

Instance variables:

`

``

68

`+

delegate: Delegator below this one in the stack, meaning the

`

``

69

`+

one this one delegates to.

`

``

70

`+

"""

`

56

71

``

57

72

`def init(self):

`

58

73

`Delegator.init(self)

`

`@@ -61,6 +76,16 @@ def init(self):

`

61

76

`self.LoadTagDefs()

`

62

77

``

63

78

`def setdelegate(self, delegate):

`

``

79

`+

"""Set the delegate for this instance.

`

``

80

+

``

81

`+

A delegate is an instance of a Delegator class and each

`

``

82

`+

delegate points to the next delegator in the stack. This

`

``

83

`+

allows multiple delegators to be chained together for a

`

``

84

`+

widget. The bottom delegate for a colorizer is a Text

`

``

85

`+

widget.

`

``

86

+

``

87

`+

If there is a delegate, also start the colorizing process.

`

``

88

`+

"""

`

64

89

`if self.delegate is not None:

`

65

90

`self.unbind("<>")

`

66

91

`Delegator.setdelegate(self, delegate)

`

`@@ -69,17 +94,18 @@ def setdelegate(self, delegate):

`

69

94

`self.bind("<>", self.toggle_colorize_event)

`

70

95

`self.notify_range("1.0", "end")

`

71

96

`else:

`

72

``

`-

No delegate - stop any colorizing

`

``

97

`+

No delegate - stop any colorizing.

`

73

98

`self.stop_colorizing = True

`

74

99

`self.allow_colorizing = False

`

75

100

``

76

101

`def config_colors(self):

`

``

102

`+

"Configure text widget tags with colors from tagdefs."

`

77

103

`for tag, cnf in self.tagdefs.items():

`

78

``

`-

if cnf:

`

79

``

`-

self.tag_configure(tag, **cnf)

`

``

104

`+

self.tag_configure(tag, **cnf)

`

80

105

`self.tag_raise('sel')

`

81

106

``

82

107

`def LoadTagDefs(self):

`

``

108

`+

"Create dictionary of tag names to text colors."

`

83

109

`theme = idleConf.CurrentTheme()

`

84

110

`self.tagdefs = {

`

85

111

`"COMMENT": idleConf.GetHighlight(theme, "comment"),

`

`@@ -97,20 +123,24 @@ def LoadTagDefs(self):

`

97

123

`if DEBUG: print('tagdefs',self.tagdefs)

`

98

124

``

99

125

`def insert(self, index, chars, tags=None):

`

``

126

`+

"Insert chars into widget at index and mark for colorizing."

`

100

127

`index = self.index(index)

`

101

128

`self.delegate.insert(index, chars, tags)

`

102

129

`self.notify_range(index, index + "+%dc" % len(chars))

`

103

130

``

104

131

`def delete(self, index1, index2=None):

`

``

132

`+

"Delete chars between indexes and mark for colorizing."

`

105

133

`index1 = self.index(index1)

`

106

134

`self.delegate.delete(index1, index2)

`

107

135

`self.notify_range(index1)

`

108

136

``

109

137

`after_id = None

`

110

138

`allow_colorizing = True

`

``

139

`+

stop_colorizing = False

`

111

140

`colorizing = False

`

112

141

``

113

142

`def notify_range(self, index1, index2=None):

`

``

143

`+

"Mark text changes for processing and restart colorizing, if active."

`

114

144

`self.tag_add("TODO", index1, index2)

`

115

145

`if self.after_id:

`

116

146

`if DEBUG: print("colorizing already scheduled")

`

`@@ -121,8 +151,9 @@ def notify_range(self, index1, index2=None):

`

121

151

`if self.allow_colorizing:

`

122

152

`if DEBUG: print("schedule colorizing")

`

123

153

`self.after_id = self.after(1, self.recolorize)

`

``

154

`+

return

`

124

155

``

125

``

`-

close_when_done = None # Window to be closed when done colorizing

`

``

156

`+

close_when_done = None # Window to be closed when done colorizing.

`

126

157

``

127

158

`def close(self, close_when_done=None):

`

128

159

`if self.after_id:

`

`@@ -138,7 +169,14 @@ def close(self, close_when_done=None):

`

138

169

`else:

`

139

170

`self.close_when_done = close_when_done

`

140

171

``

141

``

`-

def toggle_colorize_event(self, event):

`

``

172

`+

def toggle_colorize_event(self, event=None):

`

``

173

`+

"""Toggle colorizing on and off.

`

``

174

+

``

175

`+

When toggling off, if colorizing is scheduled or is in

`

``

176

`+

process, it will be cancelled and/or stopped.

`

``

177

+

``

178

`+

When toggling on, colorizing will be scheduled.

`

``

179

`+

"""

`

142

180

`if self.after_id:

`

143

181

`after_id = self.after_id

`

144

182

`self.after_id = None

`

`@@ -156,6 +194,17 @@ def toggle_colorize_event(self, event):

`

156

194

`return "break"

`

157

195

``

158

196

`def recolorize(self):

`

``

197

`+

"""Timer event (every 1ms) to colorize text.

`

``

198

+

``

199

`+

Colorizing is only attempted when the text widget exists,

`

``

200

`+

when colorizing is toggled on, and when the colorizing

`

``

201

`+

process is not already running.

`

``

202

+

``

203

`+

After colorizing is complete, some cleanup is done to

`

``

204

`+

make sure that all the text has been colorized and to close

`

``

205

`+

the window if the close event had been called while the

`

``

206

`+

process was running.

`

``

207

`+

"""

`

159

208

`self.after_id = None

`

160

209

`if not self.delegate:

`

161

210

`if DEBUG: print("no delegate")

`

`@@ -185,6 +234,7 @@ def recolorize(self):

`

185

234

`top.destroy()

`

186

235

``

187

236

`def recolorize_main(self):

`

``

237

`+

"Evaluate text and apply colorizing tags."

`

188

238

`next = "1.0"

`

189

239

`while True:

`

190

240

`item = self.tag_nextrange("TODO", next)

`

`@@ -250,6 +300,7 @@ def recolorize_main(self):

`

250

300

`return

`

251

301

``

252

302

`def removecolors(self):

`

``

303

`+

"Remove all colorizing tags."

`

253

304

`for tag in self.tagdefs:

`

254

305

`self.tag_remove(tag, "1.0", "end")

`

255

306

``

`@@ -273,7 +324,7 @@ def _color_delegator(parent): # htest #

`

273

324

`"'x', '''x''', "x", """x"""\n"

`

274

325

`"r'x', u'x', R'x', U'x', f'x', F'x'\n"

`

275

326

`"fr'x', Fr'x', fR'x', FR'x', rf'x', rF'x', Rf'x', RF'x'\n"

`

276

``

`-

"b'x',B'x', br'x',Br'x',bR'x',BR'x', rb'x'.rB'x',Rb'x',RB'x'\n"

`

``

327

`+

"b'x',B'x', br'x',Br'x',bR'x',BR'x', rb'x', rB'x',Rb'x',RB'x'\n"

`

277

328

`"# Invalid combinations of legal characters should be half colored.\n"

`

278

329

`"ur'x', ru'x', uf'x', fu'x', UR'x', ufr'x', rfu'x', xf'x', fx'x'\n"

`

279

330

` )

`