Skip to content

Commit f0ab415

Browse files
committed
temp
1 parent 9d64778 commit f0ab415

21 files changed

Lines changed: 629 additions & 297 deletions

package.json

Lines changed: 1 addition & 51 deletions
Original file line numberDiff line numberDiff line change
@@ -887,57 +887,7 @@
887887
}
888888
}
889889
}
890-
},
891-
"initialConfigurations": [
892-
{
893-
"name": "Python: Current File",
894-
"type": "python",
895-
"request": "launch",
896-
"program": "${file}"
897-
},
898-
{
899-
"name": "Python: Attach",
900-
"type": "python",
901-
"request": "attach",
902-
"port": 5678,
903-
"host": "localhost"
904-
},
905-
{
906-
"name": "Python: Module",
907-
"type": "python",
908-
"request": "launch",
909-
"module": "enter-your-module-name-here",
910-
"console": "integratedTerminal"
911-
},
912-
{
913-
"name": "Python: Django",
914-
"type": "python",
915-
"request": "launch",
916-
"program": "${workspaceFolder}/manage.py",
917-
"console": "integratedTerminal",
918-
"args": [
919-
"runserver",
920-
"--noreload",
921-
"--nothreading"
922-
],
923-
"django": true
924-
},
925-
{
926-
"name": "Python: Flask",
927-
"type": "python",
928-
"request": "launch",
929-
"module": "flask",
930-
"env": {
931-
"FLASK_APP": "app.py"
932-
},
933-
"args": [
934-
"run",
935-
"--no-debugger",
936-
"--no-reload"
937-
],
938-
"jinja": true
939-
}
940-
]
890+
}
941891
}
942892
],
943893
"configuration": {

package.nls.json

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -140,7 +140,7 @@
140140
"DataScience.pythonInterruptFailedHeader": "Keyboard interrupt crashed the kernel. Kernel restarted.",
141141
"DataScience.sysInfoURILabel": "Jupyter Server URI: ",
142142
"Common.loadingPythonExtension": "Python extension loading...",
143-
"debug.selectConfiguration": "Select Debug Configuration",
143+
"debug.selectConfiguration": "Select a debug configuration",
144144
"debug.debugFileConfigurationLabel": "Debug Python File",
145145
"debug.attachConfigurationLabel": "Attach debugger to remote application",
146146
"debug.debugDjangoConfigurationLabel": "Debug Django",
@@ -150,7 +150,7 @@
150150
"debug.attachRemotePortValidationError": "Enter a valid Port Number",
151151
"debug.attachRemoteHostPlaceholder": "Host",
152152
"debug.attachRemoteHostPrompt": "Enter Host Name",
153-
"debug.attachRemoteHostValidationError": "Enter a Host Name",
153+
"debug.attachRemoteHostValidationError": "Enter a Host Name or IP Address",
154154
"debug.debugDjangoSelectManagePyOpenDialogLabel": "Select 'manage.py' file",
155155
"debug.debugFlaskSelectAppOpenDialogLabel": "Select Flask Application file/package"
156156
}

src/client/common/application/applicationShell.ts

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
const opn = require('opn');
77

88
import { injectable } from 'inversify';
9-
import { CancellationToken, Disposable, InputBoxOptions, MessageItem, MessageOptions, OpenDialogOptions, Progress, ProgressOptions, QuickPickItem, QuickPickOptions, SaveDialogOptions, StatusBarAlignment, StatusBarItem, Uri, window, WorkspaceFolder, WorkspaceFolderPickOptions } from 'vscode';
9+
import { CancellationToken, Disposable, InputBox, InputBoxOptions, MessageItem, MessageOptions, OpenDialogOptions, Progress, ProgressOptions, QuickPick, QuickPickItem, QuickPickOptions, SaveDialogOptions, StatusBarAlignment, StatusBarItem, Uri, window, WorkspaceFolder, WorkspaceFolderPickOptions } from 'vscode';
1010
import { IApplicationShell } from './types';
1111

1212
@injectable()
@@ -70,4 +70,10 @@ export class ApplicationShell implements IApplicationShell {
7070
public withProgress<R>(options: ProgressOptions, task: (progress: Progress<{ message?: string; increment?: number }>, token: CancellationToken) => Thenable<R>): Thenable<R> {
7171
return window.withProgress<R>(options, task);
7272
}
73+
public createQuickPick<T extends QuickPickItem>(): QuickPick<T> {
74+
return window.createQuickPick<T>();
75+
}
76+
public createInputBox(): InputBox {
77+
return window.createInputBox();
78+
}
7379
}

src/client/common/application/types.ts

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,12 +15,14 @@ import {
1515
Event,
1616
FileSystemWatcher,
1717
GlobPattern,
18+
InputBox,
1819
InputBoxOptions,
1920
MessageItem,
2021
MessageOptions,
2122
OpenDialogOptions,
2223
Progress,
2324
ProgressOptions,
25+
QuickPick,
2426
QuickPickItem,
2527
QuickPickOptions,
2628
SaveDialogOptions,
@@ -227,6 +229,28 @@ export interface IApplicationShell {
227229
*/
228230
showInputBox(options?: InputBoxOptions, token?: CancellationToken): Thenable<string | undefined>;
229231

232+
/**
233+
* Creates a [QuickPick](#QuickPick) to let the user pick an item from a list
234+
* of items of type T.
235+
*
236+
* Note that in many cases the more convenient [window.showQuickPick](#window.showQuickPick)
237+
* is easier to use. [window.createQuickPick](#window.createQuickPick) should be used
238+
* when [window.showQuickPick](#window.showQuickPick) does not offer the required flexibility.
239+
*
240+
* @return A new [QuickPick](#QuickPick).
241+
*/
242+
createQuickPick<T extends QuickPickItem>(): QuickPick<T>;
243+
244+
/**
245+
* Creates a [InputBox](#InputBox) to let the user enter some text input.
246+
*
247+
* Note that in many cases the more convenient [window.showInputBox](#window.showInputBox)
248+
* is easier to use. [window.createInputBox](#window.createInputBox) should be used
249+
* when [window.showInputBox](#window.showInputBox) does not offer the required flexibility.
250+
*
251+
* @return A new [InputBox](#InputBox).
252+
*/
253+
createInputBox(): InputBox;
230254
/**
231255
* Opens URL in a default browser.
232256
*

src/client/common/utils/localize.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -117,7 +117,7 @@ export namespace Debug {
117117

118118
export const attachRemoteHostPlaceholder = localize('debug.attachRemoteHostPlaceholder', 'Host');
119119
export const attachRemoteHostPrompt = localize('debug.attachRemoteHostPrompt', 'Enter Host Name');
120-
export const attachRemoteHostValidationError = localize('debug.attachRemoteHostValidationError', 'Enter a Host Name');
120+
export const attachRemoteHostValidationError = localize('debug.attachRemoteHostValidationError', 'Enter a Host Name or IP Address');
121121
export const debugDjangoSelectManagePyOpenDialogLabel = localize('debug.debugDjangoSelectManagePyOpenDialogLabel', 'Select \'manage.py\' file');
122122
export const debugFlaskSelectAppOpenDialogLabel = localize('debug.debugFlaskSelectAppOpenDialogLabel', 'Select Flask Application file/package');
123123
}
Lines changed: 187 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,187 @@
1+
// Copyright (c) Microsoft Corporation. All rights reserved.
2+
// Licensed under the MIT License.
3+
4+
'use strict';
5+
6+
// tslint:disable:max-func-body-length no-any no-unnecessary-class
7+
8+
import { Disposable, QuickInput, QuickInputButton, QuickInputButtons, QuickPickItem } from 'vscode';
9+
import { IApplicationShell } from '../application/types';
10+
11+
// Borrowed from https://github.com/Microsoft/vscode-extension-samples/blob/master/quickinput-sample/src/multiStepInput.ts
12+
// Why re-invent the wheel :)
13+
14+
export class InputFlowAction {
15+
public static back = new InputFlowAction();
16+
public static cancel = new InputFlowAction();
17+
public static resume = new InputFlowAction();
18+
private constructor() { }
19+
}
20+
21+
export type InputStep<T extends any> = (input: MultiStepInput<T>, state?: T) => Thenable<InputStep<T> | void>;
22+
23+
export interface IQuickPickParameters<T extends QuickPickItem> {
24+
title: string;
25+
step?: number;
26+
totalSteps?: number;
27+
canGoBack?: boolean;
28+
items: T[];
29+
activeItem?: T;
30+
placeholder: string;
31+
buttons?: QuickInputButton[];
32+
shouldResume?(): Thenable<boolean>;
33+
}
34+
35+
export interface InputBoxParameters {
36+
title: string;
37+
step?: number;
38+
totalSteps?: number;
39+
value: string;
40+
prompt: string;
41+
buttons?: QuickInputButton[];
42+
validate(value: string): Promise<string | undefined>;
43+
shouldResume?(): Thenable<boolean>;
44+
}
45+
46+
export class MultiStepInput<S> {
47+
private current?: QuickInput;
48+
private steps: InputStep<S>[] = [];
49+
constructor(private readonly shell: IApplicationShell) { }
50+
public static async run<S>(shell: IApplicationShell, start: InputStep<S>, state: S) {
51+
const input = new MultiStepInput<S>(shell);
52+
return input.stepThrough(start, state);
53+
}
54+
55+
public async showQuickPick<T extends QuickPickItem, P extends IQuickPickParameters<T>>({ title, step, totalSteps, items, activeItem, placeholder, buttons, shouldResume }: P) {
56+
const disposables: Disposable[] = [];
57+
try {
58+
return await new Promise<T | (P extends { buttons: (infer I)[] } ? I : never)>((resolve, reject) => {
59+
const input = this.shell.createQuickPick<T>();
60+
input.title = title;
61+
input.step = step;
62+
input.totalSteps = totalSteps;
63+
input.placeholder = placeholder;
64+
input.ignoreFocusOut = true;
65+
input.items = items;
66+
if (activeItem) {
67+
input.activeItems = [activeItem];
68+
}
69+
input.buttons = [
70+
...(this.steps.length > 1 ? [QuickInputButtons.Back] : []),
71+
...(buttons || [])
72+
];
73+
disposables.push(
74+
input.onDidTriggerButton(item => {
75+
if (item === QuickInputButtons.Back) {
76+
reject(InputFlowAction.back);
77+
} else {
78+
resolve(<any>item);
79+
}
80+
}),
81+
input.onDidChangeSelection(selectedItems => resolve(selectedItems[0])),
82+
input.onDidHide(() => {
83+
(async () => {
84+
reject(shouldResume && await shouldResume() ? InputFlowAction.resume : InputFlowAction.cancel);
85+
})()
86+
.catch(reject);
87+
})
88+
);
89+
if (this.current) {
90+
this.current.dispose();
91+
}
92+
this.current = input;
93+
this.current.show();
94+
});
95+
} finally {
96+
disposables.forEach(d => d.dispose());
97+
}
98+
}
99+
100+
public async showInputBox<P extends InputBoxParameters>({ title, step, totalSteps, value, prompt, validate, buttons, shouldResume }: P) {
101+
const disposables: Disposable[] = [];
102+
try {
103+
return await new Promise<string | (P extends { buttons: (infer I)[] } ? I : never)>((resolve, reject) => {
104+
const input = this.shell.createInputBox();
105+
input.title = title;
106+
input.step = step;
107+
input.totalSteps = totalSteps;
108+
input.value = value || '';
109+
input.prompt = prompt;
110+
input.ignoreFocusOut = true;
111+
input.buttons = [
112+
...(this.steps.length > 1 ? [QuickInputButtons.Back] : []),
113+
...(buttons || [])
114+
];
115+
let validating = validate('');
116+
disposables.push(
117+
input.onDidTriggerButton(item => {
118+
if (item === QuickInputButtons.Back) {
119+
reject(InputFlowAction.back);
120+
} else {
121+
resolve(<any>item);
122+
}
123+
}),
124+
input.onDidAccept(async () => {
125+
const inputValue = input.value;
126+
input.enabled = false;
127+
input.busy = true;
128+
if (!(await validate(inputValue))) {
129+
resolve(inputValue);
130+
}
131+
input.enabled = true;
132+
input.busy = false;
133+
}),
134+
input.onDidChangeValue(async text => {
135+
const current = validate(text);
136+
validating = current;
137+
const validationMessage = await current;
138+
if (current === validating) {
139+
input.validationMessage = validationMessage;
140+
}
141+
}),
142+
input.onDidHide(() => {
143+
(async () => {
144+
reject(shouldResume && await shouldResume() ? InputFlowAction.resume : InputFlowAction.cancel);
145+
})()
146+
.catch(reject);
147+
})
148+
);
149+
if (this.current) {
150+
this.current.dispose();
151+
}
152+
this.current = input;
153+
this.current.show();
154+
});
155+
} finally {
156+
disposables.forEach(d => d.dispose());
157+
}
158+
}
159+
160+
private async stepThrough<T>(start: InputStep<S>, state: S) {
161+
let step: InputStep<S> | void = start;
162+
while (step) {
163+
this.steps.push(step);
164+
if (this.current) {
165+
this.current.enabled = false;
166+
this.current.busy = true;
167+
}
168+
try {
169+
step = await step(this, state);
170+
} catch (err) {
171+
if (err === InputFlowAction.back) {
172+
this.steps.pop();
173+
step = this.steps.pop();
174+
} else if (err === InputFlowAction.resume) {
175+
step = this.steps.pop();
176+
} else if (err === InputFlowAction.cancel) {
177+
step = undefined;
178+
} else {
179+
throw err;
180+
}
181+
}
182+
}
183+
if (this.current) {
184+
this.current.dispose();
185+
}
186+
}
187+
}

0 commit comments

Comments
 (0)