public async Task New_directives_can_be_added_after_older_ones_have_been_evaluated()
        {
            using var kernel = new CompositeKernel { new CSharpKernel() };

            using var events = kernel.KernelEvents.ToSubscribedList();

            var oneWasCalled = false;
            var twoWasCalled = false;

            kernel.AddDirective(new Command("#!one")
            {
                Handler = CommandHandler.Create(() => oneWasCalled = true)
            });

            await kernel.SubmitCodeAsync("#!one\n123");

            events.Should().NotContainErrors();

            kernel.AddDirective(new Command("#!two")
            {
                Handler = CommandHandler.Create(() => twoWasCalled = true)
            });

            await kernel.SubmitCodeAsync("#!two\n123");

            events.Should().NotContainErrors();
            oneWasCalled.Should().BeTrue();
            twoWasCalled.Should().BeTrue();
        }
            public async Task Completions_do_not_include_duplicates()
            {
                var cSharpKernel = new CSharpKernel();

                using var compositeKernel = new CompositeKernel
                      {
                          cSharpKernel
                      };

                compositeKernel.DefaultKernelName = cSharpKernel.Name;

                var commandName = "#!hello";

                compositeKernel.AddDirective(new Command(commandName)
                {
                    Handler = CommandHandler.Create(() => { })
                });
                cSharpKernel.AddDirective(new Command(commandName)
                {
                    Handler = CommandHandler.Create(() => { })
                });

                var result = await compositeKernel.SendAsync(new RequestCompletions("#!", new LinePosition(0, 2)));

                var events = result.KernelEvents.ToSubscribedList();

                events
                .Should()
                .ContainSingle <CompletionsProduced>()
                .Which
                .Completions
                .Should()
                .ContainSingle(e => e.DisplayText == commandName);
            }
        public async Task Directives_can_display_help()
        {
            using var kernel = new CompositeKernel();
            using var events = kernel.KernelEvents.ToSubscribedList();

            var command = new Command("#!hello")
            {
                new Option <bool>("--loudness")
            };

            kernel.AddDirective(command);

            await kernel.SubmitCodeAsync("#!hello -h");

            var stdOut = string.Join(
                "",
                events
                .OfType <StandardOutputValueProduced>()
                .Select(e => e.Value.As <string>()));

            stdOut
            .Should()
            .ContainAll("Usage", "#!hello", "[options]", "--loudness");

            stdOut
            .Should()
            .NotContain(new RootCommand().Name, "RootCommand.Name is generally intended to reflect the command line tool's name but in this case it's just an implementation detail and it looks weird in the output.");
        }
Example #4
0
        public static CompositeKernel UseModelAnswerValidation(this CompositeKernel kernel)
        {
            var modelAnswerCommand = new Command(_modelAnswerCommandName);

            kernel.AddDirective(modelAnswerCommand);
            return(kernel);
        }
Example #5
0
        public async Task Directives_can_display_help()
        {
            // using var consoleOut = await ConsoleOutput.Capture();

            using var kernel = new CompositeKernel();
            using var events = kernel.KernelEvents.ToSubscribedList();

            var command = new Command("#!hello")
            {
                new Option <bool>("--loudness")
            };

            command.Handler = CommandHandler.Create((IConsole console) =>
            {
            });

            kernel.AddDirective(command);

            await kernel.SubmitCodeAsync("#!hello -h");

            events.Should()
            .ContainSingle <DisplayedValueProduced>()
            .Which
            .FormattedValues
            .Should()
            .ContainSingle(e => e.MimeType == "text/html")
            .Which
            .Value
            .As <string>()
            .Should()
            .ContainAll("Usage", "#!hello [options]", "--loudness");
        }
Example #6
0
            public async Task lsmagic_lists_registered_magic_commands()
            {
                using var kernel = new CompositeKernel()
                                   .UseDefaultMagicCommands()
                                   .LogEventsToPocketLogger();

                kernel.AddDirective(new Command("#!one"));
                kernel.AddDirective(new Command("#!two"));
                kernel.AddDirective(new Command("#!three"));

                using var events = kernel.KernelEvents.ToSubscribedList();

                await kernel.SendAsync(new SubmitCode("#!lsmagic"));

                events.Should()
                .ContainSingle(e => e is DisplayedValueProduced)
                .Which
                .As <DisplayedValueProduced>()
                .Value
                .ToDisplayString("text/html")
                .Should()
                .ContainAll("#!lsmagic", "#!one", "#!three", "#!two");
            }
Example #7
0
        public async Task lsmagic_lists_registered_magic_commands()
        {
            var kernel = new CompositeKernel()
                         .UseDefaultMagicCommands()
                         .LogEventsToPocketLogger();

            kernel.AddDirective(new Command("%%one"));
            kernel.AddDirective(new Command("%%two"));
            kernel.AddDirective(new Command("%%three"));

            using var events = kernel.KernelEvents.ToSubscribedList();

            await kernel.SendAsync(new SubmitCode("%lsmagic"));

            events.Should()
            .ContainSingle(e => e is ValueProduced)
            .Which
            .As <ValueProduced>()
            .Value
            .As <string>()
            .Should()
            .ContainAll("%lsmagic", "%%one %%three %%two");
        }
        public void Directives_with_duplicate_aliases_are_not_allowed()
        {
            using var kernel = new CompositeKernel();

            kernel.AddDirective(new Command("#dupe"));

            kernel.Invoking(k =>
                            k.AddDirective(new Command("#dupe")))
            .Should()
            .Throw <ArgumentException>()
            .Which
            .Message
            .Should()
            .Be("Alias \'#dupe\' is already in use.");
        }
Example #9
0
            public async Task lsmagic_lists_registered_magic_commands_in_subkernels()
            {
                var subkernel1 = new CSharpKernel();

                subkernel1.AddDirective(new Command("#!from-subkernel-1"));
                var subkernel2 = new FSharpKernel();

                subkernel2.AddDirective(new Command("#!from-subkernel-2"));

                using var compositeKernel = new CompositeKernel
                      {
                          subkernel1,
                          subkernel2
                      }
                      .UseDefaultMagicCommands()
                      .LogEventsToPocketLogger();
                compositeKernel.DefaultKernelName = "csharp";

                compositeKernel.AddDirective(new Command("#!from-compositekernel"));

                using var events = compositeKernel.KernelEvents.ToSubscribedList();

                await compositeKernel.SendAsync(new SubmitCode("#!lsmagic"));

                var valueProduceds = events.OfType <DisplayedValueProduced>().ToArray();

                valueProduceds[0].Value
                .ToDisplayString("text/html")
                .Should()
                .ContainAll("#!lsmagic",
                            "#!csharp",
                            "#!fsharp",
                            "#!from-compositekernel");

                valueProduceds[1].Value
                .ToDisplayString("text/html")
                .Should()
                .ContainAll("#!lsmagic",
                            "#!from-subkernel-1");
                valueProduceds[2].Value
                .ToDisplayString("text/html")
                .Should()
                .ContainAll("#!lsmagic",
                            "#!from-subkernel-2");
            }
Example #10
0
        private static SubmissionParser CreateSubmissionParser(
            string defaultLanguage = "csharp",
            params Command[] directives)
        {
            using var kernel         = new CompositeKernel();
            kernel.DefaultKernelName = defaultLanguage;
            kernel.Add(new FakeKernel("csharp"));
            kernel.Add(new FakeKernel("fsharp"));
            kernel.Add(new FakeKernel("powershell"), new[] { "pwsh" });
            kernel.UseDefaultMagicCommands();

            foreach (var directive in directives)
            {
                kernel.AddDirective(directive);
            }

            return(kernel.SubmissionParser);
        }
        public void Directives_may_not_have_aliases_that_begin_with_(string value)
        {
            using var kernel = new CompositeKernel();

            var command = new Command("#!this-is-fine");

            command.AddAlias($"{value}hello");

            kernel
            .Invoking(k =>
            {
                kernel.AddDirective(command);
            })
            .Should()
            .Throw <ArgumentException>()
            .Which
            .Message
            .Should()
            .Be($"Invalid directive name \"{value}hello\". Directives must begin with \"#\".");
        }
Example #12
0
        public async Task lsmagic_does_not_list_hidden_commands()
        {
            using var kernel = new CompositeKernel()
                               .UseDefaultMagicCommands()
                               .LogEventsToPocketLogger();

            kernel.AddDirective(new Command("#!hidden")
            {
                IsHidden = true
            });

            using var events = kernel.KernelEvents.ToSubscribedList();

            await kernel.SendAsync(new SubmitCode("#!lsmagic"));

            events.Should()
            .ContainSingle(e => e is DisplayedValueProduced)
            .Which
            .As <DisplayedValueProduced>()
            .Value
            .ToDisplayString("text/html")
            .Should()
            .NotContain("#!hidden");
        }
        public async Task Deferred_commands_on_composite_kernel_can_use_directives()
        {
            var deferredCommandExecuted = false;
            var subKernel = new CSharpKernel();

            using var compositeKernel = new CompositeKernel
                  {
                      subKernel
                  };
            var customDirective = new Command("#!customDirective")
            {
                Handler = CommandHandler.Create(() => { deferredCommandExecuted = true; })
            };

            compositeKernel.AddDirective(customDirective);

            compositeKernel.DefaultKernelName = subKernel.Name;

            var deferred = new SubmitCode("#!customDirective");

            compositeKernel.DeferCommand(deferred);

            var events = compositeKernel.KernelEvents.ToSubscribedList();

            await compositeKernel.SendAsync(new SubmitCode("var x = 1;", targetKernelName : subKernel.Name));

            deferredCommandExecuted.Should().Be(true);

            events
            .Select(e => e.GetType())
            .Should()
            .ContainInOrder(
                typeof(CodeSubmissionReceived),
                typeof(CompleteCodeSubmissionReceived),
                typeof(CommandSucceeded));
        }
Example #14
0
        public static CompositeKernel UseProgressiveLearning(
            this CompositeKernel kernel,
            HttpClient httpClient = null)
        {
            kernel.Bootstrapping();

            var fromUrlOption = new Option <Uri>(
                "--from-url",
                "Specify lesson source URL");

            var fromFileOption = new Option <FileInfo>(
                "--from-file",
                description: "Specify lesson source file",
                parseArgument: result =>
            {
                var filePath      = result.Tokens.Single().Value;
                var fromUrlResult = result.FindResultFor(fromUrlOption);
                if (fromUrlResult is not null)
                {
                    result.ErrorMessage = $"The {fromUrlResult.Token.Value} and {(result.Parent as OptionResult).Token.Value} options cannot be used together";
                    return(null);
                }

                if (!File.Exists(filePath))
                {
                    result.ErrorMessage = Resources.Instance.FileDoesNotExist(filePath);
                    return(null);
                }

                return(new FileInfo(filePath));
            });

            var startCommand = new Command("#!start-lesson")
            {
                fromFileOption,
                fromUrlOption
            };

            startCommand.Handler = CommandHandler.Create <Uri, FileInfo, KernelInvocationContext>(StartCommandHandler);

            kernel.AddDirective(startCommand);

            return(kernel);

            async Task StartCommandHandler(Uri fromUrl, FileInfo fromFile, KernelInvocationContext context)
            {
                InteractiveDocument document = fromFile switch
                {
                    { } => await NotebookLessonParser.ReadFileAsInteractiveDocument(fromFile, kernel),
                    _ => await NotebookLessonParser.LoadNotebookFromUrl(fromUrl, httpClient)
                };

                NotebookLessonParser.Parse(document, out var lessonDefinition, out var challengeDefinitions);

                var challenges = challengeDefinitions.Select(b => b.ToChallenge()).ToList();

                challenges.SetDefaultProgressionHandlers();
                Lesson.From(lessonDefinition);
                Lesson.SetChallengeLookup(queryName => { return(challenges.FirstOrDefault(c => c.Name == queryName)); });

                await kernel.StartLesson();

                await Lesson.StartChallengeAsync(challenges.First());

                await kernel.InitializeChallenge(Lesson.CurrentChallenge);
            }