diff options
| author | Martin Bielik <mx.bielik@gmail.com> | 2023-12-02 23:07:03 +0100 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2023-12-02 23:07:03 +0100 |
| commit | af1036be541f6743e2cd3b4c692ac5dcaa156354 (patch) | |
| tree | 64771c8307d3040ae779e03937f4eefe7d1fbc12 /py | |
| parent | c190089fc11985bbaff51362d8a00fbfff133796 (diff) | |
| parent | 1ca4e82b0435c7d65f65e535271f958a1021a5b2 (diff) | |
| download | vim-ai-af1036be541f6743e2cd3b4c692ac5dcaa156354.tar.gz | |
Merge pull request #64 from cposture/fix-visual-selection
fix selection include extra content when the user is in visual mode
Diffstat (limited to '')
| -rw-r--r-- | py/chat.py | 3 | ||||
| -rw-r--r-- | py/complete.py | 3 | ||||
| -rw-r--r-- | py/utils.py | 31 |
3 files changed, 33 insertions, 4 deletions
@@ -52,6 +52,7 @@ initial_messages = parse_chat_messages(initial_prompt) chat_content = vim.eval('trim(join(getline(1, "$"), "\n"))') chat_messages = parse_chat_messages(chat_content) +is_selection = vim.eval("l:is_selection") messages = initial_messages + chat_messages @@ -75,7 +76,7 @@ try: printDebug("[chat] response: {}", resp) return resp['choices'][0]['delta'].get('content', '') text_chunks = map(map_chunk, response) - render_text_chunks(text_chunks) + render_text_chunks(text_chunks, is_selection) vim.command("normal! a\n\n>>> user\n\n") vim.command("redraw") diff --git a/py/complete.py b/py/complete.py index 8386c09..ede0aea 100644 --- a/py/complete.py +++ b/py/complete.py @@ -9,6 +9,7 @@ openai_options = make_openai_options(config_options) http_options = make_http_options(config_options) prompt = vim.eval("l:prompt").strip() +is_selection = vim.eval("l:is_selection") def complete_engine(prompt): request = { @@ -51,7 +52,7 @@ try: print('Completing...') vim.command("redraw") text_chunks = engines[engine](prompt) - render_text_chunks(text_chunks) + render_text_chunks(text_chunks, is_selection) clear_echo_message() except BaseException as error: handle_completion_error(error) diff --git a/py/utils.py b/py/utils.py index 4e638e2..b5ede7f 100644 --- a/py/utils.py +++ b/py/utils.py @@ -62,14 +62,41 @@ def make_http_options(options): 'enable_auth': bool(int(options['enable_auth'])), } -def render_text_chunks(chunks): +# During text manipulation in Vim's visual mode, we utilize "normal! c" command. This command deletes the highlighted text, +# immediately followed by entering insert mode where it generates desirable text. + +# Normally, Vim contemplates the position of the first character in selection to decide whether to place the entered text +# before or after the cursor. For instance, if the given line is "abcd", and "abc" is selected for deletion and "1234" is +# written in its place, the result is as expected "1234d" rather than "d1234". However, if "bc" is chosen for deletion, the +# achieved output is "a1234d", whereas "1234ad" is not. + +# Despite this, post Vim script's execution of "normal! c", it takes an exit immediately returning to the normal mode. This +# might trigger a potential misalignment issue especially when the most extreme left character is the line’s second character. + +# To avoid such pitfalls, the method "need_insert_before_cursor" checks not only the selection status, but also the character +# at the first position of the highlighting. If the selection is off or the first position is not the second character in the line, +# it determines no need for prefixing the cursor. +def need_insert_before_cursor(is_selection): + if is_selection == False: + return False + pos = vim.eval("getpos(\"'<\")[1:2]") + if not isinstance(pos, list) or len(pos) != 2: + raise ValueError("Unexpected getpos value, it should be a list with two elements") + return pos[1] == "1" + +def render_text_chunks(chunks, is_selection): generating_text = False full_text = '' + insert_before_cursor = need_insert_before_cursor(is_selection) for text in chunks: if not text.strip() and not generating_text: continue # trim newlines from the beginning generating_text = True - vim.command("normal! a" + text) + if insert_before_cursor: + vim.command("normal! i" + text) + insert_before_cursor = False + else: + vim.command("normal! a" + text) vim.command("undojoin") vim.command("redraw") full_text += text |