summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNate Sesti <sestinj@gmail.com>2023-07-02 20:14:27 -0700
committerNate Sesti <sestinj@gmail.com>2023-07-02 20:14:27 -0700
commita606c13ca75f0c9177b3d04f20dcf7211d81f083 (patch)
treea10e65936bf6d519e7edc877b66000c90e4bb519
parent36577b8e94809da47a540499132774a0fe2c085d (diff)
downloadsncontinue-a606c13ca75f0c9177b3d04f20dcf7211d81f083.tar.gz
sncontinue-a606c13ca75f0c9177b3d04f20dcf7211d81f083.tar.bz2
sncontinue-a606c13ca75f0c9177b3d04f20dcf7211d81f083.zip
finishing up explicit context
-rw-r--r--continuedev/src/continuedev/core/autopilot.py17
-rw-r--r--continuedev/src/continuedev/models/filesystem.py16
-rw-r--r--continuedev/src/continuedev/models/main.py5
-rw-r--r--continuedev/src/continuedev/steps/chat.py2
-rw-r--r--extension/react-app/src/components/ComboBox.tsx83
-rw-r--r--extension/react-app/src/components/ContinueButton.tsx1
-rw-r--r--extension/react-app/src/components/PillButton.tsx66
7 files changed, 131 insertions, 59 deletions
diff --git a/continuedev/src/continuedev/core/autopilot.py b/continuedev/src/continuedev/core/autopilot.py
index b9e61c63..1a77ca64 100644
--- a/continuedev/src/continuedev/core/autopilot.py
+++ b/continuedev/src/continuedev/core/autopilot.py
@@ -139,21 +139,22 @@ class Autopilot(ContinueBaseModel):
for rif in range_in_files:
rif.filepath = os.path.relpath(rif.filepath, workspace_path)
+ old_ranges = self._highlighted_ranges + range_in_files
new_ranges = []
- for rif in range_in_files:
+
+ while len(old_ranges) > 0:
+ old_range = old_ranges.pop(0)
found_overlap = False
- for i in range(len(self._highlighted_ranges)):
- hr = self._highlighted_ranges[i]
- if hr.filepath == rif.filepath and hr.range.overlaps_with(rif.range):
- new_ranges.append(rif.union(hr))
+ for i in range(len(new_ranges)):
+ if old_range.filepath == new_ranges[i].filepath and old_range.range.overlaps_with(new_ranges[i].range):
+ new_ranges[i] = old_range.union(new_ranges[i])
found_overlap = True
- self._highlighted_ranges.pop(i)
break
if not found_overlap:
- new_ranges.append(rif)
+ new_ranges.append(old_range)
- self._highlighted_ranges += new_ranges
+ self._highlighted_ranges = new_ranges
await self.update_subscribers()
_step_depth: int = 0
diff --git a/continuedev/src/continuedev/models/filesystem.py b/continuedev/src/continuedev/models/filesystem.py
index fc1c3f13..df0b15d7 100644
--- a/continuedev/src/continuedev/models/filesystem.py
+++ b/continuedev/src/continuedev/models/filesystem.py
@@ -40,21 +40,15 @@ class RangeInFileWithContents(RangeInFile):
assert first.filepath == second.filepath
- # Calculate the start and end positions of the overlap
- overlap_start = max(first.range.start,
- second.range.start) - first.range.start
- overlap_end = min(first.range.end, second.range.end) - \
- first.range.start
-
- # Calculate the new contents by removing the overlap
- union_contents = first.contents[:overlap_start] + \
- second.contents[overlap_start:overlap_end] + \
- first.contents[overlap_end:]
+ # Calculate union of contents
+ num_overlapping_lines = first.range.end.line - second.range.start.line + 1
+ union_lines = first.contents.splitlines()[:-num_overlapping_lines] + \
+ second.contents.splitlines()
return RangeInFileWithContents(
filepath=first.filepath,
range=first.range.union(second.range),
- contents=union_contents
+ contents="\n".join(union_lines)
)
@staticmethod
diff --git a/continuedev/src/continuedev/models/main.py b/continuedev/src/continuedev/models/main.py
index 101be4ae..fa736772 100644
--- a/continuedev/src/continuedev/models/main.py
+++ b/continuedev/src/continuedev/models/main.py
@@ -43,6 +43,11 @@ class Position(BaseModel):
def from_end_of_file(contents: str) -> "Position":
return Position.from_index(contents, len(contents))
+ def to_index(self, string: str) -> int:
+ """Convert line and character to index in string"""
+ lines = string.splitlines()
+ return sum(map(len, lines[:self.line])) + self.character
+
class Range(BaseModel):
"""A range in a file. 0-indexed."""
diff --git a/continuedev/src/continuedev/steps/chat.py b/continuedev/src/continuedev/steps/chat.py
index 8494563b..b10ec3d7 100644
--- a/continuedev/src/continuedev/steps/chat.py
+++ b/continuedev/src/continuedev/steps/chat.py
@@ -106,7 +106,7 @@ class RunTerminalCommandStep(Step):
class ViewDirectoryTreeStep(Step):
name: str = "View Directory Tree"
- description: str = "View the directory tree to learn which folder and files exist."
+ description: str = "View the directory tree to learn which folder and files exist. You should always do this before adding new files."
async def describe(self, models: Models) -> Coroutine[Any, Any, Coroutine[str, None, None]]:
return f"Viewed the directory tree."
diff --git a/extension/react-app/src/components/ComboBox.tsx b/extension/react-app/src/components/ComboBox.tsx
index 34027a42..f299c3a2 100644
--- a/extension/react-app/src/components/ComboBox.tsx
+++ b/extension/react-app/src/components/ComboBox.tsx
@@ -9,6 +9,7 @@ import {
} from ".";
import CodeBlock from "./CodeBlock";
import { RangeInFile } from "../../../src/client";
+import PillButton from "./PillButton";
const mainInputFontSize = 16;
@@ -22,27 +23,9 @@ const ContextDropdown = styled.div`
border-bottom-left-radius: ${defaultBorderRadius};
/* border: 1px solid white; */
border-top: none;
- margin-left: 8px;
- margin-right: 8px;
- margin-top: -12px;
+ margin: 8px;
outline: 1px solid orange;
-`;
-
-const PillButton = styled.button`
- display: flex;
- justify-content: space-between;
- align-items: center;
- border: none;
- color: white;
- background-color: gray;
- border-radius: 50px;
- padding: 5px 10px;
- margin: 5px 0;
- cursor: pointer;
-
- &:hover {
- background-color: ${buttonColor};
- }
+ z-index: 5;
`;
const MainTextInput = styled.textarea`
@@ -118,7 +101,9 @@ const ComboBox = React.forwardRef((props: ComboBoxProps, ref) => {
// The position of the current command you are typing now, so the one that will be appended to history once you press enter
const [positionInHistory, setPositionInHistory] = React.useState<number>(0);
const [items, setItems] = React.useState(props.items);
- const [showContextDropdown, setShowContextDropdown] = React.useState(false);
+ const [hoveringButton, setHoveringButton] = React.useState(false);
+ const [hoveringContextDropdown, setHoveringContextDropdown] =
+ React.useState(false);
const [highlightedCodeSections, setHighlightedCodeSections] = React.useState(
props.highlightedCodeSections || [
{
@@ -184,7 +169,7 @@ const ComboBox = React.forwardRef((props: ComboBoxProps, ref) => {
300
).toString()}px`;
- setShowContextDropdown(target.value.endsWith("@"));
+ // setShowContextDropdown(target.value.endsWith("@"));
},
onKeyDown: (event) => {
if (event.key === "Enter" && event.shiftKey) {
@@ -256,22 +241,11 @@ const ComboBox = React.forwardRef((props: ComboBoxProps, ref) => {
))}
</Ul>
</div>
- <ContextDropdown hidden={!showContextDropdown}>
- <p>Highlight code to include as context:</p>
- {highlightedCodeSections.map((section, idx) => (
- <>
- <p>{section.filepath}</p>
- <CodeBlock showCopy={false} key={idx}>
- {section.contents}
- </CodeBlock>
- </>
- ))}
- </ContextDropdown>
- <div className="px-2">
+ <div className="px-2 flex gap-2 items-center flex-wrap">
{highlightedCodeSections.map((section, idx) => (
<PillButton
- onClick={() => {
- console.log("delete context item", idx);
+ title={section.filepath}
+ onDelete={() => {
if (props.deleteContextItem) {
props.deleteContextItem(idx);
}
@@ -281,11 +255,42 @@ const ComboBox = React.forwardRef((props: ComboBoxProps, ref) => {
return newSections;
});
}}
- >
- {section.filepath}
- </PillButton>
+ onHover={(val: boolean) => {
+ if (val) {
+ setHoveringButton(val);
+ } else {
+ setTimeout(() => {
+ setHoveringButton(val);
+ }, 100);
+ }
+ }}
+ />
))}
+
+ <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."}
+ </span>
</div>
+ <ContextDropdown
+ onMouseEnter={() => {
+ setHoveringContextDropdown(true);
+ }}
+ onMouseLeave={() => {
+ setHoveringContextDropdown(false);
+ }}
+ hidden={!hoveringContextDropdown && !hoveringButton}
+ >
+ {highlightedCodeSections.map((section, idx) => (
+ <>
+ <p>{section.filepath}</p>
+ <CodeBlock showCopy={false} key={idx}>
+ {section.contents}
+ </CodeBlock>
+ </>
+ ))}
+ </ContextDropdown>
</>
);
});
diff --git a/extension/react-app/src/components/ContinueButton.tsx b/extension/react-app/src/components/ContinueButton.tsx
index ef6719b7..5295799a 100644
--- a/extension/react-app/src/components/ContinueButton.tsx
+++ b/extension/react-app/src/components/ContinueButton.tsx
@@ -6,6 +6,7 @@ import { RootStore } from "../redux/store";
let StyledButton = styled(Button)`
margin: auto;
+ margin-top: 8px;
display: grid;
grid-template-columns: 30px 1fr;
align-items: center;
diff --git a/extension/react-app/src/components/PillButton.tsx b/extension/react-app/src/components/PillButton.tsx
new file mode 100644
index 00000000..33451db5
--- /dev/null
+++ b/extension/react-app/src/components/PillButton.tsx
@@ -0,0 +1,66 @@
+import { useState } from "react";
+import styled from "styled-components";
+import { defaultBorderRadius } from ".";
+
+const Button = styled.button`
+ border: none;
+ color: white;
+ background-color: transparent;
+ border: 1px solid white;
+ border-radius: ${defaultBorderRadius};
+ padding: 3px 6px;
+
+ &:hover {
+ background-color: white;
+ color: black;
+ }
+`;
+
+interface PillButtonProps {
+ onHover?: (arg0: boolean) => void;
+ onDelete?: () => void;
+ title: string;
+}
+
+const PillButton = (props: PillButtonProps) => {
+ const [isHovered, setIsHovered] = useState(false);
+ return (
+ <Button
+ onMouseEnter={() => {
+ setIsHovered(true);
+ if (props.onHover) {
+ props.onHover(true);
+ }
+ }}
+ onMouseLeave={() => {
+ setIsHovered(false);
+ if (props.onHover) {
+ props.onHover(false);
+ }
+ }}
+ >
+ <div
+ style={{ display: "grid", gridTemplateColumns: "1fr auto", gap: "4px" }}
+ >
+ <span>{props.title}</span>
+ <span
+ style={{
+ cursor: "pointer",
+ color: "red",
+ borderLeft: "1px solid black",
+ paddingLeft: "4px",
+ }}
+ hidden={!isHovered}
+ onClick={() => {
+ props.onDelete?.();
+ props.onHover?.(false);
+ }}
+ >
+ X
+ </span>
+ </div>
+ </Button>
+ );
+};
+
+export default PillButton;