1
1
// Import Node.js Dependencies
2
- import { emitKeypressEvents } from "readline" ;
2
+ import { emitKeypressEvents } from "node: readline" ;
3
3
4
4
// Import Third-party Dependencies
5
5
import strLength from "string-length" ;
6
6
7
7
// Import Internal Dependencies
8
8
import { localMatchOf } from "./src/utils.js" ;
9
+ import { History } from "./src/history.js" ;
9
10
10
11
/**
11
12
* @async
@@ -25,9 +26,7 @@ export default async function stdin(query = "question", options = {}) {
25
26
}
26
27
27
28
const { history = [ ] , autocomplete = [ ] } = options ;
28
- if ( ! Array . isArray ( history ) ) {
29
- throw new TypeError ( "history must be an Array Object" ) ;
30
- }
29
+ const histo = new History ( history ) ;
31
30
32
31
emitKeypressEvents ( process . stdin ) ;
33
32
if ( ! process . stdin . isTTY ) {
@@ -46,26 +45,21 @@ export default async function stdin(query = "question", options = {}) {
46
45
return new Promise ( ( resolve ) => {
47
46
let rawStr = "" ;
48
47
let currentCursorPosition = 0 ;
49
- let currentHistoryIndex = history . length ;
50
48
let isOriginalStr = true ;
51
- let autoCompletionActivated = false ;
52
- let autoCompletionStr = "" ;
53
- let realCompletionStr = "" ;
49
+ let completionHint = "" ;
50
+ let completionHintStripped = "" ;
54
51
55
- // eslint-disable-next-line
56
52
function clearAutoCompletion ( forceClean = false ) {
57
- if ( autoCompletionActivated ) {
53
+ if ( completionHint . length > 0 ) {
58
54
process . stdout . clearLine ( 1 ) ;
59
55
60
- autoCompletionActivated = false ;
61
- autoCompletionStr = "" ;
56
+ completionHint = "" ;
62
57
}
63
58
else if ( forceClean ) {
64
59
process . stdout . clearLine ( 1 ) ;
65
60
}
66
61
}
67
62
68
- // eslint-disable-next-line
69
63
function searchForCompletion ( str , forceNextMatch = false ) {
70
64
if ( noRefComplete . length === 0 ) {
71
65
return true ;
@@ -74,11 +68,10 @@ export default async function stdin(query = "question", options = {}) {
74
68
75
69
clearAutoCompletion ( ) ;
76
70
if ( localMatch !== null && localMatch !== "" ) {
77
- realCompletionStr = localMatch ;
78
- autoCompletionStr = `\x1b[90m${ localMatch } \x1b[39m` ;
79
- autoCompletionActivated = true ;
80
- process . stdout . write ( typeof str === "undefined" ? autoCompletionStr : `${ str } ${ autoCompletionStr } ` ) ;
81
- process . stdout . moveCursor ( - strLength ( autoCompletionStr ) , 0 ) ;
71
+ completionHintStripped = localMatch ;
72
+ completionHint = `\x1b[90m${ localMatch } \x1b[39m` ;
73
+ process . stdout . write ( typeof str === "undefined" ? completionHint : `${ str } ${ completionHint } ` ) ;
74
+ process . stdout . moveCursor ( - strLength ( completionHint ) , 0 ) ;
82
75
83
76
return false ;
84
77
}
@@ -93,18 +86,12 @@ export default async function stdin(query = "question", options = {}) {
93
86
process . stdin . pause ( ) ;
94
87
process . stdout . write ( "\n" ) ;
95
88
process . stdin . removeListener ( "keypress" , listener ) ;
96
- const uniqueHistorySet = new Set ( history ) ;
97
89
98
90
const trimedRawStr = rawStr . trim ( ) ;
99
- const result = trimedRawStr === "" ? null : trimedRawStr ;
100
-
101
- if ( result !== null ) {
102
- uniqueHistorySet . add ( rawStr ) ;
91
+ if ( trimedRawStr !== "" ) {
92
+ histo . push ( trimedRawStr ) ;
103
93
}
104
- history . splice ( 0 , history . length ) ;
105
- history . push ( ...uniqueHistorySet ) ;
106
-
107
- resolve ( result ) ;
94
+ resolve ( trimedRawStr ) ;
108
95
}
109
96
else if ( key . name === "left" ) {
110
97
if ( currentCursorPosition <= 0 ) {
@@ -122,45 +109,45 @@ export default async function stdin(query = "question", options = {}) {
122
109
return ;
123
110
}
124
111
125
- if ( ! autoCompletionActivated ) {
112
+ if ( completionHint . length === 0 ) {
126
113
return ;
127
114
}
128
115
129
116
clearAutoCompletion ( ) ;
130
- process . stdout . write ( realCompletionStr ) ;
131
- rawStr += realCompletionStr ;
132
- currentCursorPosition += realCompletionStr . length ;
133
- realCompletionStr = "" ;
117
+ process . stdout . write ( completionHintStripped ) ;
118
+ rawStr += completionHintStripped ;
119
+ currentCursorPosition += completionHintStripped . length ;
120
+ completionHintStripped = "" ;
134
121
searchForCompletion ( void 0 , true ) ;
135
122
}
136
123
else if ( key . name === "up" || key . name === "down" ) {
137
- const moveIndexValue = key . name === "up" ? - 1 : 1 ;
138
- const nextIndex = currentHistoryIndex + moveIndexValue ;
139
124
const rawStrCopy = rawStr ;
140
125
141
- if ( history . length === 0 ) {
126
+ if ( histo . length === 0 ) {
142
127
if ( isOriginalStr && rawStrCopy . trim ( ) !== "" ) {
143
- history . push ( rawStrCopy ) ;
128
+ histo . push ( rawStrCopy ) ;
129
+
144
130
isOriginalStr = false ;
145
131
}
146
132
147
133
return ;
148
134
}
149
- if ( nextIndex < 0 || nextIndex >= history . length ) {
135
+
136
+ const hasSwitchedHistory = key . name === "up" ? histo . up ( ) : histo . down ( ) ;
137
+ if ( ! hasSwitchedHistory ) {
150
138
return ;
151
139
}
152
140
153
141
clearAutoCompletion ( ) ;
154
- rawStr = history [ nextIndex ] ;
142
+ rawStr = histo . current ;
155
143
process . stdout . moveCursor ( - rawStrCopy . length , 0 ) ;
156
144
process . stdout . clearLine ( 1 ) ;
157
145
process . stdout . write ( rawStr ) ;
158
146
159
147
currentCursorPosition = rawStr . length ;
160
- currentHistoryIndex = nextIndex ;
161
148
162
149
if ( isOriginalStr && rawStrCopy . trim ( ) !== "" ) {
163
- history . push ( rawStrCopy ) ;
150
+ histo . push ( rawStrCopy ) ;
164
151
isOriginalStr = false ;
165
152
}
166
153
}
0 commit comments