/// <summary> /// Provides very basic workbook parsing and shunting of code cells /// into the evaluation service. Does not display non-code-cell contents /// but does evaluate a workbook from top-to-bottom. Restores nuget /// packages from the workbook's manifest. /// </summary> static async Task <int> WorkbookPlayerMain(InteractiveSession session, ClientSessionUri sessionUri) { var path = new FilePath(sessionUri.WorkbookPath); if (!path.FileExists) { Error.WriteLine($"File does not exist: {path}"); return(1); } // load the workbook file var workbook = new WorkbookPackage(path); await workbook.Open( quarantineInfo => Task.FromResult(true), path); #pragma warning disable 0618 // TODO: WorkbookDocumentManifest needs to eliminate AgentType like we've done on web // to avoid having to use the the flavor mapping in AgentIdentity. var targetPlatformIdentifier = AgentIdentity.GetFlavorId(workbook.PlatformTargets [0]); #pragma warning restore 0618 // initialize the session based on manifest metadata from the workbook file language = workbook.GetLanguageDescriptions().First(); await session.InitializeAsync(new InteractiveSessionDescription ( language, targetPlatformIdentifier, new EvaluationEnvironment(Environment.CurrentDirectory))); // restore NuGet packages await session.PackageManagerService.RestoreAsync( workbook.Pages.SelectMany(page => page.Packages)); // insert and evaluate cells in the workbook foreach (var cell in workbook.IndexPage.Contents.OfType <CodeCell> ()) { var buffer = cell.CodeAnalysisBuffer.Value; lastCodeCellId = await session.EvaluationService.InsertCodeCellAsync( buffer, lastCodeCellId); ForegroundColor = ConsoleColor.DarkYellow; Write(GetPrompt()); ResetColor(); WriteLine(buffer); await session.EvaluationService.EvaluateAsync(lastCodeCellId); if (lastCellEvaluationStatus != CodeCellEvaluationStatus.Success) { break; } } return(0); }
/// <summary> /// Hosts an interactive REPL against a supported Workbooks target platform. /// This is analogous to 'csharp' or 'csi' or any other REPL on the planet. /// </summary> static async Task <int> ReplPlayerMain(InteractiveSession session) { // As an exercise to the reader, this puppy should take an optional // workbook flavor ID to know what platform you want to REPL and find // it in the list of installed and available ones... // For now we'll just pick the first available option 😺 var workbookTarget = WorkbookAppInstallation.All.FirstOrDefault(); if (workbookTarget == null) { RenderError("No workbook target platforms could be found."); return(1); } // We do not currently expose a list of available language descriptions // for the given build/installation, but if we did, this is when // you'd want to pick one. Just assume 'csharp' for now. Stay tuned. language = "csharp"; // A session description combines just enough info for the entire // EvaluationService to get itself in order to do your bidding. var sessionDescription = new InteractiveSessionDescription( language, workbookTarget.Id, new EvaluationEnvironment(Environment.CurrentDirectory)); // And initialize it with all of our prerequisites... // Status events raised within this method will be posted to the // observable above ("starting agent", "initializing workspace", etc). await session.InitializeAsync(sessionDescription); CodeCellId cellId = default; var editor = new LineEditor("xic"); editor.BeforeRenderPrompt = () => ForegroundColor = ConsoleColor.Yellow; editor.AfterRenderPrompt = () => ResetColor(); // At this point we have the following in order, ready to serve: // // 1. a connected agent ready to execute code // 2. a workspace that can perform compliation, intellisense, etc // 3. an evaluation service that is ready to deal with (1) and (2) // // It's at this point that a full UI would allow the user to actually // run code. This is the "User Experience main()"... // // This is the REPL you're looking for... while (true) { // append a new cell (no arguments here imply append) cellId = await session.EvaluationService.InsertCodeCellAsync(); for (int i = 0; true; i++) { var deltaBuffer = editor.Edit( GetPrompt(i > 0), null); var existingBuffer = await session.EvaluationService.GetCodeCellBufferAsync(cellId); await session.EvaluationService.UpdateCodeCellAsync( cellId, existingBuffer.Value + deltaBuffer); if (session.WorkspaceService.IsCellComplete(cellId)) { break; } } var finishedEvent = await session.EvaluationService.EvaluateAsync(cellId); // if the evaluation was not successful, remove the cell so it's not internally // re-evaluated (which would continue to yield the same failures) if (finishedEvent.Status != CodeCellEvaluationStatus.Success) { await session.EvaluationService.RemoveCodeCellAsync(finishedEvent.CodeCellId); } } }