@@ -23,11 +23,6 @@ import Input from './Input'
23
23
24
24
const debug = Debug ( 'core-support/history/reverse-i-search' )
25
25
26
- // TODO externalize
27
- const strings = {
28
- prompt : "(reverse-i-search$1)`$2':"
29
- }
30
-
31
26
/** state of the reverse-i-search */
32
27
export default class ActiveISearch {
33
28
// eslint-disable-next-line no-useless-constructor
@@ -39,7 +34,6 @@ export default class ActiveISearch {
39
34
) { }
40
35
41
36
private fixedPart ( ) {
42
- const text = strings . prompt . replace ( / \$ 1 / , '' ) . replace ( / \$ 2 / , this . input . state . prompt . value )
43
37
const className = 'small-right-pad' + ( this . reachedTheEnd ? ' alert-pulse' : '' )
44
38
45
39
if ( this . reachedTheEnd ) {
@@ -51,7 +45,15 @@ export default class ActiveISearch {
51
45
)
52
46
}
53
47
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
+ )
55
57
}
56
58
57
59
private matchedPrefixPart ( newValue : string , caretPosition : number ) {
@@ -69,11 +71,15 @@ export default class ActiveISearch {
69
71
return < strong className = "red-text kui--prompt-like" > { this . input . state . prompt . value . replace ( / / g, '_' ) } </ strong >
70
72
}
71
73
74
+ private matchAt ( idx = this . currentSearchIdx ) : string {
75
+ return this . history . line ( idx ) . raw
76
+ }
77
+
72
78
public currentMatch ( ) : string {
73
79
if ( this . currentSearchIdx === - 1 ) {
74
80
return ''
75
81
} else {
76
- return this . history . line ( this . currentSearchIdx ) . raw
82
+ return this . matchAt ( )
77
83
}
78
84
}
79
85
@@ -102,6 +108,28 @@ export default class ActiveISearch {
102
108
this . input . setState ( { isearch : undefined } )
103
109
}
104
110
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
+
105
133
/**
106
134
* Attempt to initiate or extend a search
107
135
*
@@ -112,23 +140,19 @@ export default class ActiveISearch {
112
140
// typing, then start from the end of history; if the user hit
113
141
// ctrl+r, then they want to search for the next match
114
142
const userHitCtrlR = evt . ctrlKey && evt . key === 'r'
115
- const startIdx = userHitCtrlR ? this . currentSearchIdx - 1 : - 1
143
+ const startIdx = userHitCtrlR ? this . currentSearchIdx - 1 : undefined
116
144
117
145
const { prompt } = this . input . state
118
- const newSearchIdx = prompt . value && this . history . findIndex ( prompt . value , startIdx )
146
+ const newSearchIdx = this . findPrevious ( startIdx )
119
147
debug ( 'search index' , prompt . value , newSearchIdx )
120
148
121
149
if ( newSearchIdx > 0 ) {
122
150
this . input . setState ( { isearch : new ActiveISearch ( this . input , this . history , newSearchIdx ) } )
123
- } else if ( ! userHitCtrlR ) {
151
+ } else if ( userHitCtrlR ) {
124
152
// if we found no match, reset the match text, unless the user
125
153
// is using repeated ctrl+R to search backwards; in this case,
126
154
// let's continue to display the previous match if no new match
127
155
// 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) */
132
156
} else {
133
157
this . input . setState ( { isearch : new ActiveISearch ( this . input , this . history , newSearchIdx , true ) } )
134
158
}
0 commit comments