11// The module 'vscode' contains the VS Code extensibility API
22// Import the module and reference it with the alias vscode in your code below
33import * as vscode from "vscode" ;
4- import * as parser from "./parsing/parser" ;
5- import * as sizer from "./parsing/sizes" ;
6- import * as coord from "./parsing/coords" ;
7- import { boundary , setCanvasWidthHeight } from "./constants/variableconsts" ;
8- import * as vconsts from "./constants/variableconsts" ;
9- import * as ast from "./parsing/ast" ;
10- import { getCanvasHtml } from "./webview/webview" ;
4+ import { coqLspApi , only_with_lsp } from "./lspguards" ;
5+ import { render , renderCallback } from "./rendering/callback" ;
116
12- let openWebview : vscode . WebviewPanel | undefined = undefined ;
137let history : string [ ] = [ ] ;
148const HISTORY_LENGTH = vscode . workspace
159 . getConfiguration ( "vizx" )
1610 . get < number > ( "historyLength" , 25 ) ;
1711const HISTORY_KEY = "vizxInputHistory" ;
1812
13+ let hook : vscode . Disposable | undefined = undefined ;
1914// this method is called when your extension is activated
2015// your extension is activated the very first time the command is executed
2116export function activate ( context : vscode . ExtensionContext ) {
@@ -26,121 +21,168 @@ export function activate(context: vscode.ExtensionContext) {
2621 // The command has been defined in the package.json file
2722 // Now provide the implementation of the command with registerCommand
2823 // The commandId parameter must match the command field in package.json
29- let disposable = vscode . commands . registerCommand ( "vizx.render" , ( ) => {
30- const newDiag = "New..." ;
31- const inputBox = vscode . window
32- . showQuickPick ( [ ...history , newDiag ] , {
33- placeHolder : "Diagram syntax with notations" ,
34- title : "Enter or choose diagram" ,
35- } )
36- . then ( ( selected ) => {
37- if ( selected === undefined ) {
38- return ;
39- } else if ( selected === newDiag ) {
40- vscode . window
41- . showInputBox ( { prompt : "Enter diagram syntax with notations" } )
42- . then ( ( value ) => {
43- if ( value ) {
44- history . unshift ( value ) ; // Add to history
45- if ( history . length > HISTORY_LENGTH ) {
46- history . pop ( ) ; // Limit history size
47- }
48- context . workspaceState . update ( HISTORY_KEY , history ) ; // Save to workspaceState
49- renderCallback ( context , value ) ;
50- }
51- } ) ;
52- } else {
53- history = history . filter ( ( item ) => item !== selected ) ;
54- history . unshift ( selected ) ; // Add to the front of history
55- context . workspaceState . update ( HISTORY_KEY , history ) ;
56- renderCallback ( context , selected ) ;
57- }
58- } ) ;
59- } ) ;
24+ let disposables = [
25+ vscode . commands . registerCommand ( "vizx.render" , ( ) =>
26+ renderCommand ( context )
27+ ) ,
28+ ] ;
29+
30+ disposables . push (
31+ vscode . commands . registerCommand ( "vizx.lspRender" , ( expr ) =>
32+ renderCallback ( context , expr )
33+ )
34+ ) ;
6035
61- context . subscriptions . push ( disposable ) ;
62- disposable = vscode . commands . registerCommand ( "vizx.lspRender" , ( expr ) =>
63- renderCallback ( context , expr )
36+ disposables . push (
37+ vscode . commands . registerCommand ( "vizx.activateRendering" , ( ) =>
38+ activateRenderingCommand ( context )
39+ )
6440 ) ;
65- context . subscriptions . push ( disposable ) ;
66- let coqLspApi = vscode . extensions . getExtension ( "ejgallego.coq-lsp" ) ! . exports ;
67- let hook = coqLspApi . onUserGoals ( ( goals : any ) =>
68- vscode . commands . executeCommand ( "vizx.lspRender" , goals )
41+ disposables . push (
42+ vscode . commands . registerCommand ( "vizx.deactivateRendering" , ( ) =>
43+ deactivateRenderingCommand ( )
44+ )
6945 ) ;
46+ context . subscriptions . push ( ...disposables ) ;
7047
71- disposable = vscode . commands . registerCommand ( "vizx.activateRendering" , ( ) => {
72- vscode . window . showInformationMessage (
73- "Automatic rendering is now turned on."
74- ) ;
75- } ) ;
76- context . subscriptions . push ( disposable ) ;
77- disposable = vscode . commands . registerCommand (
78- "vizx.deactivateRendering" ,
79- ( ) => {
80- deactivate ( ) ;
81- vscode . window . showInformationMessage (
82- "Automatic rendering is now turned off."
48+ const config = vscode . workspace . getConfiguration ( "vizx" ) ;
49+ const autoRenderingEnabled = config . get < boolean > (
50+ "enableAutomaticRendering" ,
51+ false
52+ ) ;
53+ if ( autoRenderingEnabled ) {
54+ // Wait until a tab named "goals" exists before activating rendering
55+ activateRendering ( context ) ;
56+ if ( hook === undefined ) {
57+ vscode . window . showWarningMessage (
58+ "Automatic rendering is enabled, but the LSP hook could not be set up. Please ensure that the Coq LSP is running."
8359 ) ;
84- hook . dispose ( ) ;
8560 }
86- ) ;
61+ vscode . window . showInformationMessage (
62+ "ViZX automatic rendering is now turned on."
63+ ) ;
64+ } else {
65+ vscode . window
66+ . showInformationMessage (
67+ "ViZX automatic rendering is currently disabled." ,
68+ "Enable" ,
69+ "OK"
70+ )
71+ . then ( ( selection ) => {
72+ if ( selection === "Enable" ) {
73+ vscode . commands . executeCommand ( "vizx.activateRendering" ) ;
74+ }
75+ } ) ;
76+ }
77+ }
8778
88- context . subscriptions . push ( disposable ) ;
79+ function renderCommand ( context : vscode . ExtensionContext ) : void {
80+ const newDiag = "New..." ;
81+ vscode . window
82+ . showQuickPick ( [ ...history , newDiag ] , {
83+ placeHolder : "Diagram syntax with notations" ,
84+ title : "Enter or choose diagram" ,
85+ } )
86+ . then ( ( selected ) => {
87+ if ( selected === undefined ) {
88+ return ;
89+ } else if ( selected === newDiag ) {
90+ vscode . window
91+ . showInputBox ( { prompt : "Enter diagram syntax with notations" } )
92+ . then ( ( value ) => {
93+ if ( value ) {
94+ history . unshift ( value ) ; // Add to history
95+ if ( history . length > HISTORY_LENGTH ) {
96+ history . pop ( ) ; // Limit history size
97+ }
98+ context . workspaceState . update ( HISTORY_KEY , history ) ; // Save to workspaceState
99+ render ( context , value ) ;
100+ }
101+ } ) ;
102+ } else {
103+ history = history . filter ( ( item ) => item !== selected ) ;
104+ history . unshift ( selected ) ; // Add to the front of history
105+ context . workspaceState . update ( HISTORY_KEY , history ) ;
106+ render ( context , selected ) ;
107+ }
108+ } ) ;
89109}
90110
91- function renderCallback ( context : vscode . ExtensionContext , expr : any ) {
92- {
93- if ( expr === undefined ) {
94- console . log ( "no expression to be rendered" ) ;
95- return ;
96- }
97- if ( expr . goals !== undefined ) {
98- // extract correct field from lsp information
99- expr = expr . goals . goals [ 0 ] . ty . toString ( ) ;
100- }
101- console . log ( "expr: " , expr ) ;
102- let node : ast . ASTNode ;
103- try {
104- node = parser . parseAST ( expr ) ;
105- node = sizer . addSizes ( node ) ;
106- console . log ( "sized node: " , node ) ;
107- const size = sizer . determineCanvasWidthHeight ( node ) ;
108- setCanvasWidthHeight ( size ) ;
109- node = coord . addCoords ( node , boundary ) ;
110- } catch ( e ) {
111- vscode . window . showErrorMessage (
112- `Error rendering your expression (${ expr } ): ${ e } `
113- ) ;
114- return ;
115- }
116- if ( openWebview !== undefined ) {
117- openWebview . dispose ( ) ;
118- }
119- const panel = vscode . window . createWebviewPanel (
120- "ViZX" ,
121- `ViZX: ${ expr } ` ,
122- {
123- viewColumn : vscode . ViewColumn . Three ,
124- preserveFocus : true ,
125- } ,
126- {
127- enableScripts : true ,
128- retainContextWhenHidden : true ,
111+ function activateRenderingCommand ( context : vscode . ExtensionContext ) : void {
112+ const config = vscode . workspace . getConfiguration ( "vizx" ) ;
113+ const enabled = config . get < boolean > ( "enableAutomaticRendering" , false ) ;
114+ if ( ! enabled ) {
115+ // if disabled, then ask user if they want to enable it
116+ vscode . window
117+ . showInformationMessage (
118+ "Automatic rendering is currently disabled. Do you want to enable it?" ,
119+ "Enable for this project" ,
120+ "Enable globally"
121+ )
122+ . then ( ( selection ) => {
123+ if ( selection === "Enable for this project" ) {
124+ config . update (
125+ "enableAutomaticRendering" ,
126+ true ,
127+ vscode . ConfigurationTarget . Workspace
128+ ) ;
129+ } else if ( selection === "Enable globally" ) {
130+ config . update (
131+ "enableAutomaticRendering" ,
132+ true ,
133+ vscode . ConfigurationTarget . Global
134+ ) ;
135+ }
136+ activateRendering ( context ) ;
137+ } ) ;
138+ return ;
139+ }
140+ vscode . window . showInformationMessage ( "Automatic rendering is now turned on." ) ;
141+ }
142+
143+ function deactivateRenderingCommand ( ) : void {
144+ vscode . window
145+ . showInformationMessage (
146+ "Automatic rendering is now turned off." ,
147+ "Deactivate for this project" ,
148+ "Deactivate globally"
149+ )
150+ . then ( ( selection ) => {
151+ if ( selection === "Deactivate for this project" ) {
152+ vscode . workspace
153+ . getConfiguration ( "vizx" )
154+ . update (
155+ "enableAutomaticRendering" ,
156+ false ,
157+ vscode . ConfigurationTarget . Workspace
158+ ) ;
159+ } else if ( selection === "Deactivate globally" ) {
160+ vscode . workspace
161+ . getConfiguration ( "vizx" )
162+ . update (
163+ "enableAutomaticRendering" ,
164+ false ,
165+ vscode . ConfigurationTarget . Global
166+ ) ;
129167 }
130- ) ;
131- panel . onDidDispose (
132- async ( ) => {
133- console . log ( "openWebview before: " , openWebview ) ;
134- openWebview = undefined ;
135- } ,
136- null ,
137- context . subscriptions
138- ) ;
139- openWebview = panel ;
140- panel . webview . html = getCanvasHtml ( panel , context ) ;
141- panel . webview . onDidReceiveMessage ( ( msg ) => console . log ( msg ) ) ;
142- panel . webview . postMessage ( { command : JSON . stringify ( node ) } ) ;
168+ } ) ;
169+ deactivateRendering ( ) ;
170+ }
171+
172+ function activateRendering ( context : vscode . ExtensionContext ) : void {
173+ if ( hook !== undefined ) {
174+ return ; // no need to recreate as it would be the exact same
143175 }
176+ only_with_lsp ( ( ) => {
177+ hook = coqLspApi ! . onUserGoals ( ( goals : any ) =>
178+ renderCallback ( context , goals )
179+ ) ;
180+ } ) ;
181+ }
182+
183+ function deactivateRendering ( ) {
184+ hook ?. dispose ( ) ;
185+ hook = undefined ;
144186}
145187
146188// this method is called when your extension is deactivated
0 commit comments