Skip to content

Commit da8a744

Browse files
committed
Enable quick file referencing using the @ sign by supporting search values and implementing Tab key completion in the chat input
1 parent 5473c18 commit da8a744

9 files changed

Lines changed: 76 additions & 12 deletions

File tree

‎packages/ui/src/components/editor/panel/ChatInput/ChatInput.tsx‎

Lines changed: 29 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ export type ChatInputProps = {
2222
on_caret_position_change: (caret_position: number) => void
2323
is_web_mode: boolean
2424
on_search_click: () => void
25-
on_at_sign_click: () => void
25+
on_at_sign_click: (search_value?: string) => void
2626
on_hash_sign_click: () => void
2727
on_curly_braces_click: () => void
2828
caret_position_to_set?: number
@@ -99,6 +99,32 @@ export const ChatInput: React.FC<ChatInputProps> = (props) => {
9999
props.is_web_mode
100100
])
101101

102+
const custom_handle_key_down = (
103+
e: React.KeyboardEvent<HTMLTextAreaElement>
104+
) => {
105+
if (e.key === 'Tab' && !e.shiftKey) {
106+
const textarea = e.currentTarget
107+
const value = textarea.value
108+
const selection_start = textarea.selectionStart
109+
110+
if (selection_start > 0) {
111+
const text_before_cursor = value.substring(0, selection_start)
112+
if (
113+
text_before_cursor.trim() !== '' &&
114+
!/\s$/.test(text_before_cursor)
115+
) {
116+
e.preventDefault()
117+
const match = text_before_cursor.match(/(\S+)$/)
118+
if (match) {
119+
props.on_at_sign_click(match[1])
120+
return
121+
}
122+
}
123+
}
124+
}
125+
handle_key_down(e)
126+
}
127+
102128
return (
103129
<div className={styles.container}>
104130
{props.has_active_selection && props.is_in_code_completions_mode && (
@@ -146,7 +172,7 @@ export const ChatInput: React.FC<ChatInputProps> = (props) => {
146172
placeholder={placeholder}
147173
value={props.value}
148174
onChange={handle_input_change}
149-
onKeyDown={handle_key_down}
175+
onKeyDown={custom_handle_key_down}
150176
onSelect={handle_select}
151177
autoFocus
152178
className={styles.textarea}
@@ -170,7 +196,7 @@ export const ChatInput: React.FC<ChatInputProps> = (props) => {
170196
}}
171197
>
172198
<button
173-
onClick={props.on_at_sign_click}
199+
onClick={() => props.on_at_sign_click()}
174200
className={cn(styles['footer__left__button'])}
175201
title="Reference file"
176202
>

‎packages/ui/src/components/editor/panel/modals/Modal/Modal.module.scss‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
display: flex;
88
align-items: center;
99
justify-content: center;
10-
padding-bottom: var(--padding-24px) var(--padding-24px) var(--padding-30px)
10+
padding: var(--padding-24px) var(--padding-24px) var(--padding-30px)
1111
var(--padding-24px);
1212

1313
&::before {

‎packages/ui/src/components/editor/panel/modals/StageFilesModal/StageFilesModal.module.scss‎

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,9 +6,8 @@
66
&__item {
77
display: flex;
88
align-items: center;
9-
gap: var(--padding-8px);
9+
gap: var(--padding-6px);
1010
cursor: pointer;
11-
font-size: var(--vscode-font-size);
1211

1312
&__details {
1413
overflow: hidden;
@@ -18,6 +17,7 @@
1817

1918
&__path {
2019
padding-left: var(--padding-6px);
20+
font-size: var(--font-size-12px);
2121
color: var(--vscode-descriptionForeground);
2222
}
2323
}

‎packages/ui/src/components/editor/panel/modals/StageFilesModal/StageFilesModal.tsx‎

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,17 @@ export const StageFilesModal: React.FC<Props> = (props) => {
2121
}
2222
}
2323

24+
const handle_toggle_select_all = (is_checked: boolean) => {
25+
if (is_checked) {
26+
set_selected_files(props.files)
27+
} else {
28+
set_selected_files([])
29+
}
30+
}
31+
32+
const all_selected =
33+
props.files.length > 0 && selected_files.length === props.files.length
34+
2435
const handle_stage = () => {
2536
props.on_stage(selected_files)
2637
}
@@ -31,6 +42,15 @@ export const StageFilesModal: React.FC<Props> = (props) => {
3142
content_max_height="30vh"
3243
content_slot={
3344
<div className={styles.files}>
45+
<label className={styles.files__item}>
46+
<Checkbox
47+
checked={all_selected}
48+
on_change={handle_toggle_select_all}
49+
/>
50+
<div className={styles.files__item__details}>
51+
<strong>Select all</strong>
52+
</div>
53+
</label>
3454
{props.files.map((file) => {
3555
const last_slash_index = file.lastIndexOf('/')
3656
const filename =

‎packages/vscode/src/views/panel/backend/message-handlers/handle-at-sign-quick-pick.ts‎

Lines changed: 18 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ import { natural_sort } from '@/utils/natural-sort'
88

99
const at_sign_quick_pick = async (params: {
1010
workspace_provider: WorkspaceProvider
11+
search_value?: string
1112
}): Promise<string | undefined> => {
1213
const checked_paths = params.workspace_provider.get_all_checked_paths()
1314
if (checked_paths.length == 0) {
@@ -46,6 +47,14 @@ const at_sign_quick_pick = async (params: {
4647
fullPath: normalized_path
4748
}
4849
})
50+
.filter((item) => {
51+
if (params.search_value) {
52+
const search_lower = params.search_value.toLowerCase()
53+
const full_path_lower = item.fullPath.toLowerCase()
54+
return full_path_lower.includes(search_lower)
55+
}
56+
return true
57+
})
4958

5059
quick_pick_items.sort((a, b) => natural_sort(a.fullPath, b.fullPath))
5160

@@ -64,10 +73,12 @@ const at_sign_quick_pick = async (params: {
6473
}
6574

6675
export const handle_at_sign_quick_pick = async (
67-
provider: ViewProvider
76+
provider: ViewProvider,
77+
search_value?: string
6878
): Promise<void> => {
6979
const replacement = await at_sign_quick_pick({
70-
workspace_provider: provider.workspace_provider
80+
workspace_provider: provider.workspace_provider,
81+
search_value: search_value
7182
})
7283

7384
if (!replacement) {
@@ -77,6 +88,11 @@ export const handle_at_sign_quick_pick = async (
7788
return
7889
}
7990

91+
if (search_value) {
92+
provider.add_text_at_cursor_position(replacement, search_value.length)
93+
return
94+
}
95+
8096
let current_text = ''
8197

8298
const mode =

‎packages/vscode/src/views/panel/backend/panel-provider.ts‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -430,7 +430,7 @@ export class ViewProvider implements vscode.WebviewViewProvider {
430430
} else if (message.command == 'GET_VERSION') {
431431
handle_get_version(this)
432432
} else if (message.command == 'SHOW_AT_SIGN_QUICK_PICK') {
433-
await handle_at_sign_quick_pick(this)
433+
await handle_at_sign_quick_pick(this, message.search_value)
434434
} else if (message.command == 'SHOW_HASH_SIGN_QUICK_PICK') {
435435
await handle_hash_sign_quick_pick(
436436
this,

‎packages/vscode/src/views/panel/frontend/Main/Main.tsx‎

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -500,10 +500,11 @@ export const Main: React.FC<Props> = (props) => {
500500
}
501501
}
502502

503-
const handle_at_sign_click = () => {
503+
const handle_at_sign_click = (search_value?: string) => {
504504
post_message(props.vscode, {
505505
command: 'SHOW_AT_SIGN_QUICK_PICK',
506-
is_for_code_completions: is_in_code_completions_mode
506+
is_for_code_completions: is_in_code_completions_mode,
507+
search_value
507508
})
508509
}
509510

‎packages/vscode/src/views/panel/frontend/Main/MainView/MainView.tsx‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@ type Props = {
3939
on_show_home: () => void
4040
on_search_click: () => void
4141
on_create_preset: () => void
42-
on_at_sign_click: () => void
42+
on_at_sign_click: (search_value?: string) => void
4343
on_hash_sign_click: () => void
4444
on_curly_braces_click: () => void
4545
on_quick_action_click: (command: string) => void

‎packages/vscode/src/views/panel/types/messages.ts‎

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -189,6 +189,7 @@ export interface CodeCompletionMessage extends BaseMessage {
189189

190190
export interface ShowAtSignQuickPickMessage extends BaseMessage {
191191
command: 'SHOW_AT_SIGN_QUICK_PICK'
192+
search_value?: string
192193
is_for_code_completions: boolean
193194
}
194195

0 commit comments

Comments
 (0)