Repository: microsoft/ptvsd

Issue:
Debug console is now outputting tabs as spaces
## Environment data

- PTVSD version: Latest
- OS and version: Mac & Windows
- Python version (& distribution if applicable, e.g. Anaconda): N/A
- Using VS Code or Visual Studio:VSC

## Actual behavior

Tabs are converted into spaces when output is displayed in VS Code debugger output window.

## Expected  behavior

Tabs should not be replaced with spaces

## Steps to reproduce:
1. Debug the following code:
* `print("Hello\tWorld")`
2. The output in the terminal is correct.
3. The output in the debug console window is incorrect it is `Hello<single space>World`




Discussion:
@karthiknadig 	@int19h 
Going forward I won't be labelling the issues I create, this way its easier for your team to find issues that you haven't triaged and added appropriate labels.
@int19h Looks like the XML parser in `wrapper.py` is replacing the `\t` with ` `. I am not able to find any setting for that.

Resolving patch:
diff --git a/ptvsd/_vendored/pydevd/_pydevd_bundle/pydevd_comm.py b/ptvsd/_vendored/pydevd/_pydevd_bundle/pydevd_comm.py
--- a/ptvsd/_vendored/pydevd/_pydevd_bundle/pydevd_comm.py
+++ b/ptvsd/_vendored/pydevd/_pydevd_bundle/pydevd_comm.py
@@ -751,7 +751,7 @@ def make_io_message(self, v, ctx):
                 v = v[0:MAX_IO_MSG_SIZE]
                 v += '...'
 
-            v = pydevd_xml.make_valid_xml_value(quote(v, '/>_= \t'))
+            v = pydevd_xml.make_valid_xml_value(quote(v, '/>_= '))
             return NetCommand(str(CMD_WRITE_TO_CONSOLE), 0, '<xml><io s="%s" ctx="%s"/></xml>' % (v, ctx))
         except:
             return self.make_error_message(0, get_exception_traceback_str())


Test patch:
diff --git a/tests/resources/system_tests/test_misc/output_test.py b/tests/resources/system_tests/test_misc/output_test.py
new file mode 100644
--- /dev/null
+++ b/tests/resources/system_tests/test_misc/output_test.py
@@ -0,0 +1 @@
+print('Hello\tworld')
diff --git a/tests/system_tests/test_misc.py b/tests/system_tests/test_misc.py
--- a/tests/system_tests/test_misc.py
+++ b/tests/system_tests/test_misc.py
@@ -27,6 +27,28 @@ def test_with_no_output(self):
             DebugInfo(filename=filename, cwd=cwd))
 
 
+class OutputTests(LifecycleTestsBase):
+    def run_test_output(self, debug_info, expected_output):
+        options = {'debugOptions': ['RedirectOutput']}
+        with self.start_debugging(debug_info) as dbg:
+            session = dbg.session
+            lifecycle_handshake(session, debug_info.starttype,
+                                options=options)
+        out = dbg.adapter._proc.output.decode('utf-8')
+        self.assertTrue(out.startswith(expected_output))
+        received = list(_strip_newline_output_events(session.received))
+        self.assert_contains(received, [
+            self.new_event('output', category='stdout', output=expected_output)
+        ])
+
+    def test_tab_output(self):
+        filename = TEST_FILES.resolve('output_test.py')
+        cwd = os.path.dirname(filename)
+        self.run_test_output(
+            DebugInfo(filename=filename, cwd=cwd),
+            'Hello\tworld')
+
+
 class ThreadCountTests(LifecycleTestsBase):
     def run_test_threads(self, debug_info, bp_filename, bp_line, count):
         breakpoints = [{