11const State = {
2+ preamble : "" ,
23 editor : null ,
34 terminal : null ,
45 module : null ,
@@ -21,6 +22,7 @@ function initializeTerminal() {
2122 AppState . terminal . loadAddon ( fitAddon ) ;
2223 AppState . terminal . open ( document . getElementById ( 'output' ) ) ;
2324 fitAddon . fit ( ) ;
25+ window . AppState = AppState ;
2426 console . log ( "Terminal initialized" ) ;
2527}
2628
@@ -58,7 +60,7 @@ function initializeModule() {
5860 AppState . isModuleReady = true ;
5961 console . log ( "Module initialized" ) ;
6062 // Attempt to run the kernel with the initial content
61- AppState . editor . updateEditor ( { action : 'insert' , lines : [ '' ] } ) ;
63+ updateEditor ( { action : 'insert' , lines : [ '' ] } ) ;
6264 } ) . catch ( error => {
6365 console . error ( "Failed to initialize module:" , error ) ;
6466 } ) ;
@@ -83,6 +85,10 @@ function setupEventListeners() {
8385 } ) ;
8486}
8587
88+ ////////////////////////////////////////
89+ // Printing to terminal
90+ ////////////////////////////////////////
91+
8692function customPrint ( text ) {
8793 console . log ( text ) ;
8894 if ( AppState . terminal ) {
@@ -91,3 +97,128 @@ function customPrint(text) {
9197 console . warn ( "Terminal not initialized" ) ;
9298 }
9399}
100+
101+ ////////////////////////////////////////
102+ // Code Editor
103+ ////////////////////////////////////////
104+
105+ async function showCompletionSuggestion ( ) {
106+ const cursorPosition = editor . getCursorPosition ( ) ;
107+ const screenPosition = editor . renderer . textToScreenCoordinates ( cursorPosition . row , cursorPosition . column ) ;
108+
109+ completionTippy . setContent ( 'Loading...' ) ;
110+ completionTippy . setProps ( {
111+ getReferenceClientRect : ( ) => ( {
112+ width : 0 ,
113+ height : 0 ,
114+ top : screenPosition . pageY ,
115+ bottom : screenPosition . pageY ,
116+ left : screenPosition . pageX ,
117+ right : screenPosition . pageX ,
118+ } )
119+ } ) ;
120+ completionTippy . show ( ) ;
121+
122+ try {
123+ const response = await fetch ( '/complete' , {
124+ method : 'POST' ,
125+ headers : {
126+ 'Content-Type' : 'application/json' ,
127+ } ,
128+ body : JSON . stringify ( {
129+ code : editor . getValue ( ) ,
130+ row : cursorPosition . row ,
131+ column : cursorPosition . column
132+ } ) ,
133+ } ) ;
134+
135+ if ( ! response . ok ) {
136+ throw new Error ( `HTTP error! status: ${ response . status } ` ) ;
137+ }
138+
139+ const data = await response . json ( ) ;
140+ currentCompletion = data . completion ;
141+ completionTippy . setContent ( `${ currentCompletion } (Press Tab to insert)` ) ;
142+ } catch ( error ) {
143+ console . error ( 'Error:' , error ) ;
144+ completionTippy . setContent ( 'Error fetching completion' ) ;
145+ currentCompletion = '' ;
146+ }
147+
148+ setTimeout ( ( ) => {
149+ if ( currentCompletion ) {
150+ completionTippy . hide ( ) ;
151+ currentCompletion = '' ;
152+ }
153+ } , 5000 ) ;
154+ }
155+
156+ function updateEditor ( delta ) {
157+ if ( delta . action === 'insert' && ( delta . lines [ 0 ] === '.' || delta . lines [ 0 ] === ' ' ) ) {
158+ showCompletionSuggestion ( ) ;
159+ }
160+ // Recover from errors TODO(avh): only do this if there's an error
161+ createModule ( ) . then ( ( Module ) => {
162+ // Keep your existing Module setup
163+ console . log ( "updateEditor() - Module ready" ) ;
164+ } ) ;
165+ if ( AppState . module && AppState . module . executeKernel ) {
166+ console . log ( "Executing kernel" ) ;
167+ AppState . terminal . clear ( ) ;
168+ wgSize = [ 256 , 1 , 1 ] ;
169+ gridSize = [ 256 , 1 , 1 ] ;
170+ AppState . module . executeKernel ( AppState . preamble + AppState . editor . getValue ( ) , wgSize , gridSize ) ;
171+ } else {
172+ console . log ( "updateEditor() - Module not ready" ) ;
173+ }
174+ }
175+
176+ function initEditor ( initial_code ) {
177+ AppState . editor = ace . edit ( "editor" ) ;
178+ editor = AppState . editor ;
179+ // editor = ace.edit("editor");
180+ editor . setTheme ( "ace/theme/monokai" ) ;
181+ editor . session . setMode ( "ace/mode/javascript" ) ;
182+ editor . setOptions ( {
183+ fontSize : "14px" ,
184+ showPrintMargin : false ,
185+ // disable showing errors in gutter, Ace's WGSL parser is out of date
186+ showGutter : false ,
187+ highlightActiveLine : true ,
188+ wrap : true ,
189+ } ) ;
190+ editor . setKeyboardHandler ( "ace/keyboard/vim" ) ;
191+ editor . setValue ( initial_code ) ;
192+ window . addEventListener ( 'resize' , function ( ) {
193+ editor . resize ( ) ;
194+ } ) ;
195+ // document.getElementById('language').addEventListener('change', function(e) {
196+ // let mode = "ace/mode/" + e.target.value;
197+ // editor.session.setMode(mode);
198+ // });
199+
200+ editor . session . on ( 'change' , updateEditor ) ;
201+
202+ completionTippy = tippy ( document . getElementById ( 'editor' ) , {
203+ content : 'Loading...' ,
204+ trigger : 'manual' ,
205+ placement : 'top-start' ,
206+ arrow : true ,
207+ interactive : true
208+ } ) ;
209+
210+ // Override the default tab behavior
211+ editor . commands . addCommand ( {
212+ name : 'insertCompletion' ,
213+ bindKey : { win : 'Tab' , mac : 'Tab' } ,
214+ exec : function ( editor ) {
215+ if ( currentCompletion ) {
216+ editor . insert ( currentCompletion ) ;
217+ currentCompletion = '' ;
218+ completionTippy . hide ( ) ;
219+ } else {
220+ editor . indent ( ) ;
221+ }
222+ }
223+ } ) ;
224+ }
0 commit comments