@@ -85,6 +85,7 @@ let orcaOutlineProvider = new OrcaOutlineProvider([]);
8585
8686async function showOrcaOutline ( ) { // Make the function asynchronous
8787 const activeEditor = vscode . window . activeTextEditor ;
88+
8889 if ( ! activeEditor ) {
8990 // Check if there's a file with .out extension in the workspace
9091 if ( vscode . workspace . textDocuments . some ( doc => doc . uri . scheme === 'file' && doc . fileName . endsWith ( '.out' ) ) ) {
@@ -126,33 +127,6 @@ async function showOrcaOutline() { // Make the function asynchronous
126127 }
127128}
128129
129- function activate ( context ) {
130- context . subscriptions . push ( vscode . commands . registerCommand ( 'extension.showOrcaOutline' , showOrcaOutline ) ) ;
131-
132- // Register the global instance
133- vscode . window . registerTreeDataProvider ( 'orcaFileOutline' , orcaOutlineProvider ) ;
134- // Listen to changes in the active editor
135- context . subscriptions . push ( vscode . window . onDidChangeActiveTextEditor ( editor => {
136- if ( editor && editor . document . languageId === 'orcaOut' && editor . document . fileName . endsWith ( '.out' ) ) {
137- showOrcaOutline ( ) ;
138- }
139- } ) ) ;
140- // Initial check if the currently opened document meets the conditions
141- const activeEditor = vscode . window . activeTextEditor ;
142- if ( activeEditor && activeEditor . document . languageId === 'orcaOut' && activeEditor . document . fileName . endsWith ( '.out' ) ) {
143- showOrcaOutline ( ) ;
144- }
145- }
146-
147- function deactivate ( ) { }
148-
149- function toTitleCase ( str ) {
150- return str . replace ( / \w \S * / g, function ( txt ) {
151- return txt . charAt ( 0 ) . toUpperCase ( ) + txt . substr ( 1 ) . toLowerCase ( ) ;
152- } ) ;
153- }
154-
155-
156130function parseOrcaFile ( document , filePath ) {
157131 let matches = [ ] ;
158132 let stack = [ { children : matches } ] ;
@@ -173,17 +147,9 @@ function parseOrcaFile(document, filePath) {
173147 const line = document . positionAt ( match . index ) . line ;
174148 let title = match [ 1 ] || pattern . title ;
175149 title = toTitleCase ( title . trim ( ) ) ;
176- //console.log(title);
177-
178- // Replace keywords in the title
179- //for (let keyword in keywordReplacements) {
180- // if (title.includes(keyword)) {
181- // title = title.replace(keyword, keywordReplacements[keyword]);
182- // }
183- // }
184150
185151 allMatches . push ( {
186- line : line ,
152+ line : line + 1 ,
187153 title : title ,
188154 level : pattern . level ,
189155 children : [ ] ,
@@ -206,6 +172,7 @@ function parseOrcaFile(document, filePath) {
206172 } ) ;
207173
208174 allMatches . sort ( ( a , b ) => a . line - b . line ) ;
175+ allMatches = insertDummyHeadings ( allMatches ) ;
209176
210177 allMatches . forEach ( matchItem => {
211178 while ( stack . length > matchItem . level ) {
@@ -221,8 +188,32 @@ function parseOrcaFile(document, filePath) {
221188 } ) ;
222189}
223190
224-
225-
191+ function insertDummyHeadings ( allMatches ) {
192+ let correctedMatches = [ ] ;
193+ let lastMatch = null ;
194+
195+ for ( let i = 0 ; i < allMatches . length ; i ++ ) {
196+ let currentLevel = allMatches [ i ] . level ;
197+
198+ if ( lastMatch && currentLevel - lastMatch . level > 1 ) {
199+ for ( let j = 1 ; j < currentLevel - lastMatch . level ; j ++ ) {
200+ correctedMatches . push ( {
201+ line : lastMatch . line ,
202+ title : lastMatch . title ,
203+ level : lastMatch . level + j ,
204+ children : [ ] ,
205+ command : null ,
206+ tooltip : `Dummy for missing level`
207+ } ) ;
208+ }
209+ }
210+
211+ correctedMatches . push ( allMatches [ i ] ) ;
212+ lastMatch = allMatches [ i ] ;
213+ }
214+
215+ return correctedMatches ;
216+ }
226217
227218async function replaceKeywords ( matches ) {
228219 for ( let match of matches ) {
@@ -237,6 +228,141 @@ async function replaceKeywords(matches) {
237228 }
238229}
239230
231+ function toTitleCase ( str ) {
232+ return str . replace ( / \w \S * / g, function ( txt ) {
233+ return txt . charAt ( 0 ) . toUpperCase ( ) + txt . substr ( 1 ) . toLowerCase ( ) ;
234+ } ) ;
235+ }
236+
237+ function deactivate ( ) { }
238+
239+ function activate ( context ) {
240+ const orcaProvider = new OrcaFileSystemProvider ( ) ;
241+ context . subscriptions . push ( vscode . workspace . registerFileSystemProvider ( 'orca' , orcaProvider , { isReadonly : true } ) ) ;
242+ context . subscriptions . push ( vscode . commands . registerCommand ( 'extension.showOrcaOutlineExternal' , ( ...args ) => showOrcaOutlineExternal ( context , ...args ) ) ) ;
243+ context . subscriptions . push ( vscode . commands . registerCommand ( 'extension.showOrcaOutline' , showOrcaOutline ) ) ;
244+ // Register the global instance
245+ vscode . window . registerTreeDataProvider ( 'orcaFileOutline' , orcaOutlineProvider ) ;
246+ // Listen to changes in the active editor
247+ context . subscriptions . push ( vscode . window . onDidChangeActiveTextEditor ( editor => {
248+ if ( editor && editor . document . languageId === 'orcaOut' && editor . document . fileName . endsWith ( '.out' ) ) {
249+ showOrcaOutline ( ) ;
250+ }
251+ } ) ) ;
252+ // Initial check if the currently opened document meets the conditions
253+ const activeEditor = vscode . window . activeTextEditor ;
254+ if ( activeEditor && activeEditor . document . languageId === 'orcaOut' && activeEditor . document . fileName . endsWith ( '.out' ) ) {
255+ showOrcaOutline ( ) ;
256+ }
257+ context . subscriptions . push ( vscode . commands . registerCommand ( 'extension.navigateToLine' , ( lineNumber ) => {
258+ if ( globalEditor ) {
259+ let position = new vscode . Position ( lineNumber , 0 ) ;
260+ let range = new vscode . Range ( position , position ) ;
261+ globalEditor . selection = new vscode . Selection ( position , position ) ;
262+ globalEditor . revealRange ( range , vscode . TextEditorRevealType . Default ) ;
263+ }
264+ } ) ) ;
265+
266+
267+ }
268+
269+
270+ class OrcaFileSystemProvider {
271+ constructor ( ) {
272+ this . _emitter = new vscode . EventEmitter ( ) ;
273+ this . onDidChangeFile = this . _emitter . event ;
274+ }
275+ async readFile ( uri ) {
276+ try {
277+ const fsPath = uri . fsPath ;
278+ const fileStream = fs . createReadStream ( fsPath , { encoding : 'utf8' , highWaterMark : 1024 * 1024 } ) ; // 1MB chunks
279+ let buffer = '' ;
280+ for await ( const chunk of fileStream ) {
281+ buffer += chunk ;
282+ // Skip lines as per your requirement
283+ buffer = buffer . replace ( / ^ ( \ { 0 , 3 } \d + .* \n ) / gm, '\n' ) ;
284+ // Process buffer with regex here...
285+ }
286+ return Buffer . from ( buffer ) ;
287+ } catch ( error ) {
288+ console . error ( `Failed to read file: ${ error . message } ` ) ;
289+ throw new Error ( `Failed to read file: ${ error . message } ` ) ;
290+ }
291+ }
292+ watch ( uri , options ) {
293+ const watcher = fs . watch ( uri . fsPath , ( event , filename ) => {
294+ if ( event === 'change' ) {
295+ this . _emitter . fire ( [ { type : vscode . FileChangeType . Changed , uri } ] ) ;
296+ }
297+ } ) ;
298+
299+ return { dispose : ( ) => watcher . close ( ) } ;
300+ }
301+ stat ( uri ) {
302+ try {
303+ const stats = fs . statSync ( uri . fsPath ) ;
304+ const type = stats . isFile ( ) ? vscode . FileType . File : stats . isDirectory ( ) ? vscode . FileType . Directory : vscode . FileType . Unknown ;
305+ return { type, ctime : stats . ctimeMs , mtime : stats . mtimeMs , size : stats . size } ;
306+ } catch ( error ) {
307+ throw vscode . FileSystemError . FileNotFound ( uri ) ;
308+ }
309+ }
310+ readDirectory ( uri ) {
311+ try {
312+ const entries = fs . readdirSync ( uri . fsPath , { withFileTypes : true } ) ;
313+ return entries . map ( entry => {
314+ const type = entry . isFile ( ) ? vscode . FileType . File :
315+ entry . isDirectory ( ) ? vscode . FileType . Directory :
316+ vscode . FileType . Unknown ;
317+ return [ entry . name , type ] ;
318+ } ) ;
319+ } catch ( error ) {
320+ throw vscode . FileSystemError . FileNotFound ( uri ) ;
321+ }
322+ }
323+ createDirectory ( uri ) {
324+ throw vscode . FileSystemError . NoPermissions ( 'Creating directories is not allowed.' ) ;
325+ }
326+ writeFile ( uri , content , options ) {
327+ throw vscode . FileSystemError . NoPermissions ( 'Writing to files is not allowed.' ) ;
328+ }
329+ delete ( uri , options ) {
330+ throw vscode . FileSystemError . NoPermissions ( 'Deleting files is not allowed.' ) ;
331+ }
332+ rename ( oldUri , newUri , options ) {
333+ throw vscode . FileSystemError . NoPermissions ( 'Renaming files is not allowed.' ) ;
334+ }
335+ }
336+
337+
338+ async function showOrcaOutlineExternal ( context , uri ) {
339+
340+ // Prompt the user to select a .out file
341+ const uris = await vscode . window . showOpenDialog ( {
342+ canSelectFiles : true ,
343+ canSelectFolders : false ,
344+ canSelectMany : false ,
345+ filters : { 'ORCA Files' : [ 'out' ] } ,
346+ openLabel : 'Select ORCA file to open...'
347+ } ) ;
348+
349+ if ( uris && uris . length > 0 ) {
350+ // Change the scheme to 'orca' to trigger the custom file system provider
351+ const orcaUri = uris [ 0 ] . with ( { scheme : 'orca' } ) ;
352+
353+ // Attempt to open the document using the custom file system provider
354+ try {
355+ const doc = await vscode . workspace . openTextDocument ( orcaUri ) ;
356+ vscode . window . showTextDocument ( doc , { preview : false } ) ;
357+ } catch ( error ) {
358+ vscode . window . showErrorMessage ( `Failed to open ORCA file: ${ error . message } ` ) ;
359+ }
360+ }
361+
362+
363+ }
364+
365+
240366
241367module . exports = {
242368 activate,
0 commit comments