1- import * as fs from 'fs' ;
2- import { window , Disposable } from 'vscode' ;
1+ import { window , Disposable , Memento } from 'vscode' ;
32import { QuickPickItem } from 'vscode' ;
4- import * as _ from 'lodash' ;
53
64export const historyPath = `${ process . env . HOME } /.vscode-cmd-history` ;
75
6+ const HISTORY_KEY = 'HISTORY_KEY' ;
7+
88/**
99 * A command prompt with history
1010 *
1111 */
12- export async function promptCommand ( ) {
13- const command = await pickCommand ( ) ;
14- if ( command ) {
15- window . showInformationMessage ( `You picked the following command: '${ command } '` )
12+ export const getPromptCommand = ( memo : Memento ) => {
13+ const pickCommand = getPickCommand ( memo ) ;
14+ // §TODO: cache promptCommand!
15+ return async function promptCommand ( ) {
16+ const command = await pickCommand ( ) ;
17+ if ( command ) {
18+ window . showInformationMessage ( `You picked the following command: '${ command } '` )
19+ }
1620 }
1721}
1822
19- class CommandItem implements QuickPickItem {
23+ abstract class CommandItem implements QuickPickItem {
2024 public label : string ;
2125 public description ?: string ;
26+ public abstract type : string ;
2227 constructor ( label : string , description ?: string ) {
2328 this . label = label ;
2429 this . description = description ;
2530 }
2631}
2732class HistoryItem extends CommandItem {
33+ public type : string ;
2834 constructor ( label : string , description ?: string ) {
2935 super ( label , description ) ;
36+ this . type = 'history'
3037 }
3138}
3239class InputItem extends CommandItem {
40+ public type : string ;
3341 constructor ( public label : string ) {
3442 super ( label , '(current input)' ) ;
43+ this . type = 'input' ;
3544 } ;
3645}
3746
38- async function pickCommand ( ) {
47+ const getPickCommand = ( memo : Memento ) => async function pickCommand ( ) {
3948 const disposables : Disposable [ ] = [ ] ;
40- let commandsItems : CommandItem [ ] = [ ] ;
41- let currentValue : string | undefined = undefined ;
42- let historyShouldBeUpdated = false ;
43-
4449 try {
4550 return await new Promise < string | undefined > ( ( resolve , reject ) => {
4651 const input = window . createQuickPick < CommandItem > ( ) ;
4752 input . placeholder = 'Type a command' ;
48- input . items = commandsItems ;
53+ input . items = [ ] ;
4954
5055 const updateQuickPick = ( value ?: string ) : void => {
56+ if ( value === input . value ) return ;
5157 if ( ! value ) {
52- input . items = commandsItems ;
58+ if ( input . items [ 0 ] && input . items [ 0 ] . type === 'input' )
59+ input . items = input . items . slice ( 1 ) ;
5360 return ;
5461 }
55- input . items = [
56- new InputItem ( value )
57- ] . concat (
58- commandsItems
59- )
62+ if ( input . items [ 0 ] && input . items [ 0 ] . type === 'input' ) {
63+ input . items = [ new InputItem ( value ) ] . concat ( input . items . slice ( 1 ) ) ;
64+ } else {
65+ input . items = [ new InputItem ( value ) ] . concat ( input . items ) ;
66+ }
6067 // §todo: add autocomplete suggestions
6168 }
6269
6370 disposables . push (
64- input . onDidChangeValue ( ( value ?: string ) => {
65- currentValue = value ;
66- updateQuickPick ( value ) ;
67- } ) ,
71+ input . onDidChangeValue ( updateQuickPick ) ,
6872 input . onDidChangeSelection ( ( items : CommandItem [ ] ) => {
6973 const item = items [ 0 ] ;
7074 if ( item instanceof HistoryItem ) {
7175 resolve ( item . label ) ;
7276 input . hide ( ) ;
7377 // do not record new input in history
78+ // §todo : maybe reorder
7479 } else if ( item instanceof InputItem ) {
7580 resolve ( item . label ) ;
7681 input . hide ( ) ;
7782 // record new input in history
78- if ( historyShouldBeUpdated && ! item . label . startsWith ( ' ' ) ) {
79- fs . appendFile ( historyPath , item . label + '\n' , function ( err ) {
80- if ( err ) console . error ( 'Problem while updating history file' , err ) ;
81- } ) ;
83+ if ( ! item . label . startsWith ( ' ' ) ) {
84+ const currentHistory : string [ ] = memo . get ( HISTORY_KEY , [ ] ) ;
85+ currentHistory . unshift ( item . label ) ;
86+ memo . update ( HISTORY_KEY , currentHistory ) ;
8287 }
8388 }
8489 } ) ,
@@ -88,22 +93,10 @@ async function pickCommand() {
8893 } )
8994 ) ;
9095 input . show ( ) ;
91-
92- if ( fs . existsSync ( historyPath ) ) {
93- fs . readFile ( historyPath , ( err , content ) => {
94- if ( err ) {
95- console . error ( 'Could not load file history' , err ) ;
96- }
97- historyShouldBeUpdated = true ;
98- const commands = content . toString ( ) . trimRight ( ) . split ( '\n' ) . reverse ( ) ;
99- commandsItems = _ . map ( commands , ( cmd : string , index : number ) => new HistoryItem ( cmd , `(history item ${ index } )` ) ) ;
100- updateQuickPick ( currentValue ) ;
101- } ) ;
102- } else {
103- console . log ( 'history file does not exist yet' ) ;
104- historyShouldBeUpdated = true ;
105- }
106-
96+ const historyItems : HistoryItem [ ] = memo . get ( HISTORY_KEY , [ ] ) . map (
97+ ( cmd : string , index : number ) => new HistoryItem ( cmd , `(history item ${ index } )` )
98+ ) ;
99+ input . items = input . items . concat ( historyItems )
107100 } ) ;
108101 } finally {
109102 disposables . forEach ( d => d . dispose ( ) ) ;
0 commit comments