A JupyterLab extension to facilitate invocation of code formatters for multiple programming languages.
—
Comprehensive notebook cell formatting capabilities including selected cells, all cells, and format-on-save functionality with support for magic commands and special syntax.
Main class for handling notebook cell formatting operations.
class JupyterlabNotebookCodeFormatter extends JupyterlabCodeFormatter {
constructor(
client: JupyterlabCodeFormatterClient,
notebookTracker: INotebookTracker
);
formatAction(config: any, formatter?: string): Promise<void>;
formatSelectedCodeCells(config: any, formatter?: string, notebook?: Notebook): Promise<void>;
formatAllCodeCells(config: any, context: Context, formatter?: string, notebook?: Notebook): Promise<void>;
applicable(formatter: string, currentWidget: Widget): boolean;
}Constructor Parameters:
client - HTTP client for backend communicationnotebookTracker - JupyterLab notebook trackerMethods:
formatAction() - Formats selected cells (wrapper for formatSelectedCodeCells)formatSelectedCodeCells() - Formats currently selected code cellsformatAllCodeCells() - Formats all code cells in the notebookapplicable() - Checks if formatter is applicable to current notebook contextAbstract base class providing common formatting functionality.
abstract class JupyterlabCodeFormatter {
working: boolean;
protected client: JupyterlabCodeFormatterClient;
constructor(client: JupyterlabCodeFormatterClient);
protected formatCode(
code: string[],
formatter: string,
options: any,
notebook: boolean,
cache: boolean
): Promise<any>;
}Properties:
working - Boolean flag indicating if formatting operation is in progressProtected Methods:
formatCode() - Sends code to backend for formattingDefines the context for formatting operations.
interface Context {
saving: boolean;
}Properties:
saving - Indicates if formatting is occurring during save operationimport JupyterlabCodeFormatterClient from './client';
import { JupyterlabNotebookCodeFormatter } from './formatter';
import { INotebookTracker } from '@jupyterlab/notebook';
// Create client and formatter
const client = new JupyterlabCodeFormatterClient();
const notebookFormatter = new JupyterlabNotebookCodeFormatter(client, notebookTracker);// Format selected cells with default formatter
await notebookFormatter.formatSelectedCodeCells(config);
// Format selected cells with specific formatter
await notebookFormatter.formatSelectedCodeCells(config, 'black');
// Format selected cells in specific notebook
await notebookFormatter.formatSelectedCodeCells(config, undefined, notebook);// Format all cells (manual operation)
await notebookFormatter.formatAllCodeCells(
config,
{ saving: false }
);
// Format all cells during save operation
await notebookFormatter.formatAllCodeCells(
config,
{ saving: true },
'black'
);import { Widget } from '@lumino/widgets';
const currentWidget: Widget = app.shell.currentWidget;
const isApplicable = notebookFormatter.applicable('black', currentWidget);
if (isApplicable) {
await notebookFormatter.formatAction(config, 'black');
}The formatter identifies code cells to format based on:
formatSelectedCodeCells is called, only selected/active cells are formattedformatAllCodeCells is called, all code cells in the notebook are formattedmodel.type === 'code' are processedThe formatter determines the programming language through:
metadata.kernelspec.languagemetadata.language_info.codemirror_mode// Example of how default formatters are selected
const notebookType = getNotebookType(); // "python", "r", etc.
const defaultFormatters = config.preferences.default_formatter[notebookType];
// Can be a single formatter string or array of formatters
if (Array.isArray(defaultFormatters)) {
// Apply multiple formatters in sequence
for (const formatter of defaultFormatters) {
await applyFormatter(formatter);
}
} else if (defaultFormatters) {
// Apply single formatter
await applyFormatter(defaultFormatters);
}The formatter provides comprehensive error handling:
The formatter preserves Jupyter notebook magic commands and special syntax:
%matplotlib inline, %time, etc.%%bash, %%html, %%javascript, etc.?function_name, ??function_name!ls, !pip install package#| label: fig-plotThese are temporarily escaped before formatting and restored afterward to prevent formatter corruption.
Each formatter can have specific configuration options:
// Example configuration
const config = {
black: {
line_length: 88,
string_normalization: true,
magic_trailing_comma: true
},
isort: {
multi_line_output: 3,
include_trailing_comma: true,
force_grid_wrap: 0
},
preferences: {
default_formatter: {
python: ['isort', 'black'],
r: ['formatR']
}
},
formatOnSave: true,
cacheFormatters: true,
suppressFormatterErrors: false,
suppressFormatterErrorsIFFAutoFormatOnSave: true
};Install with Tessl CLI
npx tessl i tessl/pypi-jupyterlab-code-formatter