diff --git a/st3/sublime_lib/view_stream.py b/st3/sublime_lib/view_stream.py index cc50072..1ae8de5 100644 --- a/st3/sublime_lib/view_stream.py +++ b/st3/sublime_lib/view_stream.py @@ -45,6 +45,17 @@ def guard_read_only(self): else: yield + @define_guard + @contextmanager + def guard_auto_indent(self): + settings = self.view.settings() + if settings.get('auto_indent'): + settings.set('auto_indent', False) + yield + settings.set('auto_indent', True) + else: + yield + @define_guard def guard_validity(self): if not self.view.is_valid(): @@ -95,25 +106,23 @@ def _read(self, begin, end, size): @guard_validity @guard_selection @guard_read_only + @guard_auto_indent def write(self, s): """Insert the string `s` into the view and return the number of characters inserted. The string will be inserted immediately before the - cursor. + cursor. It will not be auto-indented. Note: Because Sublime may convert tabs to spaces, the number of characters inserted may not match the length of the argument. """ - # This is a hack to get around auto-indentation. old_size = self.view.size() - self.view.run_command('insert_snippet', { - 'contents': '$sublime_lib__insert_text', - 'sublime_lib__insert_text': s, - }) + self.view.run_command('insert', {'characters': s}) return self.view.size() - old_size - def print(self, *objects, **kwargs): - """Shorthand for ``print(*objects, file=self, **kwargs)``.""" - print(*objects, file=self, **kwargs) + def print(self, *objects, sep=' ', end='\n'): + """Shorthand for :func:`print()` passing this ViewStream as the `file` + argument.""" + print(*objects, file=self, sep=sep, end=end) def flush(self): """Do nothing. (The stream is not buffered.)""" diff --git a/tests/test_view_stream.py b/tests/test_view_stream.py index 7460a92..54b59be 100644 --- a/tests/test_view_stream.py +++ b/tests/test_view_stream.py @@ -2,7 +2,7 @@ from sublime_lib import ViewStream from unittest import TestCase -from io import UnsupportedOperation +from io import UnsupportedOperation, StringIO class TestViewStream(TestCase): @@ -48,11 +48,12 @@ def test_write_size(self): self.assertEqual(size, self.stream.view.size()) def test_no_indent(self): - text = "Hello\n World\n!" + text = " " self.stream.view.settings().set('auto_indent', True) self.stream.write(text) - self.assertContents(text) + self.stream.write("\n") + self.assertContents(text + "\n") def test_clear(self): self.stream.write("Some text") @@ -109,17 +110,66 @@ def test_readline(self): self.assertEqual(text, "World") self.assertEqual(self.stream.tell(), 12) - def test_write_only(self): + def test_write_read_only_failure(self): self.stream.view.set_read_only(True) self.assertRaises(ValueError, self.stream.write, 'foo') self.assertRaises(ValueError, self.stream.clear) + def test_write_read_only_success(self): + self.stream.view.set_read_only(True) self.stream.force_writes = True - self.assertEqual(self.stream.write('foo'), 3) + + self.stream.write('foo') + self.assertContents('foo') + + self.stream.clear() + self.assertContents('') + + def _compare_print(self, *args, **kwargs): + s = StringIO() + print(*args, file=s, **kwargs) + + self.stream.clear() + self.stream.print(*args, **kwargs) + + self.assertContents(s.getvalue()) + + self.stream.clear() + print(*args, file=self.stream, **kwargs) + + self.assertContents(s.getvalue()) + + def test_print(self): + text = "Hello, World!" + number = 42 + + self._compare_print(text, number) + self._compare_print(text, number, sep=',', end=';') + self._compare_print(text, number, sep='', end='') + + def test_print_no_indent(self): + text = " " + + self.stream.view.settings().set('auto_indent', True) + self.stream.print(text) + self.assertContents(text + "\n") + + def test_print_read_only_failure(self): + self.stream.view.set_read_only(True) + + self.assertRaises(ValueError, self.stream.print, 'foo') + self.assertRaises(ValueError, self.stream.clear) + + def test_print_read_only_success(self): + self.stream.view.set_read_only(True) + self.stream.force_writes = True + + self.stream.print('foo') + self.assertContents("foo\n") self.stream.clear() - self.assertEqual(self.stream.view.size(), 0) + self.assertContents('') def test_unsupported(self): self.assertRaises(UnsupportedOperation, self.stream.detach)