Skip to content
This repository was archived by the owner on Jul 30, 2025. It is now read-only.

Commit c16dad3

Browse files
committed
fix(plugins/plugin-client-common): reverse-i-search does not properly report no matches
this also shows the history index of the current match, and skips over repeated matches (bash does the latter; the former is a kui novelty) Fixes #4943
1 parent 0331533 commit c16dad3

File tree

2 files changed

+42
-15
lines changed

2 files changed

+42
-15
lines changed

plugins/plugin-client-common/src/components/Views/Terminal/Block/ActiveISearch.tsx

Lines changed: 39 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -23,11 +23,6 @@ import Input from './Input'
2323

2424
const debug = Debug('core-support/history/reverse-i-search')
2525

26-
// TODO externalize
27-
const strings = {
28-
prompt: "(reverse-i-search$1)`$2':"
29-
}
30-
3126
/** state of the reverse-i-search */
3227
export default class ActiveISearch {
3328
// eslint-disable-next-line no-useless-constructor
@@ -39,7 +34,6 @@ export default class ActiveISearch {
3934
) {}
4035

4136
private fixedPart() {
42-
const text = strings.prompt.replace(/\$1/, '').replace(/\$2/, this.input.state.prompt.value)
4337
const className = 'small-right-pad' + (this.reachedTheEnd ? ' alert-pulse' : '')
4438

4539
if (this.reachedTheEnd) {
@@ -51,7 +45,15 @@ export default class ActiveISearch {
5145
)
5246
}
5347

54-
return <span className={className}>{text}</span>
48+
return (
49+
<span className={className}>
50+
(reverse-i-search
51+
<span className="sub-text semi-transparent">
52+
{this.currentSearchIdx === -1 ? '' : ' ' + this.currentSearchIdx.toString()}
53+
</span>
54+
){!this.input.state.prompt.value ? '' : '`' + this.input.state.prompt.value + '`:'}
55+
</span>
56+
)
5557
}
5658

5759
private matchedPrefixPart(newValue: string, caretPosition: number) {
@@ -69,11 +71,15 @@ export default class ActiveISearch {
6971
return <strong className="red-text kui--prompt-like">{this.input.state.prompt.value.replace(/ /g, '_')}</strong>
7072
}
7173

74+
private matchAt(idx = this.currentSearchIdx): string {
75+
return this.history.line(idx).raw
76+
}
77+
7278
public currentMatch(): string {
7379
if (this.currentSearchIdx === -1) {
7480
return ''
7581
} else {
76-
return this.history.line(this.currentSearchIdx).raw
82+
return this.matchAt()
7783
}
7884
}
7985

@@ -102,6 +108,28 @@ export default class ActiveISearch {
102108
this.input.setState({ isearch: undefined })
103109
}
104110

111+
/**
112+
* Search command history for a match, skipping over identicals.
113+
*
114+
* @return a command history index, or -1 if not match is found
115+
*
116+
*/
117+
private findPrevious(startIdx: number): number {
118+
if (startIdx < 0) {
119+
return -1
120+
}
121+
122+
const { prompt } = this.input.state
123+
124+
const newSearchIdx = prompt.value ? this.history.findIndex(prompt.value, startIdx) : -1
125+
if (newSearchIdx < 0 || this.currentSearchIdx < 0 || this.matchAt(newSearchIdx) !== this.matchAt()) {
126+
return newSearchIdx
127+
} else {
128+
// skip this match because it is the same as the current match
129+
return this.findPrevious(newSearchIdx - 1)
130+
}
131+
}
132+
105133
/**
106134
* Attempt to initiate or extend a search
107135
*
@@ -112,23 +140,19 @@ export default class ActiveISearch {
112140
// typing, then start from the end of history; if the user hit
113141
// ctrl+r, then they want to search for the next match
114142
const userHitCtrlR = evt.ctrlKey && evt.key === 'r'
115-
const startIdx = userHitCtrlR ? this.currentSearchIdx - 1 : -1
143+
const startIdx = userHitCtrlR ? this.currentSearchIdx - 1 : undefined
116144

117145
const { prompt } = this.input.state
118-
const newSearchIdx = prompt.value && this.history.findIndex(prompt.value, startIdx)
146+
const newSearchIdx = this.findPrevious(startIdx)
119147
debug('search index', prompt.value, newSearchIdx)
120148

121149
if (newSearchIdx > 0) {
122150
this.input.setState({ isearch: new ActiveISearch(this.input, this.history, newSearchIdx) })
123-
} else if (!userHitCtrlR) {
151+
} else if (userHitCtrlR) {
124152
// if we found no match, reset the match text, unless the user
125153
// is using repeated ctrl+R to search backwards; in this case,
126154
// let's continue to display the previous match if no new match
127155
// is found
128-
/* this.placeholderTypedPart.innerText = ''
129-
this.placeholderMatchedPrefixPart.innerText = ''
130-
this.placeholderMatchedSuffixPart.innerText = ''
131-
this.placeholderFixedPart.innerText = strings.prompt.replace(/\$1/, ``).replace(/\$2/, this.prompt.value) */
132156
} else {
133157
this.input.setState({ isearch: new ActiveISearch(this.input, this.history, newSearchIdx, true) })
134158
}

plugins/plugin-client-common/web/css/static/ui.css

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -374,6 +374,9 @@ code.fancy-code.hljs {
374374
.smaller-text {
375375
font-size: 0.875em;
376376
}
377+
.semi-transparent {
378+
opacity: 0.7;
379+
}
377380
.somewhat-smaller-text {
378381
font-size: 0.925em;
379382
}

0 commit comments

Comments
 (0)