Repository: spyder-ide/spyder

Issue:
Printing from the editor shows dark background or blank text
I've set the Editor syntax/color theme to Spyder/Dark which works fine.  The problem is that the dark background is now also being applied to the printed page (and print preview) which does not seem right and wastes ink.  I'm using Spyder 2.3.5.2 and do not recall having this problem before. Here is a screenshot of print-preview and that's how it came out on the printer.
![image](https://cloud.githubusercontent.com/assets/5048607/8526679/235c1a08-23d6-11e5-9c83-9a5191a3ce95.png)



Discussion:
Thanks for reporting. We barely use the print functionality so we weren't aware of this problem.

I'll try to fix it for our next version.

This problem persists in v3.1.3
Sure, that's why this bug is still open. We think it's of low importance because very few people has complained about it.
I see a different issue (on mac at least)

<img width="814" alt="Screen Shot 2019-11-27 at 21 03 09" src="https://user-images.githubusercontent.com/3627835/69771038-568c0580-1159-11ea-8a53-23eec6cc055e.png">

The text color is white so it is not visible.
Same results here on linux.

![image](https://user-images.githubusercontent.com/10513354/69833644-78859680-11f2-11ea-9024-a1e2b9d43a2b.png)

@bcolsen what do you think is a reasonable behavior here? 
## Option 1
I think that we either always default to spyder light syntax highlighting for printing 

## Option 2
We could make a separate print highlighter setting in preferences

## Option 3
If that's not easy to change highlighting for just printing then we could remove printing all together. I couldn't find a print option on vscode.



Thanks for the input, I will see what we can do
Well, printing is a very important function in data analysis, especially the print-to-pdf function. You write some code, run the code, get the output in terminal with beautiful code highlighting, then print-to-pdf and send to someone who does not not have python environment installed or who does not care about the the code itself but does care about the output.

I think one easy solution is to automatically switch to a light theme when printing, and then automatically switch back to the previous theme when printing is finished. Or, when printing, if the software detects that thare are chars in white color (or any color which is similar than white), then change it to another color for printing.
Agree with @suokunlong , I already miss printing in VS Code; for code that you didn't write is good to print it and write notes.
We'll try to solve this during the Scipy sprints this weekend.
The discussion on Issue  #12057, which was closed due to overlap with this one, mentioned the need to restart after changing the settings, and someone commented a restart wasn't necessary. While this seems to be true, a message box comes up when you change from the default Spyder Dark to Spyder in preferences in Spyder 4 that a reset IS necessary. If it isn't, this message box shouldn't pop up. 

Also, consider this a +1 for getting it fixed. I don't use printing a lot, but need it sometimes. My other workaround is to cut and paste into Notepad++ and print from there. That shouldn't be necessary. 

Ideal fix is to make printing preferences separate, but if that's a lot more work, then defaulting to the Spyder, rather than Spyder Dark settings would be fine. 
> If it isn't, this message box shouldn't pop up.

A restart is necessary.

> Also, consider this a +1 for getting it fixed. I don't use printing a lot, but need it sometimes. My other workaround is to cut and paste into Notepad++ and print from there. That shouldn't be necessary.

We really don't know why this happens. And since this is low priority, we decided to focus on more pressing things, sorry.
As somebody who consistently has to turn in code as part of homework, I would seriously appreciate proper printing from dark mode. As of now, I've been using "Print to PDF" from code copied to Notepad because it is such a pain to reset Spyder twice (once to print, and then again to switch back) just to add my program to a PDF document I need to submit.

Also, I just found that if you set a theme and hit "Apply", then cancel out, you change the theme without having to restart Spyder. I don't know if this is an intended occurrence. Nevertheless, I have yet to come across any problems with changing the theme this way. Perhaps it should be reevaluated as to whether the restart is actually necessary.
> As somebody who consistently has to turn in code as part of homework, I would seriously appreciate proper printing from dark mode.

@Aquilafer, ok, this is a good point. We'll try to fix this bug in our 5.3.3 version, to be released at the end of August (it's too late for 5.3.2 because it's going to be released this Friday).

> Also, I just found that if you set a theme and hit "Apply", then cancel out, you change the theme without having to restart Spyder. I don't know if this is an intended occurrence. Nevertheless, I have yet to come across any problems with changing the theme this way. Perhaps it should be reevaluated as to whether the restart is actually necessary.

A restart is necessary so that the interface matches your syntax highlighting theme. In other words, if you selected a light theme, then Spyder will switch automatically to light mode after the restart. However, I agree it's confusing that the new theme is applied before the restart. Could you open a new issue about that so we don't forget to address it in 5.3.3?

Also, if you want to avoid a restart you can change the `Interface theme` option from `Automatic` to `Dark`. That will keep the interface in Dark mode regardless of the syntax highlighting theme you're using.

![imagen](https://user-images.githubusercontent.com/365293/177196707-d4d0768a-2583-4db4-93e3-81d88e2362e5.png)


Resolving patch:
diff --git a/spyder/plugins/editor/plugin.py b/spyder/plugins/editor/plugin.py
--- a/spyder/plugins/editor/plugin.py
+++ b/spyder/plugins/editor/plugin.py
@@ -22,7 +22,9 @@
 # Third party imports
 from qtpy.compat import from_qvariant, getopenfilenames, to_qvariant
 from qtpy.QtCore import QByteArray, Qt, Signal, Slot, QDir
-from qtpy.QtPrintSupport import QAbstractPrintDialog, QPrintDialog, QPrinter
+from qtpy.QtGui import QTextCursor
+from qtpy.QtPrintSupport import (QAbstractPrintDialog, QPrintDialog, QPrinter,
+                                 QPrintPreviewDialog)
 from qtpy.QtWidgets import (QAction, QActionGroup, QApplication, QDialog,
                             QFileDialog, QInputDialog, QMenu, QSplitter,
                             QToolBar, QVBoxLayout, QWidget)
@@ -61,6 +63,7 @@
                                         get_run_configuration, RunConfigDialog,
                                         RunConfiguration, RunConfigOneDialog)
 from spyder.plugins.mainmenu.api import ApplicationMenus
+from spyder.widgets.simplecodeeditor import SimpleCodeEditor
 
 
 logger = logging.getLogger(__name__)
@@ -246,10 +249,15 @@ def __init__(self, parent, ignore_last_opened_files=False):
         # (needs to be done before EditorSplitter)
         self.autosave = AutosaveForPlugin(self)
         self.autosave.try_recover_from_autosave()
+
         # Multiply by 1000 to convert seconds to milliseconds
         self.autosave.interval = self.get_option('autosave_interval') * 1000
         self.autosave.enabled = self.get_option('autosave_enabled')
 
+        # SimpleCodeEditor instance used to print file contents
+        self._print_editor = self._create_print_editor()
+        self._print_editor.hide()
+
         # Tabbed editor widget + Find/Replace widget
         editor_widgets = QWidget(self)
         editor_layout = QVBoxLayout()
@@ -259,6 +267,7 @@ def __init__(self, parent, ignore_last_opened_files=False):
                                          self.stack_menu_actions, first=True)
         editor_layout.addWidget(self.editorsplitter)
         editor_layout.addWidget(self.find_widget)
+        editor_layout.addWidget(self._print_editor)
 
         # Splitter: editor widgets (see above) + outline explorer
         self.splitter = QSplitter(self)
@@ -2295,36 +2304,79 @@ def _convert(fname):
         self.__ignore_cursor_history = cursor_history_state
         self.add_cursor_to_history()
 
+    def _create_print_editor(self):
+        """Create a SimpleCodeEditor instance to print file contents."""
+        editor = SimpleCodeEditor(self)
+        editor.setup_editor(
+            color_scheme="scintilla", highlight_current_line=False
+        )
+        return editor
+
     @Slot()
     def print_file(self):
-        """Print current file"""
+        """Print current file."""
         editor = self.get_current_editor()
         filename = self.get_current_filename()
+
+        # Set print editor
+        self._print_editor.set_text(editor.toPlainText())
+        self._print_editor.set_language(editor.language)
+        self._print_editor.set_font(self.get_font())
+
+        # Create printer
         printer = Printer(mode=QPrinter.HighResolution,
                           header_font=self.get_font())
-        printDialog = QPrintDialog(printer, editor)
+        print_dialog = QPrintDialog(printer, self._print_editor)
+
+        # Adjust print options when user has selected text
         if editor.has_selected_text():
-            printDialog.setOption(QAbstractPrintDialog.PrintSelection, True)
+            print_dialog.setOption(QAbstractPrintDialog.PrintSelection, True)
+
+            # Copy selection from current editor to print editor
+            cursor_1 = editor.textCursor()
+            start, end = cursor_1.selectionStart(), cursor_1.selectionEnd()
+
+            cursor_2 = self._print_editor.textCursor()
+            cursor_2.setPosition(start)
+            cursor_2.setPosition(end, QTextCursor.KeepAnchor)
+            self._print_editor.setTextCursor(cursor_2)
+
+        # Print
         self.redirect_stdio.emit(False)
-        answer = printDialog.exec_()
+        answer = print_dialog.exec_()
         self.redirect_stdio.emit(True)
+
         if answer == QDialog.Accepted:
             self.starting_long_process(_("Printing..."))
             printer.setDocName(filename)
-            editor.print_(printer)
+            self._print_editor.print_(printer)
             self.ending_long_process()
 
+        # Clear selection
+        self._print_editor.textCursor().removeSelectedText()
+
     @Slot()
     def print_preview(self):
-        """Print preview for current file"""
-        from qtpy.QtPrintSupport import QPrintPreviewDialog
-
+        """Print preview for current file."""
         editor = self.get_current_editor()
+
+        # Set print editor
+        self._print_editor.set_text(editor.toPlainText())
+        self._print_editor.set_language(editor.language)
+        self._print_editor.set_font(self.get_font())
+
+        # Create printer
         printer = Printer(mode=QPrinter.HighResolution,
                           header_font=self.get_font())
+
+        # Create preview
         preview = QPrintPreviewDialog(printer, self)
         preview.setWindowFlags(Qt.Window)
-        preview.paintRequested.connect(lambda printer: editor.print_(printer))
+        preview.paintRequested.connect(
+            lambda printer: self._print_editor.print_(printer)
+        )
+
+        # Show preview
         self.redirect_stdio.emit(False)
         preview.exec_()
         self.redirect_stdio.emit(True)


Test patch: