microsoft/qdk

Public

mirrored from https://github.com/microsoft/qdkAvailable

CodeCommitsIssuesPull requestsActionsInsightsSecurity
dmitryv/select-updated

Branches

Tags

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

Clone

HTTPS

Download ZIP

jupyterlab/src/index.ts

162lines · modecode

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