diff options
-rw-r--r-- | continuedev/src/continuedev/core/autopilot.py | 11 | ||||
-rw-r--r-- | continuedev/src/continuedev/core/main.py | 1 | ||||
-rw-r--r-- | continuedev/src/continuedev/server/gui.py | 7 | ||||
-rw-r--r-- | continuedev/src/continuedev/steps/core/core.py | 83 | ||||
-rw-r--r-- | extension/package.json | 10 | ||||
-rw-r--r-- | extension/react-app/src/components/ComboBox.tsx | 27 | ||||
-rw-r--r-- | extension/react-app/src/components/PillButton.tsx | 27 | ||||
-rw-r--r-- | extension/react-app/src/components/UserInputContainer.tsx | 4 | ||||
-rw-r--r-- | extension/react-app/src/hooks/ContinueGUIClientProtocol.ts | 2 | ||||
-rw-r--r-- | extension/react-app/src/hooks/useContinueGUIProtocol.ts | 4 | ||||
-rw-r--r-- | extension/react-app/src/tabs/gui.tsx | 6 | ||||
-rw-r--r-- | extension/src/commands.ts | 4 | ||||
-rw-r--r-- | extension/src/continueIdeClient.ts | 38 | ||||
-rw-r--r-- | extension/src/diffs.ts | 114 | ||||
-rw-r--r-- | extension/src/lang-server/codeLens.ts | 40 |
15 files changed, 286 insertions, 92 deletions
diff --git a/continuedev/src/continuedev/core/autopilot.py b/continuedev/src/continuedev/core/autopilot.py index 313ceded..29be3b79 100644 --- a/continuedev/src/continuedev/core/autopilot.py +++ b/continuedev/src/continuedev/core/autopilot.py @@ -69,7 +69,8 @@ class Autopilot(ContinueBaseModel): user_input_queue=self._main_user_input_queue, default_model=self.continue_sdk.config.default_model, highlighted_ranges=self._highlighted_ranges, - slash_commands=self.get_available_slash_commands() + slash_commands=self.get_available_slash_commands(), + adding_highlighted_code=self._adding_highlighted_code, ) def get_available_slash_commands(self) -> List[Dict]: @@ -140,8 +141,12 @@ class Autopilot(ContinueBaseModel): await self._run_singular_step(step) _highlighted_ranges: List[RangeInFileWithContents] = [] + _adding_highlighted_code: bool = False async def handle_highlighted_code(self, range_in_files: List[RangeInFileWithContents]): + if not self._adding_highlighted_code: + return + workspace_path = self.continue_sdk.ide.workspace_directory for rif in range_in_files: rif.filepath = os.path.basename(rif.filepath) @@ -186,6 +191,10 @@ class Autopilot(ContinueBaseModel): self._highlighted_ranges = kept_ranges await self.update_subscribers() + async def toggle_adding_highlighted_code(self): + self._adding_highlighted_code = not self._adding_highlighted_code + await self.update_subscribers() + async def _run_singular_step(self, step: "Step", is_future_step: bool = False) -> Coroutine[Observation, None, None]: # Allow config to set disallowed steps if step.__class__.__name__ in self.continue_sdk.config.disallowed_steps: diff --git a/continuedev/src/continuedev/core/main.py b/continuedev/src/continuedev/core/main.py index 8bad09d1..28fd964e 100644 --- a/continuedev/src/continuedev/core/main.py +++ b/continuedev/src/continuedev/core/main.py @@ -207,6 +207,7 @@ class FullState(ContinueBaseModel): default_model: str highlighted_ranges: List[RangeInFileWithContents] slash_commands: List[SlashCommandDescription] + adding_highlighted_code: bool class ContinueSDK: diff --git a/continuedev/src/continuedev/server/gui.py b/continuedev/src/continuedev/server/gui.py index 4e960f7c..fa573b37 100644 --- a/continuedev/src/continuedev/server/gui.py +++ b/continuedev/src/continuedev/server/gui.py @@ -85,6 +85,8 @@ class GUIProtocolServer(AbstractGUIProtocolServer): self.on_delete_at_index(data["index"]) elif message_type == "delete_context_at_indices": self.on_delete_context_at_indices(data["indices"]) + elif message_type == "toggle_adding_highlighted_code": + self.on_toggle_adding_highlighted_code() except Exception as e: print(e) @@ -128,6 +130,11 @@ class GUIProtocolServer(AbstractGUIProtocolServer): self.session.autopilot.delete_context_at_indices(indices) ) + def on_toggle_adding_highlighted_code(self): + asyncio.create_task( + self.session.autopilot.toggle_adding_highlighted_code() + ) + @router.websocket("/ws") async def websocket_endpoint(websocket: WebSocket, session: Session = Depends(websocket_session)): diff --git a/continuedev/src/continuedev/steps/core/core.py b/continuedev/src/continuedev/steps/core/core.py index b9f0da35..c74412ba 100644 --- a/continuedev/src/continuedev/steps/core/core.py +++ b/continuedev/src/continuedev/steps/core/core.py @@ -286,6 +286,7 @@ class DefaultModelEditCodeStep(Step): return "```" in line or "<modified_code_to_edit>" in line or "<file_prefix>" in line or "</file_prefix>" in line or "<file_suffix>" in line or "</file_suffix>" in line or "<user_request>" in line or "</user_request>" in line or "<code_to_edit>" in line async def stream_rif(self, rif: RangeInFileWithContents, sdk: ContinueSDK): + await sdk.ide.saveFile(rif.filepath) full_file_contents = await sdk.ide.readFile(rif.filepath) file_prefix, contents, file_suffix, model_to_use = await self.get_prompt_parts( @@ -295,6 +296,17 @@ class DefaultModelEditCodeStep(Step): prompt = self.compile_prompt(file_prefix, contents, file_suffix, sdk) full_file_contents_lines = full_file_contents.split("\n") + async def sendDiffUpdate(lines: List[str], sdk: ContinueSDK): + nonlocal full_file_contents_lines, rif + + completion = "\n".join(lines) + + full_prefix_lines = full_file_contents_lines[:rif.range.start.line] + full_suffix_lines = full_file_contents_lines[rif.range.end.line + 1:] + new_file_contents = "\n".join( + full_prefix_lines) + "\n" + completion + "\n" + "\n".join(full_suffix_lines) + await sdk.ide.showDiff(rif.filepath, new_file_contents) + # Important state variables # ------------------------- original_lines = [] if rif.contents == "" else rif.contents.split("\n") @@ -435,16 +447,16 @@ class DefaultModelEditCodeStep(Step): chunk_lines.pop() # because this will be an empty string else: unfinished_line = chunk_lines.pop() - lines.extend(chunk_lines) + lines.extend(map(lambda l: common_whitespace + l, chunk_lines)) + + if True: + await sendDiffUpdate(lines, sdk) # Deal with newly accumulated lines for line in chunk_lines: # Trailing whitespace doesn't matter line = line.rstrip() - # Add the common whitespace that was removed before prompting - line = common_whitespace + line - # Lines that should signify the end of generation if self.is_end_line(line): break @@ -463,7 +475,9 @@ class DefaultModelEditCodeStep(Step): break # If none of the above, insert the line! - await handle_generated_line(line) + if False: + await handle_generated_line(line) + completion_lines_covered += 1 current_line_in_file += 1 @@ -475,34 +489,37 @@ class DefaultModelEditCodeStep(Step): completion_lines_covered += 1 current_line_in_file += 1 - # If the current block isn't empty, add that suggestion - if len(current_block_lines) > 0: - # We have a chance to back-track here for blank lines that are repeats of the end of the original - # Don't want to have the same ending in both the original and the generated, can just leave it there - num_to_remove = 0 - for i in range(-1, -len(current_block_lines) - 1, -1): - if len(original_lines_below_previous_blocks) == 0: - break - if current_block_lines[i] == original_lines_below_previous_blocks[-1]: - num_to_remove += 1 - original_lines_below_previous_blocks.pop() - else: - break - current_block_lines = current_block_lines[:- - num_to_remove] if num_to_remove > 0 else current_block_lines - - # It's also possible that some lines match at the beginning of the block - # while len(current_block_lines) > 0 and len(original_lines_below_previous_blocks) > 0 and current_block_lines[0] == original_lines_below_previous_blocks[0]: - # current_block_lines.pop(0) - # original_lines_below_previous_blocks.pop(0) - # current_block_start += 1 - - await sdk.ide.showSuggestion(FileEdit( - filepath=rif.filepath, - range=Range.from_shorthand( - current_block_start, 0, current_block_start + len(original_lines_below_previous_blocks), 0), - replacement="\n".join(current_block_lines) - )) + await sendDiffUpdate(lines, sdk) + + if False: + # If the current block isn't empty, add that suggestion + if len(current_block_lines) > 0: + # We have a chance to back-track here for blank lines that are repeats of the end of the original + # Don't want to have the same ending in both the original and the generated, can just leave it there + num_to_remove = 0 + for i in range(-1, -len(current_block_lines) - 1, -1): + if len(original_lines_below_previous_blocks) == 0: + break + if current_block_lines[i] == original_lines_below_previous_blocks[-1]: + num_to_remove += 1 + original_lines_below_previous_blocks.pop() + else: + break + current_block_lines = current_block_lines[:- + num_to_remove] if num_to_remove > 0 else current_block_lines + + # It's also possible that some lines match at the beginning of the block + # while len(current_block_lines) > 0 and len(original_lines_below_previous_blocks) > 0 and current_block_lines[0] == original_lines_below_previous_blocks[0]: + # current_block_lines.pop(0) + # original_lines_below_previous_blocks.pop(0) + # current_block_start += 1 + + await sdk.ide.showSuggestion(FileEdit( + filepath=rif.filepath, + range=Range.from_shorthand( + current_block_start, 0, current_block_start + len(original_lines_below_previous_blocks), 0), + replacement="\n".join(current_block_lines) + )) # Record the completion completion = "\n".join(lines) diff --git a/extension/package.json b/extension/package.json index 52e7f891..d4850671 100644 --- a/extension/package.json +++ b/extension/package.json @@ -87,6 +87,16 @@ "title": "Reject Suggestion" }, { + "command": "continue.acceptDiff", + "category": "Continue", + "title": "Accept Diff" + }, + { + "command": "continue.rejectDiff", + "category": "Continue", + "title": "Reject Diff" + }, + { "command": "continue.acceptAllSuggestions", "category": "Continue", "title": "Accept All Suggestions" diff --git a/extension/react-app/src/components/ComboBox.tsx b/extension/react-app/src/components/ComboBox.tsx index 3e1f3e16..97f5b57e 100644 --- a/extension/react-app/src/components/ComboBox.tsx +++ b/extension/react-app/src/components/ComboBox.tsx @@ -11,7 +11,12 @@ import CodeBlock from "./CodeBlock"; import { RangeInFile } from "../../../src/client"; import PillButton from "./PillButton"; import HeaderButtonWithText from "./HeaderButtonWithText"; -import { Trash, LockClosed, LockOpen } from "@styled-icons/heroicons-outline"; +import { + Trash, + LockClosed, + LockOpen, + Plus, +} from "@styled-icons/heroicons-outline"; // #region styled components const mainInputFontSize = 16; @@ -100,6 +105,8 @@ interface ComboBoxProps { highlightedCodeSections: (RangeInFile & { contents: string })[]; deleteContextItems: (indices: number[]) => void; onTogglePin: () => void; + onToggleAddContext: () => void; + addingHighlightedCode: boolean; } const ComboBox = React.forwardRef((props: ComboBoxProps, ref) => { @@ -249,6 +256,19 @@ const ComboBox = React.forwardRef((props: ComboBoxProps, ref) => { </Ul> </div> <div className="px-2 flex gap-2 items-center flex-wrap"> + {highlightedCodeSections.length === 0 && ( + <HeaderButtonWithText + text={ + props.addingHighlightedCode ? "Adding Context" : "Add Context" + } + onClick={() => { + props.onToggleAddContext(); + }} + inverted={props.addingHighlightedCode} + > + <Plus size="1.6em" /> + </HeaderButtonWithText> + )} {highlightedCodeSections.length > 0 && ( <> <HeaderButtonWithText @@ -305,9 +325,8 @@ const ComboBox = React.forwardRef((props: ComboBoxProps, ref) => { ))} <span className="text-trueGray-400 ml-auto mr-4 text-xs"> - Highlight code to include as context.{" "} - {highlightedCodeSections.length === 0 && - "Otherwise using entire currently open file."} + Highlight code to include as context. Currently open file included by + default. {highlightedCodeSections.length === 0 && ""} </span> </div> <ContextDropdown diff --git a/extension/react-app/src/components/PillButton.tsx b/extension/react-app/src/components/PillButton.tsx index 2352c3ad..5a02c6b2 100644 --- a/extension/react-app/src/components/PillButton.tsx +++ b/extension/react-app/src/components/PillButton.tsx @@ -15,6 +15,8 @@ const Button = styled.button` background-color: white; color: black; } + + cursor: pointer; `; interface PillButtonProps { @@ -39,26 +41,13 @@ const PillButton = (props: PillButtonProps) => { props.onHover(false); } }} + onClick={() => { + if (props.onDelete) { + props.onDelete(); + } + }} > - <div - style={{ display: "grid", gridTemplateColumns: "1fr auto", gap: "4px" }} - > - <span - style={{ - cursor: "pointer", - color: "red", - borderRight: "1px solid black", - paddingRight: "4px", - }} - onClick={() => { - props.onDelete?.(); - props.onHover?.(false); - }} - > - <XMark style={{ padding: "0px" }} size="1.2em" strokeWidth="2px" /> - </span> - <span>{props.title}</span> - </div> + {props.title} </Button> ); }; diff --git a/extension/react-app/src/components/UserInputContainer.tsx b/extension/react-app/src/components/UserInputContainer.tsx index 44fdba38..a72f6098 100644 --- a/extension/react-app/src/components/UserInputContainer.tsx +++ b/extension/react-app/src/components/UserInputContainer.tsx @@ -14,7 +14,7 @@ interface UserInputContainerProps { historyNode: HistoryNode; } -const StyledDiv = styled.div` +const StyledDiv = styled.div<{ hidden: boolean }>` background-color: rgb(50 50 50); padding: 8px; padding-left: 16px; @@ -24,6 +24,8 @@ const StyledDiv = styled.div` font-size: 13px; display: flex; align-items: center; + visibility: ${(props) => (props.hidden ? "hidden" : "visible")}; + height: ${(props) => (props.hidden ? "0px" : "auto")}; `; const UserInputContainer = (props: UserInputContainerProps) => { diff --git a/extension/react-app/src/hooks/ContinueGUIClientProtocol.ts b/extension/react-app/src/hooks/ContinueGUIClientProtocol.ts index 96ea7ab3..f123bb2b 100644 --- a/extension/react-app/src/hooks/ContinueGUIClientProtocol.ts +++ b/extension/react-app/src/hooks/ContinueGUIClientProtocol.ts @@ -22,6 +22,8 @@ abstract class AbstractContinueGUIClientProtocol { abstract deleteAtIndex(index: number): void; abstract deleteContextAtIndices(indices: number[]): void; + + abstract toggleAddingHighlightedCode(): void; } export default AbstractContinueGUIClientProtocol; diff --git a/extension/react-app/src/hooks/useContinueGUIProtocol.ts b/extension/react-app/src/hooks/useContinueGUIProtocol.ts index e950387c..49f200ae 100644 --- a/extension/react-app/src/hooks/useContinueGUIProtocol.ts +++ b/extension/react-app/src/hooks/useContinueGUIProtocol.ts @@ -74,6 +74,10 @@ class ContinueGUIClientProtocol extends AbstractContinueGUIClientProtocol { deleteContextAtIndices(indices: number[]) { this.messenger.send("delete_context_at_indices", { indices }); } + + toggleAddingHighlightedCode(): void { + this.messenger.send("toggle_adding_highlighted_code", {}); + } } export default ContinueGUIClientProtocol; diff --git a/extension/react-app/src/tabs/gui.tsx b/extension/react-app/src/tabs/gui.tsx index bbf0b126..851045d5 100644 --- a/extension/react-app/src/tabs/gui.tsx +++ b/extension/react-app/src/tabs/gui.tsx @@ -71,6 +71,7 @@ function GUI(props: GUIProps) { const [waitingForSteps, setWaitingForSteps] = useState(false); const [userInputQueue, setUserInputQueue] = useState<string[]>([]); const [highlightedRanges, setHighlightedRanges] = useState([]); + const [addingHighlightedCode, setAddingHighlightedCode] = useState(false); const [availableSlashCommands, setAvailableSlashCommands] = useState< { name: string; description: string }[] >([]); @@ -157,6 +158,7 @@ function GUI(props: GUIProps) { setHistory(state.history); setHighlightedRanges(state.highlighted_ranges); setUserInputQueue(state.user_input_queue); + setAddingHighlightedCode(state.adding_highlighted_code); setAvailableSlashCommands( state.slash_commands.map((c: any) => { return { @@ -361,6 +363,10 @@ function GUI(props: GUIProps) { onTogglePin={() => { setPinned((prev: boolean) => !prev); }} + onToggleAddContext={() => { + client?.toggleAddingHighlightedCode(); + }} + addingHighlightedCode={addingHighlightedCode} /> <ContinueButton onClick={onMainTextInput} /> </TopGUIDiv> diff --git a/extension/src/commands.ts b/extension/src/commands.ts index 8072353b..4414a171 100644 --- a/extension/src/commands.ts +++ b/extension/src/commands.ts @@ -12,6 +12,8 @@ import { acceptAllSuggestionsCommand, rejectAllSuggestionsCommand, } from "./suggestions"; + +import { acceptDiffCommand, rejectDiffCommand } from "./diffs"; import * as bridge from "./bridge"; import { debugPanelWebview } from "./debugPanel"; import { sendTelemetryEvent, TelemetryEvent } from "./telemetry"; @@ -51,6 +53,8 @@ const commandsMap: { [command: string]: (...args: any) => any } = { "continue.suggestionUp": suggestionUpCommand, "continue.acceptSuggestion": acceptSuggestionCommand, "continue.rejectSuggestion": rejectSuggestionCommand, + "continue.acceptDiff": acceptDiffCommand, + "continue.rejectDiff": rejectDiffCommand, "continue.acceptAllSuggestions": acceptAllSuggestionsCommand, "continue.rejectAllSuggestions": rejectAllSuggestionsCommand, "continue.focusContinueInput": async () => { diff --git a/extension/src/continueIdeClient.ts b/extension/src/continueIdeClient.ts index b9969858..90547edc 100644 --- a/extension/src/continueIdeClient.ts +++ b/extension/src/continueIdeClient.ts @@ -15,6 +15,10 @@ import { import { FileEditWithFullContents } from "../schema/FileEditWithFullContents"; import fs = require("fs"); import { WebsocketMessenger } from "./util/messenger"; +import * as path from "path"; +import * as os from "os"; +import { diffManager } from "./diffs"; + class IdeProtocolClient { private messenger: WebsocketMessenger | null = null; private readonly context: vscode.ExtensionContext; @@ -239,40 +243,8 @@ class IdeProtocolClient { ); } - contentProvider: vscode.Disposable | null = null; - showDiff(filepath: string, replacement: string) { - const myProvider = new (class - implements vscode.TextDocumentContentProvider - { - onDidChangeEmitter = new vscode.EventEmitter<vscode.Uri>(); - onDidChange = this.onDidChangeEmitter.event; - provideTextDocumentContent = (uri: vscode.Uri) => { - return replacement; - }; - })(); - this.contentProvider = vscode.workspace.registerTextDocumentContentProvider( - "continueDiff", - myProvider - ); - - // Call the event fire - const diffFilename = `continueDiff://${filepath}`; - myProvider.onDidChangeEmitter.fire(vscode.Uri.parse(diffFilename)); - - const leftUri = vscode.Uri.file(filepath); - const rightUri = vscode.Uri.parse(diffFilename); - const title = "Continue Diff"; - vscode.commands - .executeCommand("vscode.diff", leftUri, rightUri, title) - .then( - () => { - console.log("Diff view opened successfully"); - }, - (error) => { - console.error("Error opening diff view:", error); - } - ); + diffManager.writeDiff(filepath, replacement); } openFile(filepath: string) { diff --git a/extension/src/diffs.ts b/extension/src/diffs.ts new file mode 100644 index 00000000..19ec80ab --- /dev/null +++ b/extension/src/diffs.ts @@ -0,0 +1,114 @@ +import * as os from "os"; +import * as path from "path"; +import * as fs from "fs"; +import * as vscode from "vscode"; + +interface DiffInfo { + originalFilepath: string; + newFilepath: string; + editor?: vscode.TextEditor; +} + +export const DIFF_DIRECTORY = path.join(os.homedir(), ".continue", "diffs"); + +class DiffManager { + // Create a temporary file in the global .continue directory which displays the updated version + // Doing this because virtual files are read-only + private diffs: Map<string, DiffInfo> = new Map(); + + constructor() { + // Make sure the diff directory exists + if (!fs.existsSync(DIFF_DIRECTORY)) { + fs.mkdirSync(DIFF_DIRECTORY, { + recursive: true, + }); + } + } + + private escapeFilepath(filepath: string): string { + return filepath.replace(/\\/g, "_").replace(/\//g, "_"); + } + + private openDiffEditor( + originalFilepath: string, + newFilepath: string, + newContent: string + ): vscode.TextEditor { + const rightUri = vscode.Uri.parse(newFilepath); + const leftUri = vscode.Uri.file(originalFilepath); + const title = "Continue Diff"; + vscode.commands.executeCommand("vscode.diff", leftUri, rightUri, title); + + const editor = vscode.window.activeTextEditor; + if (!editor) { + throw new Error("No active text editor found for Continue Diff"); + } + return editor; + } + + writeDiff(originalFilepath: string, newContent: string): string { + // Create or update existing diff + const newFilepath = path.join( + DIFF_DIRECTORY, + this.escapeFilepath(originalFilepath) + ); + fs.writeFileSync(newFilepath, newContent); + + // Open the diff editor if this is a new diff + if (!this.diffs.has(newFilepath)) { + const diffInfo: DiffInfo = { + originalFilepath, + newFilepath, + }; + diffInfo.editor = this.openDiffEditor( + originalFilepath, + newFilepath, + newContent + ); + this.diffs.set(newFilepath, diffInfo); + } + return newFilepath; + } + + cleanUpDiff(diffInfo: DiffInfo) { + // Close the editor, remove the record, delete the file + if (diffInfo.editor) { + vscode.window.showTextDocument(diffInfo.editor.document); + vscode.commands.executeCommand("workbench.action.closeActiveEditor"); + } + this.diffs.delete(diffInfo.newFilepath); + fs.unlinkSync(diffInfo.newFilepath); + } + + acceptDiff(newFilepath: string) { + // Get the diff info, copy new file to original, then delete from record and close the corresponding editor + const diffInfo = this.diffs.get(newFilepath); + if (!diffInfo) { + return; + } + fs.writeFileSync( + diffInfo.originalFilepath, + fs.readFileSync(diffInfo.newFilepath) + ); + this.cleanUpDiff(diffInfo); + } + + rejectDiff(newFilepath: string) { + const diffInfo = this.diffs.get(newFilepath); + if (!diffInfo) { + return; + } + + this.cleanUpDiff(diffInfo); + } +} + +export const diffManager = new DiffManager(); + +export async function acceptDiffCommand(newFilepath: string) { + diffManager.acceptDiff(newFilepath); +} + +export async function rejectDiffCommand(newFilepath: string) { + diffManager.rejectDiff(newFilepath); +} diff --git a/extension/src/lang-server/codeLens.ts b/extension/src/lang-server/codeLens.ts index 3bd4f153..08435a3b 100644 --- a/extension/src/lang-server/codeLens.ts +++ b/extension/src/lang-server/codeLens.ts @@ -1,6 +1,8 @@ import * as vscode from "vscode"; import { editorToSuggestions, editorSuggestionsLocked } from "../suggestions"; - +import * as path from "path"; +import * as os from "os"; +import { DIFF_DIRECTORY } from "../diffs"; class SuggestionsCodeLensProvider implements vscode.CodeLensProvider { public provideCodeLenses( document: vscode.TextDocument, @@ -60,15 +62,51 @@ class SuggestionsCodeLensProvider implements vscode.CodeLensProvider { } } +class DiffViewerCodeLensProvider implements vscode.CodeLensProvider { + public provideCodeLenses( + document: vscode.TextDocument, + token: vscode.CancellationToken + ): vscode.CodeLens[] | Thenable<vscode.CodeLens[]> { + if (path.dirname(document.uri.fsPath) !== DIFF_DIRECTORY) { + return []; + } else { + const codeLenses: vscode.CodeLens[] = []; + const range = new vscode.Range(0, 0, 0, 0); + codeLenses.push( + new vscode.CodeLens(range, { + title: "Accept ✅", + command: "continue.acceptDiff", + arguments: [document.uri.fsPath], + }), + new vscode.CodeLens(range, { + title: "Reject ❌", + command: "continue.rejectDiff", + arguments: [document.uri.fsPath], + }) + ); + return codeLenses; + } + } +} + +let diffsCodeLensDisposable: vscode.Disposable | undefined = undefined; let suggestionsCodeLensDisposable: vscode.Disposable | undefined = undefined; export function registerAllCodeLensProviders(context: vscode.ExtensionContext) { if (suggestionsCodeLensDisposable) { suggestionsCodeLensDisposable.dispose(); } + if (diffsCodeLensDisposable) { + diffsCodeLensDisposable.dispose(); + } suggestionsCodeLensDisposable = vscode.languages.registerCodeLensProvider( "*", new SuggestionsCodeLensProvider() ); + diffsCodeLensDisposable = vscode.languages.registerCodeLensProvider( + "*", + new DiffViewerCodeLensProvider() + ); context.subscriptions.push(suggestionsCodeLensDisposable); + context.subscriptions.push(diffsCodeLensDisposable); } |