diff --git a/news/1 Enhancements/4111.md b/news/1 Enhancements/4111.md new file mode 100644 index 000000000000..ee8423ee8e1a --- /dev/null +++ b/news/1 Enhancements/4111.md @@ -0,0 +1 @@ +Watermark for Python Interactive input prompt diff --git a/package.nls.json b/package.nls.json index 2b8d494e54ca..cccdccf610ea 100644 --- a/package.nls.json +++ b/package.nls.json @@ -120,6 +120,7 @@ "DataScience.pythonVersionHeaderNoPyKernel": "Python version may not match, no ipykernel found:", "DataScience.pythonRestartHeader": "Restarted Kernel:", "DataScience.executingCodeFailure" : "Executing code failed : {0}", + "DataScience.inputWatermark" : "Shift-enter to run", "Linter.InstalledButNotEnabled": "Linter {0} is installed but not enabled.", "Linter.replaceWithSelectedLinter": "Multiple linters are enabled in settings. Replace with '{0}'?", "DataScience.jupyterSelectURILaunchLocal": "Launch a local Jupyter server when needed", diff --git a/src/client/common/utils/localize.ts b/src/client/common/utils/localize.ts index 0a505c719781..9279d6a26e82 100644 --- a/src/client/common/utils/localize.ts +++ b/src/client/common/utils/localize.ts @@ -118,6 +118,7 @@ export namespace DataScience { export const pythonInterruptFailedHeader = localize('DataScience.pythonInterruptFailedHeader', 'Keyboard interrupt crashed the kernel. Kernel restarted.'); export const sysInfoURILabel = localize('DataScience.sysInfoURILabel', 'Jupyter Server URI: '); export const executingCodeFailure = localize('DataScience.executingCodeFailure', 'Executing code failed : {0}'); + export const inputWatermark = localize('DataScience.inputWatermark', 'Shift-enter to run'); } export namespace DebugConfigurationPrompts { diff --git a/src/datascience-ui/history-react/MainPanel.tsx b/src/datascience-ui/history-react/MainPanel.tsx index 622f1cbe769e..6b6616076111 100644 --- a/src/datascience-ui/history-react/MainPanel.tsx +++ b/src/datascience-ui/history-react/MainPanel.tsx @@ -37,7 +37,7 @@ export class MainPanel extends React.Component super(props); // Default state should show a busy message - this.state = { cellVMs: [], busy: true, undoStack: [], redoStack : [], historyStack: []}; + this.state = { cellVMs: [], busy: true, undoStack: [], redoStack : [], historyStack: [], submittedText: false}; // Add test state if necessary if (!this.props.skipDefault) { @@ -213,6 +213,7 @@ export class MainPanel extends React.Component submitNewCode={this.submitInput} baseTheme={this.props.baseTheme} codeTheme={this.props.codeTheme} + showWatermark={!this.state.submittedText} gotoCode={() => this.gotoCellCode(index)} delete={() => this.deleteCell(index)}/> @@ -637,7 +638,8 @@ export class MainPanel extends React.Component undoStack : this.pushStack(this.state.undoStack, this.state.cellVMs), redoStack: this.state.redoStack, skipNextScroll: false, - historyStack: newHistory + historyStack: newHistory, + submittedText: true }); // Send a message to execute this code if necessary. diff --git a/src/datascience-ui/history-react/cell.tsx b/src/datascience-ui/history-react/cell.tsx index 1b48490b0780..54f6acce038d 100644 --- a/src/datascience-ui/history-react/cell.tsx +++ b/src/datascience-ui/history-react/cell.tsx @@ -34,6 +34,7 @@ interface ICellProps { autoFocus: boolean; maxTextSize?: number; history: string []; + showWatermark: boolean; gotoCode(): void; delete(): void; submitNewCode(code: string): void; @@ -204,6 +205,7 @@ export class Cell extends React.Component { codeTheme={this.props.codeTheme} testMode={this.props.testMode ? true : false} readOnly={!this.props.cellVM.editable} + showWatermark={this.props.showWatermark} onSubmit={this.props.submitNewCode} onChangeLineCount={this.onChangeLineCount} ref={this.updateCodeRef} diff --git a/src/datascience-ui/history-react/code.css b/src/datascience-ui/history-react/code.css index 08aadb31c45d..47a124abefa6 100644 --- a/src/datascience-ui/history-react/code.css +++ b/src/datascience-ui/history-react/code.css @@ -36,3 +36,17 @@ .code-area-editable { margin-bottom: 10px; } + +.code-watermark { + position: absolute; + top: 0; + left: 30px; + z-index: 500; + font-style: italic; + color: var(--vscode-pickerGroup-border); +} + +.hide { + visibility: hidden; +} + diff --git a/src/datascience-ui/history-react/code.tsx b/src/datascience-ui/history-react/code.tsx index 6551b2b7a3e4..d2c074f05087 100644 --- a/src/datascience-ui/history-react/code.tsx +++ b/src/datascience-ui/history-react/code.tsx @@ -11,6 +11,7 @@ import * as RCM from 'react-codemirror'; import './code.css'; +import { getLocString } from '../react-common/locReactSide'; import { Cursor } from './cursor'; import { InputHistory } from './inputHistory'; @@ -22,6 +23,7 @@ export interface ICodeProps { readOnly: boolean; history: string[]; cursorType: string; + showWatermark: boolean; onSubmit(code: string): void; onChangeLineCount(lineCount: number) : void; @@ -33,6 +35,7 @@ interface ICodeState { cursorTop: number; cursorBottom: number; charUnderCursor: string; + allowWatermark: boolean; } export class Code extends React.Component { @@ -43,7 +46,7 @@ export class Code extends React.Component { constructor(prop: ICodeProps) { super(prop); - this.state = {focused: false, cursorLeft: 0, cursorTop: 0, cursorBottom: 0, charUnderCursor: ''}; + this.state = {focused: false, cursorLeft: 0, cursorTop: 0, cursorBottom: 0, charUnderCursor: '', allowWatermark: true}; this.history = new InputHistory(this.props.history); } @@ -57,6 +60,7 @@ export class Code extends React.Component { public render() { const readOnly = this.props.testMode || this.props.readOnly; const classes = readOnly ? 'code-area' : 'code-area code-area-editable'; + const waterMarkClass = this.props.showWatermark && this.state.allowWatermark && !readOnly ? 'code-watermark' : 'hide'; return (
{ onFocusChange={this.onFocusChange} onCursorActivity={this.onCursorActivity} /> +
{this.getWatermarkString()}
); } @@ -104,6 +109,10 @@ export class Code extends React.Component { } } + private getWatermarkString = () : string => { + return getLocString('DataScience.inputWatermark', 'Shift-enter to run'); + } + private onCursorActivity = (codeMirror: CodeMirror.Editor) => { // Update left/top/char for cursor if (codeMirror) { @@ -245,5 +254,6 @@ export class Code extends React.Component { private onChange = (newValue: string, change: CodeMirror.EditorChange) => { this.history.onChange(); + this.setState({allowWatermark: false}); } } diff --git a/src/datascience-ui/history-react/mainPanelState.ts b/src/datascience-ui/history-react/mainPanelState.ts index afb9f5418a7a..e7caf7fcc048 100644 --- a/src/datascience-ui/history-react/mainPanelState.ts +++ b/src/datascience-ui/history-react/mainPanelState.ts @@ -18,6 +18,7 @@ export interface IMainPanelState { undoStack : ICellViewModel[][]; redoStack : ICellViewModel[][]; historyStack: string[]; + submittedText: boolean; } // This function generates test state when running under a browser instead of inside of @@ -28,7 +29,8 @@ export function generateTestState(inputBlockToggled : (id: string) => void, file skipNextScroll : false, undoStack : [], redoStack : [], - historyStack: [] + historyStack: [], + submittedText: false }; }