microsoft/qdk

Public

mirrored fromhttps://github.com/microsoft/qdkAvailable

CodeCommitsIssuesPull requestsActionsInsightsSecurity
alex/loggylog

Branches

Tags

  • No tags available.
0Branches0Tags
Go to file
Add file
Code

Clone

HTTPS

Download ZIP

jupyterlab/src/index.ts

165lines · modecode

1// Copyright (c) Microsoft Corporation.
2// Licensed under the MIT License.
3
4import {
5 JupyterFrontEnd,
6 JupyterFrontEndPlugin,
7} from "@jupyterlab/application";
8
9import { IEditorLanguageRegistry } from "@jupyterlab/codemirror";
10import { simpleMode } from "@codemirror/legacy-modes/mode/simple-mode";
11import { LanguageSupport, StreamLanguage } from "@codemirror/language";
12import { INotebookTracker, NotebookPanel } from "@jupyterlab/notebook";
13import { ICellModel } from "@jupyterlab/cells/lib/model";
14
15const plugin: JupyterFrontEndPlugin<void> = {
16 id: "qsharp",
17 autoStart: true,
18 requires: [IEditorLanguageRegistry, INotebookTracker],
19 activate: async (
20 app: JupyterFrontEnd,
21 codemirrorLanguageRegistry: IEditorLanguageRegistry,
22 notebookTracker: INotebookTracker,
23 ) => {
24 registerQSharpLanguage(codemirrorLanguageRegistry);
25 registerQSharpNotebookHandlers(notebookTracker);
26 },
27};
28
29/**
30 * Registers the text/x-qsharp mime type and the .qs file extension
31 * and associates them with the qsharp CodeMirror mode.
32 */
33function registerQSharpLanguage(
34 codemirrorLanguageRegistry: IEditorLanguageRegistry,
35) {
36 const rules = [
37 {
38 token: "comment",
39 regex: /(\/\/).*/,
40 beginWord: false,
41 },
42 {
43 token: "string",
44 regex: String.raw`^\"(?:[^\"\\]|\\[\s\S])*(?:\"|$)`,
45 beginWord: false,
46 },
47 {
48 token: "keyword",
49 regex: String.raw`(namespace|open|import|export|as|operation|function|body|adjoint|newtype|struct|new|controlled|internal)\b`,
50 beginWord: true,
51 },
52 {
53 token: "keyword",
54 regex: String.raw`(if|elif|else|repeat|until|fixup|for|in|return|fail|within|apply)\b`,
55 beginWord: true,
56 },
57 {
58 token: "keyword",
59 regex: String.raw`(Adjoint|Controlled|Adj|Ctl|is|self|auto|distribute|invert|intrinsic)\b`,
60 beginWord: true,
61 },
62 {
63 token: "keyword",
64 regex: String.raw`(let|set|use|borrow|mutable)\b`,
65 beginWord: true,
66 },
67 {
68 token: "operatorKeyword",
69 regex: String.raw`(not|and|or)\b|(w/)`,
70 beginWord: true,
71 },
72 {
73 token: "operatorKeyword",
74 regex: String.raw`(=)|(!)|(<)|(>)|(\+)|(-)|(\*)|(/)|(\^)|(%)|(\|)|(&&&)|(~~~)|(\.\.\.)|(\.\.)|(\?)`,
75 beginWord: false,
76 },
77 {
78 token: "meta",
79 regex: String.raw`(Int|BigInt|Double|Bool|Qubit|Pauli|Result|Range|String|Unit)\b`,
80 beginWord: true,
81 },
82 {
83 token: "atom",
84 regex: String.raw`(true|false|Pauli(I|X|Y|Z)|One|Zero)\b`,
85 beginWord: true,
86 },
87 ];
88 const simpleRules = [];
89 for (const rule of rules) {
90 simpleRules.push({
91 token: rule.token,
92 regex: new RegExp(rule.regex, "g"),
93 sol: rule.beginWord,
94 });
95 if (rule.beginWord) {
96 // Need an additional rule due to the fact that CodeMirror simple mode doesn't work with ^ token
97 simpleRules.push({
98 token: rule.token,
99 regex: new RegExp(String.raw`\W` + rule.regex, "g"),
100 sol: false,
101 });
102 }
103 }
104
105 const parser = simpleMode({ start: simpleRules });
106 const languageSupport = new LanguageSupport(StreamLanguage.define(parser));
107 codemirrorLanguageRegistry.addLanguage({
108 name: "qsharp",
109 mime: "text/x-qsharp",
110 support: languageSupport,
111 extensions: ["qs"],
112 });
113}
114
115/**
116 * Sets up handlers to detect Q# code cells in Python notebooks and set the language to Q#.
117 */
118function registerQSharpNotebookHandlers(notebookTracker: INotebookTracker) {
119 notebookTracker.forEach((notebookPanel) => {
120 // When the application is first loaded
121 watchAndSetLanguageForQsharpCells(notebookPanel);
122 });
123
124 notebookTracker.widgetAdded.connect((notebookTracker, notebookPanel) => {
125 // When a new notebook editor is opened
126 watchAndSetLanguageForQsharpCells(notebookPanel);
127 });
128}
129
130function watchAndSetLanguageForQsharpCells(notebookPanel: NotebookPanel) {
131 notebookPanel.revealed.then(() => {
132 const notebook = notebookPanel.model;
133
134 if (notebook?.defaultKernelName === "python3") {
135 for (const cell of notebook.cells) {
136 // When notebook cells are first loaded
137 setLanguageIfCellIsQSharp(cell);
138 }
139
140 notebook.cells.changed.connect((cellList, changedCells) => {
141 changedCells.newValues.forEach((cell) => {
142 // When a new cell is added
143 setLanguageIfCellIsQSharp(cell);
144 cell.contentChanged.connect((cell) => {
145 // When cell contents are updated
146 setLanguageIfCellIsQSharp(cell);
147 });
148 });
149 });
150 }
151 });
152}
153
154function setLanguageIfCellIsQSharp(cell: ICellModel) {
155 if (cell.type === "code") {
156 if (cell.sharedModel.source.startsWith("%%qsharp")) {
157 if (cell.mimeType !== "text/x-qsharp") {
158 cell.mimeType = "text/x-qsharp";
159 console.log("updated cell mime type to text/x-qsharp");
160 }
161 }
162 }
163}
164
165export default plugin;
166