Detailed Installation Guide#

Python#

  1. Install the package

pip install jupyterlab-code-formatter
conda install -c conda-forge jupyterlab_code_formatter
poetry add jupyterlab-code-formatter
pipenv install jupyterlab-code-formatter
  1. Install some supported formatters

Install any desired formatter from the below list

# NOTE: You don't have to install all of them if you don't want to.
pip install black
pip install yapf
pip install isort
pip install autopep8
# NOTE: You don't have to install all of them if you don't want to.
conda install -c conda-forge black
conda install -c conda-forge yapf
conda install -c conda-forge isort
conda install -c conda-forge autopep8
# NOTE: You don't have to install all of them if you don't want to.
poetry add black
poetry add yapf
poetry add isort
poetry add autopep8
# NOTE: You don't have to install all of them if you don't want to.
pipenv install black
pipenv install yapf
pipenv install isort
pipenv install autopep8
  1. Restart JupyterLab

This plugin includes a server plugin, restart JupyterLab if you have followed the above steps while it’s running.

  1. Configure plugin

To configure which/how formatters are invoked, see configuration.

R#

  1. Install Python -> R Bridge

pip install rpy2
conda install -c conda-forge rpy2
poetry add rpy2
pipenv install jupyterlab-code-formatter
  1. Install the package

pip install jupyterlab-code-formatter
conda install -c conda-forge jupyterlab_code_formatter
poetry add jupyterlab-code-formatter
pipenv install jupyterlab-code-formatter
  1. Install some supported formatters Install any desired formatter from the below list.

# NOTE: You don't have to install all of them if you don't want to.
R --vanilla -e 'install.packages("formatR", repos = "http://cran.us.r-project.org")'
R --vanilla -e 'install.packages("styler", repos = "http://cran.us.r-project.org")'
  1. Restart JupyterLab

This plugin includes a server plugin, restart JupyterLab if you have followed the above steps while it’s running.

  1. Configure plugin

To configure which/how formatters are invoked, see configuration.

Usage#

Preface#

This plugin registers JupyterLab commands when supported formatters are detected.

Here is a non-exhaustive list of possibilities:

  • jupyterlab_code_formatter:black

  • jupyterlab_code_formatter:isort

  • jupyterlab_code_formatter:yapf

  • jupyterlab_code_formatter:formatr

  • jupyterlab_code_formatter:styler

These commands invoke the specified code formatter in the current focused cell.

To find out what formatters are available, you can query http://localhost:8888/jupyterlab_code_formatter/formatters (you might need to replace the port and address), the keys of formatter are shown there.


In addition to the above commands, this plugin also adds two non-formatter-specific commands:

  • jupyterlab_code_formatter:format

  • jupyterlab_code_formatter:format_all

These commands invoke the configured default code formatters, to configure the default code formatters see here.

Invoke Default Code Formatter(s)#

Here are some examples showing how to invoke the default code formatter(s) via comand palette.

For Focused Cell(s)#

Example using the context menu:

format-selected

You can also achieve this by invoking jupyterlab_code_formatter:format.

For The Entire Document#

Example using the button on the toolbar:

format-all

You can also achieve this by invoking jupyterlab_code_formatter:format_all.

Invoke Specific Code Formatter#

Example using the command palette or menu bar:

format-specific

You can also achieve this by invoking jupyterlab_code_formatter:black for example, see possiblities in the preface.

Configuration#

For configuring this plugin, I highly recommend you turn use the JSON Settings Editor instead of the weird graphical settings editor.

settings

Format On Save#

In the settings page, include the following key value pair:-

{
  "formatOnSave": true
}

Note

Settings can be found in “Settings” in the toolbar > “Advanced Settings Editor” > “Jupyterlab Code Formatter”.

This invokes jupyterlab_code_formatter:format_all every time you save, which uses the default formatters specified in settings.

Keyboard Shortcuts#

To add a keyboard shortcut calling the JupyterLab commands registered by this plugin (documented here), add an entry in the Advanced Setting Edtior of JupyterLab (TDOO: How to get there.) like so:-

{
  "shortcuts": [
    {
      "command": "jupyterlab_code_formatter:format",
      "keys": [
        "Ctrl K",
        "Ctrl M"
      ],
      "selector": ".jp-Notebook.jp-mod-editMode"
    }
  ]
}

The above example breaks down to

  • Under edit mode (detected through the selector);

  • Using the chord Ctrl+K Ctrl+M;

  • Invoke the jupyterlab_code_formatter:format command;

Changing Default Formatter(s)#

The jupyterlab_code_formatter:format and jupyterlab_code_formatter:format_all JupyterLab commands will always invoke the formatter(s) specified in the settings.

Note

Settings can be found in “Settings” in the toolbar > “Advanced Settings Editor” > “Jupyterlab Code Formatter”.

To override the default settings, enter something like so in the “User Preferences” panel of the settings:-

{
    "preferences": {
        "default_formatter": {
            "python": "autopep8",
            "R": "styler"
        }
    }
}

Changing Formatter Parameters#

Sometimes the stock default config of a code formatter doesn’t suit your need, you can override the code formatter in the settings.

Note

Settings can be found in “Settings” in the toolbar > “Advanced Settings Editor” > “Jupyterlab Code Formatter”.

For example to override settings for the autopep8 formatter, enter something like so in the “User Preferences” pnael of the settings:-

{
  "autopep8": {
    "max_line_length": 120,
    "ignore": [
      "E226",
      "E302",
      "E41"
    ]
  }
}

Warning

This plugin does not pick up file based configuration at the moment (e.g. setup.cfg, pyproject.yml, etc.)

Ticket is already opened at #167.

Warning

This plugin might be out of sync with the list of possibilities of configuration option.

See settings.json for the JSON schema used, feel free to open a PR for updating it.

Chaining Formatters Invocation#

The jupyterlab_code_formatter:format and jupyterlab_code_formatter:format_all JupyterLab commands support invocation of multiple formatters one after the other via settings.

Note

Settings can be found in “Settings” in the toolbar > “Advanced Settings Editor” > “Jupyterlab Code Formatter”.

To do so, configure the default formatter to be an array of strings:-

{
    "preferences": {
        "default_formatter": {
            "python": ["isort", "black"],
            "R": ["styler", "formatR"]
        }
    }
}

R Formatter Configuration Example#

R formatters are a little finicky to configure, the list construct in R is actually a JSON dictionary, to configure value of math_token_spacing and reindention of styler, do something like so:-

{
    "styler": {
        "math_token_spacing": {
            "zero":["'^'"],
            "one":["'+'", "'-'", "'*'","'/'"]
        },
        "reindention": {
            "regex_pattern" : "^###",
            "indention" : 0,
            "comments_only" : true}
    }
}

Once again this is done in the settings page.

Note

Settings can be found in “Settings” in the toolbar > “Advanced Settings Editor” > “Jupyterlab Code Formatter”.

Adding Custom Formatters#

To define a custom formatter, you can do so in the Jupyter notebook configuration (usually found ~/.jupyter/jupyter_notebook_config.py or something along those lines), the following example adds a rather useless formatter as a example.


from jupyterlab_code_formatter.formatters import BaseFormatter, handle_line_ending_and_magic, SERVER_FORMATTERS

class ExampleCustomFormatter(BaseFormatter):

    label = "Apply Example Custom Formatter"

    @property
    def importable(self) -> bool:
        return True

    @handle_line_ending_and_magic
    def format_code(self, code: str, notebook: bool, **options) -> str:
        return "42"
        
SERVER_FORMATTERS["example"] = ExampleCustomFormatter()

When implementing your customer formatter using third party library, you will likely use try... except in the importable block instead of always returning True.

Remember you are always welcomed to submit a pull request!

Frequently Asked Questions#

Error When Writing Grammar Tables#

It is possible that black will fail when trying to create local cache directory, you can resovle this by creating the directory yourself (elevated permissions might be required):-

python -c "import black; black.CACHE_DIR.mkdir(parents=True, exist_ok=True)"

For more information, see issue #10.

JupyterLab Commands Not Showing Up#

Make sure you really have one of the formatters properly installed in the Jupyter Server’s environment.

The plugin is also configured to only show commands when a suitable notebook/script is opened, it’s worth checking if you have opened one such notebook/script.

#

JupyterHub#

This plugin should work under a JupyterHub environment, however due to the difference in how JupyterHub starts the JupyterLab instance, one would need to enable the server extension with the --sys-prefix flag, that is:

jupyter serverextension enable --py jupyterlab_code_formatter --sys-prefix

Changelog#

2.1.0 2023-05-08#

Jupyterlab extension

  • Support for JupyterLab 3.6+/4+ and Notebook v7, courtesy of mcrutch;

    • This will drop support for jupyterlab<=3.5!

2.0.0 2023-05-08#

General

  • Major refactor of repo, now based off the update jupyterlab extension cookiecutter;

  • Introduce an actually working dockerised dev env;

Server extension

  • Add ruff support - courtesy of felix-cw;

Jupyterlab extension

  • Add ruff support - courtesy of felix-cw;

1.6.1 2023-04-16#

Server extension

  • Use importlib instead of pkg_resources which is being deprecated;

1.6.0 2023-03-26#

Server extension

  • Swap importable check to something more performant - courtesy of krassowski;

Jupyterlab extension

  • Add more isort configuration settings - courtesy of dcnadler;

1.5.3 2022-08-10#

Server extension

  • Remove implicit dependency of which binary - courtesy of KanchiShimono;

1.5.2 2022-08-06#

Server extension

  • Add AStyle support using `subprocess - courtesy of nthiery;

1.5.1 2022-07-24#

General

  • Add rustfmt support using subprocess - courtesy of andrelfpinto;

  • Add docs for adding a custom formatter;

Server extension

  • Handle single/double leading question mark properly;

  • Re-add trailing new line if not in notebook;

Jupyterlab extension

  • Suppress cell skipped error properly if configured to suppress;

1.5.0 2022-07-16#

General

  • Add scalafmt support using subprocess - courtesy of andrelfpinto;

  • Add Py10 to supported list - courtesy of haoxins;

  • Better error message - courtesy of ianhi;

  • Support more black configuration - courtesy of utkarshgupta137;

Server extension

  • Make server extension work without notebook package, courtesy of KanchiShimono;

Jupyterlab extension

  • Fix JSON schemas - courtesy of KanchiShimono;

  • Fix UI errors in configuration screen - courtesy of KanchiShimono;

1.4.11 2022-05-01#

General

  • Revamp documentation site;

  • Revamp development environment;

Server extension

  • Escape Quarto’s comment to exmept it from formatting - thanks rgaiacs for providing test case;

  • Add support for blue formatter;

  • Restore easily accessible formatter list API;

  • Escape run script command in JupyterLab;

Jupyterlab extension

  • Add suppress formatter errors setting;

1.4.10 2021-04-02#

Server extension

  • Ignore more magic;

Jupyterlab extension

No change.

1.4.9 2021-04-02#

Server extension

  • Don’t expect options to be always passed;

Jupyterlab extension

No change.

1.4.8 2021-04-02#

Server extension

  • Improve interactive help regex - again;

Jupyterlab extension

  • Remove include_trailing_comma option for black, it’s not an option to begin with.

1.4.7 2021-04-01#

Server extension

  • Improve interactive help regex;

Jupyterlab extension

No change.

1.4.6 2021-04-01#

Server extension

  • Improve interactive help regex;

Jupyterlab extension

  • Support noop/skip in default formatters setting;

1.4.5 2021-03-14#

Server extension

  • Ignore interactive help lines while formatting;

Jupyterlab extension

No change.

1.4.4 2021-02-13#

Server extension

  • Handle incompatible magic language cellblock better;

Jupyterlab extension

  • Auto format on save as an option - courtesy of simamumu;

1.4.3 2021-01-01#

Server extension

  • Attempt to address JupyterHub precarity - courtesy of SarunasAzna;

Jupyterlab extension

No changes.

1.4.2 2021-01-01#

Server extension

  • Attempt to auto enable server extension - courtesy of fcollonval;

Jupyterlab extension

No changes.

1.4.1 2021-01-01#

Server extension

No changes.

Jupyterlab extension

No changes.

General

  • Fix package publish procedure;

1.4.0 2021-01-01#

Server extension

No changes.

Jupyterlab extension

  • Minor fix for error messages;

General

  • Project reorganisation, improve plugin packaging, massive thanks to ianhi for laying the groundwork;

1.3.8 2020-11-17#

Server extension

No changes.

Jupyterlab extension

  • Fix icon color in dark theme, courtesy of AllanChain;

1.3.7 2020-11-15#

Server extension

  • Handle shell commands in code cells;

Jupyterlab extension

No changes.

1.3.6 2020-08-08#

Server extension

No changes.

Jupyterlab extension

  • Fix isort schema spec for the following settings:

    • known_future_library

    • known_standard_library

    • known_third_party

    • known_first_party

1.3.5 2020-07-18#

Server extension

No changes.

Jupyterlab extension

  • Fix server URL lookup for JupyterLab 2.2.0+;

1.3.4 2020-07-11#

Server extension

  • Fix semicolon handling again;

Jupyterlab extension

No changes.

1.3.3 2020-07-10#

Server extension

  • Support isort 5 and also isort 4 at the same time, courtesy of dialvarezs;

Jupyterlab extension

No changes.

1.3.2 2020-07-08#

Server extension

  • Fix semicolon handling again; (This was mistakenly removed in 1.3.3 later on, and reintroduced later.)

  • Improve error message when formatter is not found;

Jupyterlab extension

No changes.

1.3.1 2020-05-08#

Same as 1.3.0.

1.3.0 2020-05-08#

Server extension

  • Move cell/file ending handling back to server extension;

  • Fix semicolon handling;

Jupyterlab extension

  • Move cell/file ending handling back to server extension;

  • Fix erroneous detection of R default formatters;

1.2.5 2020-04-25#

Server extension

  • Ignore magic and trailing semicolon for R formatters;

Jupyterlab extension

No changes.

1.2.4 2020-04-18#

Server extension

  • Fix detect notebook type fallback - courtesy of devstein;

Jupyterlab extension

No changes.

1.2.3 2020-04-09#

Server extension

No changes.

Jupyterlab extension

  • Add detect notebook type fallback;

  • Make failure to determin default formatters more prominent;

1.2.2 2020-03-14#

Server extension

No changes.

Jupyterlab extension

  • Fix error reporting when blank code cell(s) exists;

1.2.1 2020-03-12#

Server extension

  • Add version API handler;

Jupyterlab extension

  • Fully prohibit mismatched lab and server extension usage (accounting for either stale lab or server extension);

  • Use Jupyterlab dialogs for error reporting instead of console for clarity;

  • Support multiple default formatters to be ran in sequence;

1.2.0 2020-03-04#

Server extension

No Changes

Jupyterlab extension

  • Address Jupyter lab 2.0.0 breaing changes;

1.1.0 2020-02-08#

Server extension

  • Defer trailing newline removal to labextension;

  • Prohibit mismatched lab and server extension usage;

Jupyterlab extension

  • Make tool bar format all button respect where it’s clicked;

  • Delete trailing newline for notebook cells only;

  • Prohibit mismatched lab and server extension usage;

1.0.3 2019-12-07#

Server extension

  • Handle :code:indent_by and :code:start_comments_with_one_space for styler;

  • Unify magic and semicolon handling for Python formatters;

Jupyterlab extension

  • Handle :code:indent_by and :code:start_comments_with_one_space for styler;

General

  • Various fixes to docs;

  • Various fixes to Makefile;

1.0.2 2019-12-01#

Server extension

  • Fix optional :code:rpy2 import crashing server extension;

Jupyterlab extension

No changes.

1.0.1 2019-12-01#

No change, simply fixing versioning error.

1.0.0 2019-12-01#

Server extension

  • Fix missing rpy2 import error;

  • Add tests;

Jupyterlab extension

  • Major refactoring;

  • Temporarily removed language filtering for command palette;

  • Tooltip format notebook changed to icon - thanks to mlucool;

General

  • Project reorgnaisation;

  • Use nix for local development environment;

  • Documentation generation;

0.7.0 2019-11-02#

Server extension

  • Support more styler options;

  • Fix bad string comparsion of version strings;

  • Compile regex once only;

Jupyterlab extension

  • Support more styler options;

  • Fix bad capitalisation of config schema;

0.6.1 2019-10-23#

Server extension

  • Retain semicolon after black’s formatting action - courtesy of dfm;

Jupyterlab extension

No Change.

0.6.0 2019-10-16#

Server extension

  • Support formatting multiple code cell at the same time - courtesy of mlucool;

  • Return formatting error if they exists - courtesy of mlucool;

Jupyterlab extension

  • Add jupyterlab_code_foramtter:format command and context menu button - courtesy of mlucool;

  • Add jupyterlab_code_foramtter:format_all command and command tools bar button - courtesy of mlucool;

0.5.2 2019-09-29#

Server extension

  • Trim trialing newline for autopep8;

Jupyterlab extension

No changes.

0.5.1 2019-09-09#

Server extension

  • Fix bug where presence of rpy2 could cause plugin to be useless;

Jupyterlab extension

No changes.

0.5.0 2019-08-21#

Server extension

  • Support styler - Another R code formatter - courtesy of dev-wei;

Jupyterlab extension

  • Support styler - Another R code formatter - courtesy of dev-wei;

0.4.0 2019-08-19#

Server extension

  • Support formatr - A R code formatter - courtesy of dev-wei;

Jupyterlab extension

  • Support formatr - A R code formatter - courtesy of dev-wei;

0.3.0 2019-07-10#

General

  • Minor updates to README - courtesy of reza1615;

Server extension

No Change

Jupyterlab extension

  • Support Jupyterlab ^1.0.0 - courtesy of gnestor;

  • Remove custom_style enum restriction - courtesy of CaselIT;

  • Add companion packages info;

0.2.3 2019-06-17#

Same as v0.2.2 - Re-publishing because I messed up the versioning.

0.2.2 2019-06-17#

General

  • Minor updates to README - courtesy of akashlakhera and mzakariaCERN;

Server extension

No Change

Jupyterlab extension

  • Remove some excessive logging - courtesy of jtpio;

  • Make formatter commands visible for Python files and notebooks only - courtesy of jtpio;

0.2.1 2019-04-29#

General

  • Add Binder to README - courtesy of jtpio;

  • Add a test notebook for easier testing with Binder;

Server extension

  • Add LICENSE in sdist - courtesy of xhochy;

  • Handle the exsistence of magic commands in codecell for Black - courtesy of Lif3line;

Jupyterlab extension

No Change

0.2.0 2019-03-24#

  • Handle format_str interface change for black>=19.3b0;

  • Support Isort as a formatter;

  • Bugfixes - courtesy of gnestor;

0.1.8 2019-02-16#

  • Minor fix for formatting files in code cells;

0.1.7 2019-02-16#

  • Support formatting files in FileEditor - courtesy of rbedi;

0.1.6 2019-01-19#

  • Expose autopep8 options - courtesy of timlod;

0.1.5 2018-12-01#

  • Add commands to the main menu for better accessibility - courtesy of jtpio;

0.1.4 2018-10-10#

  • Bump dependency ranges;

0.1.3 2018-08-24#

  • Fix typo in command;

0.1.2 2018-08-24#

  • Bump dependency ranges;

0.1.1 2018-08-18#

  • Minor README update;

0.1.0 2018-08-18#

  • Inital implementation;

Development#

Prerequisites:

  • Install task;

  • Install docker, with buildkit;

  1. Spin up docker compose based dev env - task dev:up

  2. Run jlpm watch inside dev container - task dev:jlpm-watch

  3. In another terminal, run jupyter lab inside dev container - task dev:jupyter-lab

This watches the source directory and run JupyterLab at the same time in different terminals to watch for changes in the extension’s source and automatically rebuild the extension inside the dev docker container.

With the watch command running, every saved change will immediately be built locally and available in your running JupyterLab. Refresh JupyterLab to load the change in your browser (you may need to wait several seconds for the extension to be rebuilt).

Your Support#

I could really use your support in giving me a star on GitHub, recommending features, fixing bugs or maybe even providing monetary support!

JupyterLab Code Formatter#

A JupyterLab plugin to facilitate invocation of code formatters.

Source Code: GitHub.

Demo#

format-all

Requirements#

  • Python 3.7+

  • JupyterLab >= 3.6.0 (if you are using JupyterLab>=3.0,<=3.5, pin this package to 2.0.0)

  • Any supported code formatters (you can also specify your own, see custom formatter).

Important

JupyterLab Code Formatter only provides an interface for invoking code formatters on Jupyter Server, and does not include any code formatter by default.

Quick Start#

  1. Install the package

pip install jupyterlab-code-formatter
poetry add jupyterlab-code-formatter
pipenv install jupyterlab-code-formatter
  1. Install some supported formatters (isort+black are default for Python)

# NOTE: Install black and isort,
#       JL code formatter is configured to invoke isort and black by default
pip install black isort
# NOTE: Install black and isort,
#       JL code formatter is configured to invoke isort and black by default
poetry add black isort
# NOTE: Install black and isort,
#       JL code formatter is configured to invoke isort and black by default
pipenv install black isort
  1. Restart JupyterLab

This plugin includes a server plugin, as suck you will need to restart JupyterLab if you have followed the above steps while it’s running.

  1. Configure plugin

To configure which/how formatters are invoked, see configuration.