Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Provide option for tab to apply completion #390

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
99 changes: 99 additions & 0 deletions ptpython/key_bindings.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
from jedi import Interpreter
from prompt_toolkit.completion import CompleteEvent
from prompt_toolkit.application import get_app
from prompt_toolkit.document import Document
from prompt_toolkit.enums import DEFAULT_BUFFER
Expand All @@ -6,10 +8,13 @@
emacs_insert_mode,
emacs_mode,
has_focus,
has_completions,
completion_is_selected,
has_selection,
vi_insert_mode,
)
from prompt_toolkit.key_binding import KeyBindings
from prompt_toolkit.key_binding.key_processor import KeyPress
from prompt_toolkit.keys import Keys

from .utils import document_is_multiline_python
Expand Down Expand Up @@ -201,6 +206,100 @@ def _(event):
" Abort when Control-C has been pressed. "
event.app.exit(exception=KeyboardInterrupt, style="class:aborting")

def is_callable(text=""):
completions = Interpreter(text, [locals()]).complete()
match = next((i for i in completions if i.name == text), None)
return match.type in ("class", "function") if match else None

@Condition
def auto_complete_selected_option_on_tab():
return python_input.enable_auto_complete_selected_option_on_tab

@Condition
def auto_complete_top_option_on_enter():
return python_input.enable_auto_complete_top_option_on_enter

@Condition
def auto_complete_top_option_on_tab():
return python_input.enable_auto_complete_top_option_on_tab

@Condition
def auto_complete_only_option_on_tab():
return python_input.enable_auto_complete_only_option_on_tab

@Condition
def auto_complete_function_parentheses():
return python_input.enable_auto_complete_function_parentheses

insert_mode = vi_insert_mode | emacs_insert_mode
focused_insert = insert_mode & has_focus(DEFAULT_BUFFER)
shown_not_selected = has_completions & ~completion_is_selected

# apply selected completion option with enter
@handle('c-j', filter=focused_insert & completion_is_selected)
@handle("enter", filter=focused_insert & completion_is_selected)
def _(event):
b = event.current_buffer
completion = b.complete_state.current_completion
b.apply_completion(completion)
if python_input.enable_auto_complete_function_parentheses:
if is_callable(completion.text) or is_callable(b.document.get_word_under_cursor()):
b.insert_text("()")
b.cursor_left()

# apply selected completion option with tab
@handle("tab", filter=focused_insert & completion_is_selected & auto_complete_selected_option_on_tab)
@handle("c-space", filter=focused_insert & completion_is_selected & auto_complete_selected_option_on_tab)
def _(event):
b = event.current_buffer
completion = b.complete_state.current_completion
b.apply_completion(completion)
if python_input.enable_auto_complete_function_parentheses:
if is_callable(completion.text) or is_callable(b.document.get_word_under_cursor()):
b.insert_text("()")
b.cursor_left()

# apply first completion option with enter when completion menu is showing
@handle('c-j', filter=focused_insert & shown_not_selected & auto_complete_top_option_on_enter)
@handle("enter", filter=focused_insert & shown_not_selected & auto_complete_top_option_on_enter)
def _(event):
b = event.current_buffer
completion = b.complete_state.completions[0]
b.apply_completion(completion)
if python_input.enable_auto_complete_function_parentheses:
if is_callable(completion.text) or is_callable(b.document.get_word_under_cursor()):
b.insert_text("()")
b.cursor_left()

# apply first completion option with tab if completion menu is showing
@handle("tab", filter=focused_insert & shown_not_selected & auto_complete_top_option_on_tab)
@handle("c-space", filter=focused_insert & shown_not_selected & auto_complete_top_option_on_tab)
def _(event):
b = event.current_buffer
completion = b.complete_state.completions[0]
b.apply_completion(completion)
if python_input.enable_auto_complete_function_parentheses:
if is_callable(completion.text) or is_callable(b.document.get_word_under_cursor()):
b.insert_text("()")
b.cursor_left()

# apply completion if there is only one option, otherwise start completion
@handle("tab", filter=focused_insert & ~has_completions & auto_complete_only_option_on_tab)
@handle("c-space", filter=focused_insert & ~has_completions & auto_complete_only_option_on_tab)
def _(event):
b = event.current_buffer
complete_event = CompleteEvent(completion_requested=True)
completions = list(b.completer.get_completions(b.document, complete_event))
if len(completions) == 1:
completion = completions[0]
b.apply_completion(completion)
if python_input.enable_auto_complete_function_parentheses:
if is_callable(completion.text) or is_callable(b.document.get_word_under_cursor()):
b.insert_text("()")
b.cursor_left()
else:
b.start_completion(insert_common_part=True)

return bindings


Expand Down
5 changes: 5 additions & 0 deletions ptpython/python_input.py
Original file line number Diff line number Diff line change
Expand Up @@ -234,6 +234,11 @@ def __init__(
self.enable_system_bindings: bool = True
self.enable_input_validation: bool = True
self.enable_auto_suggest: bool = False
self.enable_auto_complete_on_tab: bool = False
self.enable_auto_complete_top_option_on_enter: bool = False
self.enable_auto_complete_top_option_on_tab: bool = False
self.enable_auto_complete_only_option_on_tab: bool = False
self.enable_auto_complete_function_parentheses: bool = False
self.enable_mouse_support: bool = False
self.enable_history_search: bool = False # When True, like readline, going
# back in history will filter the
Expand Down