forked from CopilotC-Nvim/CopilotChat.nvim
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathcopilot-plugin.py
More file actions
127 lines (107 loc) · 4.55 KB
/
Copy pathcopilot-plugin.py
File metadata and controls
127 lines (107 loc) · 4.55 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
import os
import time
import copilot
import dotenv
import prompts
import pynvim
dotenv.load_dotenv()
@pynvim.plugin
class CopilotChatPlugin(object):
def __init__(self, nvim: pynvim.Nvim):
self.nvim = nvim
self.copilot = copilot.Copilot(os.getenv("COPILOT_TOKEN"))
if self.copilot.github_token is None:
req = self.copilot.request_auth()
self.nvim.out_write(
f"Please visit {req['verification_uri']} and enter the code {req['user_code']}\n"
)
current_time = time.time()
wait_until = current_time + req["expires_in"]
while self.copilot.github_token is None:
self.copilot.poll_auth(req["device_code"])
time.sleep(req["interval"])
if time.time() > wait_until:
self.nvim.out_write("Timed out waiting for authentication\n")
return
self.nvim.out_write("Successfully authenticated with Copilot\n")
self.copilot.authenticate()
@pynvim.command("CopilotChat", nargs="1")
def copilotChat(self, args: list[str]):
if self.copilot.github_token is None:
self.nvim.out_write("Please authenticate with Copilot first\n")
return
# Start the spinner
self.nvim.exec_lua('require("CopilotChat.spinner").show()')
prompt = " ".join(args)
if prompt == "/fix":
prompt = prompts.FIX_SHORTCUT
elif prompt == "/test":
prompt = prompts.TEST_SHORTCUT
elif prompt == "/explain":
prompt = prompts.EXPLAIN_SHORTCUT
# Get code from the unnamed register
code = self.nvim.eval("getreg('\"')")
file_type = self.nvim.eval("expand('%')").split(".")[-1]
# Get the view option from the command
view_option = self.nvim.eval("g:copilot_chat_view_option")
def is_buffer_in_current_tab(buffer):
# check if the buffer is in the current tab.
# if so, switch to it
for window in self.nvim.current.tabpage.windows:
if window.buffer.number == buffer['bufnr']:
self.nvim.current.window = window
return True
return False
buffer_name = "CopilotChat"
existing_buffers = self.nvim.eval('getbufinfo()')
for buffer in existing_buffers:
if os.path.basename(buffer['name']) == buffer_name:
# If the buffer exists, switch to it
if is_buffer_in_current_tab(buffer):
# If the buffer is already in the current tab, switch to the window
break
if (buffer['bufnr'] != self.nvim.current.buffer.number
and view_option == "split"):
# open a split if the buffer is not the current one
self.nvim.command("vnew")
self.nvim.command('buffer {}'.format(buffer['bufnr']))
break
else:
# Create a new scratch buffer to hold the chat
if view_option == "split":
self.nvim.command("vnew")
else:
self.nvim.command("enew")
# Set the buffer type to nofile and hide it when it's not active
self.nvim.command("setlocal buftype=nofile bufhidden=hide noswapfile")
# Set filetype as markdown and wrap with linebreaks
self.nvim.command("setlocal filetype=markdown wrap linebreak")
self.nvim.command('file {}'.format(buffer_name))
# Get the current buffer
buf = self.nvim.current.buffer
self.nvim.api.buf_set_option(buf, "fileencoding", "utf-8")
# Add start separator
start_separator = f"""### User
{prompt}
### Copilot
"""
buf.append(start_separator.split("\n"), -1)
# Add chat messages
for token in self.copilot.ask(prompt, code, language=file_type):
buffer_lines = self.nvim.api.buf_get_lines(buf, 0, -1, 0)
last_line_row = len(buffer_lines) - 1
last_line = buffer_lines[-1]
last_line_col = len(last_line.encode("utf-8"))
self.nvim.api.buf_set_text(
buf,
last_line_row,
last_line_col,
last_line_row,
last_line_col,
token.split("\n"),
)
# Stop the spinner
self.nvim.exec_lua('require("CopilotChat.spinner").hide()')
# Add end separator
end_separator = "\n---\n"
buf.append(end_separator.split("\n"), -1)