Per folder custom titles for Jupyter notebooks

    Per folder custom titles for Jupyter notebooks

    I work on many different projects and I use some ActivityWatch for automatic time tracking. AW has a feature where you can use regexes to match window titles to assign them automatically to different projects. But, unfortunately, Jupyter Notebook have a "{filename} - Jupyter Notebook" title in the browser, so it's hard to match on them. I'd rather not name all the notebook with a prefix of the project, so I went looking for a different solution.

    I quickly found a way to customize the title shown in the browser, but not in a dynamic way (aka dependent on the folder I'm in).

    To get dynamic custom titles, I had to first update in the config file used by Jupyter (~/.jupyter/jupyter_notebook_config.py) the following two values:

    c.NotebookApp.extra_template_paths = ["~/.jupyter/templates/"]
    
    import os
    from pathlib import Path
    
    cur_dir = os.getcwd()
    
    projects = {
            'folder_name1': 'Project 1',
            'folder_name2': "Project 2",
    }
    
    cur_env = Path(cur_dir).name
    for p in projects:
        if p in cur_dir:
            cur_env = projects[p]
        
    c.NotebookApp.jinja_template_vars = {"env_name": cur_env}

    The first line add a new path where Jupyter looks for HTML templates. Then I get the name of the current working directory. I look for some folder names and if they match, I get the project name, otherwise I'll use as project name the name of the current working directory. On the last line I inject the env_name variable into every Jinja2 template used by Jupyter.

    Then I copied into ~/.jupyter/templates/page.html the template file from the notebook project and at the end of the last script block, I added the following:

    {% if env_name %}
    window.title += " - {{ env_name }}";
    document.__defineSetter__('title', function(val) {
        document.querySelector('title').childNodes[0].nodeValue = val + " - {{ env_name }}";
    });
    {% endif %}

    First I check if env_name is set. If it is, I add Javascript code which will add the value of it to the window title, and also will update the window title whenever it changes (such as when you rename the file).

    This is a bit hackish and when the notebook templates update, I should update my own copy as well. Luckily, it doesn't change too often, there being only 5 commits since 2020.