Coverage for /pythoncovmergedfiles/medio/medio/usr/local/lib/python3.8/site-packages/prompt_toolkit/filters/app.py: 45%

173 statements  

« prev     ^ index     » next       coverage.py v7.4.4, created at 2024-04-20 06:09 +0000

1""" 

2Filters that accept a `Application` as argument. 

3""" 

4from __future__ import annotations 

5 

6from typing import TYPE_CHECKING, cast 

7 

8from prompt_toolkit.application.current import get_app 

9from prompt_toolkit.cache import memoized 

10from prompt_toolkit.enums import EditingMode 

11 

12from .base import Condition 

13 

14if TYPE_CHECKING: 

15 from prompt_toolkit.layout.layout import FocusableElement 

16 

17 

18__all__ = [ 

19 "has_arg", 

20 "has_completions", 

21 "completion_is_selected", 

22 "has_focus", 

23 "buffer_has_focus", 

24 "has_selection", 

25 "has_suggestion", 

26 "has_validation_error", 

27 "is_done", 

28 "is_read_only", 

29 "is_multiline", 

30 "renderer_height_is_known", 

31 "in_editing_mode", 

32 "in_paste_mode", 

33 "vi_mode", 

34 "vi_navigation_mode", 

35 "vi_insert_mode", 

36 "vi_insert_multiple_mode", 

37 "vi_replace_mode", 

38 "vi_selection_mode", 

39 "vi_waiting_for_text_object_mode", 

40 "vi_digraph_mode", 

41 "vi_recording_macro", 

42 "emacs_mode", 

43 "emacs_insert_mode", 

44 "emacs_selection_mode", 

45 "shift_selection_mode", 

46 "is_searching", 

47 "control_is_searchable", 

48 "vi_search_direction_reversed", 

49] 

50 

51 

52# NOTE: `has_focus` below should *not* be `memoized`. It can reference any user 

53# control. For instance, if we would continuously create new 

54# `PromptSession` instances, then previous instances won't be released, 

55# because this memoize (which caches results in the global scope) will 

56# still refer to each instance. 

57def has_focus(value: FocusableElement) -> Condition: 

58 """ 

59 Enable when this buffer has the focus. 

60 """ 

61 from prompt_toolkit.buffer import Buffer 

62 from prompt_toolkit.layout import walk 

63 from prompt_toolkit.layout.containers import Container, Window, to_container 

64 from prompt_toolkit.layout.controls import UIControl 

65 

66 if isinstance(value, str): 

67 

68 def test() -> bool: 

69 return get_app().current_buffer.name == value 

70 

71 elif isinstance(value, Buffer): 

72 

73 def test() -> bool: 

74 return get_app().current_buffer == value 

75 

76 elif isinstance(value, UIControl): 

77 

78 def test() -> bool: 

79 return get_app().layout.current_control == value 

80 

81 else: 

82 value = to_container(value) 

83 

84 if isinstance(value, Window): 

85 

86 def test() -> bool: 

87 return get_app().layout.current_window == value 

88 

89 else: 

90 

91 def test() -> bool: 

92 # Consider focused when any window inside this container is 

93 # focused. 

94 current_window = get_app().layout.current_window 

95 

96 for c in walk(cast(Container, value)): 

97 if isinstance(c, Window) and c == current_window: 

98 return True 

99 return False 

100 

101 @Condition 

102 def has_focus_filter() -> bool: 

103 return test() 

104 

105 return has_focus_filter 

106 

107 

108@Condition 

109def buffer_has_focus() -> bool: 

110 """ 

111 Enabled when the currently focused control is a `BufferControl`. 

112 """ 

113 return get_app().layout.buffer_has_focus 

114 

115 

116@Condition 

117def has_selection() -> bool: 

118 """ 

119 Enable when the current buffer has a selection. 

120 """ 

121 return bool(get_app().current_buffer.selection_state) 

122 

123 

124@Condition 

125def has_suggestion() -> bool: 

126 """ 

127 Enable when the current buffer has a suggestion. 

128 """ 

129 buffer = get_app().current_buffer 

130 return buffer.suggestion is not None and buffer.suggestion.text != "" 

131 

132 

133@Condition 

134def has_completions() -> bool: 

135 """ 

136 Enable when the current buffer has completions. 

137 """ 

138 state = get_app().current_buffer.complete_state 

139 return state is not None and len(state.completions) > 0 

140 

141 

142@Condition 

143def completion_is_selected() -> bool: 

144 """ 

145 True when the user selected a completion. 

146 """ 

147 complete_state = get_app().current_buffer.complete_state 

148 return complete_state is not None and complete_state.current_completion is not None 

149 

150 

151@Condition 

152def is_read_only() -> bool: 

153 """ 

154 True when the current buffer is read only. 

155 """ 

156 return get_app().current_buffer.read_only() 

157 

158 

159@Condition 

160def is_multiline() -> bool: 

161 """ 

162 True when the current buffer has been marked as multiline. 

163 """ 

164 return get_app().current_buffer.multiline() 

165 

166 

167@Condition 

168def has_validation_error() -> bool: 

169 "Current buffer has validation error." 

170 return get_app().current_buffer.validation_error is not None 

171 

172 

173@Condition 

174def has_arg() -> bool: 

175 "Enable when the input processor has an 'arg'." 

176 return get_app().key_processor.arg is not None 

177 

178 

179@Condition 

180def is_done() -> bool: 

181 """ 

182 True when the CLI is returning, aborting or exiting. 

183 """ 

184 return get_app().is_done 

185 

186 

187@Condition 

188def renderer_height_is_known() -> bool: 

189 """ 

190 Only True when the renderer knows it's real height. 

191 

192 (On VT100 terminals, we have to wait for a CPR response, before we can be 

193 sure of the available height between the cursor position and the bottom of 

194 the terminal. And usually it's nicer to wait with drawing bottom toolbars 

195 until we receive the height, in order to avoid flickering -- first drawing 

196 somewhere in the middle, and then again at the bottom.) 

197 """ 

198 return get_app().renderer.height_is_known 

199 

200 

201@memoized() 

202def in_editing_mode(editing_mode: EditingMode) -> Condition: 

203 """ 

204 Check whether a given editing mode is active. (Vi or Emacs.) 

205 """ 

206 

207 @Condition 

208 def in_editing_mode_filter() -> bool: 

209 return get_app().editing_mode == editing_mode 

210 

211 return in_editing_mode_filter 

212 

213 

214@Condition 

215def in_paste_mode() -> bool: 

216 return get_app().paste_mode() 

217 

218 

219@Condition 

220def vi_mode() -> bool: 

221 return get_app().editing_mode == EditingMode.VI 

222 

223 

224@Condition 

225def vi_navigation_mode() -> bool: 

226 """ 

227 Active when the set for Vi navigation key bindings are active. 

228 """ 

229 from prompt_toolkit.key_binding.vi_state import InputMode 

230 

231 app = get_app() 

232 

233 if ( 

234 app.editing_mode != EditingMode.VI 

235 or app.vi_state.operator_func 

236 or app.vi_state.waiting_for_digraph 

237 or app.current_buffer.selection_state 

238 ): 

239 return False 

240 

241 return ( 

242 app.vi_state.input_mode == InputMode.NAVIGATION 

243 or app.vi_state.temporary_navigation_mode 

244 or app.current_buffer.read_only() 

245 ) 

246 

247 

248@Condition 

249def vi_insert_mode() -> bool: 

250 from prompt_toolkit.key_binding.vi_state import InputMode 

251 

252 app = get_app() 

253 

254 if ( 

255 app.editing_mode != EditingMode.VI 

256 or app.vi_state.operator_func 

257 or app.vi_state.waiting_for_digraph 

258 or app.current_buffer.selection_state 

259 or app.vi_state.temporary_navigation_mode 

260 or app.current_buffer.read_only() 

261 ): 

262 return False 

263 

264 return app.vi_state.input_mode == InputMode.INSERT 

265 

266 

267@Condition 

268def vi_insert_multiple_mode() -> bool: 

269 from prompt_toolkit.key_binding.vi_state import InputMode 

270 

271 app = get_app() 

272 

273 if ( 

274 app.editing_mode != EditingMode.VI 

275 or app.vi_state.operator_func 

276 or app.vi_state.waiting_for_digraph 

277 or app.current_buffer.selection_state 

278 or app.vi_state.temporary_navigation_mode 

279 or app.current_buffer.read_only() 

280 ): 

281 return False 

282 

283 return app.vi_state.input_mode == InputMode.INSERT_MULTIPLE 

284 

285 

286@Condition 

287def vi_replace_mode() -> bool: 

288 from prompt_toolkit.key_binding.vi_state import InputMode 

289 

290 app = get_app() 

291 

292 if ( 

293 app.editing_mode != EditingMode.VI 

294 or app.vi_state.operator_func 

295 or app.vi_state.waiting_for_digraph 

296 or app.current_buffer.selection_state 

297 or app.vi_state.temporary_navigation_mode 

298 or app.current_buffer.read_only() 

299 ): 

300 return False 

301 

302 return app.vi_state.input_mode == InputMode.REPLACE 

303 

304 

305@Condition 

306def vi_replace_single_mode() -> bool: 

307 from prompt_toolkit.key_binding.vi_state import InputMode 

308 

309 app = get_app() 

310 

311 if ( 

312 app.editing_mode != EditingMode.VI 

313 or app.vi_state.operator_func 

314 or app.vi_state.waiting_for_digraph 

315 or app.current_buffer.selection_state 

316 or app.vi_state.temporary_navigation_mode 

317 or app.current_buffer.read_only() 

318 ): 

319 return False 

320 

321 return app.vi_state.input_mode == InputMode.REPLACE_SINGLE 

322 

323 

324@Condition 

325def vi_selection_mode() -> bool: 

326 app = get_app() 

327 if app.editing_mode != EditingMode.VI: 

328 return False 

329 

330 return bool(app.current_buffer.selection_state) 

331 

332 

333@Condition 

334def vi_waiting_for_text_object_mode() -> bool: 

335 app = get_app() 

336 if app.editing_mode != EditingMode.VI: 

337 return False 

338 

339 return app.vi_state.operator_func is not None 

340 

341 

342@Condition 

343def vi_digraph_mode() -> bool: 

344 app = get_app() 

345 if app.editing_mode != EditingMode.VI: 

346 return False 

347 

348 return app.vi_state.waiting_for_digraph 

349 

350 

351@Condition 

352def vi_recording_macro() -> bool: 

353 "When recording a Vi macro." 

354 app = get_app() 

355 if app.editing_mode != EditingMode.VI: 

356 return False 

357 

358 return app.vi_state.recording_register is not None 

359 

360 

361@Condition 

362def emacs_mode() -> bool: 

363 "When the Emacs bindings are active." 

364 return get_app().editing_mode == EditingMode.EMACS 

365 

366 

367@Condition 

368def emacs_insert_mode() -> bool: 

369 app = get_app() 

370 if ( 

371 app.editing_mode != EditingMode.EMACS 

372 or app.current_buffer.selection_state 

373 or app.current_buffer.read_only() 

374 ): 

375 return False 

376 return True 

377 

378 

379@Condition 

380def emacs_selection_mode() -> bool: 

381 app = get_app() 

382 return bool( 

383 app.editing_mode == EditingMode.EMACS and app.current_buffer.selection_state 

384 ) 

385 

386 

387@Condition 

388def shift_selection_mode() -> bool: 

389 app = get_app() 

390 return bool( 

391 app.current_buffer.selection_state 

392 and app.current_buffer.selection_state.shift_mode 

393 ) 

394 

395 

396@Condition 

397def is_searching() -> bool: 

398 "When we are searching." 

399 app = get_app() 

400 return app.layout.is_searching 

401 

402 

403@Condition 

404def control_is_searchable() -> bool: 

405 "When the current UIControl is searchable." 

406 from prompt_toolkit.layout.controls import BufferControl 

407 

408 control = get_app().layout.current_control 

409 

410 return ( 

411 isinstance(control, BufferControl) and control.search_buffer_control is not None 

412 ) 

413 

414 

415@Condition 

416def vi_search_direction_reversed() -> bool: 

417 "When the '/' and '?' key bindings for Vi-style searching have been reversed." 

418 return get_app().reverse_vi_search_direction()