Skip to content

Commit e6c8bf1

Browse files
authored
Added a Completer that throttles superfluous calls
1 parent 6695411 commit e6c8bf1

File tree

1 file changed

+41
-0
lines changed
  • src/prompt_toolkit/completion

1 file changed

+41
-0
lines changed

src/prompt_toolkit/completion/base.py

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
"ThreadedCompleter",
1717
"DummyCompleter",
1818
"DynamicCompleter",
19+
"ThrottledCompleter",
1920
"CompleteEvent",
2021
"ConditionalCompleter",
2122
"merge_completers",
@@ -316,6 +317,46 @@ def __repr__(self) -> str:
316317
return f"DynamicCompleter({self.get_completer!r} -> {self.get_completer()!r})"
317318

318319

320+
class ThrottledCompleter(Completer):
321+
"""
322+
Completer that throttles completion requests to prevent rapid successive calls.
323+
324+
:param completer: :class:`.Completer` instance.
325+
:param delay: Delay in seconds between completions. Default is 0.3.
326+
"""
327+
328+
def __init__(self, completer: Completer, delay: float = 0.3):
329+
self.completer = completer
330+
self.delay = delay
331+
self._last_completion_time = 0
332+
self._semaphore = asyncio.Semaphore(1)
333+
334+
def get_completions(
335+
self, document: Document, complete_event: CompleteEvent
336+
) -> Iterable[Completion]:
337+
"""Get completions without throttling."""
338+
yield from self.completer.get_completions(document, complete_event)
339+
340+
async def get_completions_async(
341+
self, document: Document, complete_event: CompleteEvent
342+
) -> AsyncGenerator[Completion, None]:
343+
"""Get completions asynchronously, applying throttle delay."""
344+
async with self._semaphore:
345+
current_time = asyncio.get_running_loop().time()
346+
time_since_last_completion = current_time - self._last_completion_time
347+
348+
if time_since_last_completion < self.delay:
349+
await asyncio.sleep(self.delay - time_since_last_completion)
350+
351+
self._last_completion_time = asyncio.get_running_loop().time()
352+
353+
async with aclosing(
354+
self.completer.get_completions_async(document, complete_event)
355+
) as async_generator:
356+
async for item in async_generator:
357+
yield item
358+
359+
319360
class ConditionalCompleter(Completer):
320361
"""
321362
Wrapper around any other completer that will enable/disable the completions

0 commit comments

Comments
 (0)