A JupyterLab extension to facilitate invocation of code formatters for multiple programming languages.
—
JupyterLab settings integration with support for formatter-specific options, format-on-save settings, error handling preferences, and language-specific default formatters.
The extension provides a comprehensive JSON schema for configuration.
Schema Location: schema/settings.json
{
"formatOnSave": {
"type": "boolean",
"default": false,
"description": "Automatically format code when saving files"
}
}{
"cacheFormatters": {
"type": "boolean",
"default": true,
"description": "Cache formatter availability checks for better performance"
}
}{
"suppressFormatterErrors": {
"type": "boolean",
"default": false,
"description": "Suppress formatter error dialogs globally"
},
"suppressFormatterErrorsIFFAutoFormatOnSave": {
"type": "boolean",
"default": true,
"description": "Suppress errors only during automatic format-on-save"
}
}Language-specific default formatter settings.
{
"preferences": {
"type": "object",
"properties": {
"default_formatter": {
"type": "object",
"properties": {
"python": {
"anyOf": [
{ "type": "string" },
{ "type": "array", "items": { "type": "string" } }
],
"default": ["isort", "black"]
},
"R": {
"anyOf": [
{ "type": "string" },
{ "type": "array", "items": { "type": "string" } }
]
}
},
"additionalProperties": true
}
}
}
}{
"black": {
"type": "object",
"properties": {
"line_length": {
"type": "number",
"default": 88,
"description": "Maximum line length"
},
"string_normalization": {
"type": "boolean",
"default": true,
"description": "Normalize string quotes"
},
"magic_trailing_comma": {
"type": "boolean",
"default": true,
"description": "Use trailing commas"
},
"experimental_string_processing": {
"type": "boolean",
"default": false,
"description": "Enable experimental string processing"
},
"preview": {
"type": "boolean",
"default": false,
"description": "Enable preview features"
}
}
}
}{
"blue": {
"type": "object",
"properties": {
"line_length": {
"type": "number",
"default": 88
},
"string_normalization": {
"type": "boolean",
"default": true
}
}
}
}{
"autopep8": {
"type": "object",
"properties": {
"max_line_length": {
"type": "number",
"default": 79
},
"aggressive": {
"type": "number",
"default": 0,
"description": "Aggressiveness level (0-2)"
}
}
}
}{
"yapf": {
"type": "object",
"properties": {
"based_on_style": {
"type": "string",
"default": "pep8",
"enum": ["pep8", "google", "chromium", "facebook"]
},
"column_limit": {
"type": "number",
"default": 79
},
"indent_width": {
"type": "number",
"default": 4
}
}
}
}{
"isort": {
"type": "object",
"properties": {
"multi_line_output": {
"type": "number",
"default": 3,
"description": "Multi-line output mode"
},
"include_trailing_comma": {
"type": "boolean",
"default": true
},
"force_grid_wrap": {
"type": "number",
"default": 0
},
"use_parentheses": {
"type": "boolean",
"default": true
},
"line_length": {
"type": "number",
"default": 88
}
}
}
}{
"ruff": {
"type": "object",
"properties": {
"line_length": {
"type": "number",
"default": 88
},
"select": {
"type": "array",
"items": { "type": "string" },
"description": "Rule codes to enable"
},
"ignore": {
"type": "array",
"items": { "type": "string" },
"description": "Rule codes to ignore"
}
}
}
}{
"formatOnSave": true,
"cacheFormatters": true,
"suppressFormatterErrors": false,
"suppressFormatterErrorsIFFAutoFormatOnSave": true,
"preferences": {
"default_formatter": {
"python": ["isort", "black"],
"r": "formatR",
"scala": "scalafmt",
"rust": "rustfmt",
"cpp": "astyle"
}
},
"black": {
"line_length": 88,
"string_normalization": true,
"magic_trailing_comma": true,
"experimental_string_processing": false,
"preview": false
},
"isort": {
"multi_line_output": 3,
"include_trailing_comma": true,
"force_grid_wrap": 0,
"use_parentheses": true,
"line_length": 88,
"profile": "black"
},
"yapf": {
"based_on_style": "google",
"column_limit": 100,
"indent_width": 2
},
"ruff": {
"line_length": 88,
"select": ["E", "F", "W"],
"ignore": ["E501"]
}
}import { ISettingRegistry } from '@jupyterlab/settingregistry';
// In the extension class
private async setupSettings() {
const settings = await this.settingRegistry.load('jupyterlab_code_formatter:settings');
const onSettingsUpdated = (jsettings: ISettingRegistry.ISettings) => {
this.config = jsettings.composite;
};
settings.changed.connect(onSettingsUpdated);
onSettingsUpdated(settings);
}
// Access configuration values
if (this.config.formatOnSave) {
// Perform format on save
}
const blackOptions = this.config.black || {};
const defaultFormatters = this.config.preferences?.default_formatter?.python || [];# Configuration is passed from frontend to backend via HTTP API
def format_code(self, code: str, notebook: bool, **options) -> str:
# Options contain formatter-specific configuration
line_length = options.get('line_length', 88)
string_normalization = options.get('string_normalization', True)
# Use options to configure formatter
black_mode = black.FileMode(
line_length=line_length,
string_normalization=string_normalization,
**options
)
return black.format_str(code, mode=black_mode)The extension integrates with JupyterLab's settings system:
ISettingRegistry serviceUsers can modify settings through:
The extension provides sensible defaults:
false (user must opt-in)true (performance optimization)false (show errors by default)["isort", "black"]{
"preferences": {
"default_formatter": {
"python": ["isort", "black"] // Multiple formatters in order
}
},
"black": { "line_length": 88 },
"isort": { "profile": "black" }
}{
"preferences": {
"default_formatter": {
"R": "styler" // Single formatter
}
},
"styler": {
"scope": "tokens",
"indent_by": 2
}
}{
"preferences": {
"default_formatter": {
"python": ["isort", "black"],
"r": "formatR",
"scala": "scalafmt",
"rust": "rustfmt",
"cpp": "astyle"
}
}
}{
// Show all errors (default)
"suppressFormatterErrors": false,
"suppressFormatterErrorsIFFAutoFormatOnSave": false,
// Suppress errors only during auto-format (recommended)
"suppressFormatterErrors": false,
"suppressFormatterErrorsIFFAutoFormatOnSave": true,
// Suppress all errors (not recommended)
"suppressFormatterErrors": true,
"suppressFormatterErrorsIFFAutoFormatOnSave": true
}{
"cacheFormatters": true // Cache formatter availability checks
}Benefits of caching:
{
"formatOnSave": true,
"suppressFormatterErrorsIFFAutoFormatOnSave": true // Avoid error dialogs during save
}This configuration enables automatic formatting while preventing disruptive error dialogs during the save process.
Install with Tessl CLI
npx tessl i tessl/pypi-jupyterlab-code-formatter