Skip to content

Commit

Permalink
Added notebook output options and tag preference search (#13773)
Browse files Browse the repository at this point in the history
* Added notebook output options and the ability to search for tags in settings

Signed-off-by: Jonah Iden <[email protected]>

* review changes

Signed-off-by: Jonah Iden <[email protected]>

* review fixes

Signed-off-by: Jonah Iden <[email protected]>

* improved tag search

Signed-off-by: Jonah Iden <[email protected]>

* fixed line height when set to 0

Signed-off-by: Jonah Iden <[email protected]>

---------

Signed-off-by: Jonah Iden <[email protected]>
  • Loading branch information
jonah-iden authored Jun 7, 2024
1 parent fcd227a commit d79b710
Show file tree
Hide file tree
Showing 10 changed files with 289 additions and 35 deletions.
1 change: 1 addition & 0 deletions packages/core/src/common/preferences/preference-schema.ts
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,7 @@ export interface PreferenceSchemaProperty extends PreferenceItem {
description?: string;
markdownDescription?: string;
scope?: 'application' | 'machine' | 'window' | 'resource' | 'language-overridable' | 'machine-overridable' | PreferenceScope;
tags?: string[];
}

export interface PreferenceDataProperty extends PreferenceItem {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,19 +13,71 @@
//
// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-only WITH Classpath-exception-2.0
// *****************************************************************************
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/

import { nls } from '@theia/core';
import { PreferenceSchema } from '@theia/core/lib/browser';

export const NOTEBOOK_LINE_NUMBERS = 'notebook.lineNumbers';
export namespace NotebookPreferences {
export const NOTEBOOK_LINE_NUMBERS = 'notebook.lineNumbers';
export const OUTPUT_LINE_HEIGHT = 'notebook.output.lineHeight';
export const OUTPUT_FONT_SIZE = 'notebook.output.fontSize';
export const OUTPUT_FONT_FAMILY = 'notebook.output.fontFamily';
export const OUTPUT_SCROLLING = 'notebook.output.scrolling';
export const OUTPUT_WORD_WRAP = 'notebook.output.wordWrap';
export const OUTPUT_LINE_LIMIT = 'notebook.output.textLineLimit';
}

export const notebookPreferenceSchema: PreferenceSchema = {
properties: {
[NOTEBOOK_LINE_NUMBERS]: {
[NotebookPreferences.NOTEBOOK_LINE_NUMBERS]: {
type: 'string',
enum: ['on', 'off'],
default: 'off',
description: nls.localizeByDefault('Controls the display of line numbers in the cell editor.')
},
[NotebookPreferences.OUTPUT_LINE_HEIGHT]: {
// eslint-disable-next-line max-len
markdownDescription: nls.localizeByDefault('Line height of the output text within notebook cells.\n - When set to 0, editor line height is used.\n - Values between 0 and 8 will be used as a multiplier with the font size.\n - Values greater than or equal to 8 will be used as effective values.'),
type: 'number',
default: 0,
tags: ['notebookLayout', 'notebookOutputLayout']
},
[NotebookPreferences.OUTPUT_FONT_SIZE]: {
markdownDescription: nls.localizeByDefault('Font size for the output text within notebook cells. When set to 0, {0} is used.', '`#editor.fontSize#`'),
type: 'number',
default: 0,
tags: ['notebookLayout', 'notebookOutputLayout']
},
[NotebookPreferences.OUTPUT_FONT_FAMILY]: {
markdownDescription: nls.localizeByDefault('The font family of the output text within notebook cells. When set to empty, the {0} is used.', '`#editor.fontFamily#`'),
type: 'string',
tags: ['notebookLayout', 'notebookOutputLayout']
},
[NotebookPreferences.OUTPUT_SCROLLING]: {
markdownDescription: nls.localizeByDefault('Initially render notebook outputs in a scrollable region when longer than the limit.'),
type: 'boolean',
tags: ['notebookLayout', 'notebookOutputLayout'],
default: false
},
[NotebookPreferences.OUTPUT_WORD_WRAP]: {
markdownDescription: nls.localizeByDefault('Controls whether the lines in output should wrap.'),
type: 'boolean',
tags: ['notebookLayout', 'notebookOutputLayout'],
default: false
},
[NotebookPreferences.OUTPUT_LINE_LIMIT]: {
markdownDescription: nls.localizeByDefault(
'Controls how many lines of text are displayed in a text output. If {0} is enabled, this setting is used to determine the scroll height of the output.',
'`#notebook.output.scrolling#`'),
type: 'number',
default: 30,
tags: ['notebookLayout', 'notebookOutputLayout'],
minimum: 1,
},

}
};
2 changes: 2 additions & 0 deletions packages/notebook/src/browser/notebook-frontend-module.ts
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@ import { NotebookLabelProviderContribution } from './contributions/notebook-labe
import { NotebookOutputActionContribution } from './contributions/notebook-output-action-contribution';
import { NotebookClipboardService } from './service/notebook-clipboard-service';
import { notebookPreferenceSchema } from './contributions/notebook-preferences';
import { NotebookOptionsService } from './service/notebook-options';

export default new ContainerModule((bind, unbind, isBound, rebind) => {
bind(NotebookColorContribution).toSelf().inSingletonScope();
Expand Down Expand Up @@ -106,4 +107,5 @@ export default new ContainerModule((bind, unbind, isBound, rebind) => {
bind(LabelProviderContribution).toService(NotebookLabelProviderContribution);

bind(PreferenceContribution).toConstantValue({ schema: notebookPreferenceSchema });
bind(NotebookOptionsService).toSelf().inSingletonScope();
});
154 changes: 154 additions & 0 deletions packages/notebook/src/browser/service/notebook-options.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,154 @@

// *****************************************************************************
// Copyright (C) 2024 TypeFox and others.
//
// This program and the accompanying materials are made available under the
// terms of the Eclipse Public License v. 2.0 which is available at
// http://www.eclipse.org/legal/epl-2.0.
//
// This Source Code may also be made available under the following Secondary
// Licenses when the conditions for such availability set forth in the Eclipse
// Public License v. 2.0 are satisfied: GNU General Public License, version 2
// with the GNU Classpath Exception which is available at
// https://www.gnu.org/software/classpath/license.html.
//
// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-only WITH Classpath-exception-2.0
// *****************************************************************************

import { inject, injectable, postConstruct } from '@theia/core/shared/inversify';
import { PreferenceService } from '@theia/core/lib/browser';
import { Emitter } from '@theia/core';
import { NotebookPreferences, notebookPreferenceSchema } from '../contributions/notebook-preferences';
import { EditorPreferences } from '@theia/editor/lib/browser';
import { BareFontInfo } from '@theia/monaco-editor-core/esm/vs/editor/common/config/fontInfo';
import { PixelRatio } from '@theia/monaco-editor-core/esm/vs/base/browser/browser';

const notebookOutputOptionsRelevantPreferences = [
'editor.fontSize',
'editor.fontFamily',
NotebookPreferences.NOTEBOOK_LINE_NUMBERS,
NotebookPreferences.OUTPUT_LINE_HEIGHT,
NotebookPreferences.OUTPUT_FONT_SIZE,
NotebookPreferences.OUTPUT_FONT_FAMILY,
NotebookPreferences.OUTPUT_SCROLLING,
NotebookPreferences.OUTPUT_WORD_WRAP,
NotebookPreferences.OUTPUT_LINE_LIMIT
];

export interface NotebookOutputOptions {
// readonly outputNodePadding: number;
// readonly outputNodeLeftPadding: number;
// readonly previewNodePadding: number;
// readonly markdownLeftMargin: number;
// readonly leftMargin: number;
// readonly rightMargin: number;
// readonly runGutter: number;
// readonly dragAndDropEnabled: boolean;
readonly fontSize: number;
readonly outputFontSize?: number;
readonly fontFamily: string;
readonly outputFontFamily?: string;
// readonly markupFontSize: number;
// readonly markdownLineHeight: number;
readonly outputLineHeight: number;
readonly outputScrolling: boolean;
readonly outputWordWrap: boolean;
readonly outputLineLimit: number;
// readonly outputLinkifyFilePaths: boolean;
// readonly minimalError: boolean;

}

@injectable()
export class NotebookOptionsService {

@inject(PreferenceService)
protected readonly preferenceService: PreferenceService;

@inject(EditorPreferences)
protected readonly editorPreferences: EditorPreferences;

protected outputOptionsChangedEmitter = new Emitter<NotebookOutputOptions>();
onDidChangeOutputOptions = this.outputOptionsChangedEmitter.event;

protected fontInfo?: BareFontInfo;
get editorFontInfo(): BareFontInfo {
return this.getOrCreateMonacoFontInfo();
}

@postConstruct()
protected init(): void {
this.preferenceService.onPreferencesChanged(async preferenceChanges => {
if (notebookOutputOptionsRelevantPreferences.some(p => p in preferenceChanges)) {
this.outputOptionsChangedEmitter.fire(this.computeOutputOptions());
}
});
}

computeOutputOptions(): NotebookOutputOptions {
const outputLineHeight = this.getNotebookPreferenceWithDefault<number>(NotebookPreferences.OUTPUT_LINE_HEIGHT);

const fontSize = this.preferenceService.get<number>('editor.fontSize')!;
const outputFontSize = this.getNotebookPreferenceWithDefault<number>(NotebookPreferences.OUTPUT_FONT_SIZE);

return {
fontSize,
outputFontSize: outputFontSize,
fontFamily: this.preferenceService.get<string>('editor.fontFamily')!,
outputFontFamily: this.getNotebookPreferenceWithDefault<string>(NotebookPreferences.OUTPUT_FONT_FAMILY),
outputLineHeight: this.computeOutputLineHeight(outputLineHeight, outputFontSize ?? fontSize),
outputScrolling: this.getNotebookPreferenceWithDefault<boolean>(NotebookPreferences.OUTPUT_SCROLLING)!,
outputWordWrap: this.getNotebookPreferenceWithDefault<boolean>(NotebookPreferences.OUTPUT_WORD_WRAP)!,
outputLineLimit: this.getNotebookPreferenceWithDefault<number>(NotebookPreferences.OUTPUT_LINE_LIMIT)!
};
}

protected getNotebookPreferenceWithDefault<T>(key: string): T {
return this.preferenceService.get<T>(key, notebookPreferenceSchema.properties?.[key]?.default as T);
}

protected computeOutputLineHeight(lineHeight: number, outputFontSize: number): number {
const minimumLineHeight = 9;

if (lineHeight === 0) {
// use editor line height
lineHeight = this.editorFontInfo.lineHeight;
} else if (lineHeight < minimumLineHeight) {
// Values too small to be line heights in pixels are in ems.
let fontSize = outputFontSize;
if (fontSize === 0) {
fontSize = this.preferenceService.get<number>('editor.fontSize')!;
}

lineHeight = lineHeight * fontSize;
}

// Enforce integer, minimum constraints
lineHeight = Math.round(lineHeight);
if (lineHeight < minimumLineHeight) {
lineHeight = minimumLineHeight;
}

return lineHeight;
}

protected getOrCreateMonacoFontInfo(): BareFontInfo {
if (!this.fontInfo) {
this.fontInfo = this.createFontInfo();
this.editorPreferences.onPreferenceChanged(e => this.fontInfo = this.createFontInfo());
}
return this.fontInfo;
}

protected createFontInfo(): BareFontInfo {
return BareFontInfo.createFromRawSettings({
fontFamily: this.editorPreferences['editor.fontFamily'],
fontWeight: String(this.editorPreferences['editor.fontWeight']),
fontSize: this.editorPreferences['editor.fontSize'],
fontLigatures: this.editorPreferences['editor.fontLigatures'],
lineHeight: this.editorPreferences['editor.lineHeight'],
letterSpacing: this.editorPreferences['editor.letterSpacing'],
}, PixelRatio.value);
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ import { NotebookCellOutputsSplice } from '../notebook-types';
import { NotebookMonacoTextModelService } from '../service/notebook-monaco-text-model-service';
import { NotebookCellOutputModel } from './notebook-cell-output-model';
import { PreferenceService } from '@theia/core/lib/browser';
import { NOTEBOOK_LINE_NUMBERS } from '../contributions/notebook-preferences';
import { NotebookPreferences } from '../contributions/notebook-preferences';
import { LanguageService } from '@theia/core/lib/browser/language-service';

export const NotebookCellModelFactory = Symbol('NotebookModelFactory');
Expand Down Expand Up @@ -245,13 +245,13 @@ export class NotebookCellModel implements NotebookCell, Disposable {
this._internalMetadata = this.props.internalMetadata ?? {};

this.editorOptions = {
lineNumbers: this.preferenceService.get(NOTEBOOK_LINE_NUMBERS)
lineNumbers: this.preferenceService.get(NotebookPreferences.NOTEBOOK_LINE_NUMBERS)
};
this.toDispose.push(this.preferenceService.onPreferenceChanged(e => {
if (e.preferenceName === NOTEBOOK_LINE_NUMBERS) {
if (e.preferenceName === NotebookPreferences.NOTEBOOK_LINE_NUMBERS) {
this.editorOptions = {
...this.editorOptions,
lineNumbers: this.preferenceService.get(NOTEBOOK_LINE_NUMBERS)
lineNumbers: this.preferenceService.get(NotebookPreferences.NOTEBOOK_LINE_NUMBERS)
};
}
}));
Expand Down
26 changes: 4 additions & 22 deletions packages/notebook/src/browser/view/notebook-code-cell-view.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -32,8 +32,7 @@ import { CommandRegistry, DisposableCollection, nls } from '@theia/core';
import { NotebookContextManager } from '../service/notebook-context-manager';
import { NotebookViewportService } from './notebook-viewport-service';
import { EditorPreferences } from '@theia/editor/lib/browser';
import { BareFontInfo } from '@theia/monaco-editor-core/esm/vs/editor/common/config/fontInfo';
import { PixelRatio } from '@theia/monaco-editor-core/esm/vs/base/browser/browser';
import { NotebookOptionsService } from '../service/notebook-options';

@injectable()
export class NotebookCodeCellRenderer implements CellRenderer {
Expand Down Expand Up @@ -64,7 +63,8 @@ export class NotebookCodeCellRenderer implements CellRenderer {
@inject(CommandRegistry)
protected readonly commandRegistry: CommandRegistry;

protected fontInfo: BareFontInfo | undefined;
@inject(NotebookOptionsService)
protected readonly notebookOptionsService: NotebookOptionsService;

render(notebookModel: NotebookModel, cell: NotebookCellModel, handle: number): React.ReactNode {
return <div>
Expand All @@ -81,7 +81,7 @@ export class NotebookCodeCellRenderer implements CellRenderer {
monacoServices={this.monacoServices}
notebookContextManager={this.notebookContextManager}
notebookViewportService={this.notebookViewportService}
fontInfo={this.getOrCreateMonacoFontInfo()} />
fontInfo={this.notebookOptionsService.editorFontInfo} />
<NotebookCodeCellStatus cell={cell} notebook={notebookModel}
commandRegistry={this.commandRegistry}
executionStateService={this.executionStateService}
Expand All @@ -106,24 +106,6 @@ export class NotebookCodeCellRenderer implements CellRenderer {
return dragImage;
}

protected getOrCreateMonacoFontInfo(): BareFontInfo {
if (!this.fontInfo) {
this.fontInfo = this.createFontInfo();
this.editorPreferences.onPreferenceChanged(e => this.fontInfo = this.createFontInfo());
}
return this.fontInfo;
}

protected createFontInfo(): BareFontInfo {
return BareFontInfo.createFromRawSettings({
fontFamily: this.editorPreferences['editor.fontFamily'],
fontWeight: String(this.editorPreferences['editor.fontWeight']),
fontSize: this.editorPreferences['editor.fontSize'],
fontLigatures: this.editorPreferences['editor.fontLigatures'],
lineHeight: this.editorPreferences['editor.lineHeight'],
letterSpacing: this.editorPreferences['editor.letterSpacing'],
}, PixelRatio.value);
}
}

export interface NotebookCodeCellStatusProps {
Expand Down
Loading

0 comments on commit d79b710

Please sign in to comment.