Commit 40ea1f47 authored by Phil Jones's avatar Phil Jones

Update to be compatible with JupyterLab 3.0.

parent e1a29b85
node_modules
dist
coverage
**/*.d.ts
tests
module.exports = {
extends: [
'eslint:recommended',
'plugin:@typescript-eslint/eslint-recommended',
'plugin:@typescript-eslint/recommended',
'plugin:prettier/recommended'
],
parser: '@typescript-eslint/parser',
parserOptions: {
project: 'tsconfig.json',
sourceType: 'module'
},
plugins: ['@typescript-eslint'],
rules: {
'@typescript-eslint/naming-convention': [
'error',
{
'selector': 'interface',
'format': ['PascalCase'],
'custom': {
'regex': '^I[A-Z]',
'match': true
}
}
],
'@typescript-eslint/no-unused-vars': ['warn', { args: 'none' }],
'@typescript-eslint/no-explicit-any': 'off',
'@typescript-eslint/no-namespace': 'off',
'@typescript-eslint/no-use-before-define': 'off',
'@typescript-eslint/quotes': [
'error',
'single',
{ avoidEscape: true, allowTemplateLiterals: false }
],
curly: ['error', 'all'],
eqeqeq: 'error',
'prefer-arrow-callback': 'error'
}
};
lib/*
node_modules/*
tsconfig.tsbuildinfo
yarn.lock
*.bundle.*
lib/
node_modules/
*.egg-info/
.ipynb_checkpoints
*.tsbuildinfo
finesse-syntax-jupyterlab/labextension
# Created by https://www.gitignore.io/api/python
# Edit at https://www.gitignore.io/?templates=python
### Python ###
# Byte-compiled / optimized / DLL files
__pycache__/
*.py[cod]
*$py.class
# C extensions
*.so
# Distribution / packaging
.Python
build/
develop-eggs/
dist/
downloads/
eggs/
.eggs/
lib/
lib64/
parts/
sdist/
var/
wheels/
pip-wheel-metadata/
share/python-wheels/
.installed.cfg
*.egg
MANIFEST
# PyInstaller
# Usually these files are written by a python script from a template
# before PyInstaller builds the exe, so as to inject date/other infos into it.
*.manifest
*.spec
# Installer logs
pip-log.txt
pip-delete-this-directory.txt
# Unit test / coverage reports
htmlcov/
.tox/
.nox/
.coverage
.coverage.*
.cache
nosetests.xml
coverage.xml
*.cover
.hypothesis/
.pytest_cache/
# Translations
*.mo
*.pot
# Scrapy stuff:
.scrapy
# Sphinx documentation
docs/_build/
# PyBuilder
target/
# pyenv
.python-version
# celery beat schedule file
celerybeat-schedule
# SageMath parsed files
*.sage.py
# Spyder project settings
.spyderproject
.spyproject
# Rope project settings
.ropeproject
# Mr Developer
.mr.developer.cfg
.project
.pydevproject
# mkdocs documentation
/site
# mypy
.mypy_cache/
.dmypy.json
dmypy.json
# Pyre type checker
.pyre/
# End of https://www.gitignore.io/api/python
# OSX files
.DS_Store
node_modules
**/node_modules
**/lib
**/package.json
finesse-syntax-jupyterlab
{
"singleQuote": true,
"trailingComma": "none",
"arrowParens": "avoid"
}
BSD 3-Clause License
Copyright (c) 2020, Philip Jones All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright notice, this
list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
* Neither the name of the copyright holder nor the names of its
contributors may be used to endorse or promote products derived from
this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
include LICENSE
include README.md
include pyproject.toml
include jupyter-config/finesse-syntax-jupyterlab.json
include package.json
include install.json
include ts*.json
include yarn.lock
graft finesse-syntax-jupyterlab/labextension
# Javascript files
graft src
graft style
prune **/node_modules
prune lib
# Patterns to exclude from any directory
global-exclude *~
global-exclude *.pyc
global-exclude *.pyo
global-exclude .git
global-exclude .ipynb_checkpoints
# Finesse Syntax for JupyterLab
# finesse-syntax-jupyterlab
![Github Actions Status](http://gitlab.sr.bham.ac.uk/pjj/finesse-syntax-jupyterlab.git/workflows/Build/badge.svg)
Syntax highlighting for KatScript within JupyterLab.
## Requirements
* JupyterLab >= 3.0
## Install
```bash
pip install finesse-syntax-jupyterlab
```
## Contributing
### Development install
Note: You will need NodeJS to build the extension package.
The `jlpm` command is JupyterLab's pinned version of
[yarn](https://yarnpkg.com/) that is installed with JupyterLab. You may use
`yarn` or `npm` in lieu of `jlpm` below.
```bash
# Clone the repo to your local environment
# Change directory to the finesse-syntax-jupyterlab directory
# Install package in development mode
pip install -e .
# Link your development version of the extension with JupyterLab
jupyter labextension develop . --overwrite
# If using a server extension, it must be manually installed in develop mode
jupyter server extension enable <extension_name>
# Rebuild extension Typescript source after making changes
jlpm run build
```
You can watch 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.
```bash
# Watch the source directory in one terminal, automatically rebuilding when needed
jlpm run watch
# Run JupyterLab in another terminal
jupyter lab
```
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).
By default, the `jlpm run build` command generates the source maps for this extension to make it easier to debug using the browser dev tools. To also generate source maps for the JupyterLab core extensions, you can run the following command:
```bash
jupyter lab build --minimize=False
```
### Uninstall
## Installation
Use the JupyterLab extension manager, or:
```bash
jupyter labextension install finesse-syntax-jupyterlab
pip uninstall finesse-syntax-jupyterlab
```
{
"packageManager": "python",
"packageName": "finesse-syntax-jupyterlab",
"uninstallInstructions": "Use your Python package manager (pip, conda, etc.) to uninstall the package finesse-syntax-jupyterlab"
}
This diff is collapsed.
......@@ -12,10 +12,14 @@
"url": "http://gitlab.sr.bham.ac.uk/pjj/finesse-syntax-jupyterlab/issues"
},
"license": "BSD-3-Clause",
"author": "Philip Jones",
"author": {
"name": "Philip Jones",
"email": "philip.jones@ligo.org"
},
"files": [
"lib/**/*.{d.ts,eot,gif,html,jpg,js,js.map,json,png,svg,woff2,ttf}",
"tsconfig.json"
"tsconfig.json",
"style/index.js"
],
"main": "lib/index.js",
"types": "lib/index.d.ts",
......@@ -24,23 +28,44 @@
"url": "http://gitlab.sr.bham.ac.uk/pjj/finesse-syntax-jupyterlab.git"
},
"scripts": {
"build": "tsc && cp src/codemirror-multiplex.js lib/",
"clean": "rimraf lib tsconfig.tsbuildinfo",
"build": "jlpm run build:lib && jlpm run build:labextension:dev",
"build:labextension": "jupyter labextension build .",
"build:labextension:dev": "jupyter labextension build --development True .",
"build:lib": "jlpm run copyjs && tsc",
"build:prod": "jlpm run clean && jlpm run build:lib && jlpm run build:labextension:dev",
"clean": "jlpm run clean:lib",
"clean:all": "jlpm run clean:lib && jlpm run clean:labextension",
"clean:labextension": "rimraf finesse-syntax-jupyterlab/labextension",
"clean:lib": "rimraf lib tsconfig.tsbuildinfo",
"copyjs": "mkdir -p lib && cp src/codemirror-my-multiplex.js lib/",
"eslint": "eslint . --ext .ts,.tsx --fix",
"eslint:check": "eslint . --ext .ts,.tsx",
"install:extension": "jlpm run build",
"prepare": "jlpm run clean && jlpm run build",
"watch": "tsc -w"
"watch": "run-p watch:src watch:labextension",
"watch:labextension": "jupyter labextension watch .",
"watch:src": "tsc -w"
},
"dependencies": {
"@jupyterlab/application": "^2.0.0",
"@jupyterlab/notebook": "^2.0.0",
"@jupyterlab/cells": "^2.0.0",
"codemirror": "~5.49.2"
"@jupyterlab/application": "^3.0.9",
"@jupyterlab/cells": "^3.0.9",
"@jupyterlab/notebook": "^3.0.9"
},
"devDependencies": {
"@types/codemirror": "^0.0.76",
"typescript": "~3.7.3",
"rimraf": "~3.0.0"
"@jupyterlab/builder": "^3.0.0",
"@types/codemirror": "^0.0.97",
"@typescript-eslint/eslint-plugin": "^4.8.1",
"@typescript-eslint/parser": "^4.8.1",
"eslint": "^7.14.0",
"eslint-config-prettier": "^6.15.0",
"eslint-plugin-prettier": "^3.1.4",
"npm-run-all": "^4.1.5",
"prettier": "^2.1.1",
"rimraf": "^3.0.2",
"typescript": "~4.1.3"
},
"jupyterlab": {
"extension": true
"extension": true,
"outputDir": "finesse-syntax-jupyterlab/labextension"
}
}
[build-system]
requires = ["jupyter_packaging~=0.9,<2", "jupyterlab~=3.0"]
build-backend = "jupyter_packaging.build_api"
[tool.jupyter-packaging.builder]
factory = "jupyter_packaging.npm_builder"
[tool.jupyter-packaging.build-args]
build_cmd = "build:prod"
npm = ["jlpm"]
[tool.check-manifest]
ignore = ["finesse-syntax-jupyterlab/labextension/**", "yarn.lock", ".*", "package-lock.json"]
"""
finesse-syntax-jupyterlab setup
"""
import json
from pathlib import Path
from jupyter_packaging import (
wrap_installers,
npm_builder,
get_data_files
)
import setuptools
HERE = Path(__file__).parent.resolve()
# The name of the project
name = "finesse-syntax-jupyterlab"
lab_path = (HERE / name / "labextension")
# Representative files that should exist after a successful build
ensured_targets = [
str(lab_path / "package.json"),
str(lab_path / "static/style.js")
]
labext_name = "finesse-syntax-jupyterlab"
data_files_spec = [
("share/jupyter/labextensions/%s" % labext_name, str(lab_path), "**"),
("share/jupyter/labextensions/%s" % labext_name, str(HERE), "install.json"),
]
post_develop = npm_builder(
build_cmd="install:extension", source_dir="src", build_dir=lab_path
)
cmdclass = wrap_installers(post_develop=post_develop, ensured_targets=ensured_targets)
long_description = (HERE / "README.md").read_text()
# Get the package info from package.json
pkg_json = json.loads((HERE / "package.json").read_bytes())
setup_args = dict(
name=name,
version=pkg_json["version"],
url=pkg_json["homepage"],
author=pkg_json["author"]["name"],
author_email=pkg_json["author"]["email"],
description=pkg_json["description"],
license=pkg_json["license"],
long_description=long_description,
long_description_content_type="text/markdown",
cmdclass=cmdclass,
data_files=get_data_files(data_files_spec),
packages=setuptools.find_packages(),
install_requires=[
"jupyterlab~=3.0",
"jupyter_packaging~=0.9,<2"
],
zip_safe=False,
include_package_data=True,
python_requires=">=3.6",
platforms="Linux, Mac OS X, Windows",
keywords=["Jupyter", "JupyterLab", "JupyterLab3"],
classifiers=[
"License :: OSI Approved :: BSD License",
"Programming Language :: Python",
"Programming Language :: Python :: 3",
"Programming Language :: Python :: 3.6",
"Programming Language :: Python :: 3.7",
"Programming Language :: Python :: 3.8",
"Programming Language :: Python :: 3.9",
"Framework :: Jupyter",
],
)
if __name__ == "__main__":
setuptools.setup(**setup_args)
import {
Mode
} from '@jupyterlab/codemirror'
import { defineMultiplexingMode } from './codemirror-my-multiplex';
import { defineFinesse2Mode } from './codemirror-finesse2';
import CodeMirror from 'codemirror';
export function setupFinesseCodeMirror(CodeMirror: any): void {
defineMultiplexingMode(CodeMirror);
defineFinesse2Mode(CodeMirror);
import 'codemirror/mode/python/python';
import './codemirror-multiplex';
import './codemirror-finesse2';
CodeMirror.defineMode('finesse-python', (config: any) => {
const pmode = CodeMirror.getMode(config, 'python');
return CodeMirror.myMultiplexingMode(pmode, {
open: /(?=#kat2code)/,
close: /(?=""")/, // Match string end without consuming it
mode: CodeMirror.getMode(config, 'text/x-finesse2'),
delimStyle: 'delim'
});
});
declare module 'codemirror' {
function myMultiplexingMode(outerMode: CodeMirror.Mode<any>, ...others: object[]): CodeMirror.Mode<any>;
}
CodeMirror.defineMIME('text/x-finesse-python', 'finesse-python');
CodeMirror.defineMode("finesse-python", (config) => {
let pmode = CodeMirror.getMode(config, "python");
return CodeMirror.myMultiplexingMode(
pmode,
{
open: /(?=#kat2code)/,
close: /(?=""")/, // Match string end without consuming it
mode: CodeMirror.getMode(config, "text/x-finesse2"),
delimStyle: "delim"
}
)
});
CodeMirror.defineMIME("text/x-finesse-python", "finesse-python");
Mode.getModeInfo().push({
name: 'Finesse Python',
mime: "text/x-finesse-python",
mode: 'finesse-python',
ext: [],
});
CodeMirror.modeInfo.push({
name: 'Finesse Python',
mime: 'text/x-finesse-python',
mode: 'finesse-python',
ext: []
});
}
import CodeMirror from 'codemirror';
const components = [
'bs[12]\?',
'dbs',
'gr\d*',
'isol',
'l',
'lens',
'm[12]\?',
'mod',
's',
'sq',
]
'bs[12]?',
'dbs',
'grd*',
'isol',
'l',
'lens',
'm[12]?',
'mod',
's',
'sq'
];
const detectors = [
'ad',
'beam',
'bp',
'cp',
'guoy',
'hd',
'pd[SN]\?\d*',
'pgaind',
'qd',
'q\d*hd\?',
'qhd[SN]\?',
'qnoised[SN]\?',
'qshot',
'qshot[SN]\?',
'sd',
'xd',
]
'ad',
'beam',
'bp',
'cp',
'guoy',
'hd',
'pd[SN]?d*',
'pgaind',
'qd',
'qd*hd?',
'qhd[SN]?',
'qnoised[SN]?',
'qshot',
'qshot[SN]?',
'sd',
'xd'
];
const commands = [
'attr',
'cav',
'conf',
'fadd',
'fsig',
'gauss',
'knm',
'lambda',
'map',
'mask',
'maxtem',
'pdtype',
'phase',
'retrace',
'smotion',
'startnode',
'tem',
'tf2\?',
'vacuum',
'attr',
'cav',
'conf',
'fadd',
'fsig',
'gauss',
'knm',
'lambda',
'map',
'mask',
'maxtem',
'pdtype',
'phase',
'retrace',
'smotion',
'startnode',
'tem',
'tf2?',
'vacuum',
// Plotting:
'const',
'deriv_h',
'diff',
'func',
'lock',
'noplot',
'noxaxis',
'put',
'scale',
'set',
'trace',
'var',
'x2?axis',
'yaxis',
// Plotting:
'const',
'deriv_h',
'diff',
'func',
'lock',
'noplot',
'noxaxis',
'put',
'scale',
'set',
'trace',
'var',
'x2\?axis',
'yaxis',
// Auxiliary
'gnuterm',
'multi',
'pause',
'pyterm',
]
// Auxiliary
'gnuterm',
'multi',
'pause',
'pyterm'
];
const reserved = [
'dump'
]
const reserved = ['dump'];
function wordListRegexp(words: string[]): RegExp {
return new RegExp("^((" + words.join(")|(") + "))$");
return new RegExp('^((' + words.join(')|(') + '))$');
}
const regex = {
"command": wordListRegexp(commands),
"component": wordListRegexp(components),
"detector": wordListRegexp(detectors),
"name": /[a-zA-Z_][a-zA-Z0-9_-]/,
"number": /^(([+-]?inf)|([+-]?(\d+\.\d*|\d*\.\d+|\d+)([eE]-?\d*\.?\d*)?j?([pnumkMGT])?))$/,
"reserved": wordListRegexp(reserved),
"variable": /\$\w+/
}
command: wordListRegexp(commands),
component: wordListRegexp(components),
detector: wordListRegexp(detectors),
name: /[a-zA-Z_][a-zA-Z0-9_-]/,
number: /^(([+-]?inf)|([+-]?(\d+\.\d*|\d*\.\d+|\d+)([eE]-?\d*\.?\d*)?j?([pnumkMGT])?))$/,
reserved: wordListRegexp(reserved),
variable: /\$\w+/
};
/*
* Available tokens:
......@@ -121,73 +117,75 @@ const regex = {
* link
*/
CodeMirror.defineMode("finesse2", () => {
function tokenBase(stream: CodeMirror.StringStream, state: any) {
return "line-background-finesse " + tokenLex(stream, state);
}
export function defineFinesse2Mode(CodeMirror: any): void {
CodeMirror.defineMode('finesse2', () => {
function tokenBase(stream: CodeMirror.StringStream, state: any) {
return 'line-background-finesse ' + tokenLex(stream, state);
}
function tokenLex(stream: CodeMirror.StringStream, state: any) {
if (stream.sol()) {
state.firstOnLine = true;
}
if (stream.eatSpace()) {
return;
}
if (/[#%]/.test(stream.peek())) {
stream.skipToEnd();
return "comment";
}
if (stream.peek() == '$') {
stream.next();
}
stream.eatWhile(/[^\s]/);
let style = null;
let cur = stream.current();
function tokenLex(stream: CodeMirror.StringStream, state: any) {
if (stream.sol()) {
state.firstOnLine = true;
}
if (stream.eatSpace()) {
return;
}
if (/[#%]/.test(stream.peek())) {
stream.skipToEnd();
return 'comment';
}
if (stream.peek() == '$') {
stream.next();
}
stream.eatWhile(/[^\s]/);
let style = null;
let cur = stream.current();
if (state.firstOnLine) {
if (regex["component"].test(cur) || regex["detector"].test(cur)) {
// Component definition
style = "keyword";
state.nextIsDef = true;
} else if (regex["command"].test(cur)) {
// Command
style = "builtin";
}
} else if (state.nextIsDef && regex["name"].test(cur)) {
// Component name
style = "def";
state.nextIsDef = false;
} else if (regex["number"].test(cur)) {
// Number
style = "number";
} else if (regex["reserved"].test(cur)) {
// Reserved keyword
style = "keyword";
} else if (regex["variable"].test(cur)) {
style = "variable-2";
}
if (style != null) {
state.firstOnLine = false;
return style;
}
stream.next();
}
if (state.firstOnLine) {
if (regex['component'].test(cur) || regex['detector'].test(cur)) {
// Component definition
style = 'keyword';
state.nextIsDef = true;
} else if (regex['command'].test(cur)) {
// Command
style = 'builtin';
}
} else if (state.nextIsDef && regex['name'].test(cur)) {
// Component name
style = 'def';
state.nextIsDef = false;
} else if (regex['number'].test(cur)) {
// Number
style = 'number';
} else if (regex['reserved'].test(cur)) {
// Reserved keyword
style = 'keyword';
} else if (regex['variable'].test(cur)) {
style = 'variable-2';
}
if (style != null) {
state.firstOnLine = false;
return style;
}
stream.next();
}
return {
return {
startState: function () {
return {
tokenize: tokenBase,
firstOnLine: true,
nextIsDef: false
};
},
blankLine: function (state: any) {
return 'line-background-finesse';
},
token: function (stream: any, state: any) {
return state.tokenize(stream, state);
}
};
});
startState: function() {
return {
tokenize: tokenBase,
firstOnLine: true,
nextIsDef: false
};
},
blankLine: function(state: any) { return "line-background-finesse";},
token: function(stream, state) {
return state.tokenize(stream, state)
}
};
});
CodeMirror.defineMIME("text/x-finesse2", "finesse2");
CodeMirror.defineMIME('text/x-finesse2', 'finesse2');
}
This diff is collapsed.
export function defineMultiplexingMode(
CodeMirror: any,
): void
// CodeMirror, copyright (c) by Marijn Haverbeke and others
// Distributed under an MIT license: https://codemirror.net/LICENSE
//
// This is a clone of addon/mode/multiplexingMode.js from CodeMirror. The
// original blankLine function doesn't return the style returned by its
// sub-modes, so we have to copy the whole thing in here -_-
export function defineMultiplexingMode(CodeMirror) {
CodeMirror.myMultiplexingMode = function (outer /*, others */) {
// Others should be {open, close, mode [, delimStyle] [, innerStyle]} objects
var others = Array.prototype.slice.call(arguments, 1);
function indexOf(string, pattern, from, returnEnd) {
if (typeof pattern == 'string') {
var found = string.indexOf(pattern, from);
return returnEnd && found > -1 ? found + pattern.length : found;
}
var m = pattern.exec(from ? string.slice(from) : string);
return m ? m.index + from + (returnEnd ? m[0].length : 0) : -1;
}
return {
startState: function () {
return {
outer: CodeMirror.startState(outer),
innerActive: null,
inner: null,
startingInner: false
};
},
copyState: function (state) {
return {
outer: CodeMirror.copyState(outer, state.outer),
innerActive: state.innerActive,
inner:
state.innerActive &&
CodeMirror.copyState(state.innerActive.mode, state.inner),
startingInner: state.startingInner
};
},
token: function (stream, state) {
if (!state.innerActive) {
var cutOff = Infinity,
oldContent = stream.string;
for (var i = 0; i < others.length; ++i) {
var other = others[i];
var found = indexOf(oldContent, other.open, stream.pos);
if (found == stream.pos) {
if (!other.parseDelimiters) stream.match(other.open);
state.startingInner = !!other.parseDelimiters;
state.innerActive = other;
// Get the outer indent, making sure to handle CodeMirror.Pass
var outerIndent = 0;
if (outer.indent) {
var possibleOuterIndent = outer.indent(state.outer, '', '');
if (possibleOuterIndent !== CodeMirror.Pass)
outerIndent = possibleOuterIndent;
}
state.inner = CodeMirror.startState(other.mode, outerIndent);
return (
other.delimStyle &&
other.delimStyle + ' ' + other.delimStyle + '-open'
);
} else if (found != -1 && found < cutOff) {
cutOff = found;
}
}
if (cutOff != Infinity) stream.string = oldContent.slice(0, cutOff);
var outerToken = outer.token(stream, state.outer);
if (cutOff != Infinity) stream.string = oldContent;
return outerToken;
} else {
var curInner = state.innerActive,
oldContent = stream.string;
if (!curInner.close && stream.sol()) {
state.innerActive = state.inner = null;
return this.token(stream, state);
}
var found =
curInner.close && !state.startingInner
? indexOf(
oldContent,
curInner.close,
stream.pos,
curInner.parseDelimiters
)
: -1;
if (found == stream.pos && !curInner.parseDelimiters) {
stream.match(curInner.close);
state.innerActive = state.inner = null;
return (
curInner.delimStyle &&
curInner.delimStyle + ' ' + curInner.delimStyle + '-close'
);
}
if (found > -1) stream.string = oldContent.slice(0, found);
var innerToken = curInner.mode.token(stream, state.inner);
if (found > -1) stream.string = oldContent;
else if (stream.pos > stream.start) state.startingInner = false;
if (found == stream.pos && curInner.parseDelimiters)
state.innerActive = state.inner = null;
if (curInner.innerStyle) {
if (innerToken) innerToken = innerToken + ' ' + curInner.innerStyle;
else innerToken = curInner.innerStyle;
}
return innerToken;
}
},
indent: function (state, textAfter, line) {
var mode = state.innerActive ? state.innerActive.mode : outer;
if (!mode.indent) return CodeMirror.Pass;
return mode.indent(
state.innerActive ? state.inner : state.outer,
textAfter,
line
);
},
blankLine: function (state) {
var mode = state.innerActive ? state.innerActive.mode : outer;
var ret = null;
if (mode.blankLine) {
ret = mode.blankLine(state.innerActive ? state.inner : state.outer);
}
if (!state.innerActive) {
for (var i = 0; i < others.length; ++i) {
var other = others[i];
if (other.open === '\n') {
state.innerActive = other;
state.inner = CodeMirror.startState(
other.mode,
mode.indent ? mode.indent(state.outer, '', '') : 0
);
}
}
} else if (state.innerActive.close === '\n') {
state.innerActive = state.inner = null;
}
return ret;
},
electricChars: outer.electricChars,
innerMode: function (state) {
return state.inner
? { state: state.inner, mode: state.innerActive.mode }
: { state: state.outer, mode: outer };
}
};
};
}
import {
JupyterFrontEnd, JupyterFrontEndPlugin
JupyterFrontEnd,
JupyterFrontEndPlugin
} from '@jupyterlab/application';
import {
NotebookPanel, INotebookTracker, Notebook
NotebookPanel,
INotebookTracker,
Notebook
} from '@jupyterlab/notebook';
import {
Cell, CodeCell, ICellModel
} from '@jupyterlab/cells';
import { ICodeMirror } from '@jupyterlab/codemirror';
import { Cell, CodeCell, ICellModel } from '@jupyterlab/cells';
import './codemirror-finesse-python';
import { setupFinesseCodeMirror } from './codemirror-finesse-python';
const plugin: JupyterFrontEndPlugin<void> = {
activate,
id: 'finesse-syntax-jupyter',
requires: [INotebookTracker],
autoStart: true
id: 'finesse-syntax-jupyter',
autoStart: true,
requires: [INotebookTracker, ICodeMirror],
activate
};
function activate(app: JupyterFrontEnd, tracker: INotebookTracker) {
let style = document.createElement('style');
style.type = 'text/css';
style.innerHTML = '.finesse { background-color: rgba(0, 0, 0, 0.04); }';
document.getElementsByTagName('head')[0].appendChild(style);
tracker.widgetAdded.connect(activate_finesse)
};
function activate(
app: JupyterFrontEnd,
tracker: INotebookTracker,
codemirror: ICodeMirror
) {
setupFinesseCodeMirror(codemirror.CodeMirror);
const style = document.createElement('style');
style.type = 'text/css';
style.innerHTML = '.finesse { background-color: rgba(0, 0, 0, 0.04); }';
document.getElementsByTagName('head')[0].appendChild(style);
tracker.widgetAdded.connect(activate_finesse);
}
function check_all(sender: NotebookPanel): void {
sender.content.widgets.forEach(cell => {
if (cell instanceof CodeCell && cell.model.mimeType != "text/x-finesse-python") {
cell.model.mimeType = "text/x-finesse-python";
}
});
};
sender.content.widgets.forEach(cell => {
if (
cell instanceof CodeCell &&
cell.model.mimeType !== 'text/x-finesse-python'
) {
cell.model.mimeType = 'text/x-finesse-python';
}
});
}
function set_mime(model: ICellModel) {
// Jupyter seems to have some weirdness related to setup of the
// mime type of each cell. To avoid having timeouts everywhere,
// everytime we select a new cell, we attach a function that checks the
// mime type on each content change and sets it if required, otherwise
// disconnects itself.
if (model.mimeType == "text/x-finesse-python") {
model.contentChanged.disconnect(set_mime);
} else {
model.mimeType = "text/x-finesse-python";
}
// Jupyter seems to have some weirdness related to setup of the
// mime type of each cell. To avoid having timeouts everywhere,
// everytime we select a new cell, we attach a function that checks the
// mime type on each content change and sets it if required, otherwise
// disconnects itself.
if (model.mimeType === 'text/x-finesse-python') {
model.contentChanged.disconnect(set_mime);
} else {
model.mimeType = 'text/x-finesse-python';
}
}
function check_cell(sender: Notebook, cell: Cell): void {
if (cell instanceof CodeCell) {
cell.model.contentChanged.connect(set_mime);
}
if (cell instanceof CodeCell) {
cell.model.contentChanged.connect(set_mime);
}
}
function activate_finesse(sender: INotebookTracker, panel: NotebookPanel): void {
panel.content.activeCellChanged.connect(check_cell);
function activate_finesse(
sender: INotebookTracker,
panel: NotebookPanel
): void {
panel.content.activeCellChanged.connect(check_cell);
// I ain't proud of this, but it's the sanest way I could find to get
// the syntax highlighting to change on startup without selecting a
// different cell
setTimeout(() => {check_all(panel)}, 500);
setTimeout(() => {check_all(panel)}, 2000);
setTimeout(() => {check_all(panel)}, 5000);
};
// I ain't proud of this, but it's the sanest way I could find to get
// the syntax highlighting to change on startup without selecting a
// different cell
setTimeout(() => {
check_all(panel);
}, 500);
setTimeout(() => {
check_all(panel);
}, 2000);
setTimeout(() => {
check_all(panel);
}, 5000);
}
export default plugin;
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment