A JupyterLab extension to facilitate invocation of code formatters for multiple programming languages.
—
File editor formatting capabilities for standalone code files with MIME type-based language detection and format-on-save support.
Main class for handling file editor formatting operations.
class JupyterlabFileEditorCodeFormatter extends JupyterlabCodeFormatter {
constructor(
client: JupyterlabCodeFormatterClient,
editorTracker: IEditorTracker
);
formatAction(config: any, formatter: string): Promise<void>;
formatEditor(config: any, context: Context, formatter?: string): Promise<void>;
applicable(formatter: string, currentWidget: Widget): boolean;
}Constructor Parameters:
client - HTTP client for backend communicationeditorTracker - JupyterLab file editor trackerMethods:
formatAction() - Formats current editor (wrapper for formatEditor)formatEditor() - Formats the currently active file editorapplicable() - Checks if formatter is applicable to current editor contextimport JupyterlabCodeFormatterClient from './client';
import { JupyterlabFileEditorCodeFormatter } from './formatter';
import { IEditorTracker } from '@jupyterlab/fileeditor';
// Create client and formatter
const client = new JupyterlabCodeFormatterClient();
const fileFormatter = new JupyterlabFileEditorCodeFormatter(client, editorTracker);// Format with default formatter for file type
await fileFormatter.formatEditor(config, { saving: false });
// Format with specific formatter
await fileFormatter.formatEditor(config, { saving: false }, 'black');
// Format during save operation
await fileFormatter.formatEditor(config, { saving: true }, 'rustfmt');// Convenient wrapper for manual formatting
await fileFormatter.formatAction(config, 'black');import { Widget } from '@lumino/widgets';
const currentWidget: Widget = app.shell.currentWidget;
const isApplicable = fileFormatter.applicable('rustfmt', currentWidget);
if (isApplicable) {
await fileFormatter.formatAction(config, 'rustfmt');
}The file editor formatter detects programming languages through MIME type analysis:
// MIME type to language mapping
const mimeTypes = new Map([
['text/x-python', 'python'],
['application/x-rsrc', 'r'],
['application/x-scala', 'scala'],
['application/x-rustsrc', 'rust'],
['application/x-c++src', 'cpp']
]);Supported MIME Types:
text/x-python → Python files (.py)application/x-rsrc → R files (.r, .R)application/x-scala → Scala files (.scala)application/x-rustsrc → Rust files (.rs)application/x-c++src → C++ files (.cpp, .cxx, .cc)Default formatters are configured per programming language:
// Example configuration
const config = {
preferences: {
default_formatter: {
python: ['isort', 'black'],
r: ['formatR'],
scala: ['scalafmt'],
rust: ['rustfmt'],
cpp: ['astyle']
}
}
};The formatter manages editor state during formatting operations:
working = true to prevent concurrent operationseditor.model.sharedModel.sourceworking = false when completeComprehensive error handling for file editor operations:
File editor formatting uses promises for non-blocking operations:
// Example of async formatter chain
for (const formatterToUse of formattersToUse) {
if (formatterToUse === 'noop' || formatterToUse === 'skip') {
continue;
}
const code = editor.model.sharedModel.source;
try {
const result = await this.formatCode(
[code],
formatterToUse,
config[formatterToUse],
false, // not notebook
config.cacheFormatters
);
if (result.code[0].error) {
// Handle error
} else {
// Update editor content
editor.model.sharedModel.source = result.code[0].code;
}
} catch (error) {
// Handle network/API errors
}
}Configure formatters for different file types:
const config = {
preferences: {
default_formatter: {
// Python files
python: 'black', // Single formatter
// or
python: ['isort', 'black'], // Multiple formatters in order
// R files
r: 'formatR',
// Rust files
rust: 'rustfmt',
// C++ files
cpp: 'astyle'
}
},
// Formatter-specific options
black: {
line_length: 88,
string_normalization: true
},
rustfmt: {
edition: '2021',
max_width: 100
},
astyle: {
style: 'google',
indent: 'spaces=2'
}
};The file editor formatter integrates with JupyterLab's document registry:
File editor formatting is accessible through:
File editor settings are managed through JupyterLab's settings system:
Install with Tessl CLI
npx tessl i tessl/pypi-jupyterlab-code-formatter