/// <summary> /// Takes the new input and appends it to any existing input that's been entered so far. The combined /// input is then split into multiple top-level statements that will be executed one-by-one. /// /// Also handles any dedents necessary to make the input a valid input, which usually would only /// apply if we have no input so far. /// </summary> private static List <string> RecombineInput( string input, string pendingInput, bool supportsMultipleStatements, PythonLanguageVersion version, string newLineCharacter ) { // Combine the current input text with the newly submitted text. This will prevent us // from dedenting code when doing line-by-line submissions of things like: // if True: // x = 1 // // So that we don't dedent "x = 1" when we submit it by its self. var combinedText = (pendingInput ?? string.Empty) + input; var oldLineCount = string.IsNullOrEmpty(pendingInput) ? 0 : pendingInput.Split(_newLineChars, StringSplitOptions.None).Length - 1; // The split and join will not alter the number of lines that are fed in and returned but // may change the text by dedenting it if we hadn't submitted the "if True:" in the // code above. var split = ReplEditFilter.SplitAndDedent(combinedText); IEnumerable <string> joinedLines; if (!supportsMultipleStatements) { joinedLines = ReplEditFilter.JoinToCompleteStatements(split, version, false); } else { joinedLines = new[] { string.Join(newLineCharacter, split) }; } // Remove any of the lines that were previously inputted into the buffer and also // remove any extra newlines in the submission. List <string> res = new List <string>(); foreach (var inputLine in joinedLines) { var actualLines = inputLine.Split(_newLineChars, StringSplitOptions.None); var newLine = ReplEditFilter.FixEndingNewLine( string.Join(newLineCharacter, actualLines.Skip(oldLineCount)) ); res.Add(newLine); oldLineCount -= actualLines.Count(); if (oldLineCount < 0) { oldLineCount = 0; } } return(res); }
/// <summary> /// Takes the new input and appends it to any existing input that's been entered so far. The combined /// input is then split into multiple top-level statements that will be executed one-by-one. /// /// Also handles any dedents necessary to make the input a valid input, which usually would only /// apply if we have no input so far. /// </summary> private List <string> RecombineInput(string input) { var textView = _window.TextView; var curLangBuffer = _window.CurrentLanguageBuffer; var analyzer = textView.GetAnalyzerAtCaret(_serviceProvider); if (analyzer == null) { return(new List <string>()); } var version = analyzer.InterpreterFactory.Configuration.Version.ToLanguageVersion(); // Combine the current input text with the newly submitted text. This will prevent us // from dedenting code when doing line-by-line submissions of things like: // if True: // x = 1 // // So that we don't dedent "x = 1" when we submit it by its self. string newText = input; var curText = curLangBuffer.CurrentSnapshot.GetText(); var combinedText = curText + newText; var oldLineCount = curText.Split(_newLineChars, StringSplitOptions.None).Length - 1; // The split and join will not alter the number of lines that are fed in and returned but // may change the text by dedenting it if we hadn't submitted the "if True:" in the // code above. var split = ReplEditFilter.SplitAndDedent(combinedText); var joinedLines = ReplEditFilter.JoinToCompleteStatements(split, version, false); // Remove any of the lines that were previously inputted into the buffer and also // remove any extra newlines in the submission. List <string> res = new List <string>(); foreach (var inputLine in joinedLines) { var actualLines = inputLine.Split(_newLineChars, StringSplitOptions.None); var newLine = ReplEditFilter.FixEndingNewLine( string.Join( textView.Options.GetNewLineCharacter(), actualLines.Skip(oldLineCount) ) ); res.Add(newLine); oldLineCount -= actualLines.Count(); if (oldLineCount < 0) { oldLineCount = 0; } } return(res); }
public void ReplSplitCodeTest() { // http://pytools.codeplex.com/workitem/606 var testCases = new[] { new { Code = @"def f(): pass def g(): pass f() g()", Expected = new[] { "def f():\r\n pass\r\n", "def g():\r\n pass\r\n", "f()", "g()" } }, new { Code = @"def f(): pass f() def g(): pass f() g()", Expected = new[] { "def f():\r\n pass\r\n", "f()", "def g():\r\n pass\r\n", "f()", "g()" } }, new { Code = @"def f(): pass f() f() def g(): pass f() g()", Expected = new[] { "def f():\r\n pass\r\n", "f()", "f()", "def g():\r\n pass\r\n", "f()", "g()" } }, new { Code = @" def f(): pass f() f() def g(): pass f() g()", Expected = new[] { "def f():\r\n pass\r\n", "f()", "f()", "def g():\r\n pass\r\n", "f()", "g()" } }, new { Code = @"# Comment f() f()", Expected = new[] { "# Comment\r\n\r\nf()\r\n", "f()" } } }; using (var evaluator = MakeEvaluator()) { int counter = 0; foreach (var testCase in testCases) { Console.WriteLine("Test case {0}", ++counter); AssertUtil.AreEqual(ReplEditFilter.JoinToCompleteStatements(ReplEditFilter.SplitAndDedent(testCase.Code), Microsoft.PythonTools.Parsing.PythonLanguageVersion.V35), testCase.Expected); } } }