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

Shortcuts on this page

r m x   toggle line displays

j k   next/prev highlighted chunk

0   (zero) top of page

1   (one) first highlighted chunk

174 statements  

1""" 

2Filters that accept a `Application` as argument. 

3""" 

4 

5from __future__ import annotations 

6 

7from typing import TYPE_CHECKING, cast 

8 

9from prompt_toolkit.application.current import get_app 

10from prompt_toolkit.cache import memoized 

11from prompt_toolkit.enums import EditingMode 

12 

13from .base import Condition 

14 

15if TYPE_CHECKING: 

16 from prompt_toolkit.layout.layout import FocusableElement 

17 

18 

19__all__ = [ 

20 "has_arg", 

21 "has_completions", 

22 "completion_is_selected", 

23 "has_focus", 

24 "buffer_has_focus", 

25 "has_selection", 

26 "has_suggestion", 

27 "has_validation_error", 

28 "is_done", 

29 "is_read_only", 

30 "is_multiline", 

31 "renderer_height_is_known", 

32 "in_editing_mode", 

33 "in_paste_mode", 

34 "vi_mode", 

35 "vi_navigation_mode", 

36 "vi_insert_mode", 

37 "vi_insert_multiple_mode", 

38 "vi_replace_mode", 

39 "vi_selection_mode", 

40 "vi_waiting_for_text_object_mode", 

41 "vi_digraph_mode", 

42 "vi_recording_macro", 

43 "emacs_mode", 

44 "emacs_insert_mode", 

45 "emacs_selection_mode", 

46 "shift_selection_mode", 

47 "is_searching", 

48 "control_is_searchable", 

49 "vi_search_direction_reversed", 

50] 

51 

52 

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

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

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

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

57# still refer to each instance. 

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

59 """ 

60 Enable when this buffer has the focus. 

61 """ 

62 from prompt_toolkit.buffer import Buffer 

63 from prompt_toolkit.layout import walk 

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

65 from prompt_toolkit.layout.controls import UIControl 

66 

67 if isinstance(value, str): 

68 

69 def test() -> bool: 

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

71 

72 elif isinstance(value, Buffer): 

73 

74 def test() -> bool: 

75 return get_app().current_buffer == value 

76 

77 elif isinstance(value, UIControl): 

78 

79 def test() -> bool: 

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

81 

82 else: 

83 value = to_container(value) 

84 

85 if isinstance(value, Window): 

86 

87 def test() -> bool: 

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

89 

90 else: 

91 

92 def test() -> bool: 

93 # Consider focused when any window inside this container is 

94 # focused. 

95 current_window = get_app().layout.current_window 

96 

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

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

99 return True 

100 return False 

101 

102 @Condition 

103 def has_focus_filter() -> bool: 

104 return test() 

105 

106 return has_focus_filter 

107 

108 

109@Condition 

110def buffer_has_focus() -> bool: 

111 """ 

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

113 """ 

114 return get_app().layout.buffer_has_focus 

115 

116 

117@Condition 

118def has_selection() -> bool: 

119 """ 

120 Enable when the current buffer has a selection. 

121 """ 

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

123 

124 

125@Condition 

126def has_suggestion() -> bool: 

127 """ 

128 Enable when the current buffer has a suggestion. 

129 """ 

130 buffer = get_app().current_buffer 

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

132 

133 

134@Condition 

135def has_completions() -> bool: 

136 """ 

137 Enable when the current buffer has completions. 

138 """ 

139 state = get_app().current_buffer.complete_state 

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

141 

142 

143@Condition 

144def completion_is_selected() -> bool: 

145 """ 

146 True when the user selected a completion. 

147 """ 

148 complete_state = get_app().current_buffer.complete_state 

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

150 

151 

152@Condition 

153def is_read_only() -> bool: 

154 """ 

155 True when the current buffer is read only. 

156 """ 

157 return get_app().current_buffer.read_only() 

158 

159 

160@Condition 

161def is_multiline() -> bool: 

162 """ 

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

164 """ 

165 return get_app().current_buffer.multiline() 

166 

167 

168@Condition 

169def has_validation_error() -> bool: 

170 "Current buffer has validation error." 

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

172 

173 

174@Condition 

175def has_arg() -> bool: 

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

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

178 

179 

180@Condition 

181def is_done() -> bool: 

182 """ 

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

184 """ 

185 return get_app().is_done 

186 

187 

188@Condition 

189def renderer_height_is_known() -> bool: 

190 """ 

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

192 

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

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

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

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

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

198 """ 

199 return get_app().renderer.height_is_known 

200 

201 

202@memoized() 

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

204 """ 

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

206 """ 

207 

208 @Condition 

209 def in_editing_mode_filter() -> bool: 

210 return get_app().editing_mode == editing_mode 

211 

212 return in_editing_mode_filter 

213 

214 

215@Condition 

216def in_paste_mode() -> bool: 

217 return get_app().paste_mode() 

218 

219 

220@Condition 

221def vi_mode() -> bool: 

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

223 

224 

225@Condition 

226def vi_navigation_mode() -> bool: 

227 """ 

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

229 """ 

230 from prompt_toolkit.key_binding.vi_state import InputMode 

231 

232 app = get_app() 

233 

234 if ( 

235 app.editing_mode != EditingMode.VI 

236 or app.vi_state.operator_func 

237 or app.vi_state.waiting_for_digraph 

238 or app.current_buffer.selection_state 

239 ): 

240 return False 

241 

242 return ( 

243 app.vi_state.input_mode == InputMode.NAVIGATION 

244 or app.vi_state.temporary_navigation_mode 

245 or app.current_buffer.read_only() 

246 ) 

247 

248 

249@Condition 

250def vi_insert_mode() -> bool: 

251 from prompt_toolkit.key_binding.vi_state import InputMode 

252 

253 app = get_app() 

254 

255 if ( 

256 app.editing_mode != EditingMode.VI 

257 or app.vi_state.operator_func 

258 or app.vi_state.waiting_for_digraph 

259 or app.current_buffer.selection_state 

260 or app.vi_state.temporary_navigation_mode 

261 or app.current_buffer.read_only() 

262 ): 

263 return False 

264 

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

266 

267 

268@Condition 

269def vi_insert_multiple_mode() -> bool: 

270 from prompt_toolkit.key_binding.vi_state import InputMode 

271 

272 app = get_app() 

273 

274 if ( 

275 app.editing_mode != EditingMode.VI 

276 or app.vi_state.operator_func 

277 or app.vi_state.waiting_for_digraph 

278 or app.current_buffer.selection_state 

279 or app.vi_state.temporary_navigation_mode 

280 or app.current_buffer.read_only() 

281 ): 

282 return False 

283 

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

285 

286 

287@Condition 

288def vi_replace_mode() -> bool: 

289 from prompt_toolkit.key_binding.vi_state import InputMode 

290 

291 app = get_app() 

292 

293 if ( 

294 app.editing_mode != EditingMode.VI 

295 or app.vi_state.operator_func 

296 or app.vi_state.waiting_for_digraph 

297 or app.current_buffer.selection_state 

298 or app.vi_state.temporary_navigation_mode 

299 or app.current_buffer.read_only() 

300 ): 

301 return False 

302 

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

304 

305 

306@Condition 

307def vi_replace_single_mode() -> bool: 

308 from prompt_toolkit.key_binding.vi_state import InputMode 

309 

310 app = get_app() 

311 

312 if ( 

313 app.editing_mode != EditingMode.VI 

314 or app.vi_state.operator_func 

315 or app.vi_state.waiting_for_digraph 

316 or app.current_buffer.selection_state 

317 or app.vi_state.temporary_navigation_mode 

318 or app.current_buffer.read_only() 

319 ): 

320 return False 

321 

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

323 

324 

325@Condition 

326def vi_selection_mode() -> bool: 

327 app = get_app() 

328 if app.editing_mode != EditingMode.VI: 

329 return False 

330 

331 return bool(app.current_buffer.selection_state) 

332 

333 

334@Condition 

335def vi_waiting_for_text_object_mode() -> bool: 

336 app = get_app() 

337 if app.editing_mode != EditingMode.VI: 

338 return False 

339 

340 return app.vi_state.operator_func is not None 

341 

342 

343@Condition 

344def vi_digraph_mode() -> bool: 

345 app = get_app() 

346 if app.editing_mode != EditingMode.VI: 

347 return False 

348 

349 return app.vi_state.waiting_for_digraph 

350 

351 

352@Condition 

353def vi_recording_macro() -> bool: 

354 "When recording a Vi macro." 

355 app = get_app() 

356 if app.editing_mode != EditingMode.VI: 

357 return False 

358 

359 return app.vi_state.recording_register is not None 

360 

361 

362@Condition 

363def emacs_mode() -> bool: 

364 "When the Emacs bindings are active." 

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

366 

367 

368@Condition 

369def emacs_insert_mode() -> bool: 

370 app = get_app() 

371 if ( 

372 app.editing_mode != EditingMode.EMACS 

373 or app.current_buffer.selection_state 

374 or app.current_buffer.read_only() 

375 ): 

376 return False 

377 return True 

378 

379 

380@Condition 

381def emacs_selection_mode() -> bool: 

382 app = get_app() 

383 return bool( 

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

385 ) 

386 

387 

388@Condition 

389def shift_selection_mode() -> bool: 

390 app = get_app() 

391 return bool( 

392 app.current_buffer.selection_state 

393 and app.current_buffer.selection_state.shift_mode 

394 ) 

395 

396 

397@Condition 

398def is_searching() -> bool: 

399 "When we are searching." 

400 app = get_app() 

401 return app.layout.is_searching 

402 

403 

404@Condition 

405def control_is_searchable() -> bool: 

406 "When the current UIControl is searchable." 

407 from prompt_toolkit.layout.controls import BufferControl 

408 

409 control = get_app().layout.current_control 

410 

411 return ( 

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

413 ) 

414 

415 

416@Condition 

417def vi_search_direction_reversed() -> bool: 

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

419 return get_app().reverse_vi_search_direction()