Skip to content

Commit 09c4cd2

Browse files
feat: add strictness and selector UI
1 parent 1e065a4 commit 09c4cd2

File tree

4 files changed

+73
-3
lines changed

4 files changed

+73
-3
lines changed

src/types.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,8 @@ export interface SearchQuery {
3131
inputValue: string
3232
includeFile: string
3333
rewrite: string
34+
strictness: string
35+
selector: string
3436
}
3537

3638
export type SgSearch = {
Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
import { SearchInput } from './SearchInput'
2+
import { VSCodeDropdown, VSCodeOption } from '@vscode/webview-ui-toolkit/react'
3+
import { usePatternConfig } from '../../hooks/useQuery'
4+
import { useCallback } from 'react'
5+
6+
const titleStyle = {
7+
textOverflow: 'ellipsis',
8+
overflow: 'hidden',
9+
whiteSpace: 'nowrap',
10+
padding: '4px 0 0',
11+
fontSize: '11px',
12+
fontWeight: '400',
13+
lineHeight: '19px',
14+
}
15+
const NOOP = () => {}
16+
17+
export default function PatternConfig() {
18+
const [strictness, setStrictness] = usePatternConfig('strictness', 'smart')
19+
const [selector, setSelector] = usePatternConfig('selector', '')
20+
// biome-ignore lint/suspicious/noExplicitAny: onChange event has wrong type signature.
21+
const onStrictnessChange = useCallback(
22+
(e: any) => {
23+
const select = e.target as HTMLSelectElement
24+
setStrictness(select.value)
25+
},
26+
[setStrictness],
27+
)
28+
return (
29+
<div>
30+
<h4 style={titleStyle}>Selector</h4>
31+
<SearchInput
32+
isSingleLine={true}
33+
placeholder="sub-node kind to match"
34+
value={selector}
35+
onChange={setSelector}
36+
onKeyEnterUp={NOOP}
37+
/>
38+
<h4 style={titleStyle}>Strictness</h4>
39+
<VSCodeDropdown
40+
value={strictness}
41+
onChange={onStrictnessChange}
42+
style={{ width: '100%', zIndex: '2' }}
43+
>
44+
<VSCodeOption value="cst">Cst (ignore nothing)</VSCodeOption>
45+
<VSCodeOption value="smart">Smart (default option)</VSCodeOption>
46+
<VSCodeOption value="ast">Ast (ignore unnamed nodes)</VSCodeOption>
47+
<VSCodeOption value="relaxed">Relaxed (ignore comments)</VSCodeOption>
48+
<VSCodeOption value="signature">Signature (ignore text)</VSCodeOption>
49+
</VSCodeDropdown>
50+
</div>
51+
)
52+
}

src/webview/SearchSidebar/SearchWidgetContainer/SearchOptions.tsx

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import { VscEllipsis } from 'react-icons/vsc'
22
import IncludeFile from './IncludeFile'
3+
import PatternConfig from './PatternConfig'
34
import * as stylex from '@stylexjs/stylex'
45
import { useSearchOption, refreshResult } from '../../hooks/useQuery'
56

@@ -45,6 +46,7 @@ export default function SearchOptions() {
4546
refreshResult={refreshResult}
4647
/>
4748
{/* TODO: add file exclude*/}
49+
<PatternConfig />
4850
</div>
4951
)}
5052
</div>

src/webview/hooks/useQuery.tsx

Lines changed: 17 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { useEffect } from 'react'
1+
import { useEffect, useState } from 'react'
22
import { useLocalStorage, useDebounce, useBoolean } from 'react-use'
33
import { SearchQuery } from '../../types'
44
import { childPort } from '../postMessage'
@@ -9,11 +9,15 @@ import { postSearch } from './useSearch'
99

1010
const searchQuery: Record<keyof SearchQuery, string> = {
1111
inputValue: '',
12+
strictness: 'smart',
13+
selector: '',
1214
includeFile: '',
1315
rewrite: '',
1416
}
1517

16-
const LS_KEYS: Record<keyof SearchQuery, string> = {
18+
type PatternKeys = 'strictness' | 'selector'
19+
20+
const LS_KEYS: Record<Exclude<keyof SearchQuery, PatternKeys>, string> = {
1721
inputValue: 'ast-grep-search-panel-input-value',
1822
includeFile: 'ast-grep-search-panel-include-value',
1923
rewrite: 'ast-grep-search-panel-rewrite-value',
@@ -28,7 +32,7 @@ childPort.onMessage('clearSearchResults', () => {
2832
refreshResult()
2933
})
3034

31-
export function useSearchField(key: keyof SearchQuery) {
35+
export function useSearchField(key: keyof typeof LS_KEYS) {
3236
const [field = '', setField] = useLocalStorage(LS_KEYS[key], '')
3337
// this useEffect and useDebounce is silly
3438
useEffect(() => {
@@ -38,6 +42,16 @@ export function useSearchField(key: keyof SearchQuery) {
3842
return [field, setField] as const
3943
}
4044

45+
export function usePatternConfig(key: PatternKeys, defaultValue: string) {
46+
const [field, setField] = useState(defaultValue)
47+
// this useEffect and useDebounce is silly
48+
useEffect(() => {
49+
searchQuery[key] = field
50+
}, [field, key])
51+
useDebounce(refreshResult, 150, [field])
52+
return [field, setField] as const
53+
}
54+
4155
export function useSearchOption() {
4256
const [includeFile = '', setIncludeFile] = useSearchField('includeFile')
4357
const [showOptions, toggleOptions] = useBoolean(Boolean(includeFile))

0 commit comments

Comments
 (0)